Ejemplo n.º 1
0
unsigned int httpParseResponseHdr(WspHttpParms_t *parmPtr, const char *rspHeader)
{
   unsigned int rc = SML_ERR_OK;

   XPTDEBUG(("    httpParseResponseHdr(%lx, %s)\n", (unsigned long) parmPtr, rspHeader));

   rc = initializeResponseParms(parmPtr, rspHeader);

   if (rc != SML_ERR_OK)
      return rc;

   rc = validateResponse(parmPtr);

   return rc;
} /* End httpParseResponseHdr */
Ejemplo n.º 2
0
void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD login_params)
{
	try
	{
	LLSD printable_params = login_params;
	//if(printable_params.has("params") 
	//	&& printable_params["params"].has("passwd")) 
	//{
	//	printable_params["params"]["passwd"] = "*******";
	//}
    LL_DEBUGS("LLLogin") << "Entering coroutine " << LLCoros::instance().getName(self)
                        << " with uri '" << uri << "', parameters " << printable_params << LL_ENDL;

	// Arriving in SRVRequest state
    LLEventStream replyPump("SRVreply", true);
    // Should be an array of one or more uri strings.

    LLSD rewrittenURIs;
    {
        LLEventTimeout filter(replyPump);
        sendProgressEvent("offline", "srvrequest");

        // Request SRV record.
        LL_DEBUGS("LLLogin") << "Requesting SRV record from " << uri << LL_ENDL;

        // *NOTE:Mani - Completely arbitrary default timeout value for SRV request.
		F32 seconds_to_timeout = 5.0f;
		if(login_params.has("cfg_srv_timeout"))
		{
			seconds_to_timeout = login_params["cfg_srv_timeout"].asReal();
		}

        // If the SRV request times out (e.g. EXT-3934), simulate response: an
        // array containing our original URI.
        LLSD fakeResponse(LLSD::emptyArray());
        fakeResponse.append(uri);
		filter.eventAfter(seconds_to_timeout, fakeResponse);

		std::string srv_pump_name = "LLAres";
		if(login_params.has("cfg_srv_pump"))
		{
			srv_pump_name = login_params["cfg_srv_pump"].asString();
		}

		// Make request
        LLSD request;
        request["op"] = "rewriteURI";
        request["uri"] = uri;
        request["reply"] = replyPump.getName();
        rewrittenURIs = postAndWait(self, request, srv_pump_name, filter);
    } // we no longer need the filter

    LLEventPump& xmlrpcPump(LLEventPumps::instance().obtain("LLXMLRPCTransaction"));
    // EXT-4193: use a DIFFERENT reply pump than for the SRV request. We used
    // to share them -- but the EXT-3934 fix made it possible for an abandoned
    // SRV response to arrive just as we were expecting the XMLRPC response.
    LLEventStream loginReplyPump("loginreply", true);

    // Loop through the rewrittenURIs, counting attempts along the way.
    // Because of possible redirect responses, we may make more than one
    // attempt per rewrittenURIs entry.
    LLSD::Integer attempts = 0;
    for (LLSD::array_const_iterator urit(rewrittenURIs.beginArray()),
             urend(rewrittenURIs.endArray());
         urit != urend; ++urit)
    {
        LLSD request(login_params);
        request["reply"] = loginReplyPump.getName();
        request["uri"] = *urit;
        std::string status;

        // Loop back to here if login attempt redirects to a different
        // request["uri"]
        for (;;)
        {
            ++attempts;
            LLSD progress_data;
            progress_data["attempt"] = attempts;
            progress_data["request"] = request;
			if(progress_data["request"].has("params")
				&& progress_data["request"]["params"].has("passwd"))
			{
				progress_data["request"]["params"]["passwd"] = "*******";
			}
            sendProgressEvent("offline", "authenticating", progress_data);

            // We expect zero or more "Downloading" status events, followed by
            // exactly one event with some other status. Use postAndWait() the
            // first time, because -- at least in unit-test land -- it's
            // possible for the reply to arrive before the post() call
            // returns. Subsequent responses, of course, must be awaited
            // without posting again.
            for (mAuthResponse = validateResponse(loginReplyPump.getName(),
                                 postAndWait(self, request, xmlrpcPump, loginReplyPump, "reply"));
                 mAuthResponse["status"].asString() == "Downloading";
                 mAuthResponse = validateResponse(loginReplyPump.getName(),
                                     waitForEventOn(self, loginReplyPump)))
            {
                // Still Downloading -- send progress update.
                sendProgressEvent("offline", "downloading");
            }
				 
			LL_DEBUGS("LLLogin") << "Auth Response: " << mAuthResponse << LL_ENDL;
            status = mAuthResponse["status"].asString();

            // Okay, we've received our final status event for this
            // request. Unless we got a redirect response, break the retry
            // loop for the current rewrittenURIs entry.
            if (!(status == "Complete" &&
                  mAuthResponse["responses"]["login"].asString() == "indeterminate"))
            {
                break;
            }

			sendProgressEvent("offline", "indeterminate", mAuthResponse["responses"]);

            // Here the login service at the current URI is redirecting us
            // to some other URI ("indeterminate" -- why not "redirect"?).
            // The response should contain another uri to try, with its
            // own auth method.
            request["uri"] = mAuthResponse["responses"]["next_url"].asString();
            request["method"] = mAuthResponse["responses"]["next_method"].asString();
        } // loop back to try the redirected URI

        // Here we're done with redirects for the current rewrittenURIs
        // entry.
        if (status == "Complete")
        {
            // StatusComplete does not imply auth success. Check the
            // actual outcome of the request. We've already handled the
            // "indeterminate" case in the loop above.
            if (mAuthResponse["responses"]["login"].asString() == "true")
            {
                sendProgressEvent("online", "connect", mAuthResponse["responses"]);
            }
            else
            {
                sendProgressEvent("offline", "fail.login", mAuthResponse["responses"]);
            }
            return;             // Done!
        }
        // If we don't recognize status at all, trouble
        if (! (status == "CURLError"
               || status == "XMLRPCError"
               || status == "OtherError"))
        {
            LL_ERRS("LLLogin") << "Unexpected status from " << xmlrpcPump.getName() << " pump: "
                               << mAuthResponse << LL_ENDL;
            return;
        }

        // Here status IS one of the errors tested above.
    } // Retry if there are any more rewrittenURIs.

    // Here we got through all the rewrittenURIs without succeeding. Tell
    // caller this didn't work out so well. Of course, the only failure data
    // we can reasonably show are from the last of the rewrittenURIs.

	// *NOTE: The response from LLXMLRPCListener's Poller::poll method returns an
	// llsd with no "responses" node. To make the output from an incomplete login symmetrical 
	// to success, add a data/message and data/reason fields.
	LLSD error_response;
	error_response["reason"] = mAuthResponse["status"];
	error_response["errorcode"] = mAuthResponse["errorcode"];
	error_response["message"] = mAuthResponse["error"];
	if(mAuthResponse.has("certificate"))
	{
		error_response["certificate"] = mAuthResponse["certificate"];
	}
	sendProgressEvent("offline", "fail.login", error_response);
	}
	catch (...) {
		llerrs << "login exception caught" << llendl; 
	}
}
Ejemplo n.º 3
0
int CommsHandler::process(uint8_t *responseBuffer, uint16_t responseBufferLen)
{
  if (commsPtr == NULL) {
    errno = errorCommsNotSet;
    return false;
  }
  
  bool validResponse = false;
  errno = errorNoError;
  
  commsPtr->poll();
  
  switch (state) {
  case stateWaitingForMessages:
    if (!stack.isEmpty()) {
      messageLen = stack.read(messageBuffer, messageBufferLen);
      if (messageLen) {
	bytesSent = 0;
	state = statePowerUp;

	if (commsBlockSize) {
	  // Append null characters to fill a complete block
	  // const uint8_t xrfBlockSize = 12;
	  uint8_t remainder = messageLen % commsBlockSize;
	  if (remainder) {
	    uint16_t newLen = messageLen + (commsBlockSize - remainder);
	    if (newLen <= messageBufferLen) {
	      memset(messageBuffer + messageLen, 0, commsBlockSize - remainder);
	      messageLen = newLen;
	    }
	  }
	}
      }
    }
    break;

  case statePowerUp:
    if (commsPtr->powerOn())
      state = sendingData;
    break;

  case sendingData:
    // Send each byte individually. At present
    // HardwareSerial.write() waits until the buffer has room but
    // in future it might return immediately with a return value of
    // zero.
    if (bytesSent == 0 && verbosity)
      AWPacket::printPacket(messageBuffer, messageLen, console);
    
    if (bytesSent == 0)
      commsPtr->messageStart();
    
    {
      size_t bytesToSend = commsPtr->messageWriteSize();
      if (bytesToSend == 0)
	bytesToSend = messageLen;
      bytesSent += commsPtr->write(messageBuffer + bytesSent, bytesToSend);
    }
    
    if (bytesSent == messageLen) {
      commsPtr->messageEnd();
      responseLen = 0;
      responseTimeout.start(responseTimeout_ms, AsyncDelay::MILLIS);
      responsePacketLen = 65535; // Use maximum value until we know
      state = stateWaitingForResponse;
    }
    break;

  case stateWaitingForResponse:
    if (responseTimeout.isExpired()) {
      Serial.println("Message timeout");
      errno = errorResponseTimeout;

      ++ messagesWithoutAck;
      uint8_t maxMessagesNoAck
	= eeprom_read_byte((uint8_t*)EEPROM_MAX_MESSAGES_NO_ACK); 
      if (maxMessagesNoAck && messagesWithoutAck >= maxMessagesNoAck) {
	Serial.println("Reboot due to timeout"); // DEBUG
	delay(1000);
	xboot_reset();
	//wdt_enable(WDTO_1S);
	//while (1)
	//  ;
      }
      
      // Put message back into queue if retries not exceeded
      AWPacket failedPacket(messageBuffer, messageLen);
      if (failedPacket.getRetries() < maxRetries) {
	failedPacket.incrementRetries();
	// Update the signature for new retries
	failedPacket.setKey(key, keyLen);
	failedPacket.putSignature(messageBuffer, messageBufferLen);

	messageLen = 0;
	stack.write(messageBuffer, AWPacket::getPacketLength(messageBuffer));
      }
      else {
	Serial.print("Too many retries: ");
	AWPacket::printPacket(messageBuffer, messageBufferLen, Serial);
      }
      state = stateTimedOut;
      break;
    }

    commsPtr->checkForResponse();
    if (int avail = commsPtr->available()) {
      if (responseLen >= responseBufferLen) {
	errno = errorBufferTooSmall;
	messageLen = 0;
	state = stateWaitingForMessages;
	break;
      }

      for (int i = avail; i; --i) {
	uint8_t b = commsPtr->read();
	responseBuffer[responseLen++] = b;
      }

      if (validateResponse(responseBuffer, responseLen)) {
	// The response in the buffer is valid, but is it a response
	// to our last message?
	uint32_t messageSeconds, responseSeconds;
	uint16_t messageFraction, responseFraction;
	AWPacket::getTimestamp(messageBuffer, messageSeconds,
			       messageFraction);
	AWPacket::getTimestamp(responseBuffer, responseSeconds,
			       responseFraction);
	if ((AWPacket::getSiteId(responseBuffer)
	     == AWPacket::getSiteId(messageBuffer)) &&
	    (messageSeconds == responseSeconds) &&
	    (messageFraction == responseFraction) &&
	    (AWPacket::getSequenceId(responseBuffer)
	     == AWPacket::getSequenceId(messageBuffer)) &&
	    (AWPacket::getRetries(responseBuffer)
	     == AWPacket::getRetries(messageBuffer))) {
	  // Valid response found
	  validResponse = true;
	  messageLen = 0;
	  state = stateWaitingForMessages;
	}
	else {
	  // Need another response
	  Serial.println("######################");
	  Serial.println("Packet valid but incorrect response");
	  AWPacket::printPacket(responseBuffer, responseLen, Serial);
	  Serial.println("######################");
	  
	  responseLen = 0;
	  responsePacketLen = 65535; // Use maximum value until we know
	}
      }
    }
    break;

  case stateTimedOut:
    // Stuck here until a new message is added
    break;
  }

  return validResponse;
}