For the upcoming SIMtrace hardware (e.g. see the communication between SIM and Phone) I want to provide a patched Wireshark and packages for our host utilities to make the installation (and upgrading) very easy.
Being a happy Ubuntu user I started with launchpad, trying to create my own wireshark package. It was very easy to get source of the wireshark package, add a patch, upload it to my ppa. Then I spent some hours figuring out that launchpad does not allow 3.0 (git) git packages (it simply rejects the upload without a proper error message). My biggest issue is to figure how with one upload I could end up with packages for multiple series. E.g. simply copying the package to another series does not work due version numbers (and the need to be able to easily upgrade). So how do people provide to multiple series?
The next thing I tried was the OpenSUSE Build Service. I know that Cornelius is working on it for many years but so far I have always failed using it via the Web Interface. This time I started with an installation of OpenSUSE and used the osc application. The documentation is very sparse (there are many commands and some inconsistencies in naming) and I decided to start with the easy task of modifying an existing package. I have picked wireshark again (it was a bit difficult to find the authorative copy of it), added my patch, uploaded, and I ended up with SuSE packages. The next task was to build packages for the other RPM based distributions and as expected just adding a repository for Fedora didn't work. But here comes the power of this system. First of all the interface shows me that I have a build failure or some missing dependencies and using osc build DISTRO ARCH I can start a local build and take a look at things. awesome! And the build farm of OpenSUSE is fast as well!
The biggest problem I have with OBS is finding documentation, or google not showing it to me. E.g. the cross distribution howto always fails to come up in searches but is very valuable when trying to make your package work on different distributions.
One thing that impressed me a lot was adding a new package. I used osc mkpac placed my sourcecode there and then I had to write my first ever RPM spec file from scratch. So I typed vim libosomocore.spec and somehow I had a skeleton of the spec file present. This is very nice!
Wednesday, July 06, 2011
The last couple of days, to some degree weeks I was implementing a SIP stack for GNU Smalltalk to be used in my Smalltalk GSM project. The first time I encountered SIP was around 2001 when we were excited to run a SIP Phone on our Linux powered iPAQs (Linphone on Opie).
For Smalltalk I started with looking at SipStack by Frank Shearar (who was very responsive to questions regarding his code and SIP in general). The main problem was that his stack was incomplete and as usual it is difficult to pick things up without knowing SIP and not knowing where the code was heading.
I began with mapping the BNF SIP Grammar to rules for the PetitParser parsing framework. I have shortened some rules (e.g. because the generic rule is a catch-all one and I don't need the specialized form yet).
The next big task was to deal with the concepts of a SIP Dialog, a SIP Session, a SIP Transaction and getting the relationship of these entities right. E.g. to place a call one creates an unconfirmed Dialog, prepares the INVITE Transaction and passes it to the transport layer. During this transaction one can get a reply that leads to a confirmation of the dialog. In fact one can end up with multiple confirmed dialogs (called forking, the target phones start ringing in multiple places and can be picked up multiple times as well). To make matters worse some answers need to be sent sent within the same transaction, some open a new one. My code seems to work now but there are some things I don't do properly (e.g. routing). I have documented this and if I have a need for those I will address them.
In the last couple of years I was mostly dealing with a single select IO model, coming to Smalltalk makes me use Processes to read and write from sockets. My basic model is to have a RX Process to use Socket>>#next and a TX process that will do SharedQueue>>#next and then Socket>>#nextPutAll. But with having multiple processes one is required to do proper locking, e.g. have a simple locking hierarchy (first pick the lock of the CallAgent, then the lock of a Dialog/Session). This all works nicely until I reached the point that I have two sub systems talking to each other.
For setting up a call I might have one leg coming from GSM and use the MGCP Protocol, the other leg might be SIP. To hang-up I will need to inform the other leg of the call about it, but this means I will need to have a locking hierarchy that first takes all locks of the left leg of a call, then all locks of the right one which in turns means me I need to dispatch messages without any locks being held. Now besides having RX from maybe a couple of different Processes, I also deal with timeouts that will come from different Processes as well.
To put an end to this (and the complications in the code) I created a simple queue that will BlockClosure>>#value a block from a central dispatch process, this way I have serialized everything and can mostly ignore locking. I hope that Smalltalk VMs will have a nice M:N Process model in the future and that my code will evolve into having different dispatchers running on these N native processes.
Using the code
st> PackageLoader fileInPackage: #OsmoSIP.
st> transport :=SIPUdpTransport startOn: '172.16.254.55' port: 5061.
st> useragent := SIPUserAgent createOn: transport.
st> transport start. "Starts the RX/TX process"
st> call := SIPCall fromUser: 'sip:email@example.com'
host: '172.16.1.72' port: 5060 to: 'sip:firstname.lastname@example.org' on: useragent.
st> call createCall: 'SomeSDP file'.
st> call cancel. "E.g. before it is connected"
st> call hangup. "E.g. when the call is connected."
st> call terminate. "End the call somehow.."