// A certain number of bytes are expected in the payload, according to the header. // This function tries to read that many bytes, and inserts them into an OTPayload object. // From there, a simple method call extracts the message, we return true, and the message // gets added to our internal list for processing. bool OTClientConnection::ProcessType1Cmd(u_header & theCMD, OTMessage & theMessage) { // At this point, the checksum has already validated. // Might as well get the PAYLOAD next. // int err; uint32_t nread, lSize = theCMD.fields.size; // Make sure our byte-order is correct here. // theCMD.fields.size = ntohl(theCMD.fields.size); // I was doing this twice!! This is already done when the header is first read. // setup the buffer we are reading into OTPayload thePayload; nread = thePayload.ReadBytesFrom(m_Buffer, lSize); /* // actually read the payload from the socket into the buffer. for (nread = 0; nread < theCMD.fields.size; nread += err) { err = SFSocketRead(m_pSocket, (unsigned char *)thePayload.GetPayloadPointer() + nread, theCMD.fields.size - nread); // if we don't read anything more, stop reading and move on if (err <= 0) break; } */ // TODO fix the buffering so that if a complete command has not yet been received, it saves the other // bytes instead of discarding them. For now I'll just sleep for a second to make sure the entire command // was received. // sleep(1); // ------------------------------------------------------------ // Try to interpret the command number. // Right now we support signed messages and encrypted envelopes containing // signed messages. switch (theCMD.fields.command_id) { case TYPE_1_CMD_1: OTLog::Output(2, "Received Type 1 CMD 1:\nThere is a signed OTMessage in the payload.\n"); break; case TYPE_1_CMD_2: OTLog::Output(2, "Received Type 1 CMD 2:\n" "There is an encrypted OTEnvelope (containing signed OTMessage) in the payload.\n"); break; default: OTLog::vError("Received unexpected command number %d in OTClientConnection::ProcessType1Cmd\n", theCMD.fields.command_id); break; } // ------------------------------------------------------------ // Hm, that's weird. It was a 0 size payload message. DoS? if (theCMD.fields.size == 0) { OTLog::Output(2, "(The payload was a 0 size.)\n"); return true; } // Uh-oh, somehow the number of bytes read was less than what we expected... else if (nread < theCMD.fields.size) { // TODO: Verify that the amount read matched the amount expected // if not, we have a problem that needs to be handled. // Long term solution is to buffer the data as a comes in and just // add it to the buffer. // Then if we don't have the complete message yet, we just come around next // time some data is read, and we add that to the buffer, THEN we check to see // if there are enough bytes yet read to match the amount expected according to // the header. // // Until I can do that, I'm not yet TRULY asynchronous. TODO: lookup a good buffer class. OTLog::Error("Number of bytes read did NOT match size in header.\n"); return false; } else OTLog::vOutput(2, "Loaded a payload, size: %d\n", theCMD.fields.size); // ------------------------------------------------------------ // Okay so now we've received the expected size from the socket. Let's transfer it // into an object type that we can manipulate here in code. (Message or Envelope.) // a signed OTMessage if (TYPE_1_CMD_1 == theCMD.fields.command_id) { #ifdef _WIN32 if (OTPAYLOAD_GetMessage(thePayload, theMessage)) #else if (thePayload.GetMessage(theMessage)) #endif { OTLog::Output(2, "Successfully retrieved payload message...\n"); if (theMessage.ParseRawFile()) { OTLog::Output(2, "Successfully parsed payload message.\n"); return true; } else { OTLog::Error("Error parsing message.\n"); return false; } } else { OTLog::Error("Error retrieving message from payload.\n"); return false; } } // A base64-encoded envelope, encrypted, and containing a signed message. else if (TYPE_1_CMD_2 == theCMD.fields.command_id) { OTEnvelope theEnvelope; if (thePayload.GetEnvelope(theEnvelope)) { OTLog::Output(2, "Successfully retrieved envelope from payload...\n"); OTString strEnvelopeContents; // Decrypt the Envelope. if (m_pServer && theEnvelope.Open(m_pServer->GetServerNym(), strEnvelopeContents)) { // All decrypted, now let's load the results into an OTMessage. // No need to call theMessage.ParseRawFile() after, since // LoadContractFromString handles it. // if (strEnvelopeContents.Exists() && theMessage.LoadContractFromString(strEnvelopeContents)) { OTLog::Output(2, "Success loading message out of the envelope contents and parsing it.\n"); return true; } else { OTLog::Error("Error loading message from envelope contents.\n"); return false; } } else { OTLog::Error("Unable to open envelope.\n"); return false; } } else { OTLog::Error("Error retrieving message from payload.\n"); return false; } } return true; }