TrinityCore
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
G3D::ReliableConduit Class Reference

#include <NetworkDevice.h>

Public Member Functions

 ~ReliableConduit ()
 
virtual bool messageWaiting ()
 
template<typename T >
void send (uint32 type, const T &message)
 
void send (uint32 type)
 
virtual uint32 waitingMessageType ()
 
template<typename T >
bool receive (T &message)
 
void receive ()
 
NetAddress address () const
 
- Public Member Functions inherited from G3D::Conduit
virtual ~Conduit ()
 
uint64 bytesSent () const
 
uint64 messagesSent () const
 
uint64 bytesReceived () const
 
uint64 messagesReceived () const
 
bool ok () const
 
- Public Member Functions inherited from G3D::ReferenceCountedObject
virtual ~ReferenceCountedObject ()
 

Static Public Member Functions

static ReliableConduitRef create (const NetAddress &address)
 
template<typename T >
static void multisend (const Array< ReliableConduitRef > &array, uint32 type, const T &m)
 

Private Types

enum  State { RECEIVING, HOLDING, NO_MESSAGE }
 

Private Member Functions

 ReliableConduit (const NetAddress &addr)
 
 ReliableConduit (const SOCKET &sock, const NetAddress &addr)
 
void sendBuffer (const BinaryOutput &b)
 
void receiveIntoBuffer ()
 
void receiveHeader ()
 

Static Private Member Functions

template<typename T >
static void serializeMessage (uint32 t, const T &m, BinaryOutput &b)
 

Private Attributes

enum G3D::ReliableConduit::State state
 
NetAddress addr
 
uint32 messageType
 
uint32 messageSize
 
void * receiveBuffer
 
size_t receiveBufferTotalSize
 
size_t receiveBufferUsedSize
 

Friends

class NetworkDevice
 
class NetListener
 

Additional Inherited Members

- Protected Member Functions inherited from G3D::Conduit
 Conduit ()
 
- Protected Attributes inherited from G3D::Conduit
uint64 mSent
 
uint64 mReceived
 
uint64 bSent
 
uint64 bReceived
 
SOCKET sock
 
BinaryOutput binaryOutput
 

Detailed Description

A conduit that guarantees messages will arrive, intact and in order. Create on the client using NetworkDevice::createReliableConduit and on the server using NetListener::waitForConnection. Set the reference counted pointer to NULL to disconnect.

To construct a ReliableConduit:

  1. Create a G3D::NetworkDevice (if you are using G3D::GApp, it creates one for you) on the client and on the server.
  2. On the server, create a G3D::NetListener using G3D::NetworkDevice::createListener
  3. On the server, invoke G3D::NetListener::waitForConnection.
  4. On the client, call G3D::NetworkDevice::createReliableConduit. You will need the server's G3D::NetAddress. Consider using G3D::Discovery::Client to find it via broadcasting.
Deprecated:

Member Enumeration Documentation

Enumerator
RECEIVING 
HOLDING 
NO_MESSAGE 
Definition: NetworkDevice.h:173
Definition: NetworkDevice.h:173
enum G3D::ReliableConduit::State state
Definition: NetworkDevice.h:173

Constructor & Destructor Documentation

G3D::ReliableConduit::ReliableConduit ( const NetAddress addr)
private
617  :
618  state(NO_MESSAGE),
622 
624 
625  messageType = 0;
626 
627  addr = _addr;
628  Log::common()->print("Creating a TCP socket ");
629  sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
630 
631  if (sock == SOCKET_ERROR) {
632  Log::common()->println("FAIL");
634  nd->closesocket(sock);
635  return;
636  }
637 
638  Log::common()->println("Ok");
639 
640  // Setup socket options (both constructors should set the same options)
641 
642  // Disable Nagle's algorithm (we send lots of small packets)
643  const int T = true;
644  if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
645  (const char*)&T, sizeof(T)) == SOCKET_ERROR) {
646 
647  Log::common()->println("WARNING: Disabling Nagel's "
648  "algorithm failed.");
650  } else {
651  Log::common()->println("Disabled Nagel's algorithm.");
652  }
653 
654  // Set the NO LINGER option so the socket doesn't hang around if
655  // there is unsent data in the queue when it closes.
656  struct linger ling;
657  ling.l_onoff = 0;
658  ling.l_linger = 0;
659  if (setsockopt(sock, SOL_SOCKET, SO_LINGER,
660  (const char*)&ling, sizeof(ling)) == SOCKET_ERROR) {
661 
662  Log::common()->println("WARNING: Setting socket no linger failed.");
664  } else {
665  Log::common()->println("Set socket option no_linger.");
666  }
667 
668  // Set reuse address so that a new server can start up soon after
669  // an old one has closed.
670  if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
671  (const char*)&T, sizeof(T)) == SOCKET_ERROR) {
672 
673  Log::common()->println("WARNING: Setting socket reuseaddr failed.");
675  } else {
676  Log::common()->println("Set socket option reuseaddr.");
677  }
678 
679  // Ideally, we'd like to specify IPTOS_LOWDELAY as well.
680 
682 
684 
685  Log::common()->printf("Created TCP socket %d\n", sock);
686 
687  std::string x = addr.toString();
688  Log::common()->printf("Connecting to %s on TCP socket %d ", x.c_str(), sock);
689 
690  int ret = connect(sock, (struct sockaddr *) &(addr.addr), sizeof(addr.addr));
691 
692  if (ret == WSAEWOULDBLOCK) {
693  RealTime t = System::time() + 5.0;
694  // Non-blocking; we must wait until select returns non-zero
695  while ((selectOneWriteSocket(sock) == 0) && (System::time() < t)) {
696  System::sleep(0.02);
697  }
698 
699  // TODO: check for failure on the select call
700 
701  } else if (ret != 0) {
702  sock = (SOCKET)SOCKET_ERROR;
703  Log::common()->println("FAIL");
705  return;
706  }
707 
708  Log::common()->println("Ok");
709 }
SOCKADDR_IN addr
Definition: NetAddress.h:30
static void increaseBufferSize(SOCKET sock)
Definition: NetworkDevice.cpp:587
friend class NetworkDevice
Definition: NetworkDevice.h:170
size_t receiveBufferTotalSize
Definition: NetworkDevice.h:191
static void logSocketInfo(const SOCKET &sock)
Definition: NetworkDevice.cpp:31
static std::string socketErrorCode(int code)
Definition: networkHelpers.h:64
arena_t NULL
Definition: jemalloc_internal.h:624
static void sleep(RealTime t)
Definition: SystemImpl.cpp:14
double RealTime
Definition: G3DGameUnits.h:27
SOCKET sock
Definition: NetworkDevice.h:67
void print(const std::string &s)
Definition: Log.cpp:138
NetAddress addr
Definition: NetworkDevice.h:175
void __cdecl printf(const char *fmt,...) G3D_CHECK_PRINTF_METHOD_ARGS
Definition: Log.cpp:119
static int selectOneWriteSocket(const SOCKET &sock)
Definition: NetworkDevice.cpp:93
void * receiveBuffer
Definition: NetworkDevice.h:188
enum G3D::ReliableConduit::State state
uint32 messageType
Definition: NetworkDevice.h:180
Definition: NetworkDevice.h:173
static RealTime time()
Definition: System.cpp:934
std::string toString() const
Definition: NetAddress.cpp:185
static Log * common()
Definition: Log.cpp:100
G3D::int16 x
Definition: Vector2int16.h:37
void println(const std::string &s)
Definition: Log.cpp:144
size_t receiveBufferUsedSize
Definition: NetworkDevice.h:196
#define SOCKET
Definition: netheaders.h:20
static NetworkDevice * instance()
Definition: NetworkDevice.cpp:109

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

G3D::ReliableConduit::ReliableConduit ( const SOCKET sock,
const NetAddress addr 
)
private
714  :
715  state(NO_MESSAGE),
719  sock = _sock;
720  addr = _addr;
721 
722  messageType = 0;
723 
724  // Setup socket options (both constructors should set the same options)
725 
726  // Disable Nagle's algorithm (we send lots of small packets)
727  const int T = true;
728  if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
729  (const char*)&T, sizeof(T)) == SOCKET_ERROR) {
730 
731  Log::common()->println("WARNING: Disabling Nagel's algorithm failed.");
733  } else {
734  Log::common()->println("Disabled Nagel's algorithm.");
735  }
736 
737  // Set the NO LINGER option so the socket doesn't hang around if
738  // there is unsent data in the queue when it closes.
739  struct linger ling;
740  ling.l_onoff = 0;
741  ling.l_linger = 0;
742  if (setsockopt(sock, SOL_SOCKET, SO_LINGER,
743  (const char*)&ling, sizeof(ling)) == SOCKET_ERROR) {
744 
745  Log::common()->println("WARNING: Setting socket no linger failed.");
747  } else {
748  Log::common()->println("Set socket option no_linger.");
749  }
750 
751  // Set reuse address so that a new server can start up soon after
752  // an old one has closed.
753  if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
754  (const char*)&T, sizeof(T)) == SOCKET_ERROR) {
755 
756  Log::common()->println("WARNING: Setting socket reuseaddr failed.");
758  } else {
759  Log::common()->println("Set socket option reuseaddr.");
760  }
761 
762  // Ideally, we'd like to specify IPTOS_LOWDELAY as well.
763 
765 }
size_t receiveBufferTotalSize
Definition: NetworkDevice.h:191
static void logSocketInfo(const SOCKET &sock)
Definition: NetworkDevice.cpp:31
static std::string socketErrorCode(int code)
Definition: networkHelpers.h:64
arena_t NULL
Definition: jemalloc_internal.h:624
SOCKET sock
Definition: NetworkDevice.h:67
NetAddress addr
Definition: NetworkDevice.h:175
void * receiveBuffer
Definition: NetworkDevice.h:188
enum G3D::ReliableConduit::State state
uint32 messageType
Definition: NetworkDevice.h:180
Definition: NetworkDevice.h:173
static Log * common()
Definition: Log.cpp:100
void println(const std::string &s)
Definition: Log.cpp:144
size_t receiveBufferUsedSize
Definition: NetworkDevice.h:196

+ Here is the call graph for this function:

G3D::ReliableConduit::~ReliableConduit ( )

Closes the socket.

768  {
769  free(receiveBuffer);
773 }
size_t receiveBufferTotalSize
Definition: NetworkDevice.h:191
arena_t NULL
Definition: jemalloc_internal.h:624
void * receiveBuffer
Definition: NetworkDevice.h:188
size_t receiveBufferUsedSize
Definition: NetworkDevice.h:196

Member Function Documentation

NetAddress G3D::ReliableConduit::address ( ) const

The address of the other end of the conduit

870  {
871  return addr;
872 }
NetAddress addr
Definition: NetworkDevice.h:175
ReliableConduitRef G3D::ReliableConduit::create ( const NetAddress address)
static

Client invokes this to connect to a server. The call blocks until the conduit is opened. The conduit will not be ok() if it fails.

611  {
613 }
NetAddress address() const
Definition: NetworkDevice.cpp:870
shared_ptr< class ReliableConduit > ReliableConduitRef
Definition: NetworkDevice.h:136
ReliableConduit(const NetAddress &addr)
Definition: NetworkDevice.cpp:617

+ Here is the call graph for this function:

bool G3D::ReliableConduit::messageWaiting ( )
virtual

The message is actually copied from the socket to an internal buffer during this call. Receive only deserializes.

Reimplemented from G3D::Conduit.

776  {
777  switch (state) {
778  case HOLDING:
779  // We've already read the message and are waiting
780  // for a receive call.
781  return true;
782 
783  case RECEIVING:
784 
785  if (! ok()) {
786  return false;
787  }
788  // We're currently receiving the message. Read a little more.
790 
792  // We've read the whole mesage. Switch to holding state
793  // and return true.
794  state = HOLDING;
795  return true;
796  } else {
797  // There are more bytes left to read. We'll read them on
798  // the next call. Because the *entire* message is not ready,
799  // return false.
800  return false;
801  }
802  break;
803 
804  case NO_MESSAGE:
805  if (Conduit::messageWaiting()) {
806  // Message incoming. Read the header.
807 
808  state = RECEIVING;
809  receiveHeader();
810 
811  // Loop back around now that we're in the receive state; we
812  // may be able to read the whole message before returning
813  // to the caller.
814  return messageWaiting();
815  } else {
816  // No message incoming.
817  return false;
818  }
819  }
820 
821  debugAssertM(false, "Should not reach this point");
822  return false;
823 }
uint32 messageSize
Definition: NetworkDevice.h:185
void receiveHeader()
Definition: NetworkDevice.cpp:875
Definition: NetworkDevice.h:173
virtual bool messageWaiting()
Definition: NetworkDevice.cpp:776
void receiveIntoBuffer()
Definition: NetworkDevice.cpp:937
bool ok() const
Definition: NetworkDevice.cpp:574
#define debugAssertM(exp, message)
Definition: debugAssert.h:161
Definition: NetworkDevice.h:173
enum G3D::ReliableConduit::State state
Definition: NetworkDevice.h:173
virtual bool messageWaiting()
Definition: NetworkDevice.cpp:579
size_t receiveBufferUsedSize
Definition: NetworkDevice.h:196

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

template<typename T >
static void G3D::ReliableConduit::multisend ( const Array< ReliableConduitRef > &  array,
uint32  type,
const T &  m 
)
inlinestatic

Send the same message to a number of conduits. Useful for sending data from a server to many clients (only serializes once).

293  {
294 
295  if (array.size() > 0) {
296  array[0]->binaryOutput.reset();
297  serializeMessage(type, m, array[0]->binaryOutput);
298 
299  for (int i = 0; i < array.size(); ++i) {
300  array[i]->sendBuffer(array[0]->binaryOutput);
301  }
302  }
303  }
BinaryOutput binaryOutput
Definition: NetworkDevice.h:73
static void serializeMessage(uint32 t, const T &m, BinaryOutput &b)
Definition: NetworkDevice.h:204

+ Here is the call graph for this function:

template<typename T >
bool G3D::ReliableConduit::receive ( T &  message)
inline

If a message is waiting, deserializes the waiting message into message and returns true, otherwise returns false. You can determine the type of the message (and therefore, the class of message) using G3D::ReliableConduit::waitingMessageType().

313  {
314  if (! messageWaiting()) {
315  return false;
316  }
317 
319  // Deserialize
321  message.deserialize(b);
322 
323  // Don't let anyone read this message again. We leave the buffer
324  // allocated for the next caller, however.
326  state = NO_MESSAGE;
327  messageType = 0;
328  messageSize = 0;
329 
330  // Potentially read the next message.
331  messageWaiting();
332 
333  return true;
334  }
uint32 messageSize
Definition: NetworkDevice.h:185
virtual bool messageWaiting()
Definition: NetworkDevice.cpp:776
Definition: NetworkDevice.h:173
#define debugAssert(exp)
Definition: debugAssert.h:160
void * receiveBuffer
Definition: NetworkDevice.h:188
enum G3D::ReliableConduit::State state
static const bool NO_COPY
Definition: BinaryInput.h:147
uint32 messageType
Definition: NetworkDevice.h:180
Definition: NetworkDevice.h:173
Definition: System.h:50
uint8_t uint8
Definition: Define.h:152
size_t receiveBufferUsedSize
Definition: NetworkDevice.h:196

+ Here is the call graph for this function:

void G3D::ReliableConduit::receive ( )
inline

Removes the current message from the queue.

337  {
338  if (! messageWaiting()) {
339  return;
340  }
342  state = NO_MESSAGE;
343  messageType = 0;
344  messageSize = 0;
345 
346  // Potentially read the next message.
347  messageWaiting();
348  }
uint32 messageSize
Definition: NetworkDevice.h:185
virtual bool messageWaiting()
Definition: NetworkDevice.cpp:776
enum G3D::ReliableConduit::State state
uint32 messageType
Definition: NetworkDevice.h:180
Definition: NetworkDevice.h:173
size_t receiveBufferUsedSize
Definition: NetworkDevice.h:196

+ Here is the call graph for this function:

void G3D::ReliableConduit::receiveHeader ( )
private

Receives the messageType and messageSize from the socket.

875  {
878 
879  // Read the type
880  uint32 tmp;
881  int ret = recv(sock, (char*)&tmp, sizeof(tmp), 0);
882 
883  // The type is the first four bytes. It is little endian.
885  messageType = tmp;
886  } else {
887  // Swap the byte order
888  for (int i = 0; i < 4; ++i) {
889  ((char*)&messageType)[i] = ((char*)&tmp)[3 - i];
890  }
891  }
892 
893  if ((ret == SOCKET_ERROR) || (ret != sizeof(messageType))) {
894  Log::common()->printf("Call to recv failed. ret = %d,"
895  " sizeof(messageType) = %d\n",
896  (int)ret, (int)sizeof(messageType));
898  nd->closesocket(sock);
899  messageType = 0;
900  return;
901  }
902 
903  // Read the size
904  ret = recv(sock, (char*)&messageSize, sizeof(messageSize), 0);
905 
906  if ((ret == SOCKET_ERROR) || (ret != sizeof(messageSize))) {
907  Log::common()->printf("Call to recv failed. ret = %d,"
908  " sizeof(len) = %d\n", (int)ret,
909  (int)sizeof(messageSize));
911  nd->closesocket(sock);
912  messageType = 0;
913  return;
914  }
915 
916  messageSize = ntohl(messageSize);
917  debugAssert(messageSize < 6e7);
918 
920 
921  // Extend the size of the buffer.
925  }
926 
927  if (receiveBuffer == NULL) {
928  Log::common()->println("Could not allocate a memory buffer "
929  "during receivePacket.");
930  nd->closesocket(sock);
931  }
932 
933  bReceived += 4;
934 }
uint32 messageSize
Definition: NetworkDevice.h:185
friend class NetworkDevice
Definition: NetworkDevice.h:170
Definition: NetworkDevice.h:173
size_t receiveBufferTotalSize
Definition: NetworkDevice.h:191
static std::string socketErrorCode(int code)
Definition: networkHelpers.h:64
arena_t NULL
Definition: jemalloc_internal.h:624
SOCKET sock
Definition: NetworkDevice.h:67
void __cdecl printf(const char *fmt,...) G3D_CHECK_PRINTF_METHOD_ARGS
Definition: Log.cpp:119
#define debugAssert(exp)
Definition: debugAssert.h:160
uint32_t uint32
Definition: Define.h:150
void * receiveBuffer
Definition: NetworkDevice.h:188
enum G3D::ReliableConduit::State state
uint32 messageType
Definition: NetworkDevice.h:180
static G3DEndian machineEndian()
Definition: System.h:219
Definition: System.h:50
uint64 bReceived
Definition: NetworkDevice.h:65
static Log * common()
Definition: Log.cpp:100
void println(const std::string &s)
Definition: Log.cpp:144
size_t receiveBufferUsedSize
Definition: NetworkDevice.h:196
static NetworkDevice * instance()
Definition: NetworkDevice.cpp:109

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void G3D::ReliableConduit::receiveIntoBuffer ( )
private

Accumulates whatever part of the message (not the header) is still waiting on the socket into the receiveBuffer during state = RECEIVING mode. Closes the socket if anything goes wrong. When receiveBufferUsedSize == messageSize, the entire message has arrived.

937  {
939 
941  debugAssert(messageType != 0);
942  debugAssertM(receiveBufferUsedSize < messageSize, "Message already received.");
943  debugAssertM(messageSize >= receiveBufferUsedSize, "Message size overflow.");
944 
945  // Read the data itself
946  int ret = 0;
948  int count = 0;
949  while ((ret != SOCKET_ERROR) && (left > 0) && (count < 100)) {
950 
951  ret = recv(sock, ((char*)receiveBuffer) + (uint32)receiveBufferUsedSize, left, 0);
952 
953  if (ret > 0) {
954  left -= ret;
955  receiveBufferUsedSize += ret;
956  bReceived += ret;
957 
958  if (left > 0) {
959  // There's still more. Give the machine a chance to read
960  // more data, but don't wait forever.
961 
962  ++count;
963  System::sleep(0.001);
964  }
965  } else {
966  // Something went wrong; our blocking read returned nothing.
967  break;
968  }
969  }
970 
971  if ((ret == 0) || (ret == SOCKET_ERROR)) {
972 
973  if (ret == SOCKET_ERROR) {
974  Log::common()->printf("Call to recv failed. ret = %d,"
975  " sizeof(messageSize) = %d\n", ret, messageSize);
977  } else {
978  Log::common()->printf("recv returned 0\n");
979  }
980  nd->closesocket(sock);
981  return;
982  }
983 
984  ++mReceived;
985 }
uint32 messageSize
Definition: NetworkDevice.h:185
friend class NetworkDevice
Definition: NetworkDevice.h:170
Definition: NetworkDevice.h:173
static std::string socketErrorCode(int code)
Definition: networkHelpers.h:64
#define debugAssertM(exp, message)
Definition: debugAssert.h:161
static void sleep(RealTime t)
Definition: SystemImpl.cpp:14
SOCKET sock
Definition: NetworkDevice.h:67
void __cdecl printf(const char *fmt,...) G3D_CHECK_PRINTF_METHOD_ARGS
Definition: Log.cpp:119
#define debugAssert(exp)
Definition: debugAssert.h:160
uint32_t uint32
Definition: Define.h:150
void * receiveBuffer
Definition: NetworkDevice.h:188
enum G3D::ReliableConduit::State state
bool left(const int *a, const int *b, const int *c)
Definition: RecastContour.cpp:487
uint32 messageType
Definition: NetworkDevice.h:180
uint64 bReceived
Definition: NetworkDevice.h:65
uint32_t uint32
Definition: g3dmath.h:168
static Log * common()
Definition: Log.cpp:100
void println(const std::string &s)
Definition: Log.cpp:144
size_t receiveBufferUsedSize
Definition: NetworkDevice.h:196
uint64 mReceived
Definition: NetworkDevice.h:63
static NetworkDevice * instance()
Definition: NetworkDevice.cpp:109

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

template<typename T >
void G3D::ReliableConduit::send ( uint32  type,
const T &  message 
)
inline

Serializes the message and schedules it to be sent as soon as possible, and then returns immediately. The message can be any class with a serialize and deserialize method. On the receiving side, use G3D::ReliableConduit::waitingMessageType() to detect the incoming message and then invoke G3D::ReliableConduit::receive(msg) where msg is of the same class as the message that was sent.

The actual data sent across the network is preceeded by the message type and the size of the serialized message as a 32-bit integer. The size is sent because TCP is a stream protocol and doesn't have a concept of discrete messages.

277  {
279  serializeMessage(type, message, binaryOutput);
281  }
void sendBuffer(const BinaryOutput &b)
Definition: NetworkDevice.cpp:836
void reset()
Definition: BinaryOutput.cpp:240
BinaryOutput binaryOutput
Definition: NetworkDevice.h:73
static void serializeMessage(uint32 t, const T &m, BinaryOutput &b)
Definition: NetworkDevice.h:204

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void G3D::ReliableConduit::send ( uint32  type)

Sends an empty message with the given type. Useful for sending commands that have no parameters.

863  {
864  static Dummy dummy;
865  send(type, dummy);
866 }
void send(uint32 type, const T &message)
Definition: NetworkDevice.h:277

+ Here is the call graph for this function:

void G3D::ReliableConduit::sendBuffer ( const BinaryOutput b)
private
836  {
838  int ret = ::send(sock, (const char*)b.getCArray(), (int)b.size(), 0);
839 
840  if (ret == SOCKET_ERROR) {
841  Log::common()->println("Error occured while sending message.");
843  nd->closesocket(sock);
844  return;
845  }
846 
847  ++mSent;
848  bSent += b.size();
849 
850  // Verify the packet was actually sent
851  // Conversion to unsigned is safe because -1 is caught earlier
852  debugAssert(ret == b.size());
853 }
uint64 bSent
Definition: NetworkDevice.h:64
friend class NetworkDevice
Definition: NetworkDevice.h:170
void send(uint32 type, const T &message)
Definition: NetworkDevice.h:277
static std::string socketErrorCode(int code)
Definition: networkHelpers.h:64
uint64 mSent
Definition: NetworkDevice.h:62
SOCKET sock
Definition: NetworkDevice.h:67
#define debugAssert(exp)
Definition: debugAssert.h:160
static Log * common()
Definition: Log.cpp:100
void println(const std::string &s)
Definition: Log.cpp:144
static NetworkDevice * instance()
Definition: NetworkDevice.cpp:109

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

template<typename T >
static void G3D::ReliableConduit::serializeMessage ( uint32  t,
const T &  m,
BinaryOutput b 
)
inlinestaticprivate
204  {
205 
206  b.writeUInt32(t);
207 
208  // Reserve space for the 4 byte size header
209  b.writeUInt32(0);
210 
211  size_t L = (size_t)b.length();
212  m.serialize(b);
213  if ((size_t)b.length() == L) {
214  // No data was created by serialization.
215  // We need to send at least one byte because receive assumes that
216  // a zero length message is an error.
217  b.writeUInt8(0xFF);
218  }
219 
220  uint32 len = (uint32)b.size() - 8;
221 
222  // We send the length first to tell recv how much data to read.
223  // Here we abuse BinaryOutput a bit and write directly into
224  // its buffer, violating the abstraction.
225  // Note that we write to the second set of 4 bytes, which is
226  // the size field.
227  uint32* lenPtr = ((uint32*)b.getCArray()) + 1;
228  #if defined(__GNUC__)
229  *lenPtr = gcchtonl(len);
230  #else
231  *lenPtr = htonl(len);
232  #endif
233  }
uint32_t uint32
Definition: Define.h:150
uint32_t uint32
Definition: g3dmath.h:168

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

uint32 G3D::ReliableConduit::waitingMessageType ( )
virtual

Returns the type of the waiting message (i.e. the type supplied with send). The return value is zero when there is no message waiting.

One way to use this is to have a Table mapping message types to pre-allocated subclasses so receiving looks like:

    // My base class for messages.
    class Message {
        virtual void serialize(BinaryOutput&) const;
        virtual void deserialize(BinaryInput&);
        virtual void process() = 0;
    };
    Message* m = table[conduit->waitingMessageType()];
    conduit->receive(m);
    m->process();

Another is to simply switch on the message type:

    switch (conduit->waitingMessageType()) {
    case 0:
       // No message
       break;
    case ENTITY_SPAWN_MSG:
       {
          EntitySpawnMsg m;
          condiut->receive(m);
          spawnEntity(m.id, m.position, m.modelID);
       }
       break;
       ...
    }
 

Implements G3D::Conduit.

826  {
827  // The messageWaiting call is what actually receives the message.
828  if (messageWaiting()) {
829  return messageType;
830  } else {
831  return 0;
832  }
833 }
virtual bool messageWaiting()
Definition: NetworkDevice.cpp:776
uint32 messageType
Definition: NetworkDevice.h:180

+ Here is the call graph for this function:

Friends And Related Function Documentation

friend class NetListener
friend
friend class NetworkDevice
friend

Member Data Documentation

NetAddress G3D::ReliableConduit::addr
private
uint32 G3D::ReliableConduit::messageSize
private

Total size of the incoming message (read from the header).

uint32 G3D::ReliableConduit::messageType
private

Type of the incoming message.

void* G3D::ReliableConduit::receiveBuffer
private

Shared buffer for receiving messages.

size_t G3D::ReliableConduit::receiveBufferTotalSize
private

Total size of the receiveBuffer.

size_t G3D::ReliableConduit::receiveBufferUsedSize
private

Size occupied by the current message... so far. This will be equal to messageSize when the whole message has arrived.

enum G3D::ReliableConduit::State G3D::ReliableConduit::state
private

The documentation for this class was generated from the following files: