Thursday, October 10, 2013

PirateBox Reloaded

It's been a while since the last PirateBox update. The last version was based on a PAW server plug-in  that didn't work well for all users.
Meanwhile I developed a stand alone PirateBox Android app that hopefully will work better.

The new app is based on CyanogenMod 7 and was tested on a Nexus One.
I have no other devices running CyanogenMod but I hope that the app will run too on different versions of that ROM.

CyanogenMod 7 and Nexus One


This post will describe the app in some detail. Technical details about the networking part will not be covered, because these were described in the earlier post. The techniques are the same, so there is no need to go through all of that again.
For those of you not interested, don't worry, here is the download link to the app straight away. Just download the APK and install it. A rooted device is necessary and it has only be tested with CyanogenMod 7.

So here is the Google Drive download link: PirateBox APKs


Running the App

For those still reading here is the more detailed part...
When you start the app you will  see the (not so spectacular) main screen which basically consists of an image and a start button. If your device is not rooted or the device is missing some prerequisites there will be a message telling so and you will not be able to proceed.

PirateBox - Switched off


After pressing the start button the app will start to setup the network. There is no need to start the hotspot beforehand, that will be done automatically. The app also take care to create an open hotspot and to name it appropriately.
After all is set up, you should see three icons underneath the start button and a notification in form of a scull.



PirateBox - Running


The icons show the active components that are configured during start up. These are, from left to right, the web server, the access point and the network configuration.

 Connecting via Browser

The PirateBox should show up as access point with the default SSID named  PirateBox - Share Freely. The name can be changed inside the setting, but we'll come to that in the next section.

PirateBox - Wi-Fi Access Point


After connecting to the access point you should be able to enter any HTTP URL inside your browser's address bar to get to the index page of the PirateBox.

PirateBox - Index page


App Settings

The app has a few settings. We will discuss them briefly.

PirateBox - Settings


Start On Boot: If you check that option, the PirateBox will start up after the device has been booted and the SD card is ready.

SSID Name: You can change the SSID name here. The app will try to change the name immediately. A restart should not be necessary. The default name is PirateBox - Share Freely as mentioned above.

Storage Directory: The directory which contains the uploaded files and the messages inside the shoutbox. You can locate the directory wherever you like. The directory /sdcard/pb_store is the default.

Enable Updates: On default the configuration and HTML files are updated with each new version of the app. If you don not want to do that, because you want to use your own configuration, un-check that option and no updates will be done.

iOS WISPr Support: iOS devices use WISPr request to detect if the device is indeed online. If not the device will not permanently connect to the hotspot. If that option is enabled the iOS device assumes it's online.

WP NCSI Support: Basically the same as for iOS devices. Windows Phone request a NCSI file to check if it's online.

App Broadcasts

This is a more advances topic and directed to developers which would like to interface with the app.
You do not need to read this section to use the app.
The app broadcast Intents to make indications  about the state of the PirateBox , of file uploads and shout messages.
Here are the broadcasts and the extra values provided.

Intent: de.fun2code.android.piratebox.broadcast.intent.server
Extras: state (boolean)
Description: Indicates the state of the web server.

Intent: de.fun2code.android.piratebox.broadcast.intent.ap
Extras: state (boolean)
Description: Indicates if the access point is running or not.

Intent: de.fun2code.android.piratebox.broadcast.intent.network
Extras: state (boolean)
Description: If the state is true, the networking (dnsmasq and iptables) are configured.

Intent: de.fun2code.android.piratebox.broadcast.intent.shout
Extras: name (String), text (String)
Description: If a message is entered into the shoutbox, the name and text will be included inside the extras of this Intent.

Intent: de.fun2code.android.piratebox.broadcast.intent.upload
Extras: file (String)
Description: Upon file upload the extra will contain the FQN of the file.


Current State

The app is in an very early state. I've tested as good as I could. There are surely bugs and  in some cases the app might not work at all.

New updates of the APK will show up in the Google Drive folder linked below.
So if you are interested, check the folder from time to time.

Feedback is always welcome!

Source Code

The source code is now available on GitHub.

In Case of Errors

If the PirateBox does not work as expected, please send me a mail describing your setup and include the LogCat output ... thanks

Mail address: jochen [at] fun2code.de

Download Links

Google Drive: PirateBox APKs

Questionnaire

If you tried the app, please provide feedback by filling out the following questionnaire ... thanks!
The results can be viewed here, so you know on which configurations PirateBox is running.

Wednesday, September 18, 2013

Chatting with Web Sockets

Web Sockets enable direct socket connections between a web browser and a web server.
Newer versions of PAW support text based Web Sockets. This post shows how to build a small Web Sockets based chat server.

If you have ever tried coding a web based chat server you have surely noticed that the task is not as easy as it might seem at the first look. You have to deal with sessions and have to synchronize clients and so forth. That’s one of the reasons why I never did that ;).
We will see that with Web Sockets there are only a few lines of code necessary on the server side.

I will not go into much detail when it comes to the HTML part, this is standard and everybody can google that.
What I will explain in detail is the PAW setup and the server side BeanShell script included in implementing the chat server.

Configuring the Web Socket Handler

To enable Web Socket support for your PAW server, we have to insert and configure the Web Socket handler inside the handler.xml file. The file is located inside the conf folder of your PAW installation directory . The installation directory is normally /sdcard/paw. Inside the handler.xml file the installation directory is referenced as [PAW_HOME].

The handler can be places right in front of the configuration file inside the <handlers>...</handlers>
tag:

<handler status="active">
    <name>WebSocket Handler</name>
    <description>WebSocket Handler</description>
    <removable>true</removable>
    <id>websocket</id>
    <files/>
    <params>
      <param name="websocket.class" value="org.paw.handler.android.websocket.WebSocketHandler" />
      <param name="websocket.basedir" value="[PAW_HOME]" />
      <param name="websocket.config" value="[PAW_HOME]/webconf/websocket.conf" />
    </params>
  </handler>

There are two important parameters in that handler definition… basedir and config.

Let’s start with config. The parameter config specifies the location of the Web Socket definition file. This file defines rules that describe which BeanShell script (or Java class) to call if a Web Socket connection requesting a specific protocol comes along.

A Web Socket communication can specify a protocol to use, which makes it possible for the server to react differently even if listening to the same port.
A common protocol type is chat which the client sends to the server within the header when the connection is established. You can also define your own protocol, it’s just a text.

In our example the web browser will send a different protocol for each chat room which makes it possible for the server to distinguish them. So if a chat room is called talk, the protocol will be chat.talk.

The other parameter basedir defines the base directory of the BeanShell scripts which are defined inside the Web Socket configuration file.

In the next step, we’ll create the Web Socket config file.

Web Socket Config File

As defined in the handler definition, create a file called [PAW_HOME]/webconf/websocket.conf with the following content:

# Format:
# Protocol:Bsh script (.bsh extension) or class name
#
chat.*:html/websocket/websocket_chat.bsh

That’s it, actually quite simple. I’ll quickly explain the syntax.
The parameters are devided by colons.

First parameter is the protocol which is defined as a regular expression. So in our case the server will call the script html/websocket/websocket_chat.bsh for all protocols starting with chat. Now you already know the second parameter which is the BeanShell script to call.

Actually you can also use a Java class (or performance reasons) but this will not be handled inside this post. More about how to get this working with Java classes can be found inside the PAW Functions section of the PAW web interface.

The next step is to create the BeanShell script.

The BeanShell Script

Before creating the script, some infos in advance.
The handler sets some variables before it calls the script. These variables are action, message, sockets and socket.
The action variable tells us something about the state of the communication. Possible values are connect, disconnect  or text. The state important for us is text because it indicated that a text message has been sent by a client.

If text is set, there is also a variable called message which contains the message itself.

Let’s now have a look at the code, because I think will make things clearer.
Create a file called [PAW_HOME]/html/websocket/websocket_chat.bsh
 with the following content:

import de.fun2code.android.pawserver.websocket.WebSocketMessage;

if(action.equals("text")) {
    for(sock : sockets) {
        try {
            WebSocketMessage.sendMessage(message, sock);
        }
        catch(e) {
          sock.close();
        }
    }
}

That’s the complete server side code. First thing that is checked is if the action variable is set to text which indicates that a message text is available inside the message variable.

If a message is present the code iterates over the sockets collection. The sockets collection contains all client socket connections that have the same protocol.
The socket collections are grouped by Web Socket protocol names, so we are sure that all sockets inside the collection belong to the same chat room.
As mentioned above, the web browser sends different Web Socket protocol names for each chat room (chat.>chatroom>).

So all that is left is to send the incoming message to all connected client. This is done by the following line:

 WebSocketMessage.sendMessage(message, sock);

The try/catch block is there to close a socket if something goes wrong.

One variable that is not present in the code and therefore was not handled until now is the socket variable. This variable contains the socket of the client that delivered the message.

The HTML File

The only thing that is missing is now the HTML file that is responsible for opening the Web Socket connection from the web browser. This is actually a XHTML file because it contains some additional BeanShell code.

The file can be downloaded from the link below. Just copy it into the [PAW_HOME]/html/websocket/ directory.
Now you can start your browser and call the XHTML file by inserting the following address into your browser’s address bar:

http://<ip>:<port>/websocket/chat.xhtml

Web Socket Chat

If everything goes well, the Web Socket chat server should be up and running.
In case of questions, write a comment or send me a mail.

Happy coding :)

Links

XHTML File: websocket_chat_xhtml.zip

Monday, September 16, 2013

PAW - Build Your Own Server


A lot of people have been asking about the PAW source code.
PAW is not Open Source, so (for the time being) you cannot get the source.

Nevertheless … it is now possible for developers to build their own PAW based apps for private and educational purposes. If you plan to use PAW in a commercial product, please drop me a line.

To make this easy, the PAW source code has been restructured.
A sample project along with documentation and a sample APK can be downloaded form the links listed below.
The process of creating a PAW based app should quite easy. Please read the linked documentation for detailed instructions.

 … happy coding! :)

Links:

Documentation: Build_Own_PAW_Server.pdf
Eclipse Project: BuildOwnPawServer.zip
Sample APK: BuildOwnPawServer.apk