face: Implement WebSocket channel, face, and factory.

Change-Id: Ic4dbb1abdbbdbec028746ba14b11be8ab9cc1edb
Refs: #1468
diff --git a/.waf-tools/websocket.py b/.waf-tools/websocket.py
new file mode 100644
index 0000000..2c500c7
--- /dev/null
+++ b/.waf-tools/websocket.py
@@ -0,0 +1,77 @@
+# encoding: utf-8
+
+from waflib import Options, Logs, Errors
+from waflib.Configure import conf
+
+import re
+
+def addWebsocketOptions(self, opt):
+    opt.add_option('--without-websocket', action='store_false', default=True,
+                   dest='with_websocket',
+                   help='Disable WebSocket face support')
+setattr(Options.OptionsContext, "addWebsocketOptions", addWebsocketOptions)
+
+@conf
+def checkWebsocket(self, **kw):
+    if not self.options.with_websocket:
+        return
+
+    isMandatory = kw.get('mandatory', True)
+
+    self.start_msg('Checking for Websocket includes')
+
+    try:
+        websocketDir = self.path.find_dir('websocketpp/websocketpp')
+        if not websocketDir:
+            raise Errors.WafError('Not found')
+
+        versionFile = websocketDir.find_node('version.hpp')
+        if not websocketDir:
+            raise Errors.WafError('Corrupted: Websocket version file not found')
+
+        try:
+            txt = versionFile.read()
+        except (OSError, IOError):
+            raise Errors.WafError('Corrupted: cannot read Websocket version file')
+
+        # Looking for the following:
+        # static int const major_version = 0;
+        # static int const minor_version = 3;
+        # static int const patch_version = 0;
+
+        version = [None, None, None]
+
+        majorVersion = re.compile('^static int const major_version = (\\d+);$', re.M)
+        version[0] = majorVersion.search(txt)
+
+        minorVersion = re.compile('^static int const minor_version = (\\d+);$', re.M)
+        version[1] = minorVersion.search(txt)
+
+        patchVersion = re.compile('^static int const patch_version = (\\d+);$', re.M)
+        version[2] = patchVersion.search(txt)
+
+        if not version[0] or not version[1] or not version[2]:
+            raise Errors.WafError('Corrupted: cannot detect websocket version')
+
+        self.env['WEBSOCKET_VERSION'] = [i.group(1) for i in version]
+
+        # todo: version checking, if necessary
+
+        self.end_msg('.'.join(self.env['WEBSOCKET_VERSION']))
+
+        self.env['HAVE_WEBSOCKET'] = True
+        self.define('HAVE_WEBSOCKET', 1)
+
+    except Errors.WafError as error:
+        if isMandatory:
+            self.end_msg(str(error), color='RED')
+            Logs.warn('If you are using git NFD repository, checkout websocketpp submodule: ')
+            Logs.warn('    git submodule init && git submodule update')
+            Logs.warn('Otherwise, manually download and extract websocketpp library:')
+            Logs.warn('    mkdir websocketpp')
+            Logs.warn('    curl -L -O https://github.com/zaphoyd/websocketpp/archive/0.3.0-alpha4.tar.gz')
+            Logs.warn('    tar zxf 0.3.0-alpha4.tar.gz -C websocketpp/ --strip 1')
+            Logs.warn('Alternatively, Websocket support can be disabled with --without-websocket')
+            self.fatal("The configuration failed")
+        else:
+            self.end_msg(str(error))