2
0

connectionStringTable.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  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. #ifdef TORQUE_DEBUG_NET
  64. Con::printf("Mapping string: %s to index: %d", mString.getString(), mIndex);
  65. #endif
  66. connection->mapString(mIndex, mString);
  67. }
  68. #ifdef TORQUE_DEBUG_NET
  69. const char *getDebugName()
  70. {
  71. static char buffer[512];
  72. dSprintf(buffer, sizeof(buffer), "%s - \"", getClassName());
  73. expandEscape(buffer + dStrlen(buffer), mString.getString());
  74. dStrcat(buffer, "\"", 512);
  75. return buffer;
  76. }
  77. #endif
  78. DECLARE_CONOBJECT(NetStringEvent);
  79. };
  80. IMPLEMENT_CO_NETEVENT_V1(NetStringEvent);
  81. ConsoleDocClass( NetStringEvent,
  82. "@brief Internal event used for transmitting strings across the server.\n\n"
  83. "For internal use only, not intended for TorqueScript or game development\n\n"
  84. "@internal\n"
  85. );
  86. //--------------------------------------------------------------------
  87. ConnectionStringTable::ConnectionStringTable(NetConnection *parent)
  88. {
  89. mParent = parent;
  90. for(U32 i = 0; i < EntryCount; i++)
  91. {
  92. mEntryTable[i].nextHash = NULL;
  93. mEntryTable[i].nextLink = &mEntryTable[i+1];
  94. mEntryTable[i].prevLink = &mEntryTable[i-1];
  95. mEntryTable[i].index = i;
  96. mHashTable[i] = NULL;
  97. }
  98. mLRUHead.nextLink = &mEntryTable[0];
  99. mEntryTable[0].prevLink = &mLRUHead;
  100. mLRUTail.prevLink = &mEntryTable[EntryCount-1];
  101. mEntryTable[EntryCount-1].nextLink = &mLRUTail;
  102. }
  103. U32 ConnectionStringTable::getNetSendId(NetStringHandle &string)
  104. {
  105. // see if the entry is in the hash table right now
  106. U32 hashIndex = string.getIndex() % EntryCount;
  107. for(Entry *walk = mHashTable[hashIndex]; walk; walk = walk->nextHash)
  108. if(walk->string == string)
  109. return walk->index;
  110. AssertFatal(0, "Net send id is not in the table. Error!");
  111. return 0;
  112. }
  113. U32 ConnectionStringTable::checkString(NetStringHandle &string, bool *isOnOtherSide)
  114. {
  115. // see if the entry is in the hash table right now
  116. U32 hashIndex = string.getIndex() % EntryCount;
  117. for(Entry *walk = mHashTable[hashIndex]; walk; walk = walk->nextHash)
  118. {
  119. if(walk->string == string)
  120. {
  121. pushBack(walk);
  122. if(isOnOtherSide)
  123. *isOnOtherSide = walk->receiveConfirmed;
  124. return walk->index;
  125. }
  126. }
  127. // not in the hash table, means we have to add it
  128. Entry *newEntry;
  129. // pull the new entry from the LRU list.
  130. newEntry = mLRUHead.nextLink;
  131. pushBack(newEntry);
  132. // remove the string from the hash table
  133. Entry **hashWalk;
  134. for (hashWalk = &mHashTable[newEntry->string.getIndex() % EntryCount]; *hashWalk; hashWalk = &((*hashWalk)->nextHash))
  135. {
  136. if(*hashWalk == newEntry)
  137. {
  138. *hashWalk = newEntry->nextHash;
  139. break;
  140. }
  141. }
  142. newEntry->string = string;
  143. newEntry->receiveConfirmed = false;
  144. newEntry->nextHash = mHashTable[hashIndex];
  145. mHashTable[hashIndex] = newEntry;
  146. mParent->postNetEvent(new NetStringEvent(newEntry->index, string));
  147. if(isOnOtherSide)
  148. *isOnOtherSide = false;
  149. return newEntry->index;
  150. }
  151. void ConnectionStringTable::mapString(U32 netId, NetStringHandle &string)
  152. {
  153. // the netId is sent by the other side... throw it in our mapping table:
  154. mRemoteStringTable[netId] = string;
  155. }
  156. void ConnectionStringTable::readDemoStartBlock(BitStream *stream)
  157. {
  158. // ok, reading the demo start block
  159. for(U32 i = 0; i < EntryCount; i++)
  160. {
  161. if(stream->readFlag())
  162. {
  163. char buffer[256];
  164. stream->readString(buffer);
  165. mRemoteStringTable[i] = NetStringHandle(buffer);
  166. }
  167. }
  168. }
  169. void ConnectionStringTable::writeDemoStartBlock(ResizeBitStream *stream)
  170. {
  171. // ok, writing the demo start block
  172. for(U32 i = 0; i < EntryCount; i++)
  173. {
  174. if(stream->writeFlag(mRemoteStringTable[i].isValidString()))
  175. {
  176. stream->writeString(mRemoteStringTable[i].getString());
  177. stream->validate();
  178. }
  179. }
  180. }