|
a/libupnpp/upnpplib.cxx |
|
b/libupnpp/upnpplib.cxx |
|
... |
|
... |
13 |
* along with this program; if not, write to the
|
13 |
* along with this program; if not, write to the
|
14 |
* Free Software Foundation, Inc.,
|
14 |
* Free Software Foundation, Inc.,
|
15 |
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
15 |
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
16 |
*/
|
16 |
*/
|
17 |
|
17 |
|
|
|
18 |
#include <string.h>
|
|
|
19 |
|
18 |
#include <string>
|
20 |
#include <string>
|
19 |
#include <iostream>
|
21 |
#include <iostream>
|
20 |
#include <sstream>
|
22 |
#include <sstream>
|
21 |
#include <map>
|
23 |
#include <map>
|
22 |
#include <vector>
|
24 |
#include <vector>
|
|
... |
|
... |
30 |
|
32 |
|
31 |
#include <upnp/ixml.h>
|
33 |
#include <upnp/ixml.h>
|
32 |
|
34 |
|
33 |
#include "upnpp_p.hxx"
|
35 |
#include "upnpp_p.hxx"
|
34 |
#include "upnpplib.hxx"
|
36 |
#include "upnpplib.hxx"
|
|
|
37 |
extern "C" {
|
|
|
38 |
#include "getsyshwaddr.h"
|
|
|
39 |
}
|
|
|
40 |
#include "md5.hxx"
|
35 |
|
41 |
|
36 |
static LibUPnP *theLib;
|
42 |
static LibUPnP *theLib;
|
37 |
|
43 |
|
38 |
LibUPnP *LibUPnP::getLibUPnP()
|
44 |
LibUPnP *LibUPnP::getLibUPnP(bool server)
|
39 |
{
|
45 |
{
|
40 |
if (theLib == 0)
|
46 |
if (theLib == 0)
|
41 |
theLib = new LibUPnP;
|
47 |
theLib = new LibUPnP(server);
|
42 |
if (theLib && !theLib->ok())
|
48 |
if (theLib && !theLib->ok())
|
43 |
return 0;
|
49 |
return 0;
|
44 |
return theLib;
|
50 |
return theLib;
|
45 |
}
|
51 |
}
|
46 |
|
52 |
|
47 |
LibUPnP::LibUPnP()
|
53 |
LibUPnP::LibUPnP(bool server)
|
48 |
: m_ok(false)
|
54 |
: m_ok(false)
|
49 |
{
|
55 |
{
|
50 |
m_init_error = UpnpInit(0, 0);
|
56 |
m_init_error = UpnpInit(0, 0);
|
51 |
if (m_init_error != UPNP_E_SUCCESS) {
|
57 |
if (m_init_error != UPNP_E_SUCCESS) {
|
52 |
cerr << errAsString("UpnpInit", m_init_error) << endl;
|
58 |
cerr << errAsString("UpnpInit", m_init_error) << endl;
|
53 |
return;
|
59 |
return;
|
54 |
}
|
60 |
}
|
55 |
setMaxContentLength(2000*1024);
|
61 |
setMaxContentLength(2000*1024);
|
|
|
62 |
|
56 |
#ifdef DEBUG
|
63 |
#ifdef DEBUG
|
|
|
64 |
const char *ip_address = UpnpGetServerIpAddress();
|
|
|
65 |
int port = UpnpGetServerPort();
|
|
|
66 |
cerr << "Using IP " << ip_address << " port " << port << endl;
|
57 |
UpnpCloseLog();
|
67 |
UpnpCloseLog();
|
58 |
#endif
|
68 |
#endif
|
59 |
m_init_error = UpnpRegisterClient(o_callback, (void *)this, &m_clh);
|
69 |
|
60 |
if (m_init_error == UPNP_E_SUCCESS) {
|
70 |
if (server) {
|
61 |
// cerr << "Initialized on " << UpnpGetServerIpAddress() <<
|
|
|
62 |
// "with cookie = " << this << endl;
|
|
|
63 |
m_ok = true;
|
71 |
m_ok = true;
|
64 |
} else {
|
72 |
} else {
|
|
|
73 |
// Client initialization is simple, just do it. Defer device init
|
|
|
74 |
// completion because it's more complicated.
|
|
|
75 |
m_init_error = UpnpRegisterClient(o_callback, (void *)this, &m_clh);
|
|
|
76 |
|
|
|
77 |
if (m_init_error == UPNP_E_SUCCESS) {
|
|
|
78 |
m_ok = true;
|
|
|
79 |
} else {
|
65 |
cerr << errAsString("UpnpRegisterClient", m_init_error);
|
80 |
cerr << errAsString("UpnpRegisterClient", m_init_error) << endl;
|
66 |
}
|
81 |
}
|
|
|
82 |
}
|
67 |
|
83 |
|
68 |
// Servers sometimes make error (e.g.: minidlna returns bad utf-8)
|
84 |
// Servers sometimes make error (e.g.: minidlna returns bad
|
|
|
85 |
// utf-8).
|
69 |
ixmlRelaxParser(1);
|
86 |
ixmlRelaxParser(1);
|
|
|
87 |
}
|
|
|
88 |
|
|
|
89 |
int LibUPnP::setupWebServer(const string& description)
|
|
|
90 |
{
|
|
|
91 |
//static const string description("/tmp/description.xml");
|
|
|
92 |
//m_init_error = UpnpSetWebServerRootDir("/tmp/root");
|
|
|
93 |
int res = UpnpRegisterRootDevice2(
|
|
|
94 |
UPNPREG_BUF_DESC,
|
|
|
95 |
description.c_str(),
|
|
|
96 |
description.size(), /* Desc filename len, ignored */
|
|
|
97 |
1, /* URLBase*/
|
|
|
98 |
o_callback, (void *)this, &m_dvh);
|
|
|
99 |
|
|
|
100 |
if (res != UPNP_E_SUCCESS) {
|
|
|
101 |
cerr << errAsString("UpnpRegisterRootDevice2", m_init_error) << endl;
|
|
|
102 |
}
|
|
|
103 |
return res;
|
70 |
}
|
104 |
}
|
71 |
|
105 |
|
72 |
void LibUPnP::setMaxContentLength(int bytes)
|
106 |
void LibUPnP::setMaxContentLength(int bytes)
|
73 |
{
|
107 |
{
|
74 |
UpnpSetMaxContentLength(bytes);
|
108 |
UpnpSetMaxContentLength(bytes);
|
|
... |
|
... |
137 |
if (error != UPNP_E_SUCCESS) {
|
171 |
if (error != UPNP_E_SUCCESS) {
|
138 |
PLOGINF("%s\n", errAsString("UpnpFinish", error).c_str());
|
172 |
PLOGINF("%s\n", errAsString("UpnpFinish", error).c_str());
|
139 |
}
|
173 |
}
|
140 |
PLOGDEB("LibUPnP: done\n");
|
174 |
PLOGDEB("LibUPnP: done\n");
|
141 |
}
|
175 |
}
|
|
|
176 |
|
|
|
177 |
string LibUPnP::makeDevUUID(const string& name)
|
|
|
178 |
{
|
|
|
179 |
string digest;
|
|
|
180 |
MD5String(name, digest);
|
|
|
181 |
// digest has 16 bytes of binary data. UUID is like:
|
|
|
182 |
// f81d4fae-7dec-11d0-a765-00a0c91e6bf6
|
|
|
183 |
// Where the last 12 chars are provided by the hw addr
|
|
|
184 |
|
|
|
185 |
char hw[20];
|
|
|
186 |
if (getsyshwaddr(hw, 13) < 0) {
|
|
|
187 |
cerr << "LibUPnP::makeDevUUID: failed retrieving hw addr" << endl;
|
|
|
188 |
strcpy(hw, "2e87682c5ce8");
|
|
|
189 |
}
|
|
|
190 |
char uuid[100];
|
|
|
191 |
sprintf(uuid, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%s",
|
|
|
192 |
digest[0]&0xff, digest[1]&0xff, digest[2]&0xff, digest[3]&0xff,
|
|
|
193 |
digest[4]&0xff, digest[5]&0xff, digest[6]&0xff, digest[7]&0xff,
|
|
|
194 |
digest[8]&0xff, digest[9]&0xff, hw);
|
|
|
195 |
return uuid;
|
|
|
196 |
}
|
|
|
197 |
|
142 |
|
198 |
|
143 |
string LibUPnP::evTypeAsString(Upnp_EventType et)
|
199 |
string LibUPnP::evTypeAsString(Upnp_EventType et)
|
144 |
{
|
200 |
{
|
145 |
switch (et) {
|
201 |
switch (et) {
|
146 |
case UPNP_CONTROL_ACTION_REQUEST: return "UPNP_CONTROL_ACTION_REQUEST";
|
202 |
case UPNP_CONTROL_ACTION_REQUEST: return "UPNP_CONTROL_ACTION_REQUEST";
|
|
... |
|
... |
220 |
return "./";
|
276 |
return "./";
|
221 |
|
277 |
|
222 |
father.erase(slp);
|
278 |
father.erase(slp);
|
223 |
path_catslash(father);
|
279 |
path_catslash(father);
|
224 |
return father;
|
280 |
return father;
|
|
|
281 |
}
|
|
|
282 |
string path_getsimple(const string &s) {
|
|
|
283 |
string simple = s;
|
|
|
284 |
|
|
|
285 |
if (simple.empty())
|
|
|
286 |
return simple;
|
|
|
287 |
|
|
|
288 |
string::size_type slp = simple.rfind('/');
|
|
|
289 |
if (slp == string::npos)
|
|
|
290 |
return simple;
|
|
|
291 |
|
|
|
292 |
simple.erase(0, slp+1);
|
|
|
293 |
return simple;
|
225 |
}
|
294 |
}
|
226 |
|
295 |
|
227 |
template <class T> bool csvToStrings(const string &s, T &tokens)
|
296 |
template <class T> bool csvToStrings(const string &s, T &tokens)
|
228 |
{
|
297 |
{
|
229 |
string current;
|
298 |
string current;
|