PageRenderTime 103ms CodeModel.GetById 40ms app.highlight 21ms RepoModel.GetById 39ms app.codeStats 1ms

/thirdparty/libportfwd/src/portfwd.cpp

http://github.com/tomahawk-player/tomahawk
C++ | 214 lines | 157 code | 38 blank | 19 comment | 23 complexity | 43b221daf240c0d88f2fbab839614bcf MD5 | raw file
  1/*
  2 *   Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
  3 *
  4 *   Tomahawk is free software: you can redistribute it and/or modify
  5 *   it under the terms of the GNU General Public License as published by
  6 *   the Free Software Foundation, either version 3 of the License, or
  7 *   (at your option) any later version.
  8 *
  9 *   Tomahawk is distributed in the hope that it will be useful,
 10 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 11 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 12 *   GNU General Public License for more details.
 13 *
 14 *   You should have received a copy of the GNU General Public License
 15 *   along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
 16 */
 17
 18#include "portfwd/portfwd.h"
 19
 20#include "miniwget.h"
 21#include "miniupnpc.h"
 22#include "upnpcommands.h"
 23
 24#ifdef WIN32
 25    #include <winsock2.h>
 26#endif
 27
 28
 29Portfwd::Portfwd()
 30    : m_urls( 0 )
 31    , m_data( 0 )
 32{
 33}
 34
 35
 36Portfwd::~Portfwd()
 37{
 38    if ( m_urls )
 39        free( m_urls );
 40
 41    if ( m_data )
 42        free( m_data );
 43}
 44
 45
 46bool
 47Portfwd::init( unsigned int timeout )
 48{
 49#ifdef WIN32
 50    WSADATA wsaData;
 51    int nResult = WSAStartup( MAKEWORD( 2, 2 ), &wsaData );
 52    if ( nResult != NO_ERROR )
 53    {
 54        fprintf( stderr, "WSAStartup() failed.\n" );
 55        return -1;
 56    }
 57#endif
 58
 59    struct UPNPDev* devlist;
 60    struct UPNPDev* dev;
 61    char* descXML;
 62    int descXMLsize = 0;
 63    int error = 0;
 64
 65    printf( "Portfwd::init()\n" );
 66    m_urls = (UPNPUrls*)malloc( sizeof( struct UPNPUrls ) );
 67    m_data = (IGDdatas*)malloc( sizeof( struct IGDdatas ) );
 68    memset( m_urls, 0, sizeof( struct UPNPUrls ) );
 69    memset( m_data, 0, sizeof( struct IGDdatas ) );
 70
 71    devlist = upnpDiscover( timeout, NULL, NULL, 0, 0, &error );
 72    if ( devlist )
 73    {
 74        dev = devlist;
 75        while ( dev )
 76        {
 77            printf( "descurl: %s\n", dev->descURL );
 78            
 79            bool blocked = false;
 80            std::list<std::string>::iterator it;
 81            for ( it = m_blockedips.begin(); it != m_blockedips.end(); ++it )
 82            {
 83                printf( "blocked ip: %s\n", it->c_str() );
 84
 85                if ( strstr( dev->descURL, it->c_str() ) )
 86                {
 87                    printf( "nope, we blocked this gateway: %s\n", dev->descURL );
 88                    blocked = true;
 89                }
 90            }
 91            if ( blocked )
 92            {
 93                dev = dev->pNext;
 94                continue;
 95            }
 96
 97            if ( strstr( dev->descURL, "InternetGatewayDevice" ) )
 98                break;
 99
100            dev = dev->pNext;
101        }
102        if ( !dev )
103            dev = devlist; /* defaulting to first device */
104
105        printf( "UPnP device:\n"
106                " desc: %s\n st: %s\n",
107                dev->descURL, dev->st );
108
109       descXML = (char*)miniwget( dev->descURL, &descXMLsize );
110       if ( descXML )
111       {
112           parserootdesc( descXML, descXMLsize, m_data );
113           free( descXML );
114           descXML = 0;
115
116           GetUPNPUrls( m_urls, m_data, dev->descURL );
117       }
118       else
119       {
120           printf( "couldn't get the UPnP device description XML (descXML is null)" );
121           freeUPNPDevlist( devlist );
122           return false;
123       }
124
125       // get lan IP:
126       char lanaddr[16];
127       int idg_was_found = UPNP_GetValidIGD( devlist, m_urls, m_data, (char*)&lanaddr, 16 );
128       if ( !idg_was_found )
129       {
130           printf( "NO IGD was found (function UPNP_GetValidIGD())" );
131           freeUPNPDevlist( devlist );
132           return false;
133       }
134       m_lanip = std::string( lanaddr );
135
136       freeUPNPDevlist( devlist );
137       get_status();
138       return true;
139   }
140
141   return false;
142}
143
144
145void
146Portfwd::get_status()
147{
148    // get connection speed
149    UPNP_GetLinkLayerMaxBitRates( m_urls->controlURL_CIF, m_data->CIF.servicetype, &m_downbps, &m_upbps );
150
151    // get external IP adress
152    char ip[16];
153    if ( 0 != UPNP_GetExternalIPAddress( m_urls->controlURL, m_data->first.servicetype, (char*)&ip ) )
154    {
155        m_externalip = ""; //failed
156    }
157    else
158    {
159        m_externalip = std::string( ip );
160    }
161}
162
163
164bool
165Portfwd::add( unsigned short port, unsigned short internal_port )
166{
167    char port_str[16], port_str_internal[16];
168    int r;
169
170    printf( "Portfwd::add (%s, %d)\n", m_lanip.c_str(), port );
171    if ( m_urls->controlURL[0] == '\0' )
172    {
173        printf( "Portfwd - the init was not done!\n" );
174        return false;
175    }
176
177    sprintf( port_str, "%d", port );
178    sprintf( port_str_internal, "%d", internal_port );
179
180    r = UPNP_AddPortMapping( m_urls->controlURL, m_data->first.servicetype, port_str, port_str_internal, m_lanip.c_str(), "tomahawk", "TCP", NULL, NULL );
181    if ( r != 0 )
182    {
183        printf( "AddPortMapping(%s, %s, %s) failed, code %d\n", port_str, port_str, m_lanip.c_str(), r );
184        return false;
185    }
186
187    return true;
188}
189
190
191bool
192Portfwd::remove( unsigned short port )
193{
194   char port_str[16];
195
196   printf( "Portfwd::remove(%d)\n", port );
197   if ( m_urls->controlURL[0] == '\0' )
198   {
199       printf( "Portfwd - the init was not done!\n" );
200       return false;
201   }
202
203   sprintf( port_str, "%d", port );
204   int r = UPNP_DeletePortMapping( m_urls->controlURL, m_data->first.servicetype, port_str, "TCP", NULL );
205   return r == 0;
206}
207
208
209void
210Portfwd::addBlockedDevice( const std::string& ip )
211{
212    printf( "adding blocked: %s\n", ip.c_str() );
213    m_blockedips.push_back( ip );
214}