void gpiDestroyPeer( GPConnection * connection, GPIPeer * peer ) { #ifndef NOFILE // Cleanup any transfers that use this peer. //////////////////////////////////////////// gpiTransferPeerDestroyed(connection, peer); #endif //shutdown(peer->sock, 2); //closesocket(peer->sock); freeclear(peer->inputBuffer.buffer); freeclear(peer->outputBuffer.buffer); if(peer->messages) { ArrayFree(peer->messages); peer->messages = NULL; } freeclear(peer); GSI_UNUSED(connection); }
static GPIBool gpiDisconnectCleanupProfile( GPConnection * connection, GPIProfile * profile, void * data ) { GPIConnection * iconnection = (GPIConnection*)*connection; GSI_UNUSED(data); // Even if we cache buddy/block info, free it up to get rid of mem // leaks, just don't remove the profile until we save the cache. ////////////////////////////////////////////////////////////////// if(profile->buddyStatus) { profile->buddyOrBlockCache = gsi_true; freeclear(profile->buddyStatus->statusString); freeclear(profile->buddyStatus->locationString); freeclear(profile->buddyStatus); } if (profile->buddyStatusInfo) { profile->buddyOrBlockCache = gsi_true; freeclear(profile->buddyStatusInfo->richStatus); freeclear(profile->buddyStatusInfo->gameType); freeclear(profile->buddyStatusInfo->gameVariant); freeclear(profile->buddyStatusInfo->gameMapName); if (profile->buddyStatusInfo->extendedInfoKeys) { ArrayFree(profile->buddyStatusInfo->extendedInfoKeys); profile->buddyStatusInfo->extendedInfoKeys = NULL; } freeclear(profile->buddyStatusInfo); } if (profile->blocked) profile->buddyOrBlockCache = gsi_true; freeclear(profile->authSig); freeclear(profile->peerSig); profile->requestCount = 0; // Remove Profile if: // (there is no info to cache) or // (we only cache buddies/blocked and the user is not a buddy or a block) if ((!profile->cache) || (iconnection->infoCachingBuddyAndBlockOnly==GPITrue && !profile->buddyOrBlockCache)) { gpiRemoveProfile(connection, profile); return GPIFalse; } return GPITrue; }
GPResult gpiAuthBuddyRequest ( GPConnection * connection, GPProfile profile ) { GPIProfile * pProfile; GPIConnection * iconnection = (GPIConnection*)*connection; // Get the profile object. ////////////////////////// if(!gpiGetProfile(connection, profile, &pProfile)) Error(connection, GP_PARAMETER_ERROR, "Invalid profile."); // Check for a valid sig. ///////////////////////// if(!pProfile->authSig) Error(connection, GP_PARAMETER_ERROR, "Invalid profile."); // Send the request. //////////////////// CHECK_RESULT(gpiSendAuthBuddyRequest(connection, pProfile)); // freeclear the sig if no more requests. //////////////////////////////////// pProfile->requestCount--; if(!iconnection->infoCaching && (pProfile->requestCount <= 0)) { freeclear(pProfile->authSig); if(gpiCanFreeProfile(pProfile)) gpiRemoveProfile(connection, pProfile); } return GP_NO_ERROR; }
void gpiDestroyOperation( GPConnection * connection, GPIOperation * operation ) { GPIConnection * iconnection = (GPIConnection*)*connection; // Search? ////////// if(operation->type == GPI_PROFILE_SEARCH) { GPISearchData * data = (GPISearchData *)operation->data; // One less. //////////// iconnection->numSearches--; assert(iconnection->numSearches >= 0); // Close the socket. //////////////////// shutdown(data->sock, 2); closesocket(data->sock); // freeclear the buffers. //////////////////// freeclear(data->outputBuffer.buffer); freeclear(data->inputBuffer.buffer); } // freeclear the data. ///////////////// freeclear(operation->data); // freeclear the operation struct. ///////////////////////////// freeclear(operation); }
// gpiPeerRemoveOp: // Assumes the list is NOT NULL otherwise it returns. // Assumes the operation being passed in is on the queue. // Assumes non-null inputs! // Completed or Timed out Operations are deleted from queue by finding // the operation passed in. Removal of operations don't necessarily // happen in order. void gpiPeerRemoveOp(GPIPeer *peer, GPIPeerOp *operation) { GS_ASSERT(peer); GS_ASSERT(operation); if (!peer || !operation) { gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_WarmError, "Peer operation not removed"); return; } GS_ASSERT(peer->peerOpQueue.opList != NULL); if (peer->peerOpQueue.opList == NULL) { gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_WarmError, "Peer operation not removed"); return; } if (peer->peerOpQueue.first == peer->peerOpQueue.last && peer->peerOpQueue.first == operation) { peer->peerOpQueue.opList = peer->peerOpQueue.first = peer->peerOpQueue.last = operation->next; } else if (peer->peerOpQueue.first == operation) { peer->peerOpQueue.first = peer->peerOpQueue.first->next; peer->peerOpQueue.opList = peer->peerOpQueue.first; } else { GPIPeerOp *aPrevOp = NULL; for(aPrevOp = peer->peerOpQueue.first ; aPrevOp->next != operation ; aPrevOp = aPrevOp->next) { if(aPrevOp->next == NULL) { // Can't find this peer in the list! //////////////////////////////////// gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_HotError, "Tried to remove peer operation not in list."); return; } } aPrevOp->next = operation->next; } gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_Notice, "Peer operation removed"); freeclear(operation); }
GPResult gpiBuddyHandleKeyRequest(GPConnection *connection, GPIPeer *peer) { char *message; // get all the keys and put them in the message part of bm ////////////////////////////////////////////////////////// CHECK_RESULT(gpiSaveKeysToBuffer(connection, &message)); // Done in case we haven't set any keys if (message == NULL) message = ""; CHECK_RESULT(gpiSendBuddyMessage(connection, peer->profile, GPI_BM_KEYS_REPLY, message, GP_DONT_ROUTE, NULL)); if (strcmp(message, "")!= 0) freeclear(message); return GP_NO_ERROR; }
GPResult gpiRecvToBuffer( GPConnection * connection, SOCKET sock, GPIBuffer * inputBuffer, int * bytesRead, GPIBool * connClosed, char id[3] ) { char * buffer; int len; int size; int rcode; int total; GPIBool closed; assert(sock != INVALID_SOCKET); assert(inputBuffer != NULL); assert(bytesRead != NULL); assert(connClosed != NULL); // Init locals. /////////////// buffer = inputBuffer->buffer; len = inputBuffer->len; size = inputBuffer->size; total = 0; closed = GPIFalse; do { // Check if the buffer needs to be resized. /////////////////////////////////////////// if((len + GPI_READ_SIZE) > size) { size = (len + GPI_READ_SIZE); buffer = (char *)gsirealloc(buffer, (unsigned int)size + 1); if(buffer == NULL) Error(connection, GP_MEMORY_ERROR, "Out of memory."); } // Read from the network. rcode = recv(sock, &buffer[len], size - len, 0); if(gsiSocketIsError(rcode)) { int error = GOAGetLastError(sock); if((error != WSAEWOULDBLOCK) && (error != WSAEINPROGRESS) && (error != WSAETIMEDOUT) ) { Error(connection, GP_NETWORK_ERROR, "There was an error reading from a socket."); } } else if(rcode == 0) { // Check for a closed connection. ///////////////////////////////// closed = GPITrue; gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Network, GSIDebugLevel_Comment, "RECVXXXX(%s): Connection closed\n", id); } else { #if defined(GPI_DUMP_NET_TRAFFIC) && defined(GSI_COMMON_DEBUG) { static int recvCount; char *buf = (char *)gsimalloc((size_t)(rcode + 1)); memcpy(buf, &buffer[len], (size_t)rcode); buf[rcode] = '\0'; gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Network, GSIDebugLevel_RawDump, "RECV%04d(%s): %s\n", recvCount++, id, buf); freeclear(buf); } #elif defined(GSI_COMMON_DEBUG) { static int recvCount; gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Network, GSIDebugLevel_RawDump, "RECV%04d(%s): %d\n", recvCount++, id, rcode); } #endif // Update the buffer len. ///////////////////////// len += rcode; // Update the total. //////////////////// total += rcode; } buffer[len] = '\0'; } while((rcode >= 0) && !closed && (total < (128 * 1024))); if(total) { gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Network, GSIDebugLevel_RawDump, "RECVTOTL(%s): %d\n", id, total); } // Set output stuff. //////////////////// inputBuffer->buffer = buffer; inputBuffer->len = len; inputBuffer->size = size; *bytesRead = total; *connClosed = closed; GSI_UNUSED(id); //to get rid of codewarrior warnings return GP_NO_ERROR; }
static GPResult gpiSendData( GPConnection * connection, SOCKET sock, const char * buffer, int bufferLen, GPIBool * closed, int * sent, char id[3] ) { int rcode; rcode = send(sock, buffer, bufferLen, 0); if(gsiSocketIsError(rcode)) { rcode = GOAGetLastError(sock); if((rcode != WSAEWOULDBLOCK) && (rcode != WSAEINPROGRESS) && (rcode != WSAETIMEDOUT) ) { // handle peer connections specially if((id[0] == 'P') && (id[1] == 'R')) return GP_NETWORK_ERROR; CallbackError(connection, GP_NETWORK_ERROR, GP_NETWORK, "There was an error sending on a socket."); } *sent = 0; *closed = GPIFalse; } else if(rcode == 0) { gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Network, GSIDebugLevel_Comment, "SENDXXXX(%s): Connection closed\n", id); *sent = 0; *closed = GPITrue; } else { #if defined(GPI_DUMP_NET_TRAFFIC) && defined(GSI_COMMON_DEBUG) { static int sendCount; char *buf = (char *)gsimalloc((size_t)(rcode + 1)); memcpy(buf, buffer, (size_t)rcode); buf[rcode] = '\0'; gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Network, GSIDebugLevel_RawDump, "SENT%04d(%s): %s\n", sendCount++, id, buf); freeclear(buf); } #elif defined(GSI_COMMON_DEBUG) { static int sendCount; gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Network, GSIDebugLevel_RawDump, "SENT%04d(%s): %d\n", sendCount++, id, rcode); } #endif *sent = rcode; *closed = GPIFalse; } return GP_NO_ERROR; }
void gpiDisconnect( GPConnection * connection, GPIBool tellServer ) { GPIConnection * iconnection = (GPIConnection*)*connection; GPIPeer * peer; GPIPeer * delPeer; GPIBool connClosed; // Check if we're already disconnected. // PANTS|05.15.00 /////////////////////////////////////// if(iconnection->connectState == GPI_DISCONNECTED) return; // Skip most of this stuff if we never actually connected. // PANTS|05.16.00 ////////////////////////////////////////////////////////// if(iconnection->connectState != GPI_NOT_CONNECTED) { // Are we connected? //////////////////// if(tellServer && (iconnection->connectState == GPI_CONNECTED)) { // Send the disconnect. /////////////////////// gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\logout\\\\sesskey\\"); gpiAppendIntToBuffer(connection, &iconnection->outputBuffer, iconnection->sessKey); gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\final\\"); } // Always flush remaining messages. // PANTS|05.16.00 /////////////////////////////////// gpiSendFromBuffer(connection, iconnection->cmSocket, &iconnection->outputBuffer, &connClosed, GPITrue, "CM"); // Cleanup the connection. ////////////////////////// if(iconnection->cmSocket != INVALID_SOCKET) { shutdown(iconnection->cmSocket, 2); closesocket(iconnection->cmSocket); iconnection->cmSocket = INVALID_SOCKET; } if(/*iconnection->peerSocket != INVALID_SOCKET*/ gsUdpEngineIsInitialized()) { //shutdown(iconnection->peerSocket, 2); //closesocket(iconnection->peerSocket); //iconnection->peerSocket = INVALID_SOCKET; gsUdpEngineRemoveMsgHandler(iconnection->mHeader); if (gsUdpEngineNoMoreMsgHandlers() && gsUdpEngineNoApp()) gsUdpEngineShutdown(); } // We're disconnected. ////////////////////// iconnection->connectState = GPI_DISCONNECTED; // Don't keep the userid/profileid. /////////////////////////////////// iconnection->userid = 0; iconnection->profileid = 0; } // freeclear all the memory. /////////////////////// freeclear(iconnection->socketBuffer.buffer); freeclear(iconnection->inputBuffer); freeclear(iconnection->outputBuffer.buffer); freeclear(iconnection->updateproBuffer.buffer); freeclear(iconnection->updateuiBuffer.buffer); while(iconnection->operationList != NULL) gpiRemoveOperation(connection, iconnection->operationList); iconnection->operationList = NULL; for(peer = iconnection->peerList ; peer != NULL ; ) { delPeer = peer; peer = peer->pnext; gpiDestroyPeer(connection, delPeer); } iconnection->peerList = NULL; // Cleanup buddies. // This is not optimal - because we can't continue the mapping // after freeing a profile, we need to start it all over again. /////////////////////////////////////////////////////////////// while(!gpiProfileMap(connection, gpiDisconnectCleanupProfile, NULL)) { }; }
// Freeing up transaction list darray void gpiNpTransactionListFree(void *element) { npIdLookupTrans *aTrans = (npIdLookupTrans *)element; freeclear(aTrans->npIdForAdd); }
GPResult gpiDeleteBuddy( GPConnection * connection, GPProfile profile, GPIBool sendServerRequest ) { GPIProfile * pProfile; GPIConnection * iconnection = (GPIConnection*)*connection; int index; // Get the profile object. ////////////////////////// if(!gpiGetProfile(connection, profile, &pProfile)) Error(connection, GP_PARAMETER_ERROR, "Invalid profile."); // Check that this is a buddy. ////////////////////////////// // Removed - 092404 BED - User could be a buddy even though we don't have the status //if(!pProfile->buddyStatus) // Error(connection, GP_PARAMETER_ERROR, "Profile not a buddy."); // Send the request. //////////////////// if (GPITrue == sendServerRequest) { gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\delbuddy\\"); gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\sesskey\\"); gpiAppendIntToBuffer(connection, &iconnection->outputBuffer, iconnection->sessKey); gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\delprofileid\\"); gpiAppendIntToBuffer(connection, &iconnection->outputBuffer, pProfile->profileId); gpiAppendStringToBuffer(connection, &iconnection->outputBuffer, "\\final\\"); } // Need to fix up the buddy indexes. //////////////////////////////////// if (pProfile->buddyStatus) { index = pProfile->buddyStatus->buddyIndex; assert(index >= 0); freeclear(pProfile->buddyStatus->statusString); freeclear(pProfile->buddyStatus->locationString); freeclear(pProfile->buddyStatus); if(gpiCanFreeProfile(pProfile)) gpiRemoveProfile(connection, pProfile); iconnection->profileList.numBuddies--; assert(iconnection->profileList.numBuddies >= 0); #ifndef _PS2 gpiProfileMap(connection, gpiFixBuddyIndices, (void *)(unsigned long)index); #else gpiProfileMap(connection, gpiFixBuddyIndices, (void *)index); #endif } if (pProfile->buddyStatusInfo) { index = pProfile->buddyStatusInfo->buddyIndex; assert(index >= 0); freeclear(pProfile->buddyStatusInfo->richStatus); freeclear(pProfile->buddyStatusInfo->gameType); freeclear(pProfile->buddyStatusInfo->gameVariant); freeclear(pProfile->buddyStatusInfo->gameMapName); freeclear(pProfile->buddyStatusInfo); if (pProfile->buddyStatusInfo->extendedInfoKeys) { ArrayFree(pProfile->buddyStatusInfo->extendedInfoKeys); pProfile->buddyStatusInfo->extendedInfoKeys = NULL; } if(gpiCanFreeProfile(pProfile)) gpiRemoveProfile(connection, pProfile); iconnection->profileList.numBuddies--; assert(iconnection->profileList.numBuddies >= 0); #ifndef _PS2 gpiProfileMap(connection, gpiFixBuddyIndices, (void *)(unsigned long)index); #else gpiProfileMap(connection, gpiFixBuddyIndices, (void *)index); #endif } return GP_NO_ERROR; }
GPResult gpiProcessRecvBuddyMessage( GPConnection * connection, const char * input ) { char buffer[4096]; int type; int profileid; time_t date; GPICallback callback; GPIProfile * profile; GPIBuddyStatus * buddyStatus; char intValue[16]; char * str; unsigned short port; int productID; GPIConnection * iconnection = (GPIConnection*)*connection; char strTemp[max(GP_STATUS_STRING_LEN, GP_LOCATION_STRING_LEN)]; // Check the type of bm. //////////////////////// if(!gpiValueForKey(input, "\\bm\\", buffer, sizeof(buffer))) CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server."); type = atoi(buffer); // Get the profile this is from. //////////////////////////////// if(!gpiValueForKey(input, "\\f\\", buffer, sizeof(buffer))) CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server."); profileid = atoi(buffer); // Get the time. //////////////// if(!gpiValueForKey(input, "\\date\\", buffer, sizeof(buffer))) date = time(NULL); else date = atoi(buffer); // What type of message is this? //////////////////////////////// switch(type) { case GPI_BM_MESSAGE: // Call the callback. ///////////////////// callback = iconnection->callbacks[GPI_RECV_BUDDY_MESSAGE]; if(callback.callback != NULL) { GPRecvBuddyMessageArg * arg; arg = (GPRecvBuddyMessageArg *)gsimalloc(sizeof(GPRecvBuddyMessageArg)); if(arg == NULL) Error(connection, GP_MEMORY_ERROR, "Out of memory."); if(!gpiValueForKey(input, "\\msg\\", buffer, sizeof(buffer))) CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server."); #ifndef GSI_UNICODE arg->message = (char *)gsimalloc(strlen(buffer) + 1); if(arg->message == NULL) Error(connection, GP_MEMORY_ERROR, "Out of memory."); strcpy(arg->message, buffer); arg->profile = (GPProfile)profileid; arg->date = (unsigned int)date; #else arg->message = (unsigned short*)gsimalloc(strlen(buffer)*2+2); if(arg->message == NULL) Error(connection, GP_MEMORY_ERROR, "Out of memory."); UTF8ToUCS2String(buffer, arg->message); arg->profile = (GPProfile)profileid; arg->date = (unsigned int)date; #endif CHECK_RESULT(gpiAddCallback(connection, callback, arg, NULL, GPI_ADD_MESSAGE)); } break; case GPI_BM_UTM: // Call the callback. ///////////////////// callback = iconnection->callbacks[GPI_RECV_BUDDY_UTM]; if(callback.callback != NULL) { GPRecvBuddyUTMArg * arg; arg = (GPRecvBuddyUTMArg *)gsimalloc(sizeof(GPRecvBuddyUTMArg)); if(arg == NULL) Error(connection, GP_MEMORY_ERROR, "Out of memory."); if(!gpiValueForKey(input, "\\msg\\", buffer, sizeof(buffer))) CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server."); #ifndef GSI_UNICODE arg->message = (char *)gsimalloc(strlen(buffer) + 1); if(arg->message == NULL) Error(connection, GP_MEMORY_ERROR, "Out of memory."); strcpy(arg->message, buffer); arg->profile = (GPProfile)profileid; arg->date = (unsigned int)date; #else arg->message = (unsigned short*)gsimalloc(strlen(buffer)*2+2); if(arg->message == NULL) Error(connection, GP_MEMORY_ERROR, "Out of memory."); UTF8ToUCS2String(buffer, arg->message); arg->profile = (GPProfile)profileid; arg->date = (unsigned int)date; #endif CHECK_RESULT(gpiAddCallback(connection, callback, arg, NULL, GPI_ADD_BUDDYUTM)); } break; case GPI_BM_REQUEST: // Get the profile, adding if needed. ///////////////////////////////////// profile = gpiProfileListAdd(connection, profileid); if(!profile) Error(connection, GP_MEMORY_ERROR, "Out of memory."); // Get the reason. ////////////////// if(!gpiValueForKey(input, "\\msg\\", buffer, sizeof(buffer))) CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server."); // Find where the sig starts. ///////////////////////////// str = strstr(buffer, "|signed|"); if(str == NULL) CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server."); // Get the sig out of the message. ////////////////////////////////// *str = '\0'; str += 8; if(strlen(str) != 32) CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server."); freeclear(profile->authSig); profile->authSig = goastrdup(str); profile->requestCount++; // Call the callback. ///////////////////// callback = iconnection->callbacks[GPI_RECV_BUDDY_REQUEST]; if(callback.callback != NULL) { GPRecvBuddyRequestArg * arg; arg = (GPRecvBuddyRequestArg *)gsimalloc(sizeof(GPRecvBuddyRequestArg)); if(arg == NULL) Error(connection, GP_MEMORY_ERROR, "Out of memory."); #ifndef GSI_UNICODE strzcpy(arg->reason, buffer, GP_REASON_LEN); #else UTF8ToUCS2String(buffer, arg->reason); #endif arg->profile = (GPProfile)profileid; arg->date = (unsigned int)date; CHECK_RESULT(gpiAddCallback(connection, callback, arg, NULL, GPI_ADD_BUDDDYREQUEST)); } break; case GPI_BM_AUTH: // call the callback callback = iconnection->callbacks[GPI_RECV_BUDDY_AUTH]; if(callback.callback != NULL) { GPRecvBuddyAuthArg * arg; arg = (GPRecvBuddyAuthArg *)gsimalloc(sizeof(GPRecvBuddyAuthArg)); if (arg == NULL) Error(connection, GP_MEMORY_ERROR, "Out of memory."); arg->profile = (GPProfile)profileid; arg->date = (unsigned int)date; CHECK_RESULT(gpiAddCallback(connection, callback, arg, NULL, GPI_ADD_BUDDYAUTH)); } break; case GPI_BM_REVOKE: // call the callback callback = iconnection->callbacks[GPI_RECV_BUDDY_REVOKE]; if(callback.callback != NULL) { GPRecvBuddyRevokeArg * arg; arg = (GPRecvBuddyRevokeArg *)gsimalloc(sizeof(GPRecvBuddyRevokeArg)); if (arg == NULL) Error(connection, GP_MEMORY_ERROR, "Out of memory."); arg->profile = (GPProfile)profileid; arg->date = (unsigned int)date; CHECK_RESULT(gpiAddCallback(connection, callback, arg, NULL, GPI_ADD_BUDDYREVOKE)); } break; case GPI_BM_STATUS: // Get the profile, adding if needed. ///////////////////////////////////// profile = gpiProfileListAdd(connection, profileid); if(!profile) Error(connection, GP_MEMORY_ERROR, "Out of memory."); // Make sure profile wasn't blocked prior to getting the status update ////////////////////////////////////////////////////////////////////// if (!profile->blocked) { // This is a buddy. /////////////////// if(!profile->buddyStatus) { profile->buddyStatus = (GPIBuddyStatus *)gsimalloc(sizeof(GPIBuddyStatus)); if(!profile->buddyStatus) Error(connection, GP_MEMORY_ERROR, "Out of memory."); memset(profile->buddyStatus, 0, sizeof(GPIBuddyStatus)); if (profile->buddyStatusInfo) { profile->buddyStatus->buddyIndex = profile->buddyStatusInfo->buddyIndex; gpiRemoveBuddyStatusInfo(profile->buddyStatusInfo); profile->buddyStatusInfo = NULL; } else profile->buddyStatus->buddyIndex = iconnection->profileList.numBuddies++; } // Get the buddy status. //////////////////////// buddyStatus = profile->buddyStatus; // Get the msg. /////////////// if(!gpiValueForKey(input, "\\msg\\", buffer, sizeof(buffer))) CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server."); // Get the status. ////////////////// if(!gpiValueForKey(buffer, "|s|", intValue, sizeof(intValue))) { CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server."); } else { buddyStatus->status = (GPEnum)atoi(intValue); } // Get the status string. ///////////////////////// freeclear(buddyStatus->statusString); if(!gpiValueForKey(buffer, "|ss|", strTemp, GP_STATUS_STRING_LEN)) strTemp[0] = '\0'; buddyStatus->statusString = goastrdup(strTemp); if(!buddyStatus->statusString) Error(connection, GP_MEMORY_ERROR, "Out of memory."); // Get the location string. /////////////////////////// freeclear(buddyStatus->locationString); if(!gpiValueForKey(buffer, "|ls|", strTemp, GP_LOCATION_STRING_LEN)) strTemp[0] = '\0'; buddyStatus->locationString = goastrdup(strTemp); if(!buddyStatus->locationString) Error(connection, GP_MEMORY_ERROR, "Out of memory."); // Get the ip. ////////////// if(!gpiValueForKey(buffer, "|ip|", intValue, sizeof(intValue))) buddyStatus->ip = 0; else buddyStatus->ip = htonl((unsigned int)atoi(intValue)); // Get the port. //////////////// if(!gpiValueForKey(buffer, "|p|", intValue, sizeof(intValue))) buddyStatus->port = 0; else { port = (unsigned short)atoi(intValue); buddyStatus->port = htons(port); } // Get the quiet mode flags. //////////////////////////// if(!gpiValueForKey(buffer, "|qm|", intValue, sizeof(intValue))) buddyStatus->quietModeFlags = GP_SILENCE_NONE; else buddyStatus->quietModeFlags = (GPEnum)atoi(intValue); // Call the callback. ///////////////////// callback = iconnection->callbacks[GPI_RECV_BUDDY_STATUS]; if(callback.callback != NULL) { GPRecvBuddyStatusArg * arg; arg = (GPRecvBuddyStatusArg *)gsimalloc(sizeof(GPRecvBuddyStatusArg)); if(arg == NULL) Error(connection, GP_MEMORY_ERROR, "Out of memory."); arg->profile = (GPProfile)profileid; arg->index = buddyStatus->buddyIndex; arg->date = (unsigned int)date; CHECK_RESULT(gpiAddCallback(connection, callback, arg, NULL, GPI_ADD_STATUS)); } } break; case GPI_BM_INVITE: // Get the msg. /////////////// if(!gpiValueForKey(input, "\\msg\\", buffer, sizeof(buffer))) CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server."); // Find the productid. ////////////////////// str = strstr(buffer, "|p|"); if(str == NULL) CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server."); // Skip the |p|. //////////////// str += 3; if(str[0] == '\0') CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server."); // Get the productid. ///////////////////// productID = atoi(str); // Find the location string (optional - older versions won't have) str = strstr(buffer, "|l|"); if(str != NULL) strzcpy(strTemp, (str+3), sizeof(strTemp)); else strTemp[0] = '\0'; // no location, set to empty string // Call the callback. ///////////////////// callback = iconnection->callbacks[GPI_RECV_GAME_INVITE]; if(callback.callback != NULL) { GPRecvGameInviteArg * arg; arg = (GPRecvGameInviteArg *)gsimalloc(sizeof(GPRecvGameInviteArg)); if(arg == NULL) Error(connection, GP_MEMORY_ERROR, "Out of memory."); arg->profile = (GPProfile)profileid; arg->productID = productID; #ifdef GSI_UNICODE AsciiToUCS2String(strTemp, arg->location); #else strcpy(arg->location, strTemp); #endif CHECK_RESULT(gpiAddCallback(connection, callback, arg, NULL, 0)); } break; case GPI_BM_PING: // Get the msg. /////////////// if(!gpiValueForKey(input, "\\msg\\", buffer, sizeof(buffer))) CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server."); // Send back a pong. //////////////////// gpiSendBuddyMessage(connection, profileid, GPI_BM_PONG, "1", 0, NULL); break; #ifndef NOFILE case GPI_BM_PONG: // Lets the transfers handle this. ////////////////////////////////// gpiTransfersHandlePong(connection, profileid, NULL); break; #endif } return GP_NO_ERROR; }
GPResult gpiProcessRecvBuddyStatusInfo(GPConnection *connection, const char *input) { char buffer[1024]; int profileid; time_t date; GPICallback callback; GPIProfile * profile; GPIBuddyStatusInfo * buddyStatusInfo; GPIConnection * iconnection = (GPIConnection*)*connection; // This is what the message should look like. Its broken up for easy viewing. // // "\bsi\\state\\profile\\bip\\bport\\hostip\\hprivip\" // "\qport\\hport\\sessflags\\rstatus\\gameType\" // "\gameVnt\\gameMn\\product\\qmodeflags\" //////////////////////////////// date = time(NULL); // Get the buddy's profile //////////////////////////////// if(!gpiValueForKey(input, "\\profile\\", buffer, sizeof(buffer))) CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server."); profileid = atoi(buffer); // Get the profile from the SDK's list, adding it if needed. ///////////////////////////////////// profile = gpiProfileListAdd(connection, profileid); if(!profile) Error(connection, GP_MEMORY_ERROR, "Out of memory."); // Make sure profile wasn't blocked prior to getting the status update ////////////////////////////////////////////////////////////////////// if (!profile->blocked) { // This is a buddy. /////////////////// if(!profile->buddyStatusInfo) { profile->buddyStatusInfo = (GPIBuddyStatusInfo *)gsimalloc(sizeof(GPIBuddyStatusInfo)); if(!profile->buddyStatusInfo) Error(connection, GP_MEMORY_ERROR, "Out of memory."); memset(profile->buddyStatusInfo, 0, sizeof(GPIBuddyStatusInfo)); if (profile->buddyStatus) { profile->buddyStatusInfo->buddyIndex = profile->buddyStatus->buddyIndex; gpiRemoveBuddyStatus(profile->buddyStatus); profile->buddyStatus = NULL; } else profile->buddyStatusInfo->buddyIndex = iconnection->profileList.numBuddies++; profile->buddyStatusInfo->extendedInfoKeys = ArrayNew(sizeof(GPIKey), GPI_INITIAL_NUM_KEYS, gpiStatusInfoKeyFree); if (!profile->buddyStatusInfo->extendedInfoKeys) Error(connection, GP_MEMORY_ERROR, "Out of memory."); } // extract the buddy status information and // fill in appropriate information. ///////////////////////////////////////////// buddyStatusInfo = profile->buddyStatusInfo; if (!gpiValueForKey(input, "\\state\\", buffer, sizeof(buffer))) CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server."); buddyStatusInfo->statusState = (GPEnum)atoi(buffer); if (!gpiValueForKey(input, "\\bip\\", buffer, sizeof(buffer))) CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server."); buddyStatusInfo->buddyIp = htonl((unsigned int)atoi(buffer)); if (!gpiValueForKey(input, "\\bport\\", buffer, sizeof(buffer))) CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server."); buddyStatusInfo->buddyPort = (unsigned short)atoi(buffer); if (!gpiValueForKey(input, "\\hostip\\", buffer, sizeof(buffer))) CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server."); buddyStatusInfo->hostIp = htonl((unsigned int)atoi(buffer)); if (!gpiValueForKey(input, "\\hprivip\\", buffer, sizeof(buffer))) CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server."); buddyStatusInfo->hostPrivateIp = htonl((unsigned int)atoi(buffer)); if (!gpiValueForKey(input, "\\qport\\", buffer, sizeof(buffer))) CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server."); buddyStatusInfo->queryPort = (unsigned short)atoi(buffer); if (!gpiValueForKey(input, "\\hport\\", buffer, sizeof(buffer))) CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server."); buddyStatusInfo->hostPort = (unsigned short)atoi(buffer); if (!gpiValueForKey(input, "\\sessflags\\", buffer, sizeof(buffer))) CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server."); buddyStatusInfo->sessionFlags = (unsigned int)atoi(buffer); freeclear(buddyStatusInfo->richStatus); if (!gpiValueForKey(input, "\\rstatus\\", buffer, sizeof(buffer))) CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server."); buddyStatusInfo->richStatus = goastrdup(buffer); freeclear(buddyStatusInfo->gameType); if (!gpiValueForKey(input, "\\gameType\\", buffer, sizeof(buffer))) CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server."); buddyStatusInfo->gameType = goastrdup(buffer); freeclear(buddyStatusInfo->gameVariant); if (!gpiValueForKey(input, "\\gameVnt\\", buffer, sizeof(buffer))) CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server."); buddyStatusInfo->gameVariant = goastrdup(buffer); freeclear(buddyStatusInfo->gameMapName); if (!gpiValueForKey(input, "\\gameMn\\", buffer, sizeof(buffer))) CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server."); buddyStatusInfo->gameMapName = goastrdup(buffer); if (!gpiValueForKey(input, "\\product\\", buffer, sizeof(buffer))) CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server."); buddyStatusInfo->productId = (int)atoi(buffer); if (!gpiValueForKey(input, "\\qmodeflags\\", buffer, sizeof(buffer))) CallbackFatalError(connection, GP_NETWORK_ERROR, GP_PARSE, "Unexpected data was received from the server."); buddyStatusInfo->quietModeFlags = (GPEnum)atoi(buffer); callback = iconnection->callbacks[GPI_RECV_BUDDY_STATUS]; if (callback.callback != NULL) { GPRecvBuddyStatusArg *anArg; anArg = (GPRecvBuddyStatusArg *)gsimalloc(sizeof(GPRecvBuddyStatusArg)); if (anArg == NULL) Error(connection, GP_MEMORY_ERROR, "Out of memory."); anArg->date = (unsigned int)date; anArg->index = buddyStatusInfo->buddyIndex; anArg->profile = profileid; CHECK_RESULT(gpiAddCallback(connection, callback, anArg, NULL, 0)); } } return GP_NO_ERROR; }
static void gpiFreeMessage(void * elem) { GPIMessage * message = (GPIMessage *)elem; freeclear(message->buffer.buffer); }
//FUNCTIONS /////////// static GPResult gpiProcessPeerInitiatingConnection( GPConnection * connection, GPIPeer * peer ) { GPIConnection * iconnection = (GPIConnection*)*connection; //int state; char * str = NULL; //int len; GPIBool connClosed; GPIProfile * pProfile; GPResult result; GSUdpPeerState aPeerState; GS_ASSERT(peer); if (!peer) return GP_NETWORK_ERROR; GS_ASSERT(peer->state != GPI_PEER_DISCONNECTED && peer->state != GPI_PEER_NOT_CONNECTED); if (peer->state == GPI_PEER_DISCONNECTED || peer->state == GPI_PEER_NOT_CONNECTED) return GP_NETWORK_ERROR; // Check the state. /////////////////// switch(peer->state) { case GPI_PEER_GETTING_SIG: // Do nothing - we're waiting for getinfo to get the sig. ///////////////////////////////////////////////////////// break; case GPI_PEER_GOT_SIG: { // Start the connect. ///////////////////// gsDebugFormat(GSIDebugCat_GP, GSIDebugType_State, GSIDebugLevel_Verbose, "Got the peer signature for profileid: %d\n", peer->profile); CHECK_RESULT(gpiPeerStartConnect(connection, peer)); break; } case GPI_PEER_CONNECTING: { // Check if the connect finished. ///////////////////////////////// /* CHECK_RESULT(gpiCheckSocketConnect(connection, peer->sock, &state)); if(state == GPI_DISCONNECTED) { Error(connection, GP_NETWORK_ERROR, "Error connecting to a peer."); } */ gsUdpEngineGetPeerState(peer->ip, peer->port, &aPeerState); if(aPeerState == GS_UDP_PEER_CONNECTED) { GPIPeer * pcurr; GPIBool freePeerSig = GPITrue; // Get the profile object. ////////////////////////// if(!gpiGetProfile(connection, peer->profile, &pProfile)) Error(connection, GP_NETWORK_ERROR, "Error connecting to a peer."); // Send the auth. ///////////////// gpiAppendStringToBuffer(connection, &peer->outputBuffer, "\\auth\\"); gpiAppendStringToBuffer(connection, &peer->outputBuffer, "\\pid\\"); gpiAppendIntToBuffer(connection, &peer->outputBuffer, iconnection->profileid); gpiAppendStringToBuffer(connection, &peer->outputBuffer, "\\nick\\"); gpiAppendStringToBuffer(connection, &peer->outputBuffer, iconnection->nick); gpiAppendStringToBuffer(connection, &peer->outputBuffer, "\\sig\\"); gpiAppendStringToBuffer(connection, &peer->outputBuffer, pProfile->peerSig); gpiAppendStringToBuffer(connection, &peer->outputBuffer, "\\final\\"); // Are there any other peers still connecting? ////////////////////////////////////////////// for(pcurr = iconnection->peerList ; pcurr != NULL ; pcurr = pcurr->pnext) if((pcurr->profile == peer->profile) && (pcurr != peer)) if(pcurr->state <= GPI_PEER_CONNECTING) freePeerSig = GPIFalse; // freeclear it? /////////// if(freePeerSig) { freeclear(pProfile->peerSig); if(gpiCanFreeProfile(pProfile)) gpiRemoveProfile(connection, pProfile); } // Update the state. //////////////////// peer->state = GPI_PEER_WAITING; } break; } case GPI_PEER_WAITING: { // Check for a response. //////////////////////// //CHECK_RESULT(gpiRecvToBuffer(connection, peer->sock, &peer->inputBuffer, &len, &connClosed, "PR")); // Check for a final. ///////////////////// if (peer->inputBuffer.buffer) str = strstr(peer->inputBuffer.buffer, "\\final\\"); if(str != NULL) { str[0] = '\0'; str += 7; // Was it rejected? /////////////////// if(strncmp(peer->inputBuffer.buffer, "\\anack\\", 7) == 0) { // Rejected. //////////// peer->nackCount++; // Is this more than once? ////////////////////////// if(peer->nackCount > 1) { // we shouldn't reach this case unless there is a problem with // the server when getting a buddy's signature // Give up already. /////////////////// Error(connection, GP_NETWORK_ERROR, "Error getting buddy authorization."); } // Try getting the latest sig. ////////////////////////////// CHECK_RESULT(gpiPeerGetSig(connection, peer)); } else if(strncmp(peer->inputBuffer.buffer, "\\aack\\", 6) != 0) { // Unknown message. /////////////////// Error(connection, GP_NETWORK_ERROR, "Error parsing buddy message."); } // The connection has been established. /////////////////////////////////////// peer->state = GPI_PEER_CONNECTED; peer->inputBuffer.len = 0; } break; } // code should not reach here. default: break; } // Send stuff that needs to be sent. //////////////////////////////////// if(peer->outputBuffer.len > 0) { //result = gpiSendFromBuffer(connection, peer->sock, &peer->outputBuffer, &connClosed, GPITrue, "PR"); result = gpiSendBufferToPeer(connection, peer->ip, peer->port, &peer->outputBuffer, &connClosed, GPITrue); if(connClosed || (result != GP_NO_ERROR)) peer->state = GPI_PEER_DISCONNECTED; } return GP_NO_ERROR; }