/* **************************************************************************** * * 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); }
/* **************************************************************************** * * 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(); }
/* **************************************************************************** * * 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; }
/* **************************************************************************** * * 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; }
/* **************************************************************************** * * 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; }
/* **************************************************************************** * * 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; }
/* **************************************************************************** * * 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; }
/* **************************************************************************** * * 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; }
/* **************************************************************************** * * 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; }
/* **************************************************************************** * * 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(); } }
/* **************************************************************************** * * 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 }
/* **************************************************************************** * * 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; }