//////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // UDP Layer must be initialized // theIp and thePort cannot be 0 (Zero) // Based on an IP and port, the function will return the amount of free space // of a peer's buffer. int gsUdpEngineGetPeerOutBufferFreeSpace(unsigned int theIp, unsigned short thePort) { GSUdpEngineObject *aUdp = gsUdpEngineGetEngine(); GSUdpRemotePeer aRemotePeer, *aRemotePeerFound; int index; GS_ASSERT(aUdp->mInitialized); GS_ASSERT(theIp); GS_ASSERT(thePort); if (!aUdp->mInitialized) { gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Debug, "[Udp Engine] Engine not initialized\n"); return 0; } aRemotePeer.mAddr = theIp; aRemotePeer.mPort = thePort; index = ArraySearch(aUdp->mRemotePeers, &aRemotePeer, gsUdpRemotePeerCompare, 0, 0); if (index != NOT_FOUND) { aRemotePeerFound = (GSUdpRemotePeer *)ArrayNth(aUdp->mRemotePeers, index); return gt2GetOutgoingBufferFreeSpace(aRemotePeerFound->mConnection); } return 0; }
//////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // UDP Layer must be initialized // Used obtain the peer's state // theIp and thePort cannot be 0 (Zero) GSUdpErrorCode gsUdpEngineGetPeerState(unsigned int theIp, unsigned short thePort, GSUdpPeerState *thePeerState) { GSUdpEngineObject *aUdp = gsUdpEngineGetEngine(); GSUdpRemotePeer aPeer, *aPeerFound; int index; GS_ASSERT(aUdp->mInitialized); GS_ASSERT(theIp); GS_ASSERT(thePort); GS_ASSERT(thePeerState != NULL); if (!aUdp->mInitialized) { gsDebugFormat(GSIDebugCat_Common, GSIDebugType_State, GSIDebugLevel_Debug, "[Udp Engine] Engine not initialized\n"); *thePeerState = GS_UDP_PEER_CLOSED; return GS_UDP_NOT_INITIALIZED; } aPeer.mAddr = theIp; aPeer.mPort = thePort; index = ArraySearch(aUdp->mRemotePeers, &aPeer, gsUdpRemotePeerCompare, 0, 0); if (index == NOT_FOUND) { *thePeerState = GS_UDP_PEER_CLOSED; return GS_UDP_NO_ERROR; } aPeerFound = (GSUdpRemotePeer *)ArrayNth(aUdp->mRemotePeers, index); *thePeerState = (GSUdpPeerState)gt2GetConnectionState(aPeerFound->mConnection); return GS_UDP_NO_ERROR; }
//////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // UDP Layer must be initialized // theIp and thePort cannot be 0 (Zero) // Rejects a Peer's request for communication // Should only be used by App GSUdpErrorCode gsUdpEngineRejectPeer(unsigned int theIp, unsigned short thePort) { GSUdpRemotePeer aRemotePeer; GSUdpEngineObject *aUdp = gsUdpEngineGetEngine(); int index; GS_ASSERT(aUdp->mInitialized); GS_ASSERT(theIp); GS_ASSERT(thePort); if (!aUdp->mInitialized) { gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Debug, "[Udp Engine] Engine not initialized\n"); return GS_UDP_NETWORK_ERROR; } if (theIp == 0 || thePort == 0) { gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Debug, "[Udp Engine] Invalid parameter(s), check ip, port\n"); return GS_UDP_PARAMETER_ERROR; } // Find the connection to reject in our array of peers aRemotePeer.mAddr = theIp; aRemotePeer.mPort = thePort; index = ArraySearch(aUdp->mRemotePeers, &aRemotePeer, gsUdpRemotePeerCompare, 0, 0); if (index != NOT_FOUND) { GSUdpRemotePeer *aPeerFound = (GSUdpRemotePeer *)ArrayNth(aUdp->mRemotePeers, index); gt2Reject(aPeerFound->mConnection, NULL, 0); ArrayDeleteAt(aUdp->mRemotePeers, index); } return GS_UDP_NO_ERROR; }
//////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // Pings are passed on to higher level app or message handlers void gsUdpPingRoutingCB(GT2Connection theConnection, int theLatency) { GSUdpEngineObject *aUdp = gsUdpEngineGetEngine(); int index, len; char anAddr[GS_IP_ADDR_AND_PORT]; gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Comment, "[Udp Engine] Received ping from %s\n", gt2AddressToString(gt2GetRemoteIP(theConnection), gt2GetRemotePort(theConnection), anAddr)); len = ArrayLength(aUdp->mMsgHandlers); for (index = 0; index < len; index++) { GSUdpMsgHandler *aHandler = (GSUdpMsgHandler *)ArrayNth(aUdp->mMsgHandlers, index); if (aHandler->mPingReply) { gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Comment, "[Udp Engine] Passed to message handler\n"); aHandler->mPingReply(gt2GetRemoteIP(theConnection), gt2GetRemotePort(theConnection), (unsigned int)theLatency, aHandler->mUserData); return; } } if (aUdp->mAppPingReply) { gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Comment, "[Udp Engine] Passed to app\n"); aUdp->mAppPingReply(gt2GetRemoteIP(theConnection), gt2GetRemotePort(theConnection), (unsigned int)theLatency, aUdp->mAppUserData); } GSI_UNUSED(anAddr); }
/* SetElement * Sets the element at pos to the contents of elem */ static void SetElement(DArray array, const void *elem, int pos) { GS_ASSERT(array) // safety check -mj Oct 31st GS_ASSERT(elem) GS_ASSERT(array->elemsize) memcpy(ArrayNth(array,pos), elem, (size_t)array->elemsize); }
void *TableLookup(HashTable table, const void *elemKey) { int hash, itempos; hash = table->hashfn(elemKey, table->nbuckets); itempos = ArraySearch(table->buckets[hash], elemKey, table->compfn, 0, 0); if (itempos == NOT_FOUND) return NULL; else return ArrayNth(table->buckets[hash], itempos); }
GPResult gpiPeerSendMessages( GPConnection * connection, GPIPeer * peer ) { GPIBool connClosed; GPIMessage * message; GPResult result; GS_ASSERT(peer); if (!peer) return GP_NETWORK_ERROR; // Only send messages if there's nothing waiting in the output buffer. ////////////////////////////////////////////////////////////////////// if(peer->outputBuffer.len) return GP_NO_ERROR; // Send outgoing messages. ////////////////////////// while(ArrayLength(peer->messages)) { // Get the first message. ///////////////////////// message = (GPIMessage *)ArrayNth(peer->messages, 0); // Send as much as possible. //////////////////////////// //result = gpiSendFromBuffer(connection, peer->sock, &message->buffer, &connClosed, GPIFalse, "PR"); result = gpiSendBufferToPeer(connection, peer->ip, peer->port, &message->buffer, &connClosed, GPIFalse); if(connClosed || (result != GP_NO_ERROR)) { peer->state = GPI_PEER_DISCONNECTED; return GP_NO_ERROR; } // Did we not send it all? ////////////////////////// if(message->buffer.pos != message->buffer.len) break; // Remove the message. ////////////////////// ArrayDeleteAt(peer->messages, 0); } return GP_NO_ERROR; }
//////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // Lets the App and Message Handlers know a peer left void gsUdpClosedRoutingCB(GT2Connection theConnection, GT2CloseReason reason) { GSUdpEngineObject *aUdp = gsUdpEngineGetEngine(); GSUdpRemotePeer aRemotePeer; int index, len; GSUdpCloseReason aReason; char anAddr[GS_IP_ADDR_AND_PORT]; if (reason == GT2CommunicationError || reason == GT2SocketError) aReason = GS_UDP_CLOSED_BY_COMM_ERROR; else if (reason == GT2NotEnoughMemory) aReason = GS_UDP_CLOSED_BY_LOW_MEM; else aReason = (GSUdpCloseReason)reason; gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Comment, "[Udp Engine] Connection closed to %s\n", gt2AddressToString(gt2GetRemoteIP(theConnection), gt2GetRemotePort(theConnection), anAddr)); len = ArrayLength(aUdp->mMsgHandlers); for (index = 0; index < len; index++) { GSUdpMsgHandler *aHandler = (GSUdpMsgHandler *)ArrayNth(aUdp->mMsgHandlers, index); if (aHandler->mClosed) { gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Comment, "[Udp Engine] Connection closed: passed to message handler\n"); aHandler->mClosed(gt2GetRemoteIP(theConnection), gt2GetRemotePort(theConnection), aReason, aHandler->mUserData); } } if (aUdp->mAppClosed) { gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Comment, "[Udp Engine] Connection closed: passed to app\n"); aUdp->mAppClosed(gt2GetRemoteIP(theConnection), gt2GetRemotePort(theConnection), aReason, aUdp->mAppUserData); } aRemotePeer.mConnection = theConnection; index = ArraySearch(aUdp->mRemotePeers, &aRemotePeer, gsUdpRemotePeerCompare2, 0, 0); if (index != NOT_FOUND) { ArrayDeleteAt(aUdp->mRemotePeers, index); } GSI_UNUSED(anAddr); }
//////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // Lets the Message Handler and App know about network errors void gsUdpSocketError(GT2Socket theSocket) { int i, len; GSUdpEngineObject *aUdp = gsUdpEngineGetEngine(); gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Comment, "[Udp Engine] Socket error, passing to app and message handlers\n"); if (aUdp->mAppNetworkError) aUdp->mAppNetworkError(GS_UDP_NETWORK_ERROR, aUdp->mAppUserData); len = ArrayLength(aUdp->mMsgHandlers); for (i = 0; i < len; i++) { GSUdpMsgHandler *aMsgHandler = (GSUdpMsgHandler *)ArrayNth(aUdp->mMsgHandlers, i); if (aMsgHandler->mNetworkError) aMsgHandler->mNetworkError(GS_UDP_NETWORK_ERROR, aMsgHandler->mUserData); } GSI_UNUSED(theSocket); }
//////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // Any data received prompts the UDP layer to first find a higher level // message handler to handle the data. If there was no message handler // found, the data is passed to the higher level app. void gsUdpReceivedRoutingCB(GT2Connection theConnection, GT2Byte *theMessage, int theMessageLen, GT2Bool reliable) { GSUdpEngineObject *aUdp = gsUdpEngineGetEngine(); GSUdpMsgHandler aHandler; int index; char anAddr[GS_IP_ADDR_AND_PORT]; gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Comment, "[Udp Engine] Received data from %s\n", gt2AddressToString(gt2GetRemoteIP(theConnection), gt2GetRemotePort(theConnection), anAddr)); //If there is a handler, pass it to the handler //The header should not be stripped off if (theMessageLen >= GS_UDP_MSG_HEADER_LEN) { memcpy(aHandler.mHeader, theMessage, GS_UDP_MSG_HEADER_LEN); index = ArraySearch(aUdp->mMsgHandlers, &aHandler, gsUdpMsgHandlerCompare2, 0, 0); if (index != NOT_FOUND) { GSUdpMsgHandler *aHandlerFound = (GSUdpMsgHandler *)ArrayNth(aUdp->mMsgHandlers, index); if (aHandlerFound->mReceived) { gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Comment, "[Udp Engine] Passed to message handler\n"); aHandlerFound->mReceived(gt2GetRemoteIP(theConnection), gt2GetRemotePort(theConnection), theMessage + GS_UDP_MSG_HEADER_LEN, (unsigned int)(theMessageLen - GS_UDP_MSG_HEADER_LEN), reliable, aHandlerFound->mUserData); return; } } } if (aUdp->mAppRecvData) { gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Comment, "[Udp Engine] Passed to app\n"); aUdp->mAppRecvData(gt2GetRemoteIP(theConnection), gt2GetRemotePort(theConnection), theMessage, (unsigned int)theMessageLen, reliable, aUdp->mAppUserData); } GSI_UNUSED(anAddr); }
//////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // UDP Layer must be initialized // theIp and thePort cannot be 0 (Zero) // Accepts a Peer's request for communication // Should only be used by App GSUdpErrorCode gsUdpEngineAcceptPeer(unsigned int theIp, unsigned short thePort) { GSUdpRemotePeer aRemotePeer; GSUdpEngineObject *aUdp = gsUdpEngineGetEngine(); int index; GS_ASSERT(aUdp->mInitialized); GS_ASSERT(theIp); GS_ASSERT(thePort); if (!aUdp->mInitialized) { gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Debug, "[Udp Engine] Engine not initialized\n"); return GS_UDP_NETWORK_ERROR; } if (theIp == 0 || thePort == 0) { gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Debug, "[Udp Engine] Invalid parameter(s), check ip, port\n"); return GS_UDP_PARAMETER_ERROR; } aRemotePeer.mAddr = theIp; aRemotePeer.mPort = thePort; index = ArraySearch(aUdp->mRemotePeers, &aRemotePeer, gsUdpRemotePeerCompare, 0, 0); if (index != NOT_FOUND) { GT2ConnectionCallbacks aCallbacks; GSUdpRemotePeer *aPeerFound = (GSUdpRemotePeer *)ArrayNth(aUdp->mRemotePeers, index); aCallbacks.closed = gsUdpClosedRoutingCB; aCallbacks.connected = gsUdpConnectedRoutingCB; aCallbacks.ping = gsUdpPingRoutingCB; aCallbacks.received = gsUdpReceivedRoutingCB; gt2Accept(aPeerFound->mConnection, &aCallbacks); } return GS_UDP_NO_ERROR; }
GPResult gpiProcessNp(GPConnection * connection) { int i, ret=0; GPIConnection * iconnection = (GPIConnection*)*connection; npIdLookupTrans * transaction; // Check for uninitialized transaction darray ////////////////////////////////////////////// if (!iconnection->npTransactionList) return GP_NO_ERROR; // Need to process Sysutil for the Async lookups ///////////////////////////////////////////////// if (ArrayLength(iconnection->npTransactionList) > 0) cellSysutilCheckCallback(); // Loop through all current transactions, check if complete /////////////////////////////////////////////////////////// for (i=0; i < ArrayLength(iconnection->npTransactionList); i++) { // Grab next transaction in the list ///////////////////////////////////// transaction = (npIdLookupTrans *)ArrayNth(iconnection->npTransactionList, i); if (!transaction->npLookupDone) { if (sceNpLookupPollAsync(transaction->npTransId, &ret)==0) transaction->npLookupDone = gsi_true; } else { if (ret<0) { gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_HotError, "PS3AddToNpBlockList: sceNpLookupWaitAsync. ret = 0x%x\n", ret); if (ret == (int)SCE_NP_COMMUNITY_SERVER_ERROR_NO_SUCH_USER_NPID) { gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_HotError, "PS3AddToNpBlockList: Player '%s' is not an NP user.\n", transaction->npIdForAdd->handle.data); } } else { // Found an NpId, try to add ///////////////////////////// ret = sceNpBasicAddBlockListEntry(transaction->npIdForAdd); if (ret == (int)SCE_NP_BASIC_ERROR_BUSY) { // Oh nice, NP is too busy to help us.... keep on trying ///////////////////////////////////////////////////////// gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_Comment, "PS3AddToNpBlockList: SCE_NP_BASIC_ERROR_BUSY. continue trying to add to NP\n"); return GP_NO_ERROR; } else if ( ret < 0 ) { gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_HotError, "PS3AddToNpBlockList: sceNpBasicAddBlockListEntry() failed. ret = 0x%x\n", ret); } else { gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_Comment, "PS3AddToNpBlockList: Player '%s' added to NP Block list.\n", transaction->npIdForAdd->handle.data); } } ret = sceNpLookupDestroyTransactionCtx(transaction->npTransId); if (ret<0) { gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_HotError, "PS3AddToNpBlockList: sceNpLookupDestroyTransactionCtx() failed. ret = 0x%x\n", ret); } // Delete Transaction when its complete //////////////////////////////////////// ArrayDeleteAt(iconnection->npTransactionList, i); } } return GP_NO_ERROR; }
//////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // UDP Layer must be initialized // Sends a message to a peer using IP and Port // An empty header constitutes the app sending this message. // theIp and thePort cannot be 0 (Zero) // // WARNING: Messages should not be greater than the outgoing buffer size minus the header // and the 7 byte header for reliable messages (used for internal gt2 operations). Most // UDP fragmentation occurs if messages are bigger than 1500 bytes. Also, some routers are // known to drop those packets that are larger than 1500 bytes. The recommended outgoing // buffer size is the default (1460). So take that, and subtract 16 for message handler header // and reliable message header (if sending data reliably). // freeSpace = 1460 - 16 - 7 GSUdpErrorCode gsUdpEngineSendMessage(unsigned int theIp, unsigned short thePort, char theHeader[GS_UDP_MSG_HEADER_LEN], unsigned char *theMsg, unsigned int theMsgLen, gsi_bool theReliable) { GSUdpEngineObject *aUdp = gsUdpEngineGetEngine(); int aTotalMessageLen, index; GSUdpRemotePeer aRemotePeer, *aRemotePeerFound; GT2Byte *fullMessage; GT2Result aResult; GS_ASSERT(aUdp->mInitialized); GS_ASSERT(theIp); GS_ASSERT(thePort); if (!aUdp->mInitialized) { gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Debug, "[Udp Engine] Engine not initialized\n"); return GS_UDP_NETWORK_ERROR; } // Messages being sent with an empty header are treated as app messages if (!theHeader[0]) aTotalMessageLen = (int)theMsgLen; else aTotalMessageLen = (int)(GS_UDP_MSG_HEADER_LEN + theMsgLen); aRemotePeer.mAddr = theIp; aRemotePeer.mPort = thePort; index = ArraySearch(aUdp->mRemotePeers, &aRemotePeer, gsUdpRemotePeerCompare, 0, 0); if (index == NOT_FOUND) { char anAddr[GS_IP_ADDR_AND_PORT]; gt2AddressToString(theIp, thePort, anAddr); gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_WarmError, "[Udp Engine] address not found for sending message\n", anAddr); return GS_UDP_ADDRESS_ERROR; } else { aRemotePeerFound = (GSUdpRemotePeer *)ArrayNth(aUdp->mRemotePeers, index); } if (aTotalMessageLen > gt2GetOutgoingBufferSize(aRemotePeerFound->mConnection) && theReliable) { gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_WarmError, "[Udp Engine] Message Size too large, dropping message\n"); return GS_UDP_MSG_TOO_BIG; } fullMessage = (GT2Byte *)gsimalloc((unsigned long)aTotalMessageLen); memcpy(fullMessage, theHeader, GS_UDP_MSG_HEADER_LEN); memcpy(fullMessage + GS_UDP_MSG_HEADER_LEN, theMsg, theMsgLen); // Send the message // reliable messages will be kept in the outgoing buffers till they are sent aResult = gt2Send(aRemotePeerFound->mConnection, fullMessage, aTotalMessageLen, theReliable); gsifree(fullMessage); if (aResult != GT2Success) return GS_UDP_SEND_FAILED; return GS_UDP_NO_ERROR; }
/* FreeElement * Frees the element at position N in the array */ static void FreeElement(DArray array, int n) { if (array->elemfreefn != NULL) array->elemfreefn(ArrayNth(array,n)); }
//////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // UDP Layer must be initialized // theIp and thePort cannot be 0 (Zero) // Starts a request to open a communication channel with another peer based on // IP and port. GSUdpErrorCode gsUdpEngineStartTalkingToPeer(unsigned int theIp, unsigned short thePort, char theInitMsg[GS_UDP_MSG_HEADER_LEN], int timeOut) { char anAddr[GS_IP_ADDR_AND_PORT]; GSUdpRemotePeer aRemotePeer; GSUdpMsgHandler aHandler; GSUdpEngineObject *aUdp = gsUdpEngineGetEngine(); GT2ConnectionCallbacks aCallbacks; int index; GS_ASSERT(aUdp->mInitialized); GS_ASSERT(theIp); GS_ASSERT(thePort); if (!aUdp->mInitialized) { gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Debug, "[Udp Engine] Engine not initialized\n"); return GS_UDP_NETWORK_ERROR; } if (theIp == 0 || thePort == 0) { gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Debug, "[Udp Engine] Invalid parameter(s), check ip, port"); return GS_UDP_PARAMETER_ERROR; } aRemotePeer.mAddr = theIp; // In Network Byte Order for GT2 aRemotePeer.mPort = thePort; // In Host Byte Order for GT2 index = ArraySearch(aUdp->mRemotePeers, &aRemotePeer, gsUdpRemotePeerCompare, 0, 0); if (index != NOT_FOUND) { GSUdpRemotePeer *aPeerFound = (GSUdpRemotePeer *)ArrayNth(aUdp->mRemotePeers, index); GT2ConnectionState aState = gt2GetConnectionState(aPeerFound->mConnection); if (aState == GT2Connected) { gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Debug, "[Udp Engine] Engine is already talking to remote address\n"); return GS_UDP_ADDRESS_ALREADY_IN_USE; } else if (aState == GT2Connecting) { memcpy(aHandler.mInitialMsg, theInitMsg, GS_UDP_MSG_HEADER_LEN); index = ArraySearch(aUdp->mMsgHandlers, &aHandler, gsUdpMsgHandlerCompare, 0, 0); if (index != NOT_FOUND) { GSUdpMsgHandler *aHandlerFound = (GSUdpMsgHandler *)ArrayNth(aUdp->mMsgHandlers, index); ArrayAppend(aHandlerFound->mPendingConnections, aPeerFound); } } } else { gt2AddressToString(theIp, thePort, anAddr); aCallbacks.closed = gsUdpClosedRoutingCB; aCallbacks.connected = gsUdpConnectedRoutingCB; aCallbacks.ping = gsUdpPingRoutingCB; aCallbacks.received = gsUdpReceivedRoutingCB; // start the connect without blocking since we want the engine to be as asynchronous as possible gt2Connect(aUdp->mSocket, &aRemotePeer.mConnection, anAddr, (unsigned char *)theInitMsg, GS_UDP_MSG_HEADER_LEN, timeOut, &aCallbacks, GT2False); ArrayAppend(aUdp->mRemotePeers, &aRemotePeer); memcpy(aHandler.mInitialMsg, theInitMsg, GS_UDP_MSG_HEADER_LEN); index = ArraySearch(aUdp->mMsgHandlers, &aHandler, gsUdpMsgHandlerCompare, 0, 0); if (index != NOT_FOUND) { GSUdpRemotePeer *aRemotePeerPtr = (GSUdpRemotePeer *)ArrayNth(aUdp->mRemotePeers, ArrayLength(aUdp->mRemotePeers) - 1); GSUdpMsgHandler *aHandlerFound = (GSUdpMsgHandler *)ArrayNth(aUdp->mMsgHandlers, index); ArrayAppend(aHandlerFound->mPendingConnections, &aRemotePeerPtr); } else { aUdp->mAppPendingConnections++; } } return GS_UDP_NO_ERROR; }
void gpiRemovePeer( GPConnection * connection, GPIPeer * peer ) { GPIPeer * pprev; GPIConnection * iconnection = (GPIConnection*)*connection; GPIMessage * message; GS_ASSERT(peer != NULL); if (peer == NULL) return; GS_ASSERT(iconnection->peerList); if (iconnection->peerList == NULL) return; // Check if this is the first peer. /////////////////////////////////// if(iconnection->peerList == peer) { iconnection->peerList = peer->pnext; } else { // Find the previous peer. ////////////////////////// for(pprev = iconnection->peerList ; pprev->pnext != peer ; pprev = pprev->pnext) { if(pprev->pnext == NULL) { // Can't find this peer in the list! //////////////////////////////////// assert(0); gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_HotError, "Tried to remove peer not in list."); return; } } pprev->pnext = peer->pnext; } // Check for pending messages. ////////////////////////////// while(ArrayLength(peer->messages)) { // Get the next message. //////////////////////// message = (GPIMessage *)ArrayNth(peer->messages, 0); // Don't forward protocol messages. /////////////////////////////////// if(message->type < 100) gpiSendServerBuddyMessage(connection, peer->profile, message->type, message->buffer.buffer + message->start); // Remove the message. ////////////////////// ArrayDeleteAt(peer->messages, 0); } gpiDestroyPeer(connection, peer); }
//////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // When a peer has accepted a GT2Connection the UDP layer needs to let // higher level app or message handler know that it accepted the request to // to message a peer. void gsUdpConnectedRoutingCB(GT2Connection theConnection, GT2Result theResult, GT2Byte *theMessage, int theMessageLen) { GSUdpEngineObject *aUdp = gsUdpEngineGetEngine(); int aIndex, len; GSUdpErrorCode aCode; char anAddr[GS_IP_ADDR_AND_PORT]; switch(theResult) { case GT2NegotiationError: aCode = GS_UDP_REMOTE_ERROR; break; case GT2Rejected: aCode = GS_UDP_REJECTED; break; case GT2TimedOut: aCode = GS_UDP_TIMED_OUT; break; case GT2Success: aCode = GS_UDP_NO_ERROR; break; default: aCode = GS_UDP_UNKNOWN_ERROR; break; } if (theResult == GT2Rejected) { int aRemotePeerIdx; GSUdpRemotePeer aRemotePeer; aRemotePeer.mAddr = gt2GetRemoteIP(theConnection); aRemotePeer.mPort = gt2GetRemotePort(theConnection); aRemotePeerIdx = ArraySearch(aUdp->mRemotePeers, &aRemotePeer, gsUdpRemotePeerCompare, 0, 0); if (aRemotePeerIdx != NOT_FOUND) { gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Comment, "[Udp Engine] Connect rejected by %s\n", gt2AddressToString(gt2GetRemoteIP(theConnection), gt2GetRemotePort(theConnection), anAddr)); ArrayDeleteAt(aUdp->mRemotePeers, aRemotePeerIdx); } } len = ArrayLength(aUdp->mMsgHandlers); for (aIndex = 0; aIndex < len; aIndex++) { int aRemotePeerIdx; GSUdpRemotePeer aRemotePeer; GSUdpMsgHandler *aTempHandler = (GSUdpMsgHandler *)ArrayNth(aUdp->mMsgHandlers, aIndex); aRemotePeer.mAddr = gt2GetRemoteIP(theConnection); aRemotePeer.mPort = gt2GetRemotePort(theConnection); aRemotePeerIdx = ArraySearch(aTempHandler->mPendingConnections, &aRemotePeer, gsUdpRemotePeerCompare, 0, 0); if (aRemotePeerIdx != NOT_FOUND) { if (aTempHandler->mConnected) { gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Comment, "[Udp Engine] Passing connect result to message handler\n"); aTempHandler->mConnected(gt2GetRemoteIP(theConnection), gt2GetRemotePort(theConnection), aCode, theResult == GT2Rejected ? gsi_true : gsi_false, aTempHandler->mUserData); } ArrayDeleteAt(aTempHandler->mPendingConnections, aRemotePeerIdx); return; } } if (aUdp->mAppPendingConnections > 0) { if (aUdp->mAppConnected) { gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Comment, "[Udp Engine] Passing connect result to app\n"); aUdp->mAppConnected(gt2GetRemoteIP(theConnection),gt2GetRemotePort(theConnection), aCode, theResult == GT2Rejected ? gsi_true : gsi_false, aUdp->mAppUserData); } aUdp->mAppPendingConnections--; } GSI_UNUSED(theMessage); GSI_UNUSED(theMessageLen); GSI_UNUSED(anAddr); }