/* **************************************************************************** * * getIPv6Port - */ bool getIPv6Port(std::string in, std::string& outIp, std::string& outPort) { size_t pos; std::string partip; std::string resu; std::string staux = in; // Split IP and port pos = staux.find(":"); while (pos != std::string::npos) { partip = staux.substr(0, pos+1); resu += partip; partip = staux.substr(pos+1); staux = partip; pos = staux.find(":"); } if (resu.empty()) return false; outIp = resu.substr(0, resu.length() -1 ); outPort = staux; return isIPv6(resu); }
/* **************************************************************************** * * restInit - * * FIXME P5: add vector of the accepted content-types, instead of the bool * See Issue #256 */ void restInit ( RestService* _restServiceV, IpVersion _ipVersion, const char* _bindAddress, unsigned short _port, bool _multitenant, unsigned int _connectionMemory, unsigned int _maxConnections, unsigned int _mhdThreadPoolSize, const std::string& _rushHost, unsigned short _rushPort, const char* _allowedOrigin, const char* _httpsKey, const char* _httpsCertificate, RestServeFunction _serveFunction ) { const char* key = _httpsKey; const char* cert = _httpsCertificate; port = _port; restServiceV = _restServiceV; ipVersionUsed = _ipVersion; serveFunction = (_serveFunction != NULL)? _serveFunction : serve; multitenant = _multitenant; connMemory = _connectionMemory; maxConns = _maxConnections; threadPoolSize = _mhdThreadPoolSize; rushHost = _rushHost; rushPort = _rushPort; strncpy(restAllowedOrigin, _allowedOrigin, sizeof(restAllowedOrigin)); strncpy(bindIp, LOCAL_IP_V4, MAX_LEN_IP - 1); strncpy(bindIPv6, LOCAL_IP_V6, MAX_LEN_IP - 1); if (isIPv6(std::string(_bindAddress))) { strncpy(bindIPv6, _bindAddress, MAX_LEN_IP - 1); } else { strncpy(bindIp, _bindAddress, MAX_LEN_IP - 1); } // Starting REST interface int r; if ((r = restStart(_ipVersion, key, cert)) != 0) { fprintf(stderr, "restStart: error %d\n", r); orionExitFunction(1, "restStart: error"); } }
/* **************************************************************************** * * restInit - * * FIXME P5: add vector of the accepted content-types, instead of the bool * argument _acceptTextXml that was added for iotAgent only. * See Issue #256 */ void restInit ( RestService* _restServiceV, IpVersion _ipVersion, const char* _bindAddress, unsigned short _port, bool _multitenant, const std::string& _rushHost, unsigned short _rushPort, const char* _allowedOrigin, const char* _httpsKey, const char* _httpsCertificate, RestServeFunction _serveFunction, bool _acceptTextXml ) { const char* key = _httpsKey; const char* cert = _httpsCertificate; port = _port; restServiceV = _restServiceV; ipVersionUsed = _ipVersion; serveFunction = (_serveFunction != NULL)? _serveFunction : serve; acceptTextXml = _acceptTextXml; multitenant = _multitenant; rushHost = _rushHost; rushPort = _rushPort; strncpy(restAllowedOrigin, _allowedOrigin, sizeof(restAllowedOrigin)); strncpy(bindIp, LOCAL_IP_V4, MAX_LEN_IP - 1); strncpy(bindIPv6, LOCAL_IP_V6, MAX_LEN_IP - 1); if (isIPv6(std::string(_bindAddress))) strncpy(bindIPv6, _bindAddress, MAX_LEN_IP - 1); else strncpy(bindIp, _bindAddress, MAX_LEN_IP - 1); if ((_ipVersion == IPV4) || (_ipVersion == IPDUAL)) strncpy(bindIp, bindIp, MAX_LEN_IP - 1); if ((_ipVersion == IPV6) || (_ipVersion == IPDUAL)) strncpy(bindIPv6, bindIPv6, MAX_LEN_IP - 1); // Starting REST interface int r; if ((r = restStart(_ipVersion, key, cert)) != 0) { fprintf(stderr, "restStart: error %d\n", r); orionExitFunction(1, "restStart: error"); } }
QString KviIrcServer::ircUri() { QString szUri("irc"); if(useSSL()) szUri += "s"; if(isIPv6()) szUri += "6"; szUri += "://"; szUri += m_szHostname; if(m_uPort != 6667) { szUri += ":"; QString szNum; szNum.setNum(m_uPort); szUri += szNum; } return szUri; }
result_t net_base::isIP(exlib::string ip, int32_t& retVal) { retVal = 0; bool is = false; isIPv4(ip, is); if (is) { retVal = 4; return 0; } isIPv6(ip, is); if (is) retVal = 6; return 0; }
/* **************************************************************************** * * httpRequestSendWithCurl - * * The waitForResponse arguments specifies if the method has to wait for response * before return. If this argument is false, the return string is "" * * NOTE * We are using a hybrid approach, consisting in a static thread-local buffer of a * small size that copes with most notifications to avoid expensive * calloc/free syscalls if the notification payload is not very large. * * RETURN VALUES * httpRequestSendWithCurl 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 * -9: Error making HTTP request */ int httpRequestSendWithCurl ( CURL *curl, 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 ) { char portAsString[STRING_SIZE_FOR_INT]; static unsigned long long callNo = 0; std::string result; std::string ip = _ip; struct curl_slist* headers = NULL; MemoryStruct* httpResponse = NULL; CURLcode res; int outgoingMsgSize = 0; std::string content_type(orig_content_type); ++callNo; // For content-type application/json we add charset=utf-8 if (orig_content_type == "application/json") { content_type += "; charset=utf-8"; } if (timeoutInMilliseconds == -1) { timeoutInMilliseconds = defaultTimeout; } lmTransactionStart("to", ip.c_str(), port, resource.c_str()); // Preconditions check if (port == 0) { LM_E(("Runtime Error (port is ZERO)")); lmTransactionEnd(); *outP = "error"; return -1; } if (ip.empty()) { LM_E(("Runtime Error (ip is empty)")); lmTransactionEnd(); *outP = "error"; return -2; } if (verb.empty()) { LM_E(("Runtime Error (verb is empty)")); lmTransactionEnd(); *outP = "error"; return -3; } if (resource.empty()) { LM_E(("Runtime Error (resource is empty)")); lmTransactionEnd(); *outP = "error"; return -4; } if ((content_type.empty()) && (!content.empty())) { LM_E(("Runtime Error (Content-Type is empty but there is actual content)")); lmTransactionEnd(); *outP = "error"; return -5; } if ((!content_type.empty()) && (content.empty())) { LM_E(("Runtime Error (Content-Type non-empty but there is no content)")); lmTransactionEnd(); *outP = "error"; return -6; } // Allocate to hold HTTP response httpResponse = new MemoryStruct; httpResponse->memory = (char*) malloc(1); // will grow as needed httpResponse->size = 0; // no data at this point // // Rush // Every call to httpRequestSend 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 must be setup. // if ((rushPort == 0) || (rushHost == "")) { useRush = false; } if (useRush) { char rushHeaderPortAsString[STRING_SIZE_FOR_INT]; uint16_t rushHeaderPort = port; std::string rushHeaderIP = ip; std::string headerRushHttp; ip = rushHost; port = rushPort; snprintf(rushHeaderPortAsString, sizeof(rushHeaderPortAsString), "%d", rushHeaderPort); headerRushHttp = "X-relayer-host: " + rushHeaderIP + ":" + rushHeaderPortAsString; LM_T(LmtHttpHeaders, ("HTTP-HEADERS: '%s'", headerRushHttp.c_str())); headers = curl_slist_append(headers, headerRushHttp.c_str()); outgoingMsgSize += headerRushHttp.size(); if (protocol == "https:") { headerRushHttp = "X-relayer-protocol: https"; LM_T(LmtHttpHeaders, ("HTTP-HEADERS: '%s'", headerRushHttp.c_str())); headers = curl_slist_append(headers, headerRushHttp.c_str()); outgoingMsgSize += headerRushHttp.size(); } } snprintf(portAsString, sizeof(portAsString), "%u", port); // ----- User Agent char cvBuf[CURL_VERSION_MAX_LENGTH]; char headerUserAgent[HTTP_HEADER_USER_AGENT_MAX_LENGTH]; snprintf(headerUserAgent, sizeof(headerUserAgent), "User-Agent: orion/%s libcurl/%s", versionGet(), curlVersionGet(cvBuf, sizeof(cvBuf))); LM_T(LmtHttpHeaders, ("HTTP-HEADERS: '%s'", headerUserAgent)); headers = curl_slist_append(headers, headerUserAgent); outgoingMsgSize += strlen(headerUserAgent) + 1; // ----- Host char headerHost[HTTP_HEADER_HOST_MAX_LENGTH]; snprintf(headerHost, sizeof(headerHost), "Host: %s:%d", ip.c_str(), (int) port); LM_T(LmtHttpHeaders, ("HTTP-HEADERS: '%s'", headerHost)); headers = curl_slist_append(headers, headerHost); outgoingMsgSize += strlen(headerHost) + 1; // ----- Tenant if (tenant != "") { headers = curl_slist_append(headers, ("fiware-service: " + tenant).c_str()); outgoingMsgSize += tenant.size() + 16; // "fiware-service: " } // ----- Service-Path if (servicePath != "") { headers = curl_slist_append(headers, ("Fiware-ServicePath: " + servicePath).c_str()); outgoingMsgSize += servicePath.size() + strlen("Fiware-ServicePath: "); } // ----- X-Auth-Token if (xauthToken != "") { headers = curl_slist_append(headers, ("X-Auth-Token: " + xauthToken).c_str()); outgoingMsgSize += xauthToken.size() + strlen("X-Auth-Token: "); } // ----- Accept std::string acceptedFormats = "application/json"; if (acceptFormat != "") { acceptedFormats = acceptFormat; } std::string acceptString = "Accept: " + acceptedFormats; headers = curl_slist_append(headers, acceptString.c_str()); outgoingMsgSize += acceptString.size(); // ----- Expect headers = curl_slist_append(headers, "Expect: "); outgoingMsgSize += 8; // from "Expect: " // ----- Content-length std::stringstream contentLengthStringStream; contentLengthStringStream << content.size(); std::string headerContentLength = "Content-length: " + contentLengthStringStream.str(); LM_T(LmtHttpHeaders, ("HTTP-HEADERS: '%s'", headerContentLength.c_str())); headers = curl_slist_append(headers, headerContentLength.c_str()); outgoingMsgSize += contentLengthStringStream.str().size() + 16; // from "Content-length: " outgoingMsgSize += content.size(); // ----- Content-type headers = curl_slist_append(headers, ("Content-type: " + content_type).c_str()); outgoingMsgSize += content_type.size() + 14; // from "Content-type: " // Fiware-Correlator std::string correlation = "Fiware-Correlator: " + fiwareCorrelation; headers = curl_slist_append(headers, correlation.c_str()); outgoingMsgSize += correlation.size(); // Notify Format if ((ngisv2AttrFormat != "") && (ngisv2AttrFormat != "JSON") && (ngisv2AttrFormat != "legacy")) { std::string nFormat = "X-Ngsiv2-AttrsFormat: " + ngisv2AttrFormat; headers = curl_slist_append(headers, nFormat.c_str()); outgoingMsgSize += nFormat.size(); } // Check if total outgoing message size is too big if (outgoingMsgSize > MAX_DYN_MSG_SIZE) { LM_E(("Runtime Error (HTTP request to send is too large: %d bytes)", outgoingMsgSize)); curl_slist_free_all(headers); free(httpResponse->memory); delete httpResponse; lmTransactionEnd(); *outP = "error"; return -7; } // Contents const char* payload = content.c_str(); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, (u_int8_t*) payload); // Set up URL std::string url; if (isIPv6(ip)) url = "[" + ip + "]"; else url = ip; url = url + ":" + portAsString + (resource.at(0) == '/'? "" : "/") + resource; // Prepare CURL handle with obtained options curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, verb.c_str()); // Set HTTP verb curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); // Allow redirection (?) curl_easy_setopt(curl, CURLOPT_HEADER, 1); // Activate include the header in the body output curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); // Put headers in place curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &writeMemoryCallback); // Send data here curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*) httpResponse); // Custom data for response handling // // There is a known problem in libcurl (see http://stackoverflow.com/questions/9191668/error-longjmp-causes-uninitialized-stack-frame) // which is solved using CURLOPT_NOSIGNAL. If we update some day from libcurl 7.19 (the one that comes with CentOS 6.x) to a newer version // (there are some reports about the bug is no longer in libcurl 7.32), using CURLOPT_NOSIGNAL could be not necessary and this be removed). // See issue #1016 for more details. // curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); // // Timeout // // The parameter timeoutInMilliseconds holds the timeout time in milliseconds. // If the timeout time requested is 0, then no timeuot is used. // if (timeoutInMilliseconds != 0) { curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, timeoutInMilliseconds); } // Synchronous HTTP request // This was previously a LM_T trace, but we have "promoted" it to INFO due to it is needed to check logs in a .test case (case 000 notification_different_sizes.test) LM_I(("Sending message %lu to HTTP server: sending message of %d bytes to HTTP server", callNo, outgoingMsgSize)); res = curl_easy_perform(curl); if (res != CURLE_OK) { // // NOTE: This log line is used by the functional tests in cases/880_timeout_for_forward_and_notifications/ // So, this line should not be removed/altered, at least not without also modifying the functests. // alarmMgr.notificationError(url, "(curl_easy_perform failed: " + std::string(curl_easy_strerror(res)) + ")"); *outP = "notification failure"; } else { // The Response is here LM_I(("Notification Successfully Sent to %s", url.c_str())); outP->assign(httpResponse->memory, httpResponse->size); } // Cleanup curl environment curl_slist_free_all(headers); free(httpResponse->memory); delete httpResponse; lmTransactionEnd(); return res == CURLE_OK ? 0 : -9; }
//--------------------------------------------------------------------------- // IP V6 clear is '::' (all 128 bits zeroed) // IP V4 clear is 0000 0000 0000 0000 00000 FFFF 0000 0000 ( '::FFFF:0:0' ) bool IPAddress::isAddrAny() const { if (isIPv6()) return isAddressEqual(anyV6()); return isAddressEqualIgnoringIPv4Format(anyV4()); }
void KviIrcServer::save(KviConfigurationFile * pCfg, const QString & szPrefix) { QString szTmp; szTmp = QString("%1Hostname").arg(szPrefix); pCfg->writeEntry(szTmp,m_szHostname); szTmp = QString("%1Id").arg(szPrefix); pCfg->writeEntry(szTmp,m_szId); if(!m_szIp.isEmpty()) { szTmp = QString("%1Ip").arg(szPrefix); pCfg->writeEntry(szTmp,m_szIp); } if(!m_szDescription.isEmpty()) { szTmp = QString("%1Description").arg(szPrefix); pCfg->writeEntry(szTmp,m_szDescription); } if(!m_szUser.isEmpty()) { szTmp = QString("%1User").arg(szPrefix); pCfg->writeEntry(szTmp,m_szUser); } if(!m_szPass.isEmpty()) { szTmp = QString("%1Pass").arg(szPrefix); pCfg->writeEntry(szTmp,m_szPass); } if(!m_szNick.isEmpty()) { szTmp = QString("%1Nick").arg(szPrefix); pCfg->writeEntry(szTmp,m_szNick); } if(!m_szAlternativeNick.isEmpty()) { szTmp = QString("%1AlternativeNick").arg(szPrefix); pCfg->writeEntry(szTmp,m_szAlternativeNick); } if(!m_szSaslPass.isEmpty()) { szTmp = QString("%1SaslPass").arg(szPrefix); pCfg->writeEntry(szTmp,m_szSaslPass); } if(!m_szSaslNick.isEmpty()) { szTmp = QString("%1SaslNick").arg(szPrefix); pCfg->writeEntry(szTmp,m_szSaslNick); } if(!m_szRealName.isEmpty()) { szTmp = QString("%1RealName").arg(szPrefix); pCfg->writeEntry(szTmp,m_szRealName); } if(!m_szInitUMode.isEmpty()) { szTmp = QString("%1InitUMode").arg(szPrefix); pCfg->writeEntry(szTmp,m_szInitUMode); } if(autoJoinChannelList()) { szTmp = QString("%1AutoJoinChannels").arg(szPrefix); pCfg->writeEntry(szTmp,*(autoJoinChannelList())); } if(autoConnect()) // otherwise it defaults to false anyway { szTmp = QString("%1AutoConnect").arg(szPrefix); pCfg->writeEntry(szTmp,autoConnect()); } if(!m_szEncoding.isEmpty()) { szTmp = QString("%1Encoding").arg(szPrefix); pCfg->writeEntry(szTmp,m_szEncoding); } if(!m_szTextEncoding.isEmpty()) { szTmp = QString("%1TextEncoding").arg(szPrefix); pCfg->writeEntry(szTmp,m_szTextEncoding); } if(!m_szOnConnectCommand.isEmpty()) { szTmp = QString("%1OnConnectCommand").arg(szPrefix); pCfg->writeEntry(szTmp,m_szOnConnectCommand); } if(!m_szOnLoginCommand.isEmpty()) { szTmp = QString("%1OnLoginCommand").arg(szPrefix); pCfg->writeEntry(szTmp,m_szOnLoginCommand); } if(!m_szLinkFilter.isEmpty()) { szTmp = QString("%1LinkFilter").arg(szPrefix); pCfg->writeEntry(szTmp,m_szLinkFilter); } if(m_uPort != 6667) { szTmp = QString("%1Port").arg(szPrefix); pCfg->writeEntry(szTmp,m_uPort); } if(isIPv6()) { szTmp = QString("%1IPv6").arg(szPrefix); pCfg->writeEntry(szTmp,isIPv6()); } if(cacheIp()) { szTmp = QString("%1CacheIp").arg(szPrefix); pCfg->writeEntry(szTmp,cacheIp()); } if(useSSL()) { szTmp = QString("%1SSL").arg(szPrefix); pCfg->writeEntry(szTmp,useSSL()); } if(!enabledCAP()) { szTmp = QString("%1EnabledCAP").arg(szPrefix); pCfg->writeEntry(szTmp,enabledCAP()); } if(!enabledSTARTTLS()) { szTmp = QString("%1EnabledSTARTTLS").arg(szPrefix); pCfg->writeEntry(szTmp,enabledSTARTTLS()); } if(enabledSASL()) { szTmp = QString("%1EnabledSASL").arg(szPrefix); pCfg->writeEntry(szTmp,enabledSASL()); } if(proxy()!=-2) { szTmp = QString("%1Proxy").arg(szPrefix); pCfg->writeEntry(szTmp,proxy()); } if(!m_szUserIdentityId.isEmpty()) { szTmp = QString("%1UserIdentityId").arg(szPrefix); pCfg->writeEntry(szTmp,m_szUserIdentityId); } if(favorite()) { szTmp = QString("%1Favorite").arg(szPrefix); pCfg->writeEntry(szTmp,favorite()); } }
/* **************************************************************************** * * httpRequestSend - */ std::string 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& content_type, const std::string& content, bool useRush, bool waitForResponse, const std::string& acceptFormat, long timeoutInMilliseconds ) { char portAsString[16]; static unsigned long long callNo = 0; std::string result; std::string ip = _ip; struct curl_slist* headers = NULL; MemoryStruct* httpResponse = NULL; CURLcode res; int outgoingMsgSize = 0; CURL* curl; ++callNo; if (timeoutInMilliseconds == -1) { timeoutInMilliseconds = defaultTimeout; } LM_TRANSACTION_START("to", ip.c_str(), port, resource.c_str()); // Preconditions check if (port == 0) { LM_E(("Runtime Error (port is ZERO)")); LM_TRANSACTION_END(); return "error"; } if (ip.empty()) { LM_E(("Runtime Error (ip is empty)")); LM_TRANSACTION_END(); return "error"; } if (verb.empty()) { LM_E(("Runtime Error (verb is empty)")); LM_TRANSACTION_END(); return "error"; } if (resource.empty()) { LM_E(("Runtime Error (resource is empty)")); LM_TRANSACTION_END(); return "error"; } if ((content_type.empty()) && (!content.empty())) { LM_E(("Runtime Error (Content-Type is empty but there is actual content)")); LM_TRANSACTION_END(); return "error"; } if ((!content_type.empty()) && (content.empty())) { LM_E(("Runtime Error (Content-Type non-empty but there is no content)")); LM_TRANSACTION_END(); return "error"; } if ((curl = curl_easy_init()) == NULL) { LM_E(("Runtime Error (could not init libcurl)")); LM_TRANSACTION_END(); return "error"; } // Allocate to hold HTTP response httpResponse = new MemoryStruct; httpResponse->memory = (char*) malloc(1); // will grow as needed httpResponse->size = 0; // no data at this point // // Rush // Every call to httpRequestSend 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 must be setup. // if ((rushPort == 0) || (rushHost == "")) useRush = false; if (useRush) { char rushHeaderPortAsString[16]; uint16_t rushHeaderPort = 0; std::string rushHeaderIP = ""; std::string headerRushHttp = ""; rushHeaderIP = ip; rushHeaderPort = port; ip = rushHost; port = rushPort; snprintf(rushHeaderPortAsString, sizeof(rushHeaderPortAsString), "%d", rushHeaderPort); headerRushHttp = "X-relayer-host: " + rushHeaderIP + ":" + rushHeaderPortAsString; LM_T(LmtHttpHeaders, ("HTTP-HEADERS: '%s'", headerRushHttp.c_str())); headers = curl_slist_append(headers, headerRushHttp.c_str()); outgoingMsgSize += headerRushHttp.size(); if (protocol == "https:") { headerRushHttp = "X-relayer-protocol: https"; LM_T(LmtHttpHeaders, ("HTTP-HEADERS: '%s'", headerRushHttp.c_str())); headers = curl_slist_append(headers, headerRushHttp.c_str()); outgoingMsgSize += headerRushHttp.size(); } } snprintf(portAsString, sizeof(portAsString), "%d", port); // ----- User Agent char cvBuf[CURL_VERSION_MAX_LENGTH]; char headerUserAgent[HTTP_HEADER_USER_AGENT_MAX_LENGTH]; snprintf(headerUserAgent, sizeof(headerUserAgent), "User-Agent: orion/%s libcurl/%s", versionGet(), curlVersionGet(cvBuf, sizeof(cvBuf))); LM_T(LmtHttpHeaders, ("HTTP-HEADERS: '%s'", headerUserAgent)); headers = curl_slist_append(headers, headerUserAgent); outgoingMsgSize += strlen(headerUserAgent) + 1; // ----- Host char headerHost[HTTP_HEADER_HOST_MAX_LENGTH]; snprintf(headerHost, sizeof(headerHost), "Host: %s:%d", ip.c_str(), (int) port); LM_T(LmtHttpHeaders, ("HTTP-HEADERS: '%s'", headerHost)); headers = curl_slist_append(headers, headerHost); outgoingMsgSize += strlen(headerHost) + 1; // ----- Tenant if (tenant != "") { headers = curl_slist_append(headers, ("fiware-service: " + tenant).c_str()); outgoingMsgSize += tenant.size() + 16; // "fiware-service: " } // ----- Service-Path if (servicePath != "") { headers = curl_slist_append(headers, ("Fiware-ServicePath: " + servicePath).c_str()); outgoingMsgSize += servicePath.size() + strlen("Fiware-ServicePath: "); } // ----- X-Auth-Token if (xauthToken != "") { headers = curl_slist_append(headers, ("X-Auth-Token: " + xauthToken).c_str()); outgoingMsgSize += xauthToken.size() + strlen("X-Auth-Token: "); } // ----- Accept std::string acceptedFormats = "application/xml, application/json"; if (acceptFormat != "") { acceptedFormats = acceptFormat; } std::string acceptString = "Accept: " + acceptedFormats; headers = curl_slist_append(headers, acceptString.c_str()); outgoingMsgSize += acceptString.size(); // ----- Expect headers = curl_slist_append(headers, "Expect: "); outgoingMsgSize += 8; // from "Expect: " // ----- Content-length std::stringstream contentLengthStringStream; contentLengthStringStream << content.size(); std::string headerContentLength = "Content-length: " + contentLengthStringStream.str(); LM_T(LmtHttpHeaders, ("HTTP-HEADERS: '%s'", headerContentLength.c_str())); headers = curl_slist_append(headers, headerContentLength.c_str()); outgoingMsgSize += contentLengthStringStream.str().size() + 16; // from "Content-length: " outgoingMsgSize += content.size(); // ----- Content-type headers = curl_slist_append(headers, ("Content-type: " + content_type).c_str()); outgoingMsgSize += content_type.size() + 14; // from "Content-type: " // Check if total outgoing message size is too big if (outgoingMsgSize > MAX_DYN_MSG_SIZE) { LM_E(("Runtime Error (HTTP request to send is too large: %d bytes)", outgoingMsgSize)); // Cleanup curl environment curl_slist_free_all(headers); curl_easy_cleanup(curl); free(httpResponse->memory); delete httpResponse; LM_TRANSACTION_END(); return "error"; } // Contents const char* payload = content.c_str(); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, (u_int8_t*) payload); // Set up URL std::string url; if (isIPv6(ip)) url = "[" + ip + "]"; else url = ip; url = url + ":" + portAsString + (resource.at(0) == '/'? "" : "/") + resource; // Prepare CURL handle with obtained options curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, verb.c_str()); // Set HTTP verb curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); // Allow redirection (?) curl_easy_setopt(curl, CURLOPT_HEADER, 1); // Activate include the header in the body output curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); // Put headers in place curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &writeMemoryCallback); // Send data here curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*) httpResponse); // Custom data for response handling // // Timeout // // The parameter timeoutInMilliseconds holds the timeout time in milliseconds. // If the timeout time requested is 0, then no timeuot is used. // if (timeoutInMilliseconds != 0) { curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, timeoutInMilliseconds); } // Synchronous HTTP request LM_T(LmtClientOutputPayload, ("Sending message %lu to HTTP server: sending message of %d bytes to HTTP server", callNo, outgoingMsgSize)); res = curl_easy_perform(curl); if (res != CURLE_OK) { // // NOTE: This log line is used by the functional tests in cases/880_timeout_for_forward_and_notifications/ // So, this line should not be removed/altered, at least not without also modifying the functests. // LM_W(("Notification failure for %s:%s (curl_easy_perform failed: %s)", ip.c_str(), portAsString, curl_easy_strerror(res))); result = ""; } else { // The Response is here LM_I(("Notification Successfully Sent to %s", url.c_str())); result.assign(httpResponse->memory, httpResponse->size); } // Cleanup curl environment curl_slist_free_all(headers); curl_easy_cleanup(curl); free(httpResponse->memory); delete httpResponse; LM_TRANSACTION_END(); return result; }