1
0
Fork 0
mirror of https://github.com/transmission/transmission synced 2024-12-25 01:03:01 +00:00

Quick hack to get some PPP UPnP devices working.

This commit is contained in:
Josh Elsasser 2007-04-20 01:27:58 +00:00
parent 312fe89d7b
commit f9613c4dbc

View file

@ -30,7 +30,8 @@
#define SSDP_SUBTYPE "ssdp:alive" #define SSDP_SUBTYPE "ssdp:alive"
#define SSDP_FIRST_DELAY 3750 /* 3 3/4 seconds */ #define SSDP_FIRST_DELAY 3750 /* 3 3/4 seconds */
#define SSDP_MAX_DELAY 1800000 /* 30 minutes */ #define SSDP_MAX_DELAY 1800000 /* 30 minutes */
#define UPNP_SERVICE_TYPE "urn:schemas-upnp-org:service:WANIPConnection:1" #define SERVICE_TYPE_IP "urn:schemas-upnp-org:service:WANIPConnection:1"
#define SERVICE_TYPE_PPP "urn:schemas-upnp-org:service:WANPPPConnection:1"
#define SOAP_ENVELOPE "http://schemas.xmlsoap.org/soap/envelope/" #define SOAP_ENVELOPE "http://schemas.xmlsoap.org/soap/envelope/"
#define LOOP_DETECT_THRESHOLD 10 /* error on 10 add/get/del state changes */ #define LOOP_DETECT_THRESHOLD 10 /* error on 10 add/get/del state changes */
#define MAPPING_CHECK_INTERVAL 900000 /* 15 minutes */ #define MAPPING_CHECK_INTERVAL 900000 /* 15 minutes */
@ -45,7 +46,6 @@
typedef struct tr_upnp_action_s typedef struct tr_upnp_action_s
{ {
char * name; char * name;
char * action;
int len; int len;
struct { char * name; char * var; char dir; } * args; struct { char * name; char * var; char dir; } * args;
} tr_upnp_action_t; } tr_upnp_action_t;
@ -56,6 +56,7 @@ typedef struct tr_upnp_device_s
char * host; char * host;
char * root; char * root;
int port; int port;
int ppp;
char * soap; char * soap;
char * scpd; char * scpd;
int mappedport; int mappedport;
@ -122,7 +123,7 @@ static tr_http_t *
devicePulseGetHttp( tr_upnp_device_t * dev ); devicePulseGetHttp( tr_upnp_device_t * dev );
static int static int
parseRoot( const char * root, const char *buf, int len, parseRoot( const char * root, const char *buf, int len,
char ** soap, char ** scpd ); char ** soap, char ** scpd, int * ppp );
static void static void
addUrlbase( const char * base, char ** path ); addUrlbase( const char * base, char ** path );
static int static int
@ -137,7 +138,7 @@ static char *
joinstrs( const char *, const char *, const char * ); joinstrs( const char *, const char *, const char * );
static tr_http_t * static tr_http_t *
soapRequest( int retry, const char * host, int port, const char * path, soapRequest( int retry, const char * host, int port, const char * path,
tr_upnp_action_t * action, ... ); const char * type, tr_upnp_action_t * action, ... );
static void static void
actionSetup( tr_upnp_action_t * action, const char * name, int prealloc ); actionSetup( tr_upnp_action_t * action, const char * name, int prealloc );
static void static void
@ -673,7 +674,7 @@ devicePulse( tr_upnp_device_t * dev, int port )
dev->host, code ); dev->host, code );
} }
else if( parseRoot( dev->root, body, len, else if( parseRoot( dev->root, body, len,
&dev->soap, &dev->scpd ) ) &dev->soap, &dev->scpd, &dev->ppp ) )
{ {
tr_dbg( "upnp device %s: parse root failed", dev->host ); tr_dbg( "upnp device %s: parse root failed", dev->host );
} }
@ -822,7 +823,8 @@ static tr_http_t *
devicePulseGetHttp( tr_upnp_device_t * dev ) devicePulseGetHttp( tr_upnp_device_t * dev )
{ {
tr_http_t * ret; tr_http_t * ret;
char numstr[6]; char numstr[6];
const char * type;
ret = NULL; ret = NULL;
switch( dev->state ) switch( dev->state )
@ -846,8 +848,9 @@ devicePulseGetHttp( tr_upnp_device_t * dev )
break; break;
} }
snprintf( numstr, sizeof( numstr ), "%i", dev->mappedport ); snprintf( numstr, sizeof( numstr ), "%i", dev->mappedport );
type = ( dev->ppp ? SERVICE_TYPE_PPP : SERVICE_TYPE_IP );
ret = soapRequest( dev->soapretry, dev->host, dev->port, dev->soap, ret = soapRequest( dev->soapretry, dev->host, dev->port, dev->soap,
&dev->addcmd, type, &dev->addcmd,
"PortMappingEnabled", "1", "PortMappingEnabled", "1",
"PortMappingLeaseDuration", "0", "PortMappingLeaseDuration", "0",
"RemoteHost", "", "RemoteHost", "",
@ -860,8 +863,9 @@ devicePulseGetHttp( tr_upnp_device_t * dev )
break; break;
case UPNPDEV_STATE_GET: case UPNPDEV_STATE_GET:
snprintf( numstr, sizeof( numstr ), "%i", dev->mappedport ); snprintf( numstr, sizeof( numstr ), "%i", dev->mappedport );
type = ( dev->ppp ? SERVICE_TYPE_PPP : SERVICE_TYPE_IP );
ret = soapRequest( dev->soapretry, dev->host, dev->port, dev->soap, ret = soapRequest( dev->soapretry, dev->host, dev->port, dev->soap,
&dev->getcmd, type, &dev->getcmd,
"RemoteHost", "", "RemoteHost", "",
"ExternalPort", numstr, "ExternalPort", numstr,
"PortMappingProtocol", "TCP", "PortMappingProtocol", "TCP",
@ -869,8 +873,9 @@ devicePulseGetHttp( tr_upnp_device_t * dev )
break; break;
case UPNPDEV_STATE_DEL: case UPNPDEV_STATE_DEL:
snprintf( numstr, sizeof( numstr ), "%i", dev->mappedport ); snprintf( numstr, sizeof( numstr ), "%i", dev->mappedport );
type = ( dev->ppp ? SERVICE_TYPE_PPP : SERVICE_TYPE_IP );
ret = soapRequest( dev->soapretry, dev->host, dev->port, dev->soap, ret = soapRequest( dev->soapretry, dev->host, dev->port, dev->soap,
&dev->delcmd, type, &dev->delcmd,
"RemoteHost", "", "RemoteHost", "",
"ExternalPort", numstr, "ExternalPort", numstr,
"PortMappingProtocol", "TCP", "PortMappingProtocol", "TCP",
@ -951,7 +956,7 @@ devicePulseHttp( tr_upnp_device_t * dev,
static int static int
parseRoot( const char * root, const char *buf, int len, parseRoot( const char * root, const char *buf, int len,
char ** soap, char ** scpd ) char ** soap, char ** scpd, int * ppp )
{ {
const char * end, * ii, * jj, * kk, * urlbase; const char * end, * ii, * jj, * kk, * urlbase;
char * basedup; char * basedup;
@ -998,10 +1003,21 @@ parseRoot( const char * root, const char *buf, int len,
kk = tr_xmlFindTag( kk, end, "service" ); kk = tr_xmlFindTag( kk, end, "service" );
buf = tr_xmlTagContents( kk, end ); buf = tr_xmlTagContents( kk, end );
if( !tr_xmlFindTagVerifyContents( buf, end, "serviceType", if( !tr_xmlFindTagVerifyContents( buf, end, "serviceType",
UPNP_SERVICE_TYPE, 1 ) ) SERVICE_TYPE_IP, 1 ) )
{ {
*soap = tr_xmlDupTagContents( buf, end, "controlURL"); *soap = tr_xmlDupTagContents( buf, end, "controlURL");
*scpd = tr_xmlDupTagContents( buf, end, "SCPDURL"); *scpd = tr_xmlDupTagContents( buf, end, "SCPDURL");
*ppp = 0;
break;
}
/* XXX we should save all services of both types and
try adding mappings for each in turn */
else if( !tr_xmlFindTagVerifyContents( buf, end, "serviceType",
SERVICE_TYPE_PPP, 1 ) )
{
*soap = tr_xmlDupTagContents( buf, end, "controlURL");
*scpd = tr_xmlDupTagContents( buf, end, "SCPDURL");
*ppp = 1;
break; break;
} }
} }
@ -1207,12 +1223,13 @@ joinstrs( const char * first, const char * delim, const char * second )
static tr_http_t * static tr_http_t *
soapRequest( int retry, const char * host, int port, const char * path, soapRequest( int retry, const char * host, int port, const char * path,
tr_upnp_action_t * action, ... ) const char * type, tr_upnp_action_t * action, ... )
{ {
tr_http_t * http; tr_http_t * http;
va_list ap; va_list ap;
const char * name, * value; const char * name, * value;
int method; int method;
char * actstr;
method = ( retry ? TR_HTTP_M_POST : TR_HTTP_POST ); method = ( retry ? TR_HTTP_M_POST : TR_HTTP_POST );
http = makeHttp( method, host, port, path ); http = makeHttp( method, host, port, path );
@ -1220,7 +1237,10 @@ soapRequest( int retry, const char * host, int port, const char * path,
{ {
tr_httpAddHeader( http, "Content-type", tr_httpAddHeader( http, "Content-type",
"text/xml; encoding=\"utf-8\"" ); "text/xml; encoding=\"utf-8\"" );
tr_httpAddHeader( http, "SOAPAction", action->action ); actstr = NULL;
asprintf( &actstr, "\"%s#%s\"", type, action->name );
tr_httpAddHeader( http, "SOAPAction", actstr );
free( actstr );
if( retry ) if( retry )
{ {
tr_httpAddHeader( http, "Man", "\"" SOAP_ENVELOPE "\"" ); tr_httpAddHeader( http, "Man", "\"" SOAP_ENVELOPE "\"" );
@ -1231,7 +1251,7 @@ soapRequest( int retry, const char * host, int port, const char * path,
" xmlns:s=\"" SOAP_ENVELOPE "\"" " xmlns:s=\"" SOAP_ENVELOPE "\""
" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" " s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
" <s:Body>" " <s:Body>"
" <u:%s xmlns:u=\"" UPNP_SERVICE_TYPE "\">", action->name ); " <u:%s xmlns:u=\%s\">", action->name, type );
va_start( ap, action ); va_start( ap, action );
do do
@ -1270,8 +1290,6 @@ static void
actionSetup( tr_upnp_action_t * action, const char * name, int prealloc ) actionSetup( tr_upnp_action_t * action, const char * name, int prealloc )
{ {
action->name = strdup( name ); action->name = strdup( name );
action->action = NULL;
asprintf( &action->action, "\"%s#%s\"", UPNP_SERVICE_TYPE, name );
assert( NULL == action->args ); assert( NULL == action->args );
action->args = malloc( sizeof( *action->args ) * prealloc ); action->args = malloc( sizeof( *action->args ) * prealloc );
memset( action->args, 0, sizeof( *action->args ) * prealloc ); memset( action->args, 0, sizeof( *action->args ) * prealloc );
@ -1282,7 +1300,6 @@ static void
actionFree( tr_upnp_action_t * act ) actionFree( tr_upnp_action_t * act )
{ {
free( act->name ); free( act->name );
free( act->action );
while( 0 < act->len ) while( 0 < act->len )
{ {
act->len--; act->len--;
@ -1369,7 +1386,7 @@ main( int argc, char * argv[] )
{ {
struct stat sb; struct stat sb;
char * data, * soap, * scpd; char * data, * soap, * scpd;
int fd; int fd, ppp;
ssize_t res; ssize_t res;
if( 3 != argc ) if( 3 != argc )
@ -1414,13 +1431,13 @@ main( int argc, char * argv[] )
close( fd ); close( fd );
if( parseRoot( argv[1], data, sb.st_size, &soap, &scpd ) ) if( parseRoot( argv[1], data, sb.st_size, &soap, &scpd, &ppp ) )
{ {
tr_err( "root parsing failed" ); tr_err( "root parsing failed" );
} }
else else
{ {
tr_err( "soap=%s scpd=%s", soap, scpd ); tr_err( "soap=%s scpd=%s ppp=%s", soap, scpd, ( ppp ? "yes" : "no" ) );
free( soap ); free( soap );
free( scpd ); free( scpd );
} }