BOOL cg_socket_setmulticastttl(CgSocket *sock, int ttl) { int sockOptRet; int ttl_; unsigned int len=0; cg_log_debug_l4("Entering...\n"); #if defined(BTRON) || (defined(TENGINE) && !defined(CG_TENGINE_NET_KASAGO)) sockOptRet = so_setsockopt(sock->id, IPPROTO_IP, IP_MULTICAST_TTL, (B *)&ttl, sizeof(ttl)); #elif defined(TENGINE) && defined(CG_TENGINE_NET_KASAGO) sockOptRet = ka_setsockopt(sock->id, IPPROTO_IP, IP_MULTICAST_TTL, (const char *)&ttl, sizeof(ttl)); #elif defined (ITRON) /**** Not Implemented for NORTi ***/ sockOptRet = -1; #elif defined (WIN32) sockOptRet = setsockopt(sock->id, IPPROTO_IP, IP_MULTICAST_TTL, (const char *)&ttl, sizeof(ttl)); #else cg_log_debug("Setting multicast time to live to %d\n", ttl); sockOptRet = setsockopt(sock->id, IPPROTO_IP, IP_MULTICAST_TTL, (const unsigned char *)&ttl, sizeof(ttl)); if (sockOptRet != 0) { cg_log_debug("setsockopt() failed with errno %d: %s, fd:%d\n", errno, strerror(errno),sock->id); } else { len = sizeof(ttl_); getsockopt(sock->id, IPPROTO_IP, IP_MULTICAST_TTL, &ttl_, (socklen_t*)&len); cg_log_debug("Multicast time to live is %i\n", ttl_); } #endif cg_log_debug_l4("Leaving...\n"); return (sockOptRet == 0) ? TRUE : FALSE; }
char *cg_net_uri_getupnpbasepath(CgNetURI *locationURL) { char *path, *c; int i; path = cg_strdup(cg_net_uri_getpath(locationURL)); cg_log_debug_s("Mangling url string: %s\n", path); i = cg_strlen(path); if ( 0 >= i ) { cg_log_debug("No base path, doing nothing.\n"); return NULL; } /* Truncating out the "file name" from path */ for ( c=( path + --i); 0<=i; c=( path + --i )) if ( '/' == *c ) { *( path + i + 1 ) = '\0'; cg_log_debug_s("Truncating string from place %d\n", i); break; } cg_log_debug_s("url string after mangling: %s\n", path); return path; }
/** * Do an M-SEARCH to look for devices in the network. * * @param ctrlPoint The control point in question * @param target The Search Target parameter (ex. "ssdp:all") */ BOOL cg_upnp_controlpoint_search(CgUpnpControlPoint *ctrlPoint, const char *target) { CgUpnpSSDPRequest *ssdpReq; CgUpnpSSDPResponseServerList *ssdpResServerList; int i = 0; BOOL retval = FALSE; cg_log_debug_l4("Entering...\n"); ssdpReq = cg_upnp_ssdprequest_new(); cg_upnp_ssdprequest_setmethod(ssdpReq, CG_HTTP_MSEARCH); cg_upnp_ssdprequest_setst(ssdpReq, target); cg_upnp_ssdprequest_setmx(ssdpReq, cg_upnp_controlpoint_getssdpsearchmx(ctrlPoint)); cg_upnp_ssdprequest_setman(ssdpReq, CG_UPNP_MAN_DISCOVER); cg_log_debug("Announcing %d times.\n", cg_upnp_ssdp_getannouncecount()); cg_upnp_ssdprequest_print(ssdpReq); for (i = 0; i < cg_upnp_ssdp_getannouncecount(); i++) { ssdpResServerList = cg_upnp_controlpoint_getssdpresponseserverlist(ctrlPoint); retval = ( cg_upnp_ssdpresponse_serverlist_post(ssdpResServerList, ssdpReq ) || retval ); cg_wait(CG_UPNP_CONTROLPOINT_SSDP_MIN_DELAY); } cg_upnp_ssdprequest_delete(ssdpReq); cg_log_debug_l4("Leaving...\n"); return retval; }
BOOL cg_socket_tosockaddrinfo(int sockType, char *addr, int port, struct addrinfo **addrInfo, BOOL isBindAddr) { #if defined(TENGINE) && defined(CG_TENGINE_NET_KASAGO) struct addrinfo hints; char portStr[32]; #else struct addrinfo hints; char portStr[32]; int errorn; #endif cg_log_debug_l4("Entering...\n"); cg_socket_startup(); #if defined(TENGINE) && defined(CG_TENGINE_NET_KASAGO) memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_socktype = sockType; hints.ai_flags= 0; /*AI_NUMERICHOST | AI_PASSIVE*/; sprintf(portStr, "%d", port); if (ka_getaddrinfo(addr, portStr, &hints, addrInfo) != 0) return FALSE; if (isBindAddr == TRUE) return TRUE; hints.ai_family = (*addrInfo)->ai_family; ka_freeaddrinfo(*addrInfo); if (ka_getaddrinfo(NULL, portStr, &hints, addrInfo) != 0) return FALSE; return TRUE; #else memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_socktype = sockType; hints.ai_flags= /*AI_NUMERICHOST | */AI_PASSIVE; sprintf(portStr, "%d", port); cg_log_debug("Address: %s, port: %s\n", addr, portStr); if ( (errorn = getaddrinfo(addr, portStr, &hints, addrInfo)) != 0) { #if !defined(WINCE) cg_log_debug_s("ERROR: %s\n", gai_strerror(errorn)); cg_log_debug_s("SERROR: %s\n", strerror(errno)); #endif return FALSE; } if (isBindAddr == TRUE) return TRUE; hints.ai_family = (*addrInfo)->ai_family; freeaddrinfo(*addrInfo); if ((errorn = getaddrinfo(NULL, portStr, &hints, addrInfo)) != 0) { #if !defined(WINCE) cg_log_debug_s("ERROR: %s\n", gai_strerror(errorn)); cg_log_debug_s("SERROR: %s\n", strerror(errno)); #endif return FALSE; } return TRUE; #endif }
static int simple_string_hash(char *str, int table_size) { int sum=0; cg_log_debug_l4("Entering...\n"); if (str==NULL) return -1; cg_log_debug("Calculating hash from string |%s|, table size: %d\n", str, table_size); /* Sum up all the characters in the string */ for( ; *str; str++) sum += *str; cg_log_debug_l4("Leaving...\n"); return sum % table_size; }
char *cg_upnp_usn_getudn(char *usn, char *udnBuf, int udnBufLen) { int idx; cg_log_debug_l4("Entering...\n"); if (usn == NULL) { udnBuf[0] = '\0'; return udnBuf; } idx = cg_strstr(usn, "::"); if (idx < 0) { cg_strncpy(udnBuf, usn, udnBufLen); udnBuf[udnBufLen-1] = '\0'; cg_strtrim(udnBuf, " ", 1); return udnBuf; } if ( idx < udnBufLen ) { cg_strncpy(udnBuf, usn, (idx)); udnBuf[idx] = '\0'; } else { cg_strncpy(udnBuf, usn, udnBufLen); udnBuf[udnBufLen-1] = '\0'; } cg_strtrim(udnBuf, " ", 1); cg_log_debug("UDN: %s\n", udnBuf); return udnBuf; cg_log_debug_l4("Leaving...\n"); }
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"); }
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"); }
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"); }