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);
}
Exemple #3
0
/**
 * 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");
}