24 #ifndef __MSGQUEUE_H__ 25 #define __MSGQUEUE_H__ 27 #include <csutil/threading/atomicops.h> 28 #include <csutil/refcount.h> 29 #include <csutil/csendian.h> 30 #include <csutil/strhashr.h> 31 #include <csutil/strset.h> 32 #include <csgeom/vector3.h> 33 #include <iengine/sector.h> 34 #include <iengine/engine.h> 35 #include <csutil/csobject.h> 82 AtomicOperations::Increment(&ref_count);
88 if(AtomicOperations::Decrement(&ref_count) == 0)
90 CS_ASSERT_MSG(
"Race condition on destroying csSyncRef pointer", ref_count == 0);
98 return AtomicOperations::Read(&ref_count);
118 size_t GetSize()
const {
return csLittleEndian::Convert(size); }
119 void SetSize(
size_t len) { size = csLittleEndian::Convert((uint16)(len & 0xFFFF)); }
131 #define MSG_SIZEOF_VECTOR2 (2*sizeof(uint32)) 132 #define MSG_SIZEOF_VECTOR3 (3*sizeof(uint32)) 133 #define MSG_SIZEOF_VECTOR4 (4*sizeof(uint32)) 134 #define MSG_SIZEOF_SECTOR 100 // Sector can be a string in the message!!! 135 #define MSG_SIZEOF_FLOAT sizeof(uint32) 147 : clientnum(0), priority((sequence << 2) | msgpriority), msgid(0), overrun(false)
151 Error1(
"MsgEntry created with sequenced delivery but not guaranteed delivery. This is not reliable and probably won't work.");
156 Debug3(
LOG_NET,0,
"Call to MsgEntry construction truncated data. Requested size %u > max size %u.\n",(
unsigned int)datasize,(
unsigned int)
MAX_MESSAGE_SIZE);
161 CS_ASSERT(bytes != NULL);
164 bytes->SetSize(datasize);
168 : clientnum(0), priority(
PRIORITY_LOW), msgid(0), overrun(false)
173 Debug2(
LOG_NET,0,
"Call to MsgEntry construction (from network message psMessageBytes) truncated data. Source data > %u length.\n",
MAX_MESSAGE_SIZE);
180 CS_ASSERT(bytes != NULL);
182 memcpy (bytes, msg, msgsize);
184 bytes->SetTotalSize(msgsize);
192 Bug2(
"Call to MsgEntry copy constructor truncated data. Source data > %u length.\n",
MAX_MESSAGE_SIZE);
196 CS_ASSERT(bytes != NULL);
197 memcpy (bytes, me->
bytes, msgsize);
200 bytes->SetTotalSize(msgsize);
211 cs_free ((
void*) bytes);
216 bytes->SetSize(current);
219 void Reset(
int pos = 0) { current = pos; }
226 Bug1(
"MsgEntry::Add(const char *) bytes=NULL!\n");
238 if (current + 1 > bytes->GetSize())
240 Bug4(
"MsgEntry::Add(const char *) call for msgid=%u len=%u would overflow buffer! str = (null) type = %u\n",
241 msgid,0, bytes->type);
245 bytes->payload[current] = 0;
251 if (current + strlen(str)+1 > bytes->GetSize())
253 Bug6(
"MsgEntry::Add(const char *) call for msgid=%u len=%u would overflow buffer! str = %s type = %u size %zu\n",
254 (
unsigned int)msgid,(
unsigned int)strlen(str),str, bytes->type, bytes->GetSize());
259 strcpy(bytes->payload+current,str);
260 current += strlen(str)+1;
268 Bug1(
"MsgEntry::Add(const float) bytes=NULL!\n");
278 if (current +
sizeof(uint32) > bytes->GetSize())
280 Bug3(
"MsgEntry::Add(const float) call for msgid=%u would overflow buffer! type = %u\n",msgid, bytes->type);
285 uint32 *pf = (uint32 *)(bytes->payload+current);
286 *pf = csLittleEndian::Convert( csIEEEfloat::FromNative(f) );
287 current +=
sizeof(uint32);
293 void Add(
const double d)
297 Bug1(
"MsgEntry::Add(const double) bytes=NULL!\n");
307 if (current +
sizeof(
double) > bytes->GetSize())
309 Bug3(
"MsgEntry::Add(const double) call for msgid=%u would overflow buffer! type = %u\n",msgid, bytes->type);
314 double* p = (
double*) (bytes->payload+current);
315 *p = csLittleEndian::Convert(d);
316 current +=
sizeof(double);
321 void Add(
const uint16_t s)
325 Bug1(
"MsgEntry::Add(const uint16_t) bytes=NULL!\n");
335 if (current +
sizeof(uint16_t) > bytes->GetSize())
337 Bug3(
"MsgEntry::Add(const uint16_t) call for msgid=%u would overflow buffer! type = %u\n",msgid, bytes->type);
342 uint16_t *p = (uint16_t*) (bytes->payload+current);
343 *p = csLittleEndian::Convert(s);
344 current +=
sizeof(uint16_t);
352 Bug1(
"MsgEntry::Add(const int16_t) bytes=NULL!\n");
362 if (current +
sizeof(int16_t) > bytes->GetSize())
364 Bug3(
"MsgEntry::Add(const int16_t) call for msgid=%u would overflow buffer! type = %u\n",msgid, bytes->type);
369 int16_t *p = (int16_t *)(bytes->payload+current);
370 *p = csLittleEndian::Convert(s);
371 current +=
sizeof(int16_t);
378 Bug1(
"MsgEntry::Add(const int32_t) bytes=NULL!\n");
388 if (current +
sizeof(int32_t) > bytes->GetSize())
390 Bug3(
"MsgEntry::Add(const int32_t) call for msgid=%u would overflow buffer! type = %u\n",msgid, bytes->type);
395 int32_t *p = (int32_t *)(bytes->payload+current);
396 *p = csLittleEndian::Convert((int32) i);
397 current +=
sizeof(int32_t);
402 void Add(
const uint32_t i)
406 Bug1(
"MsgEntry::Add(const uint32_t) bytes=NULL!\n");
416 if (current +
sizeof(uint32_t) > bytes->GetSize())
418 Bug3(
"MsgEntry::Add(const uint32_t) call for msgid=%u would overflow buffer! type = %u\n",msgid, bytes->type);
423 uint32_t *p = (uint32_t *)(bytes->payload+current);
424 *p = csLittleEndian::Convert((uint32) i);
425 current +=
sizeof(uint32_t);
434 Bug1(
"MsgEntry::Add(const uintptr_t) bytes=NULL!\n");
444 if (current +
sizeof(uintptr_t) > bytes->GetSize())
446 Bug3(
"MsgEntry::Add(const uintptr_t) call for msgid=%u would overflow buffer! type = %u\n",msgid, bytes->type);
451 uintptr_t *p = (uintptr_t *)(bytes->payload+current);
453 current +=
sizeof(uintptr_t);
462 Bug1(
"MsgEntry::Add(const uint8_t) bytes=NULL!\n");
472 if (current +
sizeof(uint8_t) > bytes->GetSize())
474 Bug3(
"MsgEntry::Add(const uint8_t) call for msgid=%u would overflow buffer! type = %u\n",msgid, bytes->type);
479 uint8_t *p = (uint8_t *)(bytes->payload+current);
481 current +=
sizeof(uint8_t);
489 Bug1(
"MsgEntry::Add(const int8_t) bytes=NULL!\n");
499 if (current +
sizeof(int8_t) > bytes->GetSize())
501 Bug3(
"MsgEntry::Add(const int8_t) call for msgid=%u would overflow buffer! type = %u\n",msgid, bytes->type);
506 int8_t *p = (int8_t*) (bytes->payload+current);
508 current +=
sizeof(int8_t);
516 Bug1(
"MsgEntry::Add(const bool) bytes=NULL!\n");
526 if (current +
sizeof(uint8_t) > bytes->GetSize())
528 Bug3(
"MsgEntry::Add(const bool) call for msgid=%u would overflow buffer! type = %u\n",msgid, bytes->type);
533 uint8_t t = b ? 1 : 0;
538 void Add(
const csVector2& v)
542 Bug1(
"MsgEntry::Add(const csVector2) bytes=NULL!\n");
552 if (current + 2*
sizeof(uint32) > bytes->GetSize())
554 Bug3(
"MsgEntry::Add(const csVector2) call for msgid=%u would overflow buffer! type = %u\n",msgid, bytes->type);
559 uint32 *pf = (uint32 *)(bytes->payload+current);
560 *(pf++) = csLittleEndian::Convert( csIEEEfloat::FromNative(v.x) );
561 *pf = csLittleEndian::Convert( csIEEEfloat::FromNative(v.y) );
562 current += 2*
sizeof(uint32);
566 void Add(
const csVector3& v)
570 Bug1(
"MsgEntry::Add(const csVector3) bytes=NULL!\n");
580 if (current + 3*
sizeof(uint32) > bytes->GetSize())
582 Bug3(
"MsgEntry::Add(const csVector3) call for msgid=%u would overflow buffer! type = %u\n",msgid, bytes->type);
587 uint32 *pf = (uint32 *)(bytes->payload+current);
588 *(pf++) = csLittleEndian::Convert( csIEEEfloat::FromNative(v.x) );
589 *(pf++) = csLittleEndian::Convert( csIEEEfloat::FromNative(v.y) );
590 *pf = csLittleEndian::Convert( csIEEEfloat::FromNative(v.z) );
591 current += 3*
sizeof(uint32);
595 void Add(
const csVector4& v)
599 Bug1(
"MsgEntry::Add(const csVector4) bytes=NULL!\n");
609 if (current + 4*
sizeof(uint32) > bytes->GetSize())
611 Bug3(
"MsgEntry::Add(const csVector4) call for msgid=%u would overflow buffer! type = %u\n",msgid, bytes->type);
616 uint32 *pf = (uint32 *)(bytes->payload+current);
617 *(pf++) = csLittleEndian::Convert( csIEEEfloat::FromNative(v.x) );
618 *(pf++) = csLittleEndian::Convert( csIEEEfloat::FromNative(v.y) );
619 *(pf++) = csLittleEndian::Convert( csIEEEfloat::FromNative(v.z) );
620 *pf = csLittleEndian::Convert( csIEEEfloat::FromNative(v.w) );
621 current += 4*
sizeof(uint32);
624 void Add(
const iSector* sector,
const csStringSet* msgstrings,
const csStringHashReversible* msgstringshash = NULL)
626 const char* sectorName =
const_cast<iSector*
>(sector)->QueryObject()->GetName ();
627 csStringID sectorNameStrId = csInvalidStringID;
632 if (msgstrings->Contains(sectorName))
634 sectorNameStrId =
const_cast<csStringSet*
>(msgstrings)->Request(sectorName);
638 sectorNameStrId = csInvalidStringID;
640 }
else if (msgstringshash)
642 sectorNameStrId = msgstringshash->Request(sectorName);
645 Add( (uint32_t) sectorNameStrId );
647 if (sectorNameStrId == csInvalidStringID)
653 void Add(
const iSector* sector);
657 void Add(
const void *datastream,
const uint32_t length)
661 Bug1(
"MsgEntry::Add(const void *datastream,const uint32_t length) bytes=NULL!\n");
671 if (current +
sizeof(uint32_t) + length > bytes->GetSize())
673 Bug5(
"MsgEntry::Add(const void *datastream,const uint32_t length) call for msgid=%u len=%u would overflow buffer of size %zu! type = %u\n",
674 msgid,length, bytes->GetSize(), bytes->type);
683 void *currentloc = (
void *) (bytes->payload+current);
684 memcpy(currentloc, datastream, length);
692 return current >= bytes->GetSize();
698 return current+howMuchMore <= bytes->GetSize();
712 size_t position=current;
713 while (current < bytes->GetSize() && bytes->payload[current]!=0x00)
718 if (current>=bytes->GetSize())
720 Debug3(
LOG_NET,0,
"Message id %u would have read beyond end of buffer %zu.\n",
730 if ( bytes->payload[position] == 0 )
733 return bytes->payload+position;
743 if (current+
sizeof(
float) > bytes->GetSize())
745 Debug2(
LOG_NET,0,
"Message id %u would have read beyond end of buffer.\n",msgid);
750 uint32 *p = (uint32 *)(bytes->payload+current);
751 current +=
sizeof(uint32);
752 return csIEEEfloat::ToNative( csLittleEndian::Convert(*p) );
761 if (current+
sizeof(int16_t) > bytes->GetSize())
763 Debug2(
LOG_NET,0,
"Message id %u would have read beyond end of buffer.\n",msgid);
768 int16_t *p = (int16_t*) (bytes->payload+current);
769 current +=
sizeof(int16_t);
770 return csLittleEndian::Convert(*p);
779 if (current+
sizeof(uint16_t) > bytes->GetSize())
781 Debug2(
LOG_NET,0,
"Message id %u would have read beyond end of buffer.\n",msgid);
786 uint16_t *p = (uint16_t*) (bytes->payload+current);
787 current +=
sizeof(uint16_t);
788 return csLittleEndian::Convert(*p);
798 if (current+
sizeof(int32_t) > bytes->GetSize())
800 Debug2(
LOG_NET,0,
"Message id %u would have read beyond end of buffer.\n",msgid);
805 int32_t *p = (int32_t*) (bytes->payload+current);
806 current +=
sizeof(int32_t);
807 return csLittleEndian::Convert(*p);
817 if (current+
sizeof(uint32_t) > bytes->GetSize())
819 Debug2(
LOG_NET,0,
"Message id %u would have read beyond end of buffer.\n",msgid);
824 uint32_t *p = (uint32_t *)(bytes->payload+current);
825 current +=
sizeof(uint32_t);
826 return csLittleEndian::UInt32(*p);
836 if (current+
sizeof(uintptr_t) > bytes->GetSize())
838 Debug2(
LOG_NET,0,
"Message id %u would have read beyond end of buffer.\n",msgid);
843 uintptr_t *p = (uintptr_t *)(bytes->payload+current);
844 current +=
sizeof(uintptr_t);
855 if (current+
sizeof(int8_t) > bytes->GetSize())
857 Debug2(
LOG_NET,0,
"Message id %u would have read beyond end of buffer.\n",msgid);
862 int8_t *p = (int8_t*) (bytes->payload+current);
863 current +=
sizeof(int8_t);
873 if (current+
sizeof(uint8_t) > bytes->GetSize())
875 Debug2(
LOG_NET,0,
"Message id %u would have read beyond end of buffer.\n",msgid);
880 uint8_t *p = (uint8_t *)(bytes->payload+current);
881 current +=
sizeof(uint8_t);
891 if (current+
sizeof(uint8_t) > bytes->GetSize())
893 Debug2(
LOG_NET,0,
"Message id %u would have read beyond end of buffer.\n",msgid);
898 return (GetUInt8() != 0);
907 if (current+2*
sizeof(uint32) > bytes->GetSize())
909 Debug2(
LOG_NET,0,
"Message id %u would have read beyond end of buffer.\n",msgid);
914 uint32 *p = (uint32 *)(bytes->payload+current);
916 v.x = csIEEEfloat::ToNative( csLittleEndian::Convert(*(p++)) );
917 v.y = csIEEEfloat::ToNative( csLittleEndian::Convert(*(p++)) );
918 current += 2*
sizeof(uint32);
928 if (current+3*
sizeof(uint32) > bytes->GetSize())
930 Debug2(
LOG_NET,0,
"Message id %u would have read beyond end of buffer.\n",msgid);
935 uint32 *p = (uint32 *)(bytes->payload+current);
937 v.x = csIEEEfloat::ToNative( csLittleEndian::Convert(*(p++)) );
938 v.y = csIEEEfloat::ToNative( csLittleEndian::Convert(*(p++)) );
939 v.z = csIEEEfloat::ToNative( csLittleEndian::Convert(*(p++)) );
940 current += 3*
sizeof(uint32);
950 if (current+4*
sizeof(uint32) > bytes->GetSize())
952 Debug2(
LOG_NET,0,
"Message id %u would have read beyond end of buffer.\n",msgid);
957 uint32 *p = (uint32 *)(bytes->payload+current);
959 v.x = csIEEEfloat::ToNative( csLittleEndian::Convert(*(p++)) );
960 v.y = csIEEEfloat::ToNative( csLittleEndian::Convert(*(p++)) );
961 v.z = csIEEEfloat::ToNative( csLittleEndian::Convert(*(p++)) );
962 v.w = csIEEEfloat::ToNative( csLittleEndian::Convert(*(p++)) );
963 current += 4*
sizeof(uint32);
967 iSector*
GetSector(
const csStringSet* msgstrings,
const csStringHashReversible* msgstringshash, iEngine *engine)
970 csStringID sectorNameStrId;
971 sectorNameStrId = GetUInt32();
972 if (sectorNameStrId != csStringID(uint32_t(csInvalidStringID)))
976 sectorName = msgstrings->Request(sectorNameStrId);
978 else if(msgstringshash)
980 sectorName = msgstringshash->Request(sectorNameStrId);
985 sectorName = GetStr();
988 if(!sectorName.IsEmpty())
990 return engine->GetSectors ()->FindByName (sectorName);
997 iSector* GetSector();
1007 if (current+
sizeof(uint32_t) > bytes->GetSize())
1009 Debug2(
LOG_NET,0,
"Message id %u would have read beyond end of buffer.\n",msgid);
1015 length = GetUInt32();
1019 if (current + (length) > bytes->GetSize())
1021 Debug2(
LOG_NET,0,
"Message id %u would have read beyond end of buffer.\n",msgid);
1027 void *datastream = bytes->payload+current;
1043 return priority >> 2;
1056 {
return bytes->GetSize();}
#define Debug2(type, filter_id, a, b)
csSyncRefCount()
Initialize object and set reference to 1.
uint16_t size
the size of the following data
void Add(const void *datastream, const uint32_t length)
Add a processed buffer of some kind; should only be used by files and the like.
void Add(const char *str)
Add a string to the current psMessageBytes buffer.
#define Bug5(a, b, c, d, e)
MsgEntry(const psMessageBytes *msg)
void Add(const float f)
Add a float to the current psMessageBytes buffer.
bool IsEmpty()
Check if we are at the end of the current psMessageBytes buffer.
void SetTotalSize(size_t len)
void AddPointer(const uintptr_t i)
Add a pointer to the current psMessageBytes buffer. Pointers must never be sent over the network! ...
uint32_t msgid
Unique identifier per machine.
The structure of 1 queue entry (pointer to a message)
int16_t GetInt16()
Get a signed 16bit Integer from the current psMessageBytes buffer.
void IncRef()
Increase the number of references to this object.
int32_t GetInt32()
Get a signed 32Bit Integer from the current psMessageBytes buffer.
size_t GetTotalSize() const
#define Bug6(a, b, c, d, e, f)
size_t current
The current position for Pushing and Popping.
uint16_t GetUInt16()
Get a unsigned 16bit Integer from the curren psMessageBytes buffer.
MsgEntry(const MsgEntry *me)
bool GetBool()
Get a bool from the current psMessageBytes buffer.
MsgEntry(size_t datasize=0, uint8_t msgpriority=PRIORITY_HIGH, uint8_t sequence=0)
void Add(const uint16_t s)
Add a double the current psMessageBytes buffer.
int8_t GetInt8()
Get a signed 8bit Integer from the current psMessageBytes buffer.
void SetType(uint8_t type)
void Add(const bool b)
Add bool to current psMessageBytes buffer.
size_t GetSize()
Return the size of the databuffer.
void Add(const int32_t i)
Add unsigned 32Bit Int to current psMessageBytes buffer.
bool overrun
Indicates wether a read or write overrun has occured.
uint32_t clientnum
The Number of the client the Message is from/goes to.
void Add(const csVector3 &v)
Add an x,y,z vector to the buffer.
const char * GetStr()
Get a null-terminated string from the current psMessageBytes buffer.
void Add(const uint32_t i)
Add unsigned 4byte int to current psMessageBytes buffer.
#define CS_ASSERT_MSG(msg, x)
void Add(const uint8_t i)
Add 8bit unsigned int to current psMessageBytes buffer.
uint32_t GetUInt32()
Get an unsigned 4byte int from the current psMessageBytes buffer.
#define Debug3(type, filter_id, a, b, c)
uintptr_t GetPointer()
Get a pointer from the current psMessageBytes buffer. Pointers must never be sent over the network! ...
virtual ~csSyncRefCount()
void Add(const csVector4 &v)
Add an x,y,z,w vector to the buffer.
uint8_t GetUInt8()
Get an unsigned 8Bit Integer from the current psMessageBytes buffer.
const unsigned int MAX_MESSAGE_SIZE
float GetFloat()
Get a float from the current psMessageBytes buffer.
void DecRef()
Decrease the number of references to this object.
bool HasMore(int howMuchMore=1)
Check if we have more data in the current psMessageBytes buffer.
void Add(const int16_t s)
Add signed 16 bit int to current psMessageBytes buffer.
iSector * GetSector(const csStringSet *msgstrings, const csStringHashReversible *msgstringshash, iEngine *engine)
void Add(const int8_t i)
Add 8 bit signed int to buffer.
void Add(const iSector *sector, const csStringSet *msgstrings, const csStringHashReversible *msgstringshash=NULL)
this struct represents the data that is sent out through the network (all additional stuff should go ...
void Add(const csVector2 &v)
Add an x,y vector to the buffer.
uint8_t priority
The priority this message should be handled.
int32 GetRefCount()
Get the reference count (only for debugging).
void * GetBufferPointerUnsafe(uint32_t &length)
psMessageBytes * bytes
The message itself ie one block of memory with the header and data following.