Beispiel #1
0
ErrorPtr VdcApiRequest::sendError(ErrorPtr aErrorToSend)
{
  if (!Error::isOK(aErrorToSend)) {
    VdcApiErrorPtr ve = boost::dynamic_pointer_cast<VdcApiError>(aErrorToSend);
    if (ve) {
      // special VdcApiError, has extra user facing information
      return sendError((uint32_t)aErrorToSend->getErrorCode(), aErrorToSend->getErrorMessage(), ApiValuePtr(), ve->getErrorType(), ve->getUserFacingMessage());
    }
    else {
      return sendError((uint32_t)aErrorToSend->getErrorCode(), aErrorToSend->getErrorMessage());
    }
  }
  return ErrorPtr();
}
Beispiel #2
0
ErrorPtr VdcApiRequest::sendError(ErrorPtr aErrorToSend)
{
    if (!Error::isOK(aErrorToSend)) {
        return sendError((uint32_t)aErrorToSend->getErrorCode(), aErrorToSend->getErrorMessage());
    }
    return ErrorPtr();
}
Beispiel #3
0
ErrorPtr JsonRpcComm::sendError(const char *aJsonRpcId, ErrorPtr aErrorToSend)
{
  if (!Error::isOK(aErrorToSend)) {
    return sendError(aJsonRpcId, (uint32_t)aErrorToSend->getErrorCode(), aErrorToSend->getErrorMessage());
  }
  return ErrorPtr();
}
Beispiel #4
0
void P44VdcHost::sendCfgApiResponse(JsonCommPtr aJsonComm, JsonObjectPtr aResult, ErrorPtr aError)
{
  // create response
  JsonObjectPtr response = JsonObject::newObj();
  if (!Error::isOK(aError)) {
    // error, return error response
    response->add("error", JsonObject::newInt32((int32_t)aError->getErrorCode()));
    response->add("errormessage", JsonObject::newString(aError->getErrorMessage()));
    response->add("errordomain", JsonObject::newString(aError->getErrorDomain()));
    VdcApiErrorPtr ve = boost::dynamic_pointer_cast<VdcApiError>(aError);
    if (ve) {
      response->add("errortype", JsonObject::newInt32(ve->getErrorType()));
      response->add("userfacingmessage", JsonObject::newString(ve->getUserFacingMessage()));
    }
  }
  else {
    // no error, return result (if any)
    response->add("result", aResult);
  }
  LOG(LOG_DEBUG, "Config API response: %s", response->c_strValue());
  aJsonComm->sendMessage(response);
}
Beispiel #5
0
void JsonRpcComm::gotJson(ErrorPtr aError, JsonObjectPtr aJsonObject)
{
  JsonRpcCommPtr keepMeAlive(this); // make sure this object lives until routine terminates
  ErrorPtr respErr;
  bool safeError = false; // set when reporting error is safe (i.e. not error possibly generated by malformed error, to prevent error loops)
  JsonObjectPtr idObj;
  const char *idString = NULL;
  if (Error::isOK(aError)) {
    // received proper JSON, now check JSON-RPC specifics
    FOCUSLOG("Received JSON message:\n  %s\n", aJsonObject->c_strValue());
    if (aJsonObject->isType(json_type_array)) {
      respErr = ErrorPtr(new JsonRpcError(JSONRPC_INVALID_REQUEST, "Invalid Request - batch mode not supported by this implementation"));
    }
    else if (!aJsonObject->isType(json_type_object)) {
      respErr = ErrorPtr(new JsonRpcError(JSONRPC_INVALID_REQUEST, "Invalid Request - request must be JSON object"));
    }
    else {
      // check request object fields
      const char *method = NULL;
      JsonObjectPtr o = aJsonObject->get("jsonrpc");
      if (!o)
        respErr = ErrorPtr(new JsonRpcError(JSONRPC_INVALID_REQUEST, "Invalid Request - missing 'jsonrpc'"));
      else if (o->stringValue()!="2.0")
        respErr = ErrorPtr(new JsonRpcError(JSONRPC_INVALID_REQUEST, "Invalid Request - wrong version in 'jsonrpc'"));
      else {
        // get ID param (must be present for all messages except notification)
        idObj = aJsonObject->get("id");
        if (idObj) idString = idObj->c_strValue();
        JsonObjectPtr paramsObj = aJsonObject->get("params");
        // JSON-RPC version is correct, check other params
        method = aJsonObject->getCString("method");
        if (method) {
          // this is a request (responses don't have the method member)
          safeError = idObj!=NULL; // reporting error is safe if this is a method call. Other errors are reported only when reportAllErrors is set
          if (*method==0)
            respErr = ErrorPtr(new JsonRpcError(JSONRPC_INVALID_REQUEST, "Invalid Request - empty 'method'"));
          else {
            // looks like a valid method or notification call
            if (!jsonRequestHandler) {
              // no handler -> method cannot be executed
              respErr = ErrorPtr(new JsonRpcError(JSONRPC_METHOD_NOT_FOUND, "Method not found"));
            }
            else {
              if (paramsObj && !paramsObj->isType(json_type_array) && !paramsObj->isType(json_type_object)) {
                // invalid param object
                respErr = ErrorPtr(new JsonRpcError(JSONRPC_INVALID_REQUEST, "Invalid Request - 'params' must be object or array"));
              }
              else {
                // call handler to execute method or notification
                jsonRequestHandler(method, idString, paramsObj);
              }
            }
          }
        }
        else {
          // this is a response (requests always have a method member)
          // - check if result or error
          JsonObjectPtr respObj;
          if (!aJsonObject->get("result", respObj)) {
            // must be error, need further decoding
            respObj = aJsonObject->get("error");
            if (!respObj)
              respErr = ErrorPtr(new JsonRpcError(JSONRPC_INTERNAL_ERROR, "Internal JSON-RPC error - response with neither 'result' nor 'error'"));
            else {
              // dissect error object
              ErrorCode errCode = JSONRPC_INTERNAL_ERROR; // Internal RPC error
              const char *errMsg = "malformed Error response";
              // - try to get error code
              JsonObjectPtr o = respObj->get("code");
              if (o) errCode = o->int32Value();
              // - try to get error message
              o = respObj->get("message");
              if (o) errMsg = o->c_strValue();
              // compose error object from this
              respErr = ErrorPtr(new JsonRpcError(errCode, errMsg));
              // also get optional data element
              respObj = respObj->get("data");
            }
          }
          // Now we have either result or error.data in respObj, and respErr is Ok or contains the error code + message
          if (!idObj) {
            // errors without ID cannot be associated with calls made earlier, so just log the error
            LOG(LOG_WARNING,"JSON-RPC 2.0 warning: Received response with no or NULL 'id' that cannot be dispatched:\n  %s\n", aJsonObject->c_strValue());
          }
          else {
            // dispatch by ID
            uint32_t requestId = idObj->int32Value();
            PendingAnswerMap::iterator pos = pendingAnswers.find(requestId);
            if (pos==pendingAnswers.end()) {
              // errors without ID cannot be associated with calls made earlier, so just log the error
              LOG(LOG_WARNING,"JSON-RPC 2.0 error: Received response with unknown 'id'=%d : %s\n", requestId, aJsonObject->c_strValue());
            }
            else {
              // found callback
              JsonRpcResponseCB cb = pos->second;
              pendingAnswers.erase(pos); // erase
              cb(requestId, respErr, respObj); // call
            }
            respErr.reset(); // handled
          }
        }
      }
    }
  }
  else {
    // no proper JSON received, create error response
    if (aError->isDomain(JsonError::domain())) {
      // some kind of parsing error
      respErr = ErrorPtr(new JsonRpcError(JSONRPC_PARSE_ERROR, aError->description()));
    }
    else {
      // some other type of server error
      respErr = ErrorPtr(new JsonRpcError(JSONRPC_SERVER_ERROR, aError->description()));
    }
  }
  // auto-generate error response for internally created errors
  if (!Error::isOK(respErr)) {
    if (safeError || reportAllErrors)
      sendError(idString, respErr);
    else
      LOG(LOG_WARNING,"Received data that generated error which can't be sent back: Code=%d, Message='%s'\n", respErr->getErrorCode(), respErr->description().c_str());
  }
}