Wednesday May 09, 2007 | Jean-Christophe Collet's Weblog Jean-Christophe Collet's Weblog |
|
So, you want to contribute to the openJDK networking library? Let me tell you: We (as in the current team working on it) are very glad you do, and I mean that. There is a lot of work to be done, and we definitely could use a little help. There are a few things you should know before heading down that road though. You see, as you probably already know, having a consistent behavior across all the supported platform is one of the main design goals of Java. But I need to let you in a little secret: cross-platform networking is hard, very hard, to achieve. Why is that so do, you ask? After all network protocols and APIs are well specified in RFCs and other standardization documents. After all, a socket is a socket, ain't it? You wish! And, actually, so do I! That would make my job so much easier! But there are a few problems with that assumption. First, RFCs are not always as ironclad as we would wish and can leave room to interpretation. One example of that is what happens with IPv4 multicast addresses in IPv6. The RFCs specify that an IPv6 socket has to support Ipv4 addresses for backward compatibility in the form of a special kind of IPv6 addresses (known as Ipv4-Compatible). This makes it possible to use a single IPv6 socket to talk to both world, the old Ipv4 one and the bold new IPv6 universe. Only problem with that is that the RFCs do not state clearly whether this should work for joining IPv4 multicast groups as well. So, Lo and Behold, guess what happens? On some systems it does work while on others it's not supported and, of course, they don't consider it a bug! I let you imagine the hoops we had to go through to get a consistent behavior here. Then there are the unfortunate cases where the standard specifications are blatantly ignored for whatever reasons (don't ask, trust me on that one, you really don't want to know). An example of that would be the checksum field in the ICMP header which is supposed to be computed and set by the OS network layer before sending the packet. However some implementations of the TCP/IP stack leave that responsibility to the application layer. But, to be able to compute that checksum, the application needs to know what the source address will be in that header, which is not always readily available at that point, specially on machines with multiple network interfaces. Another frequent issue is when we're asked to provide support for features that exist on some system and not others. A good example of these are the “Unix Domain” sockets (see RFE 4145756). So, how do we deal with all that? We go through a succession of tough choices. For instance, the Unix Domain Sockets, while we think it does provide a somewhat valuable service, it is also a bit redundant with normal sockets, and, of course, it's not available everywhere. In that particular case, we decided that the cons were out-weighting the pros and voted against implementing it for the moment. But let's assume for a minute that we still wanted to do it at that point, we then would have to design an API that would not break if the feature was not available. And no, throwing an Exception when trying to create a Unix Domain socket on Windows, for instance, is not the right answer. So we would go to a “Service Provider Interface” (aka SPI), meaning the application would have to request the “service”, Unix Domain Sockets here, and, IF that service is available, get a reference to a “factory” in charge of creating these sockets (note: that's not the only approach to solve that kind of issue, but it's a rather common one). The end result is that it is now the responsibility of the application to deal with availability, or non-availability, of the feature, and, of course, it makes the code much more complex. What happens when the application absolutely rely on such a feature and it is not available? It has no option but to exit, stating something like “Sorry but this application can't run on your system...”. Which is a rather harsh blow against the “Run Anywhere” mantra. That's why we always think twice, or three, or four times, before going down that road. Specially when it comes to something as core as the Networking Stack. In other, more minor,cases, like with certain socket options, we do actually word the documentation in a way that clearly states that this may be ignored, or re-interpreted, by the OS specific implementation. A perfect example of that is the documentation of Socket.setTrafficClass(int). Naturally, that approach also has its problems, and it's not rare that developers contact us, complaining about the fact that one of these methods seems to have no effect in their application. I hope that by now you have a better idea of what kind of difficulties we have to deal with. But don't let that stop you working on your project, we'll be here to offer help and advice when you'll ask for them. That's it for now. In a future post, I'll outline what we're currently working on. (2007-05-09 05:50:55.0) Permalink |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||