PDA

View Full Version : Multicast, how detect my LMS in my home ?



Tim_LHUILLIER
2015-05-20, 07:23
Hi,


I would like to auto detect my LMS in my local network for no write in my chrome the ip with the port 9000.
For that, i think to use the multicast protocol and i suppose that LMS detect the other squeezelite in my home since multicast, no ?

If yes, What is the ip address and port used for to develop my discovery client.

Thanks,

gharris999
2015-05-20, 07:57
I'm not sure if you mean chrome, the browser, or chrome, the OS as in a chrome book. Also not sure if you're talking about developing a chrome extension that performs slimproto discovery on the local subnet or if you just want to find your server on the subnet.

If the latter, the popular option is just to set the server up with a static IP and reserve that IP in the DHCP pool in your router. That way, you'll just know where the server is.

But if you're talking about some kind of coded Chrome extension that performs slimproto discovery on the local subnet, one place to start might be to look at Triode's discovery code in squeezelite:

https://code.google.com/p/squeezelite/source/browse/slimproto.c

Look at the function discover_server().

Given that NPAPI chrome extensions are being phased out, you'd need to replicate the functionality of that C code in JavaScript...no easy task.

Here's a thread from some 5 years ago that discussed server discovery in javascript:

http://forums.slimdevices.com/showthread.php?72188-Server-discovery-(JSON-amp-CLI-Port)

..but there's not much there that would be helpful, I'm afraid.

This is way out of my area of expertise, so it's very possible that I've missed important discussions about this very topic.

Tim_LHUILLIER
2015-05-20, 08:27
Thanks for answer, gharris999


I'm not sure if you mean chrome, the browser, or chrome, the OS as in a chrome book. Also not sure if you're talking about developing a chrome extension that performs slimproto discovery on the local subnet or if you just want to find your server on the subnet.

If the latter, the popular option is just to set the server up with a static IP and reserve that IP in the DHCP pool in your router. That way, you'll just know where the server is.


I say chrome for the browser, not the OS sorry.

For the IP static, i need a plug and play. So, I must not modify the router config.



But if you're talking about some kind of coded Chrome extension that performs slimproto discovery on the local subnet, one place to start might be to look at Triode's discovery code in squeezelite:

https://code.google.com/p/squeezelite/source/browse/slimproto.c

Look at the function discover_server().

Given that NPAPI chrome extensions are being phased out, you'd need to replicate the functionality of that C code in JavaScript...no easy task.

Here's a thread from some 5 years ago that discussed server discovery in javascript:

http://forums.slimdevices.com/showthread.php?72188-Server-discovery-(JSON-amp-CLI-Port)

..but there's not much there that would be helpful, I'm afraid.

This is way out of my area of expertise, so it's very possible that I've missed important discussions about this very topic.

How LMS do this ?
18067

Since the multicast ip defined (i suppose) for LMS, My client writed in Javascript who will have a mobile/desktop application send a request on the ip multicast for to detect the squeezelites connected in the local network and work together with the CLI.

bpa
2015-05-20, 09:07
Players discover what LMS are on the LAN by broadcasting a UDP packet on port 3483. Below is the Java code used by Softsqueeze to send the packet


public void sendDiscoveryRequest(int deviceID, int revision,
byte[] macaddress) {
byte args[] = new byte[18];
args[0] = 'd';
args[2] = (byte) deviceID;
args[3] = (byte) revision;
System.arraycopy(macaddress, 0, args, 12, 6);

try {
InetAddress broadcast = InetAddress.getByName("255.255.255.255");
DatagramPacket p = new DatagramPacket(args, 18, broadcast, 3483);
udpSocket.send(p);
} catch (IOException e) {
logger.error("Sending broadcast packet", e);
}
}


From squeezelite


in_addr_t discover_server(void) {
struct sockaddr_in d;
struct sockaddr_in s;
char *buf;
struct pollfd pollinfo;

int disc_sock = socket(AF_INET, SOCK_DGRAM, 0);

socklen_t enable = 1;
setsockopt(disc_sock, SOL_SOCKET, SO_BROADCAST, (const void *)&enable, sizeof(enable));

buf = "e";

memset(&d, 0, sizeof(d));
d.sin_family = AF_INET;
d.sin_port = htons(PORT);
d.sin_addr.s_addr = htonl(INADDR_BROADCAST);

pollinfo.fd = disc_sock;
pollinfo.events = POLLIN;

do {

LOG_INFO("sending discovery");
memset(&s, 0, sizeof(s));

if (sendto(disc_sock, buf, 1, 0, (struct sockaddr *)&d, sizeof(d)) < 0) {
LOG_INFO("error sending disovery");
}

if (poll(&pollinfo, 1, 5000) == 1) {
char readbuf[10];
socklen_t slen = sizeof(s);
recvfrom(disc_sock, readbuf, 10, 0, (struct sockaddr *)&s, &slen);
LOG_INFO("got response from: %s:%d", inet_ntoa(s.sin_addr), ntohs(s.sin_port));
}

} while (s.sin_addr.s_addr == 0 && running);

closesocket(disc_sock);

return s.sin_addr.s_addr;
}

Tim_LHUILLIER
2015-05-20, 09:22
Players discover what LMS are on the LAN by broadcasting a UDP packet on port 3483. Below is the Java code used by Softsqueeze to send the packet


public void sendDiscoveryRequest(int deviceID, int revision,
byte[] macaddress) {
byte args[] = new byte[18];
args[0] = 'd';
args[2] = (byte) deviceID;
args[3] = (byte) revision;
System.arraycopy(macaddress, 0, args, 12, 6);

try {
InetAddress broadcast = InetAddress.getByName("255.255.255.255");
DatagramPacket p = new DatagramPacket(args, 18, broadcast, 3483);
udpSocket.send(p);
} catch (IOException e) {
logger.error("Sending broadcast packet", e);
}
}


From squeezelite


in_addr_t discover_server(void) {
struct sockaddr_in d;
struct sockaddr_in s;
char *buf;
struct pollfd pollinfo;

int disc_sock = socket(AF_INET, SOCK_DGRAM, 0);

socklen_t enable = 1;
setsockopt(disc_sock, SOL_SOCKET, SO_BROADCAST, (const void *)&enable, sizeof(enable));

buf = "e";

memset(&d, 0, sizeof(d));
d.sin_family = AF_INET;
d.sin_port = htons(PORT);
d.sin_addr.s_addr = htonl(INADDR_BROADCAST);

pollinfo.fd = disc_sock;
pollinfo.events = POLLIN;

do {

LOG_INFO("sending discovery");
memset(&s, 0, sizeof(s));

if (sendto(disc_sock, buf, 1, 0, (struct sockaddr *)&d, sizeof(d)) < 0) {
LOG_INFO("error sending disovery");
}

if (poll(&pollinfo, 1, 5000) == 1) {
char readbuf[10];
socklen_t slen = sizeof(s);
recvfrom(disc_sock, readbuf, 10, 0, (struct sockaddr *)&s, &slen);
LOG_INFO("got response from: %s:%d", inet_ntoa(s.sin_addr), ntohs(s.sin_port));
}

} while (s.sin_addr.s_addr == 0 && running);

closesocket(disc_sock);

return s.sin_addr.s_addr;
}


Thanks bpa,

So, my client listen the port 3483 on the ip address 255.255.255.255 ?
But, There aren't information for the address or the port in squeezelite code.


setsockopt(disc_sock, SOL_SOCKET, SO_BROADCAST, (const void *)&enable, sizeof(enable));

bpa
2015-05-20, 09:31
Not sure whether you understand what is happening.

Squeezelite send out broadcast packet asking for all LMS.

Each LMS will send back a UDP response - the IP address of the response is the IP address of the LMS server. The response packet will vary according to the player. The port etc will only be sent when a Player has selected whih LMS it wants to talk to and told LMS its capabilitiers. Player and LMS aren then using the TCP 3483 slimproto protocol - the LMS will send a strm packet will all detaisl including port. The protocol is detailed in the LMS WebUI under Help / Technical Information/ The SlimProto TCP Protocol

Here is LMS code to response to the broadcast packet



sub gotDiscoveryRequest {
my ($udpsock, $clientpaddr, $deviceid, $revision, $mac) = @_;

$revision = join('.', int($revision / 16), ($revision % 16));

main::INFOLOG && $log->info("gotDiscoveryRequest: deviceid = $deviceid, revision = $revision, MAC = $mac");

my $response = undef;

if ($deviceid == 1) {

main::INFOLOG && $log->info("It's a SLIMP3 (note: firmware v2.2 always sends revision of 1.1).");

$response = 'D'. pack('C', 0) x 17;

} elsif ($deviceid >= 2 || $deviceid <= 4) { ## FIXME always true

main::INFOLOG && $log->info("It's a Squeezebox");

$response = 'D'. serverHostname();

} else {

main::INFOLOG && $log->info("Unknown device.");
}

$udpsock->send($response, 0, $clientpaddr);

main::INFOLOG && $log->info("gotDiscoveryRequest: Sent discovery response.");
}

Tim_LHUILLIER
2015-05-20, 09:59
Not sure whether you understand what is happening.

Squeezelite send out broadcast packet asking for all LMS.

Each LMS will send back a UDP response - the IP address of the response is the IP address of the LMS server. The response packet will vary according to the player. The port etc will only be sent when a Player has selected whih LMS it wants to talk to and told LMS its capabilitiers. Player and LMS aren then using the TCP 3483 slimproto protocol - the LMS will send a strm packet will all detaisl including port. The protocol is detailed in the LMS WebUI under Help / Technical Information/ The SlimProto TCP Protocol

Here is LMS code to response to the broadcast packet



sub gotDiscoveryRequest {
my ($udpsock, $clientpaddr, $deviceid, $revision, $mac) = @_;

$revision = join('.', int($revision / 16), ($revision % 16));

main::INFOLOG && $log->info("gotDiscoveryRequest: deviceid = $deviceid, revision = $revision, MAC = $mac");

my $response = undef;

if ($deviceid == 1) {

main::INFOLOG && $log->info("It's a SLIMP3 (note: firmware v2.2 always sends revision of 1.1).");

$response = 'D'. pack('C', 0) x 17;

} elsif ($deviceid >= 2 || $deviceid <= 4) { ## FIXME always true

main::INFOLOG && $log->info("It's a Squeezebox");

$response = 'D'. serverHostname();

} else {

main::INFOLOG && $log->info("Unknown device.");
}

$udpsock->send($response, 0, $clientpaddr);

main::INFOLOG && $log->info("gotDiscoveryRequest: Sent discovery response.");
}

Ok thanks.

So, My mobile app send a UDP request in IP 255.255.255.255:3483 with the first four bytes are "RESP" and LMS (Server) my return strm packet with all information that need.


Edit : My router block the 255.255.255.255, so, LMS don't use this ip but what is the ip broadcast ? Where i can find it ?

Thanks and sorry for my beginner question.

pippin
2015-05-21, 06:47
You can try to broadcast only to your local subnet, as in 192.178.1.255:3483

Oh, and the RESP thing is for the RESPONSE by the server, not your request. See bpa's first code snippet

Tim_LHUILLIER
2015-05-21, 07:12
Hi all,

Thanks all for your anwsers.

A friend help me for this code (https://gist.github.com/timothylhuillier/f93c28c82d6f695c5bb7)

For to have this code (https://gist.github.com/timothylhuillier/f93c28c82d6f695c5bb7) ( a friend helped me), i follow code of Squeezeplay :

SlimDiscoveryApplet.lua#L284 (https://github.com/Logitech/squeezeplay/blob/49f41e48311ade3a4a879b4b27283036363724b5/src/squeezeplay/share/applets/SlimDiscovery/SlimDiscoveryApplet.lua#L284) and SlimDiscoveryApplet.lua#L68-L78 (https://github.com/Logitech/squeezeplay/blob/49f41e48311ade3a4a879b4b27283036363724b5/src/squeezeplay/share/applets/SlimDiscovery/SlimDiscoveryApplet.lua#L68-L78)