Upstream tarball 10153
[amule.git] / src / UPnPBase.h
blobba84cbd0dbb82a8ebf4b6c9ea53c787ccdc2de86
1 //
2 // This file is part of the aMule Project.
3 //
4 // Copyright (c) 2004-2008 Marcelo Roberto Jimenez ( phoenix@amule.org )
5 // Copyright (c) 2006-2008 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.
20 //
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"
40 #ifdef UPNP_C
41 std::string stdEmptyString;
42 #else // UPNP_C
43 extern std::string stdEmptyString;
44 #endif // UPNP_C
47 /**
48 * Case insensitive std::string comparison
50 bool stdStringIsEqualCI(
51 const std::string &s1,
52 const std::string &s2);
55 class CUPnPPortMapping
57 private:
58 std::string m_port;
59 std::string m_protocol;
60 std::string m_enabled;
61 std::string m_description;
62 std::string m_key;
64 public:
65 CUPnPPortMapping(
66 int port = 0,
67 const std::string &protocol = stdEmptyString,
68 bool enabled = false,
69 const std::string &description = stdEmptyString);
70 ~CUPnPPortMapping() {}
72 const std::string &getPort() const
73 { return m_port; }
74 const std::string &getProtocol() const
75 { return m_protocol; }
76 const std::string &getEnabled() const
77 { return m_enabled; }
78 const std::string &getDescription() const
79 { return m_description; }
80 const std::string &getKey() const
81 { return m_key; }
85 class CUPnPControlPoint;
88 class CUPnPLib
90 public:
91 static const std::string &UPNP_ROOT_DEVICE;
92 static const std::string &UPNP_DEVICE_IGW;
93 static const std::string &UPNP_DEVICE_WAN;
94 static const std::string &UPNP_DEVICE_WAN_CONNECTION;
95 static const std::string &UPNP_DEVICE_LAN;
96 static const std::string &UPNP_SERVICE_LAYER3_FORWARDING;
97 static const std::string &UPNP_SERVICE_WAN_COMMON_INTERFACE_CONFIG;
98 static const std::string &UPNP_SERVICE_WAN_IP_CONNECTION;
99 static const std::string &UPNP_SERVICE_WAN_PPP_CONNECTION;
100 CUPnPControlPoint &m_ctrlPoint;
102 public:
103 CUPnPLib(CUPnPControlPoint &ctrlPoint);
104 ~CUPnPLib() {}
106 // Convenience function so we don't have to write explicit calls
107 // to char2unicode every time
108 std::string GetUPnPErrorMessage(int code) const;
110 // Convenience function to avoid repetitive processing of error
111 // messages
112 std::string processUPnPErrorMessage(
113 const std::string &messsage,
114 int code,
115 const DOMString errorString,
116 IXML_Document *doc) const;
118 // Processing response to actions
119 void ProcessActionResponse(
120 IXML_Document *RespDoc,
121 const std::string &actionName) const;
123 // IXML_Element
124 IXML_Element *Element_GetRootElement(
125 IXML_Document *doc) const;
126 IXML_Element *Element_GetFirstChild(
127 IXML_Element *parent) const;
128 IXML_Element *Element_GetNextSibling(
129 IXML_Element *child) const;
130 const DOMString Element_GetTag(
131 IXML_Element *element) const;
132 const std::string Element_GetTextValue(
133 IXML_Element *element) const;
134 const std::string Element_GetChildValueByTag(
135 IXML_Element *element,
136 const DOMString tag) const;
137 IXML_Element *Element_GetFirstChildByTag(
138 IXML_Element *element,
139 const DOMString tag) const;
140 IXML_Element *Element_GetNextSiblingByTag(
141 IXML_Element *element,
142 const DOMString tag) const;
143 const std::string Element_GetAttributeByTag(
144 IXML_Element *element,
145 const DOMString tag) const;
149 class CUPnPControlPoint;
152 * Even though we can retrieve the upnpLib handler from the upnpControlPoint,
153 * we must pass it separetly at this point, because the class CUPnPControlPoint
154 * must be declared after.
156 * CUPnPLib can only be removed from the constructor once we agree to link to
157 * UPnPLib explicitly, making this dlopen() stuff unnecessary.
159 template <typename T, char const *XML_ELEMENT_NAME, char const *XML_LIST_NAME>
160 class CXML_List : public std::map<const std::string, T *>
162 public:
163 CXML_List(
164 const CUPnPControlPoint &upnpControlPoint,
165 CUPnPLib &upnpLib,
166 IXML_Element *parent,
167 const std::string &url);
168 ~CXML_List();
172 template <typename T, char const *XML_ELEMENT_NAME, char const *XML_LIST_NAME>
173 CXML_List<T, XML_ELEMENT_NAME, XML_LIST_NAME>::CXML_List(
174 const CUPnPControlPoint &upnpControlPoint,
175 CUPnPLib &upnpLib,
176 IXML_Element *parent,
177 const std::string &url)
179 IXML_Element *elementList =
180 upnpLib.Element_GetFirstChildByTag(parent, XML_LIST_NAME);
181 unsigned int i = 0;
182 for ( IXML_Element *element = upnpLib.Element_GetFirstChildByTag(elementList, XML_ELEMENT_NAME);
183 element;
184 element = upnpLib.Element_GetNextSiblingByTag(element, XML_ELEMENT_NAME)) {
185 // Add a new element to the element list
186 T *upnpElement = new T(upnpControlPoint, upnpLib, element, url);
187 (*this)[upnpElement->GetKey()] = upnpElement;
188 ++i;
190 std::ostringstream msg;
191 msg << "\n " << XML_LIST_NAME << ": " <<
192 i << " " << XML_ELEMENT_NAME << "s.";
193 AddDebugLogLineM(false, logUPnP, msg);
197 template <typename T, char const *XML_ELEMENT_NAME, char const *XML_LIST_NAME>
198 CXML_List<T, XML_ELEMENT_NAME, XML_LIST_NAME>::~CXML_List()
200 typename CXML_List<T, XML_ELEMENT_NAME, XML_LIST_NAME>::iterator it;
201 for(it = this->begin(); it != this->end(); ++it) {
202 delete (*it).second;
206 extern const char s_argument[];
207 extern const char s_argumentList[];
208 extern const char s_action[];
209 extern const char s_actionList[];
210 extern const char s_allowedValue[];
211 extern const char s_allowedValueList[];
212 extern const char s_stateVariable[];
213 extern const char s_serviceStateTable[];
214 extern const char s_service[];
215 extern const char s_serviceList[];
216 extern const char s_device[];
217 extern const char s_deviceList[];
219 #ifdef UPNP_C
220 const char s_argument[] = "argument";
221 const char s_argumentList[] = "argumentList";
222 const char s_action[] = "action";
223 const char s_actionList[] = "actionList";
224 const char s_allowedValue[] = "allowedValue";
225 const char s_allowedValueList[] = "allowedValueList";
226 const char s_stateVariable[] = "stateVariable";
227 const char s_serviceStateTable[] = "serviceStateTable";
228 const char s_service[] = "service";
229 const char s_serviceList[] = "serviceList";
230 const char s_device[] = "device";
231 const char s_deviceList[] = "deviceList";
232 #endif // UPNP_C
235 class CUPnPArgument;
236 typedef CXML_List<CUPnPArgument, s_argument, s_argumentList> ArgumentList;
237 class CUPnPAction;
238 typedef CXML_List<CUPnPAction, s_action, s_actionList> ActionList;
239 class CUPnPStateVariable;
240 typedef CXML_List<CUPnPStateVariable, s_stateVariable, s_serviceStateTable> ServiceStateTable;
241 class CUPnPAllowedValue;
242 typedef CXML_List<CUPnPAllowedValue, s_allowedValue, s_allowedValueList> AllowedValueList;
243 class CUPnPService;
244 typedef CXML_List<CUPnPService, s_service, s_serviceList> ServiceList;
245 class CUPnPDevice;
246 typedef CXML_List<CUPnPDevice, s_device, s_deviceList> DeviceList;
249 class CUPnPError
251 private:
252 IXML_Element *m_root;
253 const std::string m_ErrorCode;
254 const std::string m_ErrorDescription;
255 public:
256 CUPnPError(
257 const CUPnPLib &upnpLib,
258 IXML_Document *errorDoc);
259 ~CUPnPError() {}
260 const std::string &getErrorCode() const
261 { return m_ErrorCode; }
262 const std::string &getErrorDescription() const
263 { return m_ErrorDescription; }
267 class CUPnPArgument
269 private:
270 const CUPnPControlPoint &m_UPnPControlPoint;
271 const std::string m_name;
272 const std::string m_direction;
273 bool m_retval;
274 const std::string m_relatedStateVariable;
276 public:
277 CUPnPArgument(
278 const CUPnPControlPoint &upnpControlPoint,
279 CUPnPLib &upnpLib,
280 IXML_Element *argument,
281 const std::string &SCPDURL);
282 ~CUPnPArgument() {}
283 const std::string &GetName() const
284 { return m_name; }
285 const std::string &GetDirection() const
286 { return m_direction; }
287 bool GetRetVal() const
288 { return m_retval; }
289 const std::string &GetRelatedStateVariable() const
290 { return m_relatedStateVariable; }
291 const std::string &GetKey() const
292 { return m_name; }
297 class CUPnPAction
299 private:
300 const CUPnPControlPoint &m_UPnPControlPoint;
301 ArgumentList m_ArgumentList;
302 const std::string m_name;
304 public:
305 CUPnPAction(
306 const CUPnPControlPoint &upnpControlPoint,
307 CUPnPLib &upnpLib,
308 IXML_Element *action,
309 const std::string &SCPDURL);
310 ~CUPnPAction() {}
311 const std::string &GetName() const
312 { return m_name; }
313 const std::string &GetKey() const
314 { return m_name; }
315 const ArgumentList &GetArgumentList() const
316 { return m_ArgumentList; }
320 class CUPnPAllowedValue
322 private:
323 const CUPnPControlPoint &m_UPnPControlPoint;
324 const std::string m_allowedValue;
326 public:
327 CUPnPAllowedValue(
328 const CUPnPControlPoint &upnpControlPoint,
329 CUPnPLib &upnpLib,
330 IXML_Element *allowedValue,
331 const std::string &SCPDURL);
332 ~CUPnPAllowedValue() {}
333 const std::string &GetAllowedValue() const
334 { return m_allowedValue; }
335 const std::string &GetKey() const
336 { return m_allowedValue; }
340 class CUPnPStateVariable
342 private:
343 const CUPnPControlPoint &m_UPnPControlPoint;
344 AllowedValueList m_AllowedValueList;
345 const std::string m_name;
346 const std::string m_dataType;
347 const std::string m_defaultValue;
348 const std::string m_sendEvents;
350 public:
351 CUPnPStateVariable(
352 const CUPnPControlPoint &upnpControlPoint,
353 CUPnPLib &upnpLib,
354 IXML_Element *stateVariable,
355 const std::string &URLBase);
356 ~CUPnPStateVariable() {}
357 const std::string &GetNname() const
358 { return m_name; }
359 const std::string &GetDataType() const
360 { return m_dataType; }
361 const std::string &GetDefaultValue() const
362 { return m_defaultValue; }
363 const std::string &GetKey() const
364 { return m_name; }
365 const AllowedValueList &GetAllowedValueList() const
366 { return m_AllowedValueList; }
370 class CUPnPSCPD
372 private:
373 const CUPnPControlPoint &m_UPnPControlPoint;
374 ActionList m_ActionList;
375 ServiceStateTable m_ServiceStateTable;
376 const std::string m_SCPDURL;
378 public:
379 CUPnPSCPD(
380 const CUPnPControlPoint &upnpControlPoint,
381 CUPnPLib &upnpLib,
382 IXML_Element *scpd,
383 const std::string &SCPDURL);
384 ~CUPnPSCPD() {}
385 const ActionList &GetActionList() const
386 { return m_ActionList; }
387 const ServiceStateTable &GetServiceStateTable() const
388 { return m_ServiceStateTable; }
392 class CUPnPArgumentValue
394 private:
395 std::string m_argument;
396 std::string m_value;
398 public:
399 CUPnPArgumentValue();
400 CUPnPArgumentValue(const std::string &argument, const std::string &value);
401 ~CUPnPArgumentValue() {}
403 const std::string &GetArgument() const { return m_argument; }
404 const std::string &GetValue() const { return m_value; }
405 const std::string &SetArgument(const std::string& argument) { return m_argument = argument; }
406 const std::string &SetValue(const std::string &value) { return m_value = value; }
410 class CUPnPService
412 private:
413 const CUPnPControlPoint &m_UPnPControlPoint;
414 CUPnPLib &m_upnpLib;
415 const std::string m_serviceType;
416 const std::string m_serviceId;
417 const std::string m_SCPDURL;
418 const std::string m_controlURL;
419 const std::string m_eventSubURL;
420 std::string m_absSCPDURL;
421 std::string m_absControlURL;
422 std::string m_absEventSubURL;
423 int m_timeout;
424 Upnp_SID m_SID;
425 std::auto_ptr<CUPnPSCPD> m_SCPD;
427 public:
428 CUPnPService(
429 const CUPnPControlPoint &upnpControlPoint,
430 CUPnPLib &upnpLib,
431 IXML_Element *service,
432 const std::string &URLBase);
433 ~CUPnPService();
435 const std::string &GetServiceType() const
436 { return m_serviceType; }
437 const std::string &GetServiceId() const
438 { return m_serviceId; }
439 const std::string &GetSCPDURL() const
440 { return m_SCPDURL; }
441 const std::string &GetAbsSCPDURL() const
442 { return m_absSCPDURL; }
443 const std::string &GetControlURL() const
444 { return m_controlURL; }
445 const std::string &GetEventSubURL() const
446 { return m_eventSubURL; }
447 const std::string &GetAbsControlURL() const
448 { return m_absControlURL; }
449 const std::string &GetAbsEventSubURL() const
450 { return m_absEventSubURL; }
451 int GetTimeout() const
452 { return m_timeout; }
453 void SetTimeout(int t)
454 { m_timeout = t; }
455 int *GetTimeoutAddr()
456 { return &m_timeout; }
457 char *GetSID()
458 { return m_SID; }
459 void SetSID(const char *s)
460 { memcpy(m_SID, s, sizeof(Upnp_SID)); }
461 const std::string &GetKey() const
462 { return m_serviceId; }
463 bool IsSubscribed() const
464 { return m_SCPD.get() != NULL; }
465 void SetSCPD(CUPnPSCPD *SCPD)
466 { m_SCPD.reset(SCPD); }
468 bool Execute(
469 const std::string &ActionName,
470 const std::vector<CUPnPArgumentValue> &ArgValue) const;
471 const std::string GetStateVariable(
472 const std::string &stateVariableName) const;
476 class CUPnPDevice
478 private:
479 const CUPnPControlPoint &m_UPnPControlPoint;
481 // Please, lock these lists before use
482 DeviceList m_DeviceList;
483 ServiceList m_ServiceList;
485 const std::string m_deviceType;
486 const std::string m_friendlyName;
487 const std::string m_manufacturer;
488 const std::string m_manufacturerURL;
489 const std::string m_modelDescription;
490 const std::string m_modelName;
491 const std::string m_modelNumber;
492 const std::string m_modelURL;
493 const std::string m_serialNumber;
494 const std::string m_UDN;
495 const std::string m_UPC;
496 std::string m_presentationURL;
498 public:
499 CUPnPDevice(
500 const CUPnPControlPoint &upnpControlPoint,
501 CUPnPLib &upnpLib,
502 IXML_Element *device,
503 const std::string &URLBase);
504 ~CUPnPDevice() {}
506 const std::string &GetUDN() const
507 { return m_UDN; }
508 const std::string &GetDeviceType() const
509 { return m_deviceType; }
510 const std::string &GetFriendlyName() const
511 { return m_friendlyName; }
512 const std::string &GetPresentationURL() const
513 { return m_presentationURL; }
514 const std::string &GetKey() const
515 { return m_UDN; }
519 class CUPnPRootDevice : public CUPnPDevice
521 private:
522 const CUPnPControlPoint &m_UPnPControlPoint;
523 const std::string m_URLBase;
524 const std::string m_location;
525 int m_expires;
527 public:
528 CUPnPRootDevice(
529 const CUPnPControlPoint &upnpControlPoint,
530 CUPnPLib &upnpLib,
531 IXML_Element *rootDevice,
532 const std::string &OriginalURLBase,
533 const std::string &FixedURLBase,
534 const char *location,
535 int expires);
536 ~CUPnPRootDevice() {}
538 const std::string &GetURLBase() const
539 { return m_URLBase; }
540 const std::string &GetLocation() const
541 { return m_location; }
542 int GetExpires() const
543 { return m_expires; }
544 void SetExpires(int expires)
545 { m_expires = expires; }
549 typedef std::map<const std::string, CUPnPRootDevice *> RootDeviceMap;
550 typedef std::map<const std::string, CUPnPService *> ServiceMap;
551 typedef std::map<const std::string, CUPnPPortMapping> PortMappingMap;
554 class CUPnPControlPoint
556 private:
557 static CUPnPControlPoint *s_CtrlPoint;
558 // upnp stuff
559 CUPnPLib m_upnpLib;
560 UpnpClient_Handle m_UPnPClientHandle;
561 RootDeviceMap m_RootDeviceMap;
562 ServiceMap m_ServiceMap;
563 PortMappingMap m_ActivePortMappingsMap;
564 CUPnPMutex m_RootDeviceListMutex;
565 bool m_IGWDeviceDetected;
566 //#warning This variable is for testing purposes only and should disappear on release.
567 CUPnPService *m_WanService;
568 CUPnPMutex m_WaitForSearchTimeoutMutex;
570 public:
571 CUPnPControlPoint(unsigned short udpPort);
572 ~CUPnPControlPoint();
573 void Subscribe(CUPnPService &service);
574 void Unsubscribe(CUPnPService &service);
575 bool AddPortMappings(
576 std::vector<CUPnPPortMapping> &upnpPortMapping);
577 bool DeletePortMappings(
578 std::vector<CUPnPPortMapping> &upnpPortMapping);
580 UpnpClient_Handle GetUPnPClientHandle() const
581 { return m_UPnPClientHandle; }
583 bool GetIGWDeviceDetected() const
584 { return m_IGWDeviceDetected; }
585 void SetIGWDeviceDetected(bool b)
586 { m_IGWDeviceDetected = b; }
587 bool WanServiceDetected() const
588 { return !m_ServiceMap.empty(); }
589 void SetWanService(CUPnPService *service)
590 { m_WanService = service; }
592 // Callback function
593 static int Callback(
594 Upnp_EventType EventType,
595 void* Event,
596 void* Cookie);
598 private:
599 void OnEventReceived(
600 const std::string &Sid,
601 int EventKey,
602 IXML_Document *ChangedVariables);
603 void AddRootDevice(
604 IXML_Element *rootDevice,
605 const std::string &urlBase,
606 const char *location,
607 int expires);
608 void RemoveRootDevice(
609 const char *udn);
610 void RefreshPortMappings();
611 bool PrivateAddPortMapping(
612 CUPnPPortMapping &upnpPortMapping);
613 bool PrivateDeletePortMapping(
614 CUPnPPortMapping &upnpPortMapping);
618 #endif /* AMULE_UPNP_H */
620 // File_checked_for_headers