// true == YES, DISCONNECT m_pSocket, something must have gone wrong. // false == NO, do NOT disconnect m_pSocket, everything went wonderfully! // bool ProcessMessage_ZMQ(OTServer & theServer, const std::string & str_Message, std::string & str_Reply) { if (str_Message.size() < 1) return false; const char * szFunc = "ProcessMessage_ZMQ"; // -------------------- // return value. std::string resultString = ""; // Whatever we put in this string is what will get returned. // First we grab the client's message OTASCIIArmor ascMessage; ascMessage.MemSet(str_Message.data(), str_Message.size()); // ------------------ // // OTPayload thePayload; // thePayload.SetPayloadSize(str_Message.size()); // memcpy((void*)thePayload.GetPayloadPointer(), str_Message.data(), str_Message.size()); // ---------------------------------------------------------------------- // OTLog::vError("Envelope: \n%s\n Size: %ld\n", ascMessage.Get(), ascMessage.GetLength()); bool bReturnVal = false; // "false" == no, do NOT disconnect. No errors. ("True" means YES, DISCONNECT!) OTMessage theMsg, theReply; // we'll need these in a sec... // OTEnvelope theEnvelope(ascMessage); OTEnvelope theEnvelope; if (false == theEnvelope.SetAsciiArmoredData(ascMessage)) { OTLog::vError("%s: Error retrieving envelope.\n", szFunc); bReturnVal = true; // disconnect the socket! } else { // Now the base64 is decoded and the envelope is in binary form again. OTLog::vOutput(2, "%s: Successfully retrieved envelope from ZMQ message...\n", szFunc); OTString strEnvelopeContents; // OTString strPubkeyPath("TESTPUBKEY.txt"); // theServer.GetServerNym().SavePublicKey(strPubkeyPath); // Decrypt the Envelope. if (false == theEnvelope.Open(theServer.GetServerNym(), strEnvelopeContents)) // now strEnvelopeContents contains the decoded message. { OTLog::vError("%s: Unable to open envelope.\n", szFunc); bReturnVal = true; // disconnect the socket! } else { // All decrypted--now let's load the results into an OTMessage. // No need to call theMsg.ParseRawFile() after, since // LoadContractFromString handles it. // if (strEnvelopeContents.Exists() && theMsg.LoadContractFromString(strEnvelopeContents)) { theReply.m_strCommand.Format("@%s", theMsg.m_strCommand.Get()); theReply.m_strNymID = theMsg.m_strNymID; // UserID theReply.m_strServerID = theMsg.m_strServerID; // ServerID, a hash of the server contract. theReply.m_bSuccess = false; // The default reply. In fact this is probably superfluous. // In case you want to see all the incoming messages... // OTLog::vOutput(0, "%s\n\n", strEnvelopeContents.Get()); // By constructing this without a socket, I put it in ZMQ mode, instead of tcp/ssl. OTClientConnection theClient(theServer); // By optionally passing in &theClient, the client Nym's public key will be // set on it whenever verification is complete. (So for the reply, I'll // have the key and thus I'll be able to encrypt reply to the recipient.) if (false == theServer.ProcessUserCommand(theMsg, theReply, &theClient)) { const OTString s1(theMsg), s2(theReply); OTLog::vOutput(0, "%s: Unable to process user command.\n\n ********** " "REQUEST:\n\n%s\n\n ********** RESPONSE:\n\n%s\n\n", szFunc, s1.Get(), s2.Get()); // NOTE: normally you would even HAVE a true or false if we're in this block. ProcessUserCommand() // is what tries to process a command and then sets false if/when it fails. Until that point, you // wouldn't get any server reply. I'm now changing this slightly, so you still get a reply (defaulted // to success==false.) That way if a client needs to re-sync his request number, he will get the false // and therefore know to resync the # as his next move, vs being stuck with no server reply (and thus // stuck with a bad socket.) // We sign the reply here, but not in the else block, since it's already signed in cases where // ProcessUserCommand() is a success, by the time that call returns. theReply.m_bSuccess = false; // Since the process call definitely failed, I'm making sure this here is definitely set to false (even though it probably was already.) theReply.SignContract(theServer.GetServerNym()); theReply.SaveContract(); } else // At this point the reply is ready to go, and theClient has the public key of the recipient... OTLog::vOutput(1, "%s: Successfully processed user command: %s.\n", szFunc, theMsg.m_strCommand.Get()); // ------------------------------------------------- // The transaction is now processed (or not), and the server's reply message is in theReply. // Let's seal it up to the recipient's nym (in an envelope) and send back to the user... // OTEnvelope theRecipientEnvelope; bool bSealed = theClient.SealMessageForRecipient(theReply, theRecipientEnvelope); if (false == bSealed) { OTLog::vOutput(0, "%s: Unable to seal envelope. (No reply will be sent.)\n", szFunc); bReturnVal = true; // disconnect the socket! } else { // OTPayload theReplyPayload; // theReplyPayload.SetEnvelope(theRecipientEnvelope); // resultString = ascReply.Get(); // resultString.assign(theReplyPayload.GetPayloadPointer(), theReplyPayload.GetPayloadSize()); OTASCIIArmor ascReply; if (theRecipientEnvelope.GetAsciiArmoredData(ascReply)) resultString.assign(ascReply.Get(), ascReply.GetLength()); } } else { OTLog::vError("%s: Error loading message from envelope contents:\n\n%s\n\n", szFunc, strEnvelopeContents.Get()); bReturnVal = true; // disconnect the socket! } } } // ---------------------------------------------------------------------- str_Reply = resultString; return bReturnVal; } // ProcessMessage_ZMQ