mirror of
https://port.numenaute.org/aleajactaest/khanat-opennel-code.git
synced 2024-12-03 17:14:46 +00:00
755 lines
28 KiB
C++
755 lines
28 KiB
C++
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
|
|
// Copyright (C) 2010 Winch Gate Property Limited
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Affero General Public License as
|
|
// published by the Free Software Foundation, either version 3 of the
|
|
// License, or (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU Affero General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
#ifndef NL_UNIFIED_NETWORD_H
|
|
#define NL_UNIFIED_NETWORD_H
|
|
|
|
#include "nel/misc/types_nl.h"
|
|
|
|
#include <vector>
|
|
#include <string>
|
|
|
|
#include "nel/misc/command.h"
|
|
#include "nel/misc/time_nl.h"
|
|
|
|
#include "callback_client.h"
|
|
#include "callback_server.h"
|
|
|
|
namespace NLNET {
|
|
|
|
/** This class encapsulate the serviceId format. */
|
|
class TServiceId
|
|
{
|
|
/// Service are identified by a 16 bits integer
|
|
uint16 _ServiceId;
|
|
|
|
public:
|
|
|
|
typedef uint16 size_type;
|
|
|
|
/// A constant for the invalid service id
|
|
static const TServiceId InvalidId;
|
|
|
|
/// Default constructor, set the id to 0 (no service should have 0)
|
|
TServiceId() : _ServiceId(0) { }
|
|
|
|
/// Copy constructor
|
|
TServiceId(const TServiceId &other) : _ServiceId(other._ServiceId) { }
|
|
|
|
/// Only explicit construction from an integer are allowed
|
|
explicit TServiceId(uint16 sid) : _ServiceId(sid) { }
|
|
|
|
bool operator == (const TServiceId &other) const
|
|
{
|
|
return _ServiceId == other._ServiceId;
|
|
}
|
|
|
|
bool operator != (const TServiceId &other) const
|
|
{
|
|
return !(*this == other);
|
|
}
|
|
|
|
bool operator < (const TServiceId &other) const
|
|
{
|
|
return _ServiceId < other._ServiceId;
|
|
}
|
|
|
|
/// Getter, return the integer value of the service id
|
|
uint16 get() const { return _ServiceId; }
|
|
|
|
/// Setter, set the value of the service id
|
|
void set(uint16 sid) { _ServiceId = sid; }
|
|
|
|
void serial(NLMISC::IStream &s)
|
|
{
|
|
s.serial(_ServiceId);
|
|
}
|
|
|
|
std::string toString() const
|
|
{
|
|
return NLMISC::toString(_ServiceId);
|
|
}
|
|
|
|
bool fromString(const std::string &str)
|
|
{
|
|
return NLMISC::fromString(str, _ServiceId);
|
|
}
|
|
};
|
|
|
|
/** This class encapsulate the 8 bits service id.
|
|
* 8 bits service id are used by service register on the naming service.
|
|
* This service can be used in a NLMISC::CEntityId.
|
|
* Implicit constructor and conversion are provided with the 16 bits
|
|
* version above, but the constructor will assert if the 8 bits range is
|
|
* overflowed.
|
|
*/
|
|
class TServiceId8
|
|
{
|
|
/// The 8bits service id
|
|
uint8 _ServiceId;
|
|
|
|
public:
|
|
|
|
typedef uint8 size_type;
|
|
|
|
/// Default constructor, set the id to 0 (no service should have 0)
|
|
TServiceId8()
|
|
: _ServiceId(0)
|
|
{}
|
|
|
|
/// Copy constructor
|
|
TServiceId8(const TServiceId8 &other)
|
|
: _ServiceId(other._ServiceId)
|
|
{}
|
|
|
|
/// Only explicit construction from an integer are allowed
|
|
TServiceId8(const TServiceId &other)
|
|
{
|
|
nlassert(other.get() < 256);
|
|
_ServiceId = uint8(other.get());
|
|
}
|
|
explicit TServiceId8(uint8 sid)
|
|
: _ServiceId(sid)
|
|
{}
|
|
|
|
/// implicit up cast to TServiceId (16bits)
|
|
operator TServiceId () const
|
|
{
|
|
return TServiceId(_ServiceId);
|
|
}
|
|
|
|
bool operator == (const TServiceId8 &other) const
|
|
{
|
|
return _ServiceId == other._ServiceId;
|
|
}
|
|
bool operator != (const TServiceId8 &other) const
|
|
{
|
|
return !(*this == other);
|
|
}
|
|
bool operator == (const TServiceId &other) const
|
|
{
|
|
return _ServiceId == other.get();
|
|
}
|
|
bool operator != (const TServiceId &other) const
|
|
{
|
|
return !(*this == other);
|
|
}
|
|
bool operator < (const TServiceId8 &other) const
|
|
{
|
|
return _ServiceId < other._ServiceId;
|
|
}
|
|
|
|
/// Getter, return the integer value of the service id
|
|
uint8 get() const { return _ServiceId;}
|
|
/// Setter, set the value of the service id
|
|
void set(uint8 sid) { _ServiceId = sid;}
|
|
|
|
void serial(NLMISC::IStream &s)
|
|
{
|
|
s.serial(_ServiceId);
|
|
}
|
|
|
|
std::string toString() const
|
|
{
|
|
return NLMISC::toString(_ServiceId);
|
|
}
|
|
|
|
bool fromString(const std::string &str)
|
|
{
|
|
return NLMISC::fromString(str, _ServiceId);
|
|
}
|
|
};
|
|
|
|
|
|
|
|
/** Callback function type for service up/down processing
|
|
* \param serviceName name of the service that is un/registered to the naming service
|
|
* \param arg a pointer initialized by the user
|
|
*/
|
|
typedef void (*TUnifiedNetCallback) (const std::string &serviceName, TServiceId sid, void *arg);
|
|
|
|
/** Callback function type for message processing
|
|
* \param msgin message received
|
|
* \param serviceName name of the service that sent the message
|
|
* \param sid id of the service that sent the message
|
|
*/
|
|
typedef void (*TUnifiedMsgCallback) (CMessage &msgin, const std::string &serviceName, TServiceId sid);
|
|
|
|
/// Callback items. See CMsgSocket::update() for an explanation on how the callbacks are called.
|
|
struct TUnifiedCallbackItem
|
|
{
|
|
/// Key C string. It is a message type name, or "C" for connection or "D" for disconnection
|
|
const char *Key;
|
|
/// The callback function
|
|
TUnifiedMsgCallback Callback;
|
|
|
|
};
|
|
|
|
/**
|
|
* Layer 5
|
|
*
|
|
* When calling send(), a message is stored in a queue. It will be effectively sent
|
|
* when a flush is done. By default, the variable FlushSendsBeforeSleep is on so that
|
|
* the message is sent in the same update cycle as the send() call. If FlushSendsBeforeSleep
|
|
* is set to off, more messages will be sent together, but with a greater delay.
|
|
*
|
|
* Handling network congestion:
|
|
* When a destination service is not fast enough to process the incoming messages,
|
|
* the uploading stream can get saturated. As a result, a single flush will not manage to send the
|
|
* entire data at a time. The NeL Network Layer 5 will silently continue streaming up the remaining
|
|
* parts of the unsent data, as long as update() is called evenly.
|
|
* More in depth:
|
|
* - Either let the layer 5 handle network congestions. If the destination service is slow or
|
|
* stuck and the source service still has data to send, the delivery may be delayed for a long
|
|
* time. If your source service is shut down (calling release()) while some data is still pending,
|
|
* a call to release(true) may take a while or even not exit while the destination service is stuck.
|
|
* - Or handle yourself network congestions by calling tryFlushAllQueues() multiple times. Then you can display
|
|
* the progression of sending, abort it if too long, etc.
|
|
*
|
|
* \author Vianney Lecroart, Benjamin Legros, Olivier Cado
|
|
* \author Nevrax France
|
|
* \date 2002-2004
|
|
*/
|
|
class CUnifiedNetwork : public NLMISC::ICommandsHandler
|
|
{
|
|
NLMISC_SAFE_SINGLETON_DECL_PTR(CUnifiedNetwork);
|
|
|
|
public:
|
|
|
|
virtual const std::string &getCommandHandlerName() const
|
|
{
|
|
static const std::string name("unifiedNetwork");
|
|
|
|
return name;
|
|
}
|
|
|
|
|
|
/** Returns the singleton instance of the CUnifiedNetwork class.
|
|
*/
|
|
// static CUnifiedNetwork *getInstance ();
|
|
|
|
/** Returns true if the application called getInstance(). This function is used to know if the user is using layer 4 or layer 5
|
|
*/
|
|
static bool isUsed ();
|
|
|
|
/** Creates the connection to the Naming Service.
|
|
* If the connection failed, ESocketConnectionFailed exception is generated.
|
|
* This function is called automatically called by the service class at the beginning.
|
|
*
|
|
* \param addr address of the naming service (0 is you don't want to use the naming service)
|
|
* \param rec recording state to know if we have to record or replay messages
|
|
* \return false if the instance startup was denied by the naming service
|
|
*/
|
|
bool init (const CInetAddress *addr, CCallbackNetBase::TRecordingState rec, const std::string &shortName, uint16 port, TServiceId &sid );
|
|
|
|
/** Registers to the Naming Service, and connects to the present services
|
|
*/
|
|
void connect();
|
|
|
|
/** Closes the connection to the naming service, every other connection and free.
|
|
* \param mustFlushSendQueues If true, all send queues or only queues in namesOfOnlyServiceToFlushSending
|
|
* will be really sent before disconnecting. In some cases disconnect(true) can take a while.
|
|
* \param namesOfOnlyServiceToFlushSending When mustFlushSendQueues is true, this param can hold
|
|
* a list of service short names. Only the send queues to the services specified
|
|
* will be flushed (and waited) at exit. If the list is empty (and mustFlushSendQueues is true),
|
|
* all the queues will be flushed (and waited).
|
|
* See also "Handling network congestion" in CUnifiedNetwork above comments, and tryFlushAllQueues().
|
|
*/
|
|
void release (bool mustFlushSendQueues=true, const std::vector<std::string>& namesOfOnlyServiceToFlushSending=std::vector<std::string>() );
|
|
|
|
/** Adds a specific service to the list of connected services.
|
|
*
|
|
* If the connection succeeds immediately (i.e. the specified service is already online),
|
|
* service up callbacks (for this service and for "*") will be called from within addService().
|
|
* If the service is not available, the connection will be attempted evently in a background thread.
|
|
* Then when it will become available, the service up callbacks will be called.
|
|
*
|
|
* Warning: currently, this method must not be called within a network callback.
|
|
*/
|
|
void addService(const std::string &name, const CInetAddress &addr, bool sendId = true, bool external = true, TServiceId sid=TServiceId(), bool autoRetry = true, bool shouldBeAlreayInserted = false);
|
|
void addService(const std::string &name, const std::vector<CInetAddress> &addr, bool sendId = true, bool external = true, TServiceId sid=TServiceId(), bool autoRetry = true, bool shouldBeAlreayInserted = false);
|
|
|
|
/** Adds a callback array in the system. You can add callback only *after* adding the server, the client or the group.
|
|
*/
|
|
void addCallbackArray (const TUnifiedCallbackItem *callbackarray, sint arraysize);
|
|
|
|
/** Call it evenly. the parameter select the timeout value in seconds for each update. You are absolutely certain that this
|
|
* function will not be returns before this amount of time you set.
|
|
* If you set the update timeout value higher than 0, all messages in queues will be process until the time is greater than the timeout user update().
|
|
* If you set the update timeout value to 0, all messages in queues will be process one time before calling the user update(). In this case, we don't nlSleep(1).
|
|
*/
|
|
void update (NLMISC::TTime timeout = 0);
|
|
|
|
/** Sends a message to a specific serviceName. If there's more than one service with this name, all services of this name will receive the message.
|
|
* \param serviceName name of the service you want to send the message (may not be unique.)
|
|
* \param msg the message you want to send.
|
|
* \param nid Network Id specify to which network the message must pass throw (0xFF mean the default network)
|
|
* \return the number of service instances found (may be counter even if the sending failed)
|
|
*/
|
|
uint send (const std::string &serviceName, const CMessage &msg, bool warnIfNotFound=true, uint8 nid=0xFF);
|
|
|
|
/** Sends a message to a specific serviceId.
|
|
* \param serviceId Id of the service you want to send the message.
|
|
* \param msg the message you want to send.
|
|
* \param nid Network Id specify to which network the message must pass throw (0xFF mean the default network)
|
|
* \return true if the service was found (may return true even if the sending failed)
|
|
*/
|
|
bool send (TServiceId serviceId, const CMessage &msg, uint8 nid=0xFF);
|
|
|
|
/** Broadcasts a message to all connected services.
|
|
* \param msg the message you want to send.
|
|
* \param nid Network Id specify to which network the message must pass throw (0xFF mean the default network)
|
|
*/
|
|
void sendAll (const CMessage &msg, uint8 nid=0xFF);
|
|
|
|
/** Flush all or part of the sending queues, and report the number of bytes still pending.
|
|
* To ensure manually all data are sent before stopping a service, you may want
|
|
* to repeat calling this method evenly until it returns 0. The default release(false) of
|
|
* CUnifiedNetwork only flushes each connection once, but if the network is
|
|
* congested (when there are big streams to send) the first flush may not
|
|
* succeed to send entire buffers.
|
|
* \param namesOfOnlyServiceToFlushSending If not empty, only the send queues to the
|
|
* services specified (by short name) will be flushed.
|
|
* See also "Handling network congestion" in CUnifiedNetwork above comments.
|
|
*/
|
|
uint tryFlushAllQueues(const std::vector<std::string>& namesOfOnlyServiceToFlushSending=std::vector<std::string>());
|
|
|
|
/** Sets callback for incoming connections.
|
|
* On a client, the callback will be called when the connection to the server is established (the first connection or after the server shutdown and started)
|
|
* On a server, the callback is called each time a new client is connected to him
|
|
*
|
|
* You can set more than one callback, each one will be called one after one.
|
|
* If the serviceName is "*", the callback will be call for any services, including 'external' services
|
|
* (i.e. services not in the NS address space, usually connected by calling addService() manually)
|
|
* If you set the same callback for a specific service S and for "*", the callback might be
|
|
* called twice (in case the service S is up)
|
|
*
|
|
* \param back if true, put the callback at the end of the callback array, otherwise but on the beginning. You should always use true
|
|
*/
|
|
void setServiceUpCallback (const std::string &serviceName, TUnifiedNetCallback cb, void *arg = 0, bool back=true);
|
|
|
|
/** Remove a service up callback */
|
|
void removeServiceUpCallback (const std::string &serviceName, TUnifiedNetCallback cb, void *arg = 0);
|
|
|
|
/** Sets callback for disconnections.
|
|
* On a client, the callback will be call each time the connection to the server is lost.
|
|
* On a server, the callback is called each time a client is disconnected.
|
|
*
|
|
* You can set more than one callback, each one will be called one after one.
|
|
* If the serviceName is "*", the callback will be call for any services, including 'external' services
|
|
* (i.e. services not in the NS address space, usually connected by calling addService() manually)
|
|
* If you set the same callback for a specific service S and for "*", the callback might be
|
|
* called twice (in case the service S is down)
|
|
*
|
|
* \param back if true, put the callback at the end of the callback array, otherwise but on the beginning. You should always use true
|
|
*/
|
|
void setServiceDownCallback (const std::string &serviceName, TUnifiedNetCallback cb, void *arg = 0, bool back=true);
|
|
|
|
/** Remove a service down callback */
|
|
void removeServiceDownCallback (const std::string &serviceName, TUnifiedNetCallback cb, void *arg = 0);
|
|
|
|
/** Associate a string with a network id
|
|
* If the send don't set a specific nid, it ll use the 0, so be sure that the nid 0 is set to a network.
|
|
* You must call this function before the connect() function.
|
|
* \param networkName must be in a xxx.xxx.xxx.xxx format. The low value will be ignore depending of the network class.
|
|
* \param nid a number (used as an index in a vector for constant access so numbers should be contiguous) that will be use to send to this network.
|
|
*/
|
|
void addNetworkAssociation (const std::string &networkName, uint8 nid);
|
|
|
|
/** Clear all network association */
|
|
void clearNetworkAssociation () { _NetworkAssociations.clear (); }
|
|
|
|
/** This array says to which network we need to send the message for the default nid.
|
|
* For example you can says that message for AES will use the network 0 and message for LS will use the network 1.
|
|
* To do that, just call the function with string "AES0" and "LS1" the number is the nid (look at addNetworkAssociation())
|
|
* addNetworkAssociation("192.168.0.0", 0); addNetworkAssociation("192.168.1.0", 1);
|
|
* In this case if you send a message to AES with default nid, it'll be send to 192.168.0.x
|
|
* In this case if you send a message to LS with default nid, it'll be send to 192.168.1.y
|
|
*/
|
|
void addDefaultNetwork (const std::string &defnet) { nlinfo ("HNETL5: Add default network '%s'", defnet.c_str()); _DefaultNetwork.push_back (defnet); }
|
|
|
|
/// Clear all default network
|
|
void clearDefaultNetwork () { _DefaultNetwork.clear (); }
|
|
|
|
/// Returns true if the sid service is on the same computer than this service
|
|
bool isServiceLocal (TServiceId sid);
|
|
|
|
/// Returns true if the serviceName service is on the same computer than this service
|
|
bool isServiceLocal (const std::string &serviceName);
|
|
|
|
/// Return the name of the specified service, or "" if not found
|
|
std::string getServiceName(TServiceId sid);
|
|
|
|
/// Return a string identifying the service, using the format "NAME-sid" (or "sid" only if not found)
|
|
std::string getServiceUnifiedName(TServiceId sid);
|
|
|
|
/// \warning You should not use getNetBase functions because it could have more than one connection to a service and in this case
|
|
/// it ll return the first connection
|
|
|
|
/// Gets the CCallbackNetBase of the service
|
|
CCallbackNetBase *getNetBase(const std::string &name, TSockId &host, uint8 nid=0xFF);
|
|
|
|
/// Gets the CCallbackNetBase of the service
|
|
CCallbackNetBase *getNetBase(TServiceId sid, TSockId &host, uint8 nid=0xFF);
|
|
|
|
/// Gets the total number of bytes sent
|
|
uint64 getBytesSent ();
|
|
|
|
/// Gets the total number of bytes received
|
|
uint64 getBytesReceived ();
|
|
|
|
/// Gets the total number of bytes queued for sending
|
|
uint64 getSendQueueSize ();
|
|
|
|
/// Gets the total number of bytes queued after receiving
|
|
uint64 getReceiveQueueSize ();
|
|
|
|
/// Find a callback in the array
|
|
TUnifiedMsgCallback findCallback (const std::string &callbackName);
|
|
|
|
/// Return the service ids of the active connections
|
|
const std::vector<TServiceId>& getConnectionList() const { return _UsedConnection; }
|
|
|
|
/// Return the state of the connection (return true if the connection is fully connected)
|
|
bool isConnectionConnected(TServiceId sid) const;
|
|
|
|
void displayInternalTables (NLMISC::CLog *log = NLMISC::InfoLog);
|
|
|
|
void displayUnifiedConnection (TServiceId sid, NLMISC::CLog *log = NLMISC::InfoLog)
|
|
{
|
|
getUnifiedConnection(sid)->display(false, log);
|
|
}
|
|
|
|
private:
|
|
|
|
/// A map of service ids, referred by a service name
|
|
struct TNameMappedConnection : public CHashMultiMap<std::string, TServiceId> {};
|
|
|
|
/// A map of callbacks, referred by message name
|
|
typedef std::map<std::string, TUnifiedMsgCallback> TMsgMappedCallback;
|
|
|
|
/// A callback and its user data
|
|
typedef std::pair<TUnifiedNetCallback, void *> TCallbackArgItem;
|
|
|
|
/// A map of service up/down callbacks with their user data.
|
|
typedef CHashMap<std::string, std::list<TCallbackArgItem> > TNameMappedCallback;
|
|
|
|
/// This may contains a CCallbackClient or a TSockId, depending on which type of connection it is.
|
|
class CUnifiedConnection
|
|
{
|
|
public:
|
|
/// NotUsed = the unified connection is empty, not used
|
|
/// Ready = we can use the unified connection
|
|
enum TState { NotUsed, Ready };
|
|
|
|
/// The connection structure
|
|
struct TConnection
|
|
{
|
|
/// If the current service is connect to the other service as a server or a client
|
|
bool IsServerConnection;
|
|
/// If it s a client connection, it's the client connection otherwise it s the server connection
|
|
CCallbackNetBase *CbNetBase;
|
|
/// If it s a server connection, it's the host id, it s InvalidId if it s a client
|
|
TSockId HostId;
|
|
|
|
TConnection() : IsServerConnection(false), CbNetBase(NULL), HostId(InvalidSockId) { }
|
|
TConnection(CCallbackClient *cbc) : IsServerConnection(false), CbNetBase(cbc), HostId(InvalidSockId) { }
|
|
TConnection(CCallbackNetBase *cbnb, TSockId hi) : IsServerConnection(true), CbNetBase(cbnb), HostId(hi) { }
|
|
|
|
void setAppId (uint64 appid) { CbNetBase->getSockId (HostId)->setAppId (appid); }
|
|
uint64 getAppId () { return CbNetBase->getSockId (HostId)->appId (); }
|
|
|
|
bool valid ()
|
|
{
|
|
if(IsServerConnection)
|
|
return CbNetBase != 0 && HostId != InvalidSockId;
|
|
else
|
|
return CbNetBase != 0;
|
|
}
|
|
|
|
void reset ()
|
|
{
|
|
if (CbNetBase != 0)
|
|
{
|
|
if (IsServerConnection)
|
|
{
|
|
if (HostId != InvalidSockId)
|
|
CbNetBase->disconnect (HostId);
|
|
}
|
|
else
|
|
{
|
|
CbNetBase->disconnect ();
|
|
delete CbNetBase;
|
|
}
|
|
}
|
|
CbNetBase = 0;
|
|
IsServerConnection = false;
|
|
HostId = InvalidSockId;
|
|
}
|
|
};
|
|
|
|
|
|
/// The name of the service (may not be unique)
|
|
std::string ServiceName;
|
|
/// The id of the service (is unique)
|
|
TServiceId ServiceId;
|
|
/// If the service entry is used
|
|
TState State;
|
|
/// If the connection is extern to the naming service
|
|
bool IsExternal;
|
|
/// Auto-retry mode
|
|
bool AutoRetry;
|
|
/// Valid External
|
|
bool ValidExternal;
|
|
/// Validation Requested
|
|
bool ValidRequested;
|
|
/// Auto identify at connection
|
|
bool SendId;
|
|
/// Used for debug purpose
|
|
uint AutoCheck;
|
|
/// The external connection address
|
|
std::vector<CInetAddress> ExtAddress;
|
|
/// Connection to the service (me be > 1)
|
|
std::vector<TConnection> Connections;
|
|
/// This is used to associate a nid (look addNetworkAssociation) with a TConnection.
|
|
std::vector<uint8> NetworkConnectionAssociations;
|
|
/// This contains the connection id that will be used for default network, it's a connection id used for Connection index
|
|
uint8 DefaultNetwork;
|
|
|
|
uint32 TotalCallbackCalled;
|
|
|
|
CUnifiedConnection() { reset(); }
|
|
|
|
CUnifiedConnection(const std::string &name, TServiceId id, bool isExternal)
|
|
{
|
|
reset ();
|
|
ServiceName = name;
|
|
ServiceId = id;
|
|
State = Ready;
|
|
IsExternal = isExternal;
|
|
}
|
|
|
|
CUnifiedConnection(const std::string &name, TServiceId id, CCallbackClient *cbc)
|
|
{
|
|
reset ();
|
|
ServiceName = name;
|
|
ServiceId = id;
|
|
State = Ready;
|
|
Connections.push_back(TConnection (cbc));
|
|
}
|
|
|
|
void display (bool full, NLMISC::CLog *log = NLMISC::InfoLog);
|
|
|
|
void reset()
|
|
{
|
|
ServiceName = "DEAD";
|
|
ServiceId = TServiceId(0xDEAD);
|
|
State = NotUsed;
|
|
IsExternal = false;
|
|
ValidExternal = false;
|
|
ValidRequested = false;
|
|
AutoRetry = false;
|
|
SendId = false;
|
|
AutoCheck = false;
|
|
ExtAddress.clear ();
|
|
for (uint i = 0; i < Connections.size (); i++)
|
|
Connections[i].reset();
|
|
Connections.clear ();
|
|
DefaultNetwork = 0xDD;
|
|
NetworkConnectionAssociations.clear();
|
|
TotalCallbackCalled = 0;
|
|
}
|
|
|
|
// this function wrap the global default network and network association with this specific connection because they can have
|
|
// different index
|
|
void setupNetworkAssociation (const std::vector<uint32> &networkAssociations, const std::vector<std::string> &defaultNetwork)
|
|
{
|
|
for (uint i = 0; i < networkAssociations.size (); i++)
|
|
{
|
|
uint j;
|
|
for (j = 0; j < ExtAddress.size (); j++)
|
|
{
|
|
if (ExtAddress[j].internalNetAddress() == networkAssociations[i])
|
|
{
|
|
// we found an association, add it
|
|
if (i >= NetworkConnectionAssociations.size ())
|
|
NetworkConnectionAssociations.resize (i+1);
|
|
|
|
NetworkConnectionAssociations[i] = uint8(j);
|
|
nlinfo ("HNETL5: nid %u will be use connection %u", i, j);
|
|
break;
|
|
}
|
|
}
|
|
if (j == ExtAddress.size ())
|
|
{
|
|
nlinfo ("HNETL5: nid %u is not found", i);
|
|
}
|
|
}
|
|
// find the default network
|
|
std::vector<std::string>::size_type j;
|
|
for (j = 0; j < defaultNetwork.size (); j++)
|
|
{
|
|
std::string::size_type pos = defaultNetwork[j].find(ServiceName);
|
|
if (pos != std::string::npos && pos == 0 && ServiceName.size() == defaultNetwork[j].size ()-1)
|
|
{
|
|
uint8 nid = defaultNetwork[j][defaultNetwork[j].size ()-1] - '0';
|
|
DefaultNetwork = NetworkConnectionAssociations[nid];
|
|
nlinfo ("HNETL5: default network for '%s' will be nid %hu and connection id %hu", ServiceName.c_str(), (uint16)nid, (uint16)DefaultNetwork);
|
|
break;
|
|
}
|
|
}
|
|
if (j == defaultNetwork.size ())
|
|
{
|
|
if (NetworkConnectionAssociations.size ()>0)
|
|
DefaultNetwork = NetworkConnectionAssociations[0];
|
|
else
|
|
DefaultNetwork = 0;
|
|
|
|
if (defaultNetwork.size () > 0)
|
|
nlwarning ("HNETL5: default network not found in the array, will use connection id %hu", (uint16)DefaultNetwork);
|
|
}
|
|
}
|
|
};
|
|
|
|
NLMISC_COMMAND_HANDLER_TABLE_BEGIN(CUnifiedNetwork)
|
|
NLMISC_COMMAND_HANDLER_ADD(CUnifiedNetwork, addService, "Add a service in the unified network", "<serviceName> ( address=<address:port> [sid=<serviceId>] [sendId] [external] [autoRetry] )")
|
|
NLMISC_COMMAND_HANDLER_TABLE_END
|
|
|
|
NLMISC_CLASS_COMMAND_DECL(addService);
|
|
|
|
protected:
|
|
|
|
/// Auto-reconnect
|
|
void autoReconnect( CUnifiedConnection &uc, uint connectionIndex );
|
|
|
|
#ifdef NL_OS_UNIX
|
|
/// Sleep (implemented by select())
|
|
void sleepUntilDataAvailable( NLMISC::TTime msecMax );
|
|
#endif
|
|
|
|
private:
|
|
|
|
/// Vector of connections by service id (sid is the entry in this array, it means that there s some hole)
|
|
std::vector<CUnifiedConnection> _IdCnx ;
|
|
|
|
/// Vector of closed connection to reset outside of the client update loop
|
|
std::vector<TServiceId> _ConnectionToReset;
|
|
|
|
/// This vector contains only an index to the unified connection. It is used to have quick access on the available connections
|
|
std::vector<TServiceId> _UsedConnection;
|
|
|
|
/// Map of connections by service name
|
|
TNameMappedConnection _NamedCnx;
|
|
|
|
/// The callback server
|
|
CCallbackServer *_CbServer;
|
|
|
|
/// Map of the up/down service callbacks
|
|
TNameMappedCallback _UpCallbacks;
|
|
std::vector<TCallbackArgItem> _UpUniCallback;
|
|
TNameMappedCallback _DownCallbacks;
|
|
std::vector<TCallbackArgItem> _DownUniCallback;
|
|
|
|
/// Recording state
|
|
CCallbackNetBase::TRecordingState _RecordingState;
|
|
|
|
/// Service name
|
|
std::string _Name;
|
|
|
|
/// Map of callbacks
|
|
TMsgMappedCallback _Callbacks;
|
|
|
|
/// The server port
|
|
uint16 _ServerPort;
|
|
|
|
/// Used for external service
|
|
TServiceId _ExtSId;
|
|
|
|
/// Last time of retry
|
|
NLMISC::TTime _LastRetry;
|
|
|
|
/// Time of the theoretical next update
|
|
NLMISC::TTime _NextUpdateTime;
|
|
|
|
/// The main instance
|
|
// static CUnifiedNetwork *_Instance;
|
|
|
|
/// Naming service
|
|
NLNET::CInetAddress _NamingServiceAddr;
|
|
|
|
/// for each nid, which network address
|
|
std::vector<uint32> _NetworkAssociations;
|
|
|
|
/// for each services, which network to take
|
|
std::vector<std::string> _DefaultNetwork;
|
|
|
|
#ifdef NL_OS_UNIX
|
|
/// Pipe to select() on data available (shared among all connections)
|
|
int _MainDataAvailablePipe [2];
|
|
#endif
|
|
|
|
/// Service id of the running service
|
|
TServiceId _SId;
|
|
|
|
/// true if initialization function called
|
|
bool _Initialised;
|
|
|
|
//
|
|
CUnifiedNetwork() :
|
|
ICommandsHandler(),
|
|
_CbServer(0),
|
|
_ExtSId(256),
|
|
_LastRetry(0),
|
|
_NextUpdateTime(0),
|
|
_Initialised(false)
|
|
{
|
|
}
|
|
|
|
~CUnifiedNetwork() {}
|
|
|
|
//
|
|
void autoCheck();
|
|
|
|
// Return the unified connection if available or NULL.
|
|
// Don't keep the pointer because it can be invalid if the table is resized.
|
|
CUnifiedConnection *getUnifiedConnection (TServiceId sid, bool warn=true);
|
|
|
|
bool haveNamedCnx (const std::string &name, TServiceId sid);
|
|
void addNamedCnx (const std::string &name, TServiceId sid);
|
|
void removeNamedCnx (const std::string &name, TServiceId sid);
|
|
|
|
// with a sid and a nid, find a good connection to send a message
|
|
uint8 findConnectionId (TServiceId sid, uint8 nid);
|
|
|
|
void callServiceUpCallback (const std::string &serviceName, TServiceId sid, bool callGlobalCallback = true);
|
|
void callServiceDownCallback (const std::string &serviceName, TServiceId sid, bool callGlobalCallback = true);
|
|
|
|
friend void uncbConnection(TSockId from, void *arg);
|
|
friend void uncbDisconnection(TSockId from, void *arg);
|
|
friend void uncbServiceIdentification(CMessage &msgin, TSockId from, CCallbackNetBase &netbase);
|
|
friend void uncbMsgProcessing(CMessage &msgin, TSockId from, CCallbackNetBase &netbase);
|
|
friend void uNetRegistrationBroadcast(const std::string &name, TServiceId sid, const std::vector<CInetAddress> &addr);
|
|
friend void uNetUnregistrationBroadcast(const std::string &name, TServiceId sid, const std::vector<CInetAddress> &addr);
|
|
friend struct nel_isServiceLocalClass;
|
|
friend struct nel_l5CallbackClass;
|
|
friend struct nel_l5QueuesStatsClass;
|
|
};
|
|
|
|
} // NLNET
|
|
|
|
#endif // NL_UNIFIED_NETWORK_H
|
|
|
|
/* End of unified_network.h */
|