PageRenderTime 58ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/butils/networking/upnp/upnp.py

https://gitlab.com/balhau/pyutils
Python | 152 lines | 133 code | 18 blank | 1 comment | 2 complexity | 883c032b7016473317744146384e2e8a MD5 | raw file
  1. import sys
  2. import os
  3. import socket
  4. from select import select
  5. import struct
  6. import urllib3
  7. import requests
  8. from bs4 import BeautifulSoup
  9. class SSDPMessage():
  10. sdpMap={}
  11. def __init__(self,data):
  12. self.sdpMap=self.parseData(data)
  13. def parseData(self,data):
  14. dmap={}
  15. lines=data.split("\n")
  16. for line in lines:
  17. prop=line.split(":",1)
  18. if(len(prop)>1):
  19. dmap[prop[0].replace(":","")]=prop[1].replace("\r","")
  20. return dmap
  21. class Upnp():
  22. SSDP_ADDR = "239.255.255.250";
  23. SSDP_PORT = 1900;
  24. bcastend=(SSDP_ADDR,SSDP_PORT)
  25. SSDP_MX = 3;
  26. GET_EXTERNAL_IP_XML_MESSAGE='''
  27. <?xml version="1.0 ?>
  28. <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
  29. <s:Body>
  30. <u:GetExternalIPAddress xmlns:u="urn:schemas-upnp-org:service:WANPPPConnection:1">
  31. </u:GetExternalIPAddress>
  32. </s:Body>
  33. </s:Envelope>
  34. '''
  35. SSPD_STYPE="urn:schemas-upnp-org:service:WANPPPConnection:1"
  36. SSDP_ST = "urn:all";
  37. ssdpRequest = "M-SEARCH * HTTP/1.1\r\n" + \
  38. "HOST: %s:%d\r\n" % (SSDP_ADDR, SSDP_PORT) + \
  39. "MAN: \"ssdp:discover\"\r\n" + \
  40. "MX: %d\r\n" % (SSDP_MX, ) + \
  41. "ST: %s\r\n" % (SSDP_ST, ) + "\r\n";
  42. def broadcastRequest(self):
  43. # Create the socket
  44. sockr = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  45. sockr.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  46. # Bind to the server address
  47. sockr.bind(('',1900))
  48. ipmulticast,port=self.bcastend
  49. group = socket.inet_aton(ipmulticast)
  50. #pack the multicast address
  51. mreq = struct.pack('4sL', group, socket.INADDR_ANY)
  52. sockr.setsockopt(socket.IPPROTO_IP,socket.IP_ADD_MEMBERSHIP,mreq)
  53. i=0
  54. sockr.sendto(self.ssdpRequest,self.bcastend)
  55. sockr.settimeout(2.0)
  56. sdpResp=[]
  57. try:
  58. while True:
  59. data,address=sockr.recvfrom(1024)
  60. sdpm=SSDPMessage(data).sdpMap
  61. if 'LOCATION' in sdpm.keys():
  62. sdpResp.append(sdpm)
  63. i=i+1
  64. except:
  65. pass
  66. return sdpResp
  67. a=Upnp()
  68. responses=a.broadcastRequest()
  69. for resp in responses:
  70. print resp
  71. print '****************************'
  72. link="http://192.168.1.1:1900/igd.xml"
  73. http = urllib3.PoolManager()
  74. r = http.request('GET', link)
  75. soup=BeautifulSoup(r.data)
  76. for service in soup.find_all('service'):
  77. print service
  78. print "Posting xml soap command to retrieve the external IP"
  79. GET_EXTERNAL_IP_XML_MESSAGE='''
  80. <?xml version="1.0"?>
  81. <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
  82. <s:Body>
  83. <u:GetExternalIPAddress xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1">
  84. </u:GetExternalIPAddress>
  85. </s:Body>
  86. </s:Envelope>'''
  87. GET_GENERIC_PORTMAP_ENTRY='''
  88. <?xml version="1.0"?>
  89. <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
  90. <s:Body>
  91. <u:GetGenericPortMappingEntry xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1">
  92. <NewPortMappingIndex>0</NewPortMappingIndex>
  93. </u:GetGenericPortMappingEntry>
  94. </s:Body>
  95. </s:Envelope>
  96. '''
  97. HEADER_GENERIC_PORT_MAPPING='"urn:schemas-upnp-org:service:WANIPConnection:1#GetGenericPortMappingEntry"'
  98. eiplink="http://192.168.1.1:1900/ipc"
  99. HEADER_IPADDRESS='"urn:schemas-upnp-org:service:WANIPConnection:1#GetExternalIPAddress"'
  100. heip={'SOAPACTION':HEADER_IPADDRESS,'CONTENT-TYPE':'text/xml; charset="utf-8"'}
  101. r=requests.post(url=eiplink,data=GET_EXTERNAL_IP_XML_MESSAGE,headers=heip)
  102. print "Response: ",r.text
  103. ipxml=BeautifulSoup(r.text)
  104. print ipxml.find_all('newexternalipaddress')[0].string
  105. hgpm={'SOAPACTION':HEADER_GENERIC_PORT_MAPPING,'CONTENT-TYPE':'text/xml; charset="utf-8"'}
  106. r=requests.post(url=eiplink,data=GET_GENERIC_PORTMAP_ENTRY,headers=hgpm)
  107. print "Response: ",r.text
  108. rhxml=BeautifulSoup(r.text)
  109. print "Remote Host: ", rhxml.find('newremotehost').string
  110. print "Internal Host: ",rhxml.find('newinternalclient').string
  111. print "Description: ", rhxml.find('newportmappingdescription').string
  112. print "External Port: ", rhxml.find('newexternalport').string
  113. print "Internal Port: ", rhxml.find('newinternalport').string