/** * This function schedules the expiration when this pinhole is created or updated * * @param pinhole The pinhole to expire * @return the event_id created */ int phv6_scheduleExpiration(struct pinholev6 *pinhole) { ThreadPoolJob job; struct phv6_expirationEvent *event; event = (struct phv6_expirationEvent *)malloc( sizeof(struct phv6_expirationEvent)); if(event == NULL) { return 0; } event->pinhole = pinhole; TPJobInit( &job, ( start_routine ) phv6_expiration, event ); TPJobSetFreeFunction( &job, ( free_routine ) phv6_freeEvent ); if( TimerThreadSchedule(&gExpirationTimerThread, pinhole->lease_time, REL_SEC, &job, SHORT_TERM, &(event->event_id)) != UPNP_E_SUCCESS ) { free( event ); return 0; } pinhole->event_id = event->event_id; return event->event_id; }
/************************************************************************ * Function : ScheduleGenaAutoRenew * * Parameters: * IN int client_handle: Handle that also contains the subscription list * IN int TimeOut: The time out value of the subscription * IN client_subscription * sub: Subscription being renewed * * Description: * This function schedules a job to renew the subscription just before * time out. * * Returns: int * return GENA_E_SUCCESS if successful else returns appropriate error ***************************************************************************/ static int ScheduleGenaAutoRenew( IN int client_handle, IN int TimeOut, IN client_subscription * sub ) { struct Upnp_Event_Subscribe *RenewEventStruct = NULL; upnp_timeout *RenewEvent = NULL; int return_code = GENA_SUCCESS; ThreadPoolJob job; if( TimeOut == UPNP_INFINITE ) { return GENA_SUCCESS; } RenewEventStruct = ( struct Upnp_Event_Subscribe * )malloc( sizeof ( struct Upnp_Event_Subscribe ) ); if( RenewEventStruct == NULL ) { return UPNP_E_OUTOF_MEMORY; } RenewEvent = ( upnp_timeout * ) malloc( sizeof( upnp_timeout ) ); if( RenewEvent == NULL ) { free( RenewEventStruct ); return UPNP_E_OUTOF_MEMORY; } //schedule expire event strcpy( RenewEventStruct->Sid, sub->sid ); RenewEventStruct->ErrCode = UPNP_E_SUCCESS; strncpy( RenewEventStruct->PublisherUrl, sub->EventURL, UPNP_NAME_SIZE - 1 ); RenewEventStruct->TimeOut = TimeOut; //RenewEvent->EventType=UPNP_EVENT_SUBSCRIPTION_EXPIRE; RenewEvent->handle = client_handle; RenewEvent->Event = RenewEventStruct; TPJobInit( &job, ( start_routine ) GenaAutoRenewSubscription, RenewEvent ); TPJobSetFreeFunction( &job, ( free_routine ) free_upnp_timeout ); TPJobSetPriority( &job, MED_PRIORITY ); //Schedule the job if( ( return_code = TimerThreadSchedule( &gTimerThread, TimeOut - AUTO_RENEW_TIME, REL_SEC, &job, SHORT_TERM, &( RenewEvent-> eventId ) ) ) != UPNP_E_SUCCESS ) { free( RenewEvent ); free( RenewEventStruct ); return return_code; } sub->RenewEventId = RenewEvent->eventId; return GENA_SUCCESS; }
int SearchByTarget(int Mx, char *St, void *Cookie) { char errorBuffer[ERROR_BUFFER_LEN]; int *id = NULL; int ret = 0; char ReqBufv4[BUFSIZE]; #ifdef UPNP_ENABLE_IPV6 char ReqBufv6[BUFSIZE]; char ReqBufv6UlaGua[BUFSIZE]; #endif struct sockaddr_storage __ss_v4; #ifdef UPNP_ENABLE_IPV6 struct sockaddr_storage __ss_v6; #endif struct sockaddr_in *destAddr4 = (struct sockaddr_in *)&__ss_v4; #ifdef UPNP_ENABLE_IPV6 struct sockaddr_in6 *destAddr6 = (struct sockaddr_in6 *)&__ss_v6; #endif fd_set wrSet; SsdpSearchArg *newArg = NULL; int timeTillRead = 0; int handle; struct Handle_Info *ctrlpt_info = NULL; enum SsdpSearchType requestType; unsigned long addrv4 = inet_addr(gIF_IPV4); SOCKET max_fd = 0; int retVal; /*ThreadData *ThData; */ ThreadPoolJob job; memset(&job, 0, sizeof(job)); requestType = ssdp_request_type1(St); if (requestType == SSDP_SERROR) return UPNP_E_INVALID_PARAM; UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__, "Inside SearchByTarget\n"); timeTillRead = Mx; if (timeTillRead < MIN_SEARCH_TIME) timeTillRead = MIN_SEARCH_TIME; else if (timeTillRead > MAX_SEARCH_TIME) timeTillRead = MAX_SEARCH_TIME; retVal = CreateClientRequestPacket(ReqBufv4, sizeof(ReqBufv4), timeTillRead, St, AF_INET); if (retVal != UPNP_E_SUCCESS) return retVal; #ifdef UPNP_ENABLE_IPV6 retVal = CreateClientRequestPacket(ReqBufv6, sizeof(ReqBufv6), timeTillRead, St, AF_INET6); if (retVal != UPNP_E_SUCCESS) return retVal; retVal = CreateClientRequestPacketUlaGua(ReqBufv6UlaGua, sizeof(ReqBufv6UlaGua), timeTillRead, St, AF_INET6); if (retVal != UPNP_E_SUCCESS) return retVal; #endif memset(&__ss_v4, 0, sizeof(__ss_v4)); destAddr4->sin_family = (sa_family_t)AF_INET; inet_pton(AF_INET, SSDP_IP, &destAddr4->sin_addr); destAddr4->sin_port = htons(SSDP_PORT); #ifdef UPNP_ENABLE_IPV6 memset(&__ss_v6, 0, sizeof(__ss_v6)); destAddr6->sin6_family = (sa_family_t)AF_INET6; inet_pton(AF_INET6, SSDP_IPV6_SITELOCAL, &destAddr6->sin6_addr); destAddr6->sin6_port = htons(SSDP_PORT); destAddr6->sin6_scope_id = gIF_INDEX; #endif /* add search criteria to list */ HandleLock(); if (GetClientHandleInfo(&handle, &ctrlpt_info) != HND_CLIENT) { HandleUnlock(); return UPNP_E_INTERNAL_ERROR; } newArg = (SsdpSearchArg *) malloc(sizeof(SsdpSearchArg)); newArg->searchTarget = strdup(St); newArg->cookie = Cookie; newArg->requestType = requestType; id = (int *)malloc(sizeof(int)); TPJobInit(&job, (start_routine) searchExpired, id); TPJobSetPriority(&job, MED_PRIORITY); TPJobSetFreeFunction(&job, (free_routine) free); /* Schedule a timeout event to remove search Arg */ TimerThreadSchedule(&gTimerThread, timeTillRead, REL_SEC, &job, SHORT_TERM, id); newArg->timeoutEventId = *id; ListAddTail(&ctrlpt_info->SsdpSearchList, newArg); HandleUnlock(); /* End of lock */ FD_ZERO(&wrSet); if (gSsdpReqSocket4 != INVALID_SOCKET) { setsockopt(gSsdpReqSocket4, IPPROTO_IP, IP_MULTICAST_IF, (char *)&addrv4, sizeof(addrv4)); FD_SET(gSsdpReqSocket4, &wrSet); max_fd = max(max_fd, gSsdpReqSocket4); } #ifdef UPNP_ENABLE_IPV6 if (gSsdpReqSocket6 != INVALID_SOCKET) { setsockopt(gSsdpReqSocket6, IPPROTO_IPV6, IPV6_MULTICAST_IF, (char *)&gIF_INDEX, sizeof(gIF_INDEX)); FD_SET(gSsdpReqSocket6, &wrSet); max_fd = max(max_fd, gSsdpReqSocket6); } #endif ret = select(max_fd + 1, NULL, &wrSet, NULL, NULL); if (ret == -1) { strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__, "SSDP_LIB: Error in select(): %s\n", errorBuffer); shutdown(gSsdpReqSocket4, SD_BOTH); UpnpCloseSocket(gSsdpReqSocket4); #ifdef UPNP_ENABLE_IPV6 shutdown(gSsdpReqSocket6, SD_BOTH); UpnpCloseSocket(gSsdpReqSocket6); #endif return UPNP_E_INTERNAL_ERROR; } #ifdef UPNP_ENABLE_IPV6 if (gSsdpReqSocket6 != INVALID_SOCKET && FD_ISSET(gSsdpReqSocket6, &wrSet)) { int NumCopy = 0; while (NumCopy < NUM_SSDP_COPY) { UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__, ">>> SSDP SEND M-SEARCH >>>\n%s\n", ReqBufv6UlaGua); sendto(gSsdpReqSocket6, ReqBufv6UlaGua, strlen(ReqBufv6UlaGua), 0, (struct sockaddr *)&__ss_v6, sizeof(struct sockaddr_in6)); NumCopy++; imillisleep(SSDP_PAUSE); } NumCopy = 0; inet_pton(AF_INET6, SSDP_IPV6_LINKLOCAL, &destAddr6->sin6_addr); while (NumCopy < NUM_SSDP_COPY) { UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__, ">>> SSDP SEND M-SEARCH >>>\n%s\n", ReqBufv6); sendto(gSsdpReqSocket6, ReqBufv6, strlen(ReqBufv6), 0, (struct sockaddr *)&__ss_v6, sizeof(struct sockaddr_in6)); NumCopy++; imillisleep(SSDP_PAUSE); } } #endif /* IPv6 */ if (gSsdpReqSocket4 != INVALID_SOCKET && FD_ISSET(gSsdpReqSocket4, &wrSet)) { int NumCopy = 0; while (NumCopy < NUM_SSDP_COPY) { UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__, ">>> SSDP SEND M-SEARCH >>>\n%s\n", ReqBufv4); sendto(gSsdpReqSocket4, ReqBufv4, strlen(ReqBufv4), 0, (struct sockaddr *)&__ss_v4, sizeof(struct sockaddr_in)); NumCopy++; imillisleep(SSDP_PAUSE); } } return 1; }
void ssdp_handle_device_request(http_message_t *hmsg, struct sockaddr_storage *dest_addr) { #define MX_FUDGE_FACTOR 10 int handle; struct Handle_Info *dev_info = NULL; memptr hdr_value; int mx; char save_char; SsdpEvent event; int ret_code; SsdpSearchReply *threadArg = NULL; ThreadPoolJob job; int replyTime; int maxAge; memset(&job, 0, sizeof(job)); /* check man hdr. */ if (httpmsg_find_hdr(hmsg, HDR_MAN, &hdr_value) == NULL || memptr_cmp(&hdr_value, "\"ssdp:discover\"") != 0) /* bad or missing hdr. */ return; /* MX header. */ if (httpmsg_find_hdr(hmsg, HDR_MX, &hdr_value) == NULL || (mx = raw_to_int(&hdr_value, 10)) < 0) return; /* ST header. */ if (httpmsg_find_hdr(hmsg, HDR_ST, &hdr_value) == NULL) return; save_char = hdr_value.buf[hdr_value.length]; hdr_value.buf[hdr_value.length] = '\0'; ret_code = ssdp_request_type(hdr_value.buf, &event); /* restore. */ hdr_value.buf[hdr_value.length] = save_char; if (ret_code == -1) /* bad ST header. */ return; HandleLock(); /* device info. */ switch (GetDeviceHandleInfo((int)dest_addr->ss_family, &handle, &dev_info)) { case HND_DEVICE: break; default: HandleUnlock(); /* no info found. */ return; } maxAge = dev_info->MaxAge; HandleUnlock(); UpnpPrintf(UPNP_PACKET, API, __FILE__, __LINE__, "MAX-AGE = %d\n", maxAge); UpnpPrintf(UPNP_PACKET, API, __FILE__, __LINE__, "MX = %d\n", event.Mx); UpnpPrintf(UPNP_PACKET, API, __FILE__, __LINE__, "DeviceType = %s\n", event.DeviceType); UpnpPrintf(UPNP_PACKET, API, __FILE__, __LINE__, "DeviceUuid = %s\n", event.UDN); UpnpPrintf(UPNP_PACKET, API, __FILE__, __LINE__, "ServiceType = %s\n", event.ServiceType); threadArg = (SsdpSearchReply *)malloc(sizeof(SsdpSearchReply)); if (threadArg == NULL) return; threadArg->handle = handle; memcpy(&threadArg->dest_addr, dest_addr, sizeof(threadArg->dest_addr)); threadArg->event = event; threadArg->MaxAge = maxAge; TPJobInit(&job, advertiseAndReplyThread, threadArg); TPJobSetFreeFunction(&job, (free_routine) free); /* Subtract a percentage from the mx to allow for network and processing * delays (i.e. if search is for 30 seconds, respond * within 0 - 27 seconds). */ if (mx >= 2) mx -= MAXVAL(1, mx / MX_FUDGE_FACTOR); if (mx < 1) mx = 1; replyTime = rand() % mx; TimerThreadSchedule(&gTimerThread, replyTime, REL_SEC, &job, SHORT_TERM, NULL); }
/*! * \brief Schedules a job to renew the subscription just before time out. * * \return GENA_E_SUCCESS if successful, otherwise returns the appropriate * error code. */ static int ScheduleGenaAutoRenew( /*! [in] Handle that also contains the subscription list. */ IN int client_handle, /*! [in] The time out value of the subscription. */ IN int TimeOut, /*! [in] Subscription being renewed. */ IN ClientSubscription *sub) { struct Upnp_Event_Subscribe *RenewEventStruct = NULL; upnp_timeout *RenewEvent = NULL; int return_code = GENA_SUCCESS; ThreadPoolJob job; const UpnpString *tmpSID = UpnpClientSubscription_get_SID(sub); const UpnpString *tmpEventURL = UpnpClientSubscription_get_EventURL(sub); memset(&job, 0, sizeof(job)); if (TimeOut == UPNP_INFINITE) { return_code = GENA_SUCCESS; goto end_function; } RenewEventStruct = (struct Upnp_Event_Subscribe *)malloc(sizeof (struct Upnp_Event_Subscribe)); if (RenewEventStruct == NULL) { return_code = UPNP_E_OUTOF_MEMORY; goto end_function; } memset(RenewEventStruct, 0, sizeof(struct Upnp_Event_Subscribe)); RenewEvent = (upnp_timeout *) malloc(sizeof(upnp_timeout)); if (RenewEvent == NULL) { free(RenewEventStruct); return_code = UPNP_E_OUTOF_MEMORY; goto end_function; } memset(RenewEvent, 0, sizeof(upnp_timeout)); /* schedule expire event */ RenewEventStruct->ErrCode = UPNP_E_SUCCESS; RenewEventStruct->TimeOut = TimeOut; strncpy(RenewEventStruct->Sid, UpnpString_get_String(tmpSID), sizeof(RenewEventStruct->Sid) - 1); strncpy(RenewEventStruct->PublisherUrl, UpnpString_get_String(tmpEventURL), NAME_SIZE - 1); /* RenewEvent->EventType=UPNP_EVENT_SUBSCRIPTION_EXPIRE; */ RenewEvent->handle = client_handle; RenewEvent->Event = RenewEventStruct; TPJobInit(&job, (start_routine) GenaAutoRenewSubscription, RenewEvent); TPJobSetFreeFunction(&job, (free_routine)free_upnp_timeout); TPJobSetPriority(&job, MED_PRIORITY); /* Schedule the job */ return_code = TimerThreadSchedule( &gTimerThread, TimeOut - AUTO_RENEW_TIME, REL_SEC, &job, SHORT_TERM, &(RenewEvent->eventId)); if (return_code != UPNP_E_SUCCESS) { free(RenewEvent); free(RenewEventStruct); goto end_function; } UpnpClientSubscription_set_RenewEventId(sub, RenewEvent->eventId); return_code = GENA_SUCCESS; end_function: return return_code; }