📄 gena_server.c
字号:
/////////////////////////////////////////////////////////////////////////////// Copyright (c) 2000 Intel Corporation// All rights reserved.//// Redistribution and use in source and binary forms, with or without// modification, are permitted provided that the following conditions are met://// * Redistributions of source code must retain the above copyright notice,// this list of conditions and the following disclaimer.// * Redistributions in binary form must reproduce the above copyright notice,// this list of conditions and the following disclaimer in the documentation// and/or other materials provided with the distribution.// * Neither name of Intel Corporation nor the names of its contributors// may be used to endorse or promote products derived from this software// without specific prior written permission.//// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.///////////////////////////////////////////////////////////////////////////////// $Revision: 1.1.1.4 $// $Date: 2001/06/15 00:22:15 $// #include "../../inc/tools/config.h"#if EXCLUDE_GENA == 0#include "../inc/gena/gena.h"#include <sys/utsname.h>DEVICEONLY(int genaUnregisterDevice(UpnpDevice_Handle device_handle){ struct Handle_Info * handle_info; HandleLock(); if (GetHandleInfo(device_handle, & handle_info)!=HND_DEVICE) { DBGONLY(UpnpPrintf(UPNP_CRITICAL,GENA,__FILE__,__LINE__,"genaUnregisterDevice : BAD Handle : %d\n", device_handle)); HandleUnlock(); return GENA_E_BAD_HANDLE; } freeServiceTable(&handle_info->ServiceTable); HandleUnlock(); return UPNP_E_SUCCESS;}//********************************************************//*Name: createURL_list//*Description: Function to parse//* the Callback header Value in subscription requests//* takes in a buffer containing URLS delimited by '<' and '>'//* The entire buffer is copied into dynamic memory//* and stored in the URL_list.//* Pointers to the individual urls within this buffer //* are allocated and stored in the URL_list.//* Only URLs with network addresses are considered //* (i.e. host:port or domain name)//* In: buffer *URLS //* Out: URL_list *out (storage space is passed in) , if successful, //* then structure should be//* deallocated at some time by : freeURL_list//* Return Codes: Returns the number of URLs parsed //* Error Codes: UPNP_E_OUTOF_MEMORY//* //********************************************************int createURL_list(token *URLS, URL_list *out){ int URLcount=0; int i; int return_code=0; uri_type temp; out->URLs=NULL; out->parsedURLs=NULL; for (i=0;i<URLS->size;i++) { if ( (URLS->buff[i]=='<') && (i+1<URLS->size)) { if ( ((return_code=parse_uri(&URLS->buff[i+1], URLS->size-i+1,&temp))==HTTP_SUCCESS) && (temp.hostport.text.size!=0) ) URLcount++; else if (return_code==UPNP_E_OUTOF_MEMORY) return return_code; } } out->URLs=(char *) malloc(URLS->size+1); out->parsedURLs=(uri_type *) malloc(sizeof(uri_type) * URLcount); if ( (out->URLs==NULL) || (out->parsedURLs==NULL)) return UPNP_E_OUTOF_MEMORY; memcpy(out->URLs,URLS->buff,URLS->size); out->URLs[URLS->size]=0; URLcount=0; for (i=0;i<URLS->size;i++) { if ( (URLS->buff[i]=='<') && (i+1<URLS->size)) { if ( ((return_code=parse_uri(&out->URLs[i+1],URLS->size-i+1, &out->parsedURLs[URLcount]))==HTTP_SUCCESS) && (out->parsedURLs[URLcount].hostport.text.size!=0) ) URLcount++; else if (return_code==UPNP_E_OUTOF_MEMORY) { free (out->URLs); free (out->parsedURLs); out->URLs=NULL; out->parsedURLs=NULL; return return_code; } } } out->size=URLcount; return URLcount;}//********************************************************//*Name: respondOK//*Description: Function to return OK message in the case of a subscription request.//*In: sockfd (socket connection of request)//* time_out (accepted duration)//* subscription * sub (accepted subscription)//*Out: returns error codes from respond or UPNP_E_OUTOF_MEMORY//********************************************************int respondOK(int sockfd,int time_out,subscription *sub){ char *temp; int size=0; int return_code; struct utsname sys_info; char server[128]; memset(&sys_info,0x00,sizeof(sys_info)); uname(&sys_info); size+= strlen(HTTP_OK); size+= HTTP_DATE_LENGTH; size+= sprintf( server, "SERVER: %s/%s UPnP/1.0 Intel UPnP SDK/1.0\r\n", sys_info.sysname, sys_info.release ); //strlen(SERVER_GENA); size+= strlen("SID: \r\n") + sizeof(Upnp_SID); size+= strlen("TIMEOUT: Second-\r\n\r\n") + MAX_SECONDS +1; temp = (char *) malloc(size); if (temp==NULL) { respond(sockfd,UNABLE_MEMORY); return UPNP_E_OUTOF_MEMORY; } strcpy(temp,HTTP_OK); currentTmToHttpDate(&temp[strlen(temp)]); strcat(temp,server); strcat(temp,"SID: "); strcat(temp,sub->sid); strcat(temp,"\r\n"); if (time_out>=0) sprintf(&temp[strlen(temp)],"TIMEOUT: Second-%d\r\n\r\n",time_out); else strcat(temp,"TIMEOUT: Second-infinite\r\n\r\n"); return_code=respond(sockfd,temp); free(temp); return return_code;}//********************************************************//*Name: GeneratePropertySet//*Description: Function to generate XML propery Set for Notifications//* Note: XML_VERSION comment is NOT sent due to interop issues with Microsoft ME//*In: char **names (each char* is null terminated), char ** values, int count //*Out: char ** out (dynamically allocated must be freed by caller)//********************************************************int GeneratePropertySet(char **names, char ** values, int count, char **out){ char *buffer; int counter=0; int size=0; int temp_counter =0; // size+=strlen(XML_VERSION); Microsoft Windows Millenium interoperability currently will not work with the XML_VERSION size+=strlen(XML_PROPERTYSET_HEADER); size+=strlen("</e:propertyset>\n\n"); for (temp_counter=0,counter=0;counter<count;counter++) { size+=strlen("<e:property>\n</e:property>\n"); size+= (2*strlen(names[counter])+strlen(values[counter])+(strlen("<></>\n"))); } buffer=(char*)malloc(size+1); if (buffer==NULL) { return UPNP_E_OUTOF_MEMORY; } memset(buffer,0,size+1); // strcpy(buffer,XML_VERSION); Microsoft Windows interoperability currently doesn't accept the XML_VERSION tag strcpy(buffer,XML_PROPERTYSET_HEADER); for (counter=0;counter<count;counter++) { strcat(buffer,"<e:property>\n"); sprintf(&buffer[strlen(buffer)],"<%s>%s</%s>\n</e:property>\n",names[counter],values[counter],names[counter]); } strcat(buffer,"</e:propertyset>\n\n"); (*out)=buffer; return XML_SUCCESS; }//********************************************************//* Name: free_notify_struct//* Description: frees memory used in notify_threads//* if the reference count is 0, actually frees the struct//* In: notify_thread_struct * input//* Out: None//* Return Codes: None//* Error Codes: None//********************************************************void free_notify_struct(notify_thread_struct * input){ (*input->reference_count)--; if ((*input->reference_count)==0) { free(input->headers); free(input->propertySet); free(input->servId); free(input->UDN); free(input->reference_count); } free(input);}//********************************************************//*Name: genaNotify//*Description: Function to Notify a particular subscription of a particular event//* In general the service should NOT be blocked around this call. (this may cause deadlock with a client)//* NOTIFY http request is sent and the reply is processed.//*In: char * headers (null terminated) (includes all headers (including \r\n) except SID and SEQ)//* char * propertySet (null terminated) XML//* subscription *sub (subscription to be Notified, Assumes this is valid for life of function)//*Out: //*Return Codes: GENA_SUCCESS if the event was delivered (all codes mapped to codes in upnp.h)//*Error Codes: UPNP_E_OUTOF_MEMORY//* HTTP_E_BAD_URL //* HTTP_E_READ_SOCKET //* HTTP_E_WRITE_SOCKET //* HTTP_E_CONNECT_SOCKET //* HTTP_E_SOCKET //* GENA_E_NOTIFY_UNACCEPTED//* HTTP_E_BAD_RESPONSE //* GENA_E_NOTIFY_UNACCEPTED_REMOVE (this subscription must be removed)//********************************************************int genaNotify(char * headers, char * propertySet, subscription *sub){ int full_size=0; char *full_message; http_message parsed_response; int i; int return_code=GENA_E_NOTIFY_UNACCEPTED; char * response; full_size=strlen(headers)+strlen("SID: \r\n") + SID_SIZE+ strlen("SEQ: \r\n\r\n") + MAX_EVENTS + strlen(propertySet)+1; full_message = (char *) malloc(full_size); if (full_message==NULL) return UPNP_E_OUTOF_MEMORY; sprintf(full_message,"%sSID: %s\r\nSEQ: %d\r\n\r\n%s",headers,sub->sid,sub->ToSendEventKey,propertySet); for (i=0;i<sub->DeliveryURLs.size;i++) { if (((return_code=transferHTTPparsedURL("NOTIFY", full_message, strlen(full_message)+1, &response, &sub->DeliveryURLs.parsedURLs[i]) )==HTTP_SUCCESS)) { break; } } free(full_message); if (return_code==HTTP_SUCCESS) { //only error I really care about is Invalid SID return_code=parse_http_response(response,&parsed_response, strlen(response)); if (return_code==HTTP_SUCCESS) { if (!strncasecmp(parsed_response.status.status_code.buff, "200", strlen("200"))) return_code=GENA_SUCCESS; else { if (!strncasecmp(parsed_response.status.status_code.buff, "412",strlen("412"))) { //Invalid SID gets removed return_code=GENA_E_NOTIFY_UNACCEPTED_REMOVE_SUB; } else return_code=GENA_E_NOTIFY_UNACCEPTED; } free_http_message(&parsed_response); } free (response); return return_code; } return return_code; }void genaNotifyThread(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; 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)) ==NULL) || (!service->active) || ( (sub=GetSubscriptionSID(in->sid,service))==NULL) || ( (copy_subscription(sub,&sub_copy)!=HTTP_SUCCESS)) ) { free_notify_struct(in); HandleUnlock(); return; } if (in->eventKey!=sub->ToSendEventKey) { tpool_Schedule( genaNotifyThread, input); freeSubscription(&sub_copy); HandleUnlock(); return; } HandleUnlock(); //transmit 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)) ==NULL) || (!service->active) || ( (sub=GetSubscriptionSID(in->sid,service))==NULL) ) { 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();}int genaInitNotify(UpnpDevice_Handle device_handle, char *UDN, char *servId, char **VarNames, char **VarValues, int var_count, Upnp_SID sid){ char * UDN_copy=NULL; char * servId_copy=NULL; char * propertySet=NULL; char * headers=NULL; subscription * sub=NULL; service_info *service=NULL; int return_code=GENA_SUCCESS; int headers_size; int *reference_count=NULL; struct Handle_Info * handle_info; notify_thread_struct *thread_struct=NULL; DBGONLY(UpnpPrintf(UPNP_INFO,GENA,__FILE__,__LINE__,"GENA BEGIN INITIAL NOTIFY ")); reference_count= (int *) malloc(sizeof(int)); if (reference_count==NULL) return UPNP_E_OUTOF_MEMORY; (*reference_count)=0; UDN_copy=(char *) malloc(strlen(UDN)+1); if (UDN_copy==NULL) { free(reference_count); return UPNP_E_OUTOF_MEMORY; } servId_copy=(char *) malloc(strlen(servId)+1); if (servId_copy==NULL) { free(UDN_copy); free(reference_count);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -