Friday, July 26. 2013
The WebRTC Demo in Glassfish 4
Today, and after a long time without a typical entry, I am going to continue with the new WebRTC browser API and exploring the new possibilities of JavaEE 7. If you remember in a previous entry the apprtc (a sample application done by google and mozilla to test WebRTC interoperability between their browsers) was installed and tested inside the google application engine (python). But some weeks ago the new Glassfish 4.0 was released with all the new JavaEE 7 features. This entry is going to use two of them, JSONP (JSON Processing) and the websocket API, to replicate the server functionality of that application. This way the apprtc application (with minimal changes) will work but using glassfish 4.0 instead of the google engine as the server side component.
Only three classes were developed to replace the main python functionality:
es.rickyepoderi.apprtc.bean.AppRTCBean: A simple request JSF bean that calculates all the needed javascript variables to render the main HTML page. Things like the room key, the username,... Are calculated and inserted in the page source just as it is done in the python counterpart.
es.rickyepoderi.apprtc.server.RoomEndpoint: The websocket endpoint which is going to receive the client messages. In WebRTC both clients use the server just to exchange negotiation information with the other peer. After the negotiation the communication is P2P (browser to browser more specifically). In the original application this client / server communication was done using google channel but obviously the Java implementation is going to use websockets (this standard was also introduced in another entry of the blog, but please take in mind that now the Java API is also standardized by JavaEE 7).
es.rickyepoderi.apprtc.ejb.RoomBean: Initially this class was going to be a Singleton EJB, but the bean was not injected in the websocket endpoint (I suppose that it is a bug, because I think the injection inside an endpoint is supported by JavaEE 7), and therefore it was transformed into a common singleton object. This class handles the room management. The apprtc is based on the idea of rooms: each room has an identifier (the room key); two users can join in the same room; once both are in the room the audio / video call can start; when one of them hangs, he is disconnected from the room.
The HTML pages (index.html and full.html) were transformed into facelets HTMLX with minimal changes. And the main.js (where all the JavaScript resides) was slightly modified. Google channel and websockets are very similar APIs, so the changes are not very complex.
The Java version works in the following way (I am going to repeat the details explained in the previous entry but now some details of the implementation are described):
When the first user enters the JSF generates a random room key and a random username. The client browser opens a websocket and joins to that room (this part is different, now a join message is sent from the client to inform the server about the room key and the username). The browser also requests access to mic and camera as before. Because this client is the first one to be in the room, he waits for the other partner to join (variable initiator).
The second user accesses the application but specifying the same room key (a parameter r is used for that purpose). The JSF maintains the room key and generates another random username for this second client. The browser opens the websocket and sends the join message too. This way the server endpoint receives the second join for the same room, so the room is full and ready to start the video / audio call. Local resources (mic and camera) are requested by the second browser as usual.
The last browser to join receives a variable initiator=1 (created by the JSF bean). This variable marks that there was another user in the room and, therefore, he can start to exchange the negotiation messages. This way the second browser recollects the peer connection data and sends it to the server (an offer message).
The server receives the offer via the websocket. He locates the room using the websocket ID and sends the info to the other partner. In the two previous joins both usernames and websockets IDs were linked to the room.
The first browser receives the info from the server (via websocket) and replies with an answer message. This message is again retransmitted by the server to the other browser.
In this point some messages are exchanged between both browsers following the same idea. In this conversation the details to establish the P2P call are agreed. Besides the server and the websockets are a key part, the server just retransmits what it receives from a browser websocket to the other and vice-versa.
At the end of this point the P2P communication is established between the browsers and the audio / video call is started.
When a user hangs the call up, the websocket is closed, the server detects that, removes the user from the room and sends a bye message to the other user. The other browser in turn receives the message and returns to the initial state, this browser is maintained in the room waiting for another user to join. As soon as it leaves the page the websocket is closed and it abandons the room too.
Here I present a video with the commented behavior. The first browser (main screen) accesses the application specifying a fixed room (r=00000000). Local resources are requested and accepted. And the join message is sent to the server. It can be seen in the chromium console and in the glassfish logs. As soon as the second browser (little window in the bottom-right corner) joins to the same room the video call starts. Then the first browser hangs the call up and the second one receives the bye message and returns to initial state (waiting for other partner to join in that room). The chromium console receives all the messages perfectly and the glassfish server performs the retransmissions from one browser to the other correctly too.
With this entry I wanted to test two new features of JavaEE 7: JSONP and the websocket API. Both APIs are used in the WebRTC application for the client / server communication (a websocket is used to transmit the JSON messages). Besides implementing my own WebRTC server makes me understand even better how this technology works. I always hate the typical hello-world examples, do you want a real and modern example for websokets and JSONP? Here you have one. The complete netbeans project for the glassfish apprtc version can be downloaded from here. This time I only tested the application with chromium (version 28) because the iceweasel package is incredibly old in debian testing (come on guys, iceweasel in testing is the same version than in stable) and I did not want to install a new firefox (so take care with that).
This was my first contact with JavaEE 7. See you!
Sunday, July 7. 2013
OCSP Java Bug (Part III)
After the previous post about the OCSP bug I have exchanged a few words via email with Andrew Hughes (the guy in charge of icedtea) and he recommended me to try with openjdk-8 because bugs usually are fixed in the next version and then backported to the current one. If the bug was still present there he asked me to send a patch against that version. Besides looking my first post about this issue he stated that the custody of openjdk-6 has passed over to Red Hat, thing that I did not know.
So here it is a new entry about the same issue but now using openjdk-8. The first thing to do was compiling the current openjdk-8 tree. I followed the steps explained in the openjdk instructions:
First cloning and getting all the sources is necessary:
$ hg clone http://hg.openjdk.java.net/jdk8/jdk8 jdk8 $ cd jdk8 $ bash ./get_source.sh
Then the needed development packages are checked (they should be installed in the box).
$ bash ./configure
In my case (debian testing) the following packages were added:
# apt-get install libX11-dev libxext-dev libxrender-dev libxtst-dev libcups2-dev libasound2-dev ccache
Finally everything is compiled (this step took about half an hour for me).
$ make all
And that is all. A beautiful JVM version 8 is deployed inside the build directory:
$ cd build/linux-x86_64-normal-server-release/images/j2sdk-image/bin $ ./java -version openjdk version "1.8.0-internal" OpenJDK Runtime Environment (build 1.8.0-internal-ricky_2013_05_21_20_13-b00) OpenJDK 64-Bit Server VM (build 25.0-b32, mixed mode)
Finally I tried to test the new JVM. The jtreg application is needed and the current version in debian does not support the testng tests. Finally I compiled it by myself (I do not explain the steps because there a lot of different things, basically I followed the build instructions using the ant version but I did a lot of minor and weird extra things to make it work). After the compilation the jtreg is located in the <JT_CLONE_DIR>/dist/jtreg directory and the new JVM can be tested like this.
$ make JT_HOME=/home/ricky/jdk8/jtreg/dist/jtreg test
Only three tests fail (there are almost 3,500) and the complete process took about one hour and a half in my laptop.
Once I had the current openjdk-8 compiled I tested my problem. It was still reproducible and, looking to the sources, the code is different to previous versions 7 and 6 but much more similar to openjdk-6. Here there is not a list and the responderCert (certificate configured via java properties, for example ocsp.responderCertSubjectName) or the issuerCert (the certificate which issued the one to be checked) are passed as the only valid certificate to sign the OCSP response. But now OCSPChecker class has disappeared and a new RevocationChecker has arrived. I did another patch, which is more similar to the one provided for version 6 than the one done for 7. I tested all the situations again using the openssl OCSP engine (exactly as in the first entry of this issues) and I repeated the jtreg automated tests (the same three tests failed).
Finally I sent an email to the security-dev mailing list commenting the issue and with the patch attached (just as Andrew told me). It seems that now things are moving on. Until this moment a bug has been opened about the issue and I was requested to sign the OCA agreement (which I did some weeks ago) in order to admit my patch. The OCA has just been processed and my name can be seen in the contributors list. (In Spain everyone has the given name and two surnames. The first one comes from the father and the second from the mother. Now there are laws that let the parents to invert the order, to swap the surnames. When I work with english-speaking people they always remove my father's surname. My mother is very pleased with that. )
On the road again!
Comments