// Used to check for any timed out peer operations // assumes peer is not NULL // makes no assumption of the operation queue void gpiCheckTimedOutPeerOperations(GPConnection * connection, GPIPeer *peer) { GPIPeerOp *anIterator = peer->peerOpQueue.first; GS_ASSERT(peer); if (!peer) return; while (anIterator && anIterator != peer->peerOpQueue.last) { if (anIterator->state != GPI_PEER_OP_STATE_FINISHED && current_time() > anIterator->timeout && anIterator->callback) { // currently only one type of peer operation exists // when it's found, we need to provide the application with // a result of no data if (anIterator->type == GPI_BM_KEYS_REQUEST) { GPICallback callback; GPGetBuddyStatusInfoKeysArg *arg = (GPGetBuddyStatusInfoKeysArg *)gsimalloc(sizeof(GPGetBuddyStatusInfoKeysArg)); 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); } // The peer operation is removed regardless of type gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_Notice, "Peer operation timed out"); gpiPeerRemoveOp(peer, anIterator); } anIterator = anIterator->next; } }
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; }