Workaround for Samsung Smart TV 2012 :
- URI patch made by swiergot http://sourceforge.net/tracker/index.php?func=detail&aid=3532724&group_id=129766&atid=715782
- per device content-type engine : change video/x-matroska with video/x-mkv for Samsung devices only
--- a/tombupnp/upnp/src/genlib/miniserver/miniserver.c
+++ b/tombupnp/upnp/src/genlib/miniserver/miniserver.c
@@ -842,6 +842,8 @@
return UPNP_E_INTERNAL_ERROR; // miniserver running
}
+ ssdpdevices_init(&GlobalSsdpDevices);
+
miniSocket =
( MiniServerSockArray * ) malloc( sizeof( MiniServerSockArray ) );
if( miniSocket == NULL )
@@ -963,5 +965,8 @@
}
shutdown( sock, SD_BOTH );
UpnpCloseSocket( sock );
+
+ ssdpdevices_destroy(&GlobalSsdpDevices);
+
return 0;
}
--- a/tombupnp/upnp/src/genlib/net/http/webserver.c
+++ b/tombupnp/upnp/src/genlib/net/http/webserver.c
@@ -1211,6 +1211,7 @@
*
* Parameters:
* IN http_message_t *req ; HTTP Request message
+* IN SOCKINFO *info ; Socket info (fd with remote ip & port)
* OUT enum resp_type *rtype ; Tpye of response
* OUT membuffer *headers ;
* OUT membuffer *filename ; Get filename from request document
@@ -1230,6 +1231,7 @@
************************************************************************/
static int
process_request( IN http_message_t * req,
+ IN SOCKINFO *info,
OUT enum resp_type *rtype,
OUT membuffer * headers,
OUT membuffer * filename,
@@ -1473,6 +1475,19 @@
goto error_handler;
}
+ // change "x-matroska" by "x-mkv", for samsung devices only
+ char *newtype;
+ if((strcmp(finfo.content_type, "video/x-matroska")==0)) {
+ if(ssdpdevice_servermatch(&GlobalSsdpDevices, info->foreign_ip_addr.s_addr, "samsung")) {
+// printf("Req from Samsung device : %s\n", finfo.content_type);
+ // change is made in two steps : free the previous string, malloc a new one
+ if((newtype= (char *) strdup("video/x-mkv"))) {
+ free(finfo.content_type);
+ finfo.content_type = newtype;
+ }
+ }
+ }
+
if( RespInstr->IsRangeActive && RespInstr->IsChunkActive ) {
//Content-Range: bytes 222-3333/4000 HTTP_PARTIAL_CONTENT
//Transfer-Encoding: chunked
@@ -1800,7 +1815,7 @@
//Process request should create the different kind of header depending on the
//the type of request.
ret =
- process_request( req, &rtype, &headers, &filename, &xmldoc,
+ process_request( req, info, &rtype, &headers, &filename, &xmldoc,
&RespInstr, &Fp);
if( ret != UPNP_E_SUCCESS ) {
// send error code
--- a/tombupnp/upnp/src/genlib/net/uri/uri.c
+++ b/tombupnp/upnp/src/genlib/net/uri/uri.c
@@ -1042,7 +1042,8 @@
out->path_type = REL_PATH;
}
- if( ( ( begin_hostport + 1 ) < max ) && ( in[begin_hostport] == '/' )
+ //parse hostport only if scheme was found
+ if( ( begin_hostport > 0 ) && ( ( begin_hostport + 1 ) < max ) && ( in[begin_hostport] == '/' )
&& ( in[begin_hostport + 1] == '/' ) ) {
begin_hostport += 2;
@@ -1059,6 +1060,12 @@
out->hostport.text.size = 0;
out->hostport.text.buff = 0;
begin_path = begin_hostport;
+
+ //remove excessive leading slashes (fix for Samsung Smart TV 2012)
+ while( ( ( begin_path + 1 ) < max ) && ( in[begin_path] == '/' ) && ( in[begin_path + 1] == '/') ) {
+ begin_path++;
+ }
+
}
begin_fragment =
--- a/tombupnp/upnp/src/inc/ssdplib.h
+++ b/tombupnp/upnp/src/inc/ssdplib.h
@@ -161,9 +161,22 @@
struct sockaddr_in dest_addr;
} ssdp_thread_data;
+typedef struct
+{
+ ithread_mutex_t mutex;
+ LinkedList deviceslist;
+} ssdpdevices_t;
+
+typedef struct
+{
+ uint32_t s_addr;
+ char *serverdesc;
+} ssdp_device_t;
/* globals */
+extern ssdpdevices_t GlobalSsdpDevices;
+
CLIENTONLY(extern SOCKET gSsdpReqSocket;);
typedef int (*ParserFun)(char *, Event *);
@@ -174,6 +187,64 @@
//int AnalyzeCommand(char * szCommand, Event * Evt);
/************************************************************************
+* Function : ssdpdevices_free
+*
+* Parameters :
+* void *d ;
+*
+* Description : Free memory allocated for each SSDP Device
+*
+* Return : void ;
+*
+* Note :
+************************************************************************/
+void ssdpdevice_free( void *d );
+
+/************************************************************************
+* Function : ssdpdevice_compare
+*
+* Parameters :
+* void* param1 ;
+* void* param2 ;
+*
+* Description : Compare two SSDP devices by their ip address
+*
+* Return : int ;
+*
+* Note :
+************************************************************************/
+int ssdpdevice_compare( void *param1, void *param2 );
+
+/************************************************************************
+* Function : ssdpdevices_init
+*
+* Parameters :
+* INOUT ssdpdevices_t* s ; Array of SSDP Devices
+*
+* Description : Initialize and allocate memory for the array of SSDP devices
+*
+* Return : void ;
+*
+* Note :
+************************************************************************/
+
+void ssdpdevices_init(ssdpdevices_t* s);
+
+/************************************************************************
+* Function : ssdpdevices_destroy
+*
+* Parameters :
+* INOUT ssdpdevices_t* msg ; Array of SSDP Devices
+*
+* Description : Free memory allocated for the Array of SSDP Devices
+*
+* Return : void ;
+*
+* Note :
+************************************************************************/
+void ssdpdevices_destroy( ssdpdevices_t *s );
+
+/************************************************************************
* Function : Make_Socket_NoBlocking
*
* Parameters:
--- a/tombupnp/upnp/src/ssdp/ssdp_server.c
+++ b/tombupnp/upnp/src/ssdp/ssdp_server.c
@@ -52,8 +52,231 @@
#include "unixutil.h"
#endif
+#include <regex.h>
+
#define MAX_TIME_TOREAD 45
+// global containing the array of devices
+ssdpdevices_t GlobalSsdpDevices;
+
+/************************************************************************
+* Function : ssdpdevices_free
+*
+* Parameters :
+* void *msg ;
+*
+* Description : Free memory allocated for each SSDP Device
+*
+* Return : void ;
+*
+* Note :
+************************************************************************/
+void
+ssdpdevice_free( void *d )
+{
+ ssdp_device_t *sd = ( ssdp_device_t * ) d;
+
+ free(sd->serverdesc);
+
+ free( sd );
+}
+
+/************************************************************************
+* Function : ssdpdevice_compare
+*
+* Parameters :
+* void* param1 ;
+* void* param2 ;
+*
+* Description : Compare two SSDP devices by their ip address
+*
+* Return : int ;
+*
+* Note :
+************************************************************************/
+int
+ssdpdevice_compare( void *param1,
+ void *param2 )
+{
+ assert( param1 != NULL );
+ assert( param2 != NULL );
+
+ return ( ( ssdp_device_t * ) param1 )->s_addr ==
+ ( ( ssdp_device_t * ) param2 )->s_addr;
+}
+
+/************************************************************************
+* Function : ssdpdevices_init
+*
+* Parameters :
+* INOUT ssdpdevices_t* s ; Array of SSDP Devices
+*
+* Description : Initialize and allocate memory for the array of SSDP devices
+*
+* Return : void ;
+*
+* Note :
+************************************************************************/
+
+void ssdpdevices_init(ssdpdevices_t* s) {
+ ithread_mutex_init( &s->mutex, NULL );
+ ListInit( &s->deviceslist, ssdpdevice_compare, ssdpdevice_free );
+}
+
+/************************************************************************
+* Function : ssdpdevices_destroy
+*
+* Parameters :
+* INOUT ssdpdevices_t* s ; Array of SSDP Devices
+*
+* Description : Free memory allocated for the Array of SSDP Devices
+*
+* Return : void ;
+*
+* Note :
+************************************************************************/
+void
+ssdpdevices_destroy( ssdpdevices_t *s )
+{
+ int ret;
+
+ assert( s != NULL );
+
+ ithread_mutex_lock( &s->mutex );
+ ListDestroy( &s->deviceslist, 1 );
+ ithread_mutex_unlock( &s->mutex );
+
+ ret = ithread_mutex_destroy( &s->mutex );
+ assert( ret == 0 );
+
+}
+
+/************************************************************************
+* Function : create_device_node
+*
+* Parameters :
+* IN uint32_t *ip4addr; IP Address
+* IN membuffer *mbuf; Server descripton
+*
+* Description : Create a device structure and fill it with ip & description
+*
+* Return : ssdp_device_t *
+*
+* Note :
+************************************************************************/
+
+ssdp_device_t *create_device(uint32_t ipaddr, membuffer *mbuf) {
+ ssdp_device_t *newd;
+ if( (newd = (ssdp_device_t *) malloc(sizeof(ssdp_device_t)))) {
+ if( ( newd->serverdesc = str_alloc ( mbuf->buf, mbuf->length) ) ) {
+ newd->s_addr = ipaddr;
+ return(newd);
+ }
+ free(newd);
+ }
+ return(NULL);
+}
+
+
+/************************************************************************
+* Function : ssdpdevices_updatelist
+*
+* Parameters :
+* INOUT ssdpdevices_t* s ; Array of SSDP Devices
+* IN uint32_t *ip4addr; IP Address
+* IN char *serverstr; Server descripton
+*
+* Description : Insert or update the list with given device
+*
+* Return : void ;
+*
+* Note :
+************************************************************************/
+void
+ssdpdevices_updatelist( ssdpdevices_t *s, uint32_t ip4addr, membuffer *serverstr)
+{
+ assert( s != NULL );
+ assert( ip4addr != 0 );
+ assert( serverstr != NULL );
+
+ int found = 0;
+
+ // Loop through each existing device
+ ithread_mutex_lock( &s->mutex );
+ LinkedList *l = &s->deviceslist;
+ ListNode *temp = NULL;
+ ssdp_device_t *d,*newd;
+ for (temp = ListHead(l);temp!=NULL;temp = ListNext(l,temp))
+ {
+ d=(ssdp_device_t *)temp->item;
+ if(d->s_addr == ip4addr) {
+ found = 1;
+ break;
+ }
+ }
+
+ // Add the entry if necessary
+ if(!found) {
+ if( ( newd = create_device(ip4addr, serverstr))) {
+ ListAddTail( l, newd);
+ }
+ }
+ ithread_mutex_unlock( &s->mutex );
+
+}
+
+/************************************************************************
+* Function : ssdpdevice_descmatch
+*
+* Parameters :
+* IN ssdpdevices_t* s ; Array of SSDP Devices
+* IN uint32_t ipaddr; Ip addres to check
+* IN char *regexp; Regex to match
+*
+* Description : Check whether the device's description matches the given regex
+*
+* Return : int (1 = match, else no match)
+*
+* Note :
+************************************************************************/
+int
+ssdpdevice_servermatch( ssdpdevices_t *s, uint32_t ip4addr, char *regex)
+{
+ assert( s != NULL );
+ assert( ip4addr != 0 );
+ assert( regex != NULL );
+
+ int ret = 0;
+ regex_t reg;
+
+ if( regcomp(®, regex, REG_EXTENDED | REG_NOSUB | REG_ICASE) != 0) {
+ printf("Invalid regex : %s\n", regex);
+ return(0);
+ }
+
+ // Loop through each existing device
+ ithread_mutex_lock( &s->mutex );
+ LinkedList *l = &s->deviceslist;
+ ListNode *temp = NULL;
+ ssdp_device_t *d;
+ for (temp = ListHead(l);temp!=NULL;temp = ListNext(l,temp))
+ {
+ d=(ssdp_device_t *)temp->item;
+ if(d->s_addr == ip4addr) {
+ // We found the ip addr, let's check if the desc contains the searched string
+ if(regexec(®, d->serverdesc, 0, NULL, 0) == 0) {
+ ret=1;
+ }
+ break;
+ }
+ }
+
+ ithread_mutex_unlock( &s->mutex );
+ return(ret);
+}
+
+
+
CLIENTONLY( SOCKET gSsdpReqSocket = 0;
)
@@ -756,6 +979,24 @@
if( !valid_ssdp_msg( &parser->msg ) ) {
goto error_handler;
}
+
+ // update liste of devices for each NOTIFY received
+
+ if ( parser->msg.method == HTTPMETHOD_NOTIFY ) {
+// printf( "SSDP recvd code NOTIFY = %d from %s\n", parser->msg.method, inet_ntoa(data->dest_addr.sin_addr));
+ LinkedList *g=&parser->msg.headers;
+ ListNode *temp = NULL;
+ http_header_t *h;
+ for (temp = ListHead(g);temp!=NULL;temp = ListNext(g,temp))
+ {
+ h=(http_header_t *)temp->item;
+ if(strncasecmp(h->name.buf, "SERVER", h->name.length) == 0) {
+ ssdpdevices_updatelist(&GlobalSsdpDevices, data->dest_addr.sin_addr.s_addr, &h->value);
+ }
+ }
+
+ }
+
return 0; //////// done; thread will free 'data'
error_handler:
|