connectionStringTable.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "platform/platform.h"
  23. #include "core/dnet.h"
  24. #include "console/simBase.h"
  25. #include "sim/netConnection.h"
  26. #include "core/stream/bitStream.h"
  27. #include "console/consoleTypes.h"
  28. class NetStringEvent : public NetEvent
  29. {
  30. NetStringHandle mString;
  31. U32 mIndex;
  32. public:
  33. typedef NetEvent Parent;
  34. NetStringEvent(U32 index = 0, NetStringHandle string = NetStringHandle())
  35. {
  36. mIndex = index;
  37. mString = string;
  38. }
  39. virtual void pack(NetConnection* /*ps*/, BitStream *bstream)
  40. {
  41. bstream->writeInt(mIndex, ConnectionStringTable::EntryBitSize);
  42. bstream->writeString(mString.getString());
  43. }
  44. virtual void write(NetConnection* /*ps*/, BitStream *bstream)
  45. {
  46. bstream->writeInt(mIndex, ConnectionStringTable::EntryBitSize);
  47. bstream->writeString(mString.getString());
  48. }
  49. virtual void unpack(NetConnection* /*con*/, BitStream *bstream)
  50. {
  51. char buf[256];
  52. mIndex = bstream->readInt(ConnectionStringTable::EntryBitSize);
  53. bstream->readString(buf);
  54. mString = NetStringHandle(buf);
  55. }
  56. virtual void notifyDelivered(NetConnection *ps, bool madeit)
  57. {
  58. if(madeit)
  59. ps->confirmStringReceived(mString, mIndex);
  60. }
  61. virtual void process(NetConnection *connection)
  62. {
  63. Con::printf("Mapping string: %s to index: %d", mString.getString(), mIndex);
  64. connection->mapString(mIndex, mString);
  65. }
  66. #ifdef TORQUE_DEBUG_NET
  67. const char *getDebugName()
  68. {
  69. static char buffer[512];
  70. dSprintf(buffer, sizeof(buffer), "%s - \"", getClassName());
  71. expandEscape(buffer + dStrlen(buffer), mString.getString());
  72. dStrcat(buffer, "\"", 512);
  73. return buffer;
  74. }
  75. #endif
  76. DECLARE_CONOBJECT(NetStringEvent);
  77. };
  78. IMPLEMENT_CO_NETEVENT_V1(NetStringEvent);
  79. ConsoleDocClass( NetStringEvent,
  80. "@brief Internal event used for transmitting strings across the server.\n\n"
  81. "For internal use only, not intended for TorqueScript or game development\n\n"
  82. "@internal\n"
  83. );
  84. //--------------------------------------------------------------------
  85. ConnectionStringTable::ConnectionStringTable(NetConnection *parent)
  86. {
  87. mParent = parent;
  88. for(U32 i = 0; i < EntryCount; i++)
  89. {
  90. mEntryTable[i].nextHash = NULL;
  91. mEntryTable[i].nextLink = &mEntryTable[i+1];
  92. mEntryTable[i].prevLink = &mEntryTable[i-1];
  93. mEntryTable[i].index = i;
  94. mHashTable[i] = NULL;
  95. }
  96. mLRUHead.nextLink = &mEntryTable[0];
  97. mEntryTable[0].prevLink = &mLRUHead;
  98. mLRUTail.prevLink = &mEntryTable[EntryCount-1];
  99. mEntryTable[EntryCount-1].nextLink = &mLRUTail;
  100. }
  101. U32 ConnectionStringTable::getNetSendId(NetStringHandle &string)
  102. {
  103. // see if the entry is in the hash table right now
  104. U32 hashIndex = string.getIndex() % EntryCount;
  105. for(Entry *walk = mHashTable[hashIndex]; walk; walk = walk->nextHash)
  106. if(walk->string == string)
  107. return walk->index;
  108. AssertFatal(0, "Net send id is not in the table. Error!");
  109. return 0;
  110. }
  111. U32 ConnectionStringTable::checkString(NetStringHandle &string, bool *isOnOtherSide)
  112. {
  113. // see if the entry is in the hash table right now
  114. U32 hashIndex = string.getIndex() % EntryCount;
  115. for(Entry *walk = mHashTable[hashIndex]; walk; walk = walk->nextHash)
  116. {
  117. if(walk->string == string)
  118. {
  119. pushBack(walk);
  120. if(isOnOtherSide)
  121. *isOnOtherSide = walk->receiveConfirmed;
  122. return walk->index;
  123. }
  124. }
  125. // not in the hash table, means we have to add it
  126. Entry *newEntry;
  127. // pull the new entry from the LRU list.
  128. newEntry = mLRUHead.nextLink;
  129. pushBack(newEntry);
  130. // remove the string from the hash table
  131. Entry **hashWalk;
  132. for (hashWalk = &mHashTable[newEntry->string.getIndex() % EntryCount]; *hashWalk; hashWalk = &((*hashWalk)->nextHash))
  133. {
  134. if(*hashWalk == newEntry)
  135. {
  136. *hashWalk = newEntry->nextHash;
  137. break;
  138. }
  139. }
  140. newEntry->string = string;
  141. newEntry->receiveConfirmed = false;
  142. newEntry->nextHash = mHashTable[hashIndex];
  143. mHashTable[hashIndex] = newEntry;
  144. mParent->postNetEvent(new NetStringEvent(newEntry->index, string));
  145. if(isOnOtherSide)
  146. *isOnOtherSide = false;
  147. return newEntry->index;
  148. }
  149. void ConnectionStringTable::mapString(U32 netId, NetStringHandle &string)
  150. {
  151. // the netId is sent by the other side... throw it in our mapping table:
  152. mRemoteStringTable[netId] = string;
  153. }
  154. void ConnectionStringTable::readDemoStartBlock(BitStream *stream)
  155. {
  156. // ok, reading the demo start block
  157. for(U32 i = 0; i < EntryCount; i++)
  158. {
  159. if(stream->readFlag())
  160. {
  161. char buffer[256];
  162. stream->readString(buffer);
  163. mRemoteStringTable[i] = NetStringHandle(buffer);
  164. }
  165. }
  166. }
  167. void ConnectionStringTable::writeDemoStartBlock(ResizeBitStream *stream)
  168. {
  169. // ok, writing the demo start block
  170. for(U32 i = 0; i < EntryCount; i++)
  171. {
  172. if(stream->writeFlag(mRemoteStringTable[i].isValidString()))
  173. {
  174. stream->writeString(mRemoteStringTable[i].getString());
  175. stream->validate();
  176. }
  177. }
  178. }