~ubuntu-branches/ubuntu/maverick/libtorrent-rasterbar/maverick

« back to all changes in this revision

Viewing changes to test/test_upnp.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Christophe Sauthier
  • Date: 2010-08-10 12:59:37 UTC
  • mfrom: (1.3.7 upstream)
  • Revision ID: james.westby@ubuntu.com-20100810125937-jbcmmf17y8yo9hgz
Tags: 0.15.0-0ubuntu1
* New upstream version.
* debian/patches/100_fix_html_docs.patch: refreshed.
* debian/control: bump up standards-version to 3.9.1 (no changes).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 
 
3
Copyright (c) 2008, Arvid Norberg
 
4
All rights reserved.
 
5
 
 
6
Redistribution and use in source and binary forms, with or without
 
7
modification, are permitted provided that the following conditions
 
8
are met:
 
9
 
 
10
    * Redistributions of source code must retain the above copyright
 
11
      notice, this list of conditions and the following disclaimer.
 
12
    * Redistributions in binary form must reproduce the above copyright
 
13
      notice, this list of conditions and the following disclaimer in
 
14
      the documentation and/or other materials provided with the distribution.
 
15
    * Neither the name of the author nor the names of its
 
16
      contributors may be used to endorse or promote products derived
 
17
      from this software without specific prior written permission.
 
18
 
 
19
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 
20
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
21
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
22
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 
23
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 
24
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 
25
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 
26
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 
27
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 
28
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 
29
POSSIBILITY OF SUCH DAMAGE.
 
30
 
 
31
*/
 
32
 
 
33
#include "libtorrent/upnp.hpp"
 
34
#include "libtorrent/socket.hpp"
 
35
#include "libtorrent/connection_queue.hpp"
 
36
#include "test.hpp"
 
37
#include "setup_transfer.hpp"
 
38
#include <fstream>
 
39
#include <boost/bind.hpp>
 
40
#include <boost/ref.hpp>
 
41
#include <boost/intrusive_ptr.hpp>
 
42
 
 
43
using namespace libtorrent;
 
44
 
 
45
broadcast_socket* sock = 0;
 
46
int g_port = 0;
 
47
 
 
48
char upnp_xml[] = 
 
49
"<root>"
 
50
"<specVersion>"
 
51
"<major>1</major>"
 
52
"<minor>0</minor>"
 
53
"</specVersion>"
 
54
"<URLBase>http://127.0.0.1:%d</URLBase>"
 
55
"<device>"
 
56
"<deviceType>"
 
57
"urn:schemas-upnp-org:device:InternetGatewayDevice:1"
 
58
"</deviceType>"
 
59
"<presentationURL>http://192.168.0.1:80</presentationURL>"
 
60
"<friendlyName>D-Link Router</friendlyName>"
 
61
"<manufacturer>D-Link</manufacturer>"
 
62
"<manufacturerURL>http://www.dlink.com</manufacturerURL>"
 
63
"<modelDescription>Internet Access Router</modelDescription>"
 
64
"<modelName>D-Link Router</modelName>"
 
65
"<UDN>uuid:upnp-InternetGatewayDevice-1_0-12345678900001</UDN>"
 
66
"<UPC>123456789001</UPC>"
 
67
"<serviceList>"
 
68
"<service>"
 
69
"<serviceType>urn:schemas-upnp-org:service:Layer3Forwarding:1</serviceType>"
 
70
"<serviceId>urn:upnp-org:serviceId:L3Forwarding1</serviceId>"
 
71
"<controlURL>/Layer3Forwarding</controlURL>"
 
72
"<eventSubURL>/Layer3Forwarding</eventSubURL>"
 
73
"<SCPDURL>/Layer3Forwarding.xml</SCPDURL>"
 
74
"</service>"
 
75
"</serviceList>"
 
76
"<deviceList>"
 
77
"<device>"
 
78
"<deviceType>urn:schemas-upnp-org:device:WANDevice:1</deviceType>"
 
79
"<friendlyName>WANDevice</friendlyName>"
 
80
"<manufacturer>D-Link</manufacturer>"
 
81
"<manufacturerURL>http://www.dlink.com</manufacturerURL>"
 
82
"<modelDescription>Internet Access Router</modelDescription>"
 
83
"<modelName>D-Link Router</modelName>"
 
84
"<modelNumber>1</modelNumber>"
 
85
"<modelURL>http://support.dlink.com</modelURL>"
 
86
"<serialNumber>12345678900001</serialNumber>"
 
87
"<UDN>uuid:upnp-WANDevice-1_0-12345678900001</UDN>"
 
88
"<UPC>123456789001</UPC>"
 
89
"<serviceList>"
 
90
"<service>"
 
91
"<serviceType>"
 
92
"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1"
 
93
"</serviceType>"
 
94
"<serviceId>urn:upnp-org:serviceId:WANCommonInterfaceConfig</serviceId>"
 
95
"<controlURL>/WANCommonInterfaceConfig</controlURL>"
 
96
"<eventSubURL>/WANCommonInterfaceConfig</eventSubURL>"
 
97
"<SCPDURL>/WANCommonInterfaceConfig.xml</SCPDURL>"
 
98
"</service>"
 
99
"</serviceList>"
 
100
"<deviceList>"
 
101
"<device>"
 
102
"<deviceType>urn:schemas-upnp-org:device:WANConnectionDevice:1</deviceType>"
 
103
"<friendlyName>WAN Connection Device</friendlyName>"
 
104
"<manufacturer>D-Link</manufacturer>"
 
105
"<manufacturerURL>http://www.dlink.com</manufacturerURL>"
 
106
"<modelDescription>Internet Access Router</modelDescription>"
 
107
"<modelName>D-Link Router</modelName>"
 
108
"<modelNumber>1</modelNumber>"
 
109
"<modelURL>http://support.dlink.com</modelURL>"
 
110
"<serialNumber>12345678900001</serialNumber>"
 
111
"<UDN>uuid:upnp-WANConnectionDevice-1_0-12345678900001</UDN>"
 
112
"<UPC>123456789001</UPC>"
 
113
"<serviceList>"
 
114
"<service>"
 
115
"<serviceType>urn:schemas-upnp-org:service:WANIPConnection:1</serviceType>"
 
116
"<serviceId>urn:upnp-org:serviceId:WANIPConnection</serviceId>"
 
117
"<controlURL>/WANIPConnection</controlURL>"
 
118
"<eventSubURL>/WANIPConnection</eventSubURL>"
 
119
"<SCPDURL>/WANIPConnection.xml</SCPDURL>"
 
120
"</service>"
 
121
"</serviceList>"
 
122
"</device>"
 
123
"</deviceList>"
 
124
"</device>"
 
125
"</deviceList>"
 
126
"</device>"
 
127
"</root>";
 
128
 
 
129
char soap_add_response[] =
 
130
        "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" "
 
131
        "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
 
132
        "<s:Body><u:AddPortMapping xmlns:u=\"urn:schemas-upnp-org:service:WANIPConnection:1\">"
 
133
        "</u:AddPortMapping></s:Body></s:Envelope>";
 
134
 
 
135
char soap_delete_response[] =
 
136
        "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" "
 
137
        "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
 
138
        "<s:Body><u:DeletePortMapping xmlns:u=\"urn:schemas-upnp-org:service:WANIPConnection:1\">"
 
139
        "</u:DeletePortMapping></s:Body></s:Envelope>";
 
140
 
 
141
void incoming_msearch(udp::endpoint const& from, char* buffer
 
142
        , int size)
 
143
{
 
144
        http_parser p;
 
145
        bool error = false;
 
146
        p.incoming(buffer::const_interval(buffer, buffer + size), error);
 
147
        if (error || !p.header_finished())
 
148
        {
 
149
                std::cerr << "*** malformed HTTP from " << from << std::endl;
 
150
                return;
 
151
        }
 
152
 
 
153
        if (p.method() != "m-search") return;
 
154
 
 
155
        std::cerr << "< incoming m-search from " << from << std::endl;
 
156
 
 
157
        char msg[] = "HTTP/1.1 200 OK\r\n"
 
158
                "ST:upnp:rootdevice\r\n"
 
159
                "USN:uuid:000f-66d6-7296000099dc::upnp:rootdevice\r\n"
 
160
                "Location: http://127.0.0.1:%d/upnp.xml\r\n"
 
161
                "Server: Custom/1.0 UPnP/1.0 Proc/Ver\r\n"
 
162
                "EXT:\r\n"
 
163
                "Cache-Control:max-age=180\r\n"
 
164
                "DATE: Fri, 02 Jan 1970 08:10:38 GMT\r\n\r\n";
 
165
 
 
166
        TORRENT_ASSERT(g_port != 0);
 
167
        char buf[sizeof(msg) + 30];
 
168
        int len = snprintf(buf, sizeof(buf), msg, g_port);
 
169
 
 
170
        error_code ec;
 
171
        sock->send(buf, len, ec);
 
172
 
 
173
        if (ec) std::cerr << "*** error sending " << ec.message() << std::endl;
 
174
}
 
175
 
 
176
void log_callback(char const* err)
 
177
{
 
178
        std::cerr << "UPnP: " << err << std::endl;
 
179
        //TODO: store the log and verify that some key messages are there
 
180
}
 
181
 
 
182
struct callback_info
 
183
{
 
184
        int mapping;
 
185
        int port;
 
186
        error_code ec;
 
187
        bool operator==(callback_info const& e)
 
188
        { return mapping == e.mapping && port == e.port && !ec == !e.ec; }
 
189
};
 
190
 
 
191
std::list<callback_info> callbacks;
 
192
 
 
193
void callback(int mapping, int port, error_code const& err)
 
194
{
 
195
        callback_info info = {mapping, port, err};
 
196
        callbacks.push_back(info);
 
197
        std::cerr << "mapping: " << mapping << ", port: " << port
 
198
                << ", error: \"" << err.message() << "\"\n";
 
199
        //TODO: store the callbacks and verify that the ports were successful
 
200
}
 
201
 
 
202
int test_main()
 
203
{
 
204
        libtorrent::io_service ios;
 
205
        
 
206
        g_port = start_web_server();
 
207
        FILE* xml_file = fopen("upnp.xml", "w+");
 
208
        fprintf(xml_file, upnp_xml, g_port);
 
209
        fclose(xml_file);
 
210
 
 
211
        std::ofstream xml("WANIPConnection", std::ios::trunc);
 
212
        xml.write(soap_add_response, sizeof(soap_add_response)-1);
 
213
        xml.close();
 
214
 
 
215
        sock = new broadcast_socket(ios, udp::endpoint(address_v4::from_string("239.255.255.250"), 1900)
 
216
                , &incoming_msearch);
 
217
 
 
218
        std::string user_agent = "test agent";
 
219
 
 
220
        connection_queue cc(ios);
 
221
        boost::intrusive_ptr<upnp> upnp_handler = new upnp(ios, cc, address_v4::from_string("127.0.0.1")
 
222
                , user_agent, &callback, &log_callback, false);
 
223
        upnp_handler->discover_device();
 
224
 
 
225
        libtorrent::deadline_timer timer(ios);
 
226
        error_code ec;
 
227
        timer.expires_from_now(seconds(10), ec);
 
228
        timer.async_wait(boost::bind(&libtorrent::io_service::stop, boost::ref(ios)));
 
229
 
 
230
        ios.reset();
 
231
        ios.run(ec);
 
232
 
 
233
        int mapping1 = upnp_handler->add_mapping(upnp::tcp, 500, 500);
 
234
        int mapping2 = upnp_handler->add_mapping(upnp::udp, 501, 501);
 
235
        timer.expires_from_now(seconds(10), ec);
 
236
        timer.async_wait(boost::bind(&libtorrent::io_service::stop, boost::ref(ios)));
 
237
 
 
238
        ios.reset();
 
239
        ios.run(ec);
 
240
 
 
241
        xml.open("WANIPConnection", std::ios::trunc);
 
242
        xml.write(soap_delete_response, sizeof(soap_delete_response)-1);
 
243
        xml.close();
 
244
 
 
245
        std::cerr << "router: " << upnp_handler->router_model() << std::endl;
 
246
        TEST_CHECK(upnp_handler->router_model() == "D-Link Router");
 
247
        upnp_handler->close();
 
248
        sock->close();
 
249
 
 
250
        ios.reset();
 
251
        ios.run(ec);
 
252
 
 
253
        callback_info expected1 = {mapping1, 500, error_code()};
 
254
        callback_info expected2 = {mapping2, 501, error_code()};
 
255
        TEST_CHECK(std::count(callbacks.begin(), callbacks.end(), expected1) == 1);
 
256
        TEST_CHECK(std::count(callbacks.begin(), callbacks.end(), expected2) == 1);
 
257
 
 
258
        stop_web_server();
 
259
 
 
260
        delete sock;
 
261
        return 0;
 
262
}
 
263
 
 
264