Update Wiki URL
[amule.git] / src / UPnPBase.h
blob15caed3125d745da13de5819c1e53c21438feebd
1 //
2 // This file is part of the aMule Project.
3 //
4 // Copyright (c) 2004-2011 Marcelo Roberto Jimenez ( phoenix@amule.org )
5 // Copyright (c) 2006-2011 aMule Team ( admin@amule.org / http://www.amule.org )
6 //
7 // Any parts of this program derived from the xMule, lMule or eMule project,
8 // or contributed by third-party developers are copyrighted by their
9 // respective authors.
11 // This program is free software; you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation; either version 2 of the License, or
14 // (at your option) any later version.
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
21 // You should have received a copy of the GNU General Public License
22 // along with this program; if not, write to the Free Software
23 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 // This define must not conflict with the one in the standard header
28 #ifndef AMULE_UPNP_H
29 #define AMULE_UPNP_H
32 #include <map>
33 #include <string>
34 #include <sstream>
35 #include <memory>
37 #include "UPnPCompatibility.h"
39 extern std::string stdEmptyString;
42 /**
43 * Case insensitive std::string comparison
45 bool stdStringIsEqualCI(
46 const std::string &s1,
47 const std::string &s2);
50 class CUPnPPortMapping
52 private:
53 std::string m_port;
54 std::string m_protocol;
55 std::string m_enabled;
56 std::string m_description;
57 std::string m_key;
59 public:
60 CUPnPPortMapping(
61 int port = 0,
62 const std::string &protocol = stdEmptyString,
63 bool enabled = false,
64 const std::string &description = stdEmptyString);
65 ~CUPnPPortMapping() {}
67 const std::string &getPort() const
68 { return m_port; }
69 const std::string &getProtocol() const
70 { return m_protocol; }
71 const std::string &getEnabled() const
72 { return m_enabled; }
73 const std::string &getDescription() const
74 { return m_description; }
75 const std::string &getKey() const
76 { return m_key; }
80 class CUPnPControlPoint;
83 class CUPnPLib
85 public:
86 static const std::string &UPNP_ROOT_DEVICE;
87 static const std::string &UPNP_DEVICE_IGW;
88 static const std::string &UPNP_DEVICE_WAN;
89 static const std::string &UPNP_DEVICE_WAN_CONNECTION;
90 static const std::string &UPNP_DEVICE_LAN;
91 static const std::string &UPNP_SERVICE_LAYER3_FORWARDING;
92 static const std::string &UPNP_SERVICE_WAN_COMMON_INTERFACE_CONFIG;
93 static const std::string &UPNP_SERVICE_WAN_IP_CONNECTION;
94 static const std::string &UPNP_SERVICE_WAN_PPP_CONNECTION;
95 CUPnPControlPoint &m_ctrlPoint;
97 public:
98 CUPnPLib(CUPnPControlPoint &ctrlPoint);
99 ~CUPnPLib() {}
101 // Convenience function so we don't have to write explicit calls
102 // to char2unicode every time
103 std::string GetUPnPErrorMessage(int code) const;
105 // Convenience function to avoid repetitive processing of error
106 // messages
107 std::string processUPnPErrorMessage(
108 const std::string &messsage,
109 int code,
110 const DOMString errorString,
111 IXML_Document *doc) const;
113 // Processing response to actions
114 void ProcessActionResponse(
115 IXML_Document *RespDoc,
116 const std::string &actionName) const;
118 // IXML_Element
119 IXML_Element *Element_GetRootElement(
120 IXML_Document *doc) const;
121 IXML_Element *Element_GetFirstChild(
122 IXML_Element *parent) const;
123 IXML_Element *Element_GetNextSibling(
124 IXML_Element *child) const;
125 const DOMString Element_GetTag(
126 IXML_Element *element) const;
127 const std::string Element_GetTextValue(
128 IXML_Element *element) const;
129 const std::string Element_GetChildValueByTag(
130 IXML_Element *element,
131 const DOMString tag) const;
132 IXML_Element *Element_GetFirstChildByTag(
133 IXML_Element *element,
134 const DOMString tag) const;
135 IXML_Element *Element_GetNextSiblingByTag(
136 IXML_Element *element,
137 const DOMString tag) const;
138 const std::string Element_GetAttributeByTag(
139 IXML_Element *element,
140 const DOMString tag) const;
144 class CUPnPControlPoint;
147 * Even though we can retrieve the upnpLib handler from the upnpControlPoint,
148 * we must pass it separetly at this point, because the class CUPnPControlPoint
149 * must be declared after.
151 * CUPnPLib can only be removed from the constructor once we agree to link to
152 * UPnPLib explicitly, making this dlopen() stuff unnecessary.
154 template <typename T, char const *XML_ELEMENT_NAME, char const *XML_LIST_NAME>
155 class CXML_List : public std::map<const std::string, T *>
157 public:
158 CXML_List(
159 const CUPnPControlPoint &upnpControlPoint,
160 CUPnPLib &upnpLib,
161 IXML_Element *parent,
162 const std::string &url);
163 ~CXML_List();
167 template <typename T, char const *XML_ELEMENT_NAME, char const *XML_LIST_NAME>
168 CXML_List<T, XML_ELEMENT_NAME, XML_LIST_NAME>::CXML_List(
169 const CUPnPControlPoint &upnpControlPoint,
170 CUPnPLib &upnpLib,
171 IXML_Element *parent,
172 const std::string &url)
174 IXML_Element *elementList =
175 upnpLib.Element_GetFirstChildByTag(parent, XML_LIST_NAME);
176 unsigned int i = 0;
177 for ( IXML_Element *element = upnpLib.Element_GetFirstChildByTag(elementList, XML_ELEMENT_NAME);
178 element;
179 element = upnpLib.Element_GetNextSiblingByTag(element, XML_ELEMENT_NAME)) {
180 // Add a new element to the element list
181 T *upnpElement = new T(upnpControlPoint, upnpLib, element, url);
182 (*this)[upnpElement->GetKey()] = upnpElement;
183 ++i;
185 std::ostringstream msg;
186 msg << "\n " << XML_LIST_NAME << ": " <<
187 i << " " << XML_ELEMENT_NAME << "s.";
188 AddDebugLogLineN(logUPnP, msg);
192 template <typename T, char const *XML_ELEMENT_NAME, char const *XML_LIST_NAME>
193 CXML_List<T, XML_ELEMENT_NAME, XML_LIST_NAME>::~CXML_List()
195 typename CXML_List<T, XML_ELEMENT_NAME, XML_LIST_NAME>::iterator it;
196 for(it = this->begin(); it != this->end(); ++it) {
197 delete (*it).second;
201 extern const char s_argument[];
202 extern const char s_argumentList[];
203 extern const char s_action[];
204 extern const char s_actionList[];
205 extern const char s_allowedValue[];
206 extern const char s_allowedValueList[];
207 extern const char s_stateVariable[];
208 extern const char s_serviceStateTable[];
209 extern const char s_service[];
210 extern const char s_serviceList[];
211 extern const char s_device[];
212 extern const char s_deviceList[];
216 class CUPnPArgument;
217 typedef CXML_List<CUPnPArgument, s_argument, s_argumentList> ArgumentList;
218 class CUPnPAction;
219 typedef CXML_List<CUPnPAction, s_action, s_actionList> ActionList;
220 class CUPnPStateVariable;
221 typedef CXML_List<CUPnPStateVariable, s_stateVariable, s_serviceStateTable> ServiceStateTable;
222 class CUPnPAllowedValue;
223 typedef CXML_List<CUPnPAllowedValue, s_allowedValue, s_allowedValueList> AllowedValueList;
224 class CUPnPService;
225 typedef CXML_List<CUPnPService, s_service, s_serviceList> ServiceList;
226 class CUPnPDevice;
227 typedef CXML_List<CUPnPDevice, s_device, s_deviceList> DeviceList;
230 class CUPnPError
232 private:
233 IXML_Element *m_root;
234 const std::string m_ErrorCode;
235 const std::string m_ErrorDescription;
236 public:
237 CUPnPError(
238 const CUPnPLib &upnpLib,
239 IXML_Document *errorDoc);
240 ~CUPnPError() {}
241 const std::string &getErrorCode() const
242 { return m_ErrorCode; }
243 const std::string &getErrorDescription() const
244 { return m_ErrorDescription; }
248 class CUPnPArgument
250 private:
251 const CUPnPControlPoint &m_UPnPControlPoint;
252 const std::string m_name;
253 const std::string m_direction;
254 bool m_retval;
255 const std::string m_relatedStateVariable;
257 public:
258 CUPnPArgument(
259 const CUPnPControlPoint &upnpControlPoint,
260 CUPnPLib &upnpLib,
261 IXML_Element *argument,
262 const std::string &SCPDURL);
263 ~CUPnPArgument() {}
264 const std::string &GetName() const
265 { return m_name; }
266 const std::string &GetDirection() const
267 { return m_direction; }
268 bool GetRetVal() const
269 { return m_retval; }
270 const std::string &GetRelatedStateVariable() const
271 { return m_relatedStateVariable; }
272 const std::string &GetKey() const
273 { return m_name; }
278 class CUPnPAction
280 private:
281 const CUPnPControlPoint &m_UPnPControlPoint;
282 ArgumentList m_ArgumentList;
283 const std::string m_name;
285 public:
286 CUPnPAction(
287 const CUPnPControlPoint &upnpControlPoint,
288 CUPnPLib &upnpLib,
289 IXML_Element *action,
290 const std::string &SCPDURL);
291 ~CUPnPAction() {}
292 const std::string &GetName() const
293 { return m_name; }
294 const std::string &GetKey() const
295 { return m_name; }
296 const ArgumentList &GetArgumentList() const
297 { return m_ArgumentList; }
301 class CUPnPAllowedValue
303 private:
304 const CUPnPControlPoint &m_UPnPControlPoint;
305 const std::string m_allowedValue;
307 public:
308 CUPnPAllowedValue(
309 const CUPnPControlPoint &upnpControlPoint,
310 CUPnPLib &upnpLib,
311 IXML_Element *allowedValue,
312 const std::string &SCPDURL);
313 ~CUPnPAllowedValue() {}
314 const std::string &GetAllowedValue() const
315 { return m_allowedValue; }
316 const std::string &GetKey() const
317 { return m_allowedValue; }
321 class CUPnPStateVariable
323 private:
324 const CUPnPControlPoint &m_UPnPControlPoint;
325 AllowedValueList m_AllowedValueList;
326 const std::string m_name;
327 const std::string m_dataType;
328 const std::string m_defaultValue;
329 const std::string m_sendEvents;
331 public:
332 CUPnPStateVariable(
333 const CUPnPControlPoint &upnpControlPoint,
334 CUPnPLib &upnpLib,
335 IXML_Element *stateVariable,
336 const std::string &URLBase);
337 ~CUPnPStateVariable() {}
338 const std::string &GetNname() const
339 { return m_name; }
340 const std::string &GetDataType() const
341 { return m_dataType; }
342 const std::string &GetDefaultValue() const
343 { return m_defaultValue; }
344 const std::string &GetKey() const
345 { return m_name; }
346 const AllowedValueList &GetAllowedValueList() const
347 { return m_AllowedValueList; }
351 class CUPnPSCPD
353 private:
354 const CUPnPControlPoint &m_UPnPControlPoint;
355 ActionList m_ActionList;
356 ServiceStateTable m_ServiceStateTable;
357 const std::string m_SCPDURL;
359 public:
360 CUPnPSCPD(
361 const CUPnPControlPoint &upnpControlPoint,
362 CUPnPLib &upnpLib,
363 IXML_Element *scpd,
364 const std::string &SCPDURL);
365 ~CUPnPSCPD() {}
366 const ActionList &GetActionList() const
367 { return m_ActionList; }
368 const ServiceStateTable &GetServiceStateTable() const
369 { return m_ServiceStateTable; }
373 class CUPnPArgumentValue
375 private:
376 std::string m_argument;
377 std::string m_value;
379 public:
380 CUPnPArgumentValue();
381 CUPnPArgumentValue(const std::string &argument, const std::string &value);
382 ~CUPnPArgumentValue() {}
384 const std::string &GetArgument() const { return m_argument; }
385 const std::string &GetValue() const { return m_value; }
386 const std::string &SetArgument(const std::string& argument) { return m_argument = argument; }
387 const std::string &SetValue(const std::string &value) { return m_value = value; }
391 class CUPnPService
393 private:
394 const CUPnPControlPoint &m_UPnPControlPoint;
395 CUPnPLib &m_upnpLib;
396 const std::string m_serviceType;
397 const std::string m_serviceId;
398 const std::string m_SCPDURL;
399 const std::string m_controlURL;
400 const std::string m_eventSubURL;
401 std::string m_absSCPDURL;
402 std::string m_absControlURL;
403 std::string m_absEventSubURL;
404 int m_timeout;
405 Upnp_SID m_SID;
406 std::auto_ptr<CUPnPSCPD> m_SCPD;
408 public:
409 CUPnPService(
410 const CUPnPControlPoint &upnpControlPoint,
411 CUPnPLib &upnpLib,
412 IXML_Element *service,
413 const std::string &URLBase);
414 ~CUPnPService();
416 const std::string &GetServiceType() const
417 { return m_serviceType; }
418 const std::string &GetServiceId() const
419 { return m_serviceId; }
420 const std::string &GetSCPDURL() const
421 { return m_SCPDURL; }
422 const std::string &GetAbsSCPDURL() const
423 { return m_absSCPDURL; }
424 const std::string &GetControlURL() const
425 { return m_controlURL; }
426 const std::string &GetEventSubURL() const
427 { return m_eventSubURL; }
428 const std::string &GetAbsControlURL() const
429 { return m_absControlURL; }
430 const std::string &GetAbsEventSubURL() const
431 { return m_absEventSubURL; }
432 int GetTimeout() const
433 { return m_timeout; }
434 void SetTimeout(int t)
435 { m_timeout = t; }
436 int *GetTimeoutAddr()
437 { return &m_timeout; }
438 char *GetSID()
439 { return m_SID; }
440 void SetSID(const char *s)
441 { memcpy(m_SID, s, sizeof(Upnp_SID)); }
442 const std::string &GetKey() const
443 { return m_serviceId; }
444 bool IsSubscribed() const
445 { return m_SCPD.get() != NULL; }
446 void SetSCPD(CUPnPSCPD *SCPD)
447 { m_SCPD.reset(SCPD); }
449 bool Execute(
450 const std::string &ActionName,
451 const std::vector<CUPnPArgumentValue> &ArgValue) const;
452 const std::string GetStateVariable(
453 const std::string &stateVariableName) const;
457 class CUPnPDevice
459 private:
460 const CUPnPControlPoint &m_UPnPControlPoint;
462 // Please, lock these lists before use
463 DeviceList m_DeviceList;
464 ServiceList m_ServiceList;
466 const std::string m_deviceType;
467 const std::string m_friendlyName;
468 const std::string m_manufacturer;
469 const std::string m_manufacturerURL;
470 const std::string m_modelDescription;
471 const std::string m_modelName;
472 const std::string m_modelNumber;
473 const std::string m_modelURL;
474 const std::string m_serialNumber;
475 const std::string m_UDN;
476 const std::string m_UPC;
477 std::string m_presentationURL;
479 public:
480 CUPnPDevice(
481 const CUPnPControlPoint &upnpControlPoint,
482 CUPnPLib &upnpLib,
483 IXML_Element *device,
484 const std::string &URLBase);
485 ~CUPnPDevice() {}
487 const std::string &GetUDN() const
488 { return m_UDN; }
489 const std::string &GetDeviceType() const
490 { return m_deviceType; }
491 const std::string &GetFriendlyName() const
492 { return m_friendlyName; }
493 const std::string &GetPresentationURL() const
494 { return m_presentationURL; }
495 const std::string &GetKey() const
496 { return m_UDN; }
500 class CUPnPRootDevice : public CUPnPDevice
502 private:
503 const CUPnPControlPoint &m_UPnPControlPoint;
504 const std::string m_URLBase;
505 const std::string m_location;
506 int m_expires;
508 public:
509 CUPnPRootDevice(
510 const CUPnPControlPoint &upnpControlPoint,
511 CUPnPLib &upnpLib,
512 IXML_Element *rootDevice,
513 const std::string &OriginalURLBase,
514 const std::string &FixedURLBase,
515 const char *location,
516 int expires);
517 ~CUPnPRootDevice() {}
519 const std::string &GetURLBase() const
520 { return m_URLBase; }
521 const std::string &GetLocation() const
522 { return m_location; }
523 int GetExpires() const
524 { return m_expires; }
525 void SetExpires(int expires)
526 { m_expires = expires; }
530 typedef std::map<const std::string, CUPnPRootDevice *> RootDeviceMap;
531 typedef std::map<const std::string, CUPnPService *> ServiceMap;
532 typedef std::map<const std::string, CUPnPPortMapping> PortMappingMap;
535 class CUPnPControlPoint
537 private:
538 static CUPnPControlPoint *s_CtrlPoint;
539 // upnp stuff
540 CUPnPLib m_upnpLib;
541 UpnpClient_Handle m_UPnPClientHandle;
542 RootDeviceMap m_RootDeviceMap;
543 ServiceMap m_ServiceMap;
544 PortMappingMap m_ActivePortMappingsMap;
545 CUPnPMutex m_RootDeviceListMutex;
546 bool m_IGWDeviceDetected;
547 //#warning This variable is for testing purposes only and should disappear on release.
548 CUPnPService *m_WanService;
549 CUPnPMutex m_WaitForSearchTimeoutMutex;
551 public:
552 CUPnPControlPoint(unsigned short udpPort);
553 ~CUPnPControlPoint();
554 void Subscribe(CUPnPService &service);
555 void Unsubscribe(CUPnPService &service);
556 bool AddPortMappings(
557 std::vector<CUPnPPortMapping> &upnpPortMapping);
558 bool DeletePortMappings(
559 std::vector<CUPnPPortMapping> &upnpPortMapping);
561 UpnpClient_Handle GetUPnPClientHandle() const
562 { return m_UPnPClientHandle; }
564 bool GetIGWDeviceDetected() const
565 { return m_IGWDeviceDetected; }
566 void SetIGWDeviceDetected(bool b)
567 { m_IGWDeviceDetected = b; }
568 bool WanServiceDetected() const
569 { return !m_ServiceMap.empty(); }
570 void SetWanService(CUPnPService *service)
571 { m_WanService = service; }
573 // Callback function
574 static int Callback(
575 Upnp_EventType EventType,
576 void* Event,
577 void* Cookie);
579 private:
580 void OnEventReceived(
581 const std::string &Sid,
582 int EventKey,
583 IXML_Document *ChangedVariables);
584 void AddRootDevice(
585 IXML_Element *rootDevice,
586 const std::string &urlBase,
587 const char *location,
588 int expires);
589 void RemoveRootDevice(
590 const char *udn);
591 void RefreshPortMappings();
592 bool PrivateAddPortMapping(
593 CUPnPPortMapping &upnpPortMapping);
594 bool PrivateDeletePortMapping(
595 CUPnPPortMapping &upnpPortMapping);
599 #endif /* AMULE_UPNP_H */
601 // File_checked_for_headers