char *cg_upnp_event_subscription_tosidheaderstring(char *sid, char *buf, int bufSize) { int colonIdx; cg_log_debug_l4("Entering...\n"); colonIdx = cg_strstr(sid, CG_UPNP_SUBSCRIPTION_UUID); if (0 <= colonIdx) { cg_strncpy(buf, sid, bufSize); buf[bufSize-1] = '\0'; return buf; } #if defined(HAVE_SNPRINTF) snprintf(buf, bufSize, #else sprintf(buf, #endif "%s%s", CG_UPNP_SUBSCRIPTION_UUID, sid); return buf; cg_log_debug_l4("Leaving...\n"); }
static CgUpnpProperty *cg_upnp_property_createfromnode(CgXmlNode *varNode) { CgUpnpProperty *prop; char *varName; char *varValue; int colonIdx; cg_log_debug_l4("Entering...\n"); prop = cg_upnp_property_new(); if (varNode == NULL) return prop; // remove the event namespace varName = cg_xml_node_getname(varNode); colonIdx = cg_strstr(varName, ":"); if (0 <= colonIdx) varName = varName + colonIdx + 1; varValue = cg_xml_node_getvalue(varNode); cg_upnp_property_setname(prop, varName); cg_upnp_property_setvalue(prop, varValue); cg_log_debug_l4("Leaving...\n"); return prop; }
CgDictionary *cg_net_uri_getquerydictionary(CgNetURI *uri) { char *query; int queryOffset; int eqIdx, ampIdx; CgString *paramName; CgString *paramValue; if (NULL == uri->queryDictionary) uri->queryDictionary = cg_dictionary_new(); paramName = cg_string_new(); paramValue = cg_string_new(); query = cg_net_uri_getquery(uri); queryOffset = 0; eqIdx = cg_strstr(query, "="); while (0 < eqIdx) { ampIdx = cg_strstr(query + queryOffset, "&"); if (ampIdx <= 0) { ampIdx = cg_strstr(query + queryOffset, "#"); if (ampIdx <= 0) ampIdx = cg_strlen(query + queryOffset); } if (ampIdx <= eqIdx) break; cg_string_setnvalue(paramName, query + queryOffset, eqIdx); cg_string_setnvalue(paramValue, query + queryOffset + eqIdx + 1, (ampIdx - eqIdx -1)); cg_dictionary_setvalue(uri->queryDictionary, cg_string_getvalue(paramName), cg_string_getvalue(paramValue)); queryOffset += ampIdx + 1; eqIdx = cg_strstr(query + queryOffset, "="); } cg_string_delete(paramName); cg_string_delete(paramValue); return uri->queryDictionary; }
const char *cg_upnp_event_subscription_getsid(const char *headerValue) { ssize_t colonIdx; cg_log_debug_l4("Entering...\n"); colonIdx = cg_strstr(headerValue, ":"); if (colonIdx < 0) return headerValue; cg_log_debug_l4("Leaving...\n"); return (headerValue + colonIdx + 1); }
CgTime cg_upnp_event_subscription_gettimeout(const char *headerValue) { ssize_t minusIdx; long timeout; cg_log_debug_l4("Entering...\n"); minusIdx = cg_strstr(headerValue, "-"); if (minusIdx < 0) return CG_UPNP_SUBSCRIPTION_INFINITE_VALUE; timeout = cg_str2long(headerValue + minusIdx + 1); if (timeout == 0) return CG_UPNP_SUBSCRIPTION_INFINITE_VALUE; if (timeout < 0) timeout =-timeout; return timeout; cg_log_debug_l4("Leaving...\n"); }
void cg_upnp_event_subscription_request_setsid(CgUpnpSubscriptionRequest *subReq, const char *sid) { CgString *headerSID; ssize_t uuidIdx; cg_log_debug_l4("Entering...\n"); headerSID = cg_string_new(); uuidIdx = cg_strstr(sid, CG_UPNP_ST_UUID_DEVICE); if (uuidIdx < 0) cg_string_addvalue(headerSID, CG_UPNP_ST_UUID_DEVICE ":"); cg_string_addvalue(headerSID, sid); cg_http_packet_setheadervalue(((CgHttpPacket*)subReq), CG_HTTP_SID, cg_string_getvalue(headerSID)); cg_string_delete(headerSID); cg_log_debug_l4("Leaving...\n"); }
char *cg_upnp_usn_getudn(char *usn, char *udnBuf, int udnBufLen) { int idx; cg_log_debug_l4("Entering...\n"); if (usn == NULL) { udnBuf[0] = '\0'; return udnBuf; } idx = cg_strstr(usn, "::"); if (idx < 0) { cg_strncpy(udnBuf, usn, udnBufLen); udnBuf[udnBufLen-1] = '\0'; cg_strtrim(udnBuf, " ", 1); return udnBuf; } if ( idx < udnBufLen ) { cg_strncpy(udnBuf, usn, (idx)); udnBuf[idx] = '\0'; } else { cg_strncpy(udnBuf, usn, udnBufLen); udnBuf[udnBufLen-1] = '\0'; } cg_strtrim(udnBuf, " ", 1); cg_log_debug("UDN: %s\n", udnBuf); return udnBuf; cg_log_debug_l4("Leaving...\n"); }
CgXmlNode *cg_soap_request_getbodynode(CgSoapRequest *soapReq) { CgXmlNode *envNode; CgXmlNode *bodyNode = NULL; CgXmlAttribute *attr; char *name; CgStringTokenizer *tok; char *nsPrefix; size_t bodyLen; char *body; cg_log_debug_l4("Entering...\n"); envNode = cg_soap_request_getenvelopenode(soapReq); if (envNode == NULL) return NULL; if (cg_xml_node_haschildnodes(envNode) == FALSE) return NULL; /* We cannot assume the namespace prefix for Body is 's'. According to spec, it could be anything... */ for (attr = cg_xml_node_getattributes(envNode); attr != NULL; attr = cg_xml_attribute_next(attr)) { /* First, find the namespace declaration attribute. */ /* Note: We must take a copy of the attr name. Tokenizer doesn't do it (by default) */ name = cg_strdup( cg_xml_attribute_getname(attr) ); tok = cg_string_tokenizer_new(name, ":"); nsPrefix = cg_string_tokenizer_nexttoken(tok); if ( -1 != cg_strstr(nsPrefix, "xmlns")) { /* This attribute is a namespace declaration. Check is it the one defined for SOAP. */ if (cg_strcmp(cg_xml_attribute_getvalue(attr), CG_SOAP_XMLNS_URL) == 0) { /* This namespace declaration is correct. Use it to find the body node... */ if (cg_string_tokenizer_hasmoretoken(tok)) { /* There is a prefix */ nsPrefix = cg_string_tokenizer_nexttoken(tok); bodyLen = cg_strlen(nsPrefix) + cg_strlen(CG_SOAP_DELIM) + cg_strlen(CG_SOAP_BODY) + 1; /* +1 for trailing '\0'*/ body = (char*)malloc(bodyLen); if ( NULL == body ) { cg_log_debug_s("Memory allocation failure!\n"); return NULL; } #if defined(HAVE_SNPRINTF) snprintf(body, bodyLen, "%s%s%s", nsPrefix, CG_SOAP_DELIM, CG_SOAP_BODY); #else sprintf(body, "%s%s%s", nsPrefix, CG_SOAP_DELIM, CG_SOAP_BODY); #endif bodyNode = cg_xml_node_getchildnode(envNode, body); free(body); } else { /* No prefix */ bodyNode = cg_xml_node_getchildnode(envNode, CG_SOAP_BODY); } /* Free memory before leaving the loop */ cg_string_tokenizer_delete(tok); free(name); break; } } cg_string_tokenizer_delete(tok); free(name); } cg_log_debug_l4("Leaving...\n"); return bodyNode; }
void cg_upnp_dms_youtube_http_listener(CgHttpRequest *httpReq) { CgUpnpMediaServer *dms; CgUpnpDevice *dev; char *httpURI; int contentMD5Idx; char *contentMd5; CgHttpResponse *httpRes; CgSocket *sock; char chunkedChar[32]; BOOL isHeadRequest; struct stat fileStat; off_t fileSize; FILE *fp; char readBuf[CG_FILE_READ_CHUNK_SIZE]; off_t nRead; off_t nReadCnt; off_t nWroteCnt; char contentFile[CG_MD5_STRING_BUF_SIZE+8]; dev = (CgUpnpDevice *)cg_http_request_getuserdata(httpReq); if (!dev) { cg_http_request_postbadrequest(httpReq); return; } dms = (CgUpnpMediaServer *)cg_upnp_device_getuserdata(dev); if (!dms) { cg_http_request_postbadrequest(httpReq); return; } httpURI = cg_http_request_geturi(httpReq); if (cg_strlen(httpURI) <= 0) { cg_http_request_postbadrequest(httpReq); return; } if (cg_strstr(httpURI, CG_UPNP_MEDIA_YOUTUBE_RESURL_PATH) < 0) { cg_upnp_device_httprequestrecieved(httpReq); return; } contentMD5Idx = cg_strrchr(httpURI, "/", 1); if (contentMD5Idx < 0) { cg_http_request_postbadrequest(httpReq); return; } contentMd5 = httpURI + contentMD5Idx + 1; cg_strcpy(contentFile, contentMd5); cg_strcat(contentFile, "." CG_UPNP_MEDIA_YOUTUBE_TRANSCODE_FILEEXT); cg_upnp_dms_lock(dms); isHeadRequest = cg_http_request_isheadrequest(httpReq); httpRes = cg_http_response_new(); #if defined(CG_USE_CHUNKED_STREAM) cg_http_response_setversion(httpRes, CG_HTTP_VER11); #else cg_http_response_setversion(httpRes, CG_HTTP_VER10); #endif cg_http_response_setstatuscode(httpRes, CG_HTTP_STATUS_OK); cg_http_response_setcontenttype(httpRes, CG_UPNP_MEDIA_YOUTUBE_CONTENT_MIMETYPE); sock = cg_http_request_getsocket(httpReq); cg_socket_settimeout(sock, 0); fileSize = 0; if (stat(contentFile, &fileStat) == 0) fileSize = fileStat.st_size; #if defined(CG_USE_CHUNKED_STREAM) cg_http_packet_setheadervalue((CgHttpPacket*)httpRes, "Transfer-Encoding", "chunked"); #else cg_http_response_setcontentlength(httpRes, fileSize); #endif cg_http_request_postresponse(httpReq, httpRes); if (0 < fileSize) { nReadCnt = 0; nWroteCnt = 0; fp = fopen(contentFile, "rb"); if (fp) { nRead = fread(readBuf, sizeof(char), CG_FILE_READ_CHUNK_SIZE, fp); while (nReadCnt < fileSize && 0 < nRead) { nReadCnt += nRead; #if defined(CG_USE_CHUNKED_STREAM) sprintf(chunkedChar, "%x%s", nRead, CG_HTTP_CRLF); cg_socket_write(sock, chunkedChar, cg_strlen(chunkedChar)); #endif nWroteCnt += cg_socket_write(sock, readBuf, nRead); #if defined(CG_USE_CHUNKED_STREAM) cg_socket_write(sock, CG_HTTP_CRLF, sizeof(CG_HTTP_CRLF)-1); #endif nRead = fread(readBuf, sizeof(char), CG_FILE_READ_CHUNK_SIZE, fp); } fclose(fp); } } #if defined(CG_USE_CHUNKED_STREAM) sprintf(chunkedChar, "%x%s", 0, CG_HTTP_CRLF); cg_socket_write(sock, chunkedChar, cg_strlen(chunkedChar)); #endif cg_socket_close(sock); cg_http_response_delete(httpRes); cg_upnp_dms_unlock(dms); }
void cg_upnp_device_ssdpmessagereceived(CgUpnpDevice *dev, CgUpnpSSDPPacket *ssdpPkt, int filter) { BOOL isRootDev; char *ssdpST; char *devUDN, *devType; char ssdpMsg[CG_UPNP_SSDP_HEADER_LINE_MAXSIZE]; char deviceUSN[CG_UPNP_SSDP_HEADER_LINE_MAXSIZE]; #if defined WINCE size_t n; #else int n; #endif CgUpnpService *service; CgUpnpDevice *childDev; char *ssdpMXString; int ssdpMX; cg_log_debug_l4("Entering...\n"); ssdpMXString = cg_http_headerlist_getvalue(ssdpPkt->headerList, CG_HTTP_MX); ssdpST = cg_upnp_ssdp_packet_getst(ssdpPkt); /* Check if this ssdp packet has already been checked + filtered */ if (filter) { /**************************************** * Request line * Check the request line for errors, this is not ideal as it currently only * checks for the presence of the strings and not the order. ***************************************/ /**** check for M-SEARCH and return if not found ****/ if (cg_strstr(cg_string_getvalue(ssdpPkt->dgmPkt->data), CG_HTTP_MSEARCH) < 0) return; /**** check for * and return if not found ****/ if (cg_strstr(cg_string_getvalue(ssdpPkt->dgmPkt->data), "*") < 0) return; /**** check HTTP version and return if not found ****/ if (cg_strstr(cg_string_getvalue(ssdpPkt->dgmPkt->data), CG_HTTP_VER11) < 0) return; /**************************************** * check HOST header, should always be 239.255.255.250:1900, return if incorrect ***************************************/ if (cg_strcmp(cg_upnp_ssdp_packet_gethost(ssdpPkt), CG_UPNP_SSDP_MULTICAST_ADDRESS) != 0) return; /**************************************** * check MAN header, return if incorrect ***************************************/ if (cg_upnp_ssdp_packet_isdiscover(ssdpPkt) == FALSE) return; /**************************************** * check MX header, return if incorrect ***************************************/ if (ssdpMXString == NULL || cg_strlen(ssdpMXString)==0) /* return if the MX value does not exist or is empty */ return; /* check if MX value is not an integer */ for (n=0; n<strlen(ssdpMXString); n++) { if (isdigit(ssdpMXString[n]) == 0) /* MX value contains a non-digit so is invalid */ return; } /**************************************** * check ST header and if empty return ***************************************/ if (cg_strlen(ssdpST) <= 0) return; /* Check if we have received this search recently * and ignore duplicates. */ if ( filter_duplicate_m_search(ssdpPkt) ) return; ssdpMX = cg_upnp_ssdp_packet_getmx(ssdpPkt); cg_log_debug("Sleeping for a while... (MX:%d)\n", ssdpMX); cg_waitrandom((ssdpMX*1000)/4); } isRootDev = cg_upnp_device_isrootdevice(dev); if (cg_upnp_st_isalldevice(ssdpST) == TRUE) { /* for root device only */ if (isRootDev == TRUE) { cg_upnp_device_getnotifydevicent(dev, ssdpMsg, sizeof(ssdpMsg)); cg_upnp_device_getnotifydeviceusn(dev, deviceUSN, sizeof(deviceUSN)); cg_upnp_device_postsearchresponse(dev, ssdpPkt, ssdpMsg, deviceUSN); } /* for all devices send */ /* device type : device version */ cg_upnp_device_getnotifydevicetypent(dev, ssdpMsg, sizeof(ssdpMsg)); cg_upnp_device_getnotifydevicetypeusn(dev, deviceUSN, sizeof(deviceUSN)); cg_upnp_device_postsearchresponse(dev, ssdpPkt, ssdpMsg, deviceUSN); /* device UUID */ cg_upnp_device_postsearchresponse(dev, ssdpPkt, cg_upnp_device_getudn(dev), cg_upnp_device_getudn(dev)); } else if (cg_upnp_st_isrootdevice(ssdpST) == TRUE) { if (isRootDev == TRUE) { cg_upnp_device_getnotifydeviceusn(dev, deviceUSN, sizeof(deviceUSN)); cg_upnp_device_postsearchresponse(dev, ssdpPkt, CG_UPNP_ST_ROOT_DEVICE, deviceUSN); } } else if (cg_upnp_st_isuuiddevice(ssdpST) == TRUE) { devUDN = cg_upnp_device_getudn(dev); if (cg_streq(ssdpST, devUDN) == TRUE) cg_upnp_device_postsearchresponse(dev, ssdpPkt, devUDN, devUDN); } else if (cg_upnp_st_isurn(ssdpST) == TRUE) { devType = cg_upnp_device_getdevicetype(dev); if (cg_streq(ssdpST, devType) == TRUE) { cg_upnp_device_getnotifydevicetypeusn(dev, deviceUSN, sizeof(deviceUSN)); cg_upnp_device_postsearchresponse(dev, ssdpPkt, devType, deviceUSN); } } for (service=cg_upnp_device_getservices(dev); service != NULL; service = cg_upnp_service_next(service)) cg_upnp_service_ssdpmessagereceived(service, ssdpPkt); for (childDev = cg_upnp_device_getdevices(dev); childDev != NULL; childDev = cg_upnp_device_next(childDev)) cg_upnp_device_ssdpmessagereceived(childDev, ssdpPkt, FALSE); cg_log_debug_l4("Leaving...\n"); }
CgXmlNode *cg_xml_node_getchildnodewithnamespace(CgXmlNode *node, char *name, char *ns, BOOL ignoreNs) { char *nameWithPrefix = NULL; int nameLen = 0; int nameIdx; CgXmlNode *result = NULL; CgXmlNode *child = NULL; char *nodeName = NULL; cg_log_debug_l4("Entering...\n"); if (node == NULL) return NULL; if (name == NULL) return NULL; if (ignoreNs == TRUE) { for (child = cg_xml_node_getchildnodelist(node); child != NULL; child = cg_xml_node_next(child)) { nodeName = cg_xml_node_getname(child); if (nodeName == NULL) continue; nameIdx = cg_strstr(nodeName, ":"); if (nameIdx < 0) { /* No prefix (no ':') */ if (cg_strcasecmp(nodeName, name) == 0) return child; } else { if (cg_strcasecmp(&(nodeName[nameIdx+1]), name) == 0) return child; } } return NULL; } else { if (ns == NULL) { /* When ns is NULL, this works like normal ..._getchildnode */ return cg_xml_node_getchildnode(node, name); } nameLen = cg_strlen(name) + cg_strlen(ns) + 1; /* Not including the terminating \0 */ nameWithPrefix = (char*) malloc(nameLen + 1); if (nameWithPrefix == NULL) return NULL; #if defined(HAVE_SNPRINTF) snprintf(nameWithPrefix, nameLen + 1, "%s:%s", ns, name); #else sprintf(nameWithPrefix, "%s:%s", ns, name); #endif result = cg_xml_node_getchildnode(node, nameWithPrefix); free(nameWithPrefix); return result; } cg_log_debug_l4("Leaving...\n"); }
char *cg_net_uri_unescapestring(char *buf, int bufSize, CgString *retBuf) { #if defined(CG_HTTP_CURL) char *tmp; #else int n; char hexStr[3]; long hex; unsigned char c; #endif int idx = 0; #if defined(CG_USE_NET_URI_ESCAPESTRING_SKIP) int tmpIdx = 0; #endif cg_log_debug_l4("Entering...\n"); if (!retBuf) return NULL; /* Check if URI is already escaped */ if (cg_net_uri_isescapedstring(buf + idx, bufSize) == TRUE) return buf; /* We can safely assume that the non-path part is already escaped */ #if defined(CG_USE_NET_URI_ESCAPESTRING_SKIP) idx = cg_strstr(buf, CG_NET_URI_PROTOCOL_DELIM); if (idx > 0) { idx = idx + cg_strlen(CG_NET_URI_PROTOCOL_DELIM); tmpIdx = cg_strstr(buf + idx, CG_NET_URI_SLASH_DELIM); if (tmpIdx > 0) idx += tmpIdx + cg_strlen(CG_NET_URI_SLASH_DELIM); } else { idx = 0; } #endif if (bufSize < 1) bufSize = cg_strlen(buf) + 1; #if defined(CG_HTTP_CURL) tmp = curl_unescape(buf + idx, 0); if (tmp == NULL) return NULL; cg_string_addvalue(retBuf, tmp); cg_log_debug_s("%s ==> %s\n", buf + idx, tmp); curl_free(tmp); #else for (n=0; n<bufSize;) { c = (unsigned char)buf[n]; if (buf[n] == '%' && cg_net_uri_isalphanumchar(buf[n+1]) && cg_net_uri_isalphanumchar(buf[n+2])) { hexStr[0] = buf[n+1]; hexStr[1] = buf[n+2]; hexStr[2] = '\0'; hex = strtol(hexStr, NULL, 16); c = (unsigned char)hex; n += 3; } else n++; cg_string_naddvalue(retBuf, (char *)&c, 1); } #endif cg_log_debug_l4("Leaving...\n"); return cg_string_getvalue(retBuf); }
void cg_net_uri_setvalue(CgNetURI *uri, char *value) { char *protocol; int uriLen; int currIdx; int protoIdx; int atIdx; int colonIdx; int shashIdx; char *host; int eblacketIdx; CgString *hostStr; CgString *portStr; int hostLen; int sharpIdx; int questionIdx; int queryLen; cg_log_debug_l4("Entering...\n"); uriLen = cg_strlen(value); cg_net_uri_clear(uri); cg_net_uri_seturi(uri, value); currIdx = 0; /*** Protocol ****/ protoIdx = cg_strstr(value, CG_NET_URI_PROTOCOL_DELIM); if (0 < protoIdx) { cg_string_setnvalue(uri->protocol, value, protoIdx); currIdx += protoIdx + cg_strlen(CG_NET_URI_PROTOCOL_DELIM); } /*** User (Password) ****/ atIdx = cg_strstr(value+currIdx, CG_NET_URI_USER_DELIM); if (0 < atIdx) { colonIdx = cg_strstr(value+currIdx, CG_NET_URI_COLON_DELIM); /**** Thanks for Theo Beisch (2005/08/25) ****/ if (0 < colonIdx && colonIdx<atIdx) { cg_string_setnvalue(uri->user, value+currIdx, colonIdx); cg_string_setnvalue(uri->password, value+currIdx+colonIdx+1, atIdx-(colonIdx+1)); } else cg_string_setnvalue(uri->user, value+currIdx, atIdx - currIdx); currIdx += atIdx + 1; } /*** Host (Port) ****/ shashIdx = cg_strstr(value+currIdx, CG_NET_URI_SLASH_DELIM); if (0 < shashIdx) cg_string_setnvalue(uri->host, value+currIdx, shashIdx); else if (cg_net_uri_isabsolute(uri) == TRUE) cg_string_setnvalue(uri->host, value+currIdx, cg_strlen(value) - currIdx); host = cg_net_uri_gethost(uri); colonIdx = cg_strrchr(host, CG_NET_URI_COLON_DELIM, 1); eblacketIdx = cg_strrchr(host, CG_NET_URI_EBLACET_DELIM, 1); if (0 < colonIdx && eblacketIdx < colonIdx) { hostStr = cg_string_new(); cg_string_setvalue(hostStr, host); hostLen = cg_string_length(hostStr); /**** host ****/ cg_string_setnvalue(uri->host, cg_string_getvalue(hostStr), colonIdx); host = cg_net_uri_gethost(uri); if (0 < hostLen) { if (host[0] == '[' && host[hostLen-1] == ']') cg_string_setnvalue(uri->host, cg_string_getvalue(hostStr)+1, colonIdx-2); } /**** port ****/ portStr = cg_string_new(); cg_string_setnvalue(portStr, cg_string_getvalue(hostStr)+colonIdx+1, hostLen- colonIdx-1); uri->port = atoi(cg_string_getvalue(portStr)); cg_string_delete(portStr); cg_string_delete(hostStr); } else { uri->port = CG_NET_URI_KNKOWN_PORT; protocol = cg_net_uri_getprotocol(uri); if (cg_strcmp(protocol, CG_NET_URI_PROTOCOL_HTTP) == 0) uri->port = CG_NET_URI_DEFAULT_HTTP_PORT; if (cg_strcmp(protocol, CG_NET_URI_PROTOCOL_FTP) == 0) uri->port = CG_NET_URI_DEFAULT_FTP_PORT; } if (shashIdx > 0) currIdx += shashIdx; /* Handle relative URL */ if (cg_net_uri_isabsolute(uri) == FALSE) { cg_string_addvalue(uri->path, value); } else { /* First set path simply to the rest of URI */ cg_string_setnvalue(uri->path, value+currIdx, uriLen-currIdx); } /**** Path (Query/Fragment) ****/ sharpIdx = cg_strstr(value+currIdx, CG_NET_URI_SHARP_DELIM); if (0 < sharpIdx) { cg_string_setnvalue(uri->path, value+currIdx, sharpIdx); cg_string_setnvalue(uri->fragment, value+currIdx+sharpIdx+1, uriLen-(currIdx+sharpIdx+1)); } questionIdx = cg_strstr(value+currIdx, CG_NET_URI_QUESTION_DELIM); if (0 < questionIdx) { cg_string_setnvalue(uri->path, value+currIdx, questionIdx); queryLen = uriLen-(currIdx+questionIdx+1); if (0 < sharpIdx) queryLen -= uriLen - (currIdx+sharpIdx); cg_string_setnvalue(uri->query, value+currIdx+questionIdx+1, queryLen); } cg_log_debug_l4("Leaving...\n"); }
CgHttpResponse *cg_http_request_post(CgHttpRequest *httpReq, char *ipaddr, int port) { CgHttpResponse *httpRes; BOOL newCurl = FALSE; CURL *curl; CgHttpHeader *reqHeader; struct curl_slist *curlHeaderList; CgString *headerStr; CURLcode res; char *uri, *method; char url[CG_NET_URI_MAXLEN]; long retcode; #ifdef CG_SHOW_TIMINGS struct timeval start_time, end_time, elapsed_time; #endif cg_log_debug_l4("Entering...\n"); #ifdef CG_SHOW_TIMINGS gettimeofday(&start_time, NULL); #endif httpRes = httpReq->httpRes; /* Clear the response data because new data will not * overwrite it, but it is appended to the end */ cg_string_clear(httpRes->content); cg_log_debug_s("Posting HTTP request (Curl)\n"); cg_http_request_print(httpReq); cg_http_persistentconnection_lock(); #ifdef CG_HTTP_USE_PERSISTENT_CONNECTIONS cg_log_debug_s("Looking for persistent connection to %s, port %d\n", ipaddr, port); curl = (CURL*)cg_http_persistentconnection_get(ipaddr, port); if (curl == NULL) { cg_log_debug_s("Persistent connection not found...\n"); #endif curl = curl_easy_init(); if (curl == NULL) { cg_http_persistentconnection_unlock(); return httpReq->httpRes; } #ifdef CG_HTTP_USE_PERSISTENT_CONNECTIONS newCurl = TRUE; } #endif method = cg_http_request_getmethod(httpReq); uri = cg_http_request_geturi(httpReq); /**** method ****/ curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, method); /**** url ****/ if (uri && cg_strstr(uri, CG_NET_URI_PROTOCOL_DELIM) > 0) { curl_easy_setopt(curl, CURLOPT_URL, uri); } else { cg_net_gethosturl(ipaddr, port, uri, url, sizeof(url)); curl_easy_setopt(curl, CURLOPT_URL, url); cg_log_debug_s("\n\nCURL: %s\n\n", url); } /**** header ****/ curlHeaderList = NULL; headerStr = cg_string_new(); for (reqHeader = cg_http_request_getheaders(httpReq); reqHeader; reqHeader = cg_http_header_next(reqHeader)) { cg_string_setvalue(headerStr, cg_http_header_getname(reqHeader)); if (cg_string_addvalue(headerStr, CG_HTTP_COLON CG_HTTP_SP) && cg_string_addvalue(headerStr, cg_http_header_getvalue(reqHeader))) curlHeaderList = curl_slist_append(curlHeaderList, cg_string_getvalue(headerStr)); } cg_string_delete(headerStr); /* Disable Expect header because it causes IOP issues */ curlHeaderList = curl_slist_append(curlHeaderList, "Expect:"); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curlHeaderList); /**** content ****/ /*if (cg_http_request_ispostrequest(httpReq) == TRUE) {*/ if (cg_http_request_getcontentlength(httpReq) > 0) { curl_easy_setopt(curl, CURLOPT_POSTFIELDS, cg_http_request_getcontent(httpReq)); curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, cg_http_request_getcontentlength(httpReq)); } else { curl_easy_setopt(curl, CURLOPT_POSTFIELDS, NULL); curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, 0); } /* This has to be enabled for progress callback to be called */ curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE); /* Used for checking stack state during curl easy perform */ curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, cg_http_request_progress_callback); /**** response header callback ****/ curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, cg_http_request_header_callback); curl_easy_setopt(curl, CURLOPT_WRITEHEADER, (void *)httpRes); /**** response content callback ****/ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, cg_http_request_content_callback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)httpRes); /**** useragent ****/ curl_easy_setopt(curl, CURLOPT_USERAGENT, cg_http_request_getuseragent(httpReq) ); /**** Prohibit curl from using signals ****/ curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); /**** Set the connection timeout so we don't wait forever ****/ curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, CG_HTTP_CURL_CONNECTTIMEOUT); curl_easy_setopt(curl, CURLOPT_TIMEOUT, CG_HTTP_CONN_TIMEOUT); #ifdef CG_SHOW_TIMINGS cg_log_debug_s("\nRequest: %s%s%s\n", method, CG_HTTP_SP, url); #endif /* Get the XML document with CURL */ res = curl_easy_perform(curl); if (res != CURLE_OK) cg_log_debug_s("curl_easy_perform: %s\n", curl_easy_strerror(res)); /* Set the content length, if it wasn't said in the header */ if (cg_http_response_getcontentlength(httpRes) <= 0) { cg_http_response_setcontentlength(httpRes, cg_string_length(httpRes->content)); } curl_slist_free_all(curlHeaderList); curl_easy_getinfo (curl, CURLINFO_HTTP_CODE, &retcode); cg_http_response_setstatuscode(httpRes, retcode); #ifdef CG_SHOW_TIMINGS gettimeofday(&end_time, NULL); timersub(&end_time, &start_time, &elapsed_time); cg_log_debug_s("Getting HTTP-response completed. Elapsed time: " "%ld msec\n", ((elapsed_time.tv_sec*1000) + (elapsed_time.tv_usec/1000))); cg_total_elapsed_time += (elapsed_time.tv_sec*1000000)+ (elapsed_time.tv_usec); #endif #ifdef CG_HTTP_USE_PERSISTENT_CONNECTIONS if (newCurl) { cg_log_debug_s("Putting new connection into cache: %s %d\n", ipaddr, port); cg_http_persistentconnection_put(ipaddr, port, curl); } #else curl_easy_cleanup(curl); #endif cg_http_persistentconnection_unlock(); cg_log_debug_s("Response for HTTP request (Curl)\n"); cg_http_response_print(httpReq->httpRes); return httpReq->httpRes; cg_log_debug_l4("Leaving...\n"); }