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_FIRST_DELAY 3750 /* 3 3/4 seconds */
#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 LOOP_DETECT_THRESHOLD 10 /* error on 10 add/get/del state changes */
#define MAPPING_CHECK_INTERVAL 900000 /* 15 minutes */
@ -45,7 +46,6 @@
typedef struct tr_upnp_action_s
{
char * name;
char * action;
int len;
struct { char * name; char * var; char dir; } * args;
} tr_upnp_action_t;
@ -56,6 +56,7 @@ typedef struct tr_upnp_device_s
char * host;
char * root;
int port;
int ppp;
char * soap;
char * scpd;
int mappedport;
@ -122,7 +123,7 @@ static tr_http_t *
devicePulseGetHttp( tr_upnp_device_t * dev );
static int
parseRoot( const char * root, const char *buf, int len,
char ** soap, char ** scpd );
char ** soap, char ** scpd, int * ppp );
static void
addUrlbase( const char * base, char ** path );
static int
@ -137,7 +138,7 @@ static char *
joinstrs( const char *, const char *, const char * );
static tr_http_t *
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
actionSetup( tr_upnp_action_t * action, const char * name, int prealloc );
static void
@ -673,7 +674,7 @@ devicePulse( tr_upnp_device_t * dev, int port )
dev->host, code );
}
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 );
}
@ -823,6 +824,7 @@ devicePulseGetHttp( tr_upnp_device_t * dev )
{
tr_http_t * ret;
char numstr[6];
const char * type;
ret = NULL;
switch( dev->state )
@ -846,8 +848,9 @@ devicePulseGetHttp( tr_upnp_device_t * dev )
break;
}
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,
&dev->addcmd,
type, &dev->addcmd,
"PortMappingEnabled", "1",
"PortMappingLeaseDuration", "0",
"RemoteHost", "",
@ -860,8 +863,9 @@ devicePulseGetHttp( tr_upnp_device_t * dev )
break;
case UPNPDEV_STATE_GET:
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,
&dev->getcmd,
type, &dev->getcmd,
"RemoteHost", "",
"ExternalPort", numstr,
"PortMappingProtocol", "TCP",
@ -869,8 +873,9 @@ devicePulseGetHttp( tr_upnp_device_t * dev )
break;
case UPNPDEV_STATE_DEL:
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,
&dev->delcmd,
type, &dev->delcmd,
"RemoteHost", "",
"ExternalPort", numstr,
"PortMappingProtocol", "TCP",
@ -951,7 +956,7 @@ devicePulseHttp( tr_upnp_device_t * dev,
static int
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;
char * basedup;
@ -998,10 +1003,21 @@ parseRoot( const char * root, const char *buf, int len,
kk = tr_xmlFindTag( kk, end, "service" );
buf = tr_xmlTagContents( kk, end );
if( !tr_xmlFindTagVerifyContents( buf, end, "serviceType",
UPNP_SERVICE_TYPE, 1 ) )
SERVICE_TYPE_IP, 1 ) )
{
*soap = tr_xmlDupTagContents( buf, end, "controlURL");
*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;
}
}
@ -1207,12 +1223,13 @@ joinstrs( const char * first, const char * delim, const char * second )
static tr_http_t *
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;
va_list ap;
const char * name, * value;
int method;
char * actstr;
method = ( retry ? TR_HTTP_M_POST : TR_HTTP_POST );
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",
"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 )
{
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 "\""
" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
" <s:Body>"
" <u:%s xmlns:u=\"" UPNP_SERVICE_TYPE "\">", action->name );
" <u:%s xmlns:u=\%s\">", action->name, type );
va_start( ap, action );
do
@ -1270,8 +1290,6 @@ static void
actionSetup( tr_upnp_action_t * action, const char * name, int prealloc )
{
action->name = strdup( name );
action->action = NULL;
asprintf( &action->action, "\"%s#%s\"", UPNP_SERVICE_TYPE, name );
assert( NULL == action->args );
action->args = malloc( sizeof( *action->args ) * prealloc );
memset( action->args, 0, sizeof( *action->args ) * prealloc );
@ -1282,7 +1300,6 @@ static void
actionFree( tr_upnp_action_t * act )
{
free( act->name );
free( act->action );
while( 0 < act->len )
{
act->len--;
@ -1369,7 +1386,7 @@ main( int argc, char * argv[] )
{
struct stat sb;
char * data, * soap, * scpd;
int fd;
int fd, ppp;
ssize_t res;
if( 3 != argc )
@ -1414,13 +1431,13 @@ main( int argc, char * argv[] )
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" );
}
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( scpd );
}