ssdp, soap, genlib: fix compiler warnings.
This commit is contained in:
parent
594c611a33
commit
c449fd1521
@ -117,7 +117,7 @@ static int sock_read_write(
|
|||||||
fd_set readSet;
|
fd_set readSet;
|
||||||
fd_set writeSet;
|
fd_set writeSet;
|
||||||
struct timeval timeout;
|
struct timeval timeout;
|
||||||
int numBytes;
|
long numBytes;
|
||||||
time_t start_time = time(NULL);
|
time_t start_time = time(NULL);
|
||||||
SOCKET sockfd = info->socket;
|
SOCKET sockfd = info->socket;
|
||||||
long bytes_sent = 0, byte_left = 0, num_written;
|
long bytes_sent = 0, byte_left = 0, num_written;
|
||||||
@ -164,7 +164,7 @@ static int sock_read_write(
|
|||||||
#endif
|
#endif
|
||||||
if (bRead) {
|
if (bRead) {
|
||||||
/* read data. */
|
/* read data. */
|
||||||
numBytes = recv(sockfd, buffer, bufsize, MSG_NOSIGNAL);
|
numBytes = (long)recv(sockfd, buffer, bufsize, MSG_NOSIGNAL);
|
||||||
} else {
|
} else {
|
||||||
byte_left = bufsize;
|
byte_left = bufsize;
|
||||||
bytes_sent = 0;
|
bytes_sent = 0;
|
||||||
|
@ -718,164 +718,119 @@ getSubElement( const char *element_name,
|
|||||||
*
|
*
|
||||||
* Note :
|
* Note :
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
service_info *
|
service_info *getServiceList(
|
||||||
getServiceList( IXML_Node * node,
|
IXML_Node *node,
|
||||||
service_info ** end,
|
service_info **end,
|
||||||
char *URLBase )
|
char *URLBase)
|
||||||
{
|
{
|
||||||
IXML_Node *serviceList = NULL;
|
IXML_Node *serviceList = NULL;
|
||||||
IXML_Node *current_service = NULL;
|
IXML_Node *current_service = NULL;
|
||||||
IXML_Node *UDN = NULL;
|
IXML_Node *UDN = NULL;
|
||||||
|
|
||||||
IXML_Node *serviceType = NULL;
|
IXML_Node *serviceType = NULL;
|
||||||
IXML_Node *serviceId = NULL;
|
IXML_Node *serviceId = NULL;
|
||||||
IXML_Node *SCPDURL = NULL;
|
IXML_Node *SCPDURL = NULL;
|
||||||
IXML_Node *controlURL = NULL;
|
IXML_Node *controlURL = NULL;
|
||||||
IXML_Node *eventURL = NULL;
|
IXML_Node *eventURL = NULL;
|
||||||
DOMString tempDOMString = NULL;
|
DOMString tempDOMString = NULL;
|
||||||
service_info *head = NULL;
|
service_info *head = NULL;
|
||||||
service_info *current = NULL;
|
service_info *current = NULL;
|
||||||
service_info *previous = NULL;
|
service_info *previous = NULL;
|
||||||
IXML_NodeList *serviceNodeList = NULL;
|
IXML_NodeList *serviceNodeList = NULL;
|
||||||
int NumOfServices = 0;
|
long unsigned int NumOfServices = 0;
|
||||||
int i = 0;
|
long unsigned int i = 0;
|
||||||
int fail = 0;
|
int fail = 0;
|
||||||
|
|
||||||
if( getSubElement( "UDN", node, &UDN ) &&
|
|
||||||
getSubElement( "serviceList", node, &serviceList ) ) {
|
|
||||||
|
|
||||||
serviceNodeList = ixmlElement_getElementsByTagName( ( IXML_Element
|
|
||||||
* )
|
|
||||||
serviceList,
|
|
||||||
"service" );
|
|
||||||
|
|
||||||
if( serviceNodeList != NULL ) {
|
|
||||||
NumOfServices = ixmlNodeList_length( serviceNodeList );
|
|
||||||
for( i = 0; i < NumOfServices; i++ ) {
|
|
||||||
current_service = ixmlNodeList_item( serviceNodeList, i );
|
|
||||||
fail = 0;
|
|
||||||
|
|
||||||
if( current ) {
|
|
||||||
current->next =
|
|
||||||
( service_info * )
|
|
||||||
malloc( sizeof( service_info ) );
|
|
||||||
|
|
||||||
previous = current;
|
|
||||||
current = current->next;
|
|
||||||
} else {
|
|
||||||
head =
|
|
||||||
( service_info * )
|
|
||||||
malloc( sizeof( service_info ) );
|
|
||||||
current = head;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( !current ) {
|
|
||||||
freeServiceList( head );
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
current->next = NULL;
|
|
||||||
current->controlURL = NULL;
|
|
||||||
current->eventURL = NULL;
|
|
||||||
current->serviceType = NULL;
|
|
||||||
current->serviceId = NULL;
|
|
||||||
current->SCPDURL = NULL;
|
|
||||||
current->active = 1;
|
|
||||||
current->subscriptionList = NULL;
|
|
||||||
current->TotalSubscriptions = 0;
|
|
||||||
|
|
||||||
if( !( current->UDN = getElementValue( UDN ) ) )
|
|
||||||
fail = 1;
|
|
||||||
|
|
||||||
if( ( !getSubElement( "serviceType", current_service,
|
|
||||||
&serviceType ) ) ||
|
|
||||||
( !( current->serviceType =
|
|
||||||
getElementValue( serviceType ) ) ) )
|
|
||||||
fail = 1;
|
|
||||||
|
|
||||||
if( ( !getSubElement( "serviceId", current_service,
|
|
||||||
&serviceId ) ) ||
|
|
||||||
( !
|
|
||||||
( current->serviceId =
|
|
||||||
getElementValue( serviceId ) ) ) )
|
|
||||||
fail = 1;
|
|
||||||
|
|
||||||
if( ( !
|
|
||||||
( getSubElement
|
|
||||||
( "SCPDURL", current_service, &SCPDURL ) ) )
|
|
||||||
|| ( !( tempDOMString = getElementValue( SCPDURL ) ) )
|
|
||||||
||
|
|
||||||
( !
|
|
||||||
( current->SCPDURL =
|
|
||||||
resolve_rel_url( URLBase, tempDOMString ) ) ) )
|
|
||||||
fail = 1;
|
|
||||||
|
|
||||||
ixmlFreeDOMString( tempDOMString );
|
|
||||||
tempDOMString = NULL;
|
|
||||||
|
|
||||||
if( ( !
|
|
||||||
( getSubElement
|
|
||||||
( "controlURL", current_service, &controlURL ) ) )
|
|
||||||
||
|
|
||||||
( !( tempDOMString = getElementValue( controlURL ) ) )
|
|
||||||
||
|
|
||||||
( !
|
|
||||||
( current->controlURL =
|
|
||||||
resolve_rel_url( URLBase, tempDOMString ) ) ) ) {
|
|
||||||
UpnpPrintf( UPNP_INFO, GENA, __FILE__, __LINE__,
|
|
||||||
"BAD OR MISSING CONTROL URL" );
|
|
||||||
UpnpPrintf( UPNP_INFO, GENA, __FILE__, __LINE__,
|
|
||||||
"CONTROL URL SET TO NULL IN SERVICE INFO" );
|
|
||||||
current->controlURL = NULL;
|
|
||||||
fail = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ixmlFreeDOMString( tempDOMString );
|
|
||||||
tempDOMString = NULL;
|
|
||||||
|
|
||||||
if( ( !
|
|
||||||
( getSubElement
|
|
||||||
( "eventSubURL", current_service, &eventURL ) ) )
|
|
||||||
|| ( !( tempDOMString = getElementValue( eventURL ) ) )
|
|
||||||
||
|
|
||||||
( !
|
|
||||||
( current->eventURL =
|
|
||||||
resolve_rel_url( URLBase, tempDOMString ) ) ) ) {
|
|
||||||
UpnpPrintf( UPNP_INFO, GENA, __FILE__, __LINE__,
|
|
||||||
"BAD OR MISSING EVENT URL" );
|
|
||||||
UpnpPrintf( UPNP_INFO, GENA, __FILE__, __LINE__,
|
|
||||||
"EVENT URL SET TO NULL IN SERVICE INFO" );
|
|
||||||
current->eventURL = NULL;
|
|
||||||
fail = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ixmlFreeDOMString( tempDOMString );
|
|
||||||
tempDOMString = NULL;
|
|
||||||
|
|
||||||
if( fail ) {
|
|
||||||
freeServiceList( current );
|
|
||||||
|
|
||||||
if( previous )
|
|
||||||
previous->next = NULL;
|
|
||||||
else
|
|
||||||
head = NULL;
|
|
||||||
|
|
||||||
current = previous;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
ixmlNodeList_free( serviceNodeList );
|
|
||||||
}
|
|
||||||
|
|
||||||
( *end ) = current;
|
|
||||||
|
|
||||||
return head;
|
|
||||||
} else {
|
|
||||||
( *end ) = NULL;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (getSubElement("UDN", node, &UDN) &&
|
||||||
|
getSubElement("serviceList", node, &serviceList)) {
|
||||||
|
serviceNodeList = ixmlElement_getElementsByTagName(
|
||||||
|
(IXML_Element *)serviceList, "service");
|
||||||
|
if (serviceNodeList != NULL) {
|
||||||
|
NumOfServices = ixmlNodeList_length(serviceNodeList);
|
||||||
|
for (i = 0; i < NumOfServices; i++) {
|
||||||
|
current_service =
|
||||||
|
ixmlNodeList_item(serviceNodeList, i);
|
||||||
|
fail = 0;
|
||||||
|
if (current) {
|
||||||
|
current->next = malloc(sizeof(service_info));
|
||||||
|
previous = current;
|
||||||
|
current = current->next;
|
||||||
|
} else {
|
||||||
|
head = malloc(sizeof(service_info));
|
||||||
|
current = head;
|
||||||
|
}
|
||||||
|
if (!current) {
|
||||||
|
freeServiceList(head);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
current->next = NULL;
|
||||||
|
current->controlURL = NULL;
|
||||||
|
current->eventURL = NULL;
|
||||||
|
current->serviceType = NULL;
|
||||||
|
current->serviceId = NULL;
|
||||||
|
current->SCPDURL = NULL;
|
||||||
|
current->active = 1;
|
||||||
|
current->subscriptionList = NULL;
|
||||||
|
current->TotalSubscriptions = 0;
|
||||||
|
if (!(current->UDN = getElementValue(UDN)))
|
||||||
|
fail = 1;
|
||||||
|
if (!getSubElement("serviceType", current_service, &serviceType) ||
|
||||||
|
!(current->serviceType = getElementValue(serviceType)))
|
||||||
|
fail = 1;
|
||||||
|
if (!getSubElement("serviceId", current_service, &serviceId) ||
|
||||||
|
!(current->serviceId = getElementValue(serviceId)))
|
||||||
|
fail = 1;
|
||||||
|
if (!getSubElement("SCPDURL", current_service, &SCPDURL) ||
|
||||||
|
!(tempDOMString = getElementValue(SCPDURL)) ||
|
||||||
|
!(current->SCPDURL = resolve_rel_url(URLBase, tempDOMString)))
|
||||||
|
fail = 1;
|
||||||
|
ixmlFreeDOMString(tempDOMString);
|
||||||
|
tempDOMString = NULL;
|
||||||
|
if (!(getSubElement("controlURL", current_service, &controlURL)) ||
|
||||||
|
!(tempDOMString = getElementValue(controlURL)) ||
|
||||||
|
!(current->controlURL = resolve_rel_url(URLBase, tempDOMString))) {
|
||||||
|
UpnpPrintf(UPNP_INFO, GENA, __FILE__,
|
||||||
|
__LINE__,
|
||||||
|
"BAD OR MISSING CONTROL URL");
|
||||||
|
UpnpPrintf(UPNP_INFO, GENA, __FILE__,
|
||||||
|
__LINE__,
|
||||||
|
"CONTROL URL SET TO NULL IN SERVICE INFO");
|
||||||
|
current->controlURL = NULL;
|
||||||
|
fail = 0;
|
||||||
|
}
|
||||||
|
ixmlFreeDOMString(tempDOMString);
|
||||||
|
tempDOMString = NULL;
|
||||||
|
if (!getSubElement("eventSubURL", current_service, &eventURL) ||
|
||||||
|
!(tempDOMString = getElementValue(eventURL)) ||
|
||||||
|
!(current->eventURL = resolve_rel_url(URLBase, tempDOMString))) {
|
||||||
|
UpnpPrintf(UPNP_INFO, GENA, __FILE__,
|
||||||
|
__LINE__,
|
||||||
|
"BAD OR MISSING EVENT URL");
|
||||||
|
UpnpPrintf(UPNP_INFO, GENA, __FILE__,
|
||||||
|
__LINE__,
|
||||||
|
"EVENT URL SET TO NULL IN SERVICE INFO");
|
||||||
|
current->eventURL = NULL;
|
||||||
|
fail = 0;
|
||||||
|
}
|
||||||
|
ixmlFreeDOMString(tempDOMString);
|
||||||
|
tempDOMString = NULL;
|
||||||
|
if (fail) {
|
||||||
|
freeServiceList(current);
|
||||||
|
if (previous)
|
||||||
|
previous->next = NULL;
|
||||||
|
else
|
||||||
|
head = NULL;
|
||||||
|
current = previous;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ixmlNodeList_free(serviceNodeList);
|
||||||
|
}
|
||||||
|
(*end) = current;
|
||||||
|
return head;
|
||||||
|
} else {
|
||||||
|
(*end) = NULL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
@ -899,39 +854,37 @@ getAllServiceList( IXML_Node * node,
|
|||||||
char *URLBase,
|
char *URLBase,
|
||||||
service_info ** out_end )
|
service_info ** out_end )
|
||||||
{
|
{
|
||||||
service_info *head = NULL;
|
service_info *head = NULL;
|
||||||
service_info *end = NULL;
|
service_info *end = NULL;
|
||||||
service_info *next_end = NULL;
|
service_info *next_end = NULL;
|
||||||
IXML_NodeList *deviceList = NULL;
|
IXML_NodeList *deviceList = NULL;
|
||||||
IXML_Node *currentDevice = NULL;
|
IXML_Node *currentDevice = NULL;
|
||||||
|
|
||||||
int NumOfDevices = 0;
|
long unsigned int NumOfDevices = 0;
|
||||||
int i = 0;
|
long unsigned int i = 0;
|
||||||
|
|
||||||
( *out_end ) = NULL;
|
(*out_end) = NULL;
|
||||||
|
|
||||||
deviceList =
|
deviceList = ixmlElement_getElementsByTagName(
|
||||||
ixmlElement_getElementsByTagName( ( IXML_Element * ) node,
|
(IXML_Element *)node, "device");
|
||||||
"device" );
|
if (deviceList) {
|
||||||
if( deviceList != NULL ) {
|
NumOfDevices = ixmlNodeList_length(deviceList);
|
||||||
NumOfDevices = ixmlNodeList_length( deviceList );
|
for (i = 0; i < NumOfDevices; i++) {
|
||||||
for( i = 0; i < NumOfDevices; i++ ) {
|
currentDevice = ixmlNodeList_item(deviceList, i);
|
||||||
currentDevice = ixmlNodeList_item( deviceList, i );
|
if (head) {
|
||||||
if( head ) {
|
end->next = getServiceList(currentDevice,
|
||||||
end->next =
|
&next_end, URLBase);
|
||||||
getServiceList( currentDevice, &next_end, URLBase );
|
if (next_end)
|
||||||
if ( next_end )
|
end = next_end;
|
||||||
end = next_end;
|
} else
|
||||||
} else
|
head = getServiceList(currentDevice, &end,
|
||||||
head = getServiceList( currentDevice, &end, URLBase );
|
URLBase);
|
||||||
|
}
|
||||||
|
ixmlNodeList_free(deviceList);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
(*out_end) = end;
|
||||||
|
return head;
|
||||||
ixmlNodeList_free( deviceList );
|
|
||||||
}
|
|
||||||
|
|
||||||
( *out_end ) = end;
|
|
||||||
return head;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
@ -963,8 +916,8 @@ removeServiceTable( IXML_Node * node,
|
|||||||
service_info *current_service = NULL;
|
service_info *current_service = NULL;
|
||||||
service_info *start_search = NULL;
|
service_info *start_search = NULL;
|
||||||
service_info *prev_service = NULL;
|
service_info *prev_service = NULL;
|
||||||
int NumOfDevices = 0;
|
long unsigned int NumOfDevices = 0;
|
||||||
int i = 0;
|
long unsigned int i = 0;
|
||||||
|
|
||||||
if( getSubElement( "root", node, &root ) ) {
|
if( getSubElement( "root", node, &root ) ) {
|
||||||
current_service = in->serviceList;
|
current_service = in->serviceList;
|
||||||
|
@ -311,33 +311,31 @@ membuffer_destroy( INOUT membuffer * m )
|
|||||||
*
|
*
|
||||||
* Note :
|
* Note :
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
int
|
int membuffer_assign( INOUT membuffer * m,
|
||||||
membuffer_assign( INOUT membuffer * m,
|
|
||||||
IN const void *buf,
|
IN const void *buf,
|
||||||
IN size_t buf_len )
|
IN size_t buf_len )
|
||||||
{
|
{
|
||||||
int return_code;
|
int return_code;
|
||||||
|
|
||||||
assert( m != NULL );
|
assert(m != NULL);
|
||||||
|
|
||||||
/* set value to null */
|
/* set value to null */
|
||||||
if( buf == NULL ) {
|
if (buf == NULL) {
|
||||||
membuffer_destroy( m );
|
membuffer_destroy(m);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* alloc mem */
|
/* alloc mem */
|
||||||
return_code = membuffer_set_size( m, buf_len );
|
return_code = membuffer_set_size(m, buf_len);
|
||||||
if( return_code != 0 ) {
|
if (return_code != 0)
|
||||||
return return_code;
|
return return_code;
|
||||||
}
|
/* copy */
|
||||||
/* copy */
|
if (buf_len) {
|
||||||
if( buf_len ) {
|
memcpy(m->buf, buf, buf_len);
|
||||||
memcpy( m->buf, buf, buf_len );
|
m->buf[buf_len] = 0; /* null-terminate */
|
||||||
m->buf[buf_len] = 0; /* null-terminate */
|
}
|
||||||
}
|
m->length = buf_len;
|
||||||
m->length = buf_len;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
@ -411,61 +409,37 @@ membuffer_append_str( INOUT membuffer * m,
|
|||||||
return membuffer_insert( m, c_str, strlen( c_str ), m->length );
|
return membuffer_insert( m, c_str, strlen( c_str ), m->length );
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************
|
int membuffer_insert(membuffer *m, const void *buf, size_t buf_len, size_t index)
|
||||||
* Function : membuffer_insert
|
|
||||||
*
|
|
||||||
* Parameters :
|
|
||||||
* INOUT membuffer* m ; buffer whose memory size is to be increased
|
|
||||||
* and appended.
|
|
||||||
* IN const void* buf ; source buffer whose contents will be
|
|
||||||
* copied
|
|
||||||
* IN size_t buf_len ; size of the source buffer
|
|
||||||
* int index ; index to determine the bounds while movinf the data
|
|
||||||
*
|
|
||||||
* Description : Allocates memory for the new data to be inserted. Does
|
|
||||||
* memory management by moving the data from the existing memory to
|
|
||||||
* the newly allocated memory and then appending the new data.
|
|
||||||
*
|
|
||||||
* Return : int ;
|
|
||||||
*
|
|
||||||
* Note :
|
|
||||||
************************************************************************/
|
|
||||||
int
|
|
||||||
membuffer_insert( INOUT membuffer * m,
|
|
||||||
IN const void *buf,
|
|
||||||
IN size_t buf_len,
|
|
||||||
int index )
|
|
||||||
{
|
{
|
||||||
int return_code;
|
int return_code;
|
||||||
|
|
||||||
assert( m != NULL );
|
assert(m != NULL);
|
||||||
|
|
||||||
if( index < 0 || index > ( int )m->length )
|
if (index > m->length)
|
||||||
return UPNP_E_OUTOF_BOUNDS;
|
return UPNP_E_OUTOF_BOUNDS;
|
||||||
|
if (!buf || !buf_len) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* alloc mem */
|
||||||
|
return_code = membuffer_set_size(m, m->length + buf_len);
|
||||||
|
if (return_code) {
|
||||||
|
return return_code;
|
||||||
|
}
|
||||||
|
/* insert data */
|
||||||
|
/* move data to right of insertion point */
|
||||||
|
memmove(m->buf + index + buf_len, m->buf + index, m->length - index);
|
||||||
|
memcpy(m->buf + index, buf, buf_len);
|
||||||
|
m->length += buf_len;
|
||||||
|
/* null-terminate */
|
||||||
|
m->buf[m->length] = 0;
|
||||||
|
|
||||||
if( buf == NULL || buf_len == 0 ) {
|
return 0;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/* alloc mem */
|
|
||||||
return_code = membuffer_set_size( m, m->length + buf_len );
|
|
||||||
if( return_code != 0 ) {
|
|
||||||
return return_code;
|
|
||||||
}
|
|
||||||
/* insert data */
|
|
||||||
|
|
||||||
/* move data to right of insertion point */
|
|
||||||
memmove( m->buf + index + buf_len, m->buf + index, m->length - index );
|
|
||||||
memcpy( m->buf + index, buf, buf_len );
|
|
||||||
m->length += buf_len;
|
|
||||||
m->buf[m->length] = 0; /* null-terminate */
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void membuffer_delete(membuffer *m, size_t index, size_t num_bytes)
|
void membuffer_delete(membuffer *m, size_t index, size_t num_bytes)
|
||||||
{
|
{
|
||||||
int return_value;
|
int return_value;
|
||||||
int new_length;
|
size_t new_length;
|
||||||
size_t copy_len;
|
size_t copy_len;
|
||||||
|
|
||||||
assert(m != NULL);
|
assert(m != NULL);
|
||||||
|
@ -58,7 +58,7 @@ void namecopy(char dest[NAME_SIZE], const char *src)
|
|||||||
|
|
||||||
void linecopylen(char dest[LINE_SIZE], const char *src, size_t srclen)
|
void linecopylen(char dest[LINE_SIZE], const char *src, size_t srclen)
|
||||||
{
|
{
|
||||||
int len;
|
size_t len;
|
||||||
|
|
||||||
len = srclen < (LINE_SIZE - 1) ? srclen : (LINE_SIZE - 1);
|
len = srclen < (LINE_SIZE - 1) ? srclen : (LINE_SIZE - 1);
|
||||||
strncpy(dest, src, len);
|
strncpy(dest, src, len);
|
||||||
|
@ -257,26 +257,22 @@ int membuffer_append( INOUT membuffer* m, IN const void* buf, IN size_t buf_len
|
|||||||
************************************************************************/
|
************************************************************************/
|
||||||
int membuffer_append_str( INOUT membuffer* m, IN const char* c_str );
|
int membuffer_append_str( INOUT membuffer* m, IN const char* c_str );
|
||||||
|
|
||||||
/************************************************************************
|
/*!
|
||||||
* Function : membuffer_insert
|
* \brief Allocates memory for the new data to be inserted. Does
|
||||||
*
|
* memory management by moving the data from the existing memory to
|
||||||
* Parameters :
|
* the newly allocated memory and then appending the new data.
|
||||||
* INOUT membuffer* m ; buffer whose memory size is to be increased
|
*
|
||||||
* and appended.
|
* \return 0 if successful, error code if error.
|
||||||
* IN const void* buf ; source buffer whose contents will be
|
*/
|
||||||
* copied
|
int membuffer_insert(
|
||||||
* IN size_t buf_len ; size of the source buffer
|
/* [in,out] Buffer whose memory size is to be increased and appended. */
|
||||||
* int index ; index to determine the bounds while movinf the data
|
membuffer *m,
|
||||||
*
|
/* [in] source buffer whose contents will be copied. */
|
||||||
* Description : Allocates memory for the new data to be inserted. Does
|
const void *buf,
|
||||||
* memory management by moving the data from the existing memory to
|
/* [in] size of the source buffer. */
|
||||||
* the newly allocated memory and then appending the new data.
|
size_t buf_len,
|
||||||
*
|
/* [in] index to determine the bounds while movinf the data. */
|
||||||
* Return : int ;
|
size_t index);
|
||||||
*
|
|
||||||
* Note :
|
|
||||||
************************************************************************/
|
|
||||||
int membuffer_insert( INOUT membuffer* m, IN const void* buf, IN size_t buf_len, int index );
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -234,7 +234,7 @@ static inline void ssdp_handle_device_request(
|
|||||||
* Parameters:
|
* Parameters:
|
||||||
* IN http_message_t* hmsg: SSDP message from the device
|
* IN http_message_t* hmsg: SSDP message from the device
|
||||||
* IN struct sockaddr* dest_addr: Address of the device
|
* IN struct sockaddr* dest_addr: Address of the device
|
||||||
* IN xboolean timeout: timeout kept by the control point while sending
|
* IN int timeout: timeout kept by the control point while sending
|
||||||
* search message
|
* search message
|
||||||
* IN void* cookie: Cookie stored by the control point application.
|
* IN void* cookie: Cookie stored by the control point application.
|
||||||
* This cookie will be returned to the control point
|
* This cookie will be returned to the control point
|
||||||
@ -251,7 +251,7 @@ static inline void ssdp_handle_device_request(
|
|||||||
void ssdp_handle_ctrlpt_msg(
|
void ssdp_handle_ctrlpt_msg(
|
||||||
IN http_message_t *hmsg,
|
IN http_message_t *hmsg,
|
||||||
IN struct sockaddr *dest_addr,
|
IN struct sockaddr *dest_addr,
|
||||||
IN xboolean timeout,
|
IN int timeout,
|
||||||
IN void *cookie);
|
IN void *cookie);
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
|
@ -58,145 +58,115 @@
|
|||||||
#define SOAP_ACTION_RESP_ERROR 3
|
#define SOAP_ACTION_RESP_ERROR 3
|
||||||
#define SOAP_VAR_RESP_ERROR 4
|
#define SOAP_VAR_RESP_ERROR 4
|
||||||
|
|
||||||
/****************************************************************************
|
/*!
|
||||||
* Function : dom_cmp_name
|
* \brief Compares 'name' and node's name.
|
||||||
*
|
*
|
||||||
* Parameters :
|
* \return 0 if both are equal; 1 if not equal, and UPNP_E_OUTOF_MEMORY.
|
||||||
* IN char *name : lookup name
|
*/
|
||||||
* IN IXML_Node *node : xml node
|
static int dom_cmp_name(
|
||||||
*
|
/* [in] lookup name. */
|
||||||
* Description : This function compares 'name' and node's name
|
const char *name,
|
||||||
*
|
/* [in] xml node. */
|
||||||
* Return : int
|
IXML_Node *node)
|
||||||
* 0 if both are equal; 1 if not equal, and UPNP_E_OUTOF_MEMORY
|
|
||||||
*
|
|
||||||
* Note :
|
|
||||||
****************************************************************************/
|
|
||||||
static int
|
|
||||||
dom_cmp_name( IN char *name,
|
|
||||||
IN IXML_Node * node )
|
|
||||||
{
|
{
|
||||||
const DOMString node_name = NULL;
|
const DOMString node_name = NULL;
|
||||||
memptr nameptr,
|
memptr nameptr;
|
||||||
dummy;
|
memptr dummy;
|
||||||
int ret_code;
|
int ret_code;
|
||||||
|
|
||||||
assert( name );
|
assert(name);
|
||||||
assert( node );
|
assert(node);
|
||||||
|
|
||||||
node_name = ixmlNode_getNodeName( node );
|
node_name = ixmlNode_getNodeName(node);
|
||||||
if( node_name == NULL ) {
|
if (node_name == NULL)
|
||||||
return UPNP_E_OUTOF_MEMORY;
|
return UPNP_E_OUTOF_MEMORY;
|
||||||
}
|
if (strcmp(name, node_name) == 0)
|
||||||
|
ret_code = 0;
|
||||||
|
else if (matchstr((char *)node_name, strlen(node_name),
|
||||||
|
"%s:%s%0", &dummy, &nameptr) == PARSE_OK &&
|
||||||
|
strcmp(nameptr.buf, name) == 0)
|
||||||
|
ret_code = 0;
|
||||||
|
else
|
||||||
|
/* names are not the same */
|
||||||
|
ret_code = 1;
|
||||||
|
|
||||||
if( strcmp( name, node_name ) == 0 ) {
|
return ret_code;
|
||||||
ret_code = 0;
|
|
||||||
} else if( matchstr( ( char * )node_name, strlen( node_name ),
|
|
||||||
"%s:%s%0", &dummy, &nameptr ) == PARSE_OK &&
|
|
||||||
strcmp( nameptr.buf, name ) == 0 ) {
|
|
||||||
ret_code = 0;
|
|
||||||
} else {
|
|
||||||
ret_code = 1; /* names are not the same */
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret_code;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/*!
|
||||||
* Function : dom_find_node
|
* \brief Goes thru each child of 'start_node' looking for a node having
|
||||||
*
|
* the name 'node_name'.
|
||||||
* Parameters :
|
*
|
||||||
* IN char* node_name : name of the node
|
* \return UPNP_E_SUCCESS if successful else returns appropriate error.
|
||||||
* IN IXML_Node *start_node : complete xml node
|
*/
|
||||||
* OUT IXML_Node ** matching_node : matched node
|
static int dom_find_node(
|
||||||
*
|
/* [in] name of the node. */
|
||||||
* Description : This function goes thru each child of 'start_node'
|
const char *node_name,
|
||||||
* looking for a node having the name 'node_name'.
|
/* [in] complete xml node. */
|
||||||
*
|
IXML_Node *start_node,
|
||||||
* Return : int
|
/* [out] matched node. */
|
||||||
* return UPNP_E_SUCCESS if successful else returns appropriate error
|
IXML_Node **matching_node)
|
||||||
*
|
|
||||||
* Note :
|
|
||||||
****************************************************************************/
|
|
||||||
static int
|
|
||||||
dom_find_node( IN char *node_name,
|
|
||||||
IN IXML_Node * start_node,
|
|
||||||
OUT IXML_Node ** matching_node )
|
|
||||||
{
|
{
|
||||||
IXML_Node *node;
|
IXML_Node *node;
|
||||||
|
|
||||||
/* invalid args */
|
/* invalid args */
|
||||||
if( node_name == NULL || start_node == NULL ) {
|
if (!node_name || !start_node)
|
||||||
return UPNP_E_NOT_FOUND;
|
return UPNP_E_NOT_FOUND;
|
||||||
}
|
node = ixmlNode_getFirstChild(start_node);
|
||||||
|
while (node != NULL) {
|
||||||
|
/* match name */
|
||||||
|
if (dom_cmp_name(node_name, node) == 0) {
|
||||||
|
*matching_node = node;
|
||||||
|
return UPNP_E_SUCCESS;
|
||||||
|
}
|
||||||
|
/* free and next node */
|
||||||
|
node = ixmlNode_getNextSibling(node);
|
||||||
|
}
|
||||||
|
|
||||||
node = ixmlNode_getFirstChild( start_node );
|
return UPNP_E_NOT_FOUND;
|
||||||
while( node != NULL ) {
|
|
||||||
/* match name */
|
|
||||||
if( dom_cmp_name( node_name, node ) == 0 ) {
|
|
||||||
*matching_node = node;
|
|
||||||
return UPNP_E_SUCCESS;
|
|
||||||
}
|
|
||||||
/* free and next node */
|
|
||||||
node = ixmlNode_getNextSibling( node ); /* next node */
|
|
||||||
}
|
|
||||||
|
|
||||||
return UPNP_E_NOT_FOUND;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/*!
|
||||||
* Function : dom_find_deep_node
|
* \brief Searches for the node specifed by the last name in the 'name' array.
|
||||||
*
|
*
|
||||||
* Parameters :
|
* \return UPNP_E_SUCCESS if successful, else returns appropriate error.
|
||||||
* IN char* names[] : array of names
|
*/
|
||||||
* IN int num_names : size of array
|
static int dom_find_deep_node(
|
||||||
* IN IXML_Node *start_node : Node from where it should should be
|
/* [in] array of names. */
|
||||||
* searched
|
const char *names[],
|
||||||
* OUT IXML_Node ** matching_node : Node that matches the last name
|
/* [in] size of array. */
|
||||||
* of the array
|
int num_names,
|
||||||
*
|
/* [in] Node from where it should should be searched. */
|
||||||
* Description : This function searches for the node specifed by the last
|
IXML_Node *start_node,
|
||||||
* name in the 'name' array.
|
/* [out] Node that matches the last name of the array. */
|
||||||
*
|
IXML_Node **matching_node)
|
||||||
* Return : int
|
|
||||||
* return UPNP_E_SUCCESS if successful else returns appropriate error
|
|
||||||
* Note :
|
|
||||||
****************************************************************************/
|
|
||||||
static int
|
|
||||||
dom_find_deep_node( IN char *names[],
|
|
||||||
IN int num_names,
|
|
||||||
IN IXML_Node * start_node,
|
|
||||||
OUT IXML_Node ** matching_node )
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
IXML_Node *node;
|
IXML_Node *node;
|
||||||
IXML_Node *match_node;
|
IXML_Node *match_node;
|
||||||
|
|
||||||
assert( num_names > 0 );
|
assert(num_names > 0);
|
||||||
|
|
||||||
node = start_node;
|
node = start_node;
|
||||||
if( dom_cmp_name( names[0], start_node ) == 0 ) {
|
if (dom_cmp_name(names[0], start_node) == 0) {
|
||||||
if( num_names == 1 ) {
|
if (num_names == 1) {
|
||||||
*matching_node = start_node;
|
*matching_node = start_node;
|
||||||
return UPNP_E_SUCCESS;
|
return UPNP_E_SUCCESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (i = 1; i < num_names; i++) {
|
||||||
|
if (dom_find_node(names[i], node, &match_node) != UPNP_E_SUCCESS)
|
||||||
|
return UPNP_E_NOT_FOUND;
|
||||||
|
if (i == num_names - 1) {
|
||||||
|
*matching_node = match_node;
|
||||||
|
return UPNP_E_SUCCESS;
|
||||||
|
}
|
||||||
|
/* try again */
|
||||||
|
node = match_node;
|
||||||
|
}
|
||||||
|
|
||||||
for( i = 1; i < num_names; i++ ) {
|
/* this line not reached */
|
||||||
if( dom_find_node( names[i], node, &match_node ) !=
|
return UPNP_E_NOT_FOUND;
|
||||||
UPNP_E_SUCCESS ) {
|
|
||||||
return UPNP_E_NOT_FOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( i == num_names - 1 ) {
|
|
||||||
*matching_node = match_node;
|
|
||||||
return UPNP_E_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
node = match_node; /* try again */
|
|
||||||
}
|
|
||||||
|
|
||||||
return UPNP_E_NOT_FOUND; /* this line not reached */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -290,41 +260,32 @@ get_action_name( IN char *action,
|
|||||||
return ret_code == PARSE_OK ? 0 : -1;
|
return ret_code == PARSE_OK ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/*!
|
||||||
* Function : add_man_header
|
* \brief Adds "MAN" field in the HTTP header.
|
||||||
*
|
*
|
||||||
* Parameters :
|
* \return 0 on success, UPNP_E_OUTOFMEMORY on error.
|
||||||
* INOUT membuffer* headers : HTTP header
|
*/
|
||||||
*
|
static UPNP_INLINE int add_man_header(
|
||||||
* Description : This function adds "MAN" field in the HTTP header
|
/* [in,out] HTTP header. */
|
||||||
*
|
membuffer *headers)
|
||||||
* Return : int
|
|
||||||
* returns 0 on success; UPNP_E_OUTOFMEMORY on error
|
|
||||||
*
|
|
||||||
* Note :
|
|
||||||
****************************************************************************/
|
|
||||||
static UPNP_INLINE int
|
|
||||||
add_man_header( INOUT membuffer * headers )
|
|
||||||
{
|
{
|
||||||
char *soap_action_hdr;
|
size_t n;
|
||||||
char *man_hdr = "MAN: \"http://schemas.xmlsoap.org/soap/envelope/\"; "
|
char *soap_action_hdr;
|
||||||
"ns=01\r\n01-";
|
const char *man_hdr =
|
||||||
|
"MAN: \"http://schemas.xmlsoap.org/soap/envelope/\"; ns=01\r\n01-";
|
||||||
|
|
||||||
/* change POST to M-POST */
|
/* change POST to M-POST */
|
||||||
if( membuffer_insert( headers, "M-", 2, 0 ) != 0 ) {
|
if (membuffer_insert(headers, "M-", 2, 0) != 0)
|
||||||
return UPNP_E_OUTOF_MEMORY;
|
return UPNP_E_OUTOF_MEMORY;
|
||||||
}
|
soap_action_hdr = strstr(headers->buf, "SOAPACTION:");
|
||||||
|
/* can't fail */
|
||||||
|
assert(soap_action_hdr != NULL);
|
||||||
|
/* insert MAN header */
|
||||||
|
n = (size_t)(soap_action_hdr - headers->buf);
|
||||||
|
if (membuffer_insert(headers, man_hdr, strlen(man_hdr), n))
|
||||||
|
return UPNP_E_OUTOF_MEMORY;
|
||||||
|
|
||||||
soap_action_hdr = strstr( headers->buf, "SOAPACTION:" );
|
return 0;
|
||||||
assert( soap_action_hdr != NULL ); /* can't fail */
|
|
||||||
|
|
||||||
/* insert MAN header */
|
|
||||||
if( membuffer_insert( headers, man_hdr, strlen( man_hdr ),
|
|
||||||
soap_action_hdr - headers->buf ) != 0 ) {
|
|
||||||
return UPNP_E_OUTOF_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -411,161 +372,129 @@ get_response_value( IN http_message_t * hmsg,
|
|||||||
OUT IXML_Node ** action_value,
|
OUT IXML_Node ** action_value,
|
||||||
OUT DOMString * str_value )
|
OUT DOMString * str_value )
|
||||||
{
|
{
|
||||||
IXML_Node *node = NULL;
|
IXML_Node *node = NULL;
|
||||||
IXML_Node *root_node = NULL;
|
IXML_Node *root_node = NULL;
|
||||||
IXML_Node *error_node = NULL;
|
IXML_Node *error_node = NULL;
|
||||||
IXML_Document *doc = NULL;
|
IXML_Document *doc = NULL;
|
||||||
char *node_str = NULL;
|
char *node_str = NULL;
|
||||||
const char *temp_str = NULL;
|
const char *temp_str = NULL;
|
||||||
DOMString error_node_str = NULL;
|
DOMString error_node_str = NULL;
|
||||||
int err_code;
|
int err_code = UPNP_E_BAD_RESPONSE; /* default error */ ;
|
||||||
xboolean done = FALSE;
|
int done = FALSE;
|
||||||
char *names[5];
|
const char *names[5];
|
||||||
const DOMString nodeValue;
|
const DOMString nodeValue;
|
||||||
|
|
||||||
err_code = UPNP_E_BAD_RESPONSE; /* default error */
|
/* only 200 and 500 status codes are relevant */
|
||||||
|
if ((hmsg->status_code != HTTP_OK &&
|
||||||
|
hmsg->status_code != HTTP_INTERNAL_SERVER_ERROR) ||
|
||||||
|
!has_xml_content_type(hmsg))
|
||||||
|
goto error_handler;
|
||||||
|
if (ixmlParseBufferEx(hmsg->entity.buf, &doc) != IXML_SUCCESS)
|
||||||
|
goto error_handler;
|
||||||
|
root_node = ixmlNode_getFirstChild((IXML_Node *) doc);
|
||||||
|
if (root_node == NULL)
|
||||||
|
goto error_handler;
|
||||||
|
if (code == SOAP_ACTION_RESP) {
|
||||||
|
/* try reading soap action response */
|
||||||
|
assert(action_value != NULL);
|
||||||
|
|
||||||
/* only 200 and 500 status codes are relevant */
|
*action_value = NULL;
|
||||||
if( ( hmsg->status_code != HTTP_OK &&
|
names[0] = "Envelope";
|
||||||
hmsg->status_code != HTTP_INTERNAL_SERVER_ERROR ) ||
|
names[1] = "Body";
|
||||||
!has_xml_content_type( hmsg ) ) {
|
names[2] = name;
|
||||||
|
if (dom_find_deep_node(names, 3, root_node, &node) ==
|
||||||
|
UPNP_E_SUCCESS) {
|
||||||
|
node_str = ixmlPrintNode(node);
|
||||||
|
if (node_str == NULL) {
|
||||||
|
err_code = UPNP_E_OUTOF_MEMORY;
|
||||||
|
goto error_handler;
|
||||||
|
}
|
||||||
|
if (ixmlParseBufferEx(node_str,
|
||||||
|
(IXML_Document **) action_value)
|
||||||
|
!= IXML_SUCCESS) {
|
||||||
|
err_code = UPNP_E_BAD_RESPONSE;
|
||||||
|
goto error_handler;
|
||||||
|
}
|
||||||
|
err_code = SOAP_ACTION_RESP;
|
||||||
|
done = TRUE;
|
||||||
|
}
|
||||||
|
} else if (code == SOAP_VAR_RESP) {
|
||||||
|
/* try reading var response */
|
||||||
|
assert(str_value != NULL);
|
||||||
|
|
||||||
goto error_handler;
|
*str_value = NULL;
|
||||||
}
|
names[0] = "Envelope";
|
||||||
|
names[1] = "Body";
|
||||||
|
names[2] = "QueryStateVariableResponse";
|
||||||
|
names[3] = "return";
|
||||||
|
if (dom_find_deep_node(names, 4, root_node, &node)
|
||||||
|
== UPNP_E_SUCCESS) {
|
||||||
|
nodeValue = get_node_value(node);
|
||||||
|
if (nodeValue == NULL)
|
||||||
|
goto error_handler;
|
||||||
|
*str_value = ixmlCloneDOMString(nodeValue);
|
||||||
|
err_code = SOAP_VAR_RESP;
|
||||||
|
done = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!done) {
|
||||||
|
/* not action or var resp; read error code and description */
|
||||||
|
*str_value = NULL;
|
||||||
|
names[0] = "Envelope";
|
||||||
|
names[1] = "Body";
|
||||||
|
names[2] = "Fault";
|
||||||
|
names[3] = "detail";
|
||||||
|
names[4] = "UPnPError";
|
||||||
|
if (dom_find_deep_node(names, 5, root_node, &error_node) !=
|
||||||
|
UPNP_E_SUCCESS)
|
||||||
|
goto error_handler;
|
||||||
|
if (dom_find_node("errorCode", error_node, &node) !=
|
||||||
|
UPNP_E_SUCCESS)
|
||||||
|
goto error_handler;
|
||||||
|
temp_str = get_node_value(node);
|
||||||
|
if (!temp_str)
|
||||||
|
goto error_handler;
|
||||||
|
*upnp_error_code = atoi(temp_str);
|
||||||
|
if (*upnp_error_code < 400) {
|
||||||
|
err_code = *upnp_error_code;
|
||||||
|
goto error_handler; /* bad SOAP error code */
|
||||||
|
}
|
||||||
|
if (code == SOAP_VAR_RESP) {
|
||||||
|
if (dom_find_node("errorDescription", error_node, &node)
|
||||||
|
!= UPNP_E_SUCCESS) {
|
||||||
|
goto error_handler;
|
||||||
|
}
|
||||||
|
nodeValue = get_node_value(node);
|
||||||
|
if (nodeValue == NULL) {
|
||||||
|
goto error_handler;
|
||||||
|
}
|
||||||
|
*str_value = ixmlCloneDOMString(nodeValue);
|
||||||
|
if (*str_value == NULL) {
|
||||||
|
goto error_handler;
|
||||||
|
}
|
||||||
|
err_code = SOAP_VAR_RESP_ERROR;
|
||||||
|
} else if (code == SOAP_ACTION_RESP) {
|
||||||
|
error_node_str = ixmlPrintNode(error_node);
|
||||||
|
if (error_node_str == NULL) {
|
||||||
|
err_code = UPNP_E_OUTOF_MEMORY;
|
||||||
|
goto error_handler;
|
||||||
|
}
|
||||||
|
if (ixmlParseBufferEx(error_node_str,
|
||||||
|
(IXML_Document **) action_value)
|
||||||
|
!= IXML_SUCCESS) {
|
||||||
|
err_code = UPNP_E_BAD_RESPONSE;
|
||||||
|
|
||||||
if( ixmlParseBufferEx( hmsg->entity.buf, &doc ) != IXML_SUCCESS ) {
|
goto error_handler;
|
||||||
|
}
|
||||||
|
err_code = SOAP_ACTION_RESP_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
goto error_handler;
|
error_handler:
|
||||||
}
|
ixmlDocument_free(doc);
|
||||||
|
ixmlFreeDOMString(node_str);
|
||||||
root_node = ixmlNode_getFirstChild( ( IXML_Node * ) doc );
|
ixmlFreeDOMString(error_node_str);
|
||||||
if( root_node == NULL ) {
|
return err_code;
|
||||||
|
|
||||||
goto error_handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( code == SOAP_ACTION_RESP ) {
|
|
||||||
/* */
|
|
||||||
/* try reading soap action response */
|
|
||||||
/* */
|
|
||||||
assert( action_value != NULL );
|
|
||||||
|
|
||||||
*action_value = NULL;
|
|
||||||
|
|
||||||
names[0] = "Envelope";
|
|
||||||
names[1] = "Body";
|
|
||||||
names[2] = name;
|
|
||||||
if( dom_find_deep_node( names, 3, root_node, &node ) ==
|
|
||||||
UPNP_E_SUCCESS ) {
|
|
||||||
node_str = ixmlPrintNode( node );
|
|
||||||
if( node_str == NULL ) {
|
|
||||||
err_code = UPNP_E_OUTOF_MEMORY;
|
|
||||||
goto error_handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( ixmlParseBufferEx( node_str,
|
|
||||||
( IXML_Document ** ) action_value ) !=
|
|
||||||
IXML_SUCCESS ) {
|
|
||||||
err_code = UPNP_E_BAD_RESPONSE;
|
|
||||||
goto error_handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
err_code = SOAP_ACTION_RESP;
|
|
||||||
done = TRUE;
|
|
||||||
}
|
|
||||||
} else if( code == SOAP_VAR_RESP ) {
|
|
||||||
/* try reading var response */
|
|
||||||
assert( str_value != NULL );
|
|
||||||
*str_value = NULL;
|
|
||||||
|
|
||||||
names[0] = "Envelope";
|
|
||||||
names[1] = "Body";
|
|
||||||
names[2] = "QueryStateVariableResponse";
|
|
||||||
names[3] = "return";
|
|
||||||
if( dom_find_deep_node( names, 4, root_node, &node )
|
|
||||||
== UPNP_E_SUCCESS ) {
|
|
||||||
nodeValue = get_node_value( node );
|
|
||||||
if( nodeValue == NULL ) {
|
|
||||||
goto error_handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
*str_value = ixmlCloneDOMString( nodeValue );
|
|
||||||
err_code = SOAP_VAR_RESP;
|
|
||||||
done = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( !done ) {
|
|
||||||
/* not action or var resp; read error code and description */
|
|
||||||
*str_value = NULL;
|
|
||||||
|
|
||||||
names[0] = "Envelope";
|
|
||||||
names[1] = "Body";
|
|
||||||
names[2] = "Fault";
|
|
||||||
names[3] = "detail";
|
|
||||||
names[4] = "UPnPError";
|
|
||||||
if( dom_find_deep_node( names, 5, root_node, &error_node )
|
|
||||||
!= UPNP_E_SUCCESS ) {
|
|
||||||
goto error_handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( dom_find_node( "errorCode", error_node, &node )
|
|
||||||
!= UPNP_E_SUCCESS ) {
|
|
||||||
goto error_handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
temp_str = get_node_value( node );
|
|
||||||
if( temp_str == NULL ) {
|
|
||||||
goto error_handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
*upnp_error_code = atoi( temp_str );
|
|
||||||
if( *upnp_error_code < 400 ) {
|
|
||||||
err_code = *upnp_error_code;
|
|
||||||
goto error_handler; /* bad SOAP error code */
|
|
||||||
}
|
|
||||||
|
|
||||||
if( code == SOAP_VAR_RESP ) {
|
|
||||||
if( dom_find_node( "errorDescription", error_node, &node )
|
|
||||||
!= UPNP_E_SUCCESS ) {
|
|
||||||
goto error_handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
nodeValue = get_node_value( node );
|
|
||||||
if( nodeValue == NULL ) {
|
|
||||||
goto error_handler;
|
|
||||||
}
|
|
||||||
*str_value = ixmlCloneDOMString( nodeValue );
|
|
||||||
if( *str_value == NULL ) {
|
|
||||||
goto error_handler;
|
|
||||||
}
|
|
||||||
err_code = SOAP_VAR_RESP_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if( code == SOAP_ACTION_RESP ) {
|
|
||||||
error_node_str = ixmlPrintNode( error_node );
|
|
||||||
if( error_node_str == NULL ) {
|
|
||||||
err_code = UPNP_E_OUTOF_MEMORY;
|
|
||||||
goto error_handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( ixmlParseBufferEx( error_node_str,
|
|
||||||
( IXML_Document ** ) action_value ) !=
|
|
||||||
IXML_SUCCESS ) {
|
|
||||||
err_code = UPNP_E_BAD_RESPONSE;
|
|
||||||
|
|
||||||
goto error_handler;
|
|
||||||
}
|
|
||||||
err_code = SOAP_ACTION_RESP_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
error_handler:
|
|
||||||
|
|
||||||
ixmlDocument_free( doc );
|
|
||||||
ixmlFreeDOMString( node_str );
|
|
||||||
ixmlFreeDOMString( error_node_str );
|
|
||||||
return err_code;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -601,15 +530,15 @@ SoapSendAction( IN char *action_url,
|
|||||||
uri_type url;
|
uri_type url;
|
||||||
int upnp_error_code;
|
int upnp_error_code;
|
||||||
char *upnp_error_str;
|
char *upnp_error_str;
|
||||||
xboolean got_response = FALSE;
|
int got_response = FALSE;
|
||||||
|
|
||||||
off_t content_length;
|
off_t content_length;
|
||||||
char *xml_start =
|
const char *xml_start =
|
||||||
"<s:Envelope "
|
"<s:Envelope "
|
||||||
"xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" "
|
"xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" "
|
||||||
"s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\r\n"
|
"s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\r\n"
|
||||||
"<s:Body>";
|
"<s:Body>";
|
||||||
char *xml_end =
|
const char *xml_end =
|
||||||
"</s:Body>\r\n"
|
"</s:Body>\r\n"
|
||||||
"</s:Envelope>\r\n\r\n";
|
"</s:Envelope>\r\n\r\n";
|
||||||
size_t xml_start_len;
|
size_t xml_start_len;
|
||||||
@ -655,7 +584,7 @@ SoapSendAction( IN char *action_url,
|
|||||||
|
|
||||||
/* make request msg */
|
/* make request msg */
|
||||||
request.size_inc = 50;
|
request.size_inc = 50;
|
||||||
content_length = xml_start_len + action_str_len + xml_end_len;
|
content_length = (off_t)(xml_start_len + action_str_len + xml_end_len);
|
||||||
if (http_MakeMessage(
|
if (http_MakeMessage(
|
||||||
&request, 1, 1,
|
&request, 1, 1,
|
||||||
"q" "N" "s" "sssbsc" "Uc" "b" "b" "b",
|
"q" "N" "s" "sssbsc" "Uc" "b" "b" "b",
|
||||||
@ -725,12 +654,12 @@ error_handler:
|
|||||||
* returns UPNP_E_SUCCESS if successful else returns appropriate error
|
* returns UPNP_E_SUCCESS if successful else returns appropriate error
|
||||||
* Note :
|
* Note :
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
int
|
int SoapSendActionEx(
|
||||||
SoapSendActionEx( IN char *action_url,
|
IN char *action_url,
|
||||||
IN char *service_type,
|
IN char *service_type,
|
||||||
IN IXML_Document * header,
|
IN IXML_Document * header,
|
||||||
IN IXML_Document * action_node,
|
IN IXML_Document * action_node,
|
||||||
OUT IXML_Document ** response_node )
|
OUT IXML_Document ** response_node )
|
||||||
{
|
{
|
||||||
char *xml_header_str = NULL;
|
char *xml_header_str = NULL;
|
||||||
char *action_str = NULL;
|
char *action_str = NULL;
|
||||||
@ -743,19 +672,18 @@ SoapSendActionEx( IN char *action_url,
|
|||||||
uri_type url;
|
uri_type url;
|
||||||
int upnp_error_code;
|
int upnp_error_code;
|
||||||
char *upnp_error_str;
|
char *upnp_error_str;
|
||||||
xboolean got_response = FALSE;
|
int got_response = FALSE;
|
||||||
|
const char *xml_start =
|
||||||
char *xml_start =
|
|
||||||
"<s:Envelope "
|
"<s:Envelope "
|
||||||
"xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" "
|
"xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" "
|
||||||
"s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\r\n";
|
"s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\r\n";
|
||||||
char *xml_header_start =
|
const char *xml_header_start =
|
||||||
"<s:Header>\r\n";
|
"<s:Header>\r\n";
|
||||||
char *xml_header_end =
|
const char *xml_header_end =
|
||||||
"</s:Header>\r\n";
|
"</s:Header>\r\n";
|
||||||
char *xml_body_start =
|
const char *xml_body_start =
|
||||||
"<s:Body>";
|
"<s:Body>";
|
||||||
char *xml_end =
|
const char *xml_end =
|
||||||
"</s:Body>\r\n"
|
"</s:Body>\r\n"
|
||||||
"</s:Envelope>\r\n";
|
"</s:Envelope>\r\n";
|
||||||
size_t xml_start_len;
|
size_t xml_start_len;
|
||||||
@ -816,10 +744,9 @@ SoapSendActionEx( IN char *action_url,
|
|||||||
|
|
||||||
/* make request msg */
|
/* make request msg */
|
||||||
request.size_inc = 50;
|
request.size_inc = 50;
|
||||||
content_length =
|
content_length = (off_t)(xml_start_len + xml_header_start_len +
|
||||||
xml_start_len +
|
xml_header_str_len + xml_header_end_len +
|
||||||
xml_header_start_len + xml_header_str_len + xml_header_end_len +
|
xml_body_start_len + action_str_len + xml_end_len);
|
||||||
xml_body_start_len + action_str_len + xml_end_len;
|
|
||||||
if (http_MakeMessage(
|
if (http_MakeMessage(
|
||||||
&request, 1, 1,
|
&request, 1, 1,
|
||||||
"q" "N" "s" "sssbsc" "Uc" "b" "b" "b" "b" "b" "b" "b",
|
"q" "N" "s" "sssbsc" "Uc" "b" "b" "b" "b" "b" "b" "b",
|
||||||
@ -903,33 +830,30 @@ SoapGetServiceVarStatus( IN char *action_url,
|
|||||||
int ret_code;
|
int ret_code;
|
||||||
http_parser_t response;
|
http_parser_t response;
|
||||||
int upnp_error_code;
|
int upnp_error_code;
|
||||||
|
|
||||||
off_t content_length;
|
off_t content_length;
|
||||||
char *xml_start =
|
const char *xml_start =
|
||||||
"<s:Envelope "
|
"<s:Envelope "
|
||||||
"xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" "
|
"xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" "
|
||||||
"s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\r\n"
|
"s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\r\n"
|
||||||
"<s:Body>\r\n"
|
"<s:Body>\r\n"
|
||||||
"<u:QueryStateVariable xmlns:u=\"urn:schemas-upnp-org:control-1-0\">\r\n"
|
"<u:QueryStateVariable xmlns:u=\"urn:schemas-upnp-org:control-1-0\">\r\n"
|
||||||
"<u:varName>";
|
"<u:varName>";
|
||||||
|
const char *xml_end =
|
||||||
char *xml_end =
|
|
||||||
"</u:varName>\r\n"
|
"</u:varName>\r\n"
|
||||||
"</u:QueryStateVariable>\r\n"
|
"</u:QueryStateVariable>\r\n"
|
||||||
"</s:Body>\r\n"
|
"</s:Body>\r\n"
|
||||||
"</s:Envelope>\r\n";
|
"</s:Envelope>\r\n";
|
||||||
|
|
||||||
*var_value = NULL; /* return NULL in case of an error */
|
*var_value = NULL; /* return NULL in case of an error */
|
||||||
|
|
||||||
membuffer_init( &request );
|
membuffer_init( &request );
|
||||||
|
|
||||||
/* get host hdr and url path */
|
/* get host hdr and url path */
|
||||||
if( get_host_and_path( action_url, &host, &path, &url ) == -1 ) {
|
if( get_host_and_path( action_url, &host, &path, &url ) == -1 ) {
|
||||||
return UPNP_E_INVALID_URL;
|
return UPNP_E_INVALID_URL;
|
||||||
}
|
}
|
||||||
/* make headers */
|
/* make headers */
|
||||||
request.size_inc = 50;
|
request.size_inc = 50;
|
||||||
content_length = strlen( xml_start ) + strlen( var_name ) + strlen( xml_end );
|
content_length = (off_t)(strlen(xml_start) + strlen(var_name) +
|
||||||
|
strlen(xml_end));
|
||||||
if (http_MakeMessage(
|
if (http_MakeMessage(
|
||||||
&request, 1, 1,
|
&request, 1, 1,
|
||||||
"Q" "sbc" "N" "s" "sc" "Ucc" "sss",
|
"Q" "sbc" "N" "s" "sc" "Ucc" "sss",
|
||||||
@ -950,9 +874,7 @@ SoapGetServiceVarStatus( IN char *action_url,
|
|||||||
/* get variable value from the response */
|
/* get variable value from the response */
|
||||||
ret_code = get_response_value( &response.msg, SOAP_VAR_RESP, NULL,
|
ret_code = get_response_value( &response.msg, SOAP_VAR_RESP, NULL,
|
||||||
&upnp_error_code, NULL, var_value );
|
&upnp_error_code, NULL, var_value );
|
||||||
|
|
||||||
httpmsg_destroy( &response.msg );
|
httpmsg_destroy( &response.msg );
|
||||||
|
|
||||||
if( ret_code == SOAP_VAR_RESP ) {
|
if( ret_code == SOAP_VAR_RESP ) {
|
||||||
return UPNP_E_SUCCESS;
|
return UPNP_E_SUCCESS;
|
||||||
} else if( ret_code == SOAP_VAR_RESP_ERROR ) {
|
} else if( ret_code == SOAP_VAR_RESP_ERROR ) {
|
||||||
|
@ -88,82 +88,68 @@ static UPNP_INLINE int get_request_type(
|
|||||||
/*! [out] SOAP action name. */
|
/*! [out] SOAP action name. */
|
||||||
memptr *action_name)
|
memptr *action_name)
|
||||||
{
|
{
|
||||||
memptr value;
|
memptr value;
|
||||||
memptr ns_value,
|
memptr ns_value, dummy_quote;
|
||||||
dummy_quote;
|
http_header_t *hdr;
|
||||||
http_header_t *hdr;
|
char save_char;
|
||||||
char save_char;
|
char *s;
|
||||||
char *s;
|
membuffer soap_action_name;
|
||||||
membuffer soap_action_name;
|
size_t n;
|
||||||
|
|
||||||
/* find soapaction header */
|
/* find soapaction header */
|
||||||
if( request->method == SOAPMETHOD_POST ) {
|
if (request->method == SOAPMETHOD_POST) {
|
||||||
if( httpmsg_find_hdr( request, HDR_SOAPACTION, &value )
|
if (!httpmsg_find_hdr(request, HDR_SOAPACTION, &value))
|
||||||
== NULL ) {
|
return SREQ_HDR_NOT_FOUND;
|
||||||
return SREQ_HDR_NOT_FOUND;
|
} else {
|
||||||
}
|
/* M-POST */
|
||||||
} else {
|
/* get NS value from MAN header */
|
||||||
/* M-POST */
|
hdr = httpmsg_find_hdr(request, HDR_MAN, &value);
|
||||||
/* get NS value from MAN header */
|
if (hdr == NULL)
|
||||||
hdr = httpmsg_find_hdr( request, HDR_MAN, &value );
|
return SREQ_HDR_NOT_FOUND;
|
||||||
if( hdr == NULL ) {
|
if (matchstr(value.buf, value.length, "%q%i ; ns = %s",
|
||||||
return SREQ_HDR_NOT_FOUND;
|
&dummy_quote, &ns_value) != 0)
|
||||||
}
|
return SREQ_BAD_HDR_FORMAT;
|
||||||
|
/* create soapaction name header */
|
||||||
|
membuffer_init(&soap_action_name);
|
||||||
|
if (membuffer_assign(&soap_action_name,
|
||||||
|
ns_value.buf, ns_value.length) == UPNP_E_OUTOF_MEMORY ||
|
||||||
|
membuffer_append_str(&soap_action_name,
|
||||||
|
"-SOAPACTION") == UPNP_E_OUTOF_MEMORY) {
|
||||||
|
membuffer_destroy(&soap_action_name);
|
||||||
|
return UPNP_E_OUTOF_MEMORY;
|
||||||
|
}
|
||||||
|
hdr = httpmsg_find_hdr_str(request, soap_action_name.buf);
|
||||||
|
membuffer_destroy(&soap_action_name);
|
||||||
|
if (!hdr)
|
||||||
|
return SREQ_HDR_NOT_FOUND;
|
||||||
|
value.buf = hdr->value.buf;
|
||||||
|
value.length = hdr->value.length;
|
||||||
|
}
|
||||||
|
/* determine type */
|
||||||
|
save_char = value.buf[value.length];
|
||||||
|
value.buf[value.length] = '\0';
|
||||||
|
s = strchr(value.buf, '#');
|
||||||
|
if (s == NULL) {
|
||||||
|
value.buf[value.length] = save_char;
|
||||||
|
return SREQ_BAD_HDR_FORMAT;
|
||||||
|
}
|
||||||
|
/* move to value */
|
||||||
|
s++;
|
||||||
|
n = value.length - (size_t)(s - value.buf);
|
||||||
|
if (matchstr(s, n, "%s", action_name) != PARSE_OK) {
|
||||||
|
value.buf[value.length] = save_char;
|
||||||
|
return SREQ_BAD_HDR_FORMAT;
|
||||||
|
}
|
||||||
|
/* action name or variable ? */
|
||||||
|
if (memptr_cmp(action_name, "QueryStateVariable") == 0) {
|
||||||
|
/* query variable */
|
||||||
|
action_name->buf = NULL;
|
||||||
|
action_name->length = 0;
|
||||||
|
}
|
||||||
|
/* restore */
|
||||||
|
value.buf[value.length] = save_char;
|
||||||
|
|
||||||
if( matchstr( value.buf, value.length, "%q%i ; ns = %s",
|
return 0;
|
||||||
&dummy_quote, &ns_value ) != 0 ) {
|
|
||||||
return SREQ_BAD_HDR_FORMAT;
|
|
||||||
}
|
|
||||||
/* create soapaction name header */
|
|
||||||
membuffer_init( &soap_action_name );
|
|
||||||
if( ( membuffer_assign( &soap_action_name,
|
|
||||||
ns_value.buf, ns_value.length )
|
|
||||||
== UPNP_E_OUTOF_MEMORY ) ||
|
|
||||||
( membuffer_append_str( &soap_action_name,
|
|
||||||
"-SOAPACTION" ) ==
|
|
||||||
UPNP_E_OUTOF_MEMORY )
|
|
||||||
) {
|
|
||||||
membuffer_destroy( &soap_action_name );
|
|
||||||
return UPNP_E_OUTOF_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
hdr = httpmsg_find_hdr_str( request, soap_action_name.buf );
|
|
||||||
membuffer_destroy( &soap_action_name );
|
|
||||||
if( hdr == NULL ) {
|
|
||||||
return SREQ_HDR_NOT_FOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
value.buf = hdr->value.buf;
|
|
||||||
value.length = hdr->value.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* determine type */
|
|
||||||
save_char = value.buf[value.length];
|
|
||||||
value.buf[value.length] = '\0';
|
|
||||||
|
|
||||||
s = strchr( value.buf, '#' );
|
|
||||||
if( s == NULL ) {
|
|
||||||
value.buf[value.length] = save_char;
|
|
||||||
return SREQ_BAD_HDR_FORMAT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* move to value */
|
|
||||||
s++;
|
|
||||||
|
|
||||||
if( matchstr( s, value.length - ( s - value.buf ), "%s",
|
|
||||||
action_name ) != PARSE_OK ) {
|
|
||||||
value.buf[value.length] = save_char;
|
|
||||||
return SREQ_BAD_HDR_FORMAT;
|
|
||||||
}
|
|
||||||
/* action name or variable ? */
|
|
||||||
if( memptr_cmp( action_name, "QueryStateVariable" ) == 0 ) {
|
|
||||||
/* query variable */
|
|
||||||
action_name->buf = NULL;
|
|
||||||
action_name->length = 0;
|
|
||||||
}
|
|
||||||
/* restore */
|
|
||||||
value.buf[value.length] = save_char;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -189,8 +175,8 @@ send_error_response( IN SOCKINFO * info,
|
|||||||
{
|
{
|
||||||
off_t content_length;
|
off_t content_length;
|
||||||
int timeout_secs = SOAP_TIMEOUT;
|
int timeout_secs = SOAP_TIMEOUT;
|
||||||
int major,
|
int major;
|
||||||
minor;
|
int minor;
|
||||||
const char *start_body =
|
const char *start_body =
|
||||||
/* "<?xml version=\"1.0\"?>\n" required?? */
|
/* "<?xml version=\"1.0\"?>\n" required?? */
|
||||||
"<s:Envelope "
|
"<s:Envelope "
|
||||||
@ -203,27 +189,20 @@ send_error_response( IN SOCKINFO * info,
|
|||||||
"<detail>\n"
|
"<detail>\n"
|
||||||
"<UPnPError xmlns=\"urn:schemas-upnp-org:control-1-0\">\n"
|
"<UPnPError xmlns=\"urn:schemas-upnp-org:control-1-0\">\n"
|
||||||
"<errorCode>";
|
"<errorCode>";
|
||||||
|
|
||||||
const char *mid_body = "</errorCode>\n" "<errorDescription>";
|
const char *mid_body = "</errorCode>\n" "<errorDescription>";
|
||||||
|
|
||||||
const char *end_body =
|
const char *end_body =
|
||||||
"</errorDescription>\n"
|
"</errorDescription>\n"
|
||||||
"</UPnPError>\n"
|
"</UPnPError>\n"
|
||||||
"</detail>\n" "</s:Fault>\n" "</s:Body>\n" "</s:Envelope>\n";
|
"</detail>\n" "</s:Fault>\n" "</s:Body>\n" "</s:Envelope>\n";
|
||||||
|
|
||||||
char err_code_str[30];
|
char err_code_str[30];
|
||||||
|
|
||||||
membuffer headers;
|
membuffer headers;
|
||||||
|
|
||||||
sprintf( err_code_str, "%d", error_code );
|
sprintf( err_code_str, "%d", error_code );
|
||||||
|
|
||||||
/* calc body len */
|
/* calc body len */
|
||||||
content_length = strlen( start_body ) + strlen( err_code_str ) +
|
content_length = (off_t)(strlen(start_body) + strlen(err_code_str) +
|
||||||
strlen( mid_body ) + strlen( err_msg ) + strlen( end_body );
|
strlen(mid_body) + strlen(err_msg) + strlen(end_body));
|
||||||
|
|
||||||
http_CalcResponseVersion( hmsg->major_version, hmsg->minor_version,
|
http_CalcResponseVersion( hmsg->major_version, hmsg->minor_version,
|
||||||
&major, &minor );
|
&major, &minor );
|
||||||
|
|
||||||
/* make headers */
|
/* make headers */
|
||||||
membuffer_init( &headers );
|
membuffer_init( &headers );
|
||||||
if (http_MakeMessage(
|
if (http_MakeMessage(
|
||||||
@ -242,7 +221,6 @@ send_error_response( IN SOCKINFO * info,
|
|||||||
/* send err msg */
|
/* send err msg */
|
||||||
http_SendMessage( info, &timeout_secs, "b",
|
http_SendMessage( info, &timeout_secs, "b",
|
||||||
headers.buf, headers.length );
|
headers.buf, headers.length );
|
||||||
|
|
||||||
membuffer_destroy( &headers );
|
membuffer_destroy( &headers );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,23 +254,18 @@ send_var_query_response( IN SOCKINFO * info,
|
|||||||
"<s:Body>\n"
|
"<s:Body>\n"
|
||||||
"<u:QueryStateVariableResponse "
|
"<u:QueryStateVariableResponse "
|
||||||
"xmlns:u=\"urn:schemas-upnp-org:control-1-0\">\n" "<return>";
|
"xmlns:u=\"urn:schemas-upnp-org:control-1-0\">\n" "<return>";
|
||||||
|
|
||||||
const char *end_body =
|
const char *end_body =
|
||||||
"</return>\n"
|
"</return>\n"
|
||||||
"</u:QueryStateVariableResponse>\n"
|
"</u:QueryStateVariableResponse>\n"
|
||||||
"</s:Body>\n" "</s:Envelope>\n";
|
"</s:Body>\n" "</s:Envelope>\n";
|
||||||
|
|
||||||
membuffer response;
|
membuffer response;
|
||||||
|
|
||||||
http_CalcResponseVersion( hmsg->major_version, hmsg->minor_version,
|
http_CalcResponseVersion( hmsg->major_version, hmsg->minor_version,
|
||||||
&major, &minor );
|
&major, &minor );
|
||||||
|
content_length = (off_t)(strlen(start_body) + strlen(var_value) +
|
||||||
content_length = strlen( start_body ) + strlen( var_value ) +
|
strlen(end_body));
|
||||||
strlen( end_body );
|
|
||||||
|
|
||||||
/* make headers */
|
/* make headers */
|
||||||
membuffer_init( &response );
|
membuffer_init(&response);
|
||||||
|
|
||||||
if (http_MakeMessage(
|
if (http_MakeMessage(
|
||||||
&response, major, minor,
|
&response, major, minor,
|
||||||
"RNsDsSXcc" "sss",
|
"RNsDsSXcc" "sss",
|
||||||
@ -302,15 +275,13 @@ send_var_query_response( IN SOCKINFO * info,
|
|||||||
"EXT:\r\n",
|
"EXT:\r\n",
|
||||||
X_USER_AGENT,
|
X_USER_AGENT,
|
||||||
start_body, var_value, end_body ) != 0 ) {
|
start_body, var_value, end_body ) != 0 ) {
|
||||||
membuffer_destroy( &response );
|
membuffer_destroy(&response);
|
||||||
return; /* out of mem */
|
return; /* out of mem */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* send msg */
|
/* send msg */
|
||||||
http_SendMessage( info, &timeout_secs, "b",
|
http_SendMessage(info, &timeout_secs, "b",
|
||||||
response.buf, response.length );
|
response.buf, response.length);
|
||||||
|
membuffer_destroy(&response);
|
||||||
membuffer_destroy( &response );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -475,81 +446,72 @@ check_soap_action_header( IN http_message_t * request,
|
|||||||
IN const char *urn,
|
IN const char *urn,
|
||||||
OUT char **actionName )
|
OUT char **actionName )
|
||||||
{
|
{
|
||||||
memptr header_name;
|
memptr header_name;
|
||||||
http_header_t *soap_action_header = NULL;
|
http_header_t *soap_action_header = NULL;
|
||||||
char *ns_compare = NULL;
|
char *ns_compare = NULL;
|
||||||
int tempSize = 0;
|
size_t tempSize = 0;
|
||||||
int ret_code = UPNP_E_SUCCESS;
|
int ret_code = UPNP_E_SUCCESS;
|
||||||
char *temp_header_value = NULL;
|
char *temp_header_value = NULL;
|
||||||
char *temp = NULL;
|
char *temp = NULL;
|
||||||
char *temp2 = NULL;
|
char *temp2 = NULL;
|
||||||
|
|
||||||
/* check soap action header */
|
/* check soap action header */
|
||||||
soap_action_header = httpmsg_find_hdr( request, HDR_SOAPACTION,
|
soap_action_header = httpmsg_find_hdr(request, HDR_SOAPACTION,
|
||||||
&header_name );
|
&header_name);
|
||||||
|
if (!soap_action_header) {
|
||||||
|
ret_code = UPNP_E_INVALID_ACTION;
|
||||||
|
return ret_code;
|
||||||
|
}
|
||||||
|
if (soap_action_header->value.length <= 0) {
|
||||||
|
ret_code = UPNP_E_INVALID_ACTION;
|
||||||
|
return ret_code;
|
||||||
|
}
|
||||||
|
temp_header_value = malloc(soap_action_header->value.length + 1);
|
||||||
|
if (!temp_header_value) {
|
||||||
|
ret_code = UPNP_E_OUTOF_MEMORY;
|
||||||
|
free(temp_header_value);
|
||||||
|
return ret_code;
|
||||||
|
}
|
||||||
|
strncpy(temp_header_value, soap_action_header->value.buf,
|
||||||
|
soap_action_header->value.length);
|
||||||
|
temp_header_value[soap_action_header->value.length] = 0;
|
||||||
|
temp = strchr(temp_header_value, '#');
|
||||||
|
if (!temp) {
|
||||||
|
free(temp_header_value);
|
||||||
|
ret_code = UPNP_E_INVALID_ACTION;
|
||||||
|
return ret_code;
|
||||||
|
}
|
||||||
|
|
||||||
if( !soap_action_header ) {
|
(*temp) = 0; /* temp make string */
|
||||||
ret_code = UPNP_E_INVALID_ACTION;
|
|
||||||
return ret_code;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( soap_action_header->value.length <= 0 ) {
|
/* check to see if it is Query State Variable or
|
||||||
ret_code = UPNP_E_INVALID_ACTION;
|
* Service Action */
|
||||||
return ret_code;
|
tempSize = strlen(urn) + 2;
|
||||||
}
|
ns_compare = malloc(tempSize);
|
||||||
|
if (!ns_compare) {
|
||||||
|
ret_code = UPNP_E_OUTOF_MEMORY;
|
||||||
|
free(temp_header_value);
|
||||||
|
return ret_code;
|
||||||
|
}
|
||||||
|
snprintf(ns_compare, tempSize, "\"%s", urn);
|
||||||
|
if (strcmp(temp_header_value, ns_compare))
|
||||||
|
ret_code = UPNP_E_INVALID_ACTION;
|
||||||
|
else {
|
||||||
|
ret_code = UPNP_E_SUCCESS;
|
||||||
|
temp++;
|
||||||
|
temp2 = strchr(temp, '\"');
|
||||||
|
/* remove ending " if present */
|
||||||
|
if (temp2)
|
||||||
|
(*temp2) = 0;
|
||||||
|
if (*temp)
|
||||||
|
(*actionName) = strdup(temp);
|
||||||
|
if (!*actionName)
|
||||||
|
ret_code = UPNP_E_OUTOF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
temp_header_value =
|
free(temp_header_value);
|
||||||
( char * )malloc( soap_action_header->value.length + 1 );
|
free(ns_compare);
|
||||||
|
return ret_code;
|
||||||
if( !temp_header_value ) {
|
|
||||||
ret_code = UPNP_E_OUTOF_MEMORY;
|
|
||||||
free( temp_header_value );
|
|
||||||
return ret_code;
|
|
||||||
}
|
|
||||||
|
|
||||||
strncpy( temp_header_value, soap_action_header->value.buf,
|
|
||||||
soap_action_header->value.length );
|
|
||||||
temp_header_value[soap_action_header->value.length] = 0;
|
|
||||||
|
|
||||||
temp = strchr( temp_header_value, '#' );
|
|
||||||
if( !temp ) {
|
|
||||||
free( temp_header_value );
|
|
||||||
ret_code = UPNP_E_INVALID_ACTION;
|
|
||||||
return ret_code;
|
|
||||||
}
|
|
||||||
|
|
||||||
( *temp ) = 0; /* temp make string */
|
|
||||||
|
|
||||||
/* check to see if it is Query State Variable or
|
|
||||||
* Service Action */
|
|
||||||
tempSize = strlen( urn ) + 2;
|
|
||||||
ns_compare = ( char * )malloc( tempSize );
|
|
||||||
if( !ns_compare ) {
|
|
||||||
ret_code = UPNP_E_OUTOF_MEMORY;
|
|
||||||
free( temp_header_value );
|
|
||||||
return ret_code;
|
|
||||||
}
|
|
||||||
snprintf( ns_compare, tempSize, "\"%s", urn );
|
|
||||||
if( strcmp( temp_header_value, ns_compare ) ) {
|
|
||||||
ret_code = UPNP_E_INVALID_ACTION;
|
|
||||||
} else {
|
|
||||||
ret_code = UPNP_E_SUCCESS;
|
|
||||||
temp++;
|
|
||||||
temp2 = strchr( temp, '\"' );
|
|
||||||
if( temp2 ) /* remove ending " if present */
|
|
||||||
{
|
|
||||||
( *temp2 ) = 0;
|
|
||||||
}
|
|
||||||
if( *temp )
|
|
||||||
( *actionName ) = strdup( temp );
|
|
||||||
if( !*actionName ) {
|
|
||||||
ret_code = UPNP_E_OUTOF_MEMORY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free( temp_header_value );
|
|
||||||
free( ns_compare );
|
|
||||||
return ret_code;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -686,12 +648,12 @@ send_action_response( IN SOCKINFO * info,
|
|||||||
off_t content_length;
|
off_t content_length;
|
||||||
int ret_code;
|
int ret_code;
|
||||||
int timeout_secs = SOAP_TIMEOUT;
|
int timeout_secs = SOAP_TIMEOUT;
|
||||||
static char *start_body =
|
static const char *start_body =
|
||||||
/*"<?xml version=\"1.0\"?>" required?? */
|
/*"<?xml version=\"1.0\"?>" required?? */
|
||||||
"<s:Envelope xmlns:s=\"http://schemas.xmlsoap."
|
"<s:Envelope xmlns:s=\"http://schemas.xmlsoap."
|
||||||
"org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap."
|
"org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap."
|
||||||
"org/soap/encoding/\"><s:Body>\n";
|
"org/soap/encoding/\"><s:Body>\n";
|
||||||
static char *end_body = "</s:Body> </s:Envelope>";
|
static const char *end_body = "</s:Body> </s:Envelope>";
|
||||||
|
|
||||||
/* init */
|
/* init */
|
||||||
http_CalcResponseVersion( request->major_version,
|
http_CalcResponseVersion( request->major_version,
|
||||||
@ -700,14 +662,10 @@ send_action_response( IN SOCKINFO * info,
|
|||||||
err_code = UPNP_E_OUTOF_MEMORY; /* one error only */
|
err_code = UPNP_E_OUTOF_MEMORY; /* one error only */
|
||||||
/* get xml */
|
/* get xml */
|
||||||
xml_response = ixmlPrintNode( ( IXML_Node * ) action_resp );
|
xml_response = ixmlPrintNode( ( IXML_Node * ) action_resp );
|
||||||
if( xml_response == NULL ) {
|
if (!xml_response)
|
||||||
goto error_handler;
|
goto error_handler;
|
||||||
}
|
content_length = (off_t)(strlen(start_body) + strlen(xml_response) +
|
||||||
|
strlen(end_body));
|
||||||
content_length =
|
|
||||||
strlen( start_body ) +
|
|
||||||
strlen( xml_response ) +
|
|
||||||
strlen( end_body );
|
|
||||||
/* make headers */
|
/* make headers */
|
||||||
if (http_MakeMessage(
|
if (http_MakeMessage(
|
||||||
&headers, major, minor,
|
&headers, major, minor,
|
||||||
@ -725,13 +683,11 @@ send_action_response( IN SOCKINFO * info,
|
|||||||
start_body, strlen( start_body ),
|
start_body, strlen( start_body ),
|
||||||
xml_response, strlen( xml_response ),
|
xml_response, strlen( xml_response ),
|
||||||
end_body, strlen( end_body ) );
|
end_body, strlen( end_body ) );
|
||||||
|
|
||||||
if( ret_code != 0 ) {
|
if( ret_code != 0 ) {
|
||||||
UpnpPrintf( UPNP_INFO, SOAP, __FILE__, __LINE__,
|
UpnpPrintf( UPNP_INFO, SOAP, __FILE__, __LINE__,
|
||||||
"Failed to send response: err code = %d\n",
|
"Failed to send response: err code = %d\n",
|
||||||
ret_code );
|
ret_code );
|
||||||
}
|
}
|
||||||
|
|
||||||
err_code = 0;
|
err_code = 0;
|
||||||
|
|
||||||
error_handler:
|
error_handler:
|
||||||
@ -996,9 +952,8 @@ error_handler:
|
|||||||
ixmlDocument_free( action.ActionResult );
|
ixmlDocument_free( action.ActionResult );
|
||||||
ixmlDocument_free( resp_node );
|
ixmlDocument_free( resp_node );
|
||||||
action_name.buf[action_name.length] = save_char; /* restore */
|
action_name.buf[action_name.length] = save_char; /* restore */
|
||||||
if( err_code != 0 ) {
|
if( err_code != 0 )
|
||||||
send_error_response( info, err_code, err_str, request );
|
send_error_response( info, err_code, err_str, request );
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -1018,56 +973,49 @@ error_handler:
|
|||||||
*
|
*
|
||||||
* Note :
|
* Note :
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
void
|
void soap_device_callback(IN http_parser_t *parser, IN http_message_t *request,
|
||||||
soap_device_callback( IN http_parser_t * parser,
|
INOUT SOCKINFO *info)
|
||||||
IN http_message_t * request,
|
|
||||||
INOUT SOCKINFO * info )
|
|
||||||
{
|
{
|
||||||
int err_code;
|
int err_code;
|
||||||
const char *err_str;
|
const char *err_str;
|
||||||
memptr action_name;
|
memptr action_name;
|
||||||
IXML_Document *xml_doc = NULL;
|
IXML_Document *xml_doc = NULL;
|
||||||
|
|
||||||
/* set default error */
|
/* set default error */
|
||||||
err_code = SOAP_INVALID_ACTION;
|
err_code = SOAP_INVALID_ACTION;
|
||||||
err_str = Soap_Invalid_Action;
|
err_str = Soap_Invalid_Action;
|
||||||
|
|
||||||
/* validate: content-type == text/xml */
|
/* validate: content-type == text/xml */
|
||||||
if( !has_xml_content_type( request ) ) {
|
if (!has_xml_content_type(request))
|
||||||
goto error_handler;
|
goto error_handler;
|
||||||
}
|
/* type of request */
|
||||||
/* type of request */
|
if (get_request_type(request, &action_name) != 0)
|
||||||
if( get_request_type( request, &action_name ) != 0 ) {
|
goto error_handler;
|
||||||
goto error_handler;
|
/* parse XML */
|
||||||
}
|
err_code = ixmlParseBufferEx(request->entity.buf, &xml_doc);
|
||||||
/* parse XML */
|
if (err_code != IXML_SUCCESS) {
|
||||||
err_code = ixmlParseBufferEx( request->entity.buf, &xml_doc );
|
if (err_code == IXML_INSUFFICIENT_MEMORY)
|
||||||
if( err_code != IXML_SUCCESS ) {
|
err_code = UPNP_E_OUTOF_MEMORY;
|
||||||
if( err_code == IXML_INSUFFICIENT_MEMORY ) {
|
else
|
||||||
err_code = UPNP_E_OUTOF_MEMORY;
|
err_code = SOAP_ACTION_FAILED;
|
||||||
} else {
|
err_str = "XML error";
|
||||||
err_code = SOAP_ACTION_FAILED;
|
goto error_handler;
|
||||||
}
|
}
|
||||||
|
if (action_name.length == 0)
|
||||||
|
/* query var */
|
||||||
|
handle_query_variable(info, request, xml_doc);
|
||||||
|
else
|
||||||
|
/* invoke action */
|
||||||
|
handle_invoke_action(info, request, action_name, xml_doc);
|
||||||
|
/* no error */
|
||||||
|
err_code = 0;
|
||||||
|
|
||||||
err_str = "XML error";
|
error_handler:
|
||||||
goto error_handler;
|
ixmlDocument_free(xml_doc);
|
||||||
}
|
if (err_code != 0)
|
||||||
|
send_error_response(info, err_code, err_str, request);
|
||||||
if( action_name.length == 0 ) {
|
return;
|
||||||
/* query var */
|
parser = parser;
|
||||||
handle_query_variable( info, request, xml_doc );
|
|
||||||
} else {
|
|
||||||
/* invoke action */
|
|
||||||
handle_invoke_action( info, request, action_name, xml_doc );
|
|
||||||
}
|
|
||||||
|
|
||||||
err_code = 0; /* no error */
|
|
||||||
|
|
||||||
error_handler:
|
|
||||||
ixmlDocument_free( xml_doc );
|
|
||||||
if( err_code != 0 ) {
|
|
||||||
send_error_response( info, err_code, err_str, request );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* EXCLUDE_SOAP */
|
#endif /* EXCLUDE_SOAP */
|
||||||
|
@ -81,7 +81,7 @@ void send_search_result(IN void *data)
|
|||||||
* SSDP message from the device
|
* SSDP message from the device
|
||||||
* IN struct sockaddr *dest_addr:
|
* IN struct sockaddr *dest_addr:
|
||||||
* Address of the device
|
* Address of the device
|
||||||
* IN xboolean timeout:
|
* IN int timeout:
|
||||||
* timeout kept by the control point while
|
* timeout kept by the control point while
|
||||||
* sending search message
|
* sending search message
|
||||||
* IN void* cookie:
|
* IN void* cookie:
|
||||||
@ -101,230 +101,227 @@ void ssdp_handle_ctrlpt_msg(
|
|||||||
IN http_message_t *hmsg,
|
IN http_message_t *hmsg,
|
||||||
IN struct sockaddr *dest_addr,
|
IN struct sockaddr *dest_addr,
|
||||||
/* only in search reply */
|
/* only in search reply */
|
||||||
IN xboolean timeout,
|
IN int timeout,
|
||||||
/* only in search reply */
|
/* only in search reply */
|
||||||
IN void *cookie)
|
IN void *cookie)
|
||||||
{
|
{
|
||||||
int handle;
|
int handle;
|
||||||
struct Handle_Info *ctrlpt_info = NULL;
|
struct Handle_Info *ctrlpt_info = NULL;
|
||||||
memptr hdr_value;
|
memptr hdr_value;
|
||||||
/* byebye or alive */
|
/* byebye or alive */
|
||||||
xboolean is_byebye;
|
int is_byebye;
|
||||||
struct Upnp_Discovery param;
|
struct Upnp_Discovery param;
|
||||||
SsdpEvent event;
|
SsdpEvent event;
|
||||||
xboolean nt_found;
|
int nt_found;
|
||||||
xboolean usn_found;
|
int usn_found;
|
||||||
xboolean st_found;
|
int st_found;
|
||||||
char save_char;
|
char save_char;
|
||||||
Upnp_EventType event_type;
|
Upnp_EventType event_type;
|
||||||
Upnp_FunPtr ctrlpt_callback;
|
Upnp_FunPtr ctrlpt_callback;
|
||||||
void *ctrlpt_cookie;
|
void *ctrlpt_cookie;
|
||||||
ListNode *node = NULL;
|
ListNode *node = NULL;
|
||||||
SsdpSearchArg *searchArg = NULL;
|
SsdpSearchArg *searchArg = NULL;
|
||||||
int matched = 0;
|
int matched = 0;
|
||||||
ResultData *threadData = NULL;
|
ResultData *threadData = NULL;
|
||||||
ThreadPoolJob job;
|
ThreadPoolJob job;
|
||||||
|
|
||||||
/* we are assuming that there can be only one client supported at a time */
|
/* we are assuming that there can be only one client supported at a time */
|
||||||
HandleReadLock();
|
HandleReadLock();
|
||||||
|
|
||||||
if ( GetClientHandleInfo( &handle, &ctrlpt_info ) != HND_CLIENT ) {
|
if (GetClientHandleInfo(&handle, &ctrlpt_info) != HND_CLIENT) {
|
||||||
HandleUnlock();
|
HandleUnlock();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* copy */
|
/* copy */
|
||||||
ctrlpt_callback = ctrlpt_info->Callback;
|
ctrlpt_callback = ctrlpt_info->Callback;
|
||||||
ctrlpt_cookie = ctrlpt_info->Cookie;
|
ctrlpt_cookie = ctrlpt_info->Cookie;
|
||||||
HandleUnlock();
|
HandleUnlock();
|
||||||
/* search timeout */
|
/* search timeout */
|
||||||
if ( timeout ) {
|
if (timeout) {
|
||||||
ctrlpt_callback( UPNP_DISCOVERY_SEARCH_TIMEOUT, NULL, cookie );
|
ctrlpt_callback(UPNP_DISCOVERY_SEARCH_TIMEOUT, NULL, cookie);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
param.ErrCode = UPNP_E_SUCCESS;
|
param.ErrCode = UPNP_E_SUCCESS;
|
||||||
/* MAX-AGE, assume error */
|
/* MAX-AGE, assume error */
|
||||||
param.Expires = -1;
|
param.Expires = -1;
|
||||||
if ( httpmsg_find_hdr( hmsg, HDR_CACHE_CONTROL, &hdr_value ) != NULL ) {
|
if (httpmsg_find_hdr(hmsg, HDR_CACHE_CONTROL, &hdr_value) != NULL) {
|
||||||
if( matchstr( hdr_value.buf, hdr_value.length,
|
if (matchstr(hdr_value.buf, hdr_value.length,
|
||||||
"%imax-age = %d%0", ¶m.Expires ) != PARSE_OK )
|
"%imax-age = %d%0", ¶m.Expires) != PARSE_OK)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* DATE */
|
/* DATE */
|
||||||
param.Date[0] = '\0';
|
param.Date[0] = '\0';
|
||||||
if ( httpmsg_find_hdr( hmsg, HDR_DATE, &hdr_value ) != NULL ) {
|
if (httpmsg_find_hdr(hmsg, HDR_DATE, &hdr_value) != NULL) {
|
||||||
linecopylen( param.Date, hdr_value.buf, hdr_value.length );
|
linecopylen(param.Date, hdr_value.buf, hdr_value.length);
|
||||||
}
|
}
|
||||||
/* dest addr */
|
/* dest addr */
|
||||||
memcpy(¶m.DestAddr, dest_addr, sizeof(struct sockaddr_in) );
|
memcpy(¶m.DestAddr, dest_addr, sizeof(struct sockaddr_in));
|
||||||
/* EXT */
|
/* EXT */
|
||||||
param.Ext[0] = '\0';
|
param.Ext[0] = '\0';
|
||||||
if ( httpmsg_find_hdr( hmsg, HDR_EXT, &hdr_value ) != NULL ) {
|
if (httpmsg_find_hdr(hmsg, HDR_EXT, &hdr_value) != NULL) {
|
||||||
linecopylen( param.Ext, hdr_value.buf, hdr_value.length );
|
linecopylen(param.Ext, hdr_value.buf, hdr_value.length);
|
||||||
}
|
}
|
||||||
/* LOCATION */
|
/* LOCATION */
|
||||||
param.Location[0] = '\0';
|
param.Location[0] = '\0';
|
||||||
if ( httpmsg_find_hdr( hmsg, HDR_LOCATION, &hdr_value ) != NULL ) {
|
if (httpmsg_find_hdr(hmsg, HDR_LOCATION, &hdr_value) != NULL) {
|
||||||
linecopylen( param.Location, hdr_value.buf, hdr_value.length );
|
linecopylen(param.Location, hdr_value.buf, hdr_value.length);
|
||||||
}
|
}
|
||||||
/* SERVER / USER-AGENT */
|
/* SERVER / USER-AGENT */
|
||||||
param.Os[0] = '\0';
|
param.Os[0] = '\0';
|
||||||
if ( httpmsg_find_hdr( hmsg, HDR_SERVER, &hdr_value ) != NULL ||
|
if (httpmsg_find_hdr(hmsg, HDR_SERVER, &hdr_value) != NULL ||
|
||||||
httpmsg_find_hdr( hmsg, HDR_USER_AGENT, &hdr_value ) != NULL ) {
|
httpmsg_find_hdr(hmsg, HDR_USER_AGENT, &hdr_value) != NULL) {
|
||||||
linecopylen( param.Os, hdr_value.buf, hdr_value.length );
|
linecopylen(param.Os, hdr_value.buf, hdr_value.length);
|
||||||
}
|
}
|
||||||
/* clear everything */
|
/* clear everything */
|
||||||
param.DeviceId[0] = '\0';
|
param.DeviceId[0] = '\0';
|
||||||
param.DeviceType[0] = '\0';
|
param.DeviceType[0] = '\0';
|
||||||
param.ServiceType[0] = '\0';
|
param.ServiceType[0] = '\0';
|
||||||
/* not used; version is in ServiceType */
|
/* not used; version is in ServiceType */
|
||||||
param.ServiceVer[0] = '\0';
|
param.ServiceVer[0] = '\0';
|
||||||
|
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:{
|
||||||
|
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 =
|
||||||
|
(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);
|
||||||
|
}
|
||||||
|
|
||||||
event.UDN[0] = '\0';
|
HandleUnlock();
|
||||||
event.DeviceType[0] = '\0';
|
/*ctrlpt_callback( UPNP_DISCOVERY_SEARCH_RESULT, ¶m, cookie ); */
|
||||||
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 );*/
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -217,78 +217,75 @@ void ssdp_handle_device_request(
|
|||||||
* Returns: void *
|
* Returns: void *
|
||||||
* 1 if successful else appropriate error
|
* 1 if successful else appropriate error
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
static int
|
static int NewRequestHandler(IN struct sockaddr *DestAddr, IN int NumPacket,
|
||||||
NewRequestHandler( IN struct sockaddr *DestAddr,
|
IN char **RqPacket)
|
||||||
IN int NumPacket,
|
|
||||||
IN char **RqPacket )
|
|
||||||
{
|
{
|
||||||
char errorBuffer[ERROR_BUFFER_LEN];
|
char errorBuffer[ERROR_BUFFER_LEN];
|
||||||
SOCKET ReplySock;
|
SOCKET ReplySock;
|
||||||
int socklen = sizeof( struct sockaddr_storage );
|
socklen_t socklen = sizeof(struct sockaddr_storage);
|
||||||
int Index;
|
int Index;
|
||||||
unsigned long replyAddr = inet_addr( gIF_IPV4 );
|
unsigned long replyAddr = inet_addr(gIF_IPV4);
|
||||||
/* a/c to UPNP Spec */
|
/* a/c to UPNP Spec */
|
||||||
int ttl = 4;
|
int ttl = 4;
|
||||||
int hops = 1;
|
int hops = 1;
|
||||||
char buf_ntop[64];
|
char buf_ntop[64];
|
||||||
int ret = UPNP_E_SUCCESS;
|
int ret = UPNP_E_SUCCESS;
|
||||||
|
|
||||||
ReplySock = socket( DestAddr->sa_family, SOCK_DGRAM, 0 );
|
ReplySock = socket(DestAddr->sa_family, SOCK_DGRAM, 0);
|
||||||
if ( ReplySock == -1 ) {
|
if (ReplySock == -1) {
|
||||||
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
|
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
|
||||||
UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__,
|
UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__,
|
||||||
"SSDP_LIB: New Request Handler:"
|
"SSDP_LIB: New Request Handler:"
|
||||||
"Error in socket(): %s\n", errorBuffer );
|
"Error in socket(): %s\n", errorBuffer);
|
||||||
|
|
||||||
return UPNP_E_OUTOF_SOCKET;
|
return UPNP_E_OUTOF_SOCKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( DestAddr->sa_family == AF_INET ) {
|
|
||||||
inet_ntop(AF_INET, &((struct sockaddr_in*)DestAddr)->sin_addr,
|
|
||||||
buf_ntop, sizeof(buf_ntop));
|
|
||||||
setsockopt( ReplySock, IPPROTO_IP, IP_MULTICAST_IF,
|
|
||||||
(char *)&replyAddr, sizeof (replyAddr) );
|
|
||||||
setsockopt( ReplySock, IPPROTO_IP, IP_MULTICAST_TTL,
|
|
||||||
(char *)&ttl, sizeof (int) );
|
|
||||||
socklen = sizeof(struct sockaddr_in);
|
|
||||||
} else if( DestAddr->sa_family == AF_INET6 ) {
|
|
||||||
inet_ntop(AF_INET6, &((struct sockaddr_in6*)DestAddr)->sin6_addr,
|
|
||||||
buf_ntop, sizeof(buf_ntop));
|
|
||||||
setsockopt( ReplySock, IPPROTO_IPV6, IPV6_MULTICAST_IF,
|
|
||||||
(char *)&gIF_INDEX, sizeof(gIF_INDEX) );
|
|
||||||
setsockopt( ReplySock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
|
|
||||||
(char *)&hops, sizeof(hops) );
|
|
||||||
} else {
|
|
||||||
UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__,
|
|
||||||
"Invalid destination address specified." );
|
|
||||||
ret = UPNP_E_NETWORK_ERROR;
|
|
||||||
goto end_NewRequestHandler;
|
|
||||||
}
|
|
||||||
|
|
||||||
for( Index = 0; Index < NumPacket; Index++ ) {
|
if (DestAddr->sa_family == AF_INET) {
|
||||||
int rc;
|
inet_ntop(AF_INET, &((struct sockaddr_in *)DestAddr)->sin_addr,
|
||||||
UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__,
|
buf_ntop, sizeof(buf_ntop));
|
||||||
">>> SSDP SEND to %s >>>\n%s\n",
|
setsockopt(ReplySock, IPPROTO_IP, IP_MULTICAST_IF,
|
||||||
buf_ntop, *( RqPacket + Index ) );
|
(char *)&replyAddr, sizeof(replyAddr));
|
||||||
rc = sendto( ReplySock, *( RqPacket + Index ),
|
setsockopt(ReplySock, IPPROTO_IP, IP_MULTICAST_TTL,
|
||||||
strlen( *( RqPacket + Index ) ),
|
(char *)&ttl, sizeof(int));
|
||||||
0, DestAddr, socklen );
|
socklen = sizeof(struct sockaddr_in);
|
||||||
|
} else if (DestAddr->sa_family == AF_INET6) {
|
||||||
|
inet_ntop(AF_INET6,
|
||||||
|
&((struct sockaddr_in6 *)DestAddr)->sin6_addr,
|
||||||
|
buf_ntop, sizeof(buf_ntop));
|
||||||
|
setsockopt(ReplySock, IPPROTO_IPV6, IPV6_MULTICAST_IF,
|
||||||
|
(char *)&gIF_INDEX, sizeof(gIF_INDEX));
|
||||||
|
setsockopt(ReplySock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
|
||||||
|
(char *)&hops, sizeof(hops));
|
||||||
|
} else {
|
||||||
|
UpnpPrintf(UPNP_CRITICAL, SSDP, __FILE__, __LINE__,
|
||||||
|
"Invalid destination address specified.");
|
||||||
|
ret = UPNP_E_NETWORK_ERROR;
|
||||||
|
goto end_NewRequestHandler;
|
||||||
|
}
|
||||||
|
|
||||||
if (rc == -1) {
|
for (Index = 0; Index < NumPacket; Index++) {
|
||||||
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
|
ssize_t rc;
|
||||||
UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__,
|
UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__,
|
||||||
"SSDP_LIB: New Request Handler:"
|
">>> SSDP SEND to %s >>>\n%s\n",
|
||||||
"Error in socket(): %s\n", errorBuffer );
|
buf_ntop, *(RqPacket + Index));
|
||||||
ret = UPNP_E_SOCKET_WRITE;
|
rc = sendto(ReplySock, *(RqPacket + Index),
|
||||||
goto end_NewRequestHandler;
|
strlen(*(RqPacket + Index)), 0, DestAddr, socklen);
|
||||||
}
|
if (rc == -1) {
|
||||||
}
|
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
|
||||||
|
UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__,
|
||||||
|
"SSDP_LIB: New Request Handler:"
|
||||||
|
"Error in socket(): %s\n", errorBuffer);
|
||||||
|
ret = UPNP_E_SOCKET_WRITE;
|
||||||
|
goto end_NewRequestHandler;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
end_NewRequestHandler:
|
end_NewRequestHandler:
|
||||||
shutdown( ReplySock, SD_BOTH );
|
shutdown(ReplySock, SD_BOTH);
|
||||||
UpnpCloseSocket( ReplySock );
|
UpnpCloseSocket(ReplySock);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -367,9 +364,9 @@ int isUrlV6UlaGua(char *descdocUrl)
|
|||||||
* Returns: void
|
* Returns: void
|
||||||
*
|
*
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
void CreateServicePacket(
|
static void CreateServicePacket(
|
||||||
IN int msg_type,
|
IN int msg_type,
|
||||||
IN char *nt,
|
const IN char *nt,
|
||||||
IN char *usn,
|
IN char *usn,
|
||||||
IN char *location,
|
IN char *location,
|
||||||
IN int duration,
|
IN int duration,
|
||||||
@ -377,7 +374,7 @@ void CreateServicePacket(
|
|||||||
IN int AddressFamily)
|
IN int AddressFamily)
|
||||||
{
|
{
|
||||||
int ret_code;
|
int ret_code;
|
||||||
char *nts;
|
const char *nts;
|
||||||
membuffer buf;
|
membuffer buf;
|
||||||
|
|
||||||
/* Notf == 0 means service shutdown,
|
/* Notf == 0 means service shutdown,
|
||||||
@ -405,23 +402,22 @@ void CreateServicePacket(
|
|||||||
}
|
}
|
||||||
} else if (msg_type == MSGTYPE_ADVERTISEMENT ||
|
} else if (msg_type == MSGTYPE_ADVERTISEMENT ||
|
||||||
msg_type == MSGTYPE_SHUTDOWN) {
|
msg_type == MSGTYPE_SHUTDOWN) {
|
||||||
char *host = NULL;
|
const char *host = NULL;
|
||||||
if (msg_type == MSGTYPE_ADVERTISEMENT) {
|
|
||||||
|
if (msg_type == MSGTYPE_ADVERTISEMENT)
|
||||||
nts = "ssdp:alive";
|
nts = "ssdp:alive";
|
||||||
} else {
|
else
|
||||||
/* shutdown */
|
/* shutdown */
|
||||||
nts = "ssdp:byebye";
|
nts = "ssdp:byebye";
|
||||||
}
|
|
||||||
/* NOTE: The CACHE-CONTROL and LOCATION headers are not present in
|
/* NOTE: The CACHE-CONTROL and LOCATION headers are not present in
|
||||||
* a shutdown msg, but are present here for MS WinMe interop. */
|
* a shutdown msg, but are present here for MS WinMe interop. */
|
||||||
if (AddressFamily == AF_INET) {
|
if (AddressFamily == AF_INET)
|
||||||
host = SSDP_IP;
|
host = SSDP_IP;
|
||||||
} else {
|
else {
|
||||||
if (isUrlV6UlaGua(location)) {
|
if (isUrlV6UlaGua(location))
|
||||||
host = "[" SSDP_IPV6_SITELOCAL "]";
|
host = "[" SSDP_IPV6_SITELOCAL "]";
|
||||||
} else {
|
else
|
||||||
host = "[" SSDP_IPV6_LINKLOCAL "]";
|
host = "[" SSDP_IPV6_LINKLOCAL "]";
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ret_code = http_MakeMessage(
|
ret_code = http_MakeMessage(
|
||||||
&buf, 1, 1,
|
&buf, 1, 1,
|
||||||
@ -437,14 +433,11 @@ void CreateServicePacket(
|
|||||||
"NTS: ", nts,
|
"NTS: ", nts,
|
||||||
X_USER_AGENT,
|
X_USER_AGENT,
|
||||||
"USN: ", usn );
|
"USN: ", usn );
|
||||||
if (ret_code != 0) {
|
if (ret_code)
|
||||||
return;
|
return;
|
||||||
}
|
} else
|
||||||
} else {
|
|
||||||
/* unknown msg */
|
/* unknown msg */
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
|
||||||
|
|
||||||
/* return msg */
|
/* return msg */
|
||||||
*packet = membuffer_detach(&buf);
|
*packet = membuffer_detach(&buf);
|
||||||
membuffer_destroy(&buf);
|
membuffer_destroy(&buf);
|
||||||
@ -959,6 +952,7 @@ DeviceShutdown( IN char *DevType,
|
|||||||
free( msgs[2] );
|
free( msgs[2] );
|
||||||
|
|
||||||
return ret_code;
|
return ret_code;
|
||||||
|
_Server = _Server;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* EXCLUDE_SSDP */
|
#endif /* EXCLUDE_SSDP */
|
||||||
|
@ -120,8 +120,8 @@ int AdvertiseAndReply(
|
|||||||
int Exp)
|
int Exp)
|
||||||
{
|
{
|
||||||
int retVal = UPNP_E_SUCCESS;
|
int retVal = UPNP_E_SUCCESS;
|
||||||
int i;
|
long unsigned int i;
|
||||||
int j;
|
long unsigned int j;
|
||||||
int defaultExp = DEFAULT_MAXAGE;
|
int defaultExp = DEFAULT_MAXAGE;
|
||||||
struct Handle_Info *SInfo = NULL;
|
struct Handle_Info *SInfo = NULL;
|
||||||
char UDNstr[100];
|
char UDNstr[100];
|
||||||
@ -461,87 +461,73 @@ Make_Socket_NoBlocking( SOCKET sock )
|
|||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
int unique_service_name(IN char *cmd, IN SsdpEvent *Evt)
|
int unique_service_name(IN char *cmd, IN SsdpEvent *Evt)
|
||||||
{
|
{
|
||||||
char TempBuf[COMMAND_LEN];
|
char TempBuf[COMMAND_LEN];
|
||||||
char *TempPtr = NULL;
|
char *TempPtr = NULL;
|
||||||
char *Ptr = NULL;
|
char *Ptr = NULL;
|
||||||
char *ptr1 = NULL;
|
char *ptr1 = NULL;
|
||||||
char *ptr2 = NULL;
|
char *ptr2 = NULL;
|
||||||
char *ptr3 = NULL;
|
char *ptr3 = NULL;
|
||||||
int CommandFound = 0;
|
int CommandFound = 0;
|
||||||
int length = 0;
|
size_t n = 0;
|
||||||
|
|
||||||
if( ( TempPtr = strstr( cmd, "uuid:schemas" ) ) != NULL ) {
|
if ((TempPtr = strstr(cmd, "uuid:schemas")) != NULL) {
|
||||||
ptr1 = strstr( cmd, ":device" );
|
ptr1 = strstr(cmd, ":device");
|
||||||
if( ptr1 != NULL ) {
|
if (ptr1 != NULL)
|
||||||
ptr2 = strstr( ptr1 + 1, ":" );
|
ptr2 = strstr(ptr1 + 1, ":");
|
||||||
} else {
|
else
|
||||||
return -1;
|
return -1;
|
||||||
}
|
if (ptr2 != NULL)
|
||||||
|
ptr3 = strstr(ptr2 + 1, ":");
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
if (ptr3 != NULL)
|
||||||
|
sprintf(Evt->UDN, "uuid:%s", ptr3 + 1);
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
ptr1 = strstr(cmd, ":");
|
||||||
|
if (ptr1 != NULL) {
|
||||||
|
n = (size_t)(ptr3 - ptr1);
|
||||||
|
strncpy(TempBuf, ptr1, n);
|
||||||
|
TempBuf[n] = '\0';
|
||||||
|
sprintf(Evt->DeviceType, "urn%s", TempBuf);
|
||||||
|
} else
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if ((TempPtr = strstr(cmd, "uuid")) != NULL) {
|
||||||
|
if ((Ptr = strstr(cmd, "::")) != NULL) {
|
||||||
|
n = (size_t)(Ptr - TempPtr);
|
||||||
|
strncpy(Evt->UDN, TempPtr, n);
|
||||||
|
Evt->UDN[n] = '\0';
|
||||||
|
} else
|
||||||
|
strcpy(Evt->UDN, TempPtr);
|
||||||
|
CommandFound = 1;
|
||||||
|
}
|
||||||
|
if (strstr(cmd, "urn:") != NULL && strstr(cmd, ":service:") != NULL) {
|
||||||
|
if ((TempPtr = strstr(cmd, "urn")) != NULL) {
|
||||||
|
strcpy(Evt->ServiceType, TempPtr);
|
||||||
|
CommandFound = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (strstr(cmd, "urn:") != NULL && strstr(cmd, ":device:") != NULL) {
|
||||||
|
if ((TempPtr = strstr(cmd, "urn")) != NULL) {
|
||||||
|
strcpy(Evt->DeviceType, TempPtr);
|
||||||
|
CommandFound = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((TempPtr = strstr(cmd, "::upnp:rootdevice")) != NULL) {
|
||||||
|
/* Everything before "::upnp::rootdevice" is the UDN. */
|
||||||
|
if (TempPtr != cmd) {
|
||||||
|
n = (size_t)(TempPtr - cmd);
|
||||||
|
strncpy(Evt->UDN, cmd, n);
|
||||||
|
Evt->UDN[n] = 0;
|
||||||
|
CommandFound = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (CommandFound == 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
if( ptr2 != NULL ) {
|
return 0;
|
||||||
ptr3 = strstr( ptr2 + 1, ":" );
|
|
||||||
} else {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( ptr3 != NULL ) {
|
|
||||||
sprintf( Evt->UDN, "uuid:%s", ptr3 + 1 );
|
|
||||||
} else {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ptr1 = strstr( cmd, ":" );
|
|
||||||
if( ptr1 != NULL ) {
|
|
||||||
strncpy( TempBuf, ptr1, ptr3 - ptr1 );
|
|
||||||
TempBuf[ptr3 - ptr1] = '\0';
|
|
||||||
sprintf( Evt->DeviceType, "urn%s", TempBuf );
|
|
||||||
} else {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( ( TempPtr = strstr( cmd, "uuid" ) ) != NULL ) {
|
|
||||||
if( ( Ptr = strstr( cmd, "::" ) ) != NULL ) {
|
|
||||||
strncpy( Evt->UDN, TempPtr, Ptr - TempPtr );
|
|
||||||
Evt->UDN[Ptr - TempPtr] = '\0';
|
|
||||||
} else {
|
|
||||||
strcpy( Evt->UDN, TempPtr );
|
|
||||||
}
|
|
||||||
CommandFound = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( strstr( cmd, "urn:" ) != NULL
|
|
||||||
&& strstr( cmd, ":service:" ) != NULL ) {
|
|
||||||
if( ( TempPtr = strstr( cmd, "urn" ) ) != NULL ) {
|
|
||||||
strcpy( Evt->ServiceType, TempPtr );
|
|
||||||
CommandFound = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( strstr( cmd, "urn:" ) != NULL
|
|
||||||
&& strstr( cmd, ":device:" ) != NULL ) {
|
|
||||||
if( ( TempPtr = strstr( cmd, "urn" ) ) != NULL ) {
|
|
||||||
strcpy( Evt->DeviceType, TempPtr );
|
|
||||||
CommandFound = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( ( TempPtr = strstr( cmd, "::upnp:rootdevice" ) ) != NULL ) {
|
|
||||||
/* Everything before "::upnp::rootdevice" is the UDN. */
|
|
||||||
if( TempPtr != cmd ) {
|
|
||||||
length = TempPtr - cmd;
|
|
||||||
strncpy(Evt->UDN, cmd, length);
|
|
||||||
Evt->UDN[length] = 0;
|
|
||||||
CommandFound = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( CommandFound == 0 ) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
@ -779,102 +765,85 @@ static void ssdp_event_handler_thread(void *the_data)
|
|||||||
* Returns: void
|
* Returns: void
|
||||||
*
|
*
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
void
|
void readFromSSDPSocket(SOCKET socket)
|
||||||
readFromSSDPSocket( SOCKET socket )
|
|
||||||
{
|
{
|
||||||
char *requestBuf = NULL;
|
char *requestBuf = NULL;
|
||||||
char staticBuf[BUFSIZE];
|
char staticBuf[BUFSIZE];
|
||||||
struct sockaddr_storage __ss;
|
struct sockaddr_storage __ss;
|
||||||
ThreadPoolJob job;
|
ThreadPoolJob job;
|
||||||
ssdp_thread_data *data = NULL;
|
ssdp_thread_data *data = NULL;
|
||||||
socklen_t socklen = sizeof( __ss );
|
socklen_t socklen = sizeof(__ss);
|
||||||
int byteReceived = 0;
|
ssize_t byteReceived = 0;
|
||||||
char ntop_buf[64];
|
char ntop_buf[64];
|
||||||
|
|
||||||
requestBuf = staticBuf;
|
requestBuf = staticBuf;
|
||||||
|
/* in case memory can't be allocated, still drain the socket using a
|
||||||
/* in case memory can't be allocated, still drain the socket using a
|
* static buffer. */
|
||||||
* static buffer. */
|
data = malloc(sizeof(ssdp_thread_data));
|
||||||
data = ( ssdp_thread_data * )
|
if (data) {
|
||||||
malloc( sizeof( ssdp_thread_data ) );
|
/* initialize parser */
|
||||||
|
|
||||||
if( data != NULL ) {
|
|
||||||
/* initialize parser */
|
|
||||||
#ifdef INCLUDE_CLIENT_APIS
|
#ifdef INCLUDE_CLIENT_APIS
|
||||||
#ifdef UPNP_ENABLE_IPV6
|
#ifdef UPNP_ENABLE_IPV6
|
||||||
if( socket == gSsdpReqSocket4 || socket == gSsdpReqSocket6 ) {
|
if (socket == gSsdpReqSocket4 || socket == gSsdpReqSocket6)
|
||||||
parser_response_init( &data->parser, HTTPMETHOD_MSEARCH );
|
parser_response_init(&data->parser, HTTPMETHOD_MSEARCH);
|
||||||
} else {
|
else
|
||||||
parser_request_init( &data->parser );
|
parser_request_init(&data->parser);
|
||||||
}
|
#else /* UPNP_ENABLE_IPV6 */
|
||||||
#else
|
if (socket == gSsdpReqSocket4)
|
||||||
if( socket == gSsdpReqSocket4 ) {
|
parser_response_init(&data->parser, HTTPMETHOD_MSEARCH);
|
||||||
parser_response_init( &data->parser, HTTPMETHOD_MSEARCH );
|
else
|
||||||
} else {
|
parser_request_init(&data->parser);
|
||||||
parser_request_init( &data->parser );
|
#endif /* UPNP_ENABLE_IPV6 */
|
||||||
}
|
#else /* INCLUDE_CLIENT_APIS */
|
||||||
|
parser_request_init(&data->parser);
|
||||||
#endif
|
#endif /* INCLUDE_CLIENT_APIS */
|
||||||
#else
|
/* set size of parser buffer */
|
||||||
parser_request_init( &data->parser );
|
if (membuffer_set_size(&data->parser.msg.msg, BUFSIZE) == 0)
|
||||||
#endif
|
/* use this as the buffer for recv */
|
||||||
/* set size of parser buffer */
|
requestBuf = data->parser.msg.msg.buf;
|
||||||
if( membuffer_set_size( &data->parser.msg.msg, BUFSIZE ) == 0 ) {
|
else {
|
||||||
/* use this as the buffer for recv */
|
free(data);
|
||||||
requestBuf = data->parser.msg.msg.buf;
|
data = NULL;
|
||||||
|
}
|
||||||
} else {
|
}
|
||||||
free( data );
|
byteReceived = recvfrom(socket, requestBuf, BUFSIZE - 1, 0,
|
||||||
data = NULL;
|
(struct sockaddr *)&__ss, &socklen);
|
||||||
}
|
if (byteReceived > 0) {
|
||||||
}
|
requestBuf[byteReceived] = '\0';
|
||||||
byteReceived = recvfrom( socket, requestBuf,
|
if (__ss.ss_family == AF_INET)
|
||||||
BUFSIZE - 1, 0,
|
inet_ntop(AF_INET,
|
||||||
(struct sockaddr *)&__ss, &socklen );
|
&((struct sockaddr_in *)&__ss)->sin_addr,
|
||||||
|
ntop_buf, sizeof(ntop_buf));
|
||||||
if( byteReceived > 0 ) {
|
|
||||||
requestBuf[byteReceived] = '\0';
|
|
||||||
|
|
||||||
if( __ss.ss_family == AF_INET )
|
|
||||||
inet_ntop( AF_INET, &((struct sockaddr_in*)&__ss)->sin_addr, ntop_buf, sizeof(ntop_buf) );
|
|
||||||
#ifdef UPNP_ENABLE_IPV6
|
#ifdef UPNP_ENABLE_IPV6
|
||||||
else if( __ss.ss_family == AF_INET6 )
|
else if (__ss.ss_family == AF_INET6)
|
||||||
inet_ntop( AF_INET6, &((struct sockaddr_in6*)&__ss)->sin6_addr, ntop_buf, sizeof(ntop_buf) );
|
inet_ntop(AF_INET6,
|
||||||
|
&((struct sockaddr_in6 *)&__ss)->sin6_addr,
|
||||||
|
ntop_buf, sizeof(ntop_buf));
|
||||||
#endif
|
#endif
|
||||||
else
|
else
|
||||||
strncpy( ntop_buf, "<Invalid address family>", sizeof(ntop_buf) );
|
strncpy(ntop_buf, "<Invalid address family>",
|
||||||
|
sizeof(ntop_buf));
|
||||||
UpnpPrintf( UPNP_INFO, SSDP,
|
UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__,
|
||||||
__FILE__, __LINE__,
|
"Start of received response ----------------------------------------------------\n"
|
||||||
"Start of received response ----------------------------------------------------\n"
|
"%s\n"
|
||||||
"%s\n"
|
"End of received response ------------------------------------------------------\n"
|
||||||
"End of received response ------------------------------------------------------\n"
|
"From host %s\n", requestBuf, ntop_buf);
|
||||||
"From host %s\n",
|
/* add thread pool job to handle request */
|
||||||
requestBuf,
|
if (data != NULL) {
|
||||||
ntop_buf );
|
data->parser.msg.msg.length += (size_t)byteReceived;
|
||||||
UpnpPrintf( UPNP_PACKET, SSDP, __FILE__, __LINE__,
|
/* null-terminate */
|
||||||
"Start of received multicast packet --------------------------------------------\n"
|
data->parser.msg.msg.buf[byteReceived] = 0;
|
||||||
"%s\n"
|
memcpy(&data->dest_addr, &__ss, sizeof(__ss));
|
||||||
"End of received multicast packet ----------------------------------------------\n",
|
TPJobInit(&job, (start_routine)
|
||||||
requestBuf );
|
ssdp_event_handler_thread, data);
|
||||||
/* add thread pool job to handle request */
|
TPJobSetFreeFunction(&job,
|
||||||
if( data != NULL ) {
|
free_ssdp_event_handler_data);
|
||||||
data->parser.msg.msg.length += byteReceived;
|
TPJobSetPriority(&job, MED_PRIORITY);
|
||||||
/* null-terminate */
|
if (ThreadPoolAdd(&gRecvThreadPool, &job, NULL) != 0)
|
||||||
data->parser.msg.msg.buf[byteReceived] = 0;
|
free_ssdp_event_handler_data(data);
|
||||||
memcpy( &data->dest_addr, &__ss, sizeof(__ss) );
|
}
|
||||||
TPJobInit( &job, ( start_routine )
|
} else
|
||||||
ssdp_event_handler_thread, data );
|
free_ssdp_event_handler_data(data);
|
||||||
TPJobSetFreeFunction( &job, free_ssdp_event_handler_data );
|
|
||||||
TPJobSetPriority( &job, MED_PRIORITY );
|
|
||||||
|
|
||||||
if( ThreadPoolAdd( &gRecvThreadPool, &job, NULL ) != 0 ) {
|
|
||||||
free_ssdp_event_handler_data( data );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
free_ssdp_event_handler_data( data );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -907,10 +876,8 @@ int get_ssdp_sockets(MiniServerSockArray *out)
|
|||||||
}
|
}
|
||||||
/* For use by ssdp control point. */
|
/* For use by ssdp control point. */
|
||||||
gSsdpReqSocket4 = out->ssdpReqSock4;
|
gSsdpReqSocket4 = out->ssdpReqSock4;
|
||||||
} else {
|
} else
|
||||||
out->ssdpReqSock4 = INVALID_SOCKET;
|
out->ssdpReqSock4 = INVALID_SOCKET;
|
||||||
}
|
|
||||||
|
|
||||||
/* Create the IPv6 socket for SSDP REQUESTS */
|
/* Create the IPv6 socket for SSDP REQUESTS */
|
||||||
#ifdef UPNP_ENABLE_IPV6
|
#ifdef UPNP_ENABLE_IPV6
|
||||||
if (strlen(gIF_IPV6) > 0) {
|
if (strlen(gIF_IPV6) > 0) {
|
||||||
@ -922,14 +889,10 @@ int get_ssdp_sockets(MiniServerSockArray *out)
|
|||||||
}
|
}
|
||||||
/* For use by ssdp control point. */
|
/* For use by ssdp control point. */
|
||||||
gSsdpReqSocket6 = out->ssdpReqSock6;
|
gSsdpReqSocket6 = out->ssdpReqSock6;
|
||||||
} else {
|
} else
|
||||||
out->ssdpReqSock6 = INVALID_SOCKET;
|
out->ssdpReqSock6 = INVALID_SOCKET;
|
||||||
}
|
|
||||||
#endif /* IPv6 */
|
#endif /* IPv6 */
|
||||||
|
|
||||||
|
|
||||||
#endif /* INCLUDE_CLIENT_APIS */
|
#endif /* INCLUDE_CLIENT_APIS */
|
||||||
|
|
||||||
/* Create the IPv4 socket for SSDP */
|
/* Create the IPv4 socket for SSDP */
|
||||||
if (strlen(gIF_IPV4) > 0) {
|
if (strlen(gIF_IPV4) > 0) {
|
||||||
retVal = create_ssdp_sock_v4(&out->ssdpSock4);
|
retVal = create_ssdp_sock_v4(&out->ssdpSock4);
|
||||||
@ -942,10 +905,8 @@ int get_ssdp_sockets(MiniServerSockArray *out)
|
|||||||
#endif
|
#endif
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
} else {
|
} else
|
||||||
out->ssdpSock4 = INVALID_SOCKET;
|
out->ssdpSock4 = INVALID_SOCKET;
|
||||||
}
|
|
||||||
|
|
||||||
/* Create the IPv6 socket for SSDP */
|
/* Create the IPv6 socket for SSDP */
|
||||||
#ifdef UPNP_ENABLE_IPV6
|
#ifdef UPNP_ENABLE_IPV6
|
||||||
if (strlen(gIF_IPV6) > 0) {
|
if (strlen(gIF_IPV6) > 0) {
|
||||||
@ -961,10 +922,8 @@ int get_ssdp_sockets(MiniServerSockArray *out)
|
|||||||
#endif
|
#endif
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
} else {
|
} else
|
||||||
out->ssdpSock6 = INVALID_SOCKET;
|
out->ssdpSock6 = INVALID_SOCKET;
|
||||||
}
|
|
||||||
|
|
||||||
if (strlen(gIF_IPV6_ULA_GUA) > 0) {
|
if (strlen(gIF_IPV6_ULA_GUA) > 0) {
|
||||||
retVal = create_ssdp_sock_v6_ula_gua(&out->ssdpSock6UlaGua);
|
retVal = create_ssdp_sock_v6_ula_gua(&out->ssdpSock6UlaGua);
|
||||||
if (retVal != UPNP_E_SUCCESS) {
|
if (retVal != UPNP_E_SUCCESS) {
|
||||||
@ -980,9 +939,8 @@ int get_ssdp_sockets(MiniServerSockArray *out)
|
|||||||
#endif
|
#endif
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
} else {
|
} else
|
||||||
out->ssdpSock6UlaGua = INVALID_SOCKET;
|
out->ssdpSock6UlaGua = INVALID_SOCKET;
|
||||||
}
|
|
||||||
#endif /* IPv6 */
|
#endif /* IPv6 */
|
||||||
|
|
||||||
return UPNP_E_SUCCESS;
|
return UPNP_E_SUCCESS;
|
||||||
@ -1003,26 +961,24 @@ int get_ssdp_sockets(MiniServerSockArray *out)
|
|||||||
* Returns:
|
* Returns:
|
||||||
* UPNP_E_SUCCESS on successful socket creation.
|
* UPNP_E_SUCCESS on successful socket creation.
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
int create_ssdp_sock_reqv4( SOCKET* ssdpReqSock )
|
int create_ssdp_sock_reqv4(SOCKET *ssdpReqSock)
|
||||||
{
|
{
|
||||||
char errorBuffer[ERROR_BUFFER_LEN];
|
char errorBuffer[ERROR_BUFFER_LEN];
|
||||||
u_char ttl = 4;
|
u_char ttl = 4;
|
||||||
|
|
||||||
*ssdpReqSock = socket( AF_INET, SOCK_DGRAM, 0 );
|
*ssdpReqSock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
if ( *ssdpReqSock == -1 ) {
|
if (*ssdpReqSock == -1) {
|
||||||
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
|
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
|
||||||
UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__,
|
UpnpPrintf(UPNP_CRITICAL, SSDP, __FILE__, __LINE__,
|
||||||
"Error in socket(): %s\n", errorBuffer );
|
"Error in socket(): %s\n", errorBuffer);
|
||||||
return UPNP_E_OUTOF_SOCKET;
|
return UPNP_E_OUTOF_SOCKET;
|
||||||
}
|
}
|
||||||
|
setsockopt(*ssdpReqSock, IPPROTO_IP, IP_MULTICAST_TTL,
|
||||||
|
&ttl, sizeof(ttl));
|
||||||
|
/* just do it, regardless if fails or not. */
|
||||||
|
Make_Socket_NoBlocking(*ssdpReqSock);
|
||||||
|
|
||||||
setsockopt( *ssdpReqSock, IPPROTO_IP, IP_MULTICAST_TTL,
|
return UPNP_E_SUCCESS;
|
||||||
&ttl, sizeof (ttl) );
|
|
||||||
|
|
||||||
/* just do it, regardless if fails or not. */
|
|
||||||
Make_Socket_NoBlocking( *ssdpReqSock );
|
|
||||||
|
|
||||||
return UPNP_E_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user