Issue with UDP Sockets

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
32 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Issue with UDP Sockets

Manfred Kröhnert
Hello everyone,

I am currently trying to get a list of UPnP device via SSDP (Simple Service Discovery Protocol).

A minimalistic working NodeJS example looks like this:

    var dgram = require('dgram');
    var message = new Buffer(
        "M-SEARCH * HTTP/1.1\r\n" +
        "HOST:239.255.255.250:1900\r\n" +
        "MAN:\"ssdp:discover\"\r\n" +
        "ST:ssdp:all\r\n" + 
        "MX:1\r\n" + 
        "\r\n"
    );

    var client = dgram.createSocket("udp4");

    client.on("message", function (msg, rinfo) {
        console.log("server got: " + msg + " from " + rinfo.address + ":" + rinfo.port);
    });
    client.send(message, 0, message.length, 1900, "239.255.255.250");
    client.close();

I tried to recreate the same functionality in Pharo with the following piece of code:

  | message udpSocket host |
  message := 'M-SEARCH * HTTP/1.1\r\n' ,
    'HOST:239.255.255.250:1900\r\n' ,
    'MAN:"ssdp:discover"\r\n' ,
    'ST:ssdp:all\r\n' ,
    'MX:1\r\n' , '\r\n'.

  udpSocket := Socket newUDP.
  host :=  (NetNameResolver addressFromString: '239.255.255.250').
  udpSocket sendData: message toHost: host port: 1900.
  "udpSocket waitForData."
  Transcript show: 'Received: ' , udpSocket receiveData.
  udpSocket closeAndDestroy.

Unfortunately, this script hangs both in Pharo3 and Pharo4 (OS X 10.10, Pharo 30856 and 40611).
When I interrupt with Cmd+. the debugger shows the method
    Socket>>waitForDataIfClosed:
and the hang is apparently in the line 
    self readSemaphore wait

Could anyone give me some advice if I should to do this differently or what the issue with the Pharo script is?

Thanks in advance,
Manfred
Reply | Threaded
Open this post in threaded view
|

Re: Issue with UDP Sockets

Sven Van Caekenberghe-2
Hi Manfred,

Did you see/study the example/test UDPSocketEchoTest ?

Also, UDP is very primitive: it is send and forget, returns no errors, and is totally asynchronous. Listening should best be done in a separate process.

Here is how I would write your send part:

 | message udpSocket |
  message := String crlf join: #(
   'M-SEARCH * HTTP/1.1'
   'HOST:239.255.255.250:1900'
   'MAN:"ssdp:discover'
   'ST:ssdp:all'
   'MX:1'
   '').

  udpSocket := Socket newUDP.
  udpSocket sendData: message toHost: #[239 255 255 250] port: 1900.
  udpSocket waitForSendDoneFor: 5.
  udpSocket closeAndDestroy.

Maybe nothing came back because the line ends where wrong ?

HTH,

Sven

> On 18 May 2015, at 11:29, Manfred Kröhnert <[hidden email]> wrote:
>
> Hello everyone,
>
> I am currently trying to get a list of UPnP device via SSDP (Simple Service Discovery Protocol).
>
> A minimalistic working NodeJS example looks like this:
>
>     var dgram = require('dgram');
>     var message = new Buffer(
>         "M-SEARCH * HTTP/1.1\r\n" +
>         "HOST:239.255.255.250:1900\r\n" +
>         "MAN:\"ssdp:discover\"\r\n" +
>         "ST:ssdp:all\r\n" +
>         "MX:1\r\n" +
>         "\r\n"
>     );
>
>     var client = dgram.createSocket("udp4");
>
>     client.on("message", function (msg, rinfo) {
>         console.log("server got: " + msg + " from " + rinfo.address + ":" + rinfo.port);
>     });
>     client.send(message, 0, message.length, 1900, "239.255.255.250");
>     client.close();
>
> I tried to recreate the same functionality in Pharo with the following piece of code:
>
>   | message udpSocket host |
>   message := 'M-SEARCH * HTTP/1.1\r\n' ,
>     'HOST:239.255.255.250:1900\r\n' ,
>     'MAN:"ssdp:discover"\r\n' ,
>     'ST:ssdp:all\r\n' ,
>     'MX:1\r\n' , '\r\n'.
>
>   udpSocket := Socket newUDP.
>   host :=  (NetNameResolver addressFromString: '239.255.255.250').
>   udpSocket sendData: message toHost: host port: 1900.
>   "udpSocket waitForData."
>   Transcript show: 'Received: ' , udpSocket receiveData.
>   udpSocket closeAndDestroy.
>
> Unfortunately, this script hangs both in Pharo3 and Pharo4 (OS X 10.10, Pharo 30856 and 40611).
> When I interrupt with Cmd+. the debugger shows the method
>     Socket>>waitForDataIfClosed:
> and the hang is apparently in the line
>     self readSemaphore wait
>
> Could anyone give me some advice if I should to do this differently or what the issue with the Pharo script is?
>
> Thanks in advance,
> Manfred


Reply | Threaded
Open this post in threaded view
|

Re: Issue with UDP Sockets

Manfred Kröhnert
Hello Sven,

thanks for your fast reply.

On Mon, May 18, 2015 at 11:41 AM, Sven Van Caekenberghe <[hidden email]> wrote:
Hi Manfred,

Did you see/study the example/test UDPSocketEchoTest ?

unfortunately I did not see this class, yet.
But I did look at the Socket class itself and Socket>>timeTestUDP (in Pharo3).
 
Also, UDP is very primitive: it is send and forget, returns no errors, and is totally asynchronous. Listening should best be done in a separate process.

Yes, UDP is primitive but the SSDP specification requires using UDP.

Here is how I would write your send part:

 | message udpSocket |
  message := String crlf join: #(
   'M-SEARCH * HTTP/1.1'
   'HOST:239.255.255.250:1900'
   'MAN:"ssdp:discover'
   'ST:ssdp:all'
   'MX:1'
   '').

  udpSocket := Socket newUDP.
  udpSocket sendData: message toHost: #[239 255 255 250] port: 1900.
  udpSocket waitForSendDoneFor: 5.
  udpSocket closeAndDestroy.

Thanks for this snippet.
For some reasons I do not understand yet, this gives me the expected result in contrast to my own version.

I modified it like this to print the results on the Transcript:

| message udpSocket |
  message := String crlf join: #(
   'M-SEARCH * HTTP/1.1'
   'MAN:"ssdp:discover"'
   'ST:ssdp:all'
   'MX:1'
   '').

  udpSocket := Socket newUDP.
  udpSocket sendData: message toHost: #[239 255 255 250] port: 1900.
  udpSocket waitForSendDoneFor: 5.
  udpSocket waitForData.
  [udpSocket dataAvailable ] whileTrue: [ | buffer |
  buffer := ByteArray new: 1024.
  udpSocket receiveUDPDataInto: buffer.
    Transcript show: 'Received: ', buffer.
    [udpSocket waitForDataFor: 1] on: Error do: [  ].
  ].
  udpSocket closeAndDestroy.

Currently, this will work for me, since I am not interested in continuously detecting new devices.
But you mentioned reading should in general be done in a separate process.
Would you reuse the existing udpSocket instance in this case or create a separate one for reading?

Maybe nothing came back because the line ends where wrong ?

The lineendings I used are required by the SSDP specification.
 
HTH,

Sven

Thanks,
Manfred
 
> On 18 May 2015, at 11:29, Manfred Kröhnert <[hidden email]> wrote:
>
> Hello everyone,
>
> I am currently trying to get a list of UPnP device via SSDP (Simple Service Discovery Protocol).
>
> A minimalistic working NodeJS example looks like this:
>
>     var dgram = require('dgram');
>     var message = new Buffer(
>         "M-SEARCH * HTTP/1.1\r\n" +
>         "HOST:239.255.255.250:1900\r\n" +
>         "MAN:\"ssdp:discover\"\r\n" +
>         "ST:ssdp:all\r\n" +
>         "MX:1\r\n" +
>         "\r\n"
>     );
>
>     var client = dgram.createSocket("udp4");
>
>     client.on("message", function (msg, rinfo) {
>         console.log("server got: " + msg + " from " + rinfo.address + ":" + rinfo.port);
>     });
>     client.send(message, 0, message.length, 1900, "239.255.255.250");
>     client.close();
>
> I tried to recreate the same functionality in Pharo with the following piece of code:
>
>   | message udpSocket host |
>   message := 'M-SEARCH * HTTP/1.1\r\n' ,
>     'HOST:239.255.255.250:1900\r\n' ,
>     'MAN:"ssdp:discover"\r\n' ,
>     'ST:ssdp:all\r\n' ,
>     'MX:1\r\n' , '\r\n'.
>
>   udpSocket := Socket newUDP.
>   host :=  (NetNameResolver addressFromString: '239.255.255.250').
>   udpSocket sendData: message toHost: host port: 1900.
>   "udpSocket waitForData."
>   Transcript show: 'Received: ' , udpSocket receiveData.
>   udpSocket closeAndDestroy.
>
> Unfortunately, this script hangs both in Pharo3 and Pharo4 (OS X 10.10, Pharo 30856 and 40611).
> When I interrupt with Cmd+. the debugger shows the method
>     Socket>>waitForDataIfClosed:
> and the hang is apparently in the line
>     self readSemaphore wait
>
> Could anyone give me some advice if I should to do this differently or what the issue with the Pharo script is?
>
> Thanks in advance,
> Manfred



Reply | Threaded
Open this post in threaded view
|

Re: Issue with UDP Sockets

Sven Van Caekenberghe-2

> On 18 May 2015, at 12:44, Manfred Kröhnert <[hidden email]> wrote:
>
> Hello Sven,
>
> thanks for your fast reply.
>
> On Mon, May 18, 2015 at 11:41 AM, Sven Van Caekenberghe <[hidden email]> wrote:
> Hi Manfred,
>
> Did you see/study the example/test UDPSocketEchoTest ?
>
> unfortunately I did not see this class, yet.
> But I did look at the Socket class itself and Socket>>timeTestUDP (in Pharo3).

We removed #timeTestUDP in Pharo 4 and higher, I believe, and replaced it with proper tests/examples.

> Also, UDP is very primitive: it is send and forget, returns no errors, and is totally asynchronous. Listening should best be done in a separate process.
>
> Yes, UDP is primitive but the SSDP specification requires using UDP.
>
> Here is how I would write your send part:
>
>  | message udpSocket |
>   message := String crlf join: #(
>    'M-SEARCH * HTTP/1.1'
>    'HOST:239.255.255.250:1900'
>    'MAN:"ssdp:discover'
>    'ST:ssdp:all'
>    'MX:1'
>    '').
>
>   udpSocket := Socket newUDP.
>   udpSocket sendData: message toHost: #[239 255 255 250] port: 1900.
>   udpSocket waitForSendDoneFor: 5.
>   udpSocket closeAndDestroy.
>
> Thanks for this snippet.
> For some reasons I do not understand yet, this gives me the expected result in contrast to my own version.
>
> I modified it like this to print the results on the Transcript:
>
> | message udpSocket |
>   message := String crlf join: #(
>    'M-SEARCH * HTTP/1.1'
>    'HOST:239.255.255.250:1900'
>    'MAN:"ssdp:discover"'
>    'ST:ssdp:all'
>    'MX:1'
>    '').
>
>   udpSocket := Socket newUDP.
>   udpSocket sendData: message toHost: #[239 255 255 250] port: 1900.
>   udpSocket waitForSendDoneFor: 5.
>   udpSocket waitForData.
>   [udpSocket dataAvailable ] whileTrue: [ | buffer |
>     buffer := ByteArray new: 1024.
>     udpSocket receiveUDPDataInto: buffer.
>     Transcript show: 'Received: ', buffer.
>     [udpSocket waitForDataFor: 1] on: Error do: [  ].
>   ].
>   udpSocket closeAndDestroy.
>
> Currently, this will work for me, since I am not interested in continuously detecting new devices.
> But you mentioned reading should in general be done in a separate process.
> Would you reuse the existing udpSocket instance in this case or create a separate one for reading?

I think if it is only for a one time use, it is OK like you are doing it.

> Maybe nothing came back because the line ends where wrong ?
>
> The lineendings I used are required by the SSDP specification.

I meant that writing '\r\n' has no effect in Pharo, this is not processed (you could do this manually, of course). This is why I did it with the #join:

That is the difference and why it works now, I guess.

> HTH,
>
> Sven
>
> Thanks,
> Manfred
>  
> > On 18 May 2015, at 11:29, Manfred Kröhnert <[hidden email]> wrote:
> >
> > Hello everyone,
> >
> > I am currently trying to get a list of UPnP device via SSDP (Simple Service Discovery Protocol).
> >
> > A minimalistic working NodeJS example looks like this:
> >
> >     var dgram = require('dgram');
> >     var message = new Buffer(
> >         "M-SEARCH * HTTP/1.1\r\n" +
> >         "HOST:239.255.255.250:1900\r\n" +
> >         "MAN:\"ssdp:discover\"\r\n" +
> >         "ST:ssdp:all\r\n" +
> >         "MX:1\r\n" +
> >         "\r\n"
> >     );
> >
> >     var client = dgram.createSocket("udp4");
> >
> >     client.on("message", function (msg, rinfo) {
> >         console.log("server got: " + msg + " from " + rinfo.address + ":" + rinfo.port);
> >     });
> >     client.send(message, 0, message.length, 1900, "239.255.255.250");
> >     client.close();
> >
> > I tried to recreate the same functionality in Pharo with the following piece of code:
> >
> >   | message udpSocket host |
> >   message := 'M-SEARCH * HTTP/1.1\r\n' ,
> >     'HOST:239.255.255.250:1900\r\n' ,
> >     'MAN:"ssdp:discover"\r\n' ,
> >     'ST:ssdp:all\r\n' ,
> >     'MX:1\r\n' , '\r\n'.
> >
> >   udpSocket := Socket newUDP.
> >   host :=  (NetNameResolver addressFromString: '239.255.255.250').
> >   udpSocket sendData: message toHost: host port: 1900.
> >   "udpSocket waitForData."
> >   Transcript show: 'Received: ' , udpSocket receiveData.
> >   udpSocket closeAndDestroy.
> >
> > Unfortunately, this script hangs both in Pharo3 and Pharo4 (OS X 10.10, Pharo 30856 and 40611).
> > When I interrupt with Cmd+. the debugger shows the method
> >     Socket>>waitForDataIfClosed:
> > and the hang is apparently in the line
> >     self readSemaphore wait
> >
> > Could anyone give me some advice if I should to do this differently or what the issue with the Pharo script is?
> >
> > Thanks in advance,
> > Manfred
>
>
>


Reply | Threaded
Open this post in threaded view
|

Re: Issue with UDP Sockets

Manfred Kröhnert
Thanks for the explanation.

Best,
Manfred


On Mon, May 18, 2015 at 12:49 PM, Sven Van Caekenberghe <[hidden email]> wrote:

> On 18 May 2015, at 12:44, Manfred Kröhnert <[hidden email]> wrote:
>
> Hello Sven,
>
> thanks for your fast reply.
>
> On Mon, May 18, 2015 at 11:41 AM, Sven Van Caekenberghe <[hidden email]> wrote:
> Hi Manfred,
>
> Did you see/study the example/test UDPSocketEchoTest ?
>
> unfortunately I did not see this class, yet.
> But I did look at the Socket class itself and Socket>>timeTestUDP (in Pharo3).

We removed #timeTestUDP in Pharo 4 and higher, I believe, and replaced it with proper tests/examples.

> Also, UDP is very primitive: it is send and forget, returns no errors, and is totally asynchronous. Listening should best be done in a separate process.
>
> Yes, UDP is primitive but the SSDP specification requires using UDP.
>
> Here is how I would write your send part:
>
>  | message udpSocket |
>   message := String crlf join: #(
>    'M-SEARCH * HTTP/1.1'
>    'HOST:239.255.255.250:1900'
>    'MAN:"ssdp:discover'
>    'ST:ssdp:all'
>    'MX:1'
>    '').
>
>   udpSocket := Socket newUDP.
>   udpSocket sendData: message toHost: #[239 255 255 250] port: 1900.
>   udpSocket waitForSendDoneFor: 5.
>   udpSocket closeAndDestroy.
>
> Thanks for this snippet.
> For some reasons I do not understand yet, this gives me the expected result in contrast to my own version.
>
> I modified it like this to print the results on the Transcript:
>
> | message udpSocket |
>   message := String crlf join: #(
>    'M-SEARCH * HTTP/1.1'
>    'HOST:239.255.255.250:1900'
>    'MAN:"ssdp:discover"'
>    'ST:ssdp:all'
>    'MX:1'
>    '').
>
>   udpSocket := Socket newUDP.
>   udpSocket sendData: message toHost: #[239 255 255 250] port: 1900.
>   udpSocket waitForSendDoneFor: 5.
>   udpSocket waitForData.
>   [udpSocket dataAvailable ] whileTrue: [ | buffer |
>     buffer := ByteArray new: 1024.
>     udpSocket receiveUDPDataInto: buffer.
>     Transcript show: 'Received: ', buffer.
>     [udpSocket waitForDataFor: 1] on: Error do: [  ].
>   ].
>   udpSocket closeAndDestroy.
>
> Currently, this will work for me, since I am not interested in continuously detecting new devices.
> But you mentioned reading should in general be done in a separate process.
> Would you reuse the existing udpSocket instance in this case or create a separate one for reading?

I think if it is only for a one time use, it is OK like you are doing it.

> Maybe nothing came back because the line ends where wrong ?
>
> The lineendings I used are required by the SSDP specification.

I meant that writing '\r\n' has no effect in Pharo, this is not processed (you could do this manually, of course). This is why I did it with the #join:

That is the difference and why it works now, I guess.

> HTH,
>
> Sven
>
> Thanks,
> Manfred
>
> > On 18 May 2015, at 11:29, Manfred Kröhnert <[hidden email]> wrote:
> >
> > Hello everyone,
> >
> > I am currently trying to get a list of UPnP device via SSDP (Simple Service Discovery Protocol).
> >
> > A minimalistic working NodeJS example looks like this:
> >
> >     var dgram = require('dgram');
> >     var message = new Buffer(
> >         "M-SEARCH * HTTP/1.1\r\n" +
> >         "HOST:239.255.255.250:1900\r\n" +
> >         "MAN:\"ssdp:discover\"\r\n" +
> >         "ST:ssdp:all\r\n" +
> >         "MX:1\r\n" +
> >         "\r\n"
> >     );
> >
> >     var client = dgram.createSocket("udp4");
> >
> >     client.on("message", function (msg, rinfo) {
> >         console.log("server got: " + msg + " from " + rinfo.address + ":" + rinfo.port);
> >     });
> >     client.send(message, 0, message.length, 1900, "239.255.255.250");
> >     client.close();
> >
> > I tried to recreate the same functionality in Pharo with the following piece of code:
> >
> >   | message udpSocket host |
> >   message := 'M-SEARCH * HTTP/1.1\r\n' ,
> >     'HOST:239.255.255.250:1900\r\n' ,
> >     'MAN:"ssdp:discover"\r\n' ,
> >     'ST:ssdp:all\r\n' ,
> >     'MX:1\r\n' , '\r\n'.
> >
> >   udpSocket := Socket newUDP.
> >   host :=  (NetNameResolver addressFromString: '239.255.255.250').
> >   udpSocket sendData: message toHost: host port: 1900.
> >   "udpSocket waitForData."
> >   Transcript show: 'Received: ' , udpSocket receiveData.
> >   udpSocket closeAndDestroy.
> >
> > Unfortunately, this script hangs both in Pharo3 and Pharo4 (OS X 10.10, Pharo 30856 and 40611).
> > When I interrupt with Cmd+. the debugger shows the method
> >     Socket>>waitForDataIfClosed:
> > and the hang is apparently in the line
> >     self readSemaphore wait
> >
> > Could anyone give me some advice if I should to do this differently or what the issue with the Pharo script is?
> >
> > Thanks in advance,
> > Manfred
>
>
>



Reply | Threaded
Open this post in threaded view
|

Re: Issue with UDP Sockets

Ben Coman
In reply to this post by Sven Van Caekenberghe-2


On Mon, May 18, 2015 at 6:49 PM, Sven Van Caekenberghe <[hidden email]> wrote:

I meant that writing '\r\n' has no effect in Pharo, this is not processed (you could do this manually, of course). 

Is this something we should consider implementing to ease the way for newcomers?  What downsides can you think of?
cheers -ben

Reply | Threaded
Open this post in threaded view
|

Re: Issue with UDP Sockets

Sven Van Caekenberghe-2

> On 18 May 2015, at 14:31, Ben Coman <[hidden email]> wrote:
>
>
>
> On Mon, May 18, 2015 at 6:49 PM, Sven Van Caekenberghe <[hidden email]> wrote:
>
> I meant that writing '\r\n' has no effect in Pharo, this is not processed (you could do this manually, of course).
>
> Is this something we should consider implementing to ease the way for newcomers?  What downsides can you think of?
> cheers -ben

Nah, even in C, you need (s)printf for escape sequences to be interpreted.

In any case, without error handling, this will do:

| input escapes |
escapes := { $n -> Character cr. $r -> Character lf. $\ -> $\ } asDictionary.
input := 'foo\\bar\n\r'.
String streamContents: [ :out |
  | in ch |
  in := input readStream.
  [ in atEnd ] whileFalse: [
    ch := in next.
    ch = $\
      ifTrue: [ out nextPut: (escapes at: in next) ]
      ifFalse: [ out nextPut: ch ] ] ]

Sven
Reply | Threaded
Open this post in threaded view
|

Re: Issue with UDP Sockets

Manfred Kröhnert
Hi,
apparently I am missing something else.

I can find devices when connected to a 'regular' LAN.

However, I have a camera that creates a Wifi accesspoint and makes itself discoverable via SSDP.
Once I connect to this accesspoint my computer gets a valid IP address assigned and the NodeJS code is able to discover the device.
Unfortunately, the Pharo snippet I posted before does not give me any results and hangs in Socket>>waitForDataIfClosed: .

Any further ideas?

Thanks,
Manfred
Reply | Threaded
Open this post in threaded view
|

Re: Issue with UDP Sockets

Sven Van Caekenberghe-2

> On 18 May 2015, at 15:47, Manfred Kröhnert <[hidden email]> wrote:
>
> Hi,
> apparently I am missing something else.
>
> I can find devices when connected to a 'regular' LAN.
>
> However, I have a camera that creates a Wifi accesspoint and makes itself discoverable via SSDP.
> Once I connect to this accesspoint my computer gets a valid IP address assigned and the NodeJS code is able to discover the device.
> Unfortunately, the Pharo snippet I posted before does not give me any results and hangs in Socket>>waitForDataIfClosed: .
>
> Any further ideas?

Are you sure you restarted the image and your code after switching networks ?

> Thanks,
> Manfred


Reply | Threaded
Open this post in threaded view
|

Re: Issue with UDP Sockets

Manfred Kröhnert
Hi Sven,

On Mon, May 18, 2015 at 4:14 PM, Sven Van Caekenberghe <[hidden email]> wrote:

> On 18 May 2015, at 15:47, Manfred Kröhnert <[hidden email]> wrote:
>
> Hi,
> apparently I am missing something else.
>
> I can find devices when connected to a 'regular' LAN.
>
> However, I have a camera that creates a Wifi accesspoint and makes itself discoverable via SSDP.
> Once I connect to this accesspoint my computer gets a valid IP address assigned and the NodeJS code is able to discover the device.
> Unfortunately, the Pharo snippet I posted before does not give me any results and hangs in Socket>>waitForDataIfClosed: .
>
> Any further ideas?

Are you sure you restarted the image and your code after switching networks ?

I did not check this before.
But I just downloaded a fresh 40613 image with PharoLauncher and started it after connecting to the camera accesspoint.
The code snippet freezes there as well.

Manfred
Reply | Threaded
Open this post in threaded view
|

Re: Issue with UDP Sockets

Sven Van Caekenberghe-2

> On 18 May 2015, at 16:34, Manfred Kröhnert <[hidden email]> wrote:
>
> Hi Sven,
>
> On Mon, May 18, 2015 at 4:14 PM, Sven Van Caekenberghe <[hidden email]> wrote:
>
> > On 18 May 2015, at 15:47, Manfred Kröhnert <[hidden email]> wrote:
> >
> > Hi,
> > apparently I am missing something else.
> >
> > I can find devices when connected to a 'regular' LAN.
> >
> > However, I have a camera that creates a Wifi accesspoint and makes itself discoverable via SSDP.
> > Once I connect to this accesspoint my computer gets a valid IP address assigned and the NodeJS code is able to discover the device.
> > Unfortunately, the Pharo snippet I posted before does not give me any results and hangs in Socket>>waitForDataIfClosed: .
> >
> > Any further ideas?
>
> Are you sure you restarted the image and your code after switching networks ?
>
> I did not check this before.
> But I just downloaded a fresh 40613 image with PharoLauncher and started it after connecting to the camera accesspoint.
> The code snippet freezes there as well.
>
> Manfred

I don't know then, I used the UDP stuff before in various applications and it worked fine. Just like with all networking code, you sometimes get in a stuck state when developing (i.e. running incomplete code).

Getting stuck means you are waiting forever for an answer that is not coming.

From a distance I can't help much more, just double check that your initial message is completely correct and that you send it to the right host:port.

Sven





Reply | Threaded
Open this post in threaded view
|

Re: Issue with UDP Sockets

Henrik Sperre Johansen

> On 18 May 2015, at 4:44 , Sven Van Caekenberghe <[hidden email]> wrote:
>
>
>> On 18 May 2015, at 16:34, Manfred Kröhnert <[hidden email]> wrote:
>>
>> Hi Sven,
>>
>> On Mon, May 18, 2015 at 4:14 PM, Sven Van Caekenberghe <[hidden email]> wrote:
>>
>>> On 18 May 2015, at 15:47, Manfred Kröhnert <[hidden email]> wrote:
>>>
>>> Hi,
>>> apparently I am missing something else.
>>>
>>> I can find devices when connected to a 'regular' LAN.
>>>
>>> However, I have a camera that creates a Wifi accesspoint and makes itself discoverable via SSDP.
>>> Once I connect to this accesspoint my computer gets a valid IP address assigned and the NodeJS code is able to discover the device.
>>> Unfortunately, the Pharo snippet I posted before does not give me any results and hangs in Socket>>waitForDataIfClosed: .
>>>
>>> Any further ideas?
>>
>> Are you sure you restarted the image and your code after switching networks ?
>>
>> I did not check this before.
>> But I just downloaded a fresh 40613 image with PharoLauncher and started it after connecting to the camera accesspoint.
>> The code snippet freezes there as well.
>>
>> Manfred

The socket API is a bit confusing, since it mixes together the API's that match the primitives for sending/receiving TCP/UDP.
To receive UDP data on the socket, you need something like:

| message udpSocket host buffer read|
  message := (String crlf join: #('M-SEARCH * HTTP/1.1'
    'HOST:239.255.255.250:1900'
    'MAN:"ssdp:discover"'
    'ST:ssdp:all'
    'MX:1')).

  udpSocket := Socket newUDP.
  host :=  (NetNameResolver addressFromString: '239.255.255.250').
  udpSocket sendData: message toHost: host port: 1900.
buffer := String new:4096.
"MX:1 means we expect replies within 1 second, let's be on the safe side and wait 2"
2 seconds wait.
read := 1.
[read > 0] whileTrue: [
read := (udpSocket receiveUDPDataInto: buffer) first.
Transcript show: (buffer copyFrom:1 to:read)]

Cheers,
Henry
Reply | Threaded
Open this post in threaded view
|

Re: Issue with UDP Sockets

Henrik Sperre Johansen
Hupps, was reading the old code, I guess this isn't applicable.
Sorry :/

> On 18 May 2015, at 5:15 , Henrik Johansen <[hidden email]> wrote:
>
>
>> On 18 May 2015, at 4:44 , Sven Van Caekenberghe <[hidden email]> wrote:
>>
>>
>>> On 18 May 2015, at 16:34, Manfred Kröhnert <[hidden email]> wrote:
>>>
>>> Hi Sven,
>>>
>>> On Mon, May 18, 2015 at 4:14 PM, Sven Van Caekenberghe <[hidden email]> wrote:
>>>
>>>> On 18 May 2015, at 15:47, Manfred Kröhnert <[hidden email]> wrote:
>>>>
>>>> Hi,
>>>> apparently I am missing something else.
>>>>
>>>> I can find devices when connected to a 'regular' LAN.
>>>>
>>>> However, I have a camera that creates a Wifi accesspoint and makes itself discoverable via SSDP.
>>>> Once I connect to this accesspoint my computer gets a valid IP address assigned and the NodeJS code is able to discover the device.
>>>> Unfortunately, the Pharo snippet I posted before does not give me any results and hangs in Socket>>waitForDataIfClosed: .
>>>>
>>>> Any further ideas?
>>>
>>> Are you sure you restarted the image and your code after switching networks ?
>>>
>>> I did not check this before.
>>> But I just downloaded a fresh 40613 image with PharoLauncher and started it after connecting to the camera accesspoint.
>>> The code snippet freezes there as well.
>>>
>>> Manfred
>
> The socket API is a bit confusing, since it mixes together the API's that match the primitives for sending/receiving TCP/UDP.
> To receive UDP data on the socket, you need something like:
>
> | message udpSocket host buffer read|
>  message := (String crlf join: #('M-SEARCH * HTTP/1.1'
>    'HOST:239.255.255.250:1900'
>    'MAN:"ssdp:discover"'
>    'ST:ssdp:all'
>    'MX:1')).
>
>  udpSocket := Socket newUDP.
>  host :=  (NetNameResolver addressFromString: '239.255.255.250').
>  udpSocket sendData: message toHost: host port: 1900.
> buffer := String new:4096.
> "MX:1 means we expect replies within 1 second, let's be on the safe side and wait 2"
> 2 seconds wait.
> read := 1.
> [read > 0] whileTrue: [
> read := (udpSocket receiveUDPDataInto: buffer) first.
> Transcript show: (buffer copyFrom:1 to:read)]
>
> Cheers,
> Henry


Reply | Threaded
Open this post in threaded view
|

Re: Issue with UDP Sockets

Udo Schneider
In reply to this post by Manfred Kröhnert
Hi Manfred,

I just stumbled over the IP address you are using (239.255.255.250). If
I remember correctly this is a IPv4 Class D Multicast address.
(224.0.0.0-239.255.255.255).

So if you want to transmit datagrams to this IP address or recieve
datagrams sent to this multicast groups you have to set appropriate IP
Options.

You can set this options using Socket>>#setOption:value: and read them
using Socket>>#getOption:. Please note that both methods expect the
option to set as a name - not as constant. E.g.

socket setOption: 'IP_MULTICAST_IF' value: multicastInterface.

If I do remember correctly you have to set the following options for
sending/receiving:

Sending:
IP_MULTICAST_IF
(IP_MULTICAST_LOOP)
(IP_MULTICAST_TTL)

Sending should AFAIK work w/o setting any option - although
IP_MULTICAST_IF is highly recommended.

Receiving:
(SO_REUSEADDR)
IP_ADD_MEMBERSHIP
(IP_DROP_MEMBERSHIP)

Receiving only works if you joined the multicast group previously. So I
assume that you need to do something like this (not tested).

imrMultiaddr := #[239 255 255 250].
imrInterface := #[0 0 0 0].
ipMreq := imrMultiaddr , imrInterface.
socket setOption: 'MEMBERSHIP' value: ipMreq.

Hope this helps.

CU,

Udo



On 18/05/15 16:34, Manfred Kröhnert wrote:

> Hi Sven,
>
> On Mon, May 18, 2015 at 4:14 PM, Sven Van Caekenberghe
> <[hidden email]
> <mailto:[hidden email]>> wrote:
>
>
>      > On 18 May 2015, at 15:47, Manfred Kröhnert
>     <[hidden email]
>     <mailto:[hidden email]>> wrote:
>      >
>      > Hi,
>      > apparently I am missing something else.
>      >
>      > I can find devices when connected to a 'regular' LAN.
>      >
>      > However, I have a camera that creates a Wifi accesspoint and
>     makes itself discoverable via SSDP.
>      > Once I connect to this accesspoint my computer gets a valid IP
>     address assigned and the NodeJS code is able to discover the device.
>      > Unfortunately, the Pharo snippet I posted before does not give me
>     any results and hangs in Socket>>waitForDataIfClosed: .
>      >
>      > Any further ideas?
>
>     Are you sure you restarted the image and your code after switching
>     networks ?
>
>
> I did not check this before.
> But I just downloaded a fresh 40613 image with PharoLauncher and started
> it after connecting to the camera accesspoint.
> The code snippet freezes there as well.
>
> Manfred



Reply | Threaded
Open this post in threaded view
|

Re: Issue with UDP Sockets

Manfred Kröhnert
Hello Udo,

thanks for your detailed reply.
I am going to try your suggestions and report back afterwards.
Not sure though if I get to try it before next weekend.

The address I am sending to is definitely a multi-cast address (as defined in the SSDP spec).
But what makes me wonder is why the minimal NodeJS example works in both cases without modifications (regular router/accesspoint + camera accesspoint) and the Pharo one only receives data in the first case.
But maybe there is something happening behind the curtains in NodeJS when it comes to multi-cast addresses.

Thanks,
Manfred


On Mon, May 18, 2015 at 11:29 PM, Udo Schneider <[hidden email]> wrote:
Hi Manfred,

I just stumbled over the IP address you are using (239.255.255.250). If I remember correctly this is a IPv4 Class D Multicast address. (224.0.0.0-239.255.255.255).

So if you want to transmit datagrams to this IP address or recieve datagrams sent to this multicast groups you have to set appropriate IP Options.

You can set this options using Socket>>#setOption:value: and read them using Socket>>#getOption:. Please note that both methods expect the option to set as a name - not as constant. E.g.

socket setOption: 'IP_MULTICAST_IF' value: multicastInterface.

If I do remember correctly you have to set the following options for sending/receiving:

Sending:
IP_MULTICAST_IF
(IP_MULTICAST_LOOP)
(IP_MULTICAST_TTL)

Sending should AFAIK work w/o setting any option - although IP_MULTICAST_IF is highly recommended.

Receiving:
(SO_REUSEADDR)
IP_ADD_MEMBERSHIP
(IP_DROP_MEMBERSHIP)

Receiving only works if you joined the multicast group previously. So I assume that you need to do something like this (not tested).

imrMultiaddr := #[239 255 255 250].
imrInterface := #[0 0 0 0].
ipMreq := imrMultiaddr , imrInterface.
socket setOption: 'MEMBERSHIP' value: ipMreq.

Hope this helps.

CU,

Udo



On 18/05/15 16:34, Manfred Kröhnert wrote:
Hi Sven,

On Mon, May 18, 2015 at 4:14 PM, Sven Van Caekenberghe
<[hidden email]
<mailto:[hidden email]>> wrote:


     > On 18 May 2015, at 15:47, Manfred Kröhnert
    <[hidden email]
    <mailto:[hidden email]>> wrote:
     >
     > Hi,
     > apparently I am missing something else.
     >
     > I can find devices when connected to a 'regular' LAN.
     >
     > However, I have a camera that creates a Wifi accesspoint and
    makes itself discoverable via SSDP.
     > Once I connect to this accesspoint my computer gets a valid IP
    address assigned and the NodeJS code is able to discover the device.
     > Unfortunately, the Pharo snippet I posted before does not give me
    any results and hangs in Socket>>waitForDataIfClosed: .
     >
     > Any further ideas?

    Are you sure you restarted the image and your code after switching
    networks ?


I did not check this before.
But I just downloaded a fresh 40613 image with PharoLauncher and started
it after connecting to the camera accesspoint.
The code snippet freezes there as well.

Manfred




Reply | Threaded
Open this post in threaded view
|

Re: Issue with UDP Sockets

Udo Schneider
In reply to this post by Udo Schneider
This should have been 'IP_ADD_MEMBERSHIP' of course:

imrMultiaddr := #[239 255 255 250].
imrInterface := #[0 0 0 0].
ipMreq := imrMultiaddr , imrInterface.
socket setOption: 'IP_ADD_MEMBERSHIP' value: ipMreq.


The "server" could be something like this (execute in first playground).
I used another IP address (#[239 255 255 251]) because #[239 255 255
250] might already be part of the multicast group because of other
processes and this shows the "whole" process of subscribing to a
multicast group:

[
|  udpSocket |
   udpSocket := Socket newUDP.
   udpSocket setPort: 1900.
   imrMultiaddr := #[239 255 255 251].
   imrInterface := #[0 0 0 0].
   ipMreq := imrMultiaddr , imrInterface.
   udpSocket setOption: 'IP_ADD_MEMBERSHIP' value: ipMreq.
   udpSocket setOption: 'IP_MULTICAST_LOOP' value: 1.
   "udpSocket setOption: 'SO_REUSEADDR' value: 1."
   udpSocket waitForData.
   buffer := ByteArray new: 256.
   data := udpSocket receiveUDPDataInto: buffer.
   bytesRead := data at: 1.
   sender := data at: 2.
   senderPort := data at: 3.
   more := data at: 4.
   result := buffer copyFrom: 1 to: bytesRead.
   udpSocket closeAndDestroy.
   result asString inspect.
] fork.



The "client" (execute in different playground):
| message udpSocket |
   message := String crlf join: #(
    'M-SEARCH * HTTP/1.1'
    'HOST:239.255.255.250:1900'
    'MAN:"ssdp:discover'
    'ST:ssdp:all'
    'MX:1'
    '').

   udpSocket := Socket newUDP.
   udpSocket sendData: message toHost: #[239 255 255 251] port: 1900.
   (udpSocket waitForSendDoneFor: 5).
   udpSocket closeAndDestroy.

Hope this helps.

CU,

Udo






On 18/05/15 23:29, Udo Schneider wrote:

> Hi Manfred,
>
> I just stumbled over the IP address you are using (239.255.255.250). If
> I remember correctly this is a IPv4 Class D Multicast address.
> (224.0.0.0-239.255.255.255).
>
> So if you want to transmit datagrams to this IP address or recieve
> datagrams sent to this multicast groups you have to set appropriate IP
> Options.
>
> You can set this options using Socket>>#setOption:value: and read them
> using Socket>>#getOption:. Please note that both methods expect the
> option to set as a name - not as constant. E.g.
>
> socket setOption: 'IP_MULTICAST_IF' value: multicastInterface.
>
> If I do remember correctly you have to set the following options for
> sending/receiving:
>
> Sending:
> IP_MULTICAST_IF
> (IP_MULTICAST_LOOP)
> (IP_MULTICAST_TTL)
>
> Sending should AFAIK work w/o setting any option - although
> IP_MULTICAST_IF is highly recommended.
>
> Receiving:
> (SO_REUSEADDR)
> IP_ADD_MEMBERSHIP
> (IP_DROP_MEMBERSHIP)
>
> Receiving only works if you joined the multicast group previously. So I
> assume that you need to do something like this (not tested).
>
> imrMultiaddr := #[239 255 255 250].
> imrInterface := #[0 0 0 0].
> ipMreq := imrMultiaddr , imrInterface.
> socket setOption: 'MEMBERSHIP' value: ipMreq.
>
> Hope this helps.
>
> CU,
>
> Udo
>
>
>
> On 18/05/15 16:34, Manfred Kröhnert wrote:
>> Hi Sven,
>>
>> On Mon, May 18, 2015 at 4:14 PM, Sven Van Caekenberghe
>> <[hidden email]
>> <mailto:[hidden email]>> wrote:
>>
>>
>>      > On 18 May 2015, at 15:47, Manfred Kröhnert
>>     <[hidden email]
>>     <mailto:[hidden email]>> wrote:
>>      >
>>      > Hi,
>>      > apparently I am missing something else.
>>      >
>>      > I can find devices when connected to a 'regular' LAN.
>>      >
>>      > However, I have a camera that creates a Wifi accesspoint and
>>     makes itself discoverable via SSDP.
>>      > Once I connect to this accesspoint my computer gets a valid IP
>>     address assigned and the NodeJS code is able to discover the device.
>>      > Unfortunately, the Pharo snippet I posted before does not give me
>>     any results and hangs in Socket>>waitForDataIfClosed: .
>>      >
>>      > Any further ideas?
>>
>>     Are you sure you restarted the image and your code after switching
>>     networks ?
>>
>>
>> I did not check this before.
>> But I just downloaded a fresh 40613 image with PharoLauncher and started
>> it after connecting to the camera accesspoint.
>> The code snippet freezes there as well.
>>
>> Manfred
>
>
>
>



Reply | Threaded
Open this post in threaded view
|

Re: Issue with UDP Sockets

Ben Coman
Ultimate fallback, use Wireshark to compare packets on the wire between using node.js and Pharo.
cheers -ben

On Tue, May 19, 2015 at 6:17 AM, Udo Schneider <[hidden email]> wrote:
This should have been 'IP_ADD_MEMBERSHIP' of course:

imrMultiaddr := #[239 255 255 250].
imrInterface := #[0 0 0 0].
ipMreq := imrMultiaddr , imrInterface.
socket setOption: 'IP_ADD_MEMBERSHIP' value: ipMreq.


The "server" could be something like this (execute in first playground). I used another IP address (#[239 255 255 251]) because #[239 255 255 250] might already be part of the multicast group because of other processes and this shows the "whole" process of subscribing to a multicast group:

[
|  udpSocket |
  udpSocket := Socket newUDP.
  udpSocket setPort: 1900.
  imrMultiaddr := #[239 255 255 251].
  imrInterface := #[0 0 0 0].
  ipMreq := imrMultiaddr , imrInterface.
  udpSocket setOption: 'IP_ADD_MEMBERSHIP' value: ipMreq.
  udpSocket setOption: 'IP_MULTICAST_LOOP' value: 1.
  "udpSocket setOption: 'SO_REUSEADDR' value: 1."
  udpSocket waitForData.
  buffer := ByteArray new: 256.
  data := udpSocket receiveUDPDataInto: buffer.
  bytesRead := data at: 1.
  sender := data at: 2.
  senderPort := data at: 3.
  more := data at: 4.
  result := buffer copyFrom: 1 to: bytesRead.
  udpSocket closeAndDestroy.
  result asString inspect.
] fork.



The "client" (execute in different playground):
| message udpSocket |
  message := String crlf join: #(
   'M-SEARCH * HTTP/1.1'
   'HOST:239.255.255.250:1900'
   'MAN:"ssdp:discover'
   'ST:ssdp:all'
   'MX:1'
   '').

  udpSocket := Socket newUDP.
  udpSocket sendData: message toHost: #[239 255 255 251] port: 1900.
  (udpSocket waitForSendDoneFor: 5).
  udpSocket closeAndDestroy.

Hope this helps.

CU,

Udo






On 18/05/15 23:29, Udo Schneider wrote:
Hi Manfred,

I just stumbled over the IP address you are using (239.255.255.250). If
I remember correctly this is a IPv4 Class D Multicast address.
(224.0.0.0-239.255.255.255).

So if you want to transmit datagrams to this IP address or recieve
datagrams sent to this multicast groups you have to set appropriate IP
Options.

You can set this options using Socket>>#setOption:value: and read them
using Socket>>#getOption:. Please note that both methods expect the
option to set as a name - not as constant. E.g.

socket setOption: 'IP_MULTICAST_IF' value: multicastInterface.

If I do remember correctly you have to set the following options for
sending/receiving:

Sending:
IP_MULTICAST_IF
(IP_MULTICAST_LOOP)
(IP_MULTICAST_TTL)

Sending should AFAIK work w/o setting any option - although
IP_MULTICAST_IF is highly recommended.

Receiving:
(SO_REUSEADDR)
IP_ADD_MEMBERSHIP
(IP_DROP_MEMBERSHIP)

Receiving only works if you joined the multicast group previously. So I
assume that you need to do something like this (not tested).

imrMultiaddr := #[239 255 255 250].
imrInterface := #[0 0 0 0].
ipMreq := imrMultiaddr , imrInterface.
socket setOption: 'MEMBERSHIP' value: ipMreq.

Hope this helps.

CU,

Udo



On 18/05/15 16:34, Manfred Kröhnert wrote:
Hi Sven,

On Mon, May 18, 2015 at 4:14 PM, Sven Van Caekenberghe
<[hidden email]
<mailto:[hidden email]>> wrote:


     > On 18 May 2015, at 15:47, Manfred Kröhnert
    <[hidden email]
    <mailto:[hidden email]>> wrote:
     >
     > Hi,
     > apparently I am missing something else.
     >
     > I can find devices when connected to a 'regular' LAN.
     >
     > However, I have a camera that creates a Wifi accesspoint and
    makes itself discoverable via SSDP.
     > Once I connect to this accesspoint my computer gets a valid IP
    address assigned and the NodeJS code is able to discover the device.
     > Unfortunately, the Pharo snippet I posted before does not give me
    any results and hangs in Socket>>waitForDataIfClosed: .
     >
     > Any further ideas?

    Are you sure you restarted the image and your code after switching
    networks ?


I did not check this before.
But I just downloaded a fresh 40613 image with PharoLauncher and started
it after connecting to the camera accesspoint.
The code snippet freezes there as well.

Manfred








Reply | Threaded
Open this post in threaded view
|

Re: Issue with UDP Sockets

Udo Schneider
True - having Wireshark is always a good idea. Just a warning in the
multicast context though:
The fact that Wireshark sees multicast datagrams (when recieving) does
only imply that your NIC is in promiscuous mode or that /a/ process on
the node did subscribe to the multicast group. It does not necessarily
mean that /your/ process will get the datagram via it's socket.

Debugging multicast is a little bit tricky. With unicast or broadcast
datagrams (doesn't matter if Ethernet or IP) it's quite easy:
The NIC accepts every Broadcast L2 datagram and forwards it to the IP
stack which processes every L3 broadcast datagram.
For unicast the NIC only accepts datagrams sent to it's MAC address and
the IP stack only processes them when sent to (one if) it's IP addresses.
With multicast being "something in between" you have to convince the NIC
(IP Multicast addresses map to specific Ethernet MACs) and the IP Stack
to process the datagram although it's neither directly sent to their
MAC/IP nor a broadcast.

CU,

Udo

On 19/05/15 04:17, Ben Coman wrote:

> Ultimate fallback, use Wireshark to compare packets on the wire between
> using node.js and Pharo.
> http://en.wikiversity.org/wiki/Wireshark/IPv4_multicast
> cheers -ben
>
> On Tue, May 19, 2015 at 6:17 AM, Udo Schneider
> <[hidden email]
> <mailto:[hidden email]>> wrote:
>
>     This should have been 'IP_ADD_MEMBERSHIP' of course:
>
>     imrMultiaddr := #[239 255 255 250].
>     imrInterface := #[0 0 0 0].
>     ipMreq := imrMultiaddr , imrInterface.
>     socket setOption: 'IP_ADD_MEMBERSHIP' value: ipMreq.
>
>
>     The "server" could be something like this (execute in first
>     playground). I used another IP address (#[239 255 255 251]) because
>     #[239 255 255 250] might already be part of the multicast group
>     because of other processes and this shows the "whole" process of
>     subscribing to a multicast group:
>
>     [
>     |  udpSocket |
>        udpSocket := Socket newUDP.
>        udpSocket setPort: 1900.
>        imrMultiaddr := #[239 255 255 251].
>        imrInterface := #[0 0 0 0].
>        ipMreq := imrMultiaddr , imrInterface.
>        udpSocket setOption: 'IP_ADD_MEMBERSHIP' value: ipMreq.
>        udpSocket setOption: 'IP_MULTICAST_LOOP' value: 1.
>        "udpSocket setOption: 'SO_REUSEADDR' value: 1."
>        udpSocket waitForData.
>        buffer := ByteArray new: 256.
>        data := udpSocket receiveUDPDataInto: buffer.
>        bytesRead := data at: 1.
>        sender := data at: 2.
>        senderPort := data at: 3.
>        more := data at: 4.
>        result := buffer copyFrom: 1 to: bytesRead.
>        udpSocket closeAndDestroy.
>        result asString inspect.
>     ] fork.
>
>
>
>     The "client" (execute in different playground):
>     | message udpSocket |
>        message := String crlf join: #(
>         'M-SEARCH * HTTP/1.1'
>         'HOST:239.255.255.250:1900 <http://239.255.255.250:1900>'
>         'MAN:"ssdp:discover'
>         'ST:ssdp:all'
>         'MX:1'
>         '').
>
>        udpSocket := Socket newUDP.
>        udpSocket sendData: message toHost: #[239 255 255 251] port: 1900.
>        (udpSocket waitForSendDoneFor: 5).
>        udpSocket closeAndDestroy.
>
>     Hope this helps.
>
>     CU,
>
>     Udo
>
>
>
>
>
>
>     On 18/05/15 23:29, Udo Schneider wrote:
>
>         Hi Manfred,
>
>         I just stumbled over the IP address you are using
>         (239.255.255.250). If
>         I remember correctly this is a IPv4 Class D Multicast address.
>         (224.0.0.0-239.255.255.255).
>
>         So if you want to transmit datagrams to this IP address or recieve
>         datagrams sent to this multicast groups you have to set
>         appropriate IP
>         Options.
>
>         You can set this options using Socket>>#setOption:value: and
>         read them
>         using Socket>>#getOption:. Please note that both methods expect the
>         option to set as a name - not as constant. E.g.
>
>         socket setOption: 'IP_MULTICAST_IF' value: multicastInterface.
>
>         If I do remember correctly you have to set the following options for
>         sending/receiving:
>
>         Sending:
>         IP_MULTICAST_IF
>         (IP_MULTICAST_LOOP)
>         (IP_MULTICAST_TTL)
>
>         Sending should AFAIK work w/o setting any option - although
>         IP_MULTICAST_IF is highly recommended.
>
>         Receiving:
>         (SO_REUSEADDR)
>         IP_ADD_MEMBERSHIP
>         (IP_DROP_MEMBERSHIP)
>
>         Receiving only works if you joined the multicast group
>         previously. So I
>         assume that you need to do something like this (not tested).
>
>         imrMultiaddr := #[239 255 255 250].
>         imrInterface := #[0 0 0 0].
>         ipMreq := imrMultiaddr , imrInterface.
>         socket setOption: 'MEMBERSHIP' value: ipMreq.
>
>         Hope this helps.
>
>         CU,
>
>         Udo
>
>
>
>         On 18/05/15 16:34, Manfred Kröhnert wrote:
>
>             Hi Sven,
>
>             On Mon, May 18, 2015 at 4:14 PM, Sven Van Caekenberghe
>             <[hidden email]
>             <mailto:[hidden email]>
>             <mailto:[hidden email]
>             <mailto:[hidden email]>>> wrote:
>
>
>                   > On 18 May 2015, at 15:47, Manfred Kröhnert
>                  <[hidden email]
>             <mailto:[hidden email]>
>
>             <mailto:[hidden email]
>             <mailto:[hidden email]>>>
>             wrote:
>                   >
>                   > Hi,
>                   > apparently I am missing something else.
>                   >
>                   > I can find devices when connected to a 'regular' LAN.
>                   >
>                   > However, I have a camera that creates a Wifi
>             accesspoint and
>                  makes itself discoverable via SSDP.
>                   > Once I connect to this accesspoint my computer gets
>             a valid IP
>                  address assigned and the NodeJS code is able to
>             discover the device.
>                   > Unfortunately, the Pharo snippet I posted before
>             does not give me
>                  any results and hangs in Socket>>waitForDataIfClosed: .
>                   >
>                   > Any further ideas?
>
>                  Are you sure you restarted the image and your code
>             after switching
>                  networks ?
>
>
>             I did not check this before.
>             But I just downloaded a fresh 40613 image with PharoLauncher
>             and started
>             it after connecting to the camera accesspoint.
>             The code snippet freezes there as well.
>
>             Manfred
>
>
>
>
>
>
>
>
>



Reply | Threaded
Open this post in threaded view
|

Re: Issue with UDP Sockets

Sven Van Caekenberghe-2
In reply to this post by Udo Schneider
Hi Udo,

It would be good if some of this knowledge could be added inside the image, as class comment or methods comments. Even better would be an example combined with a unit test, like UDPSocketEchoTest and TCPSocketEchoTest - the unit test would then actively ensure this functionality is protected.

I do think making all this cross platform could be a bit harder, we'll see.

Sven

> On 19 May 2015, at 00:17, Udo Schneider <[hidden email]> wrote:
>
> This should have been 'IP_ADD_MEMBERSHIP' of course:
>
> imrMultiaddr := #[239 255 255 250].
> imrInterface := #[0 0 0 0].
> ipMreq := imrMultiaddr , imrInterface.
> socket setOption: 'IP_ADD_MEMBERSHIP' value: ipMreq.
>
>
> The "server" could be something like this (execute in first playground). I used another IP address (#[239 255 255 251]) because #[239 255 255 250] might already be part of the multicast group because of other processes and this shows the "whole" process of subscribing to a multicast group:
>
> [
> |  udpSocket |
>  udpSocket := Socket newUDP.
>  udpSocket setPort: 1900.
>  imrMultiaddr := #[239 255 255 251].
>  imrInterface := #[0 0 0 0].
>  ipMreq := imrMultiaddr , imrInterface.
>  udpSocket setOption: 'IP_ADD_MEMBERSHIP' value: ipMreq.
>  udpSocket setOption: 'IP_MULTICAST_LOOP' value: 1.
>  "udpSocket setOption: 'SO_REUSEADDR' value: 1."
>  udpSocket waitForData.
>  buffer := ByteArray new: 256.
>  data := udpSocket receiveUDPDataInto: buffer.
>  bytesRead := data at: 1.
>  sender := data at: 2.
>  senderPort := data at: 3.
>  more := data at: 4.
>  result := buffer copyFrom: 1 to: bytesRead.
>  udpSocket closeAndDestroy.
>  result asString inspect.
> ] fork.
>
>
>
> The "client" (execute in different playground):
> | message udpSocket |
>  message := String crlf join: #(
>   'M-SEARCH * HTTP/1.1'
>   'HOST:239.255.255.250:1900'
>   'MAN:"ssdp:discover'
>   'ST:ssdp:all'
>   'MX:1'
>   '').
>
>  udpSocket := Socket newUDP.
>  udpSocket sendData: message toHost: #[239 255 255 251] port: 1900.
>  (udpSocket waitForSendDoneFor: 5).
>  udpSocket closeAndDestroy.
>
> Hope this helps.
>
> CU,
>
> Udo
>
>
>
>
>
>
> On 18/05/15 23:29, Udo Schneider wrote:
>> Hi Manfred,
>>
>> I just stumbled over the IP address you are using (239.255.255.250). If
>> I remember correctly this is a IPv4 Class D Multicast address.
>> (224.0.0.0-239.255.255.255).
>>
>> So if you want to transmit datagrams to this IP address or recieve
>> datagrams sent to this multicast groups you have to set appropriate IP
>> Options.
>>
>> You can set this options using Socket>>#setOption:value: and read them
>> using Socket>>#getOption:. Please note that both methods expect the
>> option to set as a name - not as constant. E.g.
>>
>> socket setOption: 'IP_MULTICAST_IF' value: multicastInterface.
>>
>> If I do remember correctly you have to set the following options for
>> sending/receiving:
>>
>> Sending:
>> IP_MULTICAST_IF
>> (IP_MULTICAST_LOOP)
>> (IP_MULTICAST_TTL)
>>
>> Sending should AFAIK work w/o setting any option - although
>> IP_MULTICAST_IF is highly recommended.
>>
>> Receiving:
>> (SO_REUSEADDR)
>> IP_ADD_MEMBERSHIP
>> (IP_DROP_MEMBERSHIP)
>>
>> Receiving only works if you joined the multicast group previously. So I
>> assume that you need to do something like this (not tested).
>>
>> imrMultiaddr := #[239 255 255 250].
>> imrInterface := #[0 0 0 0].
>> ipMreq := imrMultiaddr , imrInterface.
>> socket setOption: 'MEMBERSHIP' value: ipMreq.
>>
>> Hope this helps.
>>
>> CU,
>>
>> Udo
>>
>>
>>
>> On 18/05/15 16:34, Manfred Kröhnert wrote:
>>> Hi Sven,
>>>
>>> On Mon, May 18, 2015 at 4:14 PM, Sven Van Caekenberghe
>>> <[hidden email]
>>> <mailto:[hidden email]>> wrote:
>>>
>>>
>>>     > On 18 May 2015, at 15:47, Manfred Kröhnert
>>>    <[hidden email]
>>>    <mailto:[hidden email]>> wrote:
>>>     >
>>>     > Hi,
>>>     > apparently I am missing something else.
>>>     >
>>>     > I can find devices when connected to a 'regular' LAN.
>>>     >
>>>     > However, I have a camera that creates a Wifi accesspoint and
>>>    makes itself discoverable via SSDP.
>>>     > Once I connect to this accesspoint my computer gets a valid IP
>>>    address assigned and the NodeJS code is able to discover the device.
>>>     > Unfortunately, the Pharo snippet I posted before does not give me
>>>    any results and hangs in Socket>>waitForDataIfClosed: .
>>>     >
>>>     > Any further ideas?
>>>
>>>    Are you sure you restarted the image and your code after switching
>>>    networks ?
>>>
>>>
>>> I did not check this before.
>>> But I just downloaded a fresh 40613 image with PharoLauncher and started
>>> it after connecting to the camera accesspoint.
>>> The code snippet freezes there as well.
>>>
>>> Manfred
>>
>>
>>
>>
>
>
>


Reply | Threaded
Open this post in threaded view
|

Re: Issue with UDP Sockets

Udo Schneider
Hi Sven,

you got me :-)

I had this as a package sometime ago for my own purposes (mDNS). So I
knew it does work and how to do it. It's just I can't find that damned
package anymore...

 > I do think making all this cross platform could be a bit harder,
we'll see.
It's not that hard. The socket API is the same on all supported
platforms. No surprises on *nix based OS. The only exception is Windows
where the API is the same but where you might run into some packet drops
due to strange personal FW products and "value-add" NDIS drivers for
NICs. The situation has gotten much better though since Windows Vista/7
are using multicast for some of their services out of the box.

I will recreate it though. Should I simply publish a package or add this
as a slice?

Best Regards,

Udo


On 19/05/15 10:20, Sven Van Caekenberghe wrote:

> Hi Udo,
>
> It would be good if some of this knowledge could be added inside the image, as class comment or methods comments. Even better would be an example combined with a unit test, like UDPSocketEchoTest and TCPSocketEchoTest - the unit test would then actively ensure this functionality is protected.
>
> I do think making all this cross platform could be a bit harder, we'll see.
>
> Sven
>
>> On 19 May 2015, at 00:17, Udo Schneider <[hidden email]> wrote:
>>
>> This should have been 'IP_ADD_MEMBERSHIP' of course:
>>
>> imrMultiaddr := #[239 255 255 250].
>> imrInterface := #[0 0 0 0].
>> ipMreq := imrMultiaddr , imrInterface.
>> socket setOption: 'IP_ADD_MEMBERSHIP' value: ipMreq.
>>
>>
>> The "server" could be something like this (execute in first playground). I used another IP address (#[239 255 255 251]) because #[239 255 255 250] might already be part of the multicast group because of other processes and this shows the "whole" process of subscribing to a multicast group:
>>
>> [
>> |  udpSocket |
>>   udpSocket := Socket newUDP.
>>   udpSocket setPort: 1900.
>>   imrMultiaddr := #[239 255 255 251].
>>   imrInterface := #[0 0 0 0].
>>   ipMreq := imrMultiaddr , imrInterface.
>>   udpSocket setOption: 'IP_ADD_MEMBERSHIP' value: ipMreq.
>>   udpSocket setOption: 'IP_MULTICAST_LOOP' value: 1.
>>   "udpSocket setOption: 'SO_REUSEADDR' value: 1."
>>   udpSocket waitForData.
>>   buffer := ByteArray new: 256.
>>   data := udpSocket receiveUDPDataInto: buffer.
>>   bytesRead := data at: 1.
>>   sender := data at: 2.
>>   senderPort := data at: 3.
>>   more := data at: 4.
>>   result := buffer copyFrom: 1 to: bytesRead.
>>   udpSocket closeAndDestroy.
>>   result asString inspect.
>> ] fork.
>>
>>
>>
>> The "client" (execute in different playground):
>> | message udpSocket |
>>   message := String crlf join: #(
>>    'M-SEARCH * HTTP/1.1'
>>    'HOST:239.255.255.250:1900'
>>    'MAN:"ssdp:discover'
>>    'ST:ssdp:all'
>>    'MX:1'
>>    '').
>>
>>   udpSocket := Socket newUDP.
>>   udpSocket sendData: message toHost: #[239 255 255 251] port: 1900.
>>   (udpSocket waitForSendDoneFor: 5).
>>   udpSocket closeAndDestroy.
>>
>> Hope this helps.
>>
>> CU,
>>
>> Udo
>>
>>
>>
>>
>>
>>
>> On 18/05/15 23:29, Udo Schneider wrote:
>>> Hi Manfred,
>>>
>>> I just stumbled over the IP address you are using (239.255.255.250). If
>>> I remember correctly this is a IPv4 Class D Multicast address.
>>> (224.0.0.0-239.255.255.255).
>>>
>>> So if you want to transmit datagrams to this IP address or recieve
>>> datagrams sent to this multicast groups you have to set appropriate IP
>>> Options.
>>>
>>> You can set this options using Socket>>#setOption:value: and read them
>>> using Socket>>#getOption:. Please note that both methods expect the
>>> option to set as a name - not as constant. E.g.
>>>
>>> socket setOption: 'IP_MULTICAST_IF' value: multicastInterface.
>>>
>>> If I do remember correctly you have to set the following options for
>>> sending/receiving:
>>>
>>> Sending:
>>> IP_MULTICAST_IF
>>> (IP_MULTICAST_LOOP)
>>> (IP_MULTICAST_TTL)
>>>
>>> Sending should AFAIK work w/o setting any option - although
>>> IP_MULTICAST_IF is highly recommended.
>>>
>>> Receiving:
>>> (SO_REUSEADDR)
>>> IP_ADD_MEMBERSHIP
>>> (IP_DROP_MEMBERSHIP)
>>>
>>> Receiving only works if you joined the multicast group previously. So I
>>> assume that you need to do something like this (not tested).
>>>
>>> imrMultiaddr := #[239 255 255 250].
>>> imrInterface := #[0 0 0 0].
>>> ipMreq := imrMultiaddr , imrInterface.
>>> socket setOption: 'MEMBERSHIP' value: ipMreq.
>>>
>>> Hope this helps.
>>>
>>> CU,
>>>
>>> Udo
>>>
>>>
>>>
>>> On 18/05/15 16:34, Manfred Kröhnert wrote:
>>>> Hi Sven,
>>>>
>>>> On Mon, May 18, 2015 at 4:14 PM, Sven Van Caekenberghe
>>>> <[hidden email]
>>>> <mailto:[hidden email]>> wrote:
>>>>
>>>>
>>>>      > On 18 May 2015, at 15:47, Manfred Kröhnert
>>>>     <[hidden email]
>>>>     <mailto:[hidden email]>> wrote:
>>>>      >
>>>>      > Hi,
>>>>      > apparently I am missing something else.
>>>>      >
>>>>      > I can find devices when connected to a 'regular' LAN.
>>>>      >
>>>>      > However, I have a camera that creates a Wifi accesspoint and
>>>>     makes itself discoverable via SSDP.
>>>>      > Once I connect to this accesspoint my computer gets a valid IP
>>>>     address assigned and the NodeJS code is able to discover the device.
>>>>      > Unfortunately, the Pharo snippet I posted before does not give me
>>>>     any results and hangs in Socket>>waitForDataIfClosed: .
>>>>      >
>>>>      > Any further ideas?
>>>>
>>>>     Are you sure you restarted the image and your code after switching
>>>>     networks ?
>>>>
>>>>
>>>> I did not check this before.
>>>> But I just downloaded a fresh 40613 image with PharoLauncher and started
>>>> it after connecting to the camera accesspoint.
>>>> The code snippet freezes there as well.
>>>>
>>>> Manfred
>>>
>>>
>>>
>>>
>>
>>
>>
>
>
>



12