void gena_process_subscription_renewal_request( SOCKINFO *info, http_message_t *request) { Upnp_SID sid; subscription *sub; int time_out = 1801; service_info *service; struct Handle_Info *handle_info; UpnpDevice_Handle device_handle; memptr temp_hdr; membuffer event_url_path; memptr timeout_hdr; /* if a CALLBACK or NT header is present, then it is an error */ if( httpmsg_find_hdr( request, HDR_CALLBACK, NULL ) != NULL || httpmsg_find_hdr( request, HDR_NT, NULL ) != NULL ) { error_respond( info, HTTP_BAD_REQUEST, request ); return; } /* get SID */ if( httpmsg_find_hdr( request, HDR_SID, &temp_hdr ) == NULL || temp_hdr.length > SID_SIZE ) { error_respond( info, HTTP_PRECONDITION_FAILED, request ); return; } memcpy( sid, temp_hdr.buf, temp_hdr.length ); sid[temp_hdr.length] = '\0'; /* lookup service by eventURL */ membuffer_init( &event_url_path ); if( membuffer_append( &event_url_path, request->uri.pathquery.buff, request->uri.pathquery.size ) != 0 ) { error_respond( info, HTTP_INTERNAL_SERVER_ERROR, request ); return; } HandleLock(); /* CURRENTLY, ONLY SUPPORT ONE DEVICE */ if( GetDeviceHandleInfo( info->foreign_sockaddr.ss_family, &device_handle, &handle_info ) != HND_DEVICE ) { error_respond( info, HTTP_PRECONDITION_FAILED, request ); membuffer_destroy( &event_url_path ); HandleUnlock(); return; } service = FindServiceEventURLPath( &handle_info->ServiceTable, event_url_path.buf ); membuffer_destroy( &event_url_path ); /* get subscription */ if( service == NULL || !service->active || ( ( sub = GetSubscriptionSID( sid, service ) ) == NULL ) ) { error_respond( info, HTTP_PRECONDITION_FAILED, request ); HandleUnlock(); return; } UpnpPrintf( UPNP_INFO, GENA, __FILE__, __LINE__, "Renew request: Number of subscriptions already: %d\n " "Max Subscriptions allowed:%d\n", service->TotalSubscriptions, handle_info->MaxSubscriptions ); /* too many subscriptions */ if( handle_info->MaxSubscriptions != -1 && service->TotalSubscriptions > handle_info->MaxSubscriptions ) { error_respond( info, HTTP_INTERNAL_SERVER_ERROR, request ); RemoveSubscriptionSID( sub->sid, service ); HandleUnlock(); return; } /* set the timeout */ if( httpmsg_find_hdr( request, HDR_TIMEOUT, &timeout_hdr ) != NULL ) { if( matchstr( timeout_hdr.buf, timeout_hdr.length, "%iSecond-%d%0", &time_out ) == PARSE_OK ) { /*nothing */ } else if( memptr_cmp_nocase( &timeout_hdr, "Second-infinite" ) == 0 ) { time_out = -1; /* inifinite timeout */ } else { time_out = DEFAULT_TIMEOUT; /* default is > 1800 seconds */ } } /* replace infinite timeout with max timeout, if possible */ if( handle_info->MaxSubscriptionTimeOut != -1 ) { if( time_out == -1 || time_out > handle_info->MaxSubscriptionTimeOut ) { time_out = handle_info->MaxSubscriptionTimeOut; } } if( time_out == -1 ) { sub->expireTime = 0; } else { sub->expireTime = time( NULL ) + time_out; } if( respond_ok( info, time_out, sub, request ) != UPNP_E_SUCCESS ) { RemoveSubscriptionSID( sub->sid, service ); } HandleUnlock(); }
/************************************************************************ * Function : ssdp_handle_device_request * * Parameters: * IN http_message_t* hmsg: SSDP search request from the control point * IN struct sockaddr_in* dest_addr: The address info of control point * * Description: * This function handles the search request. It do the sanity checks of * the request and then schedules a thread to send a random time reply ( * random within maximum time given by the control point to reply). * * Returns: void * * 1 if successful else appropriate error ***************************************************************************/ void ssdp_handle_device_request( IN http_message_t * hmsg, IN struct sockaddr_in *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; // check man hdr if( httpmsg_find_hdr( hmsg, HDR_MAN, &hdr_value ) == NULL || memptr_cmp( &hdr_value, "\"ssdp:discover\"" ) != 0 ) { return; // bad or missing hdr } // 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 ); hdr_value.buf[hdr_value.length] = save_char; // restore if( ret_code == -1 ) { return; // bad ST header } HandleLock( ); // device info if( GetDeviceHandleInfo( &handle, &dev_info ) != HND_DEVICE ) { HandleUnlock( ); return; // no info found } maxAge = dev_info->MaxAge; HandleUnlock( ); DBGONLY( UpnpPrintf( UPNP_PACKET, API, __FILE__, __LINE__, "ssdp_handle_device_request with Cmd %d SEARCH\n", event.Cmd ); 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 ); )
void gena_process_subscription_request( SOCKINFO *info, http_message_t *request) { UpnpSubscriptionRequest *request_struct = UpnpSubscriptionRequest_new(); Upnp_SID temp_sid; int return_code = 1; int time_out = 1801; service_info *service; subscription *sub; uuid_upnp uid; struct Handle_Info *handle_info; void *cookie; Upnp_FunPtr callback_fun; UpnpDevice_Handle device_handle; memptr nt_hdr; char *event_url_path = NULL; memptr callback_hdr; memptr timeout_hdr; int rc = 0; UpnpPrintf(UPNP_INFO, GENA, __FILE__, __LINE__, "Subscription Request Received:\n"); if (httpmsg_find_hdr(request, HDR_NT, &nt_hdr) == NULL) { error_respond(info, HTTP_BAD_REQUEST, request); goto exit_function; } /* check NT header */ /* Windows Millenium Interoperability: */ /* we accept either upnp:event, or upnp:propchange for the NT header */ if (memptr_cmp_nocase(&nt_hdr, "upnp:event") != 0) { error_respond(info, HTTP_PRECONDITION_FAILED, request); goto exit_function; } /* if a SID is present then the we have a bad request "incompatible headers" */ if (httpmsg_find_hdr(request, HDR_SID, NULL) != NULL) { error_respond(info, HTTP_BAD_REQUEST, request); goto exit_function; } /* look up service by eventURL */ event_url_path = str_alloc(request->uri.pathquery.buff, request->uri.pathquery.size); if (event_url_path == NULL) { error_respond(info, HTTP_INTERNAL_SERVER_ERROR, request); goto exit_function; } UpnpPrintf(UPNP_INFO, GENA, __FILE__, __LINE__, "SubscriptionRequest for event URL path: %s\n", event_url_path); HandleLock(); /* CURRENTLY, ONLY ONE DEVICE */ if (GetDeviceHandleInfo(info->foreign_sockaddr.ss_family , &device_handle, &handle_info) != HND_DEVICE) { free(event_url_path); error_respond(info, HTTP_INTERNAL_SERVER_ERROR, request); HandleUnlock(); goto exit_function; } service = FindServiceEventURLPath(&handle_info->ServiceTable, event_url_path); free(event_url_path); if (service == NULL || !service->active) { error_respond(info, HTTP_NOT_FOUND, request); HandleUnlock(); goto exit_function; } UpnpPrintf(UPNP_INFO, GENA, __FILE__, __LINE__, "Subscription Request: Number of Subscriptions already %d\n " "Max Subscriptions allowed: %d\n", service->TotalSubscriptions, handle_info->MaxSubscriptions); /* too many subscriptions */ if (handle_info->MaxSubscriptions != -1 && service->TotalSubscriptions >= handle_info->MaxSubscriptions) { error_respond(info, HTTP_INTERNAL_SERVER_ERROR, request); HandleUnlock(); goto exit_function; } /* generate new subscription */ sub = (subscription *)malloc(sizeof (subscription)); if (sub == NULL) { error_respond(info, HTTP_INTERNAL_SERVER_ERROR, request); HandleUnlock(); goto exit_function; } sub->eventKey = 0; sub->ToSendEventKey = 0; sub->active = 0; sub->next = NULL; sub->DeliveryURLs.size = 0; sub->DeliveryURLs.URLs = NULL; sub->DeliveryURLs.parsedURLs = NULL; /* check for valid callbacks */ if (httpmsg_find_hdr( request, HDR_CALLBACK, &callback_hdr) == NULL) { error_respond(info, HTTP_PRECONDITION_FAILED, request); freeSubscriptionList(sub); HandleUnlock(); goto exit_function; } return_code = create_url_list(&callback_hdr, &sub->DeliveryURLs); if (return_code == 0) { error_respond(info, HTTP_PRECONDITION_FAILED, request); freeSubscriptionList(sub); HandleUnlock(); goto exit_function; } if (return_code == UPNP_E_OUTOF_MEMORY) { error_respond(info, HTTP_INTERNAL_SERVER_ERROR, request); freeSubscriptionList(sub); HandleUnlock(); goto exit_function; } /* set the timeout */ if (httpmsg_find_hdr(request, HDR_TIMEOUT, &timeout_hdr) != NULL) { if (matchstr(timeout_hdr.buf, timeout_hdr.length, "%iSecond-%d%0", &time_out) == PARSE_OK) { /* nothing */ } else if(memptr_cmp_nocase(&timeout_hdr, "Second-infinite") == 0) { /* infinite timeout */ time_out = -1; } else { /* default is > 1800 seconds */ time_out = DEFAULT_TIMEOUT; } } /* replace infinite timeout with max timeout, if possible */ if (handle_info->MaxSubscriptionTimeOut != -1) { if (time_out == -1 || time_out > handle_info->MaxSubscriptionTimeOut) { time_out = handle_info->MaxSubscriptionTimeOut; } } if (time_out >= 0) { sub->expireTime = time(NULL) + time_out; } else { /* infinite time */ sub->expireTime = 0; } /* generate SID */ uuid_create(&uid); uuid_unpack(&uid, temp_sid); rc = snprintf(sub->sid, sizeof(sub->sid), "uuid:%s", temp_sid); /* respond OK */ if (rc < 0 || (unsigned int) rc >= sizeof(sub->sid) || (respond_ok(info, time_out, sub, request) != UPNP_E_SUCCESS)) { freeSubscriptionList(sub); HandleUnlock(); goto exit_function; } /* add to subscription list */ sub->next = service->subscriptionList; service->subscriptionList = sub; service->TotalSubscriptions++; /* finally generate callback for init table dump */ UpnpSubscriptionRequest_strcpy_ServiceId(request_struct, service->serviceId); UpnpSubscriptionRequest_strcpy_UDN(request_struct, service->UDN); UpnpSubscriptionRequest_strcpy_SID(request_struct, sub->sid); /* copy callback */ callback_fun = handle_info->Callback; cookie = handle_info->Cookie; HandleUnlock(); /* make call back with request struct */ /* in the future should find a way of mainting that the handle */ /* is not unregistered in the middle of a callback */ callback_fun(UPNP_EVENT_SUBSCRIPTION_REQUEST, request_struct, cookie); exit_function: UpnpSubscriptionRequest_delete(request_struct); }
/************************************************************************ * Function : genaSubscribe * * Parameters: * IN UpnpClient_Handle client_handle: * IN char * PublisherURL: NULL Terminated, of the form : * "http://134.134.156.80:4000/RedBulb/Event" * INOUT int * TimeOut: requested Duration, if -1, then "infinite". * in the OUT case: actual Duration granted * by Service, -1 for infinite * OUT Upnp_SID out_sid:sid of subscription, memory passed in by caller * * Description: * This function subscribes to a PublisherURL ( also mentioned as EventURL * some places). It sends SUBSCRIBE http request to service processes * request. Finally adds a Subscription to * the clients subscription list, if service responds with OK * * Returns: int * return UPNP_E_SUCCESS if service response is OK else * returns appropriate error ***************************************************************************/ int genaSubscribe( IN UpnpClient_Handle client_handle, IN char *PublisherURL, INOUT int *TimeOut, OUT Upnp_SID out_sid ) { int return_code = GENA_SUCCESS; client_subscription *newSubscription = NULL; uuid_upnp uid; Upnp_SID temp_sid; char *ActualSID = NULL; struct Handle_Info *handle_info; char *EventURL = NULL; DBGONLY( UpnpPrintf( UPNP_INFO, GENA, __FILE__, __LINE__, "GENA SUBSCRIBE BEGIN" ) ); HandleLock( ); memset( out_sid, 0, sizeof( Upnp_SID ) ); // validate handle if( GetHandleInfo( client_handle, &handle_info ) != HND_CLIENT ) { HandleUnlock( ); return GENA_E_BAD_HANDLE; } HandleUnlock( ); // subscribe SubscribeLock( ); return_code = gena_subscribe( PublisherURL, TimeOut, NULL, &ActualSID ); HandleLock( ); if( return_code != UPNP_E_SUCCESS ) { DBGONLY( UpnpPrintf( UPNP_CRITICAL, GENA, __FILE__, __LINE__, "SUBSCRIBE FAILED in transfer error code: %d returned\n", return_code ) ); goto error_handler; } if( GetHandleInfo( client_handle, &handle_info ) != HND_CLIENT ) { return_code = GENA_E_BAD_HANDLE; goto error_handler; } // generate client SID uuid_create( &uid ); uuid_unpack( &uid, temp_sid ); sprintf( out_sid, "uuid:%s", temp_sid ); // create event url EventURL = ( char * )malloc( strlen( PublisherURL ) + 1 ); if( EventURL == NULL ) { return_code = UPNP_E_OUTOF_MEMORY; goto error_handler; } strcpy( EventURL, PublisherURL ); // fill subscription newSubscription = ( client_subscription * ) malloc( sizeof( client_subscription ) ); if( newSubscription == NULL ) { return_code = UPNP_E_OUTOF_MEMORY; goto error_handler; } newSubscription->EventURL = EventURL; newSubscription->ActualSID = ActualSID; strcpy( newSubscription->sid, out_sid ); newSubscription->RenewEventId = -1; newSubscription->next = handle_info->ClientSubList; handle_info->ClientSubList = newSubscription; // schedule expiration event return_code = ScheduleGenaAutoRenew( client_handle, *TimeOut, newSubscription ); error_handler: if( return_code != UPNP_E_SUCCESS ) { free( ActualSID ); free( EventURL ); free( newSubscription ); } HandleUnlock( ); SubscribeUnlock( ); return return_code; }
/************************************************************************ * Function : searchExpired * * Parameters: * IN void * arg: * * Description: * This function * * Returns: void * ***************************************************************************/ void searchExpired( void *arg ) { int *id = ( int * )arg; int handle = -1; struct Handle_Info *ctrlpt_info = NULL; //remove search Target from list and call client back ListNode *node = NULL; SsdpSearchArg *item; Upnp_FunPtr ctrlpt_callback; void *cookie = NULL; int found = 0; HandleLock( ); //remove search target from search list if( GetClientHandleInfo( &handle, &ctrlpt_info ) != HND_CLIENT ) { #ifdef _UPNP_MM_ upnp_free( id ); #else free( id ); #endif HandleUnlock( ); return; } ctrlpt_callback = ctrlpt_info->Callback; node = ListHead( &ctrlpt_info->SsdpSearchList ); while( node != NULL ) { item = ( SsdpSearchArg * ) node->item; if( item->timeoutEventId == ( *id ) ) { #ifdef _UPNP_MM_ upnp_free( item->searchTarget ); #else free( item->searchTarget ); #endif cookie = item->cookie; found = 1; item->searchTarget = NULL; #ifdef _UPNP_MM_ upnp_free( item ); #else free( item ); #endif ListDelNode( &ctrlpt_info->SsdpSearchList, node, 0 ); break; } node = ListNext( &ctrlpt_info->SsdpSearchList, node ); } HandleUnlock( ); if( found ) { ctrlpt_callback( UPNP_DISCOVERY_SEARCH_TIMEOUT, NULL, cookie ); } #ifdef _UPNP_MM_ upnp_free( id ); #else free( id ); #endif }
int genaInitNotifyExt( UpnpDevice_Handle device_handle, char *UDN, char *servId, IXML_Document *PropSet, const Upnp_SID sid) { int ret = GENA_SUCCESS; int line = 0; int *reference_count = NULL; char *UDN_copy = NULL; char *servId_copy = NULL; DOMString propertySet = NULL; char *headers = NULL; notify_thread_struct *thread_struct = NULL; subscription *sub = NULL; service_info *service = NULL; struct Handle_Info *handle_info; ThreadPoolJob job; memset(&job, 0, sizeof(job)); UpnpPrintf(UPNP_INFO, GENA, __FILE__, __LINE__, "GENA BEGIN INITIAL NOTIFY EXT"); reference_count = (int *)malloc(sizeof (int)); if (reference_count == NULL) { line = __LINE__; ret = UPNP_E_OUTOF_MEMORY; goto ExitFunction; } *reference_count = 0; UDN_copy = (char *)malloc(strlen(UDN) + 1); if (UDN_copy == NULL) { line = __LINE__; ret = UPNP_E_OUTOF_MEMORY; goto ExitFunction; } servId_copy = (char *)malloc(strlen(servId) + 1); if( servId_copy == NULL ) { line = __LINE__; ret = UPNP_E_OUTOF_MEMORY; goto ExitFunction; } memset(UDN_copy, 0, strlen(UDN) + 1); strncpy(UDN_copy, UDN, strlen(UDN)); memset(servId_copy, 0, strlen(servId) + 1); strncpy(servId_copy, servId, strlen(servId)); HandleLock(); if (GetHandleInfo(device_handle, &handle_info) != HND_DEVICE) { line = __LINE__; ret = GENA_E_BAD_HANDLE; goto ExitFunction; } service = FindServiceId(&handle_info->ServiceTable, servId, UDN); if (service == NULL) { line = __LINE__; ret = GENA_E_BAD_SERVICE; goto ExitFunction; } UpnpPrintf(UPNP_INFO, GENA, __FILE__, __LINE__, "FOUND SERVICE IN INIT NOTFY EXT: UDN %s, ServID: %s", UDN, servId); sub = GetSubscriptionSID(sid, service); if (sub == NULL || sub->active) { line = __LINE__; ret = GENA_E_BAD_SID; goto ExitFunction; } UpnpPrintf( UPNP_INFO, GENA, __FILE__, __LINE__, "FOUND SUBSCRIPTION IN INIT NOTIFY EXT: SID %s", sid); sub->active = 1; if (PropSet == 0) { line = __LINE__; ret = GENA_SUCCESS; goto ExitFunction; } propertySet = ixmlPrintNode((IXML_Node *)PropSet); if (propertySet == NULL) { line = __LINE__; ret = UPNP_E_INVALID_PARAM; goto ExitFunction; } UpnpPrintf(UPNP_INFO, GENA, __FILE__, __LINE__, "GENERATED PROPERTY SET IN INIT EXT NOTIFY: %s", propertySet); headers = AllocGenaHeaders(propertySet); if (headers == NULL) { line = __LINE__; ret = UPNP_E_OUTOF_MEMORY; goto ExitFunction; } /* schedule thread for initial notification */ thread_struct = (notify_thread_struct *)malloc(sizeof (notify_thread_struct)); if (thread_struct == NULL) { line = __LINE__; ret = UPNP_E_OUTOF_MEMORY; } else { *reference_count = 1; thread_struct->servId = servId_copy; thread_struct->UDN = UDN_copy; thread_struct->headers = headers; thread_struct->propertySet = propertySet; memset(thread_struct->sid, 0, sizeof(thread_struct->sid)); strncpy(thread_struct->sid, sid, sizeof(thread_struct->sid) - 1); thread_struct->eventKey = sub->eventKey++; thread_struct->reference_count = reference_count; thread_struct->device_handle = device_handle; TPJobInit(&job, (start_routine)genaNotifyThread, thread_struct); TPJobSetFreeFunction(&job, (free_routine)free_notify_struct); TPJobSetPriority(&job, MED_PRIORITY); ret = ThreadPoolAdd(&gSendThreadPool, &job, NULL); if (ret != 0) { if (ret == EOUTOFMEM) { line = __LINE__; ret = UPNP_E_OUTOF_MEMORY; } } else { line = __LINE__; ret = GENA_SUCCESS; } } ExitFunction: if (ret != GENA_SUCCESS || PropSet == 0) { free(thread_struct); free(headers); ixmlFreeDOMString(propertySet); free(servId_copy); free(UDN_copy); free(reference_count); } HandleUnlock(); UpnpPrintf(UPNP_INFO, GENA, __FILE__, line, "GENA END INITIAL NOTIFY EXT, ret = %d", ret); return ret; }
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 PageDraw(HPAGE PageHandle,HWND Window,int DrawLeft, int DrawTop,int DrawRight,int DrawBottom) { int SaveColor; struct viewporttype TmpViewPort; #ifdef __TURBOC__ struct linesettingstype SaveLineStyle; #else unsigned short old_style; #endif ORDINATETYPE BoxDrawLeft,BoxDrawTop,BoxDrawRight,BoxDrawBottom; ORDINATETYPE BoxXY[2*MAXPOLYGONNUMBER]; HBOX HBox; Pages *MidPage; int Left,Top,Right,Bottom; int PageLeft,PageTop,PageRight,PageBottom; WindowGetRect(Window,&Left,&Top,&Right,&Bottom); if (!RectangleIsInRectangle(DrawLeft,DrawTop,DrawRight,DrawBottom, Left,Top,Right,Bottom)) return; if (DrawRight>=Right-Left) DrawRight=Right-Left-1; if (DrawBottom>=Bottom-Top) DrawBottom=Bottom-Top-1; if (DrawLeft<0) DrawLeft=0; if (DrawTop<0) DrawTop=0; BoxDrawLeft=WindowXToUserX(DrawLeft); BoxDrawTop=WindowYToUserY(DrawTop); BoxDrawRight=WindowXToUserX(DrawRight); BoxDrawBottom=WindowYToUserY(DrawBottom); MidPage=HandleLock(ItemGetHandle(PageHandle)); if (MidPage==NULL) return; PageLeft=UserXToWindowX(0); PageTop=UserYToWindowY(0); PageRight=UserXToWindowX(PageGetPageWidth(MidPage)); PageBottom=UserYToWindowY(PageGetPageHeight(MidPage)); if(GlobalTextBlockStart<GlobalTextBlockEnd) // must clear now block DisplayBlock(GlobalBoxHeadHandle,GlobalTextBlockStart,GlobalTextBlockEnd); SaveColor=getcolor(); MouseHidden(); TextCursorOff(); getviewsettings(&TmpViewPort); setviewport(Left,Top,Right,Bottom,1); /*---- clear page -----*/ setfillstyle(1,EGA_WHITE); bar(DrawLeft,DrawTop,DrawRight,DrawBottom); /*--- draw page border ---*/ setcolor(PAGEBORDERCOLOR); rectangle(PageLeft,PageTop,PageRight,PageBottom); if(!IsInGlobalBrowser()) DrawPageFootHead(PageHandle,TRUE,TRUE); if(!fEditor) { #ifdef __TURBOC__ getlinesettings(&SaveLineStyle); setlinestyle(4,0x5555,1); #else old_style=getlinestyle(); setlinestyle(0xffff); #endif /*--- draw page shadow ---*/ setcolor(EGA_DARKGRAY); line(((PageLeft>0)?PageLeft:0)+3,PageBottom+1,PageRight+3,PageBottom+1); line(((PageLeft>0)?PageLeft:0)+3,PageBottom+2,PageRight+3,PageBottom+2); line(((PageLeft>0)?PageLeft:0)+3,PageBottom+3,PageRight+3,PageBottom+3); line(PageRight+1,((PageTop>0)?PageTop:0)+3,PageRight+1,PageBottom+3); line(PageRight+2,((PageTop>0)?PageTop:0)+3,PageRight+2,PageBottom+3); line(PageRight+3,((PageTop>0)?PageTop:0)+3,PageRight+3,PageBottom+3); /*--- draw box align line ---*/ setcolor(EGA_LIGHTBLUE); /*------------ use 0x5555 -- #ifdef __TURBOC__ setlinestyle(4,0x5f5f,1); #else setlinestyle(0x5f5f); #endif ----------------*/ setlinestyle(0x8888); PageLeft=UserXToWindowX(PageGetMarginLeft(MidPage))-1; PageTop=UserYToWindowY(PageGetMarginTop(MidPage))-1; PageRight=UserXToWindowX(PageGetPageWidth(MidPage)- PageGetMarginRight(MidPage))+1; PageBottom=UserYToWindowY(PageGetPageHeight(MidPage)- PageGetMarginBottom(MidPage))+1; line(UserXToWindowX(0),PageTop, UserXToWindowX(PageGetPageWidth(MidPage)),PageTop); line(UserXToWindowX(0),PageBottom, UserXToWindowX(PageGetPageWidth(MidPage)),PageBottom); line(PageLeft,UserYToWindowY(0),PageLeft, UserYToWindowY(PageGetPageHeight(MidPage))); line(PageRight,UserYToWindowY(0),PageRight, UserYToWindowY(PageGetPageHeight(MidPage))); #ifdef __TURBOC__ setlinestyle(SaveLineStyle.linestyle,SaveLineStyle.upattern, SaveLineStyle.thickness); #else setlinestyle(old_style); #endif } HandleUnlock(ItemGetHandle(PageHandle)); setcolor(EGA_BLACK); HBox=PageGetBoxHead(PageHandle); while (HBox) { ORDINATETYPE BoxLeft,BoxTop,BoxRight,BoxBottom; TextBoxs *MidBox; int BoxDots; MidBox=HandleLock(ItemGetHandle(HBox)); if (MidBox==NULL) break; BoxGetPolygonDrawBorder((Boxs *)MidBox,&BoxDots,BoxXY); PolygonGetMinRectangle(BoxDots,BoxXY,&BoxLeft,&BoxTop,&BoxRight,&BoxBottom); if (RectangleIsInRectangle(BoxDrawLeft,BoxDrawTop,BoxDrawRight,BoxDrawBottom, BoxLeft,BoxTop,BoxRight,BoxBottom)||TextBoxGetBoxType(MidBox)==TEXTBOX) { HBOX LinkBox; BoxDraw(HBox, (HBox==GlobalBoxHeadHandle)?DRAWBORDERWITHRECATNGLE: DRAWVIRTUALBORDOR); if (TextBoxGetBoxType(MidBox)==TEXTBOX && (GlobalBoxTool==IDX_UNLINK||GlobalBoxTool==IDX_LINK) && (LinkBox=TextBoxGetPrevLinkBox(MidBox))!=0 ) { ORDINATETYPE Left2,Top2,Right2,Bottom2; BoxGetRect(HBox,&BoxLeft,&BoxTop,&BoxRight,&BoxBottom); BoxXY[0]=BoxLeft; BoxXY[1]=BoxTop; BoxPolygonRotate(1,BoxXY,(PictureBoxs *)MidBox); BoxPolygonToWindowXY(1,BoxXY); BoxLeft=BoxXY[0]; BoxTop=BoxXY[1]; if(ItemGetFather(LinkBox)==PageHandle) { BoxGetRect(LinkBox,&Left2,&Top2,&Right2,&Bottom2); BoxXY[0]=Right2; BoxXY[1]=Bottom2; BoxPolygonRotate(1,BoxXY,HandleLock(ItemGetHandle(LinkBox))); HandleUnlock(ItemGetHandle(LinkBox)); BoxPolygonToWindowXY(1,BoxXY); } else { BoxXY[0]=getmaxx(); BoxXY[1]=0; // screen (Right,Top) } line(BoxLeft,BoxTop,BoxXY[0],BoxXY[1]); } } HandleUnlock(ItemGetHandle(HBox)); HBox=ItemGetNext(HBox); } if (GlobalGroupGetSign()) GroupDrawAllBorder(DRAWXORBORDER); setviewport(TmpViewPort.left,TmpViewPort.top,TmpViewPort.right, TmpViewPort.bottom,TmpViewPort.clip); setcolor(SaveColor); MouseShow(); return; }
void DrawPageFootHead(HPAGE PageHandle,BOOL fDrawFoot,BOOL fDrawHead) { Pages *MidPage; int i,k,PageNum,x,y,PgFtWid,PgHdWid; Wchar code; int width; int fString=NO_NUM; BOOL fBothAtMid=FALSE; char str[PAGEHEADSTRMAXLEN+20],headstr[PAGEHEADSTRMAXLEN]; MidPage=HandleLock(ItemGetHandle(PageHandle)); PageNum=PageHandleToNumber(PageHandle)+PgFtStartNum; if(PrintingSign) width=UserXToWindowX(146); else width=myUserXToWindowX(146); // /GlobalPageScale; /* use 5' size */ if(GetPageHeadOption()&&GetPageFootOption()&&GetPageFootTopOption()==FOOTTOP) { if((PageNum&1)==0) // page_head_string may be at left { if((GetPageFootLeftOption()==FOOTLEFT||GetPageFootLeftOption()==FOOTLEFT_RIGHT) && (GetPageHeadLeftOption()==FOOTLEFT||GetPageHeadLeftOption()==FOOTLEFT_RIGHT) ) fString=AFTER_NUM; //- put it after PageNum string else if(GetPageFootLeftOption()==GetPageHeadLeftOption()) // middle, right { if(GetPageFootLeftOption()==FOOTMID) fBothAtMid=TRUE; fString=PREV_NUM; //- put it prev to PageNum string } } else // page_head_string may be at right { if((GetPageFootLeftOption()==FOOTRIGHT||GetPageFootLeftOption()==FOOTLEFT_RIGHT) && (GetPageHeadLeftOption()==FOOTRIGHT||GetPageHeadLeftOption()==FOOTLEFT_RIGHT) ) fString=PREV_NUM; //- put it prev to PageNum string else if(GetPageFootLeftOption()==GetPageHeadLeftOption()) if(GetPageFootLeftOption()==FOOTLEFT) fString=AFTER_NUM; //- left, put it after PageNum string else { fString=PREV_NUM; //- middle, put it prev to PageNum string fBothAtMid=TRUE; } } } /*--- draw page foot (page number) ---*/ if(GetPageFootOption() && (fDrawFoot || fString) ) { // calculate page foot string's length itoa(PageNum,str,10); //-- insert prev<sp>, <sp>suff to str -- switch(GetPageFootPrevOption()) { case DOT_PREV: code='.'; goto calu_prev; case LINE_PREV: code='-'; calu_prev: i=strlen(str); memmove(str+2,str,i); str[0]=str[i+3]=code; str[1]=str[i+2]=BLANK; str[i+4]=0; break; } /* end of switch */ if(fBothAtMid) // ... <PageHeadStr><sp><sp><PageNum> ... { // strcat(headstr,str), then build str. if((PageNum&1)!=0) // page_head_string at right strcpy(headstr,PageHeadRightStr); else strcpy(headstr,PageHeadLeftStr); i=strlen(headstr); memmove(str+i+2,str,i); memmove(str,headstr,i); str[i+1]=str[i]=BLANK; fDrawFoot=TRUE; } PgFtWid=(float)CalcStrLen(str)*width/CHAR_WIDTH_IN_DOT+0.5; //--- calculate Y value --- if(GetPageFootTopOption()==FOOTTOP) y=UserYToWindowY(PageGetMarginTop(MidPage))-width; else y=UserYToWindowY(PageGetPageHeight(MidPage) -PageGetMarginBottom(MidPage))+width*3/2; //--- calculate X value --- switch(GetPageFootLeftOption()) { case FOOTLEFT: x=UserXToWindowX(PageGetMarginLeft(MidPage))+width; break; case FOOTRIGHT: PgFtWid+=width; x=UserXToWindowX(PageGetPageWidth(MidPage) -PageGetMarginRight(MidPage)) -PgFtWid; break; case FOOTLEFT_RIGHT: if( (PageNum&1)==0) // odd, put PageNum at left x=UserXToWindowX(PageGetMarginLeft(MidPage))+width; else // even, put it at right { PgFtWid+=width; x=UserXToWindowX(PageGetPageWidth(MidPage) -PageGetMarginRight(MidPage)) -PgFtWid; } break; case FOOTMID: x=UserXToWindowX(PageGetPageWidth(MidPage) -PageGetMarginRight(MidPage)) -PgFtWid; x+=UserXToWindowX(PageGetMarginLeft(MidPage)); x/=2; break; } /* end of switch */ /*----- now, draw page foot string ------*/ if(fDrawFoot) BuildStr(x,y,str,width); if(fBothAtMid) goto lbl_draw_page_head_line; x+=PgFtWid; } /*-- page foot --*/ /*--- draw page head string ----*/ if(GetPageHeadOption() && fDrawHead) { if((PageNum&1)!=0) strcpy(str,PageHeadRightStr); else strcpy(str,PageHeadLeftStr); PgHdWid=(float)CalcStrLen(str)*width/CHAR_WIDTH_IN_DOT+0.5; if(fString==AFTER_NUM) x+=width*3/2; // use last_modified_X, add some SPACE else switch(GetPageHeadLeftOption()) { case FOOTLEFT: lbl_head_left: x=UserXToWindowX(PageGetMarginLeft(MidPage)); break; case FOOTMID: x=UserXToWindowX(PageGetPageWidth(MidPage) -PageGetMarginRight(MidPage)) -PgHdWid; x+=UserXToWindowX(PageGetMarginLeft(MidPage)); x/=2; break; case FOOTRIGHT: lbl_head_right: x=UserXToWindowX(PageGetPageWidth(MidPage) -PageGetMarginRight(MidPage)) - PgHdWid; if(fString==PREV_NUM) // page num is at right also x-=PgFtWid+width*3/2; // add some SPACE break; case FOOTLEFT_RIGHT: if((PageNum&1)!=0) // page_head_string at right goto lbl_head_right; else goto lbl_head_left; } /*- end of switch -*/ y=UserYToWindowY(PageGetMarginTop(MidPage))-width; BuildStr(x,y,str,width); // if page head string is not NULL, draw a line if(str[0]&&GetPageHeadLineOption()) { lbl_draw_page_head_line: x=UserXToWindowX(PageGetMarginLeft(MidPage)); i=UserXToWindowX(PageGetPageWidth(MidPage) -PageGetMarginRight(MidPage)); y+=width/4; if(PrintingSign) { printer->printScanLine(x,i,y,&SysDc); printer->printScanLine(x,i,y+1,&SysDc); } else { setcolor(EGA_BLACK); line(x,y,i,y); } if(GetPageHeadLineOption()==HEADLINE_DOUBLE) { y+=width/6; for(k=0;k<width/6;k++) if(PrintingSign) printer->printScanLine(x,i,y+k,&SysDc); else { line(x,y+k,i,y+k); } } } /*--- page head line ---*/ } /*-- if pagehead --*/ HandleUnlock(ItemGetHandle(PageHandle)); }
void gena_process_notification_event( SOCKINFO *info, http_message_t *event) { struct Upnp_Event event_struct; IXML_Document *ChangedVars = NULL; int eventKey; token sid; ClientSubscription *subscription = NULL; struct Handle_Info *handle_info; void *cookie; Upnp_FunPtr callback; UpnpClient_Handle client_handle; const UpnpString *tmpSID = NULL; memptr sid_hdr; memptr nt_hdr, nts_hdr; memptr seq_hdr; /* get SID */ if (httpmsg_find_hdr(event, HDR_SID, &sid_hdr) == NULL) { error_respond(info, HTTP_PRECONDITION_FAILED, event); goto exit_function; } sid.buff = sid_hdr.buf; sid.size = sid_hdr.length; /* get event key */ if (httpmsg_find_hdr(event, HDR_SEQ, &seq_hdr) == NULL || matchstr(seq_hdr.buf, seq_hdr.length, "%d%0", &eventKey) != PARSE_OK) { error_respond( info, HTTP_BAD_REQUEST, event ); goto exit_function; } /* get NT and NTS headers */ if (httpmsg_find_hdr(event, HDR_NT, &nt_hdr) == NULL || httpmsg_find_hdr(event, HDR_NTS, &nts_hdr) == NULL) { error_respond( info, HTTP_BAD_REQUEST, event ); goto exit_function; } /* verify NT and NTS headers */ if (memptr_cmp(&nt_hdr, "upnp:event") != 0 || memptr_cmp(&nts_hdr, "upnp:propchange") != 0) { error_respond(info, HTTP_PRECONDITION_FAILED, event); goto exit_function; } /* parse the content (should be XML) */ if (!has_xml_content_type(event) || event->msg.length == 0 || ixmlParseBufferEx(event->entity.buf, &ChangedVars) != IXML_SUCCESS) { error_respond(info, HTTP_BAD_REQUEST, event); goto exit_function; } HandleLock(); /* get client info */ if (GetClientHandleInfo(&client_handle, &handle_info) != HND_CLIENT) { error_respond(info, HTTP_PRECONDITION_FAILED, event); HandleUnlock(); goto exit_function; } /* get subscription based on SID */ subscription = GetClientSubActualSID(handle_info->ClientSubList, &sid); if (subscription == NULL) { if (eventKey == 0) { /* wait until we've finished processing a subscription */ /* (if we are in the middle) */ /* this is to avoid mistakenly rejecting the first event if we */ /* receive it before the subscription response */ HandleUnlock(); /* try and get Subscription Lock */ /* (in case we are in the process of subscribing) */ SubscribeLock(); /* get HandleLock again */ HandleLock(); if (GetClientHandleInfo(&client_handle, &handle_info) != HND_CLIENT) { error_respond(info, HTTP_PRECONDITION_FAILED, event); SubscribeUnlock(); HandleUnlock(); goto exit_function; } subscription = GetClientSubActualSID(handle_info->ClientSubList, &sid); if (subscription == NULL) { error_respond( info, HTTP_PRECONDITION_FAILED, event ); SubscribeUnlock(); HandleUnlock(); goto exit_function; } SubscribeUnlock(); } else { error_respond( info, HTTP_PRECONDITION_FAILED, event ); HandleUnlock(); goto exit_function; } } /* success */ error_respond(info, HTTP_OK, event); /* fill event struct */ tmpSID = UpnpClientSubscription_get_SID(subscription); memset(event_struct.Sid, 0, sizeof(event_struct.Sid)); strncpy(event_struct.Sid, UpnpString_get_String(tmpSID), sizeof(event_struct.Sid) - 1); event_struct.EventKey = eventKey; event_struct.ChangedVariables = ChangedVars; /* copy callback */ callback = handle_info->Callback; cookie = handle_info->Cookie; HandleUnlock(); /* make callback with event struct */ /* In future, should find a way of mainting */ /* that the handle is not unregistered in the middle of a */ /* callback */ callback(UPNP_EVENT_RECEIVED, &event_struct, cookie); exit_function: ixmlDocument_free(ChangedVars); }
HPAGE PageNew(Pages *NewPage,int PageNumber) { Items NewPageHandle; HITEM MidPageItem,MidItem,MidBoxItem; Pages *MidPage; // TextBoxs NewBox; // ByHance #define NewBox (TmpBuf.TextBox) memset(&NewPageHandle,0,sizeof(NewPageHandle)); if (PageNumber>0) MidPageItem=PageNumberToHandle(PageNumber-1); else MidPageItem=0; if (!(MidPageItem=ItemInsert(&NewPageHandle,GlobalPageHeadHandle,MidPageItem))) return(0); if (!PageNumber) { if (!(MidItem=HandleAlloc(sizeof(Pages),0))) return(0); if ((MidPage=(Pages *)HandleLock(MidItem))==NULL) { HandleFree(MidItem); return(0); } memcpy(MidPage,NewPage,sizeof(Pages)); HandleUnlock(MidItem); ItemSetHandle(MidPageItem,MidItem); } else ItemSetHandle(MidPageItem,ItemGetHandle(PageNumberToHandle(0))); if (PageHaveInitialBox(*NewPage)) { HBOX NewHBox; int CursorX,CursorY; TextBoxs *BoxPointer; DefaultNewBox(NewPage,&NewBox); NewBox.BoxStatus|=4; // TextBoxSetDependPage() MidBoxItem=TextBoxInsert(&NewBox,MidPageItem); if (!MidBoxItem) return(OUTOFMEMORY); if (TotalPage==0) { GlobalBoxHeadHandle=MidBoxItem; GlobalTextPosition=0; TextBoxSeekTextPosition(GlobalBoxHeadHandle,0,1,&GlobalTextPosition); TextBoxSeekTextPosition(GlobalBoxHeadHandle,GlobalTextPosition,-1,&GlobalTextPosition); CursorLocate(GlobalBoxHeadHandle,&NewHBox,GlobalTextPosition,&CursorX,&CursorY); } // BoxPointer=HandleLock(ItemGetHandle(GlobalBoxHeadHandle)); BoxPointer=HandleLock(ItemGetHandle(MidBoxItem)); // ByHance, 95,12.5 if (BoxPointer) BoxSetLocked(BoxPointer); HandleUnlock(ItemGetHandle(MidBoxItem)); // HandleUnlock(ItemGetHandle(GlobalBoxHeadHandle)); /* else { TextBoxs *TextBox; GlobalBoxHeadHandle=MidBoxItem; TextBox=HandleLock(ItemGetHandle(GlobalBoxHeadHandle)); if (TextBox!=NULL) { InitRL(TextBox); HandleUnlock(ItemGetHandle(GlobalBoxHeadHandle)); } } */ } else if (TotalPage==0) GlobalBoxHeadHandle=0; TotalPage++; FileSetModified(); return(MidPageItem); #undef NewBox // ByHance }
int genaRenewSubscription( UpnpClient_Handle client_handle, const UpnpString *in_sid, int *TimeOut) { int return_code = GENA_SUCCESS; ClientSubscription *sub = NULL; ClientSubscription *sub_copy = UpnpClientSubscription_new(); struct Handle_Info *handle_info; UpnpString *ActualSID = UpnpString_new(); ThreadPoolJob tempJob; HandleLock(); /* validate handle and sid */ if (GetHandleInfo(client_handle, &handle_info) != HND_CLIENT) { HandleUnlock(); return_code = GENA_E_BAD_HANDLE; goto exit_function; } sub = GetClientSubClientSID(handle_info->ClientSubList, in_sid); if (sub == NULL) { HandleUnlock(); return_code = GENA_E_BAD_SID; goto exit_function; } /* remove old events */ if (TimerThreadRemove( &gTimerThread, UpnpClientSubscription_get_RenewEventId(sub), &tempJob) == 0 ) { free_upnp_timeout((upnp_timeout *)tempJob.arg); } UpnpPrintf(UPNP_INFO, GENA, __FILE__, __LINE__, "REMOVED AUTO RENEW EVENT"); UpnpClientSubscription_set_RenewEventId(sub, -1); UpnpClientSubscription_assign(sub_copy, sub); HandleUnlock(); return_code = gena_subscribe( UpnpClientSubscription_get_EventURL(sub_copy), TimeOut, UpnpClientSubscription_get_ActualSID(sub_copy), ActualSID); HandleLock(); if (GetHandleInfo(client_handle, &handle_info) != HND_CLIENT) { HandleUnlock(); return_code = GENA_E_BAD_HANDLE; goto exit_function; } /* we just called GetHandleInfo, so we don't check for return value */ /*GetHandleInfo(client_handle, &handle_info); */ if (return_code != UPNP_E_SUCCESS) { /* network failure (remove client sub) */ RemoveClientSubClientSID(&handle_info->ClientSubList, in_sid); free_client_subscription(sub_copy); HandleUnlock(); goto exit_function; } /* get subscription */ sub = GetClientSubClientSID(handle_info->ClientSubList, in_sid); if (sub == NULL) { free_client_subscription(sub_copy); HandleUnlock(); return_code = GENA_E_BAD_SID; goto exit_function; } /* store actual sid */ UpnpClientSubscription_set_ActualSID(sub, ActualSID); /* start renew subscription timer */ return_code = ScheduleGenaAutoRenew(client_handle, *TimeOut, sub); if (return_code != GENA_SUCCESS) { RemoveClientSubClientSID( &handle_info->ClientSubList, UpnpClientSubscription_get_SID(sub)); } free_client_subscription(sub_copy); HandleUnlock(); exit_function: UpnpString_delete(ActualSID); UpnpClientSubscription_delete(sub_copy); return return_code; }
int genaSubscribe( UpnpClient_Handle client_handle, const UpnpString *PublisherURL, int *TimeOut, UpnpString *out_sid) { int return_code = GENA_SUCCESS; ClientSubscription *newSubscription = UpnpClientSubscription_new(); uuid_upnp uid; Upnp_SID temp_sid; Upnp_SID temp_sid2; UpnpString *ActualSID = UpnpString_new(); UpnpString *EventURL = UpnpString_new(); struct Handle_Info *handle_info; int rc = 0; memset(temp_sid, 0, sizeof(temp_sid)); memset(temp_sid2, 0, sizeof(temp_sid2)); UpnpPrintf(UPNP_INFO, GENA, __FILE__, __LINE__, "GENA SUBSCRIBE BEGIN"); UpnpString_clear(out_sid); HandleReadLock(); /* validate handle */ if (GetHandleInfo(client_handle, &handle_info) != HND_CLIENT) { return_code = GENA_E_BAD_HANDLE; SubscribeLock(); goto error_handler; } HandleUnlock(); /* subscribe */ SubscribeLock(); return_code = gena_subscribe(PublisherURL, TimeOut, NULL, ActualSID); HandleLock(); if (return_code != UPNP_E_SUCCESS) { UpnpPrintf( UPNP_CRITICAL, GENA, __FILE__, __LINE__, "SUBSCRIBE FAILED in transfer error code: %d returned\n", return_code ); goto error_handler; } if(GetHandleInfo(client_handle, &handle_info) != HND_CLIENT) { return_code = GENA_E_BAD_HANDLE; goto error_handler; } /* generate client SID */ uuid_create(&uid ); uuid_unpack(&uid, temp_sid); rc = snprintf(temp_sid2, sizeof(temp_sid2), "uuid:%s", temp_sid); if (rc < 0 || (unsigned int) rc >= sizeof(temp_sid2)) { return_code = UPNP_E_OUTOF_MEMORY; goto error_handler; } UpnpString_set_String(out_sid, temp_sid2); /* create event url */ UpnpString_assign(EventURL, PublisherURL); /* fill subscription */ if (newSubscription == NULL) { return_code = UPNP_E_OUTOF_MEMORY; goto error_handler; } UpnpClientSubscription_set_RenewEventId(newSubscription, -1); UpnpClientSubscription_set_SID(newSubscription, out_sid); UpnpClientSubscription_set_ActualSID(newSubscription, ActualSID); UpnpClientSubscription_set_EventURL(newSubscription, EventURL); UpnpClientSubscription_set_Next(newSubscription, handle_info->ClientSubList); handle_info->ClientSubList = newSubscription; /* schedule expiration event */ return_code = ScheduleGenaAutoRenew(client_handle, *TimeOut, newSubscription); error_handler: UpnpString_delete(ActualSID); UpnpString_delete(EventURL); if (return_code != UPNP_E_SUCCESS) UpnpClientSubscription_delete(newSubscription); HandleUnlock(); SubscribeUnlock(); return return_code; }
/**************************************************************************** * Function : get_device_info * * Parameters : * IN http_message_t* request : HTTP request * IN int isQuery : flag for a querry * IN IXML_Document *actionDoc : action request document * OUT char device_udn[LINE_SIZE] : Device UDN string * OUT char service_id[LINE_SIZE] : Service ID string * OUT Upnp_FunPtr *callback : callback function of the device * application * OUT void** cookie : cookie stored by device application * * Description : This function retrives all the information needed to * process the incoming SOAP request. It finds the device and service info * and also the callback function to hand-over the request to the device * application. * * Return : int * UPNP_E_SUCCESS if successful else returns appropriate error * * Note : ****************************************************************************/ static int get_device_info( IN http_message_t * request, IN int isQuery, IN IXML_Document * actionDoc, OUT char device_udn[LINE_SIZE], OUT char service_id[LINE_SIZE], OUT Upnp_FunPtr * callback, OUT void **cookie ) { struct Handle_Info *device_info; int device_hnd; service_info *serv_info; char save_char; int ret_code = -1; // error by default const char *control_url; char *actionName = NULL; // null-terminate pathquery of url control_url = request->uri.pathquery.buff; save_char = control_url[request->uri.pathquery.size]; ((char *)control_url)[request->uri.pathquery.size] = '\0'; HandleLock(); if( GetDeviceHandleInfo( &device_hnd, &device_info ) != HND_DEVICE ) { goto error_handler; } if( ( serv_info = FindServiceControlURLPath( &device_info->ServiceTable, control_url ) ) == NULL ) { goto error_handler; } if( isQuery ) { ret_code = check_soap_action_header( request, QUERY_STATE_VAR_URN, &actionName ); if( ( ret_code != UPNP_E_SUCCESS ) && ( ret_code != UPNP_E_OUTOF_MEMORY ) ) { ret_code = UPNP_E_INVALID_ACTION; goto error_handler; } //check soap body ret_code = check_soap_body( actionDoc, QUERY_STATE_VAR_URN, actionName ); free( actionName ); if( ret_code != UPNP_E_SUCCESS ) { goto error_handler; } } else { ret_code = check_soap_action_header( request, serv_info->serviceType, &actionName ); if( ( ret_code != UPNP_E_SUCCESS ) && ( ret_code != UPNP_E_OUTOF_MEMORY ) ) { ret_code = UPNP_E_INVALID_SERVICE; goto error_handler; } //check soap body ret_code = check_soap_body( actionDoc, serv_info->serviceType, actionName ); free( actionName ); if( ret_code != UPNP_E_SUCCESS ) { ret_code = UPNP_E_INVALID_SERVICE; goto error_handler; } } namecopy( service_id, serv_info->serviceId ); namecopy( device_udn, serv_info->UDN ); *callback = device_info->Callback; *cookie = device_info->Cookie; ret_code = 0; error_handler: ((char *)control_url)[request->uri.pathquery.size] = save_char; // restore HandleUnlock(); return ret_code; }
void gena_process_unsubscribe_request( SOCKINFO *info, http_message_t *request) { Upnp_SID sid; service_info *service; struct Handle_Info *handle_info; UpnpDevice_Handle device_handle; memptr temp_hdr; membuffer event_url_path; /* if a CALLBACK or NT header is present, then it is an error */ if( httpmsg_find_hdr( request, HDR_CALLBACK, NULL ) != NULL || httpmsg_find_hdr( request, HDR_NT, NULL ) != NULL ) { error_respond( info, HTTP_BAD_REQUEST, request ); return; } /* get SID */ if( httpmsg_find_hdr( request, HDR_SID, &temp_hdr ) == NULL || temp_hdr.length > SID_SIZE ) { error_respond( info, HTTP_PRECONDITION_FAILED, request ); return; } memcpy( sid, temp_hdr.buf, temp_hdr.length ); sid[temp_hdr.length] = '\0'; /* lookup service by eventURL */ membuffer_init( &event_url_path ); if( membuffer_append( &event_url_path, request->uri.pathquery.buff, request->uri.pathquery.size ) != 0 ) { error_respond( info, HTTP_INTERNAL_SERVER_ERROR, request ); return; } HandleLock(); /* CURRENTLY, ONLY SUPPORT ONE DEVICE */ if( GetDeviceHandleInfo( info->foreign_sockaddr.ss_family, &device_handle, &handle_info ) != HND_DEVICE ) { error_respond( info, HTTP_PRECONDITION_FAILED, request ); membuffer_destroy( &event_url_path ); HandleUnlock(); return; } service = FindServiceEventURLPath( &handle_info->ServiceTable, event_url_path.buf ); membuffer_destroy( &event_url_path ); /* validate service */ if( service == NULL || !service->active || GetSubscriptionSID( sid, service ) == NULL ) { error_respond( info, HTTP_PRECONDITION_FAILED, request ); HandleUnlock(); return; } RemoveSubscriptionSID(sid, service); error_respond(info, HTTP_OK, request); /* success */ HandleUnlock(); }
/************************************************************************ * Function : gena_process_notification_event * * Parameters: * IN SOCKINFO *info: Socket structure containing the device socket * information * IN http_message_t* event: The http message contains the GENA * notification * * Description: * This function processes NOTIFY events that are sent by devices. * called by genacallback() * * Returns: void * * Note : called by genacallback() ****************************************************************************/ void gena_process_notification_event( IN SOCKINFO * info, IN http_message_t * event ) { struct Upnp_Event event_struct; int eventKey; token sid; client_subscription *subscription; IXML_Document *ChangedVars; struct Handle_Info *handle_info; void *cookie; Upnp_FunPtr callback; UpnpClient_Handle client_handle; memptr sid_hdr; memptr nt_hdr, nts_hdr; memptr seq_hdr; // get SID if( httpmsg_find_hdr( event, HDR_SID, &sid_hdr ) == NULL ) { error_respond( info, HTTP_PRECONDITION_FAILED, event ); return; } sid.buff = sid_hdr.buf; sid.size = sid_hdr.length; // get event key if( httpmsg_find_hdr( event, HDR_SEQ, &seq_hdr ) == NULL || matchstr( seq_hdr.buf, seq_hdr.length, "%d%0", &eventKey ) != PARSE_OK ) { error_respond( info, HTTP_BAD_REQUEST, event ); return; } // get NT and NTS headers if( httpmsg_find_hdr( event, HDR_NT, &nt_hdr ) == NULL || httpmsg_find_hdr( event, HDR_NTS, &nts_hdr ) == NULL ) { error_respond( info, HTTP_BAD_REQUEST, event ); return; } // verify NT and NTS headers if( memptr_cmp( &nt_hdr, "upnp:event" ) != 0 || memptr_cmp( &nts_hdr, "upnp:propchange" ) != 0 ) { error_respond( info, HTTP_PRECONDITION_FAILED, event ); return; } // parse the content (should be XML) if( !has_xml_content_type( event ) || event->msg.length == 0 || ( ixmlParseBufferEx( event->entity.buf, &ChangedVars ) ) != IXML_SUCCESS ) { error_respond( info, HTTP_BAD_REQUEST, event ); return; } HandleLock( ); // get client info if( GetClientHandleInfo( &client_handle, &handle_info ) != HND_CLIENT ) { error_respond( info, HTTP_PRECONDITION_FAILED, event ); HandleUnlock( ); ixmlDocument_free( ChangedVars ); return; } // get subscription based on SID if( ( subscription = GetClientSubActualSID( handle_info->ClientSubList, &sid ) ) == NULL ) { if( eventKey == 0 ) { // wait until we've finished processing a subscription // (if we are in the middle) // this is to avoid mistakenly rejecting the first event if we // receive it before the subscription response HandleUnlock( ); // try and get Subscription Lock // (in case we are in the process of subscribing) SubscribeLock( ); // get HandleLock again HandleLock( ); if( GetClientHandleInfo( &client_handle, &handle_info ) != HND_CLIENT ) { error_respond( info, HTTP_PRECONDITION_FAILED, event ); SubscribeUnlock( ); HandleUnlock( ); ixmlDocument_free( ChangedVars ); return; } if( ( subscription = GetClientSubActualSID( handle_info->ClientSubList, &sid ) ) == NULL ) { error_respond( info, HTTP_PRECONDITION_FAILED, event ); SubscribeUnlock( ); HandleUnlock( ); ixmlDocument_free( ChangedVars ); return; } SubscribeUnlock( ); } else { error_respond( info, HTTP_PRECONDITION_FAILED, event ); HandleUnlock( ); ixmlDocument_free( ChangedVars ); return; } } error_respond( info, HTTP_OK, event ); // success // fill event struct strcpy( event_struct.Sid, subscription->sid ); event_struct.EventKey = eventKey; event_struct.ChangedVariables = ChangedVars; // copy callback callback = handle_info->Callback; cookie = handle_info->Cookie; HandleUnlock( ); // make callback with event struct // In future, should find a way of mainting // that the handle is not unregistered in the middle of a // callback callback( UPNP_EVENT_RECEIVED, &event_struct, cookie ); ixmlDocument_free( ChangedVars ); }
/*! * \brief Thread job to Notify a control point. * * It validates the subscription and copies the subscription. Also make sure * that events are sent in order. * * \note calls the genaNotify to do the actual work. */ static void genaNotifyThread( /*! [in] notify thread structure containing all the headers and property set info. */ void *input) { subscription *sub; service_info *service; subscription sub_copy; notify_thread_struct *in = (notify_thread_struct *) input; int return_code; struct Handle_Info *handle_info; ThreadPoolJob job; memset(&job, 0, sizeof(job)); /* This should be a HandleLock and not a HandleReadLock otherwise if there * is a lot of notifications, then multiple threads will acquire a read * lock and the thread which sends the notification will be blocked forever * on the HandleLock at the end of this function. */ /*HandleReadLock(); */ HandleLock(); /* validate context */ if (GetHandleInfo(in->device_handle, &handle_info) != HND_DEVICE) { free_notify_struct(in); HandleUnlock(); return; } if (!(service = FindServiceId(&handle_info->ServiceTable, in->servId, in->UDN)) || !service->active || !(sub = GetSubscriptionSID(in->sid, service)) || copy_subscription(sub, &sub_copy) != HTTP_SUCCESS) { free_notify_struct(in); HandleUnlock(); return; } #ifdef UPNP_ENABLE_NOTIFICATION_REORDERING /*If the event is out of order push it back to the job queue */ if (in->eventKey != sub->ToSendEventKey) { TPJobInit(&job, (start_routine) genaNotifyThread, input); TPJobSetFreeFunction(&job, (free_function) free_notify_struct); TPJobSetPriority(&job, MED_PRIORITY); /* Sleep a little before creating another thread otherwise if there is * a lot of notifications to send, the device will take 100% of the CPU * to create threads and push them back to the job queue. */ imillisleep(1); ThreadPoolAdd(&gSendThreadPool, &job, NULL); freeSubscription(&sub_copy); HandleUnlock(); return; } #endif HandleUnlock(); /* send the notify */ return_code = genaNotify(in->headers, in->propertySet, &sub_copy); freeSubscription(&sub_copy); HandleLock(); if (GetHandleInfo(in->device_handle, &handle_info) != HND_DEVICE) { free_notify_struct(in); HandleUnlock(); return; } /* validate context */ if (!(service = FindServiceId(&handle_info->ServiceTable, in->servId, in->UDN)) || !service->active || !(sub = GetSubscriptionSID(in->sid, service))) { free_notify_struct(in); HandleUnlock(); return; } sub->ToSendEventKey++; if (sub->ToSendEventKey < 0) /* wrap to 1 for overflow */ sub->ToSendEventKey = 1; if (return_code == GENA_E_NOTIFY_UNACCEPTED_REMOVE_SUB) RemoveSubscriptionSID(in->sid, service); free_notify_struct(in); HandleUnlock(); }
/*! * \brief Retrives all the information needed to process the incoming SOAP * request. It finds the device and service info and also the callback * function to hand-over the request to the device application. * * \return UPNP_E_SUCCESS if successful else returns appropriate error. */ static int get_device_info( int iface, /*! [in] HTTP request. */ http_message_t *request, /*! [in] flag for a querry. */ int isQuery, /*! [in] Action request document. */ IXML_Document *actionDoc, /*! [in] . */ int AddressFamily, /*! [out] Device UDN string. */ OUT char device_udn[LINE_SIZE], /*! [out] Service ID string. */ char service_id[LINE_SIZE], /*! [out] callback function of the device application. */ Upnp_FunPtr *callback, /*! [out] cookie stored by device application. */ void **cookie) { struct Handle_Info *device_info; int device_hnd; service_info *serv_info; char save_char; /* error by default */ int ret_code = -1; const char *control_url; char *actionName = NULL; /* null-terminate pathquery of url */ control_url = request->uri.pathquery.buff; save_char = control_url[request->uri.pathquery.size]; ((char *)control_url)[request->uri.pathquery.size] = '\0'; HandleLock(); if (GetDeviceHandleInfo(iface, AddressFamily, &device_hnd, &device_info) != HND_DEVICE) goto error_handler; serv_info = FindServiceControlURLPath( &device_info->ServiceTable, control_url); if (!serv_info) goto error_handler; if (isQuery) { ret_code = check_soap_action_header(request, QUERY_STATE_VAR_URN, &actionName); if (ret_code != UPNP_E_SUCCESS && ret_code != UPNP_E_OUTOF_MEMORY) { ret_code = UPNP_E_INVALID_ACTION; goto error_handler; } /* check soap body */ ret_code = check_soap_body(actionDoc, QUERY_STATE_VAR_URN, actionName); free(actionName); if (ret_code != UPNP_E_SUCCESS) goto error_handler; } else { ret_code = check_soap_action_header(request, serv_info->serviceType, &actionName); if (ret_code != UPNP_E_SUCCESS && ret_code != UPNP_E_OUTOF_MEMORY) { ret_code = UPNP_E_INVALID_SERVICE; goto error_handler; } /* check soap body */ ret_code = check_soap_body(actionDoc, serv_info->serviceType, actionName); free(actionName); if (ret_code != UPNP_E_SUCCESS) { ret_code = UPNP_E_INVALID_SERVICE; goto error_handler; } } namecopy(service_id, serv_info->serviceId); namecopy(device_udn, serv_info->UDN); *callback = device_info->Callback; *cookie = device_info->Cookie; ret_code = 0; error_handler: /* restore */ ((char *)control_url)[request->uri.pathquery.size] = save_char; HandleUnlock(); return ret_code; }
int genaNotifyAll( UpnpDevice_Handle device_handle, char *UDN, char *servId, char **VarNames, char **VarValues, int var_count) { int ret = GENA_SUCCESS; int line = 0; int *reference_count = NULL; char *UDN_copy = NULL; char *servId_copy = NULL; DOMString propertySet = NULL; char *headers = NULL; notify_thread_struct *thread_struct = NULL; subscription *finger = NULL; service_info *service = NULL; struct Handle_Info *handle_info; ThreadPoolJob job; memset(&job, 0, sizeof(job)); UpnpPrintf(UPNP_INFO, GENA, __FILE__, __LINE__, "GENA BEGIN NOTIFY ALL"); reference_count = (int *)malloc(sizeof (int)); if (reference_count == NULL) { line = __LINE__; ret = UPNP_E_OUTOF_MEMORY; goto ExitFunction; } *reference_count = 0; UDN_copy = (char *)malloc(strlen(UDN) + 1); if (UDN_copy == NULL) { line = __LINE__; ret = UPNP_E_OUTOF_MEMORY; goto ExitFunction; } servId_copy = (char *)malloc(strlen(servId) + 1); if( servId_copy == NULL ) { line = __LINE__; ret = UPNP_E_OUTOF_MEMORY; goto ExitFunction; } memset(UDN_copy, 0, strlen(UDN) + 1); strncpy(UDN_copy, UDN, strlen(UDN)); memset(servId_copy, 0, strlen(servId) + 1); strncpy(servId_copy, servId, strlen(servId)); ret = GeneratePropertySet(VarNames, VarValues, var_count, &propertySet); if (ret != XML_SUCCESS) { line = __LINE__; goto ExitFunction; } UpnpPrintf(UPNP_INFO, GENA, __FILE__, __LINE__, "GENERATED PROPERTY SET IN EXT NOTIFY: %s", propertySet); headers = AllocGenaHeaders(propertySet); if (headers == NULL) { line = __LINE__; ret = UPNP_E_OUTOF_MEMORY; goto ExitFunction; } HandleLock(); if (GetHandleInfo(device_handle, &handle_info) != HND_DEVICE) { line = __LINE__; ret = GENA_E_BAD_HANDLE; } else { service = FindServiceId(&handle_info->ServiceTable, servId, UDN); if (service != NULL) { finger = GetFirstSubscription(service); while (finger) { thread_struct = (notify_thread_struct *)malloc(sizeof (notify_thread_struct)); if (thread_struct == NULL) { line = __LINE__; ret = UPNP_E_OUTOF_MEMORY; break; } (*reference_count)++; thread_struct->reference_count = reference_count; thread_struct->UDN = UDN_copy; thread_struct->servId = servId_copy; thread_struct->headers = headers; thread_struct->propertySet = propertySet; memset(thread_struct->sid, 0, sizeof(thread_struct->sid)); strncpy(thread_struct->sid, finger->sid, sizeof(thread_struct->sid) - 1); thread_struct->eventKey = finger->eventKey++; thread_struct->device_handle = device_handle; /* if overflow, wrap to 1 */ if (finger->eventKey < 0) { finger->eventKey = 1; } TPJobInit(&job, (start_routine)genaNotifyThread, thread_struct); TPJobSetFreeFunction(&job, (free_routine)free_notify_struct); TPJobSetPriority(&job, MED_PRIORITY); ret = ThreadPoolAdd(&gSendThreadPool, &job, NULL); if (ret != 0) { line = __LINE__; if (ret == EOUTOFMEM) { line = __LINE__; ret = UPNP_E_OUTOF_MEMORY; } break; } finger = GetNextSubscription(service, finger); } } else { line = __LINE__; ret = GENA_E_BAD_SERVICE; } } ExitFunction: if (ret != GENA_SUCCESS || *reference_count == 0) { free(headers); ixmlFreeDOMString(propertySet); free(servId_copy); free(UDN_copy); free(reference_count); } HandleUnlock(); UpnpPrintf(UPNP_INFO, GENA, __FILE__, line, "GENA END NOTIFY ALL, ret = %d", ret); return ret; }
/************************************************************************ * Function : ssdp_handle_ctrlpt_msg * * Parameters: * IN http_message_t* hmsg: SSDP message from the device * IN struct sockaddr_in* dest_addr: Address of the device * IN xboolean timeout: timeout kept by the control point while sending * search message * IN void* cookie: Cookie stored by the control point application. * This cookie will be returned to the control point * in the callback * * Description: * This function handles the ssdp messages from the devices. These * messages includes the search replies, advertisement of device coming * alive and bye byes. * * Returns: void * ***************************************************************************/ void ssdp_handle_ctrlpt_msg( IN http_message_t * hmsg, IN struct sockaddr_in *dest_addr, IN xboolean timeout, // only in search reply IN void *cookie ) // only in search reply { int handle; struct Handle_Info *ctrlpt_info = NULL; memptr hdr_value; xboolean is_byebye; // byebye or alive struct Upnp_Discovery param; SsdpEvent event; xboolean nt_found, usn_found, st_found; char save_char; Upnp_EventType event_type; Upnp_FunPtr ctrlpt_callback; void *ctrlpt_cookie; ListNode *node = NULL; SsdpSearchArg *searchArg = NULL; int matched = 0; ResultData *threadData; ThreadPoolJob job; // we are assuming that there can be only one client supported at a time HandleLock( ); if( GetClientHandleInfo( &handle, &ctrlpt_info ) != HND_CLIENT ) { HandleUnlock( ); return; } // copy ctrlpt_callback = ctrlpt_info->Callback; ctrlpt_cookie = ctrlpt_info->Cookie; HandleUnlock( ); // search timeout if( timeout ) { ctrlpt_callback( UPNP_DISCOVERY_SEARCH_TIMEOUT, NULL, cookie ); return; } param.ErrCode = UPNP_E_SUCCESS; // MAX-AGE param.Expires = -1; // assume error if( httpmsg_find_hdr( hmsg, HDR_CACHE_CONTROL, &hdr_value ) != NULL ) { matchstr( hdr_value.buf, hdr_value.length, "%imax-age = %d%0", ¶m.Expires ); } // DATE param.Date[0] = '\0'; if( httpmsg_find_hdr( hmsg, HDR_DATE, &hdr_value ) != NULL ) { linecopylen( param.Date, hdr_value.buf, hdr_value.length ); } // dest addr param.DestAddr = dest_addr; // EXT param.Ext[0] = '\0'; if( httpmsg_find_hdr( hmsg, HDR_EXT, &hdr_value ) != NULL ) { linecopylen( param.Ext, hdr_value.buf, hdr_value.length ); } // LOCATION param.Location[0] = '\0'; if( httpmsg_find_hdr( hmsg, HDR_LOCATION, &hdr_value ) != NULL ) { linecopylen( param.Location, hdr_value.buf, hdr_value.length ); } // SERVER / USER-AGENT param.Os[0] = '\0'; if( httpmsg_find_hdr( hmsg, HDR_SERVER, &hdr_value ) != NULL || httpmsg_find_hdr( hmsg, HDR_USER_AGENT, &hdr_value ) != NULL ) { linecopylen( param.Os, hdr_value.buf, hdr_value.length ); } // clear everything param.DeviceId[0] = '\0'; param.DeviceType[0] = '\0'; param.ServiceType[0] = '\0'; param.ServiceVer[0] = '\0'; // not used; version is in ServiceType event.UDN[0] = '\0'; event.DeviceType[0] = '\0'; event.ServiceType[0] = '\0'; nt_found = FALSE; if( httpmsg_find_hdr( hmsg, HDR_NT, &hdr_value ) != NULL ) { save_char = hdr_value.buf[hdr_value.length]; hdr_value.buf[hdr_value.length] = '\0'; nt_found = ( ssdp_request_type( hdr_value.buf, &event ) == 0 ); hdr_value.buf[hdr_value.length] = save_char; } usn_found = FALSE; if( httpmsg_find_hdr( hmsg, HDR_USN, &hdr_value ) != NULL ) { save_char = hdr_value.buf[hdr_value.length]; hdr_value.buf[hdr_value.length] = '\0'; usn_found = ( unique_service_name( hdr_value.buf, &event ) == 0 ); hdr_value.buf[hdr_value.length] = save_char; } if( nt_found || usn_found ) { strcpy( param.DeviceId, event.UDN ); strcpy( param.DeviceType, event.DeviceType ); strcpy( param.ServiceType, event.ServiceType ); } // ADVERT. OR BYEBYE if( hmsg->is_request ) { // use NTS hdr to determine advert., or byebye // if( httpmsg_find_hdr( hmsg, HDR_NTS, &hdr_value ) == NULL ) { return; // error; NTS header not found } if( memptr_cmp( &hdr_value, "ssdp:alive" ) == 0 ) { is_byebye = FALSE; } else if( memptr_cmp( &hdr_value, "ssdp:byebye" ) == 0 ) { is_byebye = TRUE; } else { return; // bad value } if( is_byebye ) { // check device byebye if( !nt_found || !usn_found ) { return; // bad byebye } event_type = UPNP_DISCOVERY_ADVERTISEMENT_BYEBYE; } else { // check advertisement // .Expires is valid if positive. This is for testing // only. Expires should be greater than 1800 (30 mins) if( !nt_found || !usn_found || strlen( param.Location ) == 0 || param.Expires <= 0 ) { return; // bad advertisement } event_type = UPNP_DISCOVERY_ADVERTISEMENT_ALIVE; } // call callback ctrlpt_callback( event_type, ¶m, ctrlpt_cookie ); } else // reply (to a SEARCH) { // only checking to see if there is a valid ST header st_found = FALSE; if( httpmsg_find_hdr( hmsg, HDR_ST, &hdr_value ) != NULL ) { save_char = hdr_value.buf[hdr_value.length]; hdr_value.buf[hdr_value.length] = '\0'; st_found = ssdp_request_type( hdr_value.buf, &event ) == 0; hdr_value.buf[hdr_value.length] = save_char; } if( hmsg->status_code != HTTP_OK || param.Expires <= 0 || strlen( param.Location ) == 0 || !usn_found || !st_found ) { return; // bad reply } //check each current search HandleLock( ); if( GetClientHandleInfo( &handle, &ctrlpt_info ) != HND_CLIENT ) { HandleUnlock( ); return; } node = ListHead( &ctrlpt_info->SsdpSearchList ); //temporary add null termination //save_char = hdr_value.buf[ hdr_value.length ]; //hdr_value.buf[ hdr_value.length ] = '\0'; while( node != NULL ) { searchArg = node->item; matched = 0; //check for match of ST header and search target switch ( searchArg->requestType ) { case SSDP_ALL: { matched = 1; break; } case SSDP_ROOTDEVICE: { matched = ( event.RequestType == SSDP_ROOTDEVICE ); break; } case SSDP_DEVICEUDN: { matched = !( strncmp( searchArg->searchTarget, hdr_value.buf, hdr_value.length ) ); break; } case SSDP_DEVICETYPE: { int m = min( hdr_value.length, strlen( searchArg->searchTarget ) ); matched = !( strncmp( searchArg->searchTarget, hdr_value.buf, m ) ); break; } case SSDP_SERVICE: { int m = min( hdr_value.length, strlen( searchArg->searchTarget ) ); matched = !( strncmp( searchArg->searchTarget, hdr_value.buf, m ) ); break; } default: { matched = 0; break; } } if( matched ) { //schedule call back threadData = ( ResultData * ) malloc( sizeof( ResultData ) ); if( threadData != NULL ) { threadData->param = param; threadData->cookie = searchArg->cookie; threadData->ctrlpt_callback = ctrlpt_callback; TPJobInit( &job, ( start_routine ) send_search_result, threadData ); TPJobSetPriority( &job, MED_PRIORITY ); TPJobSetFreeFunction( &job, ( free_routine ) free ); ThreadPoolAdd( &gRecvThreadPool, &job, NULL ); } } node = ListNext( &ctrlpt_info->SsdpSearchList, node ); } HandleUnlock( ); //ctrlpt_callback( UPNP_DISCOVERY_SEARCH_RESULT, ¶m, cookie ); } }
void ssdp_handle_ctrlpt_msg(http_message_t *hmsg, struct sockaddr_storage *dest_addr, int timeout, void *cookie) { int handle; struct Handle_Info *ctrlpt_info = NULL; memptr hdr_value; /* byebye or alive */ int is_byebye; UpnpDiscovery *param = UpnpDiscovery_new(); int expires; int ret; SsdpEvent event; int nt_found; int usn_found; int st_found; char save_char; Upnp_EventType event_type; Upnp_FunPtr ctrlpt_callback; void *ctrlpt_cookie; ListNode *node = NULL; SsdpSearchArg *searchArg = NULL; int matched = 0; SSDPResultData *threadData = NULL; ThreadPoolJob job; memset(&job, 0, sizeof(job)); /* we are assuming that there can be only one client supported at a time */ HandleReadLock(); if (GetClientHandleInfo(&handle, &ctrlpt_info) != HND_CLIENT) { HandleUnlock(); goto end_ssdp_handle_ctrlpt_msg; } /* copy */ ctrlpt_callback = ctrlpt_info->Callback; ctrlpt_cookie = ctrlpt_info->Cookie; HandleUnlock(); /* search timeout */ if (timeout) { ctrlpt_callback(UPNP_DISCOVERY_SEARCH_TIMEOUT, NULL, cookie); goto end_ssdp_handle_ctrlpt_msg; } UpnpDiscovery_set_ErrCode(param, UPNP_E_SUCCESS); /* MAX-AGE, assume error */ expires = -1; UpnpDiscovery_set_Expires(param, expires); if (httpmsg_find_hdr(hmsg, HDR_CACHE_CONTROL, &hdr_value) != NULL) { ret = matchstr(hdr_value.buf, hdr_value.length, "%imax-age = %d%0", &expires); UpnpDiscovery_set_Expires(param, expires); if (ret != PARSE_OK) goto end_ssdp_handle_ctrlpt_msg; } /* DATE */ if (httpmsg_find_hdr(hmsg, HDR_DATE, &hdr_value) != NULL) { UpnpDiscovery_strcpy_Date(param, hdr_value.buf); } /* dest addr */ UpnpDiscovery_set_DestAddr(param, dest_addr); /* EXT */ if (httpmsg_find_hdr(hmsg, HDR_EXT, &hdr_value) != NULL) { UpnpDiscovery_strncpy_Ext(param, hdr_value.buf, hdr_value.length); } /* LOCATION */ if (httpmsg_find_hdr(hmsg, HDR_LOCATION, &hdr_value) != NULL) { UpnpDiscovery_strncpy_Location(param, hdr_value.buf, hdr_value.length); } /* SERVER / USER-AGENT */ if (httpmsg_find_hdr(hmsg, HDR_SERVER, &hdr_value) != NULL || httpmsg_find_hdr(hmsg, HDR_USER_AGENT, &hdr_value) != NULL) { UpnpDiscovery_strncpy_Os(param, hdr_value.buf, hdr_value.length); } /* clear everything */ event.UDN[0] = '\0'; event.DeviceType[0] = '\0'; event.ServiceType[0] = '\0'; nt_found = FALSE; if (httpmsg_find_hdr(hmsg, HDR_NT, &hdr_value) != NULL) { save_char = hdr_value.buf[hdr_value.length]; hdr_value.buf[hdr_value.length] = '\0'; nt_found = (ssdp_request_type(hdr_value.buf, &event) == 0); hdr_value.buf[hdr_value.length] = save_char; } usn_found = FALSE; if (httpmsg_find_hdr(hmsg, HDR_USN, &hdr_value) != NULL) { save_char = hdr_value.buf[hdr_value.length]; hdr_value.buf[hdr_value.length] = '\0'; usn_found = (unique_service_name(hdr_value.buf, &event) == 0); hdr_value.buf[hdr_value.length] = save_char; } if (nt_found || usn_found) { UpnpDiscovery_strcpy_DeviceID(param, event.UDN); UpnpDiscovery_strcpy_DeviceType(param, event.DeviceType); UpnpDiscovery_strcpy_ServiceType(param, event.ServiceType); } /* ADVERT. OR BYEBYE */ if (hmsg->is_request) { /* use NTS hdr to determine advert., or byebye */ if (httpmsg_find_hdr(hmsg, HDR_NTS, &hdr_value) == NULL) { /* error; NTS header not found */ goto end_ssdp_handle_ctrlpt_msg; } if (memptr_cmp(&hdr_value, "ssdp:alive") == 0) { is_byebye = FALSE; } else if (memptr_cmp(&hdr_value, "ssdp:byebye") == 0) { is_byebye = TRUE; } else { /* bad value */ goto end_ssdp_handle_ctrlpt_msg; } if (is_byebye) { /* check device byebye */ if (!nt_found || !usn_found) { /* bad byebye */ goto end_ssdp_handle_ctrlpt_msg; } event_type = UPNP_DISCOVERY_ADVERTISEMENT_BYEBYE; } else { /* check advertisement. * Expires is valid if positive. This is for testing * only. Expires should be greater than 1800 (30 mins) */ if (!nt_found || !usn_found || UpnpString_get_Length(UpnpDiscovery_get_Location(param)) == 0 || UpnpDiscovery_get_Expires(param) <= 0) { /* bad advertisement */ goto end_ssdp_handle_ctrlpt_msg; } event_type = UPNP_DISCOVERY_ADVERTISEMENT_ALIVE; } /* call callback */ ctrlpt_callback(event_type, param, ctrlpt_cookie); } else { /* reply (to a SEARCH) */ /* only checking to see if there is a valid ST header */ st_found = FALSE; if (httpmsg_find_hdr(hmsg, HDR_ST, &hdr_value) != NULL) { save_char = hdr_value.buf[hdr_value.length]; hdr_value.buf[hdr_value.length] = '\0'; st_found = ssdp_request_type(hdr_value.buf, &event) == 0; hdr_value.buf[hdr_value.length] = save_char; } if (hmsg->status_code != HTTP_OK || UpnpDiscovery_get_Expires(param) <= 0 || UpnpString_get_Length(UpnpDiscovery_get_Location(param)) == 0 || !usn_found || !st_found) { /* bad reply */ goto end_ssdp_handle_ctrlpt_msg; } /* check each current search */ HandleLock(); if (GetClientHandleInfo(&handle, &ctrlpt_info) != HND_CLIENT) { HandleUnlock(); goto end_ssdp_handle_ctrlpt_msg; } node = ListHead(&ctrlpt_info->SsdpSearchList); /* temporary add null termination */ /*save_char = hdr_value.buf[ hdr_value.length ]; */ /*hdr_value.buf[ hdr_value.length ] = '\0'; */ while (node != NULL) { searchArg = node->item; /* check for match of ST header and search target */ switch (searchArg->requestType) { case SSDP_ALL: matched = 1; break; case SSDP_ROOTDEVICE: matched = (event.RequestType == SSDP_ROOTDEVICE); break; case SSDP_DEVICEUDN: matched = !strncmp(searchArg->searchTarget, hdr_value.buf, hdr_value.length); break; case SSDP_DEVICETYPE:{ size_t m = min(hdr_value.length, strlen (searchArg->searchTarget)); matched = !strncmp(searchArg->searchTarget, hdr_value.buf, m); break; } case SSDP_SERVICE:{ size_t m = min(hdr_value.length, strlen (searchArg->searchTarget)); matched = !strncmp(searchArg->searchTarget, hdr_value.buf, m); break; } default: matched = 0; break; } if (matched) { /* schedule call back */ threadData = SSDPResultData_new(); if (threadData != NULL) { SSDPResultData_set_Param(threadData, param); SSDPResultData_set_Cookie(threadData, searchArg-> cookie); SSDPResultData_set_CtrlptCallback (threadData, ctrlpt_callback); TPJobInit(&job, (start_routine) send_search_result, threadData); TPJobSetPriority(&job, MED_PRIORITY); TPJobSetFreeFunction(&job, (free_routine) SSDPResultData_delete); ThreadPoolAdd(&gRecvThreadPool, &job, NULL); } } node = ListNext(&ctrlpt_info->SsdpSearchList, node); } HandleUnlock(); /*ctrlpt_callback( UPNP_DISCOVERY_SEARCH_RESULT, param, cookie ); */ } end_ssdp_handle_ctrlpt_msg: UpnpDiscovery_delete(param); }
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); }
/************************************************************************ * Function : genaRenewSubscription * * Parameters: * IN UpnpClient_Handle client_handle: Client handle * IN const Upnp_SID in_sid: subscription ID * INOUT int * TimeOut: requested Duration, if -1, then "infinite". * in the OUT case: actual Duration granted * by Service, -1 for infinite * * Description: * This function renews a SID. It first validates the SID and * client_handle and copies the subscription. It sends RENEW * (modified SUBSCRIBE) http request to service and processes * the response. * * Returns: int * return UPNP_E_SUCCESS if service response is OK else * returns appropriate error ***************************************************************************/ int genaRenewSubscription( IN UpnpClient_Handle client_handle, IN const Upnp_SID in_sid, INOUT int *TimeOut ) { int return_code = GENA_SUCCESS; client_subscription *sub; client_subscription sub_copy; struct Handle_Info *handle_info; char *ActualSID; ThreadPoolJob tempJob; HandleLock( ); // validate handle and sid if( GetHandleInfo( client_handle, &handle_info ) != HND_CLIENT ) { HandleUnlock( ); return GENA_E_BAD_HANDLE; } if( ( sub = GetClientSubClientSID( handle_info->ClientSubList, in_sid ) ) == NULL ) { HandleUnlock( ); return GENA_E_BAD_SID; } // remove old events if( TimerThreadRemove( &gTimerThread, sub->RenewEventId, &tempJob ) == 0 ) { free_upnp_timeout( ( upnp_timeout * ) tempJob.arg ); } DBGONLY( UpnpPrintf( UPNP_INFO, GENA, __FILE__, __LINE__, "REMOVED AUTO RENEW EVENT" ) ); sub->RenewEventId = -1; return_code = copy_client_subscription( sub, &sub_copy ); HandleUnlock( ); if( return_code != HTTP_SUCCESS ) { return return_code; } return_code = gena_subscribe( sub_copy.EventURL, TimeOut, sub_copy.ActualSID, &ActualSID ); HandleLock( ); if( GetHandleInfo( client_handle, &handle_info ) != HND_CLIENT ) { HandleUnlock( ); if( return_code == UPNP_E_SUCCESS ) { free( ActualSID ); } return GENA_E_BAD_HANDLE; } // we just called GetHandleInfo, so we don't check for return value //GetHandleInfo(client_handle, &handle_info); if( return_code != UPNP_E_SUCCESS ) { // network failure (remove client sub) RemoveClientSubClientSID( &handle_info->ClientSubList, in_sid ); free_client_subscription( &sub_copy ); HandleUnlock( ); return return_code; } // get subscription if( ( sub = GetClientSubClientSID( handle_info->ClientSubList, in_sid ) ) == NULL ) { free( ActualSID ); free_client_subscription( &sub_copy ); HandleUnlock( ); return GENA_E_BAD_SID; } // store actual sid free( sub->ActualSID ); sub->ActualSID = ActualSID; // start renew subscription timer return_code = ScheduleGenaAutoRenew( client_handle, *TimeOut, sub ); if( return_code != GENA_SUCCESS ) { RemoveClientSubClientSID( &handle_info->ClientSubList, sub->sid ); } free_client_subscription( &sub_copy ); HandleUnlock( ); return return_code; }
/* PasteSign = 0:Paste to Page, 1: Paste to Text Box */ int ClipBoardGetBox(int PasteSign) { ClipBoards ClipBoardDataInformation; HBOX InsertHBox; // Boxs TmpBox,*Box; #define TmpBox TmpBuf Boxs *Box; TextBoxs *TextBox; PictureBoxs *PictureBox; ClipBoardGetDataInfomation(&ClipBoardDataInformation); if( ClipBoardDataInformation.ClipBoardDataLength==0 || ClipBoardDataInformation.ClipBoardDataType!=BOXDATA ) return(0); Box=&TmpBox; ClipBoardGet(Box,&ClipBoardDataInformation.ClipBoardDataLength, &ClipBoardDataInformation.ClipBoardDataType); InsertHBox=BoxInsert(Box,GlobalCurrentPage); if (!InsertHBox) return(OUTOFMEMORY); if (TextBoxGetBoxType((TextBoxs *)Box)==POLYGONPICTUREBOX) { int *PolygonEdges,PolygonLeft,PolygonTop,PolygonRight,PolygonBottom,i; ORDINATETYPE PolygonEdgeData[2*MAXPOLYGONNUMBER+1]; ClipBoardGetDataInfomation(&ClipBoardDataInformation); if ((ClipBoardDataInformation.ClipBoardDataLength==0)|| (ClipBoardDataInformation.ClipBoardDataType!=POLYGONDATA)) return(OUTOFMEMORY); ClipBoardGet(PolygonEdgeData,&ClipBoardDataInformation.ClipBoardDataLength, &ClipBoardDataInformation.ClipBoardDataType); PictureBox=HandleLock(ItemGetHandle(InsertHBox)); if (PictureBox==NULL) return(OUTOFMEMORY); PictureBoxSetBorderPolygon(PictureBox,HandleAlloc( sizeof(int)+2*sizeof(ORDINATETYPE)*MAXPOLYGONNUMBER,0)); if (!PictureBoxGetBorderPolygon(PictureBox)) { HandleUnlock(ItemGetHandle(InsertHBox)); return(OUTOFMEMORY); } PolygonEdges=HandleLock(PictureBoxGetBorderPolygon(PictureBox)); if (PolygonEdges==NULL) { HandleUnlock(ItemGetHandle(InsertHBox)); return(OUTOFMEMORY); } memcpy(PolygonEdges,PolygonEdgeData, ClipBoardDataInformation.ClipBoardDataLength); if (PasteSign==GETTOTEXTBOX) { PictureBoxSetBoxLeft(PictureBox,0); PictureBoxSetBoxTop(PictureBox,0); PolygonGetMinRectangle(*PolygonEdges,&(PolygonEdges[1]), &PolygonLeft,&PolygonTop,&PolygonRight,&PolygonBottom); for (i=0; i<*PolygonEdges; i++) { PolygonEdges[i*2+1]-=PolygonLeft; PolygonEdges[i*2+2]-=PolygonTop; } } HandleUnlock(PictureBoxGetBorderPolygon(PictureBox)); HandleUnlock(ItemGetHandle(InsertHBox)); } else if (TextBoxGetBoxType((TextBoxs *)Box)==TEXTBOX) { TextBox=HandleLock(ItemGetHandle(InsertHBox)); if (TextBox==NULL) return(OUTOFMEMORY); TextBoxInitialLineTable(TextBox); TextBoxSetInvalidPolygons(TextBox,0); if ((TextBoxGetTextLength((TextBoxs *)Box)>0)&& !TextBoxGetPrevLinkBox((TextBoxs *)Box)) { Wchar *TextBlock; ClipBoardGetDataInfomation(&ClipBoardDataInformation); if ((ClipBoardDataInformation.ClipBoardDataLength==0)|| (ClipBoardDataInformation.ClipBoardDataType!=TEXTDATA)) { TextBoxSetTextHandle(TextBox,0); TextBoxSetTextLength(TextBox,0); TextBoxSetBlockLength(TextBox,0); HandleUnlock(ItemGetHandle(InsertHBox)); return(OUTOFMEMORY); } TextBoxSetTextHandle(TextBox,HandleAlloc(TextBoxGetBlockLength(TextBox) *sizeof(Wchar),0)); if (!TextBoxGetTextHandle(TextBox)) { TextBoxSetTextLength(TextBox,0); TextBoxSetBlockLength(TextBox,0); HandleUnlock(ItemGetHandle(InsertHBox)); return(OUTOFMEMORY); } TextBlock=HandleLock(TextBoxGetTextHandle(TextBox)); ClipBoardGet(TextBlock,&ClipBoardDataInformation.ClipBoardDataLength, &ClipBoardDataInformation.ClipBoardDataType); TextBlock[TextBoxGetTextLength(TextBox)]=0; HandleUnlock(TextBoxGetTextHandle(TextBox)); } else { TextBoxSetTextHandle(TextBox,0); TextBoxSetTextLength(TextBox,0); TextBoxSetBlockLength(TextBox,0); } TextBoxSetPrevLinkBox(TextBox,0); TextBoxSetNextLinkBox(TextBox,0); InitRL(TextBox); FormatAll(InsertHBox); HandleUnlock(ItemGetHandle(InsertHBox)); } else if ((TextBoxGetBoxType((TextBoxs *)Box)>=RECTANGLEPICTUREBOX) &&(TextBoxGetBoxType((TextBoxs *)Box)<=POLYGONPICTUREBOX)) { PictureBox=HandleLock(ItemGetHandle(InsertHBox)); if (PictureBox==NULL) return(OUTOFMEMORY); if (PictureBoxGetPictureFileName(PictureBox)[0]) { ImageDescribes *TiffPresent; TiffPresent=&(PictureBoxGetPicturePresent(PictureBox)); TiffPresent->ImageHandle=TiffPresent->ImageNewHandle=0; PictureBoxImportTiff(PictureBoxGetPictureFileName(PictureBox), InsertHBox); } HandleUnlock(ItemGetHandle(InsertHBox)); } if (PasteSign==GETTOTEXTBOX) { ItemSetNext(ItemGetPrev(InsertHBox),0); ItemSetPrev(InsertHBox,0); ItemSetNext(InsertHBox,0); ItemSetFather(InsertHBox,0); TextBox=HandleLock(ItemGetHandle(InsertHBox)); if (TextBox==NULL) return(OUTOFMEMORY); TextBoxSetEmbodyBox(TextBox); HandleUnlock(ItemGetHandle(InsertHBox)); } return(InsertHBox); }