[Opentnl-cvs] tnl/tnl thread.cpp,NONE,1.1 tnlThread.h,NONE,1.1 byteBuffer.cpp,1.2,1.3 eventConnectio
Brought to you by:
mark_frohnmayer,
s_alanet
Update of /cvsroot/opentnl/tnl/tnl In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv11782/tnl Modified Files: byteBuffer.cpp eventConnection.cpp netConnection.cpp netInterface.cpp netStringTable.cpp random.cpp symmetricCipher.cpp tnl.dsp tnl.vcproj tnlByteBuffer.h tnlDataChunker.h tnlEventConnection.h tnlMethodDispatch.cpp tnlMethodDispatch.h tnlNetBase.h tnlNetConnection.h tnlUDP.h tnlVector.h udp.cpp Added Files: thread.cpp tnlThread.h Log Message: Updated TNL with fixes from commercial version of Zap, including: Added thread-related classes - Semaphore, Mutex, ThreadStorage, Thread, ThreadQueue Added Base16 encoding and decoding to the ByteBuffer class Added MD5 hash sum computation to the ByteBuffer class Fixed NetEvent class count bug on EventConnection startup Fixed NetEvent post fail when not connected bug Added a quicker ping/ack on an adaptive connection if it has unacked sent packets Added an isLocal flag to the connection parameters for local connections Added a RefPtr<> to hang onto a connection before dispatching a packet to it in order to prevent a crash when a packet causes a disconnect Fixed net string table bug on lookup where the lookup string is longer than the lookup length Added saved hashes to improve performance of net string table Fixed NULL free list entry string table bug Fixed string not removed from hash table bug Fixed endian bug in symmetric cipher counter initialization Added double precision float capability to RPC calls Fixed vector writing bug in RPC code on PPC Made RPC call marshalling thread safe Added support for TCP socket addresses Added support for TCP streams send and recv Index: random.cpp =================================================================== RCS file: /cvsroot/opentnl/tnl/tnl/random.cpp,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** random.cpp 3 Jun 2004 00:55:20 -0000 1.4 --- random.cpp 14 Feb 2005 06:15:28 -0000 1.5 *************** *** 88,91 **** --- 88,93 ---- U32 readI(U32 rangeStart, U32 rangeEnd) { + TNLAssert(rangeStart <= rangeEnd, "Random::readI - invalid range."); + return (readI() % (rangeEnd - rangeStart + 1)) + rangeStart; } Index: tnl.dsp =================================================================== RCS file: /cvsroot/opentnl/tnl/tnl/tnl.dsp,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** tnl.dsp 27 May 2004 22:41:16 -0000 1.6 --- tnl.dsp 14 Feb 2005 06:15:28 -0000 1.7 *************** *** 271,274 **** --- 271,278 ---- # Begin Source File + SOURCE=.\thread.cpp + # End Source File + # Begin Source File + SOURCE=.\tnl.h # End Source File Index: symmetricCipher.cpp =================================================================== RCS file: /cvsroot/opentnl/tnl/tnl/symmetricCipher.cpp,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** symmetricCipher.cpp 20 Apr 2004 04:27:18 -0000 1.1 --- symmetricCipher.cpp 14 Feb 2005 06:15:28 -0000 1.2 *************** *** 62,69 **** void SymmetricCipher::setupCounter(U32 counterValue1, U32 counterValue2, U32 counterValue3, U32 counterValue4) { ! mCounter[0] = mInitVector[0] + counterValue1; ! mCounter[1] = mInitVector[1] + counterValue2; ! mCounter[2] = mInitVector[2] + counterValue3; ! mCounter[3] = mInitVector[3] + counterValue4; rijndael_ecb_encrypt((U8 *) mCounter, mPad, (symmetric_key *) &mSymmetricKey); --- 62,69 ---- void SymmetricCipher::setupCounter(U32 counterValue1, U32 counterValue2, U32 counterValue3, U32 counterValue4) { ! mCounter[0] = convertHostToLEndian(convertLEndianToHost(mInitVector[0]) + counterValue1); ! mCounter[1] = convertHostToLEndian(convertLEndianToHost(mInitVector[1]) + counterValue2); ! mCounter[2] = convertHostToLEndian(convertLEndianToHost(mInitVector[2]) + counterValue3); ! mCounter[3] = convertHostToLEndian(convertLEndianToHost(mInitVector[3]) + counterValue4); rijndael_ecb_encrypt((U8 *) mCounter, mPad, (symmetric_key *) &mSymmetricKey); Index: udp.cpp =================================================================== RCS file: /cvsroot/opentnl/tnl/tnl/udp.cpp,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** udp.cpp 28 Jul 2004 02:06:14 -0000 1.6 --- udp.cpp 14 Feb 2005 06:15:28 -0000 1.7 *************** *** 158,162 **** static void TNLToSocketAddress(const Address &address, SOCKADDR *sockAddr, socklen_t *addressSize) { ! if(address.transport == IPProtocol) { memset(sockAddr, 0, sizeof(SOCKADDR_IN)); --- 158,162 ---- static void TNLToSocketAddress(const Address &address, SOCKADDR *sockAddr, socklen_t *addressSize) { ! if(address.transport == IPProtocol || address.transport == TCPProtocol) { memset(sockAddr, 0, sizeof(SOCKADDR_IN)); *************** *** 215,227 **** mTransportProtocol = bindAddress.transport; if(bindAddress.transport == IPProtocol) mPlatformSocket = socket(AF_INET, SOCK_DGRAM, 0); #if !defined(NO_IPX_SUPPORT) else if(bindAddress.transport == IPXProtocol) mPlatformSocket = socket(AF_IPX, SOCK_DGRAM, NSPROTO_IPX); #endif else { ! logprintf("Attempted to create a socket bound to an invalid transport."); } if(mPlatformSocket != INVALID_SOCKET) --- 215,237 ---- mTransportProtocol = bindAddress.transport; + const char *socketType = "UDP"; + if(bindAddress.transport == IPProtocol) mPlatformSocket = socket(AF_INET, SOCK_DGRAM, 0); + else if(bindAddress.transport == TCPProtocol) + { + socketType = "TCP"; + mPlatformSocket = socket(AF_INET, SOCK_STREAM, 0); + } #if !defined(NO_IPX_SUPPORT) else if(bindAddress.transport == IPXProtocol) + { + socketType = "IPX"; mPlatformSocket = socket(AF_IPX, SOCK_DGRAM, NSPROTO_IPX); + } #endif else { ! TNLLogMessageV(LogUDP, ("Attempted to create a socket bound to an invalid transport.")); } if(mPlatformSocket != INVALID_SOCKET) *************** *** 240,244 **** SocketToTNLAddress(&address, &boundAddress); ! logprintf("Socket created - bound to address: %s", boundAddress.toString()); // set the send and receive buffer sizes --- 250,254 ---- SocketToTNLAddress(&address, &boundAddress); ! TNLLogMessageV(LogUDP, ("%s socket created - bound to address: %s", socketType, boundAddress.toString())); // set the send and receive buffer sizes *************** *** 246,265 **** if(!error) { ! logprintf("UDP receive buffer size set to %d.", recvBufferSize); error = setsockopt(mPlatformSocket, SOL_SOCKET, SO_SNDBUF, (char *) &sendBufferSize, sizeof(sendBufferSize)); } else ! logprintf("Error: unable to set the receive buffer size on UDP socket."); if(!error) { ! logprintf("UDP send buffer size set to %d.", recvBufferSize); ! // set the broadcast allowed flag ! S32 bc = acceptsBroadcast; ! error = setsockopt(mPlatformSocket, SOL_SOCKET, SO_BROADCAST, (char*)&bc, sizeof(bc)); } else ! logprintf("Error: unable to set the send buffer size on UDP socket."); --- 256,278 ---- if(!error) { ! TNLLogMessageV(LogUDP, ("%s socket receive buffer size set to %d.", socketType, recvBufferSize)); error = setsockopt(mPlatformSocket, SOL_SOCKET, SO_SNDBUF, (char *) &sendBufferSize, sizeof(sendBufferSize)); } else ! TNLLogMessageV(LogUDP, ("%s socket error: unable to set the receive buffer size on socket.", socketType)); if(!error) { ! TNLLogMessageV(LogUDP, ("%s socket send buffer size set to %d.", socketType, recvBufferSize)); ! if(mTransportProtocol != TCPProtocol) ! { ! // set the broadcast allowed flag ! S32 bc = acceptsBroadcast; ! error = setsockopt(mPlatformSocket, SOL_SOCKET, SO_BROADCAST, (char*)&bc, sizeof(bc)); ! } } else ! TNLLogMessageV(LogUDP, ("%s socket error: unable to set the send buffer size on socket.", socketType)); *************** *** 276,286 **** } else ! logprintf("Error: unable to set broadcast mode on UDP socket."); if(!error) ! logprintf("UDP socket non-blocking IO set. UDP socket initialized."); else { ! logprintf("Error prevented successful initialization of UDP."); closesocket(mPlatformSocket); mPlatformSocket = INVALID_SOCKET; --- 289,303 ---- } else ! { ! TNLLogMessageV(LogUDP, ("%s socket error: unable to set broadcast mode on socket.", socketType)); ! } if(!error) ! { ! TNLLogMessageV(LogUDP, ("%s socket non-blocking IO set. Socket initialized.", socketType)); ! } else { ! TNLLogMessageV(LogUDP, ("Error prevented successful initialization of %s socket.", socketType)); closesocket(mPlatformSocket); mPlatformSocket = INVALID_SOCKET; *************** *** 378,381 **** --- 395,424 ---- } + NetError Socket::connect(const Address &theAddress) + { + SOCKADDR destAddress; + socklen_t addressSize; + + TNLToSocketAddress(theAddress, &destAddress, &addressSize); + if(::connect(mPlatformSocket, &destAddress, addressSize) == -1) + return getLastError(); + return NoError; + } + + NetError Socket::send(const U8 *buffer, S32 bufferSize) + { + if(::send(mPlatformSocket, (const char *) buffer, bufferSize, 0) == SOCKET_ERROR) + return getLastError(); + return NoError; + } + + NetError Socket::recv(U8 *buffer, S32 bufferSize, S32 *bytesRead) + { + *bytesRead = ::recv(mPlatformSocket, (char *) buffer, bufferSize, 0); + if(*bytesRead == -1) + return getLastError(); + return NoError; + } + Address Socket::getBoundAddress() { *************** *** 395,401 **** } void Socket::getInterfaceAddresses(Vector<Address> *addressVector) { - #if defined ( TNL_OS_WIN32 ) typedef struct { DWORD dwAddr; --- 438,444 ---- } + #if defined ( TNL_OS_WIN32 ) void Socket::getInterfaceAddresses(Vector<Address> *addressVector) { typedef struct { DWORD dwAddr; *************** *** 457,463 **** } free(pIPAddrTable); - #endif } bool Address::operator ==(const Address &theAddress) const --- 500,582 ---- } free(pIPAddrTable); } + #elif defined (TNL_OS_MAC_OSX) + #include <ifaddrs.h> + + void Socket::getInterfaceAddresses(Vector<Address> *addressVector) + { + struct ifaddrs *addrs; + getifaddrs(&addrs); + + for(struct ifaddrs *walk = addrs; walk; walk = walk->ifa_next) + { + Address theAddress; + SocketToTNLAddress(walk->ifa_addr, &theAddress); + if(theAddress.netNum[0] != INADDR_ANY && theAddress.netNum[0] != 0x7F000001) + { + //logprintf("found IF address %s", theAddress.toString()); + addressVector->push_back(theAddress); + } + } + + freeifaddrs(addrs); + } + + #elif defined (TNL_OS_LINUX) + #include <stdio.h> + #include <sys/ioctl.h> + #include <arpa/inet.h> + #include <netinet/in.h> + #include <netdb.h> + #include <net/if.h> + + void Socket::getInterfaceAddresses(Vector<Address> *addressVector) + { + int sfd = socket(AF_INET, SOCK_STREAM, 0); + if(sfd < 0) + return; + + FILE *f = fopen("/proc/net/dev", "r"); + if(!f) + { + close(sfd); + return; + } + char buf[1024]; + fgets(buf, 1024, f); + fgets(buf, 1024, f); + + struct ifreq ifr; + struct sockaddr_in *sin = (struct sockaddr_in *) &ifr.ifr_addr; + memset(&ifr, 0, sizeof(ifr)); + + + while(fgets(buf, 1024, f)) + { + char *s = buf; + while(*s == ' ') + s++; + char *end = strchr(s, ':'); + if(!end) + continue; + *end = 0; + + strcpy(ifr.ifr_name, s); + sin->sin_family = AF_INET; + if(ioctl(sfd, SIOCGIFADDR, &ifr) == 0) + { + Address theAddress; + SocketToTNLAddress((struct sockaddr *) sin, &theAddress); + if(theAddress.netNum[0] != INADDR_ANY && theAddress.netNum[0] != 0x7F000001) + { + addressVector->push_back(theAddress); + } + } + } + fclose(f); + close(sfd); + } + #endif bool Address::operator ==(const Address &theAddress) const *************** *** 522,528 **** --- 641,653 ---- if(strnicmp(addressString, "ipx:", 4)) { + bool isTCP = false; // assume IP if it doesn't have ipx: at the front. if(!strnicmp(addressString, "ip:", 3)) addressString += 3; // eat off the ip: + else if(!strnicmp(addressString, "tcp:", 4)) + { + addressString += 4; + isTCP = true; + } SOCKADDR_IN ipAddr; *************** *** 565,568 **** --- 690,695 ---- ipAddr.sin_family = AF_INET; SocketToTNLAddress((SOCKADDR *) &ipAddr, this); + if(isTCP) + transport = TCPProtocol; return true; } Index: tnlByteBuffer.h =================================================================== RCS file: /cvsroot/opentnl/tnl/tnl/tnlByteBuffer.h,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** tnlByteBuffer.h 6 May 2004 00:33:38 -0000 1.3 --- tnlByteBuffer.h 14 Feb 2005 06:15:28 -0000 1.4 *************** *** 127,130 **** --- 127,148 ---- } + /// Appends the specified buffer to the end of the byte buffer. + /// returns false if it does not own its own memory. + bool appendBuffer(const U8 *dataBuffer, U32 bufferSize) + { + U32 start = mBufSize; + if(!resize(mBufSize + bufferSize)) + return false; + memcpy(mDataPtr + start, dataBuffer, bufferSize); + return true; + } + + /// Appends the specified ByteBuffer to the end of this byte buffer. + /// returns fals if it does not own its own memory. + bool appendBuffer(const ByteBuffer &theBuffer) + { + return appendBuffer(theBuffer.getBuffer(), theBuffer.getBufferSize()); + } + /// Copies the current buffer into a newly allocated buffer that the ByteBuffer owns. void takeOwnership() *************** *** 166,174 **** } ! /// Encode the buffer to base 64, in place. Resizes the buffer.. RefPtr<ByteBuffer> encodeBase64() const; ! /// Decode the buffer from base 64, in place. Resizes the buffer. RefPtr<ByteBuffer> decodeBase64() const; /// Returns a 32 bit CRC for the buffer. U32 calculateCRC(U32 start = 0, U32 end = 0xFFFFFFFF, U32 crcVal = 0xFFFFFFFF) const; --- 184,200 ---- } ! /// Encode the buffer to base 64, returning the encoded buffer. RefPtr<ByteBuffer> encodeBase64() const; ! /// Decode the buffer from base 64, returning the decoded buffer. RefPtr<ByteBuffer> decodeBase64() const; + /// Computes an MD5 hash and returns it in a ByteBuffer + RefPtr<ByteBuffer> computeMD5Hash(U32 len = 0) const; + + /// Converts to ascii-hex, returning the encoded buffer. + RefPtr<ByteBuffer> encodeBase16() const; + /// Decodes the buffer from base 16, returning the decoded buffer. + RefPtr<ByteBuffer> decodeBase16() const; + /// Returns a 32 bit CRC for the buffer. U32 calculateCRC(U32 start = 0, U32 end = 0xFFFFFFFF, U32 crcVal = 0xFFFFFFFF) const; Index: tnlMethodDispatch.cpp =================================================================== RCS file: /cvsroot/opentnl/tnl/tnl/tnlMethodDispatch.cpp,v retrieving revision 1.16 retrieving revision 1.17 diff -C2 -d -r1.16 -r1.17 *** tnlMethodDispatch.cpp 28 Sep 2004 18:45:25 -0000 1.16 --- tnlMethodDispatch.cpp 14 Feb 2005 06:15:28 -0000 1.17 *************** *** 27,37 **** #include "tnlMethodDispatch.h" #include "tnlNetStringTable.h" ! ! void *TNL_gBasePtr = NULL; ! namespace TNL { - void *gThisPtr = NULL; - void *gStackPtr = NULL; struct TypeInfo --- 27,33 ---- #include "tnlMethodDispatch.h" #include "tnlNetStringTable.h" ! #include "tnlThread.h" namespace TNL { struct TypeInfo *************** *** 51,54 **** --- 47,51 ---- TypeU32, TypeF32, + TypeF64, TypeSignedInt, TypeInt, *************** *** 75,78 **** --- 72,76 ---- { "U32", sizeof(U32), true, true }, { "F32", sizeof(F32), true, true }, + { "F64", sizeof(F64), false, true }, { "SignedInt<", sizeof(SignedInt<32>), true, true }, { "Int<", sizeof(Int<32>), true, true }, *************** *** 193,197 **** info.bitCount = getValue(walk); } ! if(type == TypeF32 || type == TypeFloat || type == TypeSignedFloat) { if(numFloats < 13) --- 191,195 ---- info.bitCount = getValue(walk); } ! if(!info.isVector && (type == TypeF32 || type == TypeFloat || type == TypeSignedFloat)) { if(numFloats < 13) *************** *** 218,238 **** } ! #ifdef TNL_CPU_PPC ! U32 gRegisterSaves[8 + 13 + 1]; ! #endif void MethodArgList::marshall(MarshalledCall *theEvent) { PacketStream bstream; #if defined (TNL_CPU_PPC) ! U32 *intArg = gRegisterSaves; ! F32 *floatArg = (F32 *) (&gRegisterSaves[8]); ! void *stackPtr = (void *) gRegisterSaves[8 + 13]; stackPtr = (void *) (*((U8 **) stackPtr) + 24); // advance past linkage area of stack intArg++; // get rid of the "this" pointer. bool floatInRegs = true; #else ! U8 *ptr = (U8 *) TNL_gBasePtr; ptr += 4; // get rid of the return address and saved base ptr. #endif --- 216,246 ---- } ! ThreadStorage gRPCThreadStorage; ! ! RPCThreadStorage &getRPCThreadStorage() ! { ! RPCThreadStorage *val = (RPCThreadStorage *) gRPCThreadStorage.get(); ! if(!val) ! { ! val = new RPCThreadStorage; ! gRPCThreadStorage.set(val); ! } ! return *val; ! } void MethodArgList::marshall(MarshalledCall *theEvent) { PacketStream bstream; + RPCThreadStorage &sto = getRPCThreadStorage(); #if defined (TNL_CPU_PPC) ! U32 *intArg = sto.registerSaves; ! F32 *floatArg = (F32 *) (&sto.registerSaves[8]); ! void *stackPtr = (void *) sto.registerSaves[8 + 13]; stackPtr = (void *) (*((U8 **) stackPtr) + 24); // advance past linkage area of stack intArg++; // get rid of the "this" pointer. bool floatInRegs = true; #else ! U8 *ptr = (U8 *) sto.basePtr; ptr += 4; // get rid of the return address and saved base ptr. #endif *************** *** 315,318 **** --- 323,329 ---- floatArg++; break; + case TypeF64: + bstream.write(*((F64 *) intArg)); + break; case TypeSignedInt: bstream.writeSignedInt(((SignedInt<32> *) intArg)->value, argList[i].bitCount); *************** *** 392,414 **** } ! static U8 rpcReadData[MethodArgList::MaxRPCDataSize]; ! static U32 rpcReadOffsets[MethodArgList::MaxOffsets]; ! static U8 *rpcSTEOffsets[MethodArgList::MaxOffsets]; ! static U32 rpcSTEIndex[MethodArgList::MaxOffsets]; ! static U32 rpcNumSTEs; ! static U32 rpcNumOffsets; ! ! inline U8 *allocSpace(U8 **offsetDest, U32 ¤tSize, U32 requestSize) { ! if(rpcNumOffsets >= MethodArgList::MaxOffsets) return NULL; currentSize = fourByteAlign(currentSize); ! rpcReadOffsets[rpcNumOffsets++] = ((U8 *) offsetDest) - rpcReadData; if(requestSize + currentSize > MethodArgList::MaxRPCDataSize) return NULL; ! U8 *ret = rpcReadData + currentSize; *offsetDest = ret; --- 403,418 ---- } ! inline U8 *allocSpace(U8 **offsetDest, U32 ¤tSize, U32 requestSize, RPCThreadStorage &sto) { ! if(sto.rpcNumOffsets >= MethodArgList::MaxOffsets) return NULL; currentSize = fourByteAlign(currentSize); ! sto.rpcReadOffsets[sto.rpcNumOffsets++] = ((U8 *) offsetDest) - sto.rpcReadData; if(requestSize + currentSize > MethodArgList::MaxRPCDataSize) return NULL; ! U8 *ret = sto.rpcReadData + currentSize; *offsetDest = ret; *************** *** 419,424 **** bool MethodArgList::unmarshall(BitStream *bstream, MarshalledCall *theEvent) { ! rpcNumOffsets = 0; ! rpcNumSTEs = 0; U32 rpcCurrentSTEIndex = 0; --- 423,429 ---- bool MethodArgList::unmarshall(BitStream *bstream, MarshalledCall *theEvent) { ! RPCThreadStorage &sto = getRPCThreadStorage(); ! sto.rpcNumOffsets = 0; ! sto.rpcNumSTEs = 0; U32 rpcCurrentSTEIndex = 0; *************** *** 428,432 **** #endif U32 whichSTE = 0; ! U8 *argPtr= rpcReadData; for(S32 i = 0; i < argList.size(); i++) { --- 433,437 ---- #endif U32 whichSTE = 0; ! U8 *argPtr= sto.rpcReadData; for(S32 i = 0; i < argList.size(); i++) { *************** *** 435,439 **** if(argList[i].isVector) { ! VectorRep *vector = (VectorRep *) allocSpace((U8 **) arg, currentSize, sizeof(VectorRep)); if(!vector) goto errorOut; --- 440,444 ---- if(argList[i].isVector) { ! VectorRep *vector = (VectorRep *) allocSpace((U8 **) arg, currentSize, sizeof(VectorRep), sto); if(!vector) goto errorOut; *************** *** 444,450 **** if(argList[i].argType == TypeStringTableEntry) { ! rpcSTEIndex[rpcNumSTEs] = rpcCurrentSTEIndex; ! rpcSTEOffsets[rpcNumSTEs] = (U8 *) &vector->array; ! rpcNumSTEs++; rpcCurrentSTEIndex += vector->elementCount; argPtr += sizeof(U32); --- 449,455 ---- if(argList[i].argType == TypeStringTableEntry) { ! sto.rpcSTEIndex[sto.rpcNumSTEs] = rpcCurrentSTEIndex; ! sto.rpcSTEOffsets[sto.rpcNumSTEs] = (U8 *) &vector->array; ! sto.rpcNumSTEs++; rpcCurrentSTEIndex += vector->elementCount; argPtr += sizeof(U32); *************** *** 453,457 **** else { ! vector->array = allocSpace(&vector->array, currentSize, vector->elementCount * gTypes[argList[i].argType].size); if(!vector->array) goto errorOut; --- 458,462 ---- else { ! vector->array = allocSpace(&vector->array, currentSize, vector->elementCount * gTypes[argList[i].argType].size, sto); if(!vector->array) goto errorOut; *************** *** 514,517 **** --- 519,525 ---- bstream->read((F32 *) arg); break; + case TypeF64: + bstream->read((F64 *) arg); + break; case TypeSignedInt: ((SignedInt<32> *) arg)->value = bstream->readSignedInt(argList[i].bitCount); *************** *** 529,533 **** { char **stringPtr = (char **) arg; ! *stringPtr = (char *) allocSpace((U8 **) arg, currentSize, 256); if(!*stringPtr) goto errorOut; --- 537,541 ---- { char **stringPtr = (char **) arg; ! *stringPtr = (char *) allocSpace((U8 **) arg, currentSize, 256, sto); if(!*stringPtr) goto errorOut; *************** *** 538,546 **** break; case TypeStringTableEntryRef: ! if(rpcNumSTEs >= MethodArgList::MaxOffsets) goto errorOut; ! rpcSTEIndex[rpcNumSTEs] = rpcCurrentSTEIndex; ! rpcSTEOffsets[rpcNumSTEs] = arg; ! rpcNumSTEs++; rpcCurrentSTEIndex++; break; --- 546,554 ---- break; case TypeStringTableEntryRef: ! if(sto.rpcNumSTEs >= MethodArgList::MaxOffsets) goto errorOut; ! sto.rpcSTEIndex[sto.rpcNumSTEs] = rpcCurrentSTEIndex; ! sto.rpcSTEOffsets[sto.rpcNumSTEs] = arg; ! sto.rpcNumSTEs++; rpcCurrentSTEIndex++; break; *************** *** 553,562 **** case TypeByteBufferPtr: { ! ByteBuffer *buffer = (ByteBuffer *) allocSpace((U8 **) arg, currentSize, sizeof(ByteBuffer)); if(!buffer) goto errorOut; buffer->mOwnsMemory = false; buffer->mBufSize = bstream->readInt(ByteBufferSizeBitSize); ! buffer->mDataPtr = (U8 *) allocSpace(&buffer->mDataPtr, currentSize, buffer->mBufSize); if(!buffer->mDataPtr) goto errorOut; --- 561,570 ---- case TypeByteBufferPtr: { ! ByteBuffer *buffer = (ByteBuffer *) allocSpace((U8 **) arg, currentSize, sizeof(ByteBuffer), sto); if(!buffer) goto errorOut; buffer->mOwnsMemory = false; buffer->mBufSize = bstream->readInt(ByteBufferSizeBitSize); ! buffer->mDataPtr = (U8 *) allocSpace(&buffer->mDataPtr, currentSize, buffer->mBufSize, sto); if(!buffer->mDataPtr) goto errorOut; *************** *** 567,571 **** case TypeIPAddressRef: { ! IPAddress *ip = (IPAddress *) allocSpace((U8 **) arg, currentSize, sizeof(IPAddress)); if(!ip) goto errorOut; --- 575,579 ---- case TypeIPAddressRef: { ! IPAddress *ip = (IPAddress *) allocSpace((U8 **) arg, currentSize, sizeof(IPAddress), sto); if(!ip) goto errorOut; *************** *** 588,595 **** } theEvent->mSTEs.setSize(rpcCurrentSTEIndex); ! for(U32 i = 0; i < rpcNumSTEs; i++) ! *((StringTableEntry **) rpcSTEOffsets[i]) = &theEvent->mSTEs[rpcSTEIndex[i]]; ! theEvent->unmarshalledData.setBuffer(rpcReadData, currentSize, false); theEvent->unmarshalledData.takeOwnership(); --- 596,603 ---- } theEvent->mSTEs.setSize(rpcCurrentSTEIndex); ! for(U32 i = 0; i < sto.rpcNumSTEs; i++) ! *((StringTableEntry **) sto.rpcSTEOffsets[i]) = &theEvent->mSTEs[sto.rpcSTEIndex[i]]; ! theEvent->unmarshalledData.setBuffer(sto.rpcReadData, currentSize, false); theEvent->unmarshalledData.takeOwnership(); *************** *** 597,605 **** U8 *data; data = theEvent->unmarshalledData.getBuffer(); ! delta = data - rpcReadData; ! for(U32 i = 0; i < rpcNumOffsets; i++) { ! *((U8 **) (data + rpcReadOffsets[i])) += delta; } return true; --- 605,613 ---- U8 *data; data = theEvent->unmarshalledData.getBuffer(); ! delta = data - sto.rpcReadData; ! for(U32 i = 0; i < sto.rpcNumOffsets; i++) { ! *((U8 **) (data + sto.rpcReadOffsets[i])) += delta; } return true; Index: tnlUDP.h =================================================================== RCS file: /cvsroot/opentnl/tnl/tnl/tnlUDP.h,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** tnlUDP.h 20 Apr 2004 04:27:19 -0000 1.1 --- tnlUDP.h 14 Feb 2005 06:15:28 -0000 1.2 *************** *** 52,55 **** --- 52,56 ---- { IPProtocol, ///< The standard Internet routing protocol + TCPProtocol, ///< The standard Internet guaranteed delivery protocol IPXProtocol, ///< Novell's IPX protocol IPv6Protocol, ///< The next generation 128-bit address internet protocol (not currently supported by TNL) *************** *** 184,187 **** --- 185,192 ---- /// returns IP addresses, with the port field set to 0. static void getInterfaceAddresses(Vector<Address> *addressVector); + + NetError connect(const Address &theAddress); + NetError recv(U8 *buffer, S32 bufferSize, S32 *bytesRead); + NetError send(const U8 *buffer, S32 bufferSize); }; Index: tnlDataChunker.h =================================================================== RCS file: /cvsroot/opentnl/tnl/tnl/tnlDataChunker.h,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** tnlDataChunker.h 27 Apr 2004 23:26:15 -0000 1.2 --- tnlDataChunker.h 14 Feb 2005 06:15:28 -0000 1.3 *************** *** 125,128 **** --- 125,133 ---- freeListHead = elem; } + + void freeBlocks() + { + DataChunker::freeBlocks(); + } }; Index: netStringTable.cpp =================================================================== RCS file: /cvsroot/opentnl/tnl/tnl/netStringTable.cpp,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** netStringTable.cpp 19 May 2004 20:47:46 -0000 1.2 --- netStringTable.cpp 14 Feb 2005 06:15:28 -0000 1.3 *************** *** 45,48 **** --- 45,49 ---- StringTableEntryId masterIndex; ///< index of the Node pointer in the master list StringTableEntryId nextIndex; ///< next string in this hash bucket. + U32 hash; ///< stored hash value of this string. U16 stringLen; ///< length of string in this node. U16 refCount; ///< number of StringTableEntry's that reference this node *************** *** 154,158 **** for(U32 i = 1; i < InitialNodeListSize; i++) mNodeList[i] = (Node *) (( (i + 1) << 1) | 1); // see the doco in stringTable.h for how free list entries are coded ! mNodeList[InitialNodeListSize - 1] = 0; mNodeList[0] = (Node *) mMemPool->alloc(sizeof(Node)); mNodeList[0]->stringData[0] = 0; --- 155,160 ---- for(U32 i = 1; i < InitialNodeListSize; i++) mNodeList[i] = (Node *) (( (i + 1) << 1) | 1); // see the doco in stringTable.h for how free list entries are coded ! ! mNodeList[InitialNodeListSize - 1] = NULL; mNodeList[0] = (Node *) mMemPool->alloc(sizeof(Node)); mNodeList[0]->stringData[0] = 0; *************** *** 268,271 **** --- 270,274 ---- stringNode->masterIndex = mNodeListFreeEntry >> 1; // shift off the low bit flag for the free list stringNode->nextIndex = 0; + stringNode->hash = key; *walk = stringNode->masterIndex; *************** *** 309,313 **** StringTableEntryId *walk; Node *stringNode; ! U32 key = hashString(val); walk = &mBuckets[key % mNumBuckets]; while(*walk) --- 312,316 ---- StringTableEntryId *walk; Node *stringNode; ! U32 key = hashStringn(val, len); walk = &mBuckets[key % mNumBuckets]; while(*walk) *************** *** 357,361 **** walk = temp->nextIndex; ! key = hashString(temp->stringData); temp->nextIndex = mBuckets[key % newSize]; mBuckets[key % newSize] = temp->masterIndex; --- 360,364 ---- walk = temp->nextIndex; ! key = temp->hash; temp->nextIndex = mBuckets[key % newSize]; mBuckets[key % newSize] = temp->masterIndex; *************** *** 372,376 **** // if the low bit is set, it's an entry in the free list. ! if(((StringTableEntryId) theNode) & 1) continue; newNode = (Node *) newData->alloc(sizeof(Node) + theNode->stringLen); --- 375,381 ---- // if the low bit is set, it's an entry in the free list. ! // if it is NULL it is the last entry (see the constructor) ! // this *may* not be the best fix, but it was a crash -pw ! if(((StringTableEntryId) theNode) & 1 || theNode == NULL) continue; newNode = (Node *) newData->alloc(sizeof(Node) + theNode->stringLen); *************** *** 379,382 **** --- 384,388 ---- newNode->masterIndex = theNode->masterIndex; newNode->nextIndex = theNode->nextIndex; + newNode->hash = theNode->hash; strcpy(newNode->stringData, theNode->stringData); mNodeList[i] = newNode; *************** *** 394,399 **** void decRef(StringTableEntryId index) { ! if(--mNodeList[index]->refCount) return; mFreeStringDataSize += mNodeList[index]->stringLen + sizeof(Node); mNodeList[index] = (Node *) mNodeListFreeEntry; --- 400,421 ---- void decRef(StringTableEntryId index) { ! Node *theNode = mNodeList[index]; ! if(--theNode->refCount) return; + + // remove from the hash table first: + StringTableEntryId *walk = &mBuckets[theNode->hash % mNumBuckets]; + Node *stringNode; + while(*walk) + { + stringNode = mNodeList[*walk]; + if(stringNode == theNode) + { + *walk = theNode->nextIndex; + break; + } + walk = &(stringNode->nextIndex); + } + mFreeStringDataSize += mNodeList[index]->stringLen + sizeof(Node); mNodeList[index] = (Node *) mNodeListFreeEntry; Index: tnlNetBase.h =================================================================== RCS file: /cvsroot/opentnl/tnl/tnl/tnlNetBase.h,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** tnlNetBase.h 4 Aug 2004 18:25:27 -0000 1.4 --- tnlNetBase.h 14 Feb 2005 06:15:28 -0000 1.5 *************** *** 655,656 **** --- 655,657 ---- }; #endif + --- NEW FILE: tnlThread.h --- //----------------------------------------------------------------------------------- // // Torque Network Library // Copyright (C) 2004 GarageGames.com, Inc. // For more information see http://www.opentnl.org // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // For use in products that are not compatible with the terms of the GNU // General Public License, alternative licensing options are available // from GarageGames.com. // // 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 General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // //------------------------------------------------------------------------------------ #ifndef _TNLTHREAD_H_ #define _TNLTHREAD_H_ #include "tnl.h" #include "tnlNetBase.h" #include "tnlMethodDispatch.h" #if defined (TNL_OS_WIN32) #include <windows.h> #else #include <pthread.h> #include <semaphore.h> #endif namespace TNL { /// Platform independent semaphore class. /// /// The semaphore class wraps OS specific semaphore functionality for thread synchronization. class Semaphore { #ifdef TNL_OS_WIN32 HANDLE mSemaphore; #else sem_t mSemaphore; #endif public: /// Semaphore constructor - initialCount specifies how many wait calls /// will be let through before an increment is required. Semaphore(U32 initialCount = 0, U32 maximumCount = 1024); ~Semaphore(); /// Thread calling wait will block as long as the semaphore's count /// is zero. If the semaphore is incremented, one of the waiting threads /// will be awakened and the semaphore will decrement. void wait(); /// Increments the semaphore's internal count. This will wake /// count threads that are waiting on this semaphore. void increment(U32 count = 1); }; /// Platform independent Mutual Exclusion implementation class Mutex { #ifdef TNL_OS_WIN32 CRITICAL_SECTION mLock; #else pthread_mutex_t mMutex; #endif public: /// Mutex constructor Mutex(); /// Mutex destructor ~Mutex(); /// Locks the Mutex. If another thread already has this Mutex /// locked, this call will block until it is unlocked. If the lock /// method is called from a thread that has already locked this Mutex, /// the call will not block and the thread will have to unlock /// the mutex for as many calls as were made to lock before another /// thread will be allowed to lock the Mutex. void lock(); /// Unlocks the Mutex. The behavior of this method is undefined if called /// by a thread that has not previously locked this Mutex. void unlock(); /// Attempts to acquire a lock to this Mutex, without blocking. /// Returns true if the calling thread was able to lock the Mutex and /// false if the Mutex was already locked by another thread. bool tryLock(); }; /// Platform independent Thread class. class Thread : public Object { protected: U32 mReturnValue; ///< Return value from thread function #ifdef TNL_OS_WIN32 HANDLE mThread; #else pthread_t mThread; #endif public: /// run function called when thread is started. virtual U32 run() = 0; /// Thread constructor. Thread(); /// Thread destructor. ~Thread(); /// starts the thread's main run function. void start(); }; /// Platform independent per-thread storage class. class ThreadStorage { #ifdef TNL_OS_WIN32 DWORD mTlsIndex; #else pthread_key_t mThreadKey; #endif public: /// ThreadStorage constructor. ThreadStorage(); /// ThreadStorage destructor. ~ThreadStorage(); /// returns the per-thread stored void pointer for this ThreadStorage. The default value is NULL. void *get(); /// sets the per-thread stored void pointer for this ThreadStorage object. void set(void *data); }; /// Structure representing a stored call to a ThreadQueue function struct ThreadQueueCall { MarshalledCall *c; MethodPointer p; }; /// Managing object for a queue of worker threads that pass /// messages back and forth to the main thread. ThreadQueue /// methods declared with the TNL_DECLARE_THREADQ_METHOD macro /// are special -- if they are called from the main thread, /// they will be executed on one of the worker threads and vice /// versa. class ThreadQueue : public Object { class ThreadQueueThread : public Thread { ThreadQueue *mThreadQueue; public: ThreadQueueThread(ThreadQueue *); U32 run(); }; friend class ThreadQueueThread; /// list of worker threads on this ThreadQueue Vector<Thread *> mThreads; /// list of calls to be processed by the worker threads Vector<ThreadQueueCall> mThreadCalls; /// list of calls to be processed by the main thread Vector<ThreadQueueCall> mResponseCalls; /// Synchronization variable that manages worker threads Semaphore mSemaphore; /// Internal Mutex for synchronizing access to thread call vectors. Mutex mLock; /// Storage variable that tracks whether this is the main thread or a worker thread. ThreadStorage mStorage; protected: /// Locks the ThreadQueue for access to member variables. void lock() { mLock.lock(); } /// Unlocks the ThreadQueue. void unlock() { mLock.unlock(); } /// Posts a marshalled call onto either the worker thread call list or the response call list. void postCall(ThreadQueueCall &theCall); /// Dispatches the next available worker thread call. Called internally by the worker threads when they awaken from the semaphore. void dispatchNextCall(); /// helper function to determine if the currently executing thread is a worker thread or the main thread. bool isMainThread() { return (bool) mStorage.get(); } ThreadStorage &getStorage() { return mStorage; } /// called by each worker thread when it starts for subclass initialization of worker threads. virtual void threadStart() { } public: /// ThreadQueue constructor. threadCount specifies the number of worker threads that will be created. ThreadQueue(U32 threadCount); ~ThreadQueue(); /// Dispatches all ThreadQueue calls queued by worker threads. This should /// be called periodically from a main loop. void dispatchResponseCalls(); }; /// Declares a ThreadQueue method on a subclass of ThreadQueue. #define TNL_DECLARE_THREADQ_METHOD(func, args) \ virtual void FN_CDECL func args; \ virtual void FN_CDECL func##_body args /// Declares the implementation of a ThreadQueue method. #define TNL_IMPLEMENT_THREADQ_METHOD(className, func, args) \ TNL::MethodArgList ThreadQ_##className##_##func(#className, #args); \ void FN_CDECL className::func args { \ SAVE_PARAMS \ ThreadQueueCall theCall; \ theCall.c = new MarshalledCall(&ThreadQ_##className##_##func); \ theCall.c->marshall(); \ void (FN_CDECL className::*fptr) args; \ fptr = &className::func##_body; \ theCall.p.v1 = *((U32 *) &fptr); \ if(sizeof(fptr) > sizeof(U32)) theCall.p.v2 = *(((U32 *) &fptr) + 1); \ if(sizeof(fptr) > 2*sizeof(U32)) theCall.p.v3 = *(((U32 *) &fptr) + 2); \ postCall(theCall); \ }\ void FN_CDECL className::func##_body args }; #endif Index: netConnection.cpp =================================================================== RCS file: /cvsroot/opentnl/tnl/tnl/netConnection.cpp,v retrieving revision 1.11 retrieving revision 1.12 diff -C2 -d -r1.11 -r1.12 *** netConnection.cpp 28 Sep 2004 18:45:25 -0000 1.11 --- netConnection.cpp 14 Feb 2005 06:15:28 -0000 1.12 *************** *** 159,165 **** if(isAdaptive()) { ! timeoutCount = AdaptivePingRetryCount; ! if(!mPingSendCount) ! timeout = AdaptiveInitialPingTimeout; } if((time - mLastPingSendTime) > timeout) --- 159,172 ---- if(isAdaptive()) { ! if(hasUnackedSentPackets()) ! { ! timeout = AdaptiveUnackedSentPingTimeout; ! } ! else ! { ! timeoutCount = AdaptivePingRetryCount; ! if(!mPingSendCount) ! timeout = AdaptiveInitialPingTimeout; ! } } if((time - mLastPingSendTime) > timeout) *************** *** 370,374 **** --- 377,384 ---- mSymmetricCipher->setupCounter(pkSequenceNumber, pkHighestAck, pkPacketType, 0); if(!pstream->decryptAndCheckHash(MessageSignatureBytes, PacketHeaderByteSize, mSymmetricCipher)) + { + TNLLogMessage(LogNetConnection, "Packet failed crypto"); return false; + } } *************** *** 860,863 **** --- 870,875 ---- client->setInterface(connectionInterface); client->getConnectionParameters().mIsInitiator = true; + client->getConnectionParameters().mIsLocal = true; + server->getConnectionParameters().mIsLocal = true; server->setInterface(serverInterface); Index: tnlVector.h =================================================================== RCS file: /cvsroot/opentnl/tnl/tnl/tnlVector.h,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** tnlVector.h 13 May 2004 19:21:49 -0000 1.4 --- tnlVector.h 14 Feb 2005 06:15:28 -0000 1.5 *************** *** 219,222 **** --- 219,223 ---- { checkSize(mElementCount + 1); + constructInPlace(&mArray[mElementCount]); mElementCount++; Index: tnlNetConnection.h =================================================================== RCS file: /cvsroot/opentnl/tnl/tnl/tnlNetConnection.h,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** tnlNetConnection.h 28 Sep 2004 18:45:25 -0000 1.8 --- tnlNetConnection.h 14 Feb 2005 06:15:28 -0000 1.9 *************** *** 104,107 **** --- 104,108 ---- Vector<Address> mPossibleAddresses; ///< List of possible addresses for the remote host in an arranged connection. bool mIsInitiator; ///< True if this host initiated the arranged connection. + bool mIsLocal; ///< True if this is a connectLocal connection. ByteBufferPtr mArrangedSecret; ///< The shared secret as arranged by the connection intermediary. bool mDebugObjectSizes; ///< This connection's initiator requested debugging size information during packet writes. *************** *** 118,121 **** --- 119,123 ---- mDebugObjectSizes = false; #endif + mIsLocal = false; } }; *************** *** 191,197 **** --- 193,203 ---- DefaultPingTimeout = 5000, ///< Default milliseconds to wait before sending a ping packet. DefaultPingRetryCount = 10, ///< Default number of unacknowledged pings to send before timing out. + AdaptiveUnackedSentPingTimeout = 3000, }; U32 mPingTimeout; ///< Milliseconds to wait before sending a ping packet. U32 mPingRetryCount; ///< Number of unacknowledged pings to send before timing out. + + /// Returns true if this connection has sent packets that have not yet been acked by the remote host. + bool hasUnackedSentPackets() { return mLastSendSeq != mHighestAckedSeq; } public: struct PacketNotify; Index: eventConnection.cpp =================================================================== RCS file: /cvsroot/opentnl/tnl/tnl/eventConnection.cpp,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** eventConnection.cpp 28 Sep 2004 18:45:24 -0000 1.5 --- eventConnection.cpp 14 Feb 2005 06:15:28 -0000 1.6 *************** *** 124,127 **** --- 124,132 ---- stream->read(&mEventClassCount); + U32 myCount = NetClassRep::getNetClassCount(getNetClassGroup(), NetClassTypeEvent); + + if(mEventClassCount > myCount) + return false; + if(!NetClassRep::isVersionBorderCount(getNetClassGroup(), NetClassTypeEvent, mEventClassCount)) return false; *************** *** 137,140 **** --- 142,151 ---- } + void EventConnection::processEvent(NetEvent *theEvent) + { + if(getConnectionState() == NetConnection::Connected) + theEvent->process(this); + } + void EventConnection::packetDropped(PacketNotify *pnotify) { *************** *** 421,425 **** if(unguaranteedPhase) { ! evt->process(this); delete evt; if(mErrorBuffer[0]) --- 432,436 ---- if(unguaranteedPhase) { ! processEvent(evt); delete evt; if(mErrorBuffer[0]) *************** *** 450,454 **** TNLLogMessageV(LogEventConnection, ("EventConnection %s: ProcessGuaranteed %d", getNetAddressString(), temp->mSeqCount)); ! temp->mEvent->process(this); mEventNoteChunker.free(temp); if(mErrorBuffer[0]) --- 461,465 ---- TNLLogMessageV(LogEventConnection, ("EventConnection %s: ProcessGuaranteed %d", getNetAddressString(), temp->mSeqCount)); ! processEvent(temp->mEvent); mEventNoteChunker.free(temp); if(mErrorBuffer[0]) *************** *** 460,464 **** { S32 classId = theEvent->getClassId(getNetClassGroup()); ! if(U32(classId) >= mEventClassCount) return false; --- 471,475 ---- { S32 classId = theEvent->getClassId(getNetClassGroup()); ! if(U32(classId) >= mEventClassCount && getConnectionState() == Connected) return false; Index: netInterface.cpp =================================================================== RCS file: /cvsroot/opentnl/tnl/tnl/netInterface.cpp,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** netInterface.cpp 3 Jun 2004 00:55:20 -0000 1.8 --- netInterface.cpp 14 Feb 2005 06:15:28 -0000 1.9 *************** *** 434,438 **** // lookup the connection in the addressTable ! NetConnection *conn = findConnection(sourceAddress); if(conn) conn->readRawPacket(pStream); --- 434,439 ---- // lookup the connection in the addressTable ! // if this packet causes a disconnection, keep the conn around until this function exits ! RefPtr<NetConnection> conn = findConnection(sourceAddress); if(conn) conn->readRawPacket(pStream); *************** *** 900,903 **** --- 901,905 ---- stream->readString(reason); + TNLLogMessageV(LogNetInterface, ("Received Connect Reject - reason %s", reason)); // if the reason is a bad puzzle solution, try once more with a // new nonce. Index: byteBuffer.cpp =================================================================== RCS file: /cvsroot/opentnl/tnl/tnl/byteBuffer.cpp,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** byteBuffer.cpp 22 Apr 2004 20:42:25 -0000 1.2 --- byteBuffer.cpp 14 Feb 2005 06:15:25 -0000 1.3 *************** *** 49,52 **** --- 49,119 ---- } + RefPtr<ByteBuffer> ByteBuffer::encodeBase16() const + { + U32 outLen = getBufferSize() * 2 + 1; + ByteBuffer *ret = new ByteBuffer(outLen); + const U8 *buffer = getBuffer(); + U8 *outBuffer = ret->getBuffer(); + + S32 size = getBufferSize(); + for(S32 i = 0; i < size; i++) + { + U8 b = *buffer++; + U32 nib1 = b >> 4; + U32 nib2 = b & 0xF; + if(nib1 > 9) + *outBuffer++ = 'a' + nib1 - 10; + else + *outBuffer++ = '0' + nib1; + if(nib2 > 9) + *outBuffer++ = 'a' + nib2 - 10; + else + *outBuffer++ = '0' + nib2; + } + *outBuffer = 0; + return ret; + } + + RefPtr<ByteBuffer> ByteBuffer::decodeBase16() const + { + U32 outLen = getBufferSize() >> 1; + ByteBuffer *ret = new ByteBuffer(outLen); + const U8 *src = getBuffer(); + U8 *dst = ret->getBuffer(); + for(U32 i = 0; i < outLen; i++) + { + U8 out = 0; + U8 nib1 = *src++; + U8 nib2 = *src++; + if(nib1 >= '0' && nib1 <= '9') + out = (nib1 - '0') << 4; + else if(nib1 >= 'a' && nib1 <= 'f') + out = (nib1 - 'a' + 10) << 4; + else if(nib1 >= 'A' && nib1 <= 'A') + out = (nib1 - 'A' + 10) << 4; + if(nib2 >= '0' && nib2 <= '9') + out |= nib2 - '0'; + else if(nib2 >= 'a' && nib2 <= 'f') + out |= nib2 - 'a' + 10; + else if(nib2 >= 'A' && nib2 <= 'A') + out |= nib2 - 'A' + 10; + *dst++ = out; + } + return ret; + } + + RefPtr<ByteBuffer> ByteBuffer::computeMD5Hash(U32 len) const + { + if(!len) + len = getBufferSize(); + + ByteBuffer *ret = new ByteBuffer(16); + hash_state md; + md5_init(&md); + md5_process(&md, (unsigned char *) getBuffer(), len); + md5_done(&md, ret->getBuffer()); + return ret; + } + U32 ByteBuffer::calculateCRC(U32 start, U32 end, U32 crcVal) const { --- NEW FILE: thread.cpp --- //----------------------------------------------------------------------------------- // // Torque Network Library // Copyright (C) 2004 GarageGames.com, Inc. // For more information see http://www.opentnl.org // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // For use in products that are not compatible with the terms of the GNU // General Public License, alternative licensing options are available // from GarageGames.com. // // 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 General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // //------------------------------------------------------------------------------------ #include "tnlThread.h" #include "tnlLog.h" namespace TNL { #ifdef TNL_OS_WIN32 Semaphore::Semaphore(U32 initialCount, U32 maximumCount) { mSemaphore = CreateSemaphore(NULL, initialCount, maximumCount, NULL); } Semaphore::~Semaphore() { CloseHandle(mSemaphore); } void Semaphore::wait() { WaitForSingleObject(mSemaphore, INFINITE); } void Semaphore::increment(U32 count) { ReleaseSemaphore(mSemaphore, count, NULL); } Mutex::Mutex() { InitializeCriticalSection(&mLock); } Mutex::~Mutex() { DeleteCriticalSection(&mLock); } void Mutex::lock() { EnterCriticalSection(&mLock); } void Mutex::unlock() { LeaveCriticalSection(&mLock); } bool Mutex::tryLock() { return false;// return TryEnterCriticalSection(&mLock); } ThreadStorage::ThreadStorage() { mTlsIndex = TlsAlloc(); } ThreadStorage::~ThreadStorage() { TlsFree(mTlsIndex); } void *ThreadStorage::get() { return TlsGetValue(mTlsIndex); } void ThreadStorage::set(void *value) { TlsSetValue(mTlsIndex, value); } DWORD WINAPI ThreadProc( LPVOID lpParameter ) { return ((Thread *) lpParameter)->run(); } U32 Thread::run() { return 0; } void Thread::start() { mThread = CreateThread(NULL, 0, ThreadProc, this, 0, NULL); mReturnValue = 0; } Thread::Thread() { } Thread::~Thread() { CloseHandle(mThread); } #else Semaphore::Semaphore(U32 initialCount, U32 maximumCount) { sem_init(&mSemaphore, 0, initialCount); } Semaphore::~Semaphore() { sem_destroy(&mSemaphore); } void Semaphore::wait() { sem_wait(&mSemaphore); } void Semaphore::increment(U32 count) { for(U32 i = 0; i < count; i++) sem_post(&mSemaphore); } Mutex::Mutex() { pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); #ifdef TNL_OS_LINUX pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP); #else pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); #endif pthread_mutex_init(&mMutex, &attr); pthread_mutexattr_destroy(&attr); } Mutex::~Mutex() { pthread_mutex_destroy(&mMutex); } void Mutex::lock() { pthread_mutex_lock(&mMutex); } void Mutex::unlock() { pthread_mutex_unlock(&mMutex); } bool Mutex::tryLock() { return false;// return TryEnterCriticalSection(&mLock); } ThreadStorage::ThreadStorage() { pthread_key_create(&mThreadKey, NULL); } ThreadStorage::~ThreadStorage() { pthread_key_delete(mThreadKey); } void *ThreadStorage::get() { pthread_getspecific(mThreadKey); } void ThreadStorage::set(void *value) { pthread_setspecific(mThreadKey, value); } void *ThreadProc(void *lpParameter) { return (void *) ((Thread *) lpParameter)->run(); } Thread::Thread() { } void Thread::start() { int val = pthread_create(&mThread, NULL, ThreadProc, this); mReturnValue = 0; } Thread::~Thread() { } #endif ThreadQueue::ThreadQueueThread::ThreadQueueThread(ThreadQueue *q) { mThreadQueue = q; } U32 ThreadQueue::ThreadQueueThread::run() { mThreadQueue->threadStart(); mThreadQueue->lock(); ThreadStorage &sto = mThreadQueue->getStorage(); sto.set((void *) 0); mThreadQueue->unlock(); for(;;) mThreadQueue->dispatchNextCall(); return 0; } ThreadQueue::ThreadQueue(U32 threadCount) { mStorage.set((void *) 1); for(U32 i = 0; i < threadCount; i++) { Thread *theThread = new ThreadQueueThread(this); mThreads.push_back(theThread); theThread->start(); } } ThreadQueue::~ThreadQueue() { } void ThreadQueue::dispatchNextCall() { mSemaphore.wait(); lock(); if(mThreadCalls.size() == 0) { unlock(); return; } ThreadQueueCall c = mThreadCalls.first(); mThreadCalls.pop_front(); unlock(); BitStream unmarshallData(c.c->marshalledData.getBuffer(), c.c->marshalledData.getBytePosition()); c.c->unmarshall(&unmarshallData); c.c->dispatch(this, &c.p); delete c.c; } void ThreadQueue::postCall(ThreadQueueCall &theCall) { lock(); if(isMainThread()) { mThreadCalls.push_back(theCall); unlock(); mSemaphore.increment(); } else { mResponseCalls.push_back(theCall); unlock(); } } void ThreadQueue::dispatchResponseCalls() { lock(); for(S32 i = 0; i < mResponseCalls.size(); i++) { ThreadQueueCall c = mResponseCalls[i]; BitStream unmarshallData(c.c->marshalledData.getBuffer(), c.c->marshalledData.getBytePosition()); c.c->unmarshall(&unmarshallData); c.c->dispatch(this, &c.p); delete c.c; } mResponseCalls.clear(); unlock(); } }; Index: tnlEventConnection.h =================================================================== RCS file: /cvsroot/opentnl/tnl/tnl/tnlEventConnection.h,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** tnlEventConnection.h 3 Jul 2004 20:01:46 -0000 1.2 --- tnlEventConnection.h 14 Feb 2005 06:15:28 -0000 1.3 *************** *** 109,112 **** --- 109,115 ---- virtual bool isDataToTransmit(); + /// Dispatches an event + void processEvent(NetEvent *theEvent); + //---------------------------------------------------------------- Index: tnl.vcproj =================================================================== RCS file: /cvsroot/opentnl/tnl/tnl/tnl.vcproj,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** tnl.vcproj 30 May 2004 20:54:54 -0000 1.5 --- tnl.vcproj 14 Feb 2005 06:15:28 -0000 1.6 *************** *** 277,280 **** --- 277,283 ---- </File> <File + RelativePath=".\thread.cpp"> + </File> + <File RelativePath="tnl.h"> </File> *************** *** 367,370 **** --- 370,376 ---- </File> <File + RelativePath=".\tnlThread.h"> + </File> + <File RelativePath=".\tnlTypes.h"> </File> Index: tnlMethodDispatch.h =================================================================== RCS file: /cvsroot/opentnl/tnl/tnl/tnlMethodDispatch.h,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** tnlMethodDispatch.h 28 Sep 2004 18:59:23 -0000 1.8 --- tnlMethodDispatch.h 14 Feb 2005 06:15:28 -0000 1.9 *************** *** 146,193 **** }; ! #if defined(TNL_SUPPORTS_VC_INLINE_X86_ASM) || defined(TNL_SUPPORTS_MWERKS_INLINE_X86_ASM) }; - // VC 6.0 and Codewarrior have problems with the usage of a namespace reference inside an - // inline assembly block, so we close the namespace and add this as a global global. ! extern void *TNL_gBasePtr; ! namespace TNL { ! #define SAVE_PARAMS __asm { lea eax, this }; __asm { mov TNL_gBasePtr, eax }; #elif defined(TNL_SUPPORTS_GCC_INLINE_X86_ASM ) ! }; ! extern void *TNL_gBasePtr; ! namespace TNL { ! #define SAVE_PARAMS TNL_gBasePtr = (void *) ((TNL::U8 *) __builtin_frame_address(0) + 8); #elif defined(TNL_SUPPORTS_GCC_INLINE_PPC_ASM ) ! extern U32 gRegisterSaves[8 + 13 + 1]; ! #define SAVE_PARAMS __asm__ volatile ( \ ! "mr r2, %0\n" \ ! "stw r3, 0(r2) \n" \ ! "stw r4, 4(r2) \n" \ ! "stw r5, 8(r2) \n" \ ! "stw r6, 12(r2) \n" \ ! "stw r7, 16(r2) \n" \ ! "stw r8, 20(r2) \n" \ ! "stw r9, 24(r2) \n" \ ! "stw r10, 28(r2) \n" \ ! "stfs f1, 32(r2) \n" \ ! "stfs f2, 36(r2) \n" \ ! "stfs f3, 40(r2) \n" \ ! "stfs f4, 44(r2) \n" \ ! "stfs f5, 48(r2) \n" \ ! "stfs f6, 52(r2) \n" \ ! "stfs f7, 56(r2) \n" \ ! "stfs f8, 60(r2) \n" \ ! "stfs f9, 64(r2) \n" \ ! "stfs f10, 68(r2) \n" \ ! "stfs f11, 72(r2) \n" \ ! "stfs f12, 76(r2) \n" \ ! "stfs f13, 80(r2) \n" \ ! "stw r1, 84(r2) \n" \ ! : : "r" (TNL::gRegisterSaves) : "r2" ); #else --- 146,203 ---- }; ! struct RPCThreadStorage ! { ! void *basePtr; ! #ifdef TNL_CPU_PPC ! U32 registerSaves[8 + 13 + 1]; ! #endif ! U8 rpcReadData[MethodArgList::MaxRPCDataSize]; ! U32 rpcReadOffsets[MethodArgList::MaxOffsets]; ! U8 *rpcSTEOffsets[MethodArgList::MaxOffsets]; ! U32 rpcSTEIndex[MethodArgList::MaxOffsets]; ! U32 rpcNumSTEs; ! U32 rpcNumOffsets; }; + extern RPCThreadStorage &getRPCThreadStorage(); ! #if defined(TNL_SUPPORTS_VC_INLINE_X86_ASM) || defined(TNL_SUPPORTS_MWERKS_INLINE_X86_ASM) ! ! #define SAVE_PARAMS { void *basePtr; __asm { lea eax, this }; __asm { mov basePtr, eax }; TNL::getRPCThreadStorage().basePtr = basePtr; } #elif defined(TNL_SUPPORTS_GCC_INLINE_X86_ASM ) ! #define SAVE_PARAMS { void *basePtr = (void *) ((TNL::U8 *) __builtin_frame_address(0) + 8); TNL::getRPCThreadStorage().basePtr = basePtr; } #elif defined(TNL_SUPPORTS_GCC_INLINE_PPC_ASM ) ! ! #define SAVE_PARAMS { \ ! U32 *registerSaves = TNL::getRPCThreadStorage().registerSaves; \ ! __asm__ volatile ( \ ! "mr r2, %0\n" \ ! "stw r3, 0(r2) \n" \ ! "stw r4, 4(r2) \n" \ ! "stw r5, 8(r2) \n" \ ! "stw r6, 12(r2) \n" \ ! "stw r7, 16(r2) \n" \ ! "stw r8, 20(r2) \n" \ ! "stw r9, 24(r2) \n" \ ! "stw r10, 28(r2) \n" \ ! "stfs f1, 32(r2) \n" \ ! "stfs f2, 36(r2) \n" \ ! "stfs f3, 40(r2) \n" \ ! "stfs f4, 44(r2) \n" \ ! "stfs f5, 48(r2) \n" \ ! "stfs f6, 52(r2) \n" \ ! "stfs f7, 56(r2) \n" \ ! "stfs f8, 60(r2) \n" \ ! "stfs f9, 64(r2) \n" \ ! "stfs f10, 68(r2) \n" \ ! "stfs f11, 72(r2) \n" \ ! "stfs f12, 76(r2) \n" \ ! ... [truncated message content] |