mirror of
https://github.com/transmission/transmission
synced 2024-12-24 08:43:27 +00:00
Quick hack to get some PPP UPnP devices working.
This commit is contained in:
parent
312fe89d7b
commit
f9613c4dbc
1 changed files with 37 additions and 20 deletions
|
@ -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 );
|
||||
}
|
||||
|
@ -822,7 +823,8 @@ static tr_http_t *
|
|||
devicePulseGetHttp( tr_upnp_device_t * dev )
|
||||
{
|
||||
tr_http_t * ret;
|
||||
char numstr[6];
|
||||
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 );
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue