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; }