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 gpiBuddyHandleKeyReply(GPConnection *connection, GPIPeer *peer, char *buffer) { GPIProfile *pProfile; // Get the profile object to store the keys internally ////////////////////////////////////////////////////// if(!gpiGetProfile(connection, peer->profile, &pProfile)) Error(connection, GP_PARAMETER_ERROR, "Invalid profile."); // calculate the B64Decoded string len if (strcmp(buffer, "") == 0) { GPIPeerOp *anIterator; for (anIterator = peer->peerOpQueue.first; anIterator != NULL; anIterator = anIterator->next) if (anIterator->type == GPI_BM_KEYS_REQUEST) break; if (!anIterator) { return GP_NO_ERROR; } else if (anIterator->type == GPI_BM_KEYS_REQUEST && anIterator->callback) { GPGetBuddyStatusInfoKeysArg *arg = (GPGetBuddyStatusInfoKeysArg *)gsimalloc(sizeof(GPGetBuddyStatusInfoKeysArg)); GPICallback callback; callback.callback = anIterator->callback; callback.param = anIterator->userData; arg->keys = NULL; arg->numKeys = 0; arg->values = NULL; arg->profile = peer->profile; gpiAddCallback(connection, callback, arg, NULL, 0); gpiPeerRemoveOp(peer, anIterator); } } else { int decodedLen = 0, index = 0, numKeys, i; char keyName[512]; char keyVal[512]; char decodeKey[512]; char decodeVal[512]; gsi_char **keys; gsi_char **values; GPIPeerOp *anIterator; char *checkKey = NULL; // start by getting the number of keys gpiReadKeyAndValue(connection, buffer, &index, keyName, keyVal); // do not continue further if the header is missing if (strcmp(keyName, "keys") != 0) CallbackError(connection, GP_NETWORK_ERROR, GP_PARSE, "Error reading keys reply message"); numKeys = atoi(keyVal); if (numKeys == 0) { GPIPeerOp *anIterator; for (anIterator = peer->peerOpQueue.first; anIterator != NULL; anIterator = anIterator->next) if (anIterator->type == GPI_BM_KEYS_REQUEST) break; if (!anIterator) { return GP_NO_ERROR; } else if (anIterator->type == GPI_BM_KEYS_REQUEST && anIterator->callback) { GPGetBuddyStatusInfoKeysArg *arg = (GPGetBuddyStatusInfoKeysArg *)gsimalloc(sizeof(GPGetBuddyStatusInfoKeysArg)); GPICallback callback; callback.callback = anIterator->callback; callback.param = anIterator->userData; arg->keys = NULL; arg->numKeys = 0; arg->values = NULL; arg->profile = peer->profile; gpiAddCallback(connection, callback, arg, NULL, 0); gpiPeerRemoveOp(peer, anIterator); } } else { keys = (gsi_char **)gsimalloc(sizeof(gsi_char *) * numKeys); values = (gsi_char **)gsimalloc(sizeof(gsi_char *) * numKeys); for (i = 0; i < numKeys; i++) { gpiReadKeyAndValue(connection, buffer, &index, keyName, keyVal); B64Decode(keyName, decodeKey, (int)strlen(keyName), &decodedLen, 2); decodeKey[decodedLen] = '\0'; B64Decode(keyVal, decodeVal, (int)strlen(keyVal), &decodedLen, 2); decodeVal[decodedLen] = '\0'; #ifdef GSI_UNICODE keys[i] = UTF8ToUCS2StringAlloc(decodeKey); values[i]= UTF8ToUCS2StringAlloc(decodeVal); #else keys[i] = goastrdup(decodeKey); values[i] = goastrdup(decodeVal); #endif if (gpiStatusInfoCheckKey(connection, pProfile->buddyStatusInfo->extendedInfoKeys, decodeKey, &checkKey) == GP_NO_ERROR && checkKey == NULL) { gpiStatusInfoAddKey(connection, pProfile->buddyStatusInfo->extendedInfoKeys, decodeKey, decodeVal); } else { gpiStatusInfoSetKey(connection, pProfile->buddyStatusInfo->extendedInfoKeys, decodeKey, decodeVal); } } for (anIterator = peer->peerOpQueue.first; anIterator != NULL; anIterator = anIterator->next) if (anIterator->type == GPI_BM_KEYS_REQUEST) break; if (!anIterator) { return GP_NO_ERROR; } else if (anIterator->type == GPI_BM_KEYS_REQUEST && anIterator->callback) { GPICallback callback; GPGetBuddyStatusInfoKeysArg *arg = (GPGetBuddyStatusInfoKeysArg *)gsimalloc(sizeof(GPGetBuddyStatusInfoKeysArg)); callback.callback = anIterator->callback; callback.param = anIterator->userData; // allocate a key array that points to each extended info key for that player arg->numKeys = numKeys; arg->keys = keys; arg->values = values; arg->profile = peer->profile; gpiAddCallback(connection, callback, arg, NULL, GPI_ADD_BUDDYKEYS); gpiPeerRemoveOp(peer, anIterator); } } } return GP_NO_ERROR; }
GPResult gpiPeerStartConnect( GPConnection * connection, GPIPeer * peer ) { //int rcode; //struct sockaddr_in address; GPIProfile * profile; GPIConnection * iconnection = (GPIConnection*)*connection; GSUdpErrorCode anError; // Get the profile object. ////////////////////////// if(!gpiGetProfile(connection, peer->profile, &profile)) Error(connection, GP_NETWORK_ERROR, "Error connecting to a peer."); /* // Create the socket. ///////////////////// peer->sock = socket(AF_INET, SOCK_STREAM, 0); if(peer->sock == INVALID_SOCKET) CallbackError(connection, GP_NETWORK_ERROR, GP_NETWORK, "There was an error creating a socket."); // Make it non-blocking. //////////////////////// rcode = SetSockBlocking(peer->sock, 0); if(rcode == 0) CallbackError(connection, GP_NETWORK_ERROR, GP_NETWORK, "There was an error making a socket non-blocking."); // Bind the socket. /////////////////// // BD: PS2 Insock has bug with binding to port 0 // No sockets after the first will be able to bind memset(&address, 0, sizeof(address)); address.sin_family = AF_INET; rcode = bind(peer->sock, (struct sockaddr *)&address, sizeof(struct sockaddr_in)); if (gsiSocketIsError(rcode)) CallbackError(connection, GP_NETWORK_ERROR, GP_NETWORK, "There was an error binding a socket."); // Set the socket sizes. //////////////////////// gpiSetPeerSocketSizes(peer->sock); // Connect the socket. ////////////////////// memset(&address, 0, sizeof(address)); address.sin_family = AF_INET; address.sin_addr.s_addr = profile->buddyStatus->ip; address.sin_port = (gsi_u16)profile->buddyStatus->port; rcode = connect(peer->sock, (struct sockaddr *)&address, sizeof(struct sockaddr_in)); if (gsiSocketIsError(rcode)) { int error = GOAGetLastError(peer->sock); if((error != WSAEWOULDBLOCK) && (error != WSAEINPROGRESS) && (error != WSAETIMEDOUT) ) { CallbackFatalError(connection, GP_NETWORK_ERROR, GP_NETWORK, "There was an error connecting a socket."); } } */ if (profile->buddyStatusInfo) { GSUdpPeerState aPeerState; gsUdpEngineGetPeerState(profile->buddyStatusInfo->buddyIp , profile->buddyStatusInfo->buddyPort, &aPeerState); if (aPeerState != GS_UDP_PEER_CONNECTED || aPeerState != GS_UDP_PEER_CONNECTING) { anError = gsUdpEngineStartTalkingToPeer(profile->buddyStatusInfo->buddyIp , profile->buddyStatusInfo->buddyPort, iconnection->mHeader, GPI_PEER_TIMEOUT); if (anError != GS_UDP_ADDRESS_ALREADY_IN_USE) CallbackError(connection, GP_NETWORK_ERROR, GP_NETWORK, "There was an error starting communication with a peer."); } peer->ip = profile->buddyStatusInfo->buddyIp; peer->port = profile->buddyStatusInfo->buddyPort; } // We're waiting for the connect to complete. ///////////////////////////////////////////// peer->state = GPI_PEER_CONNECTING; return GP_NO_ERROR; }
GPResult gpiSendBuddyMessage( GPConnection * connection, int profileid, int type, const char * message, int sendOption, GPIPeerOp *peerOp ) { GPIPeer * peer; GPIProfile * profile; //GPIConnection *iconnection = (GPIConnection *)*connection; peer = gpiGetPeerByProfile(connection, profileid); if(!peer) { // Check if we should send this through the server. //////////////////////////////////////////////////// if(!gpiGetProfile(connection, profileid, &profile) || (!profile->buddyStatusInfo || !profile->buddyStatusInfo->buddyPort)) { if (sendOption == GP_DONT_ROUTE) return GP_NETWORK_ERROR; return gpiSendServerBuddyMessage(connection, profileid, type, message); } // Create a new peer connection for this message. ///////////////////////////////////////////////// peer = gpiAddPeer(connection, profileid, GPITrue); if(!peer) return GP_MEMORY_ERROR; // Check if we need a sig. ////////////////////////// if(!profile->peerSig) { // Get the sig. /////////////// CHECK_RESULT(gpiPeerGetSig(connection, peer)); } else { // Try to connect to the peer. ////////////////////////////// CHECK_RESULT(gpiPeerStartConnect(connection, peer)); } } else if (peer->state == GPI_PEER_DISCONNECTED) { if (gpiGetProfile(connection, profileid, &profile)) { // clear the buddy port to prevent future messages from // being sent via UDP layer if (profile->buddyStatusInfo) profile->buddyStatusInfo->buddyPort = 0; // send the message through the server if (sendOption == GP_DONT_ROUTE) return GP_NETWORK_ERROR; if (type < 100) return gpiSendServerBuddyMessage(connection, profileid, type, message); } } if (peerOp) { gpiPeerAddOp(peer, peerOp); } // Copy the message. //////////////////// CHECK_RESULT(gpiPeerAddMessage(connection, peer, type, message)); return GP_NO_ERROR; }
//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; }