Random video chat website using WebRTC

Seing as how many people are interested in my video-conference-webrtc project, I have decided to develop a random video chat website using WebRTC. The project is called rtcrandom and is hosted on GitHub. A live demo is also available at test.tengmo.chat.


RTCRandom is an online (video)chat website that allows users to socialize with others without the need to register. The service       randomly pairs users in one-on-one chat sessions where they chat anonymously using the names “You” and “Stranger”.

For the project I have used GitHub for my online project hosting service using Git, issue tracking, collaboration and wikis. Node.js and JavaScript are the main programming languages used for development. For continuous integration I am using Jenkins with OpenShift as my hosting service. The wiki is available here.

I not going into great detail explaining the code. I will rather give you a brief overview on how rtcrandom works and leave the pleasure of examining the code to you.

For the back-end Node.js is used with Express as the web application framework. I used winston for logging and EJS as the templating language for the views.

For the front-end simple HTML with JavaScript (jQuery, socket.io) and CSS is used. In order to add WebRTC support for browsers like Safari (which does not support WebRTC yet) I have used the Temasys WebRTC adapter. If you do not wish to use such an adapter see release v0.1-alpha.

Main components
On the back-end the main component is server.js and on the front-end the magic happens in public/js/room.js, which is loaded by the views/room.ejs view.

How does the matching work
When a client first loads the page a bidirectional event-based communication is created between the client’s browser and the back-end using socket.io. I call this the default communication channel. The default communication channel is used by the client to let the server know, that the client wants to find a new chat partner etc. It also allows the server to inform a client about a new chat partner etc.

So once a client wants to find a new (or initial) communication partner he triggers a next event through the default communication channel, letting the server know about its ID and that he wants a new chat partner. The ID is a random hash that is generated once on client-side. The server then puts the client’s request into a queue and checks if the queue has at least two requests (note: no client is put twice in the queue). If at least two requests are in the queue (one from a different client and one from our current client), the two clients are polled from the queue. The server then generates a random room name (a random six digit alphanumeric string) and sends it to the two clients via the default communication channel.

Once each client receives the new room name, they send a message to the server via the default channel that they want to join the room. The client whose message arrives first at the server creates and joins the room and the second client simply joins the new room. The peer that simply joins the new room gets notified by the server that it just joined, so that it can broadcast the message to the default channel saying that it is a new participant that joined the room and wants to receive a WebRTC offer to open up a peer-to-peer WebRTC communication with the other client in the room (the one that created the room). The room creator then receives the new participant message in the default channel and creates an offer for the joining peer. This offer will be send via a private communication channel which both clients open using the room name as namespace. The room creator then sends the offer through this channel, which the other peer receives and responds to with an answer. Further WebRTC related communication messages to build the WebRTC peer-to-peer connection between the two clients are also exchanged through the private channel. Once a peer-to-peer connection is establish the video stream and chat messages are exchanged directly between the two clients (no server required).

Note: when a peer disconnects from one peer (e.g. because it wants to chat with a different person) the disconnect event is not immediately received by the other peer, due to WebRTC delays. This is why the disconnecting peer also sends a disconnect notification message to the other peer via the private channel, so that it can update its view. The notification is send using the private channel because it tends to be faster than waiting for the WebRTC notifications.

The source code is available here. A live demo is available at test.tengmo.chat.


Reading SPIEGEL Plus articles

DISCLAIMER: The information below is for information purposes only.

I happened to be browsing on SPIEGEL Online the other day and noticed that articles published for non SPIEGEL Plus subscribers were still partially available on the article’s page in readable form while the largest portion of the text was blurred out and available only for paying subscribers.

So the first thing I did was to take a closer look at the blurred out text (which was just underneath an overlay with a CSS filter style). I noticed that the text structure was resembling an ordinary paragraph style (if I can express it like that), with the words just being gibberish:

In the above example you can see that the letter ‘/’ is used three consecutive times or that it is often followed by a space. This made me think that ‘/’ may be a replacement for the character ‘.’.

Another fun fact is that SPIEGEL Plus articles are only partially encrypted so that the reader can develop an interest for the article and then hopefully (for them) decide to buy it. The particular article that I happen to be reading was an interview like article, where SPIEGEL interviewed a guy named Butter, with SPIEGEL asking a question and Butter answering it. Fortunately for me this was a repeating pattern with participant names being styled in bold text in both the plain and encrypted text for easy detection. I could easily see that SPIEGEL: was always matching to TQJFHFM; and Butter: to Cvuufs; in the cipher text. Using this I could easily see that the letter ‘E’ was matching to ‘F’, ‘e’ to ‘f’, ‘:’ to ‘;’…

This made me think that this cipher was nothing more than a simple substitution cipher where each letter in the original message is replaced with some other predefined letter. Taking a look at the following ASCII table one can easily see that the ASCII code x of the plain text character has been replaced with the character represented by the ASCII code x+1: ‘E’ (ASCII 69) has been replace with F (ASCII 70), etc.

This cipher is also known as Caesar cipher. Anyhow, I thought it might be fun to write a small Firefox extension that I can use to view those articles. The extension basically removes the blurring overlay and replaces the encrypted text with their plain text version.

The source code is available here. If you don’t know how to temporary install a Firefox extension you can refer to this guide.


Simple token field for AngularJS

I was searching the net for a very, very simple token field for AngularJS the other day to use on a side project that I was working on. Unfortunately I couldn’t find anything that suits my requirements. So I implemented my own. Here is how to use it.

(Optional) Install Using bower
Add ng-token-field as a dependency to your project within your bower.json file

Then do a bower install in your project directory:

Import JQuery
The directive requires JQuery.

Import the ng-token-field stylesheet and script
Include the stylesheet and javascript files:

Add the dependency to your module
Add the ngTokenField module as a dependency in your AngularJS app;

Add the <ng-token-field> element to your DOM
Add the custom element to the HTML file where you want to use and bind it to a property and/or validator function.

(Optional) Add a token text validator
You can also define a validator function that validates the text of each token and styles it accordingly. Below we define a function validator that returns true if the text is an email and false otherwise.

A non AngularJS version is also available here, which does not require JQuery.

Full code & Demo


Implement a ceil() function

In this post I will explain a less intuitive approach of implementing a ceil() function in Java, that is faster than known comparison approaches.

A few known facts
Fact 1
Dividing two integers a and b in Java will always floor the result:

well almost. Actually Math.floor(a/b) rounds towards negative infinity, where as a/b rounds towards zero:

Fact 2
\lfloor x \rfloor = m if m \le x \textless m+1
\lceil x \rceil = n if n - 1 \textless x \le n

Fact 3
\lfloor x \rfloor \le \lceil x \rceil

What we need is \lfloor (x + s) \rfloor == \lceil x \rceil
Since dividing two integers a and b in Java will always floor the result, we need to find some s such that \lfloor (x + s) \rfloor == \lceil x \rceil.

How do we find s?
Think about it this way: \lceil \frac{a}{b} \rceil \textgreater \lfloor \frac{a}{b} \rfloor, except when \frac{a}{b} is a whole number. So, we want to bump \frac{a}{b} to (or past) the next whole number, unless \frac{a}{b} is a whole number, by adding s. This way \lfloor \frac{a}{b} + s \rfloor == \lceil \frac{a}{b} \rceil. We want to find s so that for whole numbers, it won’t quite push them up to the next whole number, but for non-whole numbers it will.

For instance, assume a=6, b=3 and s=1 then \lfloor \frac{a}{b} + s \rfloor = \lfloor \frac{6}{3} + 1 \rfloor = 3 \ne \lceil \frac{a}{b} \rceil = \lceil \frac{6}{3} \rceil = 2, which is not the desired result. As you can see, by using s=1 we bumped \frac{a}{b} to far. So s must definitely be less than 1.

So how much s is just enough?

Assume a=7, b=3. Then \frac{a}{b} = \frac{7}{3}, which can be re-written as:
\frac{7}{3} = \frac{1}{b} + \frac{1}{b} + \frac{1}{b} + \frac{1}{b} + \frac{1}{b} + \frac{1}{b} + \frac{1}{b} = (\frac{1}{3} + \frac{1}{3} + \frac{1}{3}) + (\frac{1}{3} + \frac{1}{3} + \frac{1}{3}) + \frac{1}{3} = 2  + \frac{1}{3}
In other words, we get an integer part (2) and a left over (\frac{1}{3}). The left over part is always in the form of k\frac{1}{b}, with 0 \le k \textless b. Thus, the smallest non-whole number we can get from \frac{a}{b} is qb + \frac{1}{b} with qb being the integer part with q \in \mathbb{N}_0.

So assuming \frac{a}{b} is not a whole number, the smallest left over we can have is \frac{1}{b}. So in-order to bump \frac{a}{b} to the next whole number, it suffices to add s = 1 - \frac{1}{b}. This is \textless 1, which will not bump \frac{a}{b} to the next whole number in case \frac{a}{b} is a whole number, but still enough to bump \frac{a}{b} to the next whole number in case \frac{a}{b} is not a whole number.

Summing it up
So we know adding s = 1 - \frac{1}{b} to \frac{a}{b} will fulfill the equality: \lfloor (\frac{a}{b} + s) \rfloor = \lceil \frac{a}{b} \rceil. Thus we get:

 \lceil \frac{a}{b} \rceil = \lfloor (\frac{a}{b} + s) \rfloor = \lfloor (\frac{a}{b} + 1 - \frac{1}{b}) \rfloor = \lfloor \frac{a + b - 1}{b} \rfloor


Next word

Problem statement
Given a word w, consisting of characters a-z, A-Z and 0-9, compute the next lexicographical word w',
with 0-9 < A-Z < a-z.


Sample Input



Notebook file


Read CSV – Java

The following code reads a CSV file and converts it to List<Map<String, String>> in Java. Each row is represented by a Map<String, String> entry in the resulting List. Map<String, String> maps column name (header value) to value.


Generating CSV reports from SQL*Plus

Problem statement
Suppose you have a query whose result needs to be exported as a CSV file. In addition some fields need to be parsed into a different format and columns need to be renamed.

The SPOOL command
The SPOOL command causes SQL*Plus to write the results to a file.

Sample script

How to run the script


Compare tables in different databases using a pre-defined mapping – Java, JDBC, Hibernate

What is this?

A small tool that illustrates how to compare different database tables using a pre-defined mapping.

Well, as a software engineer in a big ol' company with a non engineering focus, you are probably familiar with the situation where regression tests are being performed manually. This is due to the fact that many of the so called test managers come from a non technical background and are not willing to acquire the least amount of technical knowledge. As a result many of them don't have the know-how of what and how such tests can actually be automated. Such persons often claim that spending time and effort to write a tool that automates such processes is inefficient and a waste of money. This is because such people do not adopt a brighter future outlook and are anware that automating simple tasks such as that makes testing less error prone, reliable, easier, faster and cheaper in the long term.

A simplified real life scenario:

Consider an old system S that is about to be replaced with a newer and cooler system C. Both systems are responsible for managing some sort of entity. Lets call that entity a Trade. A Trade in both systems has fictional properties such as an Instrument Name, an ISIN and some sort of unique Identifier. In both systems, S and C, the trades are being edited and enriched and then persisted into an Oracle database (different database schema for each system) in their final state. Lets assume the trades are inserted into a table Trade_S and Trade_C in the two databases respectively. Since, system C is supposed to be replacing system S, it is of vital importance, that Trades coming from system C have the same state as their counterparts in system S. That is, if a trade X was managed with system S and came out with a final state t, the same trade must come out with a state t when handled in system C.

The approach one can pursue, is to create some sort of mapping between the different two databases and check their entries for equality, to see if the new system persists the same states for the trades as the old one. Consider for instance a trade X that has a property called isin in the old system and that property is now called tradeIsin in the new system. If system S has persisted Trade_S.isin = 'abc' in the database, the new system should have persisted Trade_C.tradeIsin = 'abc' in its database. Yes we are comparing database entries :-]

This sample code illustrates how to connect to two different databases, read a given number of trades and compare their properties for equality based on a predefined mapping. A modified version of this code was used in a real working environment within a company. A JDBC and a Hibernat/JDBC version is available.

How to Import into Eclipse

  • File -> Import... -> Existing Maven Projects
  • Click Next
  • Click Browse... for the Root Directory
  • Select and open RegressionToolHibernate or RegressionToolJDBC
  • Click Finish
  • Do a mvn update on the project

How to run

  • Run com.lucaslouca.app.Regression.java

Full code


Compare Excel sheets in Java

What is this?

Dear Penthouse, I never thought it would happen to me, but I got my self in a situation where I had to compare two excel sheets and give a report. And because I am lazy in respect that I don't want to compare these sheets manually, I wrote myself a small tool that does this work for me.

This simple Java application basically loads 2 excel sheets of different structures containing names and vacation entries. Nobody but me will probably need this, but I though I'll share it anyway.

For example sheet A contains names and worked hours/per-day for a single month as follows:

... ... Name Surname ... 1 2 3 4 ... 31 ... ...
... ... Joe Doe ... 0 0 4 8 ... 0 ... ...
... ... Joe Doe ... 8 8 4 8 ... 8 ... ...
... ... Foo Bar ... 8 8 0 8 ... 8 ... ...
... ... ...
... ... Moe Goo ... 0 8 8 8 ... 8 ... ...
... ... ...

And sheet B contains names and vacation-flags for each day of the year as follows:

... ... Name, Surname ... 1 ... 31 1 ... 28 1 ... 31 ...
... ... Joe, Doe ...
... ... John, Appleseed ... V V
... ... Foo, Bar ...
... ... ...
... ... Moe, Goo ... V
... ... ...

If sheet A contains a total of 0 working hours for some day for a given person X, that person must have a V (vacation) entry in sheet B for that day of the year. See Moe Goo above.

If that is not the case for a person, we have an inconsistency between the two sheets.

This Java application finds and prints out the persons that are common in both sheets and have such inconsistencies. The application excludes weekends and holidays (loaded into the application as .xml) in its consistency check.

How to Import into Eclipse * File -> Import... -> Existing Maven Projects * Click Next * Click Browse... for the Root Directory * Select and open app * Click Finish * Do a mvn update on app

Full code