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);
}
static int filter_duplicate_m_search(CgUpnpSSDPPacket *ssdpPkt)
{
    CgSysTime *timestamps = ssdpPkt->timestamps;
    int loc, s_length;
    char *id_string, *r_address, *st, port[6];
    CgSysTime curr_time;

    cg_log_debug_l4("Entering...\n");

    /* Initializing hash table to zero */
    if (!ssdpPkt->initialized) {
        ssdpPkt->initialized = 1;
        memset(timestamps, '\0', CG_UPNP_SSDP_FILTER_TABLE_SIZE * sizeof( CgSysTime ));
    }

    r_address = cg_string_getvalue(ssdpPkt->dgmPkt->remoteAddress);
    st = cg_upnp_ssdp_packet_getst(ssdpPkt);
    sprintf(port, "%d", ssdpPkt->dgmPkt->remotePort);

    /* Catenating remote address string with ssdp ST header field. */
    s_length = strlen( r_address ) + strlen( st ) + strlen( port );
    id_string = (char *)malloc( s_length + 1 );

    if ( NULL == id_string )
    {
        cg_log_debug_s("Memory allocation problem!\n");
        return FALSE;
    }

    memset(id_string, '\0', s_length + 1);

    cg_strcat(id_string, r_address );
    cg_strcat(id_string, port);
    cg_strcat(id_string, st );

    loc = simple_string_hash(id_string, CG_UPNP_SSDP_FILTER_TABLE_SIZE);

    cg_log_debug("Calculated hash: %d\n", loc);

    free(id_string);

    curr_time = cg_getcurrentsystemtime();

    if ( 0 == timestamps[loc] ) {
        timestamps[loc] = curr_time;
        cg_log_debug("First packet... Updating hash table.\n");
        return FALSE;
    }
    else if ( ( curr_time - timestamps[loc] ) < CG_UPNP_DEVICE_M_SEARCH_FILTER_INTERVAL ) {
        cg_log_debug("Filtering packet!\n");
        timestamps[loc] = curr_time;
        return TRUE;
    }
    else {
        timestamps[loc] = curr_time;
        cg_log_debug("Old timestamp found, just updating it.\n");
        return FALSE;
    }

    cg_log_debug_l4("Leaving...\n");
}