java - Unable to receive proper UDP packets using SSDP -
i'm trying implement simple ssdp functionality android app taken from here.
my application sends udp packets containing relevant m-search message broadcasting address without issue. problem is, should getting proper response other devices that's running upnp server. reason, i'm receiving exact same packets sent android device.
mainactivity.java
@override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); wifimanager wm = (wifimanager)getsystemservice(context.wifi_service); wifimanager.multicastlock multicastlock = wm.createmulticastlock("multicastlock"); multicastlock.setreferencecounted(true); multicastlock.acquire(); setcontentview(r.layout.activity_main); ((button)this.findviewbyid(r.id.btnsendssdpsearch)).setonclicklistener(this); } @override public void onclick(view v) { switch (v.getid()) { case r.id.btnsendssdpsearch: new thread(new runnable() { @override public void run() { sendmsearchmessage(); } }).start(); default: break; } } private void sendmsearchmessage() { ssdpsearchmsg searchcontentdirectory = new ssdpsearchmsg(ssdpconstants.st_contentdirectory); ssdpsearchmsg searchavtransport = new ssdpsearchmsg(ssdpconstants.st_avtransport); ssdpsearchmsg searchproduct = new ssdpsearchmsg(ssdpconstants.st_product); ssdpsocket sock; try { sock = new ssdpsocket(); (int = 0; < 2; i++) { sock.send(searchcontentdirectory.tostring()); sock.send(searchavtransport.tostring()); sock.send(searchproduct.tostring()); } while (true) { datagrampacket dp = sock.receive(); //here, receive same packets sent above string c = new string(dp.getdata()); system.out.println(c); } } catch (ioexception e) { // todo auto-generated catch block log.e("m-search", e.getmessage()); }
ssdpsocket.java udp packet transmission done
public class ssdpsocket { socketaddress mssdpmulticastgroup; multicastsocket mssdpsocket; inetaddress broadcastaddress; public ssdpsocket() throws ioexception { mssdpsocket = new multicastsocket(55325); //bind random port receiving datagram broadcastaddress = inetaddress.getbyname(ssdpconstants.address); mssdpsocket.joingroup(broadcastaddress); } /* used send ssdp packet */ public void send(string data) throws ioexception { datagrampacket dp = new datagrampacket(data.getbytes(), data.length(), broadcastaddress,ssdpconstants.port); mssdpsocket.send(dp); } /* used receive ssdp packet */ public datagrampacket receive() throws ioexception { byte[] buf = new byte[1024]; datagrampacket dp = new datagrampacket(buf, buf.length); mssdpsocket.receive(dp); return dp; } public void close() { if (mssdpsocket != null) { mssdpsocket.close(); } } }
ssdpsearchmsg.java constructing ssdp broadcast string (probably unrelated problem i'm experiencing in case)
public class ssdpsearchmsg { static final string host = "host:" + ssdp.address + ":" + ssdp.port; static final string man = "man:ssdp:discover"; static final string newline = system.getproperty("line.separator"); int mmx = 3; /* seconds delay response */ string mst; /* search target */ public ssdpsearchmsg(string st) { mst = st; } public int getmmx() { return mmx; } public void setmmx(int mmx) { this.mmx = mmx; } public string getmst() { return mst; } public void setmst(string mst) { this.mst = mst; } @override public string tostring() { stringbuilder content = new stringbuilder(); content.append(ssdp.sl_msearch).append(newline); content.append(host).append(newline); content.append(man).append(newline); content.append(mst).append(newline); content.append("mx:" + mmx).append(newline); content.append(newline); return content.tostring(); } }
ssdpconstants.java
public class ssdpconstants { /* new line definition */ public static final string newline = "\r\n"; public static final string address = "239.255.255.250"; public static final int port = 1900; /* definitions of start line */ public static final string sl_notify = "notify * http/1.1"; public static final string sl_msearch = "m-search * http/1.1"; public static final string sl_ok = "http/1.1 200 ok"; /* definitions of search targets */ public static final string st_rootdevice = "st: rootdevice"; public static final string st_contentdirectory = "st: urn:schemas-upnp-org:service:contentdirectory:1"; public static final string st_avtransport = "st: urn:schemas-upnp-org:service:avtransport:1"; public static final string st_product = "st: urn:av-openhome-org:service:product:1"; /* definitions of notification sub type */ public static final string nts_alive = "nts:ssdp:alive"; public static final string nts_bye = "nts:ssdp:byebye"; public static final string nts_update = "nts:ssdp:update"; }
i made sure manifest includes relevant permissions:
<uses-permission android:name="android.permission.internet"/> <uses-permission android:name="android.permission.change_wifi_multicast_state" /> <uses-permission android:name="android.permission.access_wifi_state" /> <uses-permission android:name="android.permission.access_network_state" />
i'm testing app on actual device, not on emulator.
any assistance appreciated.
edit upon comment:
multicast should work without issue. i've downloaded app called bubbleupnp test ssdp functionality. sure enough, wireshark captures messages sent phone broadcasting address in ssdp protocol:
m-search * http/1.1 man: "ssdp:discover" mx: 3 host: 239.255.255.250:1900 st: urn:schemas-upnp-org:service:avtransport:1
and response
http/1.1 200 ok st:urn:schemas-upnp-org:service:contentdirectory:1 usn:uuid:d5829e90-73ce-4213-9ad1-4e75dbdd0232::urn:schemas-upnp-org:service:contentdirectory:1 location:http://10.175.95.4:2869/upnphost/udhisapi.dll?content=uuid:d5829e90-73ce-4213-9ad1-4e75dbdd0232 opt:"http://schemas.upnp.org/upnp/1/0/"; ns=01 01-nls:05f3dd08b4b4b5aafa1fe983fa447f49 cache-control:max-age=900 server:microsoft-windows-nt/5.1 upnp/1.0 upnp-device-host/1.0
so yeah, without doubt, implementation issue. nothing wrong device.
weird. fixed issue i'm genuinely not sure made work.
here changes made:
instead of assigning fixed port, made dynamically allocate available port.
public class ssdpsocket { socketaddress mssdpmulticastgroup; multicastsocket mssdpsocket; inetaddress broadcastaddress; public ssdpsocket() throws ioexception { mssdpsocket = new multicastsocket(); broadcastaddress = inetaddress.getbyname(ssdpconstants.address); mssdpsocket.joingroup(broadcastaddress); } ... }
i changed m-search message structure, including order.
public class ssdpsearchmsg { static final string host = "host: " + ssdpconstants.address + ":" + ssdpconstants.port; static final string man = "man: \"ssdp:discover\""; static final string newline = "\r\n"; int mmx = 3; /* seconds delay response */ string mst; /* search target */ public ssdpsearchmsg(string st) { mst = st; } public int getmmx() { return mmx; } public void setmmx(int mmx) { this.mmx = mmx; } public string getmst() { return mst; } public void setmst(string mst) { this.mst = mst; } @override public string tostring() { stringbuilder content = new stringbuilder(); content.append(ssdpconstants.sl_msearch).append(newline); content.append(man).append(newline); content.append("mx: " + mmx).append(newline); content.append(host).append(newline); content.append(mst).append(newline); content.append(newline); return content.tostring(); } }
and works. why works beyond me. previous implementation follows ssdp protocol far can tell.
Comments
Post a Comment