Exemple #1
0
/* ****************************************************************************
*
* jsonTreat - 
*/
std::string jsonTreat(const char* content, ConnectionInfo* ciP, ParseData* parseDataP, RequestType request, std::string payloadWord, JsonRequest** reqPP)
{
  std::string   res   = "OK";
  JsonRequest*  reqP  = jsonRequestGet(request, ciP->method);

  LM_T(LmtParse, ("Treating a JSON request: '%s'", content));

  ciP->parseDataP = parseDataP;

  if (reqP == NULL)
  {
    std::string errorReply = restErrorReplyGet(ciP, ciP->outFormat, "", requestType(request), SccBadRequest,
                                               std::string("Sorry, no request treating object found for RequestType '") + requestType(request) + "'");

    LM_RE(errorReply, ("Sorry, no request treating object found for RequestType %d (%s)", request, requestType(request)));
  }

  if (reqPP != NULL)
    *reqPP = reqP;

  LM_T(LmtParse, ("Treating '%s' request", reqP->keyword.c_str()));

  reqP->init(parseDataP);

  try
  {
    res = jsonParse(ciP, content, reqP->keyword, reqP->parseVector, parseDataP);
    if (ciP->inCompoundValue == true)
      orion::compoundValueEnd(ciP, parseDataP);
    if ((lmTraceIsSet(LmtCompoundValueShow)) && (ciP->compoundValueP != NULL))
      ciP->compoundValueP->shortShow("after parse: ");
  }
  catch (std::exception &e)
  {
    std::string errorReply  = restErrorReplyGet(ciP, ciP->outFormat, "", reqP->keyword, SccBadRequest, std::string("JSON Parse Error: ") + e.what());
    LM_E(("JSON Parse Error: '%s'", e.what()));
    LM_RE(errorReply, (res.c_str()));
  }

  if (res != "OK")
  {
    LM_E(("JSON parse error: %s", res.c_str()));
    ciP->httpStatusCode = SccBadRequest;

    std::string answer = restErrorReplyGet(ciP, ciP->outFormat, "", payloadWord, ciP->httpStatusCode, res);
    return answer; 
  }

  reqP->present(parseDataP);

  LM_T(LmtParseCheck, ("Calling check for JSON parsed tree (%s)", ciP->payloadWord));
  res = reqP->check(parseDataP, ciP);
  reqP->present(parseDataP);

  return res;
}
/* ****************************************************************************
*
* socketHttpConnect -
*/
int socketHttpConnect(const std::string& host, unsigned short port)
{
  int                 fd;
  struct addrinfo     hints;
  struct addrinfo*    peer;
  char                port_str[10];


  LM_VVV(("Generic Connect to: '%s'  port: '%d'", host.c_str(), port));

  memset(&hints, 0, sizeof(struct addrinfo));
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_protocol = 0;

  if (ipVersionUsed == IPV4) 
  {
    hints.ai_family = AF_INET;
    LM_VVV(("Allow IPv4 only"));
  }
  else if (ipVersionUsed == IPV6)
  {
    hints.ai_family = AF_INET6;
    LM_VVV(("Allow  IPv6 only"));
  }
  else 
  {
    hints.ai_family = AF_UNSPEC;
    LM_VVV(("Allow IPv4 or IPv6"));
  }

  snprintf(port_str, sizeof(port_str), "%d" , (int) port);

  if (getaddrinfo(host.c_str(), port_str, &hints, &peer) != 0) {
    LM_RE(-1, ("getaddrinfo('%s'): %s", host.c_str(), strerror(errno)));
  }

  if ((fd = socket(peer->ai_family, peer->ai_socktype, peer->ai_protocol)) == -1) {
    LM_RE(-1, ("socket: %s", strerror(errno)));
  }

  if (connect(fd, peer->ai_addr, peer->ai_addrlen) == -1)
  {
    freeaddrinfo(peer);
    close(fd);
    LM_E(("connect(%s, %d): %s", host.c_str(), port, strerror(errno)));
    return -1;
  }
  freeaddrinfo(peer);
  return fd;
}
/* ****************************************************************************
*
* mapGetIndividualContextEntityAttributes - 
*/
HttpStatusCode mapGetIndividualContextEntityAttributes(const std::string& entityId, ContextElementResponse* response, ConnectionInfo* ciP)
{
   HttpStatusCode        ms;
   QueryContextRequest   qcRequest;
   QueryContextResponse  qcResponse;
   EntityId              entity(entityId, "", "false");

   // Here I fill in the 'query' entityId for the response
   response->contextElement.entityId.fill(entityId, "", "false");

   qcRequest.entityIdVector.push_back(&entity);
   ms = mongoQueryContext(&qcRequest, &qcResponse, ciP->tenant, ciP->servicePathV, ciP->uriParam);

   if ((ms != SccOk) || (qcResponse.contextElementResponseVector.size() == 0))
   {
     // Here I fill in statusCode for the response
     response->statusCode.fill(SccContextElementNotFound, std::string("Entity id: '") + entityId + "'");
     LM_RE(ms, ("entityId '%s' not found", entityId.c_str()));
   }

   std::vector<ContextAttribute*> attrV = qcResponse.contextElementResponseVector.get(0)->contextElement.contextAttributeVector.vec;
   for (unsigned int ix = 0; ix < attrV.size() ; ++ix) {
       ContextAttribute* ca = new ContextAttribute(attrV[ix]);
       response->contextElement.contextAttributeVector.push_back(ca);
   }
   response->statusCode.fill(&qcResponse.contextElementResponseVector.get(0)->statusCode);
   return ms;
}
/* ****************************************************************************
*
* attributeExpression - 
*/
static std::string attributeExpression(std::string path, std::string value, ParseData* reqDataP)
{
  LM_T(LmtParse, ("Got an attributeExpression: '%s'", value.c_str()));

  reqDataP->dcar.res.restriction.attributeExpression.set(value);

  if (value == "")
     LM_RE("Empty attribute expression", ("Empty attribute expression"));

  return "OK";
}
/* ****************************************************************************
*
* entityIdParse - 
*/
std::string entityIdParse(RequestType requestType, xml_node<>* node, EntityId* entityIdP)
{
  for (xml_attribute<> *attr = node->first_attribute(); attr; attr = attr->next_attribute())
  {
    if (attr->name() == std::string("type"))
    {
      entityIdP->type = attr->value();
      LM_T(LmtEntityId, ("Got a type for an entity: '%s'", entityIdP->type.c_str()));
    }
    else if (attr->name() == std::string("isPattern"))
    {
      entityIdP->isPattern = attr->value();
      LM_T(LmtEntityId, ("Got an isPattern for an entity: '%s'", entityIdP->isPattern.c_str()));
    }
    else
      LM_RE("unsupported attribute for EntityId", ("Warning: unsupported attribute '%s' for EntityId", attr->name()));
  }

  return "OK";
}
Exemple #6
0
/* ****************************************************************************
*
* paRcFileParse - parse startup file
*/
int paRcFileParse(void)
{
  char   dir[1024];
  char   path[1024];
  char   line[512];
  int    lineNo = 0;
  FILE*  fP;
  char   w[512];

  LM_ENTRY();

  if ((paRcFileName == NULL) || (paRcFileName[0] == 0))
  {
    LM_EXIT();
    return 0;
  }

  if (dirFind(dir, sizeof(dir)) == 0)
  {
    LM_T(LmtPaRcFile, ("RC file '%s' found in directory '%s'", paRcFileName, dir));
  }
  else
  {
    return 0;
  }

  snprintf(path, sizeof(path), "%s/%s", dir, paRcFileName);
  if ((fP = fopen(path, "r")) == NULL)
  {
    LM_RE(-1, ("error opening RC file '%s': %s", path, strerror(errno)));
  }

  LM_T(LmtPaRcFile, ("parsing RC file %s", path));

  while (fgets(line, sizeof(line), fP) != NULL)
  {
    char*         delim;
    char*         var;
    char*         val;
    PaiArgument*  aP;
    bool          varFound;
    char          envVarName[128];

    ++lineNo;
    LM_T(LmtPaRcFile, ("got line %d", lineNo));
    newlineStrip(line);
    LM_T(LmtPaRcFile, ("got line %d", lineNo));
    commentStrip(line, '#');
    LM_T(LmtPaRcFile, ("got line %d", lineNo));
    baWsStrip(line);
    LM_T(LmtPaRcFile, ("got line %d", lineNo));
    if (line[0] == 0)
    {
      continue;
    }

    LM_T(LmtPaRcFile, ("got line %d", lineNo));
    delim = strchr(line, '=');
    if (delim == NULL)
    {
      char w[512];

      snprintf(w, sizeof(w), "%s[%d]: no delimiter found", path, lineNo);
      PA_WARNING(PasParseError, w);
      continue;
    }

    *delim = 0;
    var    = line;
    val    = &delim[1];
    baWsStrip(var);
    baWsStrip(val);

    if (var[0] == 0)
    {
      fclose(fP);
      LM_RE(-1, ("%s[%d]: no variable ...", path, lineNo));
    }

    if (val[0] == 0)
    {
      fclose(fP);
      LM_RE(-1, ("%s[%d]: no value for variable %s", path, lineNo, var));
    }

    varFound = false;

    paIterateInit();
    while ((aP = paIterateNext(paiList)) != NULL)
    {
      paEnvName(aP, envVarName, sizeof(envVarName));

      if (strcmp(var, envVarName) == 0)
      {
        aP->from = PafRcFile;
        LM_T(LmtPaRcFileVal, ("got value '%s' for %s", val, envVarName));
        varFound = true;
        break;
      }
    }

    if (varFound == false)
    {
      char w[512];

      snprintf(w, sizeof(w), "%s[%d]: variable '%s' not recognized", path, lineNo, var);
      PA_WARNING(PasNoSuchVariable, w);
      continue;
    }

    switch (aP->type)
    {
    case PaString:
      strcpy((char*) aP->varP, val);
      break;

    case PaBoolean:
      if ((strcmp(val, "TRUE") == 0)
      ||  (strcmp(val, "ON")   == 0)
      ||  (strcmp(val, "yes")   == 0)
      ||  (strcmp(val, "1")    == 0))
        *((bool*) (int64_t) aP->varP) = true;
      else if ((strcmp(val, "FALSE") == 0)
      ||       (strcmp(val, "OFF")   == 0)
      ||       (strcmp(val, "no")   == 0)
      ||       (strcmp(val, "0")     == 0))
        *((bool*) (int64_t) aP->varP) = false;
      else
      {
        snprintf(w, sizeof(w), "bad value '%s' for boolean variable %s", val, envVarName);
        PA_WARNING(PasNoSuchBooleanValue, w);
      }
      break;

    case PaSList:
    case PaIList:
      LM_TODO(("lists ..."));
      break;

    case PaInt:
    case PaIntU:
      *((int64_t*) aP->varP) = baStoi(val);
      break;

    case PaShort:
    case PaShortU:
      *((int16_t*) (int64_t) aP->varP) = baStoi(val);
      break;

    case PaFloat:
      *((float*) (int64_t) aP->varP) = baStof(val);
      break;

    case PaDouble:
      *((double*) (int64_t) aP->varP) = baStod(val);
      break;

    case PaChar:
    case PaCharU:
      *((char*) (int64_t) aP->varP) = baStoi(val);
      break;

    default:
      snprintf(w, sizeof(w), "bad type %d for variable %s", aP->type, envVarName);
      PA_WARNING(PasNoSuchType, w);
    }
  }

  fclose(fP);
  return 0;
}
Exemple #7
0
/* ****************************************************************************
*
* restStart - 
*/
static int restStart(IpVersion ipVersion, const char* httpsKey = NULL, const char* httpsCertificate = NULL)
{
  if (port == 0)
     LM_RE(1, ("Please call restInit before starting the REST service"));

  if ((ipVersion == IPV4) || (ipVersion == IPDUAL)) 
  { 
    memset(&sad, 0, sizeof(sad));
    if (inet_pton(AF_INET, bindIp, &(sad.sin_addr.s_addr)) != 1)
      LM_RE(2, ("V4 inet_pton fail for %s", bindIp));

    sad.sin_family = AF_INET;
    sad.sin_port   = htons(port);

    if ((httpsKey != NULL) && (httpsCertificate != NULL))
    {
      mhdDaemon = MHD_start_daemon(MHD_USE_THREAD_PER_CONNECTION | MHD_USE_SSL, // MHD_USE_SELECT_INTERNALLY
                                   htons(port),
                                   NULL,
                                   NULL,
                                   connectionTreat,                     NULL,
                                   MHD_OPTION_HTTPS_MEM_KEY,            httpsKey,
                                   MHD_OPTION_HTTPS_MEM_CERT,           httpsCertificate,
                                   MHD_OPTION_NOTIFY_COMPLETED,         requestCompleted, NULL,
                                   MHD_OPTION_CONNECTION_MEMORY_LIMIT,  2 * PAYLOAD_SIZE,
                                   MHD_OPTION_SOCK_ADDR,                (struct sockaddr*) &sad,
                                   MHD_OPTION_END);
    }
    else
    {
      LM_V(("Starting HTTP daemon on IPv4 %s port %d", bindIp, port));
      mhdDaemon = MHD_start_daemon(MHD_USE_THREAD_PER_CONNECTION, // MHD_USE_SELECT_INTERNALLY
                                   htons(port),
                                   NULL,
                                   NULL,
                                   connectionTreat,                     NULL,
                                   MHD_OPTION_NOTIFY_COMPLETED,         requestCompleted, NULL,
                                   MHD_OPTION_CONNECTION_MEMORY_LIMIT,  2 * PAYLOAD_SIZE,
                                   MHD_OPTION_SOCK_ADDR,                (struct sockaddr*) &sad,
                                   MHD_OPTION_END);
    }

    if (mhdDaemon == NULL)
      LM_RE(3, ("MHD_start_daemon failed"));
  }  

  if ((ipVersion == IPV6) || (ipVersion == IPDUAL))
  { 
    memset(&sad_v6, 0, sizeof(sad_v6));
    if (inet_pton(AF_INET6, bindIPv6, &(sad_v6.sin6_addr.s6_addr)) != 1)
      LM_RE(1, ("V6 inet_pton fail for %s", bindIPv6));

    sad_v6.sin6_family = AF_INET6;
    sad_v6.sin6_port = htons(port);

    if ((httpsKey != NULL) && (httpsCertificate != NULL))
    {
      LM_V(("Starting HTTPS daemon on IPv6 %s port %d", bindIPv6, port));
      mhdDaemon_v6 = MHD_start_daemon(MHD_USE_THREAD_PER_CONNECTION | MHD_USE_IPv6 | MHD_USE_SSL,
                                      htons(port),
                                      NULL,
                                      NULL,
                                      connectionTreat,                     NULL,
                                      MHD_OPTION_HTTPS_MEM_KEY,            httpsKey,
                                      MHD_OPTION_HTTPS_MEM_CERT,           httpsCertificate,
                                      MHD_OPTION_NOTIFY_COMPLETED,         requestCompleted, NULL,
                                      MHD_OPTION_CONNECTION_MEMORY_LIMIT,  2 * PAYLOAD_SIZE,
                                      MHD_OPTION_SOCK_ADDR,                (struct sockaddr*) &sad_v6,
                                      MHD_OPTION_END);
    }
    else
    {
      LM_V(("Starting HTTP daemon on IPv6 %s port %d", bindIPv6, port));
      mhdDaemon_v6 = MHD_start_daemon(MHD_USE_THREAD_PER_CONNECTION | MHD_USE_IPv6,
                                      htons(port),
                                      NULL,
                                      NULL,
                                      connectionTreat,                     NULL,
                                      MHD_OPTION_NOTIFY_COMPLETED,         requestCompleted, NULL,
                                      MHD_OPTION_CONNECTION_MEMORY_LIMIT,  2 * PAYLOAD_SIZE,
                                      MHD_OPTION_SOCK_ADDR,                (struct sockaddr*) &sad_v6,
                                      MHD_OPTION_END);
    }

    if (mhdDaemon_v6 == NULL)
      LM_RE(1, ("MHD_start_daemon_v6 failed"));
  }

  return 0;
}
Exemple #8
0
/* ****************************************************************************
*
* connectionTreat - 
*
* This is the MHD_AccessHandlerCallback function for MHD_start_daemon
* This function returns:
* o MHD_YES  if the connection was handled successfully
* o MHD_NO   if the socket must be closed due to a serious error
*
* - This function is called once when the headers are read and the ciP is created.
* - Then it is called for data payload and once all the payload an acknowledgement
*   must be done, setting *upload_data_size to ZERO.
* - The last call is made with *upload_data_size == 0 and now is when the connection
*   is open to send responses.
*
* Call 1: *con_cls == NULL
* Call 2: *con_cls != NULL  AND  *upload_data_size != 0
* Call 3: *con_cls != NULL  AND  *upload_data_size == 0
*/
static int connectionTreat
(
   void*            cls,
   MHD_Connection*  connection,
   const char*      url,
   const char*      method,
   const char*      version,
   const char*      upload_data,
   size_t*          upload_data_size,
   void**           con_cls
)
{
  ConnectionInfo* ciP      = (ConnectionInfo*) *con_cls;
  size_t          dataLen  = *upload_data_size;

  // 1. First call - setup ConnectionInfo and get/check HTTP headers
  if (ciP == NULL)
  {
    if ((ciP = new ConnectionInfo(url, method, version, connection)) == NULL)
      LM_RE(MHD_NO, ("Error allocating ConnectionInfo"));
        
    *con_cls = (void*) ciP; // Pointer to ConnectionInfo for subsequent calls

    MHD_get_connection_values(connection, MHD_HEADER_KIND, httpHeaderGet, &ciP->httpHeaders);

    ciP->outFormat  = wantedOutputSupported(ciP->httpHeaders.accept, &ciP->charset);
    if (ciP->outFormat == NOFORMAT)
      ciP->outFormat = XML; // XML is default output format

    if (contentTypeCheck(ciP) != 0)
    {
      LM_W(("Error in Content-Type"));
      restReply(ciP, ciP->answer);
    }
    else if (outFormatCheck(ciP) != 0)
    {
      LM_W(("Bad Accepted Out-Format (in Accept header)"));
      restReply(ciP, ciP->answer);
    }
    else
      ciP->inFormat = formatParse(ciP->httpHeaders.contentType, NULL);

    return MHD_YES;
  }


  //
  // 2. Data gathering calls
  //
  // 2-1. Data gathering calls, just wait
  // 2-2. Last data gathering call, acknowledge the receipt of data
  //
  if (dataLen != 0)
  {
    if (dataLen == ciP->httpHeaders.contentLength)
    {
      if (ciP->httpHeaders.contentLength <= PAYLOAD_MAX_SIZE)
      {
        if (ciP->httpHeaders.contentLength > STATIC_BUFFER_SIZE)
          ciP->payload = (char*) malloc(ciP->httpHeaders.contentLength);
        else
          ciP->payload = static_buffer;

        ciP->payloadSize = dataLen;
        memcpy(ciP->payload, upload_data, dataLen);
        ciP->payload[dataLen] = 0;
      }
      else
      {
        char details[256];
        snprintf(details, sizeof(details), "payload size: %d, max size supported: %d", ciP->httpHeaders.contentLength, PAYLOAD_MAX_SIZE);

        ciP->answer         = restErrorReplyGet(ciP, ciP->outFormat, "", ciP->url, SccRequestEntityTooLarge, details);
        ciP->httpStatusCode = SccRequestEntityTooLarge;
      }

      // All payload received, acknowledge!
      *upload_data_size = 0;
    }
    else
      LM_T(LmtPartialPayload, ("Got %d of payload of %d bytes", dataLen, ciP->httpHeaders.contentLength));

    return MHD_YES;
  }


  // 3. Finally, serve the request (unless an error has occurred)
  if (((ciP->verb == POST) || (ciP->verb == PUT)) && (ciP->httpHeaders.contentLength == 0))
  {
    std::string errorMsg = restErrorReplyGet(ciP, ciP->outFormat, "", url, SccLengthRequired, "Zero/No Content-Length in PUT/POST request");
    ciP->httpStatusCode = SccLengthRequired;
    restReply(ciP, errorMsg);
  }
  else if (ciP->answer != "")
    restReply(ciP, ciP->answer);
  else
    serveFunction(ciP);

  return MHD_YES;
}
Exemple #9
0
/* ****************************************************************************
*
* wantedOutputSupported - 
*/
static Format wantedOutputSupported(std::string acceptList, std::string* charsetP)
{
  std::vector<std::string>  vec;
  char* copy;
  if (acceptList.length() == 0) 
  {
    /* HTTP RFC states that a missing Accept header must be interpreted as if the client is
     * accepting any type */
    copy = strdup("*/*");
  }
  else 
  {
    copy = strdup((char*) acceptList.c_str());
  }
  char*                     cP   = copy;

  do
  {
     char* comma;

     comma = strstr(cP, ",");
     if (comma != NULL)
     {
        *comma = 0;
        
        cP = wsStrip(cP);
        vec.push_back(cP);
        cP = comma;
        ++cP;
     }
     else
     {
        cP = wsStrip(cP);
        if (*cP != 0)
        {
           vec.push_back(cP);
        }
        *cP = 0;
     }

  } while (*cP != 0);

  free(copy);

  bool xml  = false;
  bool json = false;

  for (unsigned int ix = 0; ix < vec.size(); ++ix)
  {
     char* s;

     //
     // charset embedded in 'Accept' header?
     // We read it but we don't do anything with it ...
     //
     if ((s = strstr((char*) vec[ix].c_str(), ";")) != NULL)
     {
        *s = 0;
        ++s;
        s = wsStrip(s);
        if (strncmp(s, "charset=", 8) == 0)
        {
           s = &s[8];
           s = wsStrip(s);

           if (charsetP != NULL)
              *charsetP = s;
        }
     }

     std::string format = vec[ix].c_str();
     if (format == "*/*")              xml  = true;
     if (format == "*/xml")            xml  = true;
     if (format == "application/*")    xml  = true;
     if (format == "application/xml")  xml  = true;
     if (format == "application/json") json = true;
     if (format == "*/json")           json = true;
     
     if ((acceptTextXml == true) && (format == "text/xml"))  xml = true;

     //
     // Resetting charset
     //
     if (charsetP != NULL)
        *charsetP = "";
  }

  if (xml == true)
    return XML;
  else if (json == true)
    return JSON;

  LM_RE(NOFORMAT, ("No valid 'Accept-format' found"));
}
/* ****************************************************************************
*
* sendHttpSocket -
*
* The waitForResponse arguments specifies if the method has to wait for response
* before return. If this argument is false, the return string is ""
*
* FIXME: I don't like too much "reusing" natural output to return "error" in the
* case of error. I think it would be smarter to use "std::string* error" in the
* arguments or (even better) and exception. To be solved in the future in a hardening
* period.
*
* Note, we are using an hybrid approach, consisting in an static thread-local buffer of
* small size that cope with the most of notifications to avoid expensive
* calloc/free syscalls if the notification payload is not very large.
*
*/
std::string sendHttpSocket
(
   const std::string&     _ip,
   unsigned short         port,
   const std::string&     protocol,
   const std::string&     verb,
   const std::string&     tenant,
   const std::string&     resource,
   const std::string&     content_type,
   const std::string&     content,
   bool                   useRush,
   bool                   waitForResponse
)
{  
  char                       buffer[TAM_BUF];
  char                       response[TAM_BUF];
  char                       preContent[TAM_BUF];
  char                       msgStatic[MAX_STA_MSG_SIZE];
  char*                      what               = (char*) "static";
  char*                      msgDynamic         = NULL;
  char*                      msg                = msgStatic;   // by default, use the static buffer
  std::string                rushHeaderIP       = "";
  unsigned short             rushHeaderPort     = 0;
  std::string                rushHttpHeaders    = "";
  static unsigned long long  callNo             = 0;
  std::string                result;
  std::string                ip                 = _ip;

  ++callNo;

  // Preconditions check
  if (port == 0)        LM_RE("error", ("port is ZERO"));
  if (ip.empty())       LM_RE("error", ("ip is empty"));
  if (verb.empty())     LM_RE("error", ("verb is empty"));
  if (resource.empty()) LM_RE("error", ("resource is empty"));
  if ((content_type.empty()) && (!content.empty())) LM_RE("error", ("Content-Type is empty but there is actual content"));
  if ((!content_type.empty()) && (content.empty())) LM_RE("error", ("there is actual content but Content-Type is empty"));

  //
  // Rush
  // Every call to sendHttpSocket specifies whether RUSH should be used or not.
  // But, this depends also on how the broker was started, so here the 'useRush'
  // parameter is cancelled in case the broker was started without rush.
  //
  // If rush is to be used, the IP/port is stored in rushHeaderIP/rushHeaderPort and
  // after that, the host and port of rush is set as ip/port for the message, that is
  // now sent to rush instead of to its final destination.
  // Also, a few HTTP headers for rush nust be setup.
  //
  if (useRush)
  {
    if ((rushPort == 0) || (rushHost == ""))
      useRush = false;
    else
    {
      char portAsString[16];

      rushHeaderIP   = ip;
      rushHeaderPort = port;
      ip             = rushHost;
      port           = rushPort;

      sprintf(portAsString, "%d", (int) rushHeaderPort);
      rushHttpHeaders = "X-relayer-host: " + rushHeaderIP + ":" + portAsString + "\n";
      if (protocol == "https:")
        rushHttpHeaders += "X-relayer-protocol: https\n";
    }
  }

  // Buffers clear
  memset(buffer, 0, TAM_BUF);
  memset(response, 0, TAM_BUF);
  memset(msg, 0, MAX_STA_MSG_SIZE);

  snprintf(preContent, sizeof(preContent),
           "%s %s HTTP/1.1\n"
           "User-Agent: orion/%s\n"
           "Host: %s:%d\n"
           "Accept: application/xml, application/json\n%s",
           verb.c_str(), resource.c_str(), versionGet(), ip.c_str(), (int) port, rushHttpHeaders.c_str());

  LM_T(LmtRush, ("'PRE' HTTP headers:\n--------------\n%s\n-------------", preContent));

  if (tenant != "")
  {
    char tenantHeader[128];

    snprintf(tenantHeader, sizeof(tenantHeader), "fiware-service: %s\n", tenant.c_str());

    strncat(preContent, tenantHeader, sizeof(preContent) - strlen(preContent));
  }

  if (!content.empty())
  {
    char   headers[512];
    sprintf(headers,
            "Content-Type: %s\n"
            "Content-Length: %zu\n",
            content_type.c_str(), content.length() + 1);
    strncat(preContent, headers, sizeof(preContent) - strlen(preContent));

    /* Choose the right buffer (static or dynamic) to use. Note we are using +3 due to:
     *    + 1, for the \n between preContent and content
     *    + 1, for the \n at the end of the message
     *    + 1, for the \0 by the trailing character in C strings
     */
    int neededSize = content.length() + strlen(preContent) + 3;
    if (neededSize > MAX_DYN_MSG_SIZE) {
        LM_RE("error", ("HTTP request to send is too large: %d bytes", content.length() + strlen(preContent)));
    }
    else if (neededSize > MAX_STA_MSG_SIZE) {
        msgDynamic = (char*) calloc(sizeof(char), neededSize);
        if (msgDynamic == NULL) {
            LM_RE("error", ("dynamic memory allocation failure"));
        }
        msg = msgDynamic;
        what = (char*) "dynamic";
    }

    /* The above checking should ensure that the three parts fit, so we are using
     * sprint() instead of snprintf() */
    sprintf(msg, "%s\n%s", preContent, content.c_str());
  }
  else
  {
    /* In the case of no-content we assume that MAX_STA_MSG_SIZE is enough to send the message */
    LM_T(LmtClientOutputPayload, ("Using static buffer to send HTTP request (empty content)"));
    sprintf(msg, "%s\n", preContent);
  }

  /* We add a final newline (I guess that HTTP protocol needs it) */
  strcat(msg, "\n");

  int fd = socketHttpConnect(ip, port); // Connecting to HTTP server

  if (fd == -1)
    LM_RE("error", ("Unable to connect to HTTP server at %s:%d", ip.c_str(), port));

  int nb;
  int sz = strlen(msg);

  LM_T(LmtClientOutputPayload, ("Sending message %lu to HTTP server: sending %s message of %d bytes to HTTP server", callNo, what, sz));
  LM_T(LmtClientOutputPayloadDump, ("Sending to HTTP server payload:\n%s", msg));
  nb = send(fd, msg, sz, 0);
  if (msgDynamic != NULL) {
      free (msgDynamic);
  }

  if (nb == -1)
    LM_RE("error", ("error sending to HTTP server: %s", strerror(errno)));
  else if (nb != sz)
     LM_E(("error sending to HTTP server. Sent %d bytes of %d", nb, sz));

  if (waitForResponse) {
      nb = recv(fd,&buffer,TAM_BUF-1,0);

      if (nb == -1)
        LM_RE("error", ("error recv from HTTP server: %s", strerror(errno)));
      else if ( nb >= TAM_BUF)
         LM_RE("error", ("recv from HTTP server too long"));
      else
      {
          memcpy(response, buffer, nb);
          LM_T(LmtClientInputPayload, ("Received from HTTP server:\n%s", response));
      }

      if (strlen(response) > 0)
          result = response;
  }
  else {
     LM_T(LmtClientInputPayload, ("not waiting for response"));
     result = "";
  }

  close(fd);
  return result;
}