Exemple #1
0
/* ****************************************************************************
*
* semInit -
*
*   parameter #2: 0 - the semaphore is to be shared between threads,
*   parameter #3: 1 - initially the semaphore is free
*
* RETURN VALUE (of sem_init)
*   0 on success,
*  -1 on failure
*
*/
int semInit(SemOpType _reqPolicy, bool semTimeStat, int shared, int takenInitially)
{
  if (sem_init(&reqSem, shared, takenInitially) == -1)
  {
    LM_E(("Runtime Error (error initializing 'req' semaphore: %s)", strerror(errno)));
    return -1;
  }

  if (sem_init(&transSem, shared, takenInitially) == -1)
  {
    LM_E(("Runtime Error (error initializing 'transactionId' semaphore: %s)", strerror(errno)));
    return -1;
  }

  if (sem_init(&cacheSem, shared, takenInitially) == -1)
  {
    LM_E(("Runtime Error (error initializing 'cache' semaphore: %s)", strerror(errno)));
    return -1;
  }

  if (sem_init(&timeStatSem, shared, takenInitially) == -1)
  {
    LM_E(("Runtime Error (error initializing 'timeStat' semaphore: %s)", strerror(errno)));
    return -1;
  }

  reqPolicy = _reqPolicy;

  // Measure accumulated semaphore waiting time?
  semWaitStatistics = semTimeStat;
  return 0;
}
/* ****************************************************************************
*
* attributeValue - return value of attribute as a string
*/
static void attributeValue(std::string* valueP, const std::vector<ContextAttribute*>& vec, char* attrName)
{
  for (unsigned int ix = 0; ix < vec.size(); ++ix)
  {
    if (vec[ix]->name != attrName)
    {
      continue;
    }

    if (vec[ix]->valueType == orion::ValueTypeString)
    {
      *valueP = vec[ix]->stringValue;
    }
    else if (vec[ix]->valueType == orion::ValueTypeNumber)
    {
      *valueP = toString(vec[ix]->numberValue);
    }
    else if (vec[ix]->valueType == orion::ValueTypeBoolean)
    {
      *valueP = (vec[ix]->boolValue == true)? "true" : "false";
    }
    else if (vec[ix]->valueType == orion::ValueTypeNone)
    {
      *valueP = "null";
    }
    else if ((vec[ix]->valueType == orion::ValueTypeObject) || (vec[ix]->valueType == orion::ValueTypeVector))
    {
      if (vec[ix]->compoundValueP)
      {
        if (vec[ix]->compoundValueP->valueType == orion::ValueTypeVector)
        {
          *valueP = "[" + vec[ix]->compoundValueP->toJson(true) + "]";
        }
        else if (vec[ix]->compoundValueP->valueType == orion::ValueTypeObject)
        {
          *valueP = "{" + vec[ix]->compoundValueP->toJson(true) + "}";
        }
        else
        {
          LM_E(("Runtime Error (attribute is of object type but its compound is of invalid type)"));
          *valueP = "";
        }
      }
      else
      {
        LM_E(("Runtime Error (attribute is of object type but has no compound)"));
        *valueP = "";
      }
    }
    else
    {
      LM_E(("Runtime Error (unknown value type for attribute)"));
      *valueP = "";
    }

    return;
  }

  *valueP = "";
}
/* ****************************************************************************
*
* RegisterContextRequest::check - 
*/
std::string RegisterContextRequest::check(RequestType requestType, Format format, std::string indent, std::string predetectedError, int counter)
{
  RegisterContextResponse  response(this);
  std::string              res;

  if (predetectedError != "")
  {
    LM_E(("predetectedError not empty"));
    response.errorCode.fill(SccBadRequest, predetectedError);
  }
  else if (contextRegistrationVector.size() == 0)
  {
    LM_E(("contextRegistrationVector.size() == 0"));
    response.errorCode.fill(SccBadRequest, "Empty Context Registration List");
  }
  else if (((res = contextRegistrationVector.check(RegisterContext, format, indent, predetectedError, counter)) != "OK") ||
           ((res = duration.check(RegisterContext, format, indent, predetectedError, counter))                  != "OK") ||
           ((res = registrationId.check(RegisterContext, format, indent, predetectedError, counter))            != "OK"))
  {
    LM_E(("Some check method failed: %s", res.c_str()));
    response.errorCode.fill(SccBadRequest, res);
  }
  else
    return "OK";

  LM_E(("Not OK - returning rendered error result"));     
  return response.render(RegisterContext, format, indent);
}
Exemple #4
0
/* ****************************************************************************
*
* Notifier::destroyOntimeIntervalThreads -
*/
void Notifier::destroyOntimeIntervalThreads(const std::string& subId) {

    std::vector<pthread_t> canceled;

    /* Get all the ThreadParams associated to the given subId. Inspired in
     * http://advancedcppwithexamples.blogspot.com.es/2009/04/example-of-c-multimap.html
     */
    std::pair<std::multimap<std::string, ThreadData>::iterator, std::multimap<std::string, ThreadData>::iterator> ii;
    std::multimap<std::string, ThreadData>::iterator it;
    ii = this->threadsMap.equal_range(subId);
    for (it = ii.first; it != ii.second; ++it) {

        ThreadData td = it->second;

        /* Destroy thread */        
        int ret = pthread_cancel(td.tid);
        if (ret != 0)
        {
          LM_E(("Runtime Error (error canceling thread %lu: %d)", (unsigned long) td.tid, ret));
          return;
        }

        /* Note that we do the cancelation in parallel, storing the thread ID. This
         * vector is processed afterwards to wait for every thread to finish */
        canceled.push_back(td.tid);

        /* Release memory */
        delete td.params;

    }

    /* Remove key from the hashmap */
    threadsMap.erase(subId);

    /* Wait for all the cancelation to end */
    for (unsigned int ix = 0; ix < canceled.size(); ++ix) {
        void* res;

        /* pthread_join in blocking */
        int ret = pthread_join(canceled[ix], &res);
        if (ret != 0)
        {
          LM_E(("Runtime Error (error joining thread %lu: %d)", (unsigned long) canceled[ix], ret));
          return;
        }

        if (res == PTHREAD_CANCELED)
        {
            LM_T(LmtNotifier, ("canceled thread: %lu", (unsigned long) canceled[ix]));
        }
        else
        {
          LM_E(("Runtime Error (unexpected error: thread can not be canceled)"));
          return;
        }
    }

    canceled.clear();
}
Exemple #5
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;
}
Exemple #6
0
/* ****************************************************************************
*
* treat -
*
* This is the function that actually treats a node, bu calling its treat function
* provided by src/lib/xmlRequest - the entry point of XML parsing.
*
* It simple compares the current path with the paths in the incoming vector 'parseVector'
* and if a hit is found calls the 'treat' function of that hit (the instance of the vector).
*
* If no hit is found it means that the path of the current XML node is unknown.
* This will result in either a 'PARSE ERROR' or thatthe node is part of a Compound.
*/
static bool treat(ConnectionInfo* ciP, xml_node<>* node, const std::string& path, XmlNode* parseVector, ParseData* parseDataP)
{
  for (unsigned int ix = 0; parseVector[ix].path != "LAST"; ++ix)
  {
    if (path == parseVector[ix].path)
    {
      int r;

      //
      // Before treating a node, a check is made that the value of the node has no forbidden
      // characters.
      // However, if the the node has attributes, then the values of the attributes are checked instead
      //
      if (node->first_attribute() == NULL)
      {
        if (forbiddenChars(node->value()) == true)
        {
          LM_E(("Found a forbidden value in '%s'", node->value()));
          ciP->httpStatusCode = SccBadRequest;
          ciP->answer = std::string("Illegal value for XML attribute");
          return true;
        }
      }
      else
      {
        for (xml_attribute<> *attr = node->first_attribute(); attr; attr = attr->next_attribute())
        {
          if (forbiddenChars(attr->value()) == true)
          {
            LM_E(("Found a forbidden value in attribute: '%s'", node->value()));
            ciP->httpStatusCode = SccBadRequest;
            ciP->answer = std::string("Illegal value for XML attribute");
            return true;
          }
        }
      }

      if ((r = parseVector[ix].treat(node, parseDataP)) != 0)
      {
        LM_W(("Bad Input (xml parse error %d)", r));
      }

      return true;  // Node has been treated
    }
  }

  return false;  // Node was not found in the parse vector
}
/* ****************************************************************************
*
* strToLower - 
*/
char* strToLower(char* to, const char* from, int toSize)
{
  int fromSize = strlen(from);

  if (toSize < fromSize + 1)
  {
    LM_E(("Runtime Error (cannot copy %d bytes into a buffer of %d bytes)", fromSize + 1, toSize));
    fromSize = toSize;
  }

  int ix;
  for (ix = 0; ix < fromSize; ix++)
  {
    if ((from[ix] >= 'A') && (from[ix] <= 'Z'))
    {
      to[ix] = from[ix] + ('a' - 'A');
    }
    else
    {
      to[ix] = from[ix];
    }
  }

  to[ix] = 0;

  return to;
}
/* ****************************************************************************
*
* forbiddenChars - 
*/
bool forbiddenChars(const char* s, const char* exceptions)
{
  if (s == (void*) 0)
  {
    return false;
  }

  while (*s != 0)
  {
    if ((exceptions != NULL) && (strchr(exceptions, *s) != NULL))
    {
      ++s;
      continue;
    }

    switch (*s)
    {
    case '<':
    case '>':
    case '"':
    case '\'':
    case '=':
    case ';':
    case '(':
    case ')':
      LM_E(("Bad Input (character '%c')", *s));
      return true;
    }

    ++s;
  }

  return false;
}
Exemple #9
0
/* ****************************************************************************
*
* restReply - 
*/
void restReply(ConnectionInfo* ciP, const std::string& answer)
{
  MHD_Response*  response;

  ++replyIx;
  LM_T(LmtServiceOutPayload, ("Response %d: responding with %d bytes, Status Code %d", replyIx, answer.length(), ciP->httpStatusCode));
  LM_T(LmtServiceOutPayload, ("Response payload: '%s'", answer.c_str()));

  if (answer == "")
    response = MHD_create_response_from_data(answer.length(), (void*) answer.c_str(), MHD_NO, MHD_NO);
  else
    response = MHD_create_response_from_data(answer.length(), (void*) answer.c_str(), MHD_YES, MHD_YES);

  if (!response)
  {
    LM_E(("Runtime Error (MHD_create_response_from_buffer FAILED)"));
    return;
  }

  for (unsigned int hIx = 0; hIx < ciP->httpHeader.size(); ++hIx)
    MHD_add_response_header(response, ciP->httpHeader[hIx].c_str(), ciP->httpHeaderValue[hIx].c_str());

  if (answer != "")
  {
    if (ciP->outFormat == XML)
      MHD_add_response_header(response, "Content-Type", "application/xml");
    else if (ciP->outFormat == JSON)
      MHD_add_response_header(response, "Content-Type", "application/json");
  }

  MHD_queue_response(ciP->connection, ciP->httpStatusCode, response);
  MHD_destroy_response(response);
}
/* ****************************************************************************
*
* QueueNotifier::sendNotifyContextRequest -
*/
void QueueNotifier::sendNotifyContextRequest
(
    NotifyContextRequest*            ncr,
    const ngsiv2::HttpInfo&          httpInfo,
    const std::string&               tenant,
    const std::string&               xauthToken,
    const std::string&               fiwareCorrelator,
    RenderFormat                     renderFormat,
    const std::vector<std::string>&  attrsOrder,
    const std::vector<std::string>&  metadataFilter,
    bool                             blacklist
    )
{
  std::vector<SenderThreadParams*> *paramsV = Notifier::buildSenderParams(ncr, httpInfo, tenant, xauthToken, fiwareCorrelator, renderFormat, attrsOrder, metadataFilter, blacklist);

  for (unsigned ix = 0; ix < paramsV->size(); ix++) {
    clock_gettime(CLOCK_REALTIME, &(((*paramsV)[ix])->timeStamp));
  }
  bool enqueued = queue.try_push(paramsV);
  if (!enqueued)
  {
    QueueStatistics::incReject(paramsV->size());

    LM_E(("Runtime Error (notification queue is full)"));
    for (unsigned ix = 0; ix < paramsV->size(); ix++) {
      delete (*paramsV)[ix];
    }
    delete paramsV;

    return;
  }

  QueueStatistics::incIn(paramsV->size());

}
/* ****************************************************************************
*
* httpRequestSend - 
*
* RETURN VALUES
*   httpRequestSend returns 0 on success and a negative number on failure:
*     -1: Invalid port
*     -2: Invalid IP
*     -3: Invalid verb
*     -4: Invalid resource
*     -5: No Content-Type BUT content present
*     -6: Content-Type present but there is no content
*     -7: Total outgoing message size is too big
*     -8: Unable to initialize libcurl
*     -9: Error making HTTP request
*
*   [ error codes -1 to -7 comes from httpRequestSendWithCurl ]
*/
int httpRequestSend
(
   const std::string&     _ip,
   unsigned short         port,
   const std::string&     protocol,
   const std::string&     verb,
   const std::string&     tenant,
   const std::string&     servicePath,
   const std::string&     xauthToken,
   const std::string&     resource,
   const std::string&     orig_content_type,
   const std::string&     content,
   const std::string&     fiwareCorrelation,
   const std::string&     ngisv2AttrFormat,
   bool                   useRush,
   bool                   waitForResponse,
   std::string*           outP,
   const std::string&     acceptFormat,
   long                   timeoutInMilliseconds
)
{
  struct curl_context  cc;
  int                  response;

  get_curl_context(_ip, &cc);
  if (cc.curl == NULL)
  {
    release_curl_context(&cc);
    LM_E(("Runtime Error (could not init libcurl)"));
    lmTransactionEnd();

    *outP = "error";
    return -8;
  }

  response = httpRequestSendWithCurl(cc.curl,
                                     _ip,
                                     port,
                                     protocol,
                                     verb,
                                     tenant,
                                     servicePath,
                                     xauthToken,
                                     resource,
                                     orig_content_type,
                                     content,
                                     fiwareCorrelation,
                                     ngisv2AttrFormat,
                                     useRush,
                                     waitForResponse,
                                     outP,
                                     acceptFormat,
                                     timeoutInMilliseconds);
  release_curl_context(&cc);
  return response;
}
/* ****************************************************************************
*
* AlarmManager::semInit - 
*/
int AlarmManager::semInit(void)
{
  if (sem_init(&sem, 0, 1) == -1)
  {
    LM_E(("Runtime Error (error initializing 'alarm mgr' semaphore: %s)", strerror(errno)));
    return -1;
  }

  return 0;
}
/* ****************************************************************************
*
* Notifier::sendNotifyContextAvailabilityRequest -
*
* FIXME: this method is very similar to sendNotifyContextRequest and probably
* they could be refactored in the future to have a common part using a parent
* class for both types of notifications and using it as first argument
*/
void Notifier::sendNotifyContextAvailabilityRequest
(
  NotifyContextAvailabilityRequest*  ncar,
  const std::string&                 url,
  const std::string&                 tenant,
  const std::string&                 fiwareCorrelator,
  RenderFormat                       renderFormat
)
{
    /* Render NotifyContextAvailabilityRequest */
    std::string payload = ncar->render(NotifyContextAvailability, "");

    /* Parse URL */
    std::string  host;
    int          port;
    std::string  uriPath;
    std::string  protocol;

    if (!parseUrl(url, host, port, uriPath, protocol))
    {
      std::string details = std::string("sending NotifyContextAvailabilityRequest: malformed URL: '") + url + "'";
      alarmMgr.badInput(clientIp, details);

      return;
    }

    /* Set Content-Type */
    std::string content_type = "application/json";

    /* Send the message (without awaiting response, in a separate thread to avoid blocking) */
    pthread_t            tid;
    SenderThreadParams*  params = new SenderThreadParams();

    params->ip               = host;
    params->port             = port;
    params->verb             = "POST";
    params->tenant           = tenant;
    params->resource         = uriPath;   
    params->content_type     = content_type;
    params->content          = payload;
    params->mimeType         = JSON;
    params->fiwareCorrelator = fiwareCorrelator;
    params->renderFormat     = renderFormatToString(renderFormat);

    strncpy(params->transactionId, transactionId, sizeof(params->transactionId));

    int ret = pthread_create(&tid, NULL, startSenderThread, params);
    if (ret != 0)
    {
      LM_E(("Runtime Error (error creating thread: %d)", ret));
      return;
    }
    pthread_detach(tid);
}
/* ****************************************************************************
*
* SubscriptionCache::insert - 
*/
void SubscriptionCache::insert(Subscription* subP)
{
  if (subP->entityIdInfos.size() == 0)
  {
    LM_E(("Runtime Error (no entity for subscription - not inserted in subscription cache)"));
    return;
  }

  subs.push_back(subP);

  ++noOfSubCacheEntries;
}
Exemple #15
0
/* ****************************************************************************
*
* semInit -
*
*   parameter #1: 0 - the semaphore is to be shared between threads,
*   parameter #2: 1 - initially the semaphore is free
*
* RETURN VALUE (of sem_init)
*   0 on success,
*  -1 on failure
*
*/
int semInit(int shared, int takenInitially)
{
  if (sem_init(&reqSem, shared, takenInitially) == -1)
  {
    LM_E(("Runtime Error (error initializing 'req' semaphore: %s)", strerror(errno)));
    return 1;
  }

  if (sem_init(&mongoSem, shared, takenInitially) == -1)
  {
    LM_E(("Runtime Error (error initializing 'mongo' semaphore: %s)", strerror(errno)));
    return 2;
  }

  if (sem_init(&transSem, shared, takenInitially) == -1)
  {
    LM_E(("Runtime Error (error initializing 'transactionId' semaphore: %s)", strerror(errno)));
    return 3;
  }

  return 0;
}
/* ****************************************************************************
*
* restReply - 
*/
void restReply(ConnectionInfo* ciP, const std::string& answer)
{
  MHD_Response*  response;

  ++replyIx;
  LM_T(LmtServiceOutPayload, ("Response %d: responding with %d bytes, Status Code %d", replyIx, answer.length(), ciP->httpStatusCode));
  LM_T(LmtServiceOutPayload, ("Response payload: '%s'", answer.c_str()));

  response = MHD_create_response_from_buffer(answer.length(), (void*) answer.c_str(), MHD_RESPMEM_MUST_COPY);
  if (!response)
  {
    LM_E(("Runtime Error (MHD_create_response_from_buffer FAILED)"));
    return;
  }

  for (unsigned int hIx = 0; hIx < ciP->httpHeader.size(); ++hIx)
  {
    MHD_add_response_header(response, ciP->httpHeader[hIx].c_str(), ciP->httpHeaderValue[hIx].c_str());
  }

  if (answer != "")
  {
    if (ciP->outMimeType == JSON)
    {
      MHD_add_response_header(response, "Content-Type", "application/json");
    }
    else if (ciP->outMimeType == TEXT)
    {
      MHD_add_response_header(response, "Content-Type", "text/plain");
    }

    // At the present version, CORS is supported only for GET requests
    if ((strlen(restAllowedOrigin) > 0) && (ciP->verb == GET))
    {
      // If any origin is allowed, the header is sent always with "any" as value
      if (strcmp(restAllowedOrigin, "__ALL") == 0)
      {
        MHD_add_response_header(response, "Access-Control-Allow-Origin", "*");
      }
      // If a specific origin is allowed, the header is only sent if the origins match
      else if (strcmp(ciP->httpHeaders.origin.c_str(), restAllowedOrigin) == 0)
      {
        MHD_add_response_header(response, "Access-Control-Allow-Origin", restAllowedOrigin);
      }
    }
  }

  MHD_queue_response(ciP->connection, ciP->httpStatusCode, response);
  MHD_destroy_response(response);
}
/* ****************************************************************************
*
* attributeType -
*
*/
static std::string attributeType
(
  const std::string&                    tenant,
  const std::vector<std::string>&       servicePathV,
  const std::string                     entityType,
  const std::string                     attrName
)
{
  std::string  idType         = std::string("_id.")    + ENT_ENTITY_TYPE;
  std::string  idServicePath  = std::string("_id.")    + ENT_SERVICE_PATH;
  std::string  attributeName  = std::string(ENT_ATTRS) + "." + attrName;

  BSONObj query = BSON(idType        << entityType <<
                       idServicePath << fillQueryServicePath(servicePathV) <<
                       attributeName << BSON("$exists" << true));

  std::auto_ptr<DBClientCursor> cursor;
  std::string                   err;

  if (!collectionQuery(getEntitiesCollectionName(tenant), query, &cursor, &err))
  {
    return "";
  }

  while (cursor->more())
  {
    BSONObj r;
    try
    {
      r = cursor->nextSafe();
    }
    catch (const AssertionException &e)
    {
      // $err raised
      LM_E(("Runtime Error (assertion exception in nextSafe(): %s", e.what()));
      continue;
    }

    LM_T(LmtMongo, ("retrieved document: '%s'", r.toString().c_str()));

    /* It could happen that different entities within the same entity type may have attributes with the same name
     * but different types. In that case, one type (at random) is returned. A list could be returned but the
     * NGSIv2 operations only allow to set one type */
    BSONObj attrs = getField(r, ENT_ATTRS).embeddedObject();
    BSONObj attr = getField(attrs, attrName).embeddedObject();
    return getStringField(attr, ENT_ATTRS_TYPE);
  }

  return "";
}
/* ****************************************************************************
*
* 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;
}
Exemple #19
0
/* ****************************************************************************
*
* get_curl_context_new -
*/
static int get_curl_context_new(const std::string& key, struct curl_context* pcc)
{
  pcc->curl   = NULL;
  pcc->pmutex = NULL;

  pcc->curl = curl_easy_init();

  if (pcc->curl == NULL)
  {
    LM_E(("Runtime Error (curl_easy_init)"));
    return -1;
  }

  return 0;
}
Exemple #20
0
/* ****************************************************************************
*
* jsonRequestGet - 
*/
static JsonRequest* jsonRequestGet(RequestType request, std::string method)
{
  for (unsigned int ix = 0; ix < sizeof(jsonRequest) / sizeof(jsonRequest[0]); ++ix)
  {
    if ((request == jsonRequest[ix].type) && (jsonRequest[ix].method == method))
    {
      if (jsonRequest[ix].parseVector != NULL)
        LM_V2(("Found jsonRequest of type %d, method '%s' - index %d (%s)", request, method.c_str(), ix, jsonRequest[ix].parseVector[0].path.c_str()));
      return &jsonRequest[ix];
    }
  }

  LM_E(("No request found for RequestType '%s', method '%s'", requestType(request), method.c_str()));
  return NULL;
}
Exemple #21
0
/* ****************************************************************************
*
* countEntities -
*
*/
static long long countEntities(const std::string& tenant, const std::vector<std::string>& servicePathV,std::string entityType)
{
  DBClientBase*  connection    = NULL;
  std::string    idType        = std::string("_id.") + ENT_ENTITY_TYPE;
  std::string    idServicePath = std::string("_id.") + ENT_SERVICE_PATH;

  BSONObj query = BSON(idType        << entityType <<
                       idServicePath << fillQueryServicePath(servicePathV));

  LM_T(LmtMongo, ("count() in '%s' collection: '%s'",
                  getEntitiesCollectionName(tenant).c_str(),
                  query.toString().c_str()));

  try
  {
    connection  = getMongoConnection();
    long long c = connection->count(getEntitiesCollectionName(tenant).c_str(), query);

    releaseMongoConnection(connection);
    LM_I(("Database Operation Successful (%s)", query.toString().c_str()));

    return c;
  }
  catch (const DBException& e)
  {
    releaseMongoConnection(connection);
    LM_E(("Database Error ('%s', '%s')", query.toString().c_str(), e.what()));
  }
  catch (...)
  {
    releaseMongoConnection(connection);
    LM_E(("Database Error ('%s', '%s')", query.toString().c_str(), "generic exception"));
  }

  return -1;
}
/* ****************************************************************************
*
* AlarmManager::dbErrorReset - 
*
* Returns false if no effective alarm transition occurs, otherwise, true is returned.
*/
bool AlarmManager::dbErrorReset(void)
{
  if (dbOk == true)
  {
    return false;
  }

  semTake();
  ++dbErrorResets;
  dbOk = true;
  semGive();

  LM_E(("Releasing alarm DatabaseError"));
  return true;
}
Exemple #23
0
/* ****************************************************************************
*
* xmlParse - 
*/
void xmlParse(xml_node<>* father, xml_node<>* node, std::string indentation, std::string fatherPath, XmlNode* parseVector, ParseData* reqDataP)
{
  if (node == NULL)
    return;

  if (node->name() == NULL)
    return;

  if (node->name()[0] == 0)
    return;

  std::string path = fatherPath + "/" + node->name();


  //
  // Lookup node in the node vector
  //
  bool treated = false;
  for (unsigned int ix = 0; parseVector[ix].path != "LAST"; ++ix)
  {
    if (path == parseVector[ix].path)
    {
      int r;

      if ((r = parseVector[ix].treat(node, reqDataP)) != 0)
      {
        fprintf(stderr, "parse vector treat function error: %d\n", r);
        LM_E(("parse vector treat function error: %d", r));
      }

      treated = true;
      break;
    }
  }

  if (treated == false)
    LM_W(("Warning: node '%s' not treated (%s)", path.c_str(), node->name()));

  xml_node<>* child = node->first_node();

  while (child != NULL)
  {
    xmlParse(node, child, indentation + "  ", path, parseVector, reqDataP);
    child = child->next_sibling();
  }
}
Exemple #24
0
/* ****************************************************************************
*
* treat - 
*
* This is the function that actually treats a node, bu calling its treat function
* provided by src/lib/xmlRequest - the entry point of XML parsing.
*
* It simple compares the current path with the paths in the incoming vector 'parseVector'
* and if a hit is found calls the 'treat' function of that hit (the instance of the vector).
*
* If no hit is found it means that the path of the current XML node is unknown.
* This will result in either a 'PARSE ERROR' or thatthe node is part of a Compound.
*/
static bool treat(xml_node<>* node, std::string path, XmlNode* parseVector, ParseData* parseDataP)
{
  for (unsigned int ix = 0; parseVector[ix].path != "LAST"; ++ix)
  {
    if (path == parseVector[ix].path)
    {
      int r;

      if ((r = parseVector[ix].treat(node, parseDataP)) != 0)
        LM_E(("parse vector treat function error: %d", r));

      return true; // Node has been treated
    }
  }

  return false; // Node was not found in the parse vector
}
Exemple #25
0
/* ****************************************************************************
*
* Notifier::sendNotifyContextAvailabilityRequest -
*
* FIXME: this method is very similar to sendNotifyContextRequest and probably
* they could be refactored in the future to have a common part using a parent
* class for both types of notifications and using it as first argument
*/
void Notifier::sendNotifyContextAvailabilityRequest(NotifyContextAvailabilityRequest* ncar, const std::string& url, const std::string& tenant, Format format) {

    /* Render NotifyContextAvailabilityRequest */
    std::string payload = ncar->render(NotifyContextAvailability, format, "");

    /* Parse URL */
    std::string  host;
    int          port;
    std::string  uriPath;
    std::string  protocol;
    if (!parseUrl(url, host, port, uriPath, protocol))
    {
      LM_W(("Bad Input (sending NotifyContextAvailabilityRequest: malformed URL: '%s')", url.c_str()));
      return;
    }

    /* Set Content-Type depending on the format */
    std::string content_type = (format == XML ? "application/xml" : "application/json");

    /* Send the message (no wait for response, in a separated thread to avoid blocking response)*/
#ifdef SEND_BLOCKING
    sendHttpSocket(host, port, protocol, "POST", tenant, "", "", uriPath, content_type, payload, true, NOTIFICATION_WAIT_MODE);
#endif

#ifdef SEND_IN_NEW_THREAD
    pthread_t tid;
    SenderThreadParams* params = new SenderThreadParams();

    params->ip           = host;
    params->port         = port;
    params->verb         = "POST";
    params->tenant       = tenant;
    params->resource     = uriPath;   
    params->content_type = content_type;
    params->content      = payload;
    strncpy(params->transactionId, transactionId, sizeof(params->transactionId));

    int ret = pthread_create(&tid, NULL, startSenderThread, params);
    if (ret != 0)
    {
      LM_E(("Runtime Error (error creating thread: %d)", ret));
      return;
    }
    pthread_detach(tid);
#endif
}
/* ****************************************************************************
*
* writeMemoryCallback -
*/
size_t writeMemoryCallback(void* contents, size_t size, size_t nmemb, void* userp)
{
  size_t realsize = size * nmemb;
  MemoryStruct* mem = (MemoryStruct *) userp;

  mem->memory = (char*) realloc(mem->memory, mem->size + realsize + 1);
  if (mem->memory == NULL)
  {
    LM_E(("Runtime Error (out of memory)"));
    return 0;
  }

  memcpy(&(mem->memory[mem->size]), contents, realsize);
  mem->size += realsize;
  mem->memory[mem->size] = 0;

  return realsize;
}
/* ****************************************************************************
*
* AlarmManager::dbError - 
*
* Returns false if no effective alarm transition occurs, otherwise, true is returned.
*/
bool AlarmManager::dbError(const std::string& details)
{
  if (dbOk == false)
  {
    if (dbErrorLogAlways)
    {
      LM_W(("Repeated Database Error: %s", details.c_str()));
    }

    return false;
  }

  semTake();
  ++dbErrors;
  dbOk = false;
  semGive();

  LM_E(("Raising alarm DatabaseError: %s", details.c_str()));
  return true;
}
/* ****************************************************************************
*
* clone -
*/
CompoundValueNode* CompoundValueNode::clone(void)
{
  CompoundValueNode* me;

  LM_T(LmtCompoundValue, ("cloning '%s'", name.c_str()));

  if (rootP == this)
  {
    me = new CompoundValueNode(valueType);
  }
  else
  {
    switch (valueType)
    {
    case orion::ValueTypeString:
    case orion::ValueTypeObject:
    case orion::ValueTypeVector:
      me = new CompoundValueNode(container, path, name, stringValue, siblingNo, valueType, level);
      break;

    case orion::ValueTypeNumber:
      me = new CompoundValueNode(container, path, name, numberValue, siblingNo, valueType, level);
      break;

    case orion::ValueTypeBoolean:
      me = new CompoundValueNode(container, path, name, boolValue, siblingNo, valueType, level);
      break;
    default:
      me = NULL;
      LM_E(("Runtime Error (unknown compound node value type: %d)", valueType));
    }
  }

  for (unsigned int ix = 0; ix < childV.size(); ++ix)
  {
    LM_T(LmtCompoundValue, ("Adding child %d for '%s'", ix, name.c_str()));
    me->add(childV[ix]->clone());
  }

  return me;
}
/* ****************************************************************************
*
* StatusCode::fill - 
*/
void StatusCode::fill(const struct UpdateContextResponse& ucrs)
{
  if ((ucrs.errorCode.code != SccOk) && (ucrs.errorCode.code != SccNone))
  {
    fill(ucrs.errorCode);
  }
  else if (ucrs.contextElementResponseVector.vec.size() == 1)
  {
    fill(ucrs.contextElementResponseVector.vec[0]->statusCode);
  }
  else if (ucrs.contextElementResponseVector.vec.size() > 1)
  {
    LM_W(("Filling StatusCode from UpdateContextResponse with more than one contextElementResponse, picking one of them ..."));
    fill(ucrs.contextElementResponseVector.vec[0]->statusCode);
  }
  else
  {
    // Empty UpdateContextResponse::contextElementResponseVector AND unfilled UpdateContextResponse::errorCode
    LM_E(("Internal Error (can't fill StatusCode from UpdateContextResponse)"));
    fill(SccReceiverInternalError, "can't fill StatusCode from UpdateContextResponse");
  }
}
int release_curl_context(struct curl_context *pcc)
{
  // Reset context if not an empty context
  if (pcc->curl != NULL)
  {
    curl_easy_reset(pcc->curl);
    pcc->curl = NULL; // It will remain in global map
  }
  // Unlock the mutex if not an empty context
  if (pcc->pmutex != NULL)
    {
    int s = pthread_mutex_unlock(pcc->pmutex);
    if(s!=0)
    {
      LM_E(("pthread_mutex_unlock"));
      return s;
    }
    pcc->pmutex = NULL; // It will remain in global map
  }

  return 0;
}