/** * 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; }
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"); }
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; }
/** * 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; }
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"); }
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"); }
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); }
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"); }