68569

Parsing A UPnP Response In Swift?

Question:

This question may not need to be so specific, but I am working on a project that is searching for UPnP devices (working great).

I get the data like so;

func udpSocket(sock: GCDAsyncUdpSocket!, didReceiveData data: NSData!, fromAddress address: NSData!, withFilterContext filterContext: AnyObject!) { var host: NSString? var port1: UInt16 = 0 GCDAsyncUdpSocket.getHost(&host, port: &port1, fromAddress: address) //print(host) let response: NSString = NSString(data: data!, encoding: NSUTF8StringEncoding)! print(response) }

The data response is returned as a NSString, and looks like so;

HTTP/1.1 200 OK CACHE-CONTROL: max-age=120 DATE: Sun, 31 Jan 2016 22:47:45 GMT ST: upnp:rootdevice USN: uuid:f7a65ab0-f527-4b85-a8ad-68104aa2b322::upnp:rootdevice EXT: SERVER: Linux/BHR4 UPnP/1.1 MiniUPnPd/1.8 LOCATION: http://192.168.1.1:49420/rootDesc.xml OPT: "http://schemas.upnp.org/upnp/1/0/"; ns=01 01-NLS: 1 BOOTID.UPNP.ORG: 1 CONFIGID.UPNP.ORG: 1337 HTTP/1.1 200 OK Cache-Control: max-age=600 EXT: Location: http://192.168.1.1:1901/root.xml SECURELOCATION.UPNP.ORG: https://192.168.1.1:1902/root.xml Server: Linux/3.4 UPnP/2.0 bhr4/1.2 ST: upnp:rootdevice USN: uuid:9518ecfc-cf2f-57e4-bb23-5182aa6a23cd::upnp:rootdevice DATE: Wed, 19 Jan 2000 02:39:56 GMT BOOTID.UPNP.ORG: 1 HTTP/1.1 200 OK Cache-Control: max-age=600 EXT: Location: http://192.168.1.1:1901/root.xml SECURELOCATION.UPNP.ORG: https://192.168.1.1:1902/root.xml ST: urn:schemas-upnp-org:device:ManageableDevice:2 USN: uuid:9518acfc-cf2f-57e4-cc23-5a12aa6a23cd::urn:schemas-upnp-org:device:ManageableDevice:2 Server: Linux/3.4 UPnP/2.0 bhr4/1.2 DATE: Wed, 19 Jan 2000 02:39:56 GMT BOOTID.UPNP.ORG: 1

I have some understanding of how to parse XML or JSON responses, but being that this response seems to just be a lengthy string, I am trying to figure out how I could parse the data into a dictionary so I could do a;

for item in response { print(item.location) }

This is not necessarily specific to UPnP, but an overall premise to grasp.

Answer1:

I was working on a swift UPNP library not so long ago. Here is one way how I did it with regular expressions: <a href="https://github.com/ambientlight/ambientUPNP/blob/master/ambientUPNP/SSDPMessage.swift" rel="nofollow">https://github.com/ambientlight/ambientUPNP/blob/master/ambientUPNP/SSDPMessage.swift</a>

You can use for parsing SSDP messages, however for UPNP GENA events you should not use this approach since they are over TCP, and therefore you have a stream-socket which you should read as a stream accordingly. Take a look here: <a href="https://github.com/ambientlight/ambientUPNP/blob/master/ambientUPNP/components/HTTPInternals.swift" rel="nofollow">https://github.com/ambientlight/ambientUPNP/blob/master/ambientUPNP/components/HTTPInternals.swift</a>

<strong>Reference (reading from UDP socket - fixed length)</strong>: <a href="https://github.com/ambientlight/ambientUPNP/blob/master/ambientUPNP/SSDPServer.swift" rel="nofollow">https://github.com/ambientlight/ambientUPNP/blob/master/ambientUPNP/SSDPServer.swift</a>

self.readMulticastSocket = try PosixInternals.initMulticastUDPSocket(SSDPDefaultPort, multicastAddress: SSDPMulticastAddress) let readMulticastSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, UInt(readMulticastSocket), 0, _readMulticastQueue) dispatch_source_set_event_handler(readMulticastSource) { do { let (data, senderAddress) = try PosixInternals.recvData(self.readMulticastSocket, readSize: SSDPDefaultReadSize) let message = try SSDPMessage.messageWithDataAndAddress(data, senderAddress: senderAddress) //print("\(message)\n") self._processMessage(message) } catch { print(error) } }

Recommend

  • Communicate between asyncio protocol/servers
  • Can you use multiple instances of Edge on a Selenium Grid Node?
  • Soap Envelope Header in Delphi 7 not including utf-8 encoding. How can I modify it?
  • RabbitMQ java client stops consuming messages
  • Portable JRE on Linux - possible?
  • apply a javascript function to draggable copy
  • Firefox Extension - Monitor refresh and change of tab
  • Saving Changes After In-App Purchase Has Been Purchased
  • How to have background script and something similar to a default popup?
  • JQuery Internet Explorer and ajaxstop
  • Python urlparse: small issue
  • Jquery UI tool tip close icon
  • Is it possible to access block's scope in method?
  • How to clear text inside text field when radio button is select
  • Syntax for setting draggablecursor property in google maps api
  • Seeking advice on Jetty HttpClient Hang
  • does jqgrid support a multiple checkbox list for editing
  • Why is an OPTIONS request sent to the server?
  • Pass value from viewmodel to script in zk
  • Why ng-show works with ng-repeat but ng-if doesn't? [duplicate]
  • Optimizing database types to compact database (SQLite)
  • RectangularRangeIndicator format like triangular using dojo
  • How do I fake an specific browser client when using Java's Net library?
  • Resize panoramic image to fixed size
  • Volusion's generic SQL folder, functionality
  • To display the title for the current loaction in map in iphone
  • Alternatives to the OPTIONAL fallback SPARQL pattern?
  • Do I've to free mysql result after storing it?
  • Function pointer “assignment from incompatible pointer type” only when using vararg ellipsis
  • QuartzCore.framework for Mono Develop
  • Python - Map / Reduce - How do I read JSON specific field in using DISCO count words example
  • Warning: Can't call setState (or forceUpdate) on an unmounted component
  • bootstrap to use multiple ng-app
  • How to get icons for entities from eclipse?
  • How do you join a server to an Active Directory (domain)?
  • coudnt use logback because of log4j
  • Turn off referential integrity in Derby? is it possible?
  • JaxB to read class hierarchy