void UDPForwarder::UpdateThreaded(void) { fd_set readFD; //fd_set exceptionFD; FD_ZERO(&readFD); // FD_ZERO(&exceptionFD); timeval tv; int selectResult; tv.tv_sec=0; tv.tv_usec=0; RakNet::TimeMS curTime = RakNet::GetTimeMS(); SOCKET largestDescriptor=0; DataStructures::DefaultIndexType i; // Remove unused entries i=0; while (i < forwardList.GetSize()) { if (curTime > forwardList[i]->timeLastDatagramForwarded && // Account for timestamp wrap curTime > forwardList[i]->timeLastDatagramForwarded+forwardList[i]->timeoutOnNoDataMS) { RakNet::OP_DELETE(forwardList[i],_FILE_AND_LINE_); forwardList.RemoveAtIndex(i,_FILE_AND_LINE_); } else i++; } if (forwardList.GetSize()==0) return; for (i=0; i < forwardList.GetSize(); i++) { #ifdef _MSC_VER #pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant #endif FD_SET(forwardList[i]->readSocket, &readFD); // FD_SET(forwardList[i]->readSocket, &exceptionFD); if (forwardList[i]->readSocket > largestDescriptor) largestDescriptor = forwardList[i]->readSocket; } #if defined(_PS3) || defined(__PS3__) || defined(SN_TARGET_PS3) #else selectResult=(int) select((int) largestDescriptor+1, &readFD, 0, 0, &tv); #endif char data[ MAXIMUM_MTU_SIZE ]; sockaddr_in sa; socklen_t len2; if (selectResult > 0) { DataStructures::Queue<ForwardEntry*> entriesToRead; ForwardEntry *feSource; for (i=0; i < forwardList.GetSize(); i++) { feSource = forwardList[i]; // I do this because I'm updating the forwardList, and don't want to lose FD_ISSET as the list is no longer in order if (FD_ISSET(feSource->readSocket, &readFD)) entriesToRead.Push(feSource,__FILE__,__LINE__); } while (entriesToRead.IsEmpty()==false) { feSource=entriesToRead.Pop(); const int flag=0; int receivedDataLen, len=0; unsigned short portnum=0; len2 = sizeof( sa ); sa.sin_family = AF_INET; receivedDataLen = recvfrom( feSource->readSocket, data, MAXIMUM_MTU_SIZE, flag, ( sockaddr* ) & sa, ( socklen_t* ) & len2 ); portnum = ntohs( sa.sin_port ); if (feSource->srcAndDest.source.binaryAddress==sa.sin_addr.s_addr) { if (feSource->updatedSourceAddress==false) { feSource->updatedSourceAddress=true; if (feSource->srcAndDest.source.port!=portnum) { // Remove both source and dest from list, update addresses, and reinsert in order DataStructures::DefaultIndexType sourceIndex, destIndex; SrcAndDest srcAndDest; srcAndDest.source=feSource->srcAndDest.destination; srcAndDest.destination=feSource->srcAndDest.source; destIndex=forwardList.GetIndexOf(srcAndDest); ForwardEntry *feDest = forwardList[destIndex]; forwardList.RemoveAtIndex(destIndex,__FILE__,__LINE__); srcAndDest.source=feSource->srcAndDest.source; srcAndDest.destination=feSource->srcAndDest.destination; sourceIndex=forwardList.GetIndexOf(srcAndDest); forwardList.RemoveAtIndex(sourceIndex,__FILE__,__LINE__); feSource->srcAndDest.source.port=portnum; feDest->srcAndDest.destination.port=portnum; feSource->timeLastDatagramForwarded=curTime; feDest->timeLastDatagramForwarded=curTime; forwardList.Push(feSource,feSource->srcAndDest,__FILE__,__LINE__); forwardList.Push(feDest,feDest->srcAndDest,__FILE__,__LINE__); } } if (feSource->srcAndDest.source.port==portnum) { // Forward to destination len=0; sockaddr_in saOut; saOut.sin_port = htons( feSource->srcAndDest.destination.port ); // User port saOut.sin_addr.s_addr = feSource->srcAndDest.destination.binaryAddress; saOut.sin_family = AF_INET; do { len = sendto( feSource->writeSocket, data, receivedDataLen, 0, ( const sockaddr* ) & saOut, sizeof( saOut ) ); } while ( len == 0 ); feSource->timeLastDatagramForwarded=curTime; } } } } }
void FileListTransfer::Send(FileList *fileList, RakPeerInterface *rakPeer, SystemAddress recipient, unsigned short setID, PacketPriority priority, char orderingChannel, bool compressData, IncrementalReadInterface *_incrementalReadInterface, unsigned int _chunkSize) { (void) compressData; if (callback) fileList->SetCallback(callback); unsigned int i, totalLength; RakNet::BitStream outBitstream; bool sendReference; const char *dataBlocks[2]; int lengths[2]; totalLength=0; for (i=0; i < fileList->fileList.Size(); i++) { const FileListNode &fileListNode = fileList->fileList[i]; totalLength+=fileListNode.fileLengthBytes; } // Write the chunk header, which contains the frequency table, the total number of files, and the total number of bytes bool anythingToWrite; outBitstream.Write((MessageID)ID_FILE_LIST_TRANSFER_HEADER); outBitstream.Write(setID); anythingToWrite=fileList->fileList.Size()>0; outBitstream.Write(anythingToWrite); if (anythingToWrite) { outBitstream.WriteCompressed(fileList->fileList.Size()); outBitstream.WriteCompressed(totalLength); if (rakPeer) rakPeer->Send(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false); else SendUnified(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false); DataStructures::Queue<FileToPush*> filesToPush; for (i=0; i < fileList->fileList.Size(); i++) { sendReference = fileList->fileList[i].isAReference && _incrementalReadInterface!=0; if (sendReference) { FileToPush *fileToPush = RakNet::OP_NEW<FileToPush>(__FILE__,__LINE__); fileToPush->fileListNode.context=fileList->fileList[i].context; fileToPush->setIndex=i; fileToPush->fileListNode.filename=fileList->fileList[i].filename; fileToPush->fileListNode.fullPathToFile=fileList->fileList[i].fullPathToFile; fileToPush->fileListNode.fileLengthBytes=fileList->fileList[i].fileLengthBytes; fileToPush->fileListNode.dataLengthBytes=fileList->fileList[i].dataLengthBytes; // fileToPush->systemAddress=recipient; fileToPush->setID=setID; fileToPush->packetPriority=priority; fileToPush->orderingChannel=orderingChannel; fileToPush->currentOffset=0; fileToPush->incrementalReadInterface=_incrementalReadInterface; fileToPush->chunkSize=_chunkSize; filesToPush.Push(fileToPush,__FILE__,__LINE__); } else { outBitstream.Reset(); outBitstream.Write((MessageID)ID_FILE_LIST_TRANSFER_FILE); outBitstream.Write(fileList->fileList[i].context); outBitstream.Write(setID); stringCompressor->EncodeString(fileList->fileList[i].filename, 512, &outBitstream); outBitstream.WriteCompressed(i); outBitstream.WriteCompressed(fileList->fileList[i].dataLengthBytes); // Original length in bytes outBitstream.AlignWriteToByteBoundary(); dataBlocks[0]=(char*) outBitstream.GetData(); lengths[0]=outBitstream.GetNumberOfBytesUsed(); dataBlocks[1]=fileList->fileList[i].data; lengths[1]=fileList->fileList[i].dataLengthBytes; SendListUnified(dataBlocks,lengths,2,priority, RELIABLE_ORDERED, orderingChannel, recipient, false); } } if (filesToPush.IsEmpty()==false) { FileToPushRecipient *ftpr=0; filesToPushAllSameAddressMutex.Lock(); for (unsigned int i=0; i < filesToPushAllSameAddress.Size(); i++) { if (filesToPushAllSameAddress[i]->systemAddress==recipient) { ftpr=filesToPushAllSameAddress[i]; break; } } if (ftpr==0) { ftpr = RakNet::OP_NEW<FileToPushRecipient>(__FILE__,__LINE__); ftpr->systemAddress=recipient; filesToPushAllSameAddress.Push(ftpr, __FILE__,__LINE__); } while (filesToPush.IsEmpty()==false) { ftpr->filesToPush.Push(filesToPush.Pop(), __FILE__,__LINE__); } filesToPushAllSameAddressMutex.Unlock(); SendIRIToAddress(recipient); return; } } else { if (rakPeer) rakPeer->Send(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false); else SendUnified(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false); } }
void UDPForwarder::UpdateThreaded_Old(void) { fd_set readFD; //fd_set exceptionFD; FD_ZERO(&readFD); // FD_ZERO(&exceptionFD); timeval tv; int selectResult; tv.tv_sec=0; tv.tv_usec=0; RakNet::TimeMS curTime = RakNet::GetTimeMS(); SOCKET largestDescriptor=0; DataStructures::DefaultIndexType i; // Remove unused entries i=0; while (i < forwardList.GetSize()) { if (curTime > forwardList[i]->timeLastDatagramForwarded && // Account for timestamp wrap curTime > forwardList[i]->timeLastDatagramForwarded+forwardList[i]->timeoutOnNoDataMS) { RakNet::OP_DELETE(forwardList[i],_FILE_AND_LINE_); forwardList.RemoveAtIndex(i,_FILE_AND_LINE_); } else i++; } if (forwardList.GetSize()==0) return; for (i=0; i < forwardList.GetSize(); i++) { #ifdef _MSC_VER #pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant #endif FD_SET(forwardList[i]->socket, &readFD); // FD_SET(forwardList[i]->readSocket, &exceptionFD); if (forwardList[i]->socket > largestDescriptor) largestDescriptor = forwardList[i]->socket; } #if defined(_PS3) || defined(__PS3__) || defined(SN_TARGET_PS3) #else selectResult=(int) select((int) largestDescriptor+1, &readFD, 0, 0, &tv); #endif char data[ MAXIMUM_MTU_SIZE ]; sockaddr_in sa; socklen_t len2; if (selectResult > 0) { DataStructures::Queue<ForwardEntry*> entriesToRead; ForwardEntry *forwardEntry; for (i=0; i < forwardList.GetSize(); i++) { forwardEntry = forwardList[i]; // I do this because I'm updating the forwardList, and don't want to lose FD_ISSET as the list is no longer in order if (FD_ISSET(forwardEntry->socket, &readFD)) entriesToRead.Push(forwardEntry,_FILE_AND_LINE_); } while (entriesToRead.IsEmpty()==false) { forwardEntry=entriesToRead.Pop(); const int flag=0; int receivedDataLen, len=0; unsigned short portnum=0; len2 = sizeof( sa ); sa.sin_family = AF_INET; receivedDataLen = recvfrom( forwardEntry->socket, data, MAXIMUM_MTU_SIZE, flag, ( sockaddr* ) & sa, ( socklen_t* ) & len2 ); if (receivedDataLen<0) { #if defined(_WIN32) && defined(_DEBUG) && !defined(_XBOX) && !defined(X360) DWORD dwIOError = WSAGetLastError(); if (dwIOError!=WSAECONNRESET && dwIOError!=WSAEINTR && dwIOError!=WSAETIMEDOUT) { LPVOID messageBuffer; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwIOError, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language ( LPTSTR ) & messageBuffer, 0, NULL ); // something has gone wrong here... RAKNET_DEBUG_PRINTF( "recvfrom failed:Error code - %d\n%s", dwIOError, messageBuffer ); //Free the buffer. LocalFree( messageBuffer ); } #endif continue; } portnum = ntohs( sa.sin_port ); if (forwardEntry->srcAndDest.source.address.addr4.sin_addr.s_addr==sa.sin_addr.s_addr && forwardEntry->updatedSourcePort==false && forwardEntry->srcAndDest.dest.GetPort()!=portnum) { forwardEntry->updatedSourcePort=true; if (forwardEntry->srcAndDest.source.GetPort()!=portnum) { DataStructures::DefaultIndexType index; SrcAndDest srcAndDest(forwardEntry->srcAndDest.dest, forwardEntry->srcAndDest.source); index=forwardList.GetIndexOf(srcAndDest); forwardList.RemoveAtIndex(index,_FILE_AND_LINE_); forwardEntry->srcAndDest.source.SetPort(portnum); forwardList.Push(forwardEntry,forwardEntry->srcAndDest,_FILE_AND_LINE_); } } if (forwardEntry->srcAndDest.source.address.addr4.sin_addr.s_addr==sa.sin_addr.s_addr && forwardEntry->srcAndDest.source.GetPort()==portnum) { // Forward to dest len=0; sockaddr_in saOut; saOut.sin_port = forwardEntry->srcAndDest.dest.GetPortNetworkOrder(); // User port saOut.sin_addr.s_addr = forwardEntry->srcAndDest.dest.address.addr4.sin_addr.s_addr; saOut.sin_family = AF_INET; do { len = sendto( forwardEntry->socket, data, receivedDataLen, 0, ( const sockaddr* ) & saOut, sizeof( saOut ) ); } while ( len == 0 ); // printf("1. Forwarding after %i ms\n", curTime-forwardEntry->timeLastDatagramForwarded); forwardEntry->timeLastDatagramForwarded=curTime; } if (forwardEntry->srcAndDest.dest.address.addr4.sin_addr.s_addr==sa.sin_addr.s_addr && forwardEntry->updatedDestPort==false && forwardEntry->srcAndDest.source.GetPort()!=portnum) { forwardEntry->updatedDestPort=true; if (forwardEntry->srcAndDest.dest.GetPort()!=portnum) { DataStructures::DefaultIndexType index; SrcAndDest srcAndDest(forwardEntry->srcAndDest.source, forwardEntry->srcAndDest.dest); index=forwardList.GetIndexOf(srcAndDest); forwardList.RemoveAtIndex(index,_FILE_AND_LINE_); forwardEntry->srcAndDest.dest.SetPort(portnum); forwardList.Push(forwardEntry,forwardEntry->srcAndDest,_FILE_AND_LINE_); } } if (forwardEntry->srcAndDest.dest.address.addr4.sin_addr.s_addr==sa.sin_addr.s_addr && forwardEntry->srcAndDest.dest.GetPort()==portnum) { // Forward to source len=0; sockaddr_in saOut; saOut.sin_port = forwardEntry->srcAndDest.source.GetPortNetworkOrder(); // User port saOut.sin_addr.s_addr = forwardEntry->srcAndDest.source.address.addr4.sin_addr.s_addr; saOut.sin_family = AF_INET; do { len = sendto( forwardEntry->socket, data, receivedDataLen, 0, ( const sockaddr* ) & saOut, sizeof( saOut ) ); } while ( len == 0 ); // printf("2. Forwarding after %i ms\n", curTime-forwardEntry->timeLastDatagramForwarded); forwardEntry->timeLastDatagramForwarded=curTime; } } } }
void FileListTransfer::Send(FileList *fileList, SLNet::RakPeerInterface *rakPeer, SystemAddress recipient, unsigned short setID, PacketPriority priority, char orderingChannel, IncrementalReadInterface *_incrementalReadInterface, unsigned int _chunkSize) { for (unsigned int flpcIndex=0; flpcIndex < fileListProgressCallbacks.Size(); flpcIndex++) fileList->AddCallback(fileListProgressCallbacks[flpcIndex]); unsigned int i, totalLength; SLNet::BitStream outBitstream; bool sendReference; const char *dataBlocks[2]; int lengths[2]; totalLength=0; for (i=0; i < fileList->fileList.Size(); i++) { const FileListNode &fileListNode = fileList->fileList[i]; totalLength+=fileListNode.dataLengthBytes; } // Write the chunk header, which contains the frequency table, the total number of files, and the total number of bytes bool anythingToWrite; outBitstream.Write((MessageID)ID_FILE_LIST_TRANSFER_HEADER); outBitstream.Write(setID); anythingToWrite=fileList->fileList.Size()>0; outBitstream.Write(anythingToWrite); if (anythingToWrite) { outBitstream.WriteCompressed(fileList->fileList.Size()); outBitstream.WriteCompressed(totalLength); if (rakPeer) rakPeer->Send(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false); else SendUnified(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false); DataStructures::Queue<FileToPush*> filesToPush; for (i=0; i < fileList->fileList.Size(); i++) { sendReference = fileList->fileList[i].isAReference && _incrementalReadInterface!=0; if (sendReference) { FileToPush *fileToPush = SLNet::OP_NEW<FileToPush>(_FILE_AND_LINE_); fileToPush->fileListNode.context=fileList->fileList[i].context; fileToPush->setIndex=i; fileToPush->fileListNode.filename=fileList->fileList[i].filename; fileToPush->fileListNode.fullPathToFile=fileList->fileList[i].fullPathToFile; fileToPush->fileListNode.fileLengthBytes=fileList->fileList[i].fileLengthBytes; fileToPush->fileListNode.dataLengthBytes=fileList->fileList[i].dataLengthBytes; // fileToPush->systemAddress=recipient; //fileToPush->setID=setID; fileToPush->packetPriority=priority; fileToPush->orderingChannel=orderingChannel; fileToPush->currentOffset=0; fileToPush->incrementalReadInterface=_incrementalReadInterface; fileToPush->chunkSize=_chunkSize; filesToPush.Push(fileToPush,_FILE_AND_LINE_); } else { outBitstream.Reset(); outBitstream.Write((MessageID)ID_FILE_LIST_TRANSFER_FILE); outBitstream << fileList->fileList[i].context; // outBitstream.Write(fileList->fileList[i].context); outBitstream.Write(setID); StringCompressor::Instance()->EncodeString(fileList->fileList[i].filename, 512, &outBitstream); outBitstream.WriteCompressed(i); outBitstream.WriteCompressed(fileList->fileList[i].dataLengthBytes); // Original length in bytes outBitstream.AlignWriteToByteBoundary(); dataBlocks[0]=(char*) outBitstream.GetData(); lengths[0]=outBitstream.GetNumberOfBytesUsed(); dataBlocks[1]=fileList->fileList[i].data; lengths[1]=fileList->fileList[i].dataLengthBytes; SendListUnified(dataBlocks,lengths,2,priority, RELIABLE_ORDERED, orderingChannel, recipient, false); } } if (filesToPush.IsEmpty()==false) { FileToPushRecipient *ftpr; fileToPushRecipientListMutex.Lock(); for (i=0; i < fileToPushRecipientList.Size(); i++) { if (fileToPushRecipientList[i]->systemAddress==recipient && fileToPushRecipientList[i]->setId==setId) { // ftpr=fileToPushRecipientList[i]; // ftpr->AddRef(); // break; RakAssert("setId already in use for this recipient" && 0); } } fileToPushRecipientListMutex.Unlock(); //if (ftpr==0) //{ ftpr = SLNet::OP_NEW<FileToPushRecipient>(_FILE_AND_LINE_); ftpr->systemAddress=recipient; ftpr->setId=setID; ftpr->refCount=2; // Allocated and in the list fileToPushRecipientList.Push(ftpr, _FILE_AND_LINE_); //} while (filesToPush.IsEmpty()==false) { ////ftpr->filesToPushMutex.Lock(); ftpr->filesToPush.Push(filesToPush.Pop(), _FILE_AND_LINE_); ////ftpr->filesToPushMutex.Unlock(); } // ftpr out of scope ftpr->Deref(); SendIRIToAddress(recipient, setID); return; } else { for (unsigned int flpcIndex=0; flpcIndex < fileListProgressCallbacks.Size(); flpcIndex++) fileListProgressCallbacks[flpcIndex]->OnFilePushesComplete(recipient, setID); } } else { for (unsigned int flpcIndex=0; flpcIndex < fileListProgressCallbacks.Size(); flpcIndex++) fileListProgressCallbacks[flpcIndex]->OnFilePushesComplete(recipient, setID); if (rakPeer) rakPeer->Send(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false); else SendUnified(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false); } }