Web chat using Strophe and Openfire


XMPP is now widely used to implement messaging and presence services. Popular applications and services such as Google Voice, Google Talk, Jabber etc are based on it. Openfire is one really popular cross-platform Java server infrastructure for XMPP. On the client side there is an increasing trend towards applications done in HTML and JavaScript. There now exist some pure JavaScript client libraries such as Strophe that support this trend. These work with the HTTP binding provided by Openfire based on BOSH.

In this post I explain how I setup a simple chat application called trophyim to run with Openfire. I’ll use Apache httpd along the way to proxy access to the http binding service provided by Openfire, to get around cross-origin errors. Openfire should soon implement W3C CORS support so we don’t need to proxy HTTP requests.

Obtain and build Strophe

Download Strophe from github. Build it using make (I usually have a Linux VM around for such occasions).

Setup Openfire and Apache httpd

Download and setup Openfire (version 3.7.0 used here) and Apache httpd. Openfire provides a web browser based administration console at port 9090 (e.g. http://localhost:9090) that you can use to add users. The BOSH based http binding service runs at port 7070. A Strophe connection needs to be opened to url http://localhost:7070/http-bind/.

Setup trophyim

Obtain trophyim (version 0.3 used here) provide access to it through Apache httpd, I’ll assume that accessing http://localhost/trophyim.0.3/index.html from the browser runs the chat client. Copy strophe.js to a folder called strophejs within trophyim. You’ll need to change the variable TROPHYIM_BOSH_SERVICE in the trophyim.js file to http://localhost:7070/http-bind/.

Direct access to that URL from the chat client will result in a cross-origin request, this fails in most browsers. In Chrome you should see a message such as:

XMLHttpRequest cannot load http://localhost:7070/http-bind/.
Origin http://localhost is not allowed by Access-Control-Allow-Origin.

Change the TROPHYIM_BOSH_SERVICE variable to http://localhost/bosh. We’ll now configure Apache httpd to proxy that URL to http://localhost:7070/http-bind/.

Configure Apache httpd as a proxy

Edit conf/httpd.conf located in the Apache httpd installation folder. Uncomment the following lines (remove #):

LoadModule proxy_module modules/mod_proxy.so

LoadModule proxy_connect_module modules/mod_proxy_connect.so

LoadModule proxy_http_module modules/mod_proxy_http.so

Include conf/extra/httpd-vhosts.conf

Next, edit conf/extra/httpd-vhosts.conf. Remove any stray VirtualHost directives there and add:


    ProxyPass /bosh http://localhost:7070/http-bind/
    ProxyPassReverse /bosh http://localhost:7070/http-bind/

Restart Apache httpd and reload page http://localhost/trophyim.0.3/index.html. You should now have a running chat client. Log in. Run another instance of the chat client and log in with a different user. If both users are buddies you should be able to chat.

Happy chatting!

Build a custom embedded Linux system using buildroot


In this post I build a custom embedded Linux bootable CD that I can run in an x86 VM. I would like to appreciate the help I received from the official documentation.

Obtain buildroot

Get buildroot. I use version 2011.02 in this post. My build machine is a Virtual Box VM running Ubuntu 10.04 LTS. I have Virtual Box Guest Additions installed, which I use to access a shared folder on the host OS, to get files in and out of the VM.

To configure buildroot, you’ll require several tools. make is one, but most Linux installations have that already. You’ll probably need to apt-get a few things along the way. You’ll certainly require ncurses, which can be obtained as follows

sudo apt-get install libncurses5-dev

Configure buildroot

To configure buildroot, you need to run make menuconfig in the folder you extracted it. Here’re the options I use

  • Target architecture – i386
  • Target architecture variant – i686
  • Kernel – Kernel version: 2.6.37.2, Kernel configuration: Using a defconfig, Defconfig name: i386
  • Target filesystem options – ext2, iso image
  • Bootloaders – grub

Exit and choose to save the configuration file.

Build

Run make once you are done saving the buildroot configuration. The build process takes some time because it downloads lots of different things required to build the toolchain, Linux kernel, and the root filesystem. Go and have some coffee. You can speed up the build process by setting up the Virtual Box VM to use multiple cores on the host PC, and allowing buildroot to run as many jobs as you have cores (default setting is 2). This is done using make menuconfig under Build Options, Number of jobs to run simultaneously. Using multiple cores can be buggy, I have had my VM freeze several time.

Run embedded Linux

Copy the iso file rootfs.iso9660 from the output/images folder to the host machine as rootfs.iso. Create a new Virtual Box VM and set the iso file as the CD/DVD drive. Start the new VM. If all goes well (it won’t) you’ll get the login prompt where typing root should let you in to the command line. This first time you’ll not be able to get in because we did not configure the Linux kernel for the ext2 filesystem. Let us see how to do that now.

Configure the Linux kernel

You have built once and all kernel sources should be available at the folder output/build/linux-2.6.37.2. The kernel build configuration file .config is located in that folder. To change that configuration we’ll need to do two things – modify the linux configuration using make linux-menuconfig, and modify the buildroot configuration for the kernel to use that configuration file during the build.

To modify the Linux configuration, invoke make linux-menuconfig from the buildroot root folder. Head over to File systems and select Second extended fs support. Exit and save the configuration.

To modify the buildroot configuration to use the new kernel configuration, execute make menuconfig. Head over to Kernel, Kernel configuration, and select Using a custom config file. Change Configuration file path to output/build/linux-2.6.37.2/.config. Exit and save the buildroot configuration. Build, copy the resulting iso file to the host OS and run the test VM. You should now be able to log in as root.

Next steps

Now, you can modify your custom embedded Linux kernel to support other devices you’ll need, deploy it to hardware… sky’s the limit!

Kudos – Fabio Urquiza at cesar.org.br

Playing raw PCM audio using Audacity


Audacity has always been my favorite tool to do simple sound editing. I turned to it to play raw PCM audio captured by a sniffer I am writing. Here’re the steps to import raw PCM audio in Audacity:

1. Run Audacity

2. From the Project menu, select Import Raw Data…

Update: In newer versions of Audacity go to File menu, Import, Raw Data…

3. Select file with PCM data

4. Audacity tries to best guess the parameters required for importation. You’ll need to change some of them, at least the Sample Rate

5. Click Import

Convert ASCII Hex text to binary


Debugging sometimes means dumping a hex stream to the console, or to a log file, something like 0x0a 0xff…

I wrote a simple command line tool to convert that kind of hex data to binary. Users of Linux can resort to the fine xxd utility to do the same thing.

The following are all valid hex values (and produce the same binary sequence).

  • “0xDE 0xAD”
  • “0xDE0xAD”
  • “0xD E0xAD”
  • “0xD\r\nE0xAD”
  • “0xDE\r\n 0xAD”
  • “0xDE\n 0xAD”
  • “0xDE\r 0xAD”
  • “0xD\r\nE 0xAD”
  • “0x00DE 0xAD”
  • “DE AD”
  • “DEAD”
  • “DEA D”
  • “DEA\r\nD”

The following are invalid and will result in an error.

  • “0x01DE 0xAD”
  • “0xDExAD”
  • “0xDE AD”

The source code follows. You can also fork it at GitHub.

    public class HexToBin
    {
        /// <summary>
        /// Reads hex data from input file and writes corresponding binary to output file.
        /// </summary>
        /// <param name="infile">Input file name.</param>
        /// <param name="outfile">Output file name</param>
        /// <param name="encoding">Character encoding of data in input file.</param>
        /// <returns>Number of bytes written or a negative value on error.</returns>
        public static int Convert(string infile, string outfile, Encoding encoding)
        {
            StreamReader inf = new StreamReader(File.OpenRead(infile), encoding);
            FileStream outf = File.OpenWrite(outfile);

            int count = Convert(inf, outf);

            inf.Close();
            outf.Close();

            return count;
        }

        /// <summary>
        /// Reads hex data read from the specified reader, and writes corresponding binary
        /// to the specified output stream.
        /// </summary>
        /// <param name="input">Input text reader from where characters are read.</param>
        /// <param name="output">Output stream to where binary data is written.</param>
        /// <returns>Number of bytes written or a negative value on error.</returns>
        public static int Convert(TextReader input, Stream output)
        {
            int line = 1;
            int col = 1;
            int colStart = 0;
            int count = 0;
            bool parse = false;
            bool has0x = false;

            StringBuilder val = new StringBuilder();
            while (true)
            {
                int ch = input.Read();
                switch (ch)
                {
                    case '\n':
                    case '\r':
                        line++;
                        col = 0;
                        if (ch == '\r' && input.Peek() == '\n')
                        {
                            // just so we don't count the same line twice for dos/windows
                            input.Read();
                        }
                        if (!has0x && val.Length == 2)
                        {
                            parse = true;
                        }
                        break;

                    case ' ':
                        if (!has0x && val.Length == 2)
                        {
                            parse = true;
                        }
                        break;

                    case -1:
                        if (val.Length > 0)
                        {
                            parse = true;
                        }
                        break;

                    default:
                        if (colStart == 0)
                        {
                            colStart = col;
                        }
                        if (ch == '0')
                        {
                            // strip off 0x
                            int x = input.Peek();
                            if (x == 'x' || x == 'X')
                            {
                                has0x = true;
                                if (val.Length > 0)
                                {
                                    parse = true;
                                }

                                // skip
                                input.Read();
                                col++;
                                break;
                            }
                        }
                        val.Append((char)ch);
                        if (!has0x && val.Length == 2)
                        {
                            parse = true;
                        }
                        break;
                }

                if (parse)
                {
                    count++;
                    byte result;
                    if (byte.TryParse(val.ToString(), NumberStyles.HexNumber,
                        CultureInfo.InvariantCulture, out result))
                    {
                        output.WriteByte(result);
                    }
                    else
                    {
                        Console.Error.WriteLine("Bad data at line {0} column {1}: {2}",
                            line, colStart, val);
                        return -1;
                    }
                    val.Clear();
                    colStart = 0;
                    parse = false;
                }

                if (ch == -1)
                {
                    break;
                }

                col++;
            }
            return count;
        }
    }

    class MainClass
    {
        public static void Main (string[] args)
        {
            if (args.Length == 0)
            {
                Console.WriteLine("Usage: cmd <input filename> <output filename>");
                return;
            }

            try
            {
                int count = HexToBin.Convert(args[0], args[1], Encoding.ASCII);
                Console.WriteLine("{0} bytes written to output file", count);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                Console.WriteLine(e.StackTrace);
            }
        }
    }

Points to remember when using p/invoke from C#


This blog post tries to capture some essential points to remember when using p/invoke from C#.

C++

You can expose static methods of a C++ class using the __declspec(dllexport) modifier. The C++ compiler adds each method to the exports table of a DLL with a different name. Use the dumpbin utility (distributed with Visual Studio) to get the exported name of a method and add an EntryPoint field to the DllImport attribute. Dependency Walker is another good tool that shows the exports.

Calling conventions

Read this article that describes the different calling conventions in great detail. If you haven’t added calling conventions in your VC++ code, by using either __stdcall or __cdecl, or by changing the compiler setting, you should remember to set the CallingConvention field in the DllImport Attribute to CallingConvention.Cdecl.

Callback using delegates

I refer you to this article that demonstrates passing delegates. In particular, it shows the right calling convention for .NET delegates i.e. __stdcall. If you have only the binaries for a DLL, you can tell C# to use CallingConvention.Cdecl using the UnmanagedFunctionPointerAttribute for the delegate. Note that you need to create a new instance of the delegate and pass that in your p/invoke call. Passing the method name can lead to a hard to decipher System.AccessViolationException.

Marshalling or type mapping

This article has a table of type mappings and other tips regarding marshalling. In case you need to pass or receive an array of bytes (char* in C or C++) or any opaque pointer, the IntPtr structure can be used. Use the Copy method from the System.Runtime.InteropServices.Marshal class to recover data as an array of bytes.

P/Invoke Interop Assistant

The P/Invoke Interop Assistant tool is very useful, it automatically generates C# p/invoke declarations for type and function declarations in C and C++. Red Gate has a free plugin for Visual Studio that can help you to find and contribute p/invoke signatures for well known APIs.

Kindle store books become pricier


I purchased the Stieg Larsson thriller The Girl Who Played with Fire on February 12th for $5.00. Now it is on sale for $7.99, a noticeable price appreciation. Is it the effect of Random House books appearing in the iBooks store? In my opinion, e-Books should be cheaper. They are cheaper to replicate and distribute. They cannot be easily shared with anyone else, which in theory should lead to more individual purchases.

Immersive content for the Browser


Second life is probably the best example of a 3D simulated universe, a highly immersive experience.

I’ve seen experiments in rendering 3D using Javascript. The HTML 5 Canvas element is at the center of that revolution. Check CanvasMOL as one example of what is possible. Chrome and other webkit-based browsers have been working on GPU-based acceleration of the HTML 5 Canvas and the associated WebGL 3D graphics API. Check this cool demo of WebGL in action, several other demos are linked from this blog post on WebGL. Browser-based games that use these features are beginning to appear. Imagine racing cars such as rendered by HelloRacer.

Adobe Flash is used by pretty much everyone in the 2D gaming community. Check out Club Penguin and Habbo as examples of this approach. Unity 3D is also available for doing Browser-based games in Java for the web, and also for a raft of different devices.

All in all, developers love it when they can target different devices and form-factors from the same code base, without worrying about obsolescence. HTML 5 may really shine there.