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. 10 // 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. 15 // 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 24 // 25 26 27 // This define must not conflict with the one in the standard header 28 #ifndef AMULE_UPNP_H 29 #define AMULE_UPNP_H 30 31 32 #include <map> 33 #include <string> 34 #include <sstream> 35 36 #include "UPnPCompatibility.h" 37 38 #include <common/SmartPtr.h> // Needed for CSmartPtr 39 40 41 extern std::string stdEmptyString; 42 43 44 class CUPnPPortMapping 45 { 46 private: 47 std::string m_port; 48 std::string m_protocol; 49 std::string m_enabled; 50 std::string m_description; 51 std::string m_key; 52 53 public: 54 CUPnPPortMapping( 55 int port = 0, 56 const std::string &protocol = stdEmptyString, 57 bool enabled = false, 58 const std::string &description = stdEmptyString); 59 ~CUPnPPortMapping() {} 60 61 const std::string &getPort() const 62 { return m_port; } 63 const std::string &getProtocol() const 64 { return m_protocol; } 65 const std::string &getEnabled() const 66 { return m_enabled; } 67 const std::string &getDescription() const 68 { return m_description; } 69 const std::string &getKey() const 70 { return m_key; } 71 }; 72 73 74 namespace IXML 75 { 76 namespace Document { 77 IXML_Element *GetRootElement(IXML_Document *doc); 78 void Free(IXML_Document *doc); 79 } 80 81 namespace Element { 82 IXML_Element *GetFirstChild(IXML_Element *parent); 83 IXML_Element *GetNextSibling(IXML_Element *child); 84 const DOMString GetTag(IXML_Element *element); 85 const std::string GetTextValue(IXML_Element *element); 86 const std::string GetChildValueByTag(IXML_Element *element, const DOMString tag); 87 IXML_Element *GetFirstChildByTag(IXML_Element *element, const DOMString tag); 88 IXML_Element *GetNextSiblingByTag(IXML_Element *element, const DOMString tag); 89 const std::string GetAttributeByTag(IXML_Element *element, const DOMString tag); 90 } 91 } 92 93 94 class CUPnPControlPoint; 95 96 template <typename T, char const *XML_ELEMENT_NAME, char const *XML_LIST_NAME> 97 class CXML_List : public std::map<const std::string, T *> 98 { 99 public: 100 CXML_List( 101 const CUPnPControlPoint &upnpControlPoint, 102 IXML_Element *parent, 103 const std::string &url); 104 ~CXML_List(); 105 }; 106 107 108 template <typename T, char const *XML_ELEMENT_NAME, char const *XML_LIST_NAME> 109 CXML_List<T, XML_ELEMENT_NAME, XML_LIST_NAME>::CXML_List( 110 const CUPnPControlPoint &upnpControlPoint, 111 IXML_Element *parent, 112 const std::string &url) 113 { 114 IXML_Element *elementList = IXML::Element::GetFirstChildByTag(parent, XML_LIST_NAME); 115 unsigned int i = 0; 116 for ( IXML_Element *element = IXML::Element::GetFirstChildByTag(elementList, XML_ELEMENT_NAME); 117 element; 118 element = IXML::Element::GetNextSiblingByTag(element, XML_ELEMENT_NAME)) { 119 // Add a new element to the element list 120 T *upnpElement = new T(upnpControlPoint, element, url); 121 (*this)[upnpElement->GetKey()] = upnpElement; 122 ++i; 123 } 124 std::ostringstream msg; 125 msg << "\n " << XML_LIST_NAME << ": " << 126 i << " " << XML_ELEMENT_NAME << "s."; 127 AddDebugLogLineN(logUPnP, msg); 128 } 129 130 131 template <typename T, char const *XML_ELEMENT_NAME, char const *XML_LIST_NAME> 132 CXML_List<T, XML_ELEMENT_NAME, XML_LIST_NAME>::~CXML_List() 133 { 134 typename CXML_List<T, XML_ELEMENT_NAME, XML_LIST_NAME>::iterator it; 135 for(it = this->begin(); it != this->end(); ++it) { 136 delete (*it).second; 137 } 138 } 139 140 extern const char s_argument[]; 141 extern const char s_argumentList[]; 142 extern const char s_action[]; 143 extern const char s_actionList[]; 144 extern const char s_allowedValue[]; 145 extern const char s_allowedValueList[]; 146 extern const char s_stateVariable[]; 147 extern const char s_serviceStateTable[]; 148 extern const char s_service[]; 149 extern const char s_serviceList[]; 150 extern const char s_device[]; 151 extern const char s_deviceList[]; 152 153 154 155 class CUPnPArgument; 156 typedef CXML_List<CUPnPArgument, s_argument, s_argumentList> ArgumentList; 157 class CUPnPAction; 158 typedef CXML_List<CUPnPAction, s_action, s_actionList> ActionList; 159 class CUPnPStateVariable; 160 typedef CXML_List<CUPnPStateVariable, s_stateVariable, s_serviceStateTable> ServiceStateTable; 161 class CUPnPAllowedValue; 162 typedef CXML_List<CUPnPAllowedValue, s_allowedValue, s_allowedValueList> AllowedValueList; 163 class CUPnPService; 164 typedef CXML_List<CUPnPService, s_service, s_serviceList> ServiceList; 165 class CUPnPDevice; 166 typedef CXML_List<CUPnPDevice, s_device, s_deviceList> DeviceList; 167 168 169 class CUPnPError 170 { 171 private: 172 IXML_Element *m_root; 173 const std::string m_ErrorCode; 174 const std::string m_ErrorDescription; 175 public: 176 CUPnPError(IXML_Document *errorDoc); 177 ~CUPnPError() {} 178 const std::string &getErrorCode() const 179 { return m_ErrorCode; } 180 const std::string &getErrorDescription() const 181 { return m_ErrorDescription; } 182 }; 183 184 185 class CUPnPArgument 186 { 187 private: 188 const std::string m_name; 189 const std::string m_direction; 190 bool m_retval; 191 const std::string m_relatedStateVariable; 192 193 public: 194 CUPnPArgument( 195 const CUPnPControlPoint &upnpControlPoint, 196 IXML_Element *argument, 197 const std::string &SCPDURL); 198 ~CUPnPArgument() {} 199 const std::string &GetName() const 200 { return m_name; } 201 const std::string &GetDirection() const 202 { return m_direction; } 203 bool GetRetVal() const 204 { return m_retval; } 205 const std::string &GetRelatedStateVariable() const 206 { return m_relatedStateVariable; } 207 const std::string &GetKey() const 208 { return m_name; } 209 }; 210 211 212 213 class CUPnPAction 214 { 215 private: 216 ArgumentList m_ArgumentList; 217 const std::string m_name; 218 219 public: 220 CUPnPAction( 221 const CUPnPControlPoint &upnpControlPoint, 222 IXML_Element *action, 223 const std::string &SCPDURL); 224 ~CUPnPAction() {} 225 const std::string &GetName() const 226 { return m_name; } 227 const std::string &GetKey() const 228 { return m_name; } 229 const ArgumentList &GetArgumentList() const 230 { return m_ArgumentList; } 231 }; 232 233 234 class CUPnPAllowedValue 235 { 236 private: 237 const std::string m_allowedValue; 238 239 public: 240 CUPnPAllowedValue( 241 const CUPnPControlPoint &upnpControlPoint, 242 IXML_Element *allowedValue, 243 const std::string &SCPDURL); 244 ~CUPnPAllowedValue() {} 245 const std::string &GetAllowedValue() const 246 { return m_allowedValue; } 247 const std::string &GetKey() const 248 { return m_allowedValue; } 249 }; 250 251 252 class CUPnPStateVariable 253 { 254 private: 255 AllowedValueList m_AllowedValueList; 256 const std::string m_name; 257 const std::string m_dataType; 258 const std::string m_defaultValue; 259 const std::string m_sendEvents; 260 261 public: 262 CUPnPStateVariable( 263 const CUPnPControlPoint &upnpControlPoint, 264 IXML_Element *stateVariable, 265 const std::string &URLBase); 266 ~CUPnPStateVariable() {} 267 const std::string &GetNname() const 268 { return m_name; } 269 const std::string &GetDataType() const 270 { return m_dataType; } 271 const std::string &GetDefaultValue() const 272 { return m_defaultValue; } 273 const std::string &GetKey() const 274 { return m_name; } 275 const AllowedValueList &GetAllowedValueList() const 276 { return m_AllowedValueList; } 277 }; 278 279 280 class CUPnPSCPD 281 { 282 private: 283 ActionList m_ActionList; 284 ServiceStateTable m_ServiceStateTable; 285 const std::string m_SCPDURL; 286 287 public: 288 CUPnPSCPD( 289 const CUPnPControlPoint &upnpControlPoint, 290 IXML_Element *scpd, 291 const std::string &SCPDURL); 292 ~CUPnPSCPD() {} 293 const ActionList &GetActionList() const 294 { return m_ActionList; } 295 const ServiceStateTable &GetServiceStateTable() const 296 { return m_ServiceStateTable; } 297 }; 298 299 300 class CUPnPArgumentValue 301 { 302 private: 303 std::string m_argument; 304 std::string m_value; 305 306 public: 307 CUPnPArgumentValue(); 308 CUPnPArgumentValue(const std::string &argument, const std::string &value); 309 ~CUPnPArgumentValue() {} 310 311 const std::string &GetArgument() const { return m_argument; } 312 const std::string &GetValue() const { return m_value; } 313 const std::string &SetArgument(const std::string& argument) { return m_argument = argument; } 314 const std::string &SetValue(const std::string &value) { return m_value = value; } 315 }; 316 317 318 class CUPnPService 319 { 320 private: 321 const CUPnPControlPoint &m_UPnPControlPoint; 322 const std::string m_serviceType; 323 const std::string m_serviceId; 324 const std::string m_SCPDURL; 325 const std::string m_controlURL; 326 const std::string m_eventSubURL; 327 std::string m_absSCPDURL; 328 std::string m_absControlURL; 329 std::string m_absEventSubURL; 330 int m_timeout; 331 Upnp_SID m_SID; 332 CSmartPtr<CUPnPSCPD> m_SCPD; 333 334 public: 335 CUPnPService( 336 const CUPnPControlPoint &upnpControlPoint, 337 IXML_Element *service, 338 const std::string &URLBase); 339 ~CUPnPService(); 340 341 const std::string &GetServiceType() const 342 { return m_serviceType; } 343 const std::string &GetServiceId() const 344 { return m_serviceId; } 345 const std::string &GetSCPDURL() const 346 { return m_SCPDURL; } 347 const std::string &GetAbsSCPDURL() const 348 { return m_absSCPDURL; } 349 const std::string &GetControlURL() const 350 { return m_controlURL; } 351 const std::string &GetEventSubURL() const 352 { return m_eventSubURL; } 353 const std::string &GetAbsControlURL() const 354 { return m_absControlURL; } 355 const std::string &GetAbsEventSubURL() const 356 { return m_absEventSubURL; } 357 int GetTimeout() const 358 { return m_timeout; } 359 void SetTimeout(int t) 360 { m_timeout = t; } 361 int *GetTimeoutAddr() 362 { return &m_timeout; } 363 char *GetSID() 364 { return m_SID; } 365 void SetSID(const char *s) 366 { memcpy(m_SID, s, sizeof(Upnp_SID)); } 367 const std::string &GetKey() const 368 { return m_serviceId; } 369 bool IsSubscribed() const 370 { return m_SCPD.get() != NULL; } 371 void SetSCPD(CUPnPSCPD *SCPD) 372 { m_SCPD.reset(SCPD); } 373 374 bool Execute( 375 const std::string &ActionName, 376 const std::vector<CUPnPArgumentValue> &ArgValue) const; 377 const std::string GetStateVariable( 378 const std::string &stateVariableName) const; 379 }; 380 381 382 class CUPnPDevice 383 { 384 private: 385 // Please, lock these lists before use 386 DeviceList m_DeviceList; 387 ServiceList m_ServiceList; 388 389 const std::string m_deviceType; 390 const std::string m_friendlyName; 391 const std::string m_manufacturer; 392 const std::string m_manufacturerURL; 393 const std::string m_modelDescription; 394 const std::string m_modelName; 395 const std::string m_modelNumber; 396 const std::string m_modelURL; 397 const std::string m_serialNumber; 398 const std::string m_UDN; 399 const std::string m_UPC; 400 std::string m_presentationURL; 401 402 public: 403 CUPnPDevice( 404 const CUPnPControlPoint &upnpControlPoint, 405 IXML_Element *device, 406 const std::string &URLBase); 407 ~CUPnPDevice() {} 408 409 const std::string &GetUDN() const 410 { return m_UDN; } 411 const std::string &GetDeviceType() const 412 { return m_deviceType; } 413 const std::string &GetFriendlyName() const 414 { return m_friendlyName; } 415 const std::string &GetPresentationURL() const 416 { return m_presentationURL; } 417 const std::string &GetKey() const 418 { return m_UDN; } 419 }; 420 421 422 class CUPnPRootDevice : public CUPnPDevice 423 { 424 private: 425 const std::string m_URLBase; 426 const std::string m_location; 427 int m_expires; 428 429 public: 430 CUPnPRootDevice( 431 const CUPnPControlPoint &upnpControlPoint, 432 IXML_Element *rootDevice, 433 const std::string &OriginalURLBase, 434 const std::string &FixedURLBase, 435 const char *location, 436 int expires); 437 ~CUPnPRootDevice() {} 438 439 const std::string &GetURLBase() const 440 { return m_URLBase; } 441 const std::string &GetLocation() const 442 { return m_location; } 443 int GetExpires() const 444 { return m_expires; } 445 void SetExpires(int expires) 446 { m_expires = expires; } 447 }; 448 449 450 typedef std::map<const std::string, CUPnPRootDevice *> RootDeviceMap; 451 typedef std::map<const std::string, CUPnPService *> ServiceMap; 452 typedef std::map<const std::string, CUPnPPortMapping> PortMappingMap; 453 454 455 class CUPnPControlPoint 456 { 457 private: 458 static CUPnPControlPoint *s_CtrlPoint; 459 // upnp stuff 460 UpnpClient_Handle m_UPnPClientHandle; 461 RootDeviceMap m_RootDeviceMap; 462 ServiceMap m_ServiceMap; 463 PortMappingMap m_ActivePortMappingsMap; 464 CUPnPMutex m_RootDeviceListMutex; 465 bool m_IGWDeviceDetected; 466 //#warning This variable is for testing purposes only and should disappear on release. 467 CUPnPService *m_WanService; 468 CUPnPMutex m_WaitForSearchTimeoutMutex; 469 470 public: 471 CUPnPControlPoint(unsigned short udpPort); 472 ~CUPnPControlPoint(); 473 void Subscribe(CUPnPService &service); 474 void Unsubscribe(CUPnPService &service); 475 bool AddPortMappings( 476 std::vector<CUPnPPortMapping> &upnpPortMapping); 477 bool DeletePortMappings( 478 std::vector<CUPnPPortMapping> &upnpPortMapping); 479 480 UpnpClient_Handle GetUPnPClientHandle() const 481 { return m_UPnPClientHandle; } 482 483 bool GetIGWDeviceDetected() const 484 { return m_IGWDeviceDetected; } 485 void SetIGWDeviceDetected(bool b) 486 { m_IGWDeviceDetected = b; } 487 bool WanServiceDetected() const 488 { return !m_ServiceMap.empty(); } 489 void SetWanService(CUPnPService *service) 490 { m_WanService = service; } 491 492 // Callback function 493 static int Callback( 494 #if UPNP_VERSION >= 10800 495 Upnp_EventType_e EventType, 496 const void *Event, 497 void *Cookie); 498 #else 499 Upnp_EventType EventType, 500 void* Event, 501 void* Cookie); 502 #endif 503 504 private: 505 void OnEventReceived( 506 const std::string &Sid, 507 int EventKey, 508 IXML_Document *ChangedVariables); 509 void AddRootDevice( 510 IXML_Element *rootDevice, 511 const std::string &urlBase, 512 const char *location, 513 int expires); 514 void RemoveRootDevice( 515 const char *udn); 516 void RefreshPortMappings(); 517 bool PrivateAddPortMapping( 518 CUPnPPortMapping &upnpPortMapping); 519 bool PrivateDeletePortMapping( 520 CUPnPPortMapping &upnpPortMapping); 521 }; 522 523 524 #endif /* AMULE_UPNP_H */ 525 526 // File_checked_for_headers 527