Issue1846

classification
Title: cannot configure socket() for Multicast
Type: behaviour Severity: normal
Components: Core Versions: Jython 2.5
Milestone:
process
Status: open Resolution: remind
Dependencies: Superseder:
Assigned To: zyasoft Nosy List: amak, fwierzbicki, hulettbh, zyasoft
Priority: low Keywords:

Created on 2012-03-09.13:20:20 by hulettbh, last changed 2018-03-07.19:25:29 by jeff.allen.

Files
File name Uploaded Description Edit Remove
unnamed hulettbh, 2012-03-12.15:14:16
Messages
msg6790 (view) Author: Brian (hulettbh) Date: 2012-03-09.13:20:19
So the New Socket Module documentation (http://wiki.python.org/jython/NewSocketModule) states:
"If you find a difference in behaviour between cpython and jython that is not documented here, and where jython is behaving differently to the cpython socket documentation, then that should be considered a bug and reported, please."

I've run into a few issues while porting a python application to jython which all stemmed from the socket module.
The most frustrating for me was the inability to configure a socket for multicast like so:
self._sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
self._sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 1)

because the IPPROTO_IP and IP_MULTICAST_TTL constants are not defined in the jython socket module.  Hard-coding their values doesn't work either (Not surprisingly, but I figured it was worth a shot).

Are there any plans to add this ability? or is the only option to use the Java MulticastSocket library directly?
msg6792 (view) Author: Alan Kennedy (amak) Date: 2012-03-11.22:54:13
I didn't have any plans to implement multicast functionality, primarily because I wasn't aware that there was need for it. But you are using it, so let's have a think about it.

Problem number one is that there is no support for multicast sockets under java.nio, i.e. although java.net.MulticastSocket is a subclass of java.net.DatagramSocket, there is no corresponding java.nio equivalent subclass. This is still true on java 6, which is the target for the next version of jython.

http://docs.oracle.com/javase/6/docs/api/index.html?java/nio/channels/DatagramChannel.html
https://blogs.oracle.com/alanb/entry/multicasting_with_nio

Note that there is a multicast channel in java 7. 

http://docs.oracle.com/javase/7/docs/api/java/nio/channels/MulticastChannel.html

But we currently have no plans to target java 7, so if support for multicast sockets were to be added to jython, it could only ever work on java 7 and later.

As you may be aware, all sockets created with the jython socket module have a dual nature: they consist of a java.nio.channels.* object, which is used for all asynchronous operations and 'select'ing, and a java.net.* object, which is used for all other operations. There is no other choice than to work it this way, because neither of the java.net or java.nio APIs contain all of the functionality required.

You can see this if you look at the declaration of the "_datagram_socket_impl" class in the socket module. It creates both a "jchannel" and a "jsocket" attribute. In the case of multicast sockets, there is no way to create a "jchannel" object.

Looking at the API for the java MulticastSocket class, I see other potential problems. Some of the methods take an "Interface" parameter, i.e. they allow you to specify a particular interface on which to send and receive multicasts. At the moment, there is no support in the jython socket module for modelling individual network interfaces: dealing with a specific interface requires specifying the IP address of the interface. (As far as I can tell, cpython doesn't permit modelling network interfaces either).

(As an aside, this support for network interfaces will have to added at some stage, since support IPv6 scopes will require it)

So, some questions.

1. Would you require non-blocking support for multicast sockets? This can not be implemented on jython until we hit java 7.
2. Would you require using select or poll on multicast sockets? Again, this would require java 7.
3. Does the cpython code that you are working with specify particular interfaces? How does it do that?

If you could paste some sample code for your use case, that would be really helpful.

Lastly, if your answer to all three questions is "no", then there should be a straightforward way to monkeypatch an UDP socket to be a multicast socket, by simply

A: Creating a java.net.MulticastSocket object, through the java APIs.
B: Creating a jython UDP socket using socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
C: Assiging the "jsocket" attribute of the UDP socket to be the java Multicast socket.
D: Only ever using the socket in blocking mode, and never using it in a select or poll call.

Sample code

# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

from java.net import MulticastSocket, InetSocketAddress
import socket

ip, port = "192.168.1.1", 6789

jmultisock = MulticastSocket(InetSocketAdddress(ip, port))
mysock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
mysock.sock_impl.jsocket = jmultisock

# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
msg6793 (view) Author: Brian (hulettbh) Date: 2012-03-12.15:14:17
Glad to see that you're taking this seriously!

So the application I'm using this for is actually quite simple - my answers
to all of your questions are "No" - so I think that your "monkeypatch"
example will work well for me.  Thanks a lot for the solution!

We may have use for non-blocking sockets in the future though, so it would
be nice to see them implemented if you need to add it at some stage anyway.
 So to go back to your questions, it would be nice to have support for (1),
as well as (2), although that's less important.  (3) I suppose we could do
without - if there's no way to do it in cpython, personally I don't see any
reason to do it in jython.

On Sun, Mar 11, 2012 at 6:54 PM, Alan Kennedy <report@bugs.jython.org>wrote:

>
> Alan Kennedy <jython-dev@xhaus.com> added the comment:
>
> I didn't have any plans to implement multicast functionality, primarily
> because I wasn't aware that there was need for it. But you are using it, so
> let's have a think about it.
>
> Problem number one is that there is no support for multicast sockets under
> java.nio, i.e. although java.net.MulticastSocket is a subclass of
> java.net.DatagramSocket, there is no corresponding java.nio equivalent
> subclass. This is still true on java 6, which is the target for the next
> version of jython.
>
>
> http://docs.oracle.com/javase/6/docs/api/index.html?java/nio/channels/DatagramChannel.html
> https://blogs.oracle.com/alanb/entry/multicasting_with_nio
>
> Note that there is a multicast channel in java 7.
>
>
> http://docs.oracle.com/javase/7/docs/api/java/nio/channels/MulticastChannel.html
>
> But we currently have no plans to target java 7, so if support for
> multicast sockets were to be added to jython, it could only ever work on
> java 7 and later.
>
> As you may be aware, all sockets created with the jython socket module
> have a dual nature: they consist of a java.nio.channels.* object, which is
> used for all asynchronous operations and 'select'ing, and a java.net.*
> object, which is used for all other operations. There is no other choice
> than to work it this way, because neither of the java.net or java.nio
> APIs contain all of the functionality required.
>
> You can see this if you look at the declaration of the
> "_datagram_socket_impl" class in the socket module. It creates both a
> "jchannel" and a "jsocket" attribute. In the case of multicast sockets,
> there is no way to create a "jchannel" object.
>
> Looking at the API for the java MulticastSocket class, I see other
> potential problems. Some of the methods take an "Interface" parameter, i.e.
> they allow you to specify a particular interface on which to send and
> receive multicasts. At the moment, there is no support in the jython socket
> module for modelling individual network interfaces: dealing with a specific
> interface requires specifying the IP address of the interface. (As far as I
> can tell, cpython doesn't permit modelling network interfaces either).
>
> (As an aside, this support for network interfaces will have to added at
> some stage, since support IPv6 scopes will require it)
>
> So, some questions.
>
> 1. Would you require non-blocking support for multicast sockets? This can
> not be implemented on jython until we hit java 7.
> 2. Would you require using select or poll on multicast sockets? Again,
> this would require java 7.
> 3. Does the cpython code that you are working with specify particular
> interfaces? How does it do that?
>
> If you could paste some sample code for your use case, that would be
> really helpful.
>
> Lastly, if your answer to all three questions is "no", then there should
> be a straightforward way to monkeypatch an UDP socket to be a multicast
> socket, by simply
>
> A: Creating a java.net.MulticastSocket object, through the java APIs.
> B: Creating a jython UDP socket using socket.socket(socket.AF_INET,
> socket.SOCK_DGRAM, socket.IPPROTO_UDP)
> C: Assiging the "jsocket" attribute of the UDP socket to be the java
> Multicast socket.
> D: Only ever using the socket in blocking mode, and never using it in a
> select or poll call.
>
> Sample code
>
> # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
>
> from java.net import MulticastSocket, InetSocketAddress
> import socket
>
> ip, port = "192.168.1.1", 6789
>
> jmultisock = MulticastSocket(InetSocketAdddress(ip, port))
> mysock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM,
> socket.IPPROTO_UDP)
> mysock.sock_impl.jsocket = jmultisock
>
> # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
>
> _______________________________________
> Jython tracker <report@bugs.jython.org>
> <http://bugs.jython.org/issue1846>
> _______________________________________
>
msg7748 (view) Author: Alan Kennedy (amak) Date: 2013-02-25.20:17:35
Although I've presented a successful workaround on this issue, a proper solution will not be possible until we move to Java 7.

Setting to "pending" with a resolution of "remind".
msg8334 (view) Author: Jim Baker (zyasoft) Date: 2014-05-04.21:15:34
Should be readily supportable with socket-reboot (about to be merged into Jython trunk from https://bitbucket.org/jimbaker/jython-socket-reboot), given that this is based on Netty 4. See this unit test from Netty 4 for some ideas on where we will start:

https://github.com/netty/netty/blob/4.0/testsuite/src/test/java/io/netty/testsuite/transport/socket/DatagramMulticastTest.java
msg8335 (view) Author: Jim Baker (zyasoft) Date: 2014-05-04.21:16:13
Another note: Jython 2.7 now requires Java 7 as of beta 2
msg8494 (view) Author: Jim Baker (zyasoft) Date: 2014-05-21.23:01:36
It would nice to support this, but everything has changed with socket-reboot, so we have to re-evaluate Alan's proposed solution.
msg8708 (view) Author: Jim Baker (zyasoft) Date: 2014-06-19.05:04:22
This will likely slip to 2.7.1 (at the earliest)
History
Date User Action Args
2018-03-07 19:25:29jeff.allensetmilestone: Jython 2.7.2 ->
2015-12-29 23:50:02zyasoftsetmilestone: Jython 2.7.1 -> Jython 2.7.2
2015-07-28 15:35:33zyasoftsetassignee: zyasoft
milestone: Jython 2.7.1
2014-06-19 05:04:22zyasoftsetpriority: normal -> low
messages: + msg8708
2014-05-21 23:01:36zyasoftsetstatus: pending -> open
assignee: amak -> (no value)
messages: + msg8494
2014-05-04 21:16:13zyasoftsetmessages: + msg8335
2014-05-04 21:15:34zyasoftsetmessages: + msg8334
2014-05-04 20:37:33zyasoftsetnosy: + zyasoft
2013-02-25 20:17:35amaksetstatus: open -> pending
resolution: remind
messages: + msg7748
2013-02-25 19:08:15fwierzbickisetnosy: + fwierzbicki
versions: + Jython 2.5, - 2.5.2
2012-03-19 17:39:52amaksetpriority: normal
2012-03-12 15:14:17hulettbhsetfiles: + unnamed
messages: + msg6793
2012-03-11 22:54:14amaksetmessages: + msg6792
2012-03-10 00:10:56pjenveysetassignee: amak
nosy: + amak
2012-03-09 13:20:20hulettbhcreate