iosswiftudpcocoaasyncsocketssdp

Receiving SSDP response using CocoaAsyncSocket in Swift


I'm trying to receive a SSDP response using swift with the library CocoaAsyncSocket (https://github.com/robbiehanson/CocoaAsyncSocket)

I can successfully send the M-Search command to the multicast group and get a response, I've looked at the wireshark (https://i.sstatic.net/VpDRX.png): I can see the M-Search packets going out and the responses coming back but i never receive the NSData in my application. ( Btw I'm searching just for a Roku at the moment)

I've implemented the GCDAsyncUdpSocketDelegate Delegate and added the didReceiveData func, however i never get data.

I suspect there is something wrong in this section:

ssdpSocket = GCDAsyncUdpSocket(delegate: self, delegateQueue: dispatch_get_main_queue()) 
ssdpSocket.bindToPort(ssdpPort, error: &error)
ssdpSocket.beginReceiving(&error)
ssdpSocket.enableBroadcast(true, error: &error)
ssdpSocket.connectToHost(ssdpAddres, onPort: ssdpPort, error: &error)
ssdpSocket.joinMulticastGroup(ssdpAddres, error: &error)

Please see sample code below:

import UIKit
class ViewController: UIViewController, GCDAsyncUdpSocketDelegate {

//ssdp stuff
var ssdpAddres          = "239.255.255.250"
var ssdpPort:UInt16     = 1900
var ssdpSocket:GCDAsyncUdpSocket!
var ssdpSocketRec:GCDAsyncUdpSocket!
var error : NSError?

override func viewDidLoad() {
    super.viewDidLoad()

    ssdpSocket = GCDAsyncUdpSocket(delegate: self, delegateQueue: dispatch_get_main_queue())
    ssdpSocket.bindToPort(ssdpPort, error: &error)
    ssdpSocket.beginReceiving(&error)
    ssdpSocket.enableBroadcast(true, error: &error)
    ssdpSocket.connectToHost(ssdpAddres, onPort: ssdpPort, error: &error)
    ssdpSocket.joinMulticastGroup(ssdpAddres, error: &error)

    //replace ST:roku:ecp with ST:ssdp:all to view all devices
    let data = "M-SEARCH * HTTP/1.1\r\nHOST: 239.255.255.250:1900\r\nMAN: \"ssdp:discover\"\r\nMX: 3\r\nST: roku:ecp\r\nUSER-AGENT: iOS UPnP/1.1 TestApp/1.0\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)
    ssdpSocket.sendData(data, withTimeout: 1, tag: 0)
}


func udpSocket(sock:GCDAsyncUdpSocket!,didConnectToAddress data : NSData!){
    println("didConnectToAddress")
    println(data)
}

func udpSocket(sock: GCDAsyncUdpSocket!, didReceiveData data: NSData!, fromAddress address: NSData!, withFilterContext filterContext: AnyObject!) {
    println("didReceiveData")
    println(data)
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

}

Solution

  • After much playing around with the code, I've gotten it to work, I'm posting the code here to help anyone else with this issue.

    when i removed:

    ssdpSocket.connectToHost(ssdpAddres, onPort: ssdpPort, error: &error)
    

    i was able to receive data, i suspect this was blocking it somehow.. Not sure how or why, I'm guessing i don't need to connect to the host as its multicast

    It's working now using the following code:

    let mSearchData = "M-SEARCH * HTTP/1.1\r\nHOST: 239.255.255.250:1900\r\nMAN: \"ssdp:discover\"\r\nMX: 3\r\nST: ssdp:all\r\nUSER-AGENT: iOS UPnP/1.1 TestApp/1.0\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding) //all devices
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        //send M-Search
        ssdpSocket = GCDAsyncUdpSocket(delegate: self, delegateQueue: dispatch_get_main_queue())
        ssdpSocket.sendData(mSearchData, toHost: ssdpAddres, port: ssdpPort, withTimeout: 1, tag: 0)
    
        //bind for responses
        ssdpSocket.bindToPort(ssdpPort, error: &error)
        ssdpSocket.joinMulticastGroup(ssdpAddres, error: &error)
        ssdpSocket.beginReceiving(&error)
    
    }
    

    didReceiveData function is now getting called and i can print the response:

     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)
        println("From \(host!)")
    
    
        let gotdata: NSString = NSString(data: data!, encoding: NSUTF8StringEncoding)!
        println(gotdata)
    
     }