Firmware Upload

Are you using Lua?

The two Lua firmware examples are much smaller and easier to understand than the C example.

The firmware upload example is designed such that you can use it as a base for designing your software upload code.

This is the requirement specification we followed when designing this example.


Requirement Specification

Security

In addition to the above requirements, the web-server allows us to protect the upload resource with an authenticator and an authorizer. The Authenticator class allows us to use form based login for browsers and one of digest or basic HTTP authentication for the batch command. Form based login is normally preferred for browser clients, but non-browser clients can normally not use form based login. Please see the security examples for more information on how to add protection to the upload resource.

Encryption

The ZipIo class makes it possible to protect your firmware bundled in the ZIP file with 128 bits or 256 bits AES encryption. By providing strong AES encryption one can prevent unauthorized users from unzipping the ZIP file. The AES encryption is an open standard initiated by WinZIP, and you can use any ZIP tool that supports the AES encryption standard for creating a password protected ZIP file.

Integrity

Another great reason for using AES encryption is that it verifies the integrity of the ZIP file content. This means that you can guarantee that the ZIP file has not been changed or accidentally modified while in transit.

SharkSSL

The AES encryption is by default disabled in the ZipIo class. This can be enabled by recompiling the class, but this adds a link dependency to the SharkSSL stack.

The Upload and Installation Process

We can divide the upload and firmware installation process into two stages:

  1. Uploading the data.
  2. Checking the uploaded data, unpacking, and installing the subcomponents.

Uploading Data

A batch command typically uploads data using the HTTP PUT command. The HttpAsynchReq class allows the server to receive HTTP PUT data from a batch command.

A browser cannot use HTTP PUT for uploading data. A browser can upload data by using a HTML form of type multipart/form-data. The browser sends the data to the server by using HTTP POST with the data encoded as multipart/form-data. The MultipartUpload class allows the server to receive HTTP POST multipart/form-data.

The HttpAsynchReq and the MultipartUpload classes are designed for a wide variety of uses and are not limited to file upload. These classes, therefore, require a fair amount of support code before they can be used. We only want to upload a ZIP file from a client to the server, and we can, therefore, use the specialized file upload class HttpUpload, which is specifically designed for making it easy to upload files. The HttpUpload class is internally using HttpAsynchReq and MultipartUpload. The HttpUpload class is also used by the HttpResMgr example.

The HttpAsynchReq and the MultipartUpload classes used by the HttpUpload class are designed such that they can upload data concurrently in a single threaded configured Barracuda server, and the web-server can, therefore, accept other requests at the same time as data is uploaded.

The HttpUpload class needs to be wrapped into a Barracuda resource. The virtual file system is built out of HttpDir and HttpPage components. The HttpUpload class requires that it is used from a HttpDir -- i.e. it cannot be used by a leaf node.

You can study the code in UploadFirmware.hpp and UploadFirmware.cpp. The upload directory is called UploadFwDir. An instance of the UploadFwDir is created in InstallVirtualDir.cpp and installed into the Barracuda Virtual File System at location '/upload/'.

Checking and Unpacking the Uploaded Data

We can unpack and install the subcomponents from the ZIP file as soon as the upload is completed. The unpack and installation process may take considerable time. We have, therefore, designed the code such that a thread is started as soon as the upload is completed. This thread is responsible for unpacking the ZIP file and installing the subcomponents. We use the Barracuda Thread class for creating and starting a separate process.

The separate process must maintain the response communication link with the client, but without interfering with normal web-server operation. The HttpAsynchResp class is specifically designed for this. The class allows a non-Barracuda thread to respond to a client. Most browsers allow us to send lengthy response messages and they will asynchronously show the response chunks as they trickle into the browser.

The ZipIo class makes it very easy to unpack the components in a ZIP file. The class allows us to mount a ZIP file and use normal file operations on the files inside the ZIP file. The ZipIo class also allows us to iterate all files in the ZIP file.

We have designed this code such that it simply uncompresses the components in the ZIP file and writes them to the disk. You will have to modify this code such that it also installs the firmware components. The ZIP file is mounted and an iterator iterates and extracts all files in the root of the ZIP file. Directories in the ZIP file are ignored. You must enhance our example code if you also need to extract directories from the ZIP file.

Running the Example

You can upload any ZIP file and test the example program as soon as you have compiled and started the example. You will get to a page containing a HTML form of type multipart/form-data as soon as you type in http://localhost:9357 in a browser. You can use the form to select and upload any ZIP file.

You can also test the batch uploading by using a program such as curl.

Uploading a ZIP file using curl:

curl -T firmware.zip http://localhost:9357/upload/