Pages

Sep 5, 2012

NaCl & UDP Sockets

One of the big pieces of feedback we've been getting from developers  is that Native Client needs better networking support (read :sockets). Largely sockets have been one of the larger security issues for Native Client and the open web; Imagine if a web page could start sniffing any open packet communication on your computer :( Thankfully though, that’s all changing. With the new Platform Apps technology on the horizon, we now have the ability to play with UDP inside of Native Client, and this post will show you how to play with the early preview of the technology.

According to legend, the internet is a series of tubes. As such, we should allow you to send data through those tubes using Native Client


WARNING:
The future of this feature is in flux; 
The steps below are valid as of 9.9.2012 and are subject to change as the future changes.
Please implement this functionality at your own risk.



 Getting Started with the prototype UDP APIs:

UDP APIs are currently in draft form, meaning they are not available in the stable version of Chrome; In order to play around with these features, you need to be running a canary build of Chrome.

 1. Getting the private headers

Copy the private headers from the Chrome repo into the SDK repo
  • C:\..\chromium\src\ppapi\c\private
  • C:\nacl\pepper_canary\include\ppapi\c\private
Since these headers are currently private, you’ll need to pull them from the Chrome source code. Once these APIs’ stabilize, and are moved out of the private repo, this step will no longer be required

Once done, you can add the following includes to your NaCl app:
#include "ppapi/c/private/ppb_udp_socket_private.h"

2. Run as a packaged app

UDP support in NaCl is ONLY provided as a Chrome extension / packaged app. You cannot develop as a pepper plugin; As such, you’ll need to create a manifest file that’s co-resident with your NaCl app, and launch chrome with --load-extension=PathToYourFolder. This will add the app to your new tab page, that you can then click-on to load. For instance --load-extention=C:/myapp/bin/

NOTE : If the above gives you a 'could not load manifest' error for whatever reason, then you can load the application as an unpacked extension, and things will still work properly.


3. Enable the experimental UDP apis

  • Go to about:flags and enable "NaCl Socket API"
  • Make sure you launch chrome with --allow-nacl-socket-api=IPAddy
  • Make sure you launch chrome with --enable-nacl
In the current state of things, you MUST define what IP address you're going to be connecting to (minus the port number) from native client. For instance --allow-nacl-socket-api=127.0.0.1 will allow your UDP socket to properly connect to that IP address.

4. Note the API differences

Note that the UDP API is not the same as standard socket APIs, due to the restrictions of the Pepper API, the interfaces for UDP are:
  1. Non blocking
  2. Required to be called from the main thread (a fix for this is in the works)

To get a feel for the differences, check out ppapi/c/private/ppb_udp_socket_private.h which generally shows how to create a socket to communicate to; Because of the PPAPI restrictions, the usage of these APIs requires some jiggl’n.

5. Some implementation notes

1) You’ll notice that Bind(..) will return -1, which is a correct, valid return, meaning ‘process pending’; see pp_errors.h for the full list.

2) Notice all the UDP functions take a callback, it’s worth noting that those callbacks will always be called, even if a function fails. If a failure occurs, the datasize param will have a value of -2

3) The IP address that you use to bind your client to should be generated via calling  NetAddressPrivate::GetAnyAddress; Once done, you should call NetAddressPrivate::ReplacePort to update the address with your desired port. Doing so you will bind the UDP port on all network interfaces for the system.

4) To connect to your server, you should be using CreateFromIPv4Address . For testing purpose you can  bind localhost (127.0.0.1) with some port.

5) Note that the RecvFrom takes in a buffer parameter, but due to the async nature of the call, it is possible, but incorrect to make multiple RecvFrom calls on the same socket while a previous call is in flight. Chrome can write async to this buffer at any time, causing your data to get mangledIE. Simultaneous outstanding reads are not possible. The same principal applies with SendTo, you have to wait until previous data portion sent and buffer should stay valid until callback is called. You can, however, call RecvFrom and SendTo can be called in parallel on the same socket without any issues.

6. get ready for the roll out

Chrome Apps are still in early development phases, and when they release, will have full support for UDP sockets w/o needing flags or special params. There will be some minor hoops to jump through that are not yet documented, so stay tuned to Chrome for more!

Source Code

You can grab source code to a simple win32 client communicating to a NaCl platform app via UDP on my github repo.

The example project works by allowing the client to send a message to the server. To use, launch the server first, then launch the client. The server will receive a message that it displays in the console window.

For reference, I launch Chrome with
--allow-nacl-socket-api=127.0.0.1 --no-sandbox --load-extension="C:\nacl_examples\src\UDP_private\client"  --enable-nacl


~Main

You can find Colt McAnlis here:

  

No comments:

Post a Comment