예제 #1
0
/**
 * Find a device from the controlpoint by the UDN of the device.
 *
 * \param ctrlPoint Controlpoint in question
 * \param udn Type of the device
 *
 */
CgUpnpDevice *cg_upnp_controlpoint_getdevicebyudn(CgUpnpControlPoint *ctrlPoint,
						  char *udn)
{
	CgUpnpDevice *dev = NULL;
	CgUpnpDevice *childDev = NULL;
	
	cg_log_debug_l4("Entering...\n");

	if (cg_strlen(udn) <= 0 || ctrlPoint == NULL)
	{
		return NULL;
	}
	
	for (dev = cg_upnp_controlpoint_getdevices(ctrlPoint); 
	     dev != NULL;
	     dev = cg_upnp_device_next(dev))
	{
		if (cg_strcmp(cg_upnp_device_getudn(dev), udn) == 0)
		{
			return dev;
		}
		childDev = cg_upnp_device_getdevicebyudn(dev, udn);
		if (childDev != NULL)
		{
			return childDev;
		}
	}

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

	return NULL;
}
예제 #2
0
int cg_net_interface_cmp(CgNetworkInterface *netIfA, 
			 CgNetworkInterface *netIfB)
{
	cg_log_debug_l4("Entering...\n");

	if (netIfA == NULL && netIfB == NULL) return 0;
	if (netIfA == NULL && netIfB != NULL) return 1;
	if (netIfA != NULL && netIfB == NULL) return -1;
	
	return cg_strcmp(cg_net_interface_getaddress(netIfA), 
			 cg_net_interface_getaddress(netIfB));

	cg_log_debug_l4("Leaving...\n");
}
예제 #3
0
파일: curi.c 프로젝트: Deanzou/DLNA
BOOL cg_net_uri_isequivalent(char *url, char *relative_url)
{
	CgNetURI *u;
	char *path;
	BOOL ret;

	u = cg_net_uri_new();
	cg_net_uri_set(u, url);

	path = cg_net_uri_getpath(u);
	ret = cg_strcmp(path, relative_url) == 0;

	cg_net_uri_delete(u);
	return ret;
}
예제 #4
0
/**
 * Find a device from the controlpoint by the type of the device.
 * This function searches for devices, whose *type part* (i.e. not including
 * the version) of the device type string matches the given string.
 * For example: "urn:schemas-upnp-org:device:FooDevice". If you need
 * to know the version of a device, use \ref cg_upnp_devicetype_getversion
 *
 * \param ctrlPoint Controlpoint in question
 * \param type Type of the device
 *
 */
CgUpnpDevice *cg_upnp_controlpoint_getdevicebytype(CgUpnpControlPoint *ctrlPoint,
						   char *type)
{
	CgUpnpDevice *dev = NULL;
	CgUpnpDevice *childDev = NULL;
	const char* typeString = NULL;
	char* part = NULL;
	
	cg_log_debug_l4("Entering...\n");

	if (cg_strlen(type) <= 0 || ctrlPoint == NULL)
	{
		return NULL;
	}

	for (dev = cg_upnp_controlpoint_getdevices(ctrlPoint);
	     dev != NULL;
	     dev = cg_upnp_device_next(dev))
	{
		typeString = cg_upnp_device_getdevicetype(dev);
		if (typeString != NULL)
		{
			part = cg_upnp_devicetype_getschematype(typeString);
			if (cg_strcmp(part, type) == 0)
			{
				free(part);
				
				return dev;
			}
			else
			{
				free(part);
			}
		}
				
		childDev = cg_upnp_device_getdevicebytype(dev, type);
		if (childDev != NULL)
		{
			return childDev;
		}
	}
	
	cg_log_debug_l4("Leaving...\n");

	return NULL;
}
예제 #5
0
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_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");
}
예제 #7
0
파일: curi.c 프로젝트: Deanzou/DLNA
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");
}
예제 #8
0
static void cg_http_server_clientthread(CgThread *thread)
{
	CgHttpServerClientData *clientData;
	CgHttpServer *httpServer;
	CgSocket *clientSock;
	void *httpServerUserData;
	CgHttpRequest *httpReq;
	char *version = NULL;

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

	clientData = (CgHttpServerClientData *)cg_thread_getuserdata(thread);
	httpServer = clientData->httpServer;
	clientSock = clientData->clientSock;
	httpServerUserData = cg_http_server_getuserdata(httpServer);

	httpReq = cg_http_request_new();
	cg_http_request_setsocket(httpReq, clientSock);

	/**** Thanks for Makela Aapo (10/31/05) ****/
	while (cg_http_request_read(httpReq, clientSock) == TRUE && cg_thread_isrunnable(thread) == TRUE) {
		/* Check some validity of the request */
		version = cg_http_request_getversion(httpReq);
		if (cg_strcmp(version, CG_HTTP_VER11) == 0)
		{
			/* According to HTTP/1.1 spec, we must not tolerate
			   HTTP/1.1 request without HOST-header */
			if (cg_http_request_gethost(httpReq) == NULL)
			{
				cg_http_request_postbadrequest(httpReq);
				continue;
			}
		}

		if (httpServer->listener != NULL) {
            cg_http_request_setuserdata(httpReq, httpServerUserData);
			httpServer->listener(httpReq);
		}

		/* Close connection according to HTTP version and headers */
		if (cg_strcmp(version, CG_HTTP_VER10) == 0)
		{
			/* Terminate connection after HTTP/1.0 request */
			break;
		}

		/* We are having HTTP/1.1 or better => terminate, if requested */
		if (cg_http_request_iskeepaliveconnection(httpReq) == FALSE)
		{
			break;
		}
	}

	cg_log_debug_s("Dropping HTTP client\n");
	cg_http_request_delete(httpReq);

	cg_socket_close(clientSock);
	cg_socket_delete(clientSock);

	cg_http_server_clientdata_delete(clientData);
	cg_thread_setuserdata(thread, NULL);

    // This code frequently crashes. mutex lock referencing free'd memory.
	cg_http_server_lock(httpServer);
	cg_thread_remove(thread);
	cg_http_server_unlock(httpServer);

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

	cg_thread_delete(thread);
}
예제 #9
0
BOOL cg_upnp_controlpoint_ipchanged(CgUpnpControlPoint *ctrlPoint)
{
	CgNetworkInterfaceList *current, *added, *removed;
	CgNetworkInterface *netIf;
	CgUpnpDevice *dev, *tmp;
	CgUpnpSSDPPacket *ssdpPkt;
	char *address;
	
	cg_log_debug_l4("Entering...\n");

	current = cg_net_interfacelist_new();
	added = cg_net_interfacelist_new();
	removed = cg_net_interfacelist_new();

	if (current == NULL || added == NULL || removed == NULL)
	{
		if (current != NULL) cg_net_interfacelist_delete(current);
		if (added != NULL) cg_net_interfacelist_delete(added);
		if (removed != NULL) cg_net_interfacelist_delete(removed);
		return FALSE;
	}
	
	/* Get Interface changes */
	cg_net_gethostinterfaces(current);
	cg_net_interfacelist_getchanges(ctrlPoint->ifCache, current, 
					added, removed);
	
	/* Remove all devices registered through old interface */
	for (netIf = cg_net_interfacelist_gets(removed);
	     netIf != NULL; netIf = cg_net_interface_next(netIf))
	{
		cg_upnp_controlpoint_lock(ctrlPoint);
		tmp = cg_upnp_controlpoint_getdevices(ctrlPoint);
		while (tmp != NULL)
		{
			dev = tmp; tmp = cg_upnp_device_next(dev);
			ssdpPkt = cg_upnp_device_getssdppacket(dev);
			address = cg_upnp_ssdp_packet_getlocaladdress(ssdpPkt);
			
			if (address != NULL && 
			    cg_strcmp(address, cg_net_interface_getaddress(netIf)) == 0)
			{
				/* This device has been received from the 
				   removed interface, so it does not exist */
				cg_upnp_controlpoint_unlock(ctrlPoint);
				cg_upnp_controlpoint_removedevicebyssdppacket(ctrlPoint, 
									      ssdpPkt);
				cg_upnp_controlpoint_lock(ctrlPoint);
				address = NULL; dev = NULL; ssdpPkt = NULL;
			}
		}
		cg_upnp_controlpoint_unlock(ctrlPoint);
	}

	/* Launch new M-SEARCH */
	cg_upnp_controlpoint_search(ctrlPoint, CG_UPNP_ST_ROOT_DEVICE);
	
	/**** Cache current interfaces ****/
	cg_net_gethostinterfaces(ctrlPoint->ifCache);
	
	cg_net_interfacelist_delete(current);
	cg_net_interfacelist_delete(added);
	cg_net_interfacelist_delete(removed);

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

	return TRUE;
}
BOOL cg_http_persistentconnection_put(char *host, int port, void *data)
{
       CgHttpPersistentConnection *new_node = NULL, *node = NULL;

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

       /* If we dont have cache, then just exit */
       if (cache == NULL) {
	       cg_log_debug("(put) No cache! Persistent connections not initialized?\n");
	       return FALSE;
       }

       /* Check if we already have this one cached */
       for (node = (CgHttpPersistentConnection*)cg_list_gets((CgList*)cache);
            node != NULL;
            node = (CgHttpPersistentConnection*)cg_list_next((CgList*)node))
       {
               if (cg_strcmp(cg_string_getvalue(node->host), host) == 0 &&
                   node->port == port)
               {
                       /* If also data is the same, then update just
                          timestamp */
                       if (node->cacheData == data)
                       {
                               node->timestamp = cg_getcurrentsystemtime();
                               return TRUE;
                       }

		      cg_log_debug_s("Found cached persistent connection for %s:%d\n",
			      cg_string_getvalue(node->host), node->port);
                       new_node = node;
                       cg_list_remove((CgList*)new_node);
                       break;
               }
       }

       /* We didn't find it */
       if (new_node == NULL)
       {
               /* Check if we have already too many cached things */
               if (cg_list_size((CgList*)cache) >= CG_HTTP_PERSISTENT_CACHE_SIZE)
               {
                       /* Take last node (not refreshed for a long time) */
                       new_node = (CgHttpPersistentConnection *)cg_list_next((CgList *)cache);
                       cg_list_remove((CgList*)new_node);
                       cg_http_persistentconnection_delete(new_node);
                       new_node = NULL;

		      cg_log_debug_s("Max persistent HTTP connection cache reached.\n");
               }

               if (new_node == NULL)
               {
                       if (data == NULL) return TRUE;

                       new_node = cg_http_persistentconnection_new();
                       if (new_node == NULL) return FALSE;

		      cg_log_debug_s("Adding persistent HTTP Connection %s:%d to cache\n",
			       host, port);
		      cg_log_debug_s("Persistent connections: %d\n", cg_list_size((CgList*)cache));
               }
       }

       if (data != NULL)
       {
               /* Set appropriate values for the node */
               cg_string_setvalue(new_node->host, host);
               new_node->port = port;
               new_node->cacheData = data;
               new_node->timestamp = cg_getcurrentsystemtime();

               cg_list_add((CgList*)cache, (CgList*)new_node);
       } else {
               /* remove and delete node */
               cg_http_persistentconnection_delete(new_node);
       }

       return TRUE;

	cg_log_debug_l4("Leaving...\n");
}
void *cg_http_persistentconnection_get(char *host, int port)
{
       CgHttpPersistentConnection *node;
       CgSysTime sys_time = cg_getcurrentsystemtime();
       BOOL iterate;

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

       /* If we dont have cache, then just exit */
       if (cache == NULL) { 
	       cg_log_debug("(get) No cache! Persistent connections not initialized?\n");
	       return NULL;
	}

       /* Clear all expired nodes */
       do {
               iterate = FALSE;
               for (node = (CgHttpPersistentConnection*)cg_list_gets((CgList*)cache);
                    node != NULL;
                    node = (CgHttpPersistentConnection*)cg_list_next((CgList*)node))
               {
                       if (sys_time > node->timestamp + CG_HTTP_PERSISTENT_TIMEOUT_PERIOD)
                       {
			      cg_log_debug_s("Timeout for persistent HTTP Connection to %s:%d "
				       "(timestamp: %d)\n",
				      cg_string_getvalue(node->host), node->port,
				      node->timestamp);
                               cg_list_remove((CgList*)node);
                               cg_http_persistentconnection_delete(node);
                               iterate = TRUE;
                               break;
                       }
               }
       } while (iterate);

       /* Get persistent node */
       for (node = (CgHttpPersistentConnection*)cg_list_gets((CgList*)cache);
            node != NULL;
            node = (CgHttpPersistentConnection*)cg_list_next((CgList*)node))
       {
               if (cg_strcmp(cg_string_getvalue(node->host), host) == 0 &&
                   node->port == port)
               {
                       /* Node was required, remove and add again to refresh
                          cache */
                       cg_list_remove((CgList*)node);
                       cg_list_add((CgList*)cache, (CgList*)node);

                       node->timestamp = cg_getcurrentsystemtime();

		      cg_log_debug_s("Persistent HTTP Connection cache HIT for %s:%d\n",
			       host, port);

                       return node->cacheData;
               }
       }

      cg_log_debug_s("Persistent HTTP Connection cache MISS for %s:%d\n",
	      host, port);

       return NULL;

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