CgUpnpSSDPResponse *cg_upnp_ssdpresponse_new() { CgUpnpSSDPResponse*ssdpRes; cg_log_debug_l4("Entering...\n"); ssdpRes = cg_http_response_new(); cg_http_response_setversion(ssdpRes, CG_HTTP_VER11); cg_http_response_setstatuscode(ssdpRes, CG_HTTP_STATUS_OK); return ssdpRes; cg_log_debug_l4("Leaving...\n"); }
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); }
/** * Callback function for CURL to read each HTTP header line * CgStringTokenizer might have been a viable choice to do the parsing * of various fields. Then again, it would not have read correctly a * header line with, for example, the time (because of multiple use of colons): * Foo: 12:34:56 EEST DST */ static size_t cg_http_request_header_callback(void *ptr, size_t size, size_t nmemb, void *stream) { char* headerLine = NULL; char* name = NULL; char* value = NULL; CgStringTokenizer* strTok = NULL; CgHttpResponse* httpRes = NULL; int head = 0; int tail = 0; cg_log_debug_l4("Entering...\n"); if (stream == NULL || ptr == NULL) { return 0; } httpRes = (CgHttpResponse*) stream; headerLine = (char*) ptr; /* Read header items */ if (cg_strncmp(headerLine, CG_HTTP_VER11, cg_strlen(CG_HTTP_VER11)) == 0 || cg_strncmp(headerLine, CG_HTTP_VER10, cg_strlen(CG_HTTP_VER10)) == 0) { /* <HTTP/version> <status code> <reason phrase> */ strTok = cg_string_tokenizer_new(headerLine, CG_HTTP_STATUSLINE_DELIM); if (cg_string_tokenizer_hasmoretoken(strTok) == TRUE) { cg_http_response_setversion(httpRes, cg_string_tokenizer_nexttoken(strTok)); } if (cg_string_tokenizer_hasmoretoken(strTok) == TRUE) { cg_http_response_setstatuscode(httpRes, atoi(cg_string_tokenizer_nexttoken(strTok))); } if (cg_string_tokenizer_hasmoretoken(strTok) == TRUE) { value = cg_string_tokenizer_nextalltoken(strTok); cg_strrtrim(value, CG_HTTP_STATUSLINE_DELIM, cg_strlen(CG_HTTP_STATUSLINE_DELIM)); cg_http_response_setreasonphrase(httpRes, value); } cg_string_tokenizer_delete(strTok); } else { /* Find the header delimiter */ for (head = 0; head < size * nmemb; head++) { if (headerLine[head] == ':') { break; } } /* Unable to find a colon, this is not a valid header line */ if (head <= 0 || head >= (size * nmemb) - 1) { return size * nmemb; } /* Take the header name */ name = (char*) malloc(head + 1); if ( NULL == name ) { cg_log_debug_s("Memory allocation failure!\n"); return 0; } memcpy(name, headerLine, head); name[head] = '\0'; /* Skip colon and space(s) */ for (head++; head < size * nmemb; head++) { if (headerLine[head] != 0x20) { break; } } /* Unable to find anything sensible anymore */ if (head >= (size * nmemb) - 1) { return size * nmemb; } /* Find the end of the actual value, without CRLF */ for (tail = size * nmemb; tail > 0; tail --) { if (headerLine[tail] == '\r') { break; } else if (headerLine[tail] == '\n') { if (tail > 0 && headerLine[tail - 1] == '\r') { tail--; break; } } } /* Unable to find CRLF */ if (tail <= head) { free(name); return size * nmemb; } /* Take the header value */ value = (char*) malloc(tail - head + 1); if ( NULL == value ) { cg_log_debug_s("Memory allocation failure!\n"); return 0; } memcpy(value, headerLine + head, tail - head); value[tail - head] = '\0'; /* Set the header value to the response */ cg_http_response_setheadervalue(httpRes, name, value); free(name); free(value); } return size * nmemb; cg_log_debug_l4("Leaving...\n"); }