This patch adds utilities transmit packets via WebSocket protocol.
WebSocket version of utilities as following.
  usbws : command
  usbwsa : application-side daemon
  usbwsd : device-side daemon

The command supports all sub-command (ie. list, connect, disconnect, 
port, bind, unbind, attach and detach). It uses --url option to specify 
remote address and port number. 

Implementation of this patch depends on Poco C++ 
(http://pocoproject.org/).

The tree is shown below.
  tools
    +--usb
         +--usbip
              +--src : command, daemons and their core libraries 
              +--libsrc : common library for command and daemon
              +--websocket : new! WebSocket implementations
                   +--poco : new! implementation with Poco C++

Signed-off-by: Nobuo Iwata <nobuo.iw...@fujixerox.co.jp>
---
 tools/usb/usbip/websocket/INSTALL             | 237 ++++++++++
 tools/usb/usbip/websocket/Makefile.am         |   3 +
 tools/usb/usbip/websocket/README              | 184 ++++++++
 tools/usb/usbip/websocket/autogen.sh          |   9 +
 tools/usb/usbip/websocket/cleanup.sh          |  12 +
 tools/usb/usbip/websocket/configure.ac        |  55 +++
 tools/usb/usbip/websocket/doc/usbws.8         | 192 ++++++++
 tools/usb/usbip/websocket/doc/usbwsa.8        | 101 +++++
 tools/usb/usbip/websocket/doc/usbwsd.8        | 109 +++++
 tools/usb/usbip/websocket/poco/Makefile.am    |  18 +
 .../usb/usbip/websocket/poco/USBWSCommand.cpp | 410 ++++++++++++++++++
 tools/usb/usbip/websocket/poco/USBWSCommand.h |  99 +++++
 .../usb/usbip/websocket/poco/USBWSDaemon.cpp  | 228 ++++++++++
 tools/usb/usbip/websocket/poco/USBWSDaemon.h  |  80 ++++
 .../websocket/poco/USBWSRequestHandler.cpp    |  90 ++++
 .../websocket/poco/USBWSRequestHandler.h      |  49 +++
 .../poco/USBWSRequestHandlerFactory.cpp       |  47 ++
 .../poco/USBWSRequestHandlerFactory.h         |  48 ++
 tools/usb/usbip/websocket/poco/USBWSUtil.h    |  52 +++
 .../usbip/websocket/poco/USBWSWebSocket.cpp   | 201 +++++++++
 .../usb/usbip/websocket/poco/USBWSWebSocket.h |  69 +++
 21 files changed, 2293 insertions(+)

diff --git a/tools/usb/usbip/websocket/INSTALL 
b/tools/usb/usbip/websocket/INSTALL
new file mode 100644
index 0000000..d3c5b40
--- /dev/null
+++ b/tools/usb/usbip/websocket/INSTALL
@@ -0,0 +1,237 @@
+Installation Instructions
+*************************
+
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
+2006, 2007 Free Software Foundation, Inc.
+
+This file is free documentation; the Free Software Foundation gives
+unlimited permission to copy, distribute and modify it.
+
+Basic Installation
+==================
+
+Briefly, the shell commands `./configure; make; make install' should
+configure, build, and install this package.  The following
+more-detailed instructions are generic; see the `README' file for
+instructions specific to this package.
+
+   The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation.  It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions.  Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+   It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring.  Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.
+
+   If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release.  If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+   The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'.  You need `configure.ac' if
+you want to change it or regenerate `configure' using a newer version
+of `autoconf'.
+
+The simplest way to compile this package is:
+
+  1. `cd' to the directory containing the package's source code and type
+     `./configure' to configure the package for your system.
+
+     Running `configure' might take a while.  While running, it prints
+     some messages telling which features it is checking for.
+
+  2. Type `make' to compile the package.
+
+  3. Optionally, type `make check' to run any self-tests that come with
+     the package.
+
+  4. Type `make install' to install the programs and any data files and
+     documentation.
+
+  5. You can remove the program binaries and object files from the
+     source code directory by typing `make clean'.  To also remove the
+     files that `configure' created (so you can compile the package for
+     a different kind of computer), type `make distclean'.  There is
+     also a `make maintainer-clean' target, but that is intended mainly
+     for the package's developers.  If you use it, you may have to get
+     all sorts of other programs in order to regenerate files that came
+     with the distribution.
+
+  6. Often, you can also type `make uninstall' to remove the installed
+     files again.
+
+Compilers and Options
+=====================
+
+Some systems require unusual options for compilation or linking that the
+`configure' script does not know about.  Run `./configure --help' for
+details on some of the pertinent environment variables.
+
+   You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment.  Here
+is an example:
+
+     ./configure CC=c99 CFLAGS=-g LIBS=-lposix
+
+   *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory.  To do this, you can use GNU `make'.  `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script.  `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+   With a non-GNU `make', it is safer to compile the package for one
+architecture at a time in the source code directory.  After you have
+installed the package for one architecture, use `make distclean' before
+reconfiguring for another architecture.
+
+Installation Names
+==================
+
+By default, `make install' installs the package's commands under
+`/usr/local/bin', include files under `/usr/local/include', etc.  You
+can specify an installation prefix other than `/usr/local' by giving
+`configure' the option `--prefix=PREFIX'.
+
+   You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files.  If you
+pass the option `--exec-prefix=PREFIX' to `configure', the package uses
+PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files still use the regular prefix.
+
+   In addition, if you use an unusual directory layout you can give
+options like `--bindir=DIR' to specify different values for particular
+kinds of files.  Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+   If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System).  The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+   For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+There may be some features `configure' cannot figure out automatically,
+but needs to determine by the type of machine the package will run on.
+Usually, assuming the package is built to be run on the _same_
+architectures, `configure' can figure that out, but if it prints a
+message saying it cannot guess the machine type, give it the
+`--build=TYPE' option.  TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+     CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+     OS KERNEL-OS
+
+   See the file `config.sub' for the possible values of each field.  If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+   If you are _building_ compiler tools for cross-compiling, you should
+use the option `--target=TYPE' to select the type of system they will
+produce code for.
+
+   If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+Sharing Defaults
+================
+
+If you want to set default values for `configure' scripts to share, you
+can create a site shell script called `config.site' that gives default
+values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists.  Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+Variables not defined in a site shell script can be set in the
+environment passed to `configure'.  However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost.  In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'.  For example:
+
+     ./configure CC=/usr/local2/bin/gcc
+
+causes the specified `gcc' to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+Unfortunately, this technique does not work for `CONFIG_SHELL' due to
+an Autoconf bug.  Until the bug is fixed you can use this workaround:
+
+     CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+`configure' Invocation
+======================
+
+`configure' recognizes the following options to control how it operates.
+
+`--help'
+`-h'
+     Print a summary of the options to `configure', and exit.
+
+`--version'
+`-V'
+     Print the version of Autoconf used to generate the `configure'
+     script, and exit.
+
+`--cache-file=FILE'
+     Enable the cache: use and save the results of the tests in FILE,
+     traditionally `config.cache'.  FILE defaults to `/dev/null' to
+     disable caching.
+
+`--config-cache'
+`-C'
+     Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+     Do not print messages saying which checks are being made.  To
+     suppress all normal output, redirect it to `/dev/null' (any error
+     messages will still be shown).
+
+`--srcdir=DIR'
+     Look for the package's source code in directory DIR.  Usually
+     `configure' can determine that directory automatically.
+
+`configure' also accepts some other, not widely useful, options.  Run
+`configure --help' for more details.
+
diff --git a/tools/usb/usbip/websocket/Makefile.am 
b/tools/usb/usbip/websocket/Makefile.am
new file mode 100644
index 0000000..008c817
--- /dev/null
+++ b/tools/usb/usbip/websocket/Makefile.am
@@ -0,0 +1,3 @@
+SUBDIRS := poco
+
+dist_man_MANS := $(addprefix doc/, usbws.8 usbwsa.8 usbwsd.8)
diff --git a/tools/usb/usbip/websocket/README b/tools/usb/usbip/websocket/README
new file mode 100644
index 0000000..94d48a0
--- /dev/null
+++ b/tools/usb/usbip/websocket/README
@@ -0,0 +1,184 @@
+#
+# README for usbip-utils WebSocket extension sample.
+#
+# Copyright (C) 2015 Nobuo Iwata
+#
+
+1) Goal of this sample
+
+    To give a sample application of userspace transmission of USB/IP and it's
+    utilities.
+
+2) Requirement
+
+2-1) POCO C++ implementation
+
+    Install C++ package.
+
+    > sudo yum install gcc-c++
+
+    Install openssl-devel or openssl-dev package.
+
+    > sodo yum install openssl-devel
+
+    Get complete edition source code from http://pocoproject.org/.
+
+    > ./configure --omit=Data/ODBC,Data/MySQL
+
+    > make
+
+    > sudo make install
+
+3) Make
+
+3-1) POCO C++ implementation
+
+    Compile drivers.
+
+    > cd usbip
+    > make
+
+    Compile libraries.
+
+    > cd tools/usb/usbip
+    > make
+
+    Compile WebSocket utilities.
+
+    > cd tools/usb/usbip/websocket
+    > make
+
+4) Usage of WebSocket utilities
+
+    usbwsa [options] - daemon for application side
+
+    usbwsd [options] - daemon for device side
+
+    -d, --debug
+        Enable debug messages.
+    -t, --tcp=PORT-NUMBER
+        Serving TCP port number. Default is 80 or 443 for non-SSL and SSL
+        respectively.
+    -p, --path=PATH
+        Serving path portion of URL. Default is /usbip.
+    -i, --interval=INTERVAL
+        Noncommunication time period to send ping-pong in seconds.
+        Default is 60. 0 denotes not to use ping-pong.
+    -s, -ssl
+        SSL mode, ie. wss.
+    -k, --key=KEY-FILE
+        Private key file. Default is cert/server.key.
+    -c, --cert=CERT-FILE
+        Certificate file. Default is cert/server.crt.
+    -r, --root-cert=ROOT-CERT-FILE
+        Certificate file of root CA. Not used as default.
+    -V, --verification=VERIFICATION-MODE
+        none(default), relaxed, strict or once.
+    -h, --help
+        Print help.
+    -v, --version
+        Show version.
+
+    usbws <command> [options] - command for both device and application side
+
+    command
+        connect - export a device to remote. (at device side)
+        disconnect - unexport a device from remote. (at device side)
+
+        list - list local devices. (at device side)
+               list importable devices. (at application side)
+        port - list imported devices. (at application side)
+
+        bind - make a device importable. (at device side)
+        attach - import a device. (at application side)
+        detach - cancel import. (at application side)
+        unbind - make a device not importable. (at device side)
+
+    -d, --debug
+        Enable debug messages.
+    -u, --url=URL
+        URL of WebSocket server. ex) ws://<host>/usbip or wss://<host>/usbip
+        Default port number is 80 or 443 for ws and wsss respectively.
+    -p, --proxy=URL
+        URL of http proxy server. ex) http://<proxy-addr>:8080
+        No proxy is used as default.
+        Proxy user and password can be specified in URL.
+        ex) http://<user>:<pwd>@<proxy-host>:8080
+    -b, --busid=BUS-ID
+        Bus ID of a device to export or unexport.
+    -o, --timeout
+        Connect timeout in seconds. Default is 5.
+    -i, --interval=INTERVAL
+        Noncommunication time period to send ping-pong in seconds.
+        Default is 60. 0 denotes not to use ping-pong.
+    -k, --key=KEY-FILE
+        Private key file. Default is cert/server.key.
+    -c, --cert=CERT-FILE
+        Certificate file. Default is cert/server.crt.
+    -r, --root-cert=ROOT-CERT-FILE
+        Certificate file of root CA. Not used as default.
+    -V, --verification=VERIFICATION-MODE
+        none(default), relaxed.
+   
+5) Execution
+
+5-1) POCO C++ implementation
+
+    Insert drivers.
+
+    a) Application side computer
+        # cd usbip
+        # insmod usbip-core.ko
+        # insmod usbip-ux.ko
+        # insmod vhci-hcd.ko
+
+    b) Device side computer
+        # cd usbip
+        # insmod usbip-core.ko
+        # insmod usbip-ux.ko
+        # insmod usbip-host.ko
+
+    Execute utilities.
+
+    a) Application side computer
+        # cd usbip/userspace
+        # websocket/poco/usbwsa --tcp-port 3240 --ssl
+
+    b) Device side computer
+        --- START ---
+        # cd usbip/userspace
+        # websocket/poco/usbws connect \
+        --url wss://111.222.333.444:3240/usbip -b 1-2
+        NOTE: it will running while normal operation.
+
+        --- END ... in another window ---
+        # cd usbip/userspace
+        # websocket/poco/usbws disconnect \
+        --url wss://111.222.333.444:3240/usbip -b 1-2
+
+Usage via HTTP proxy
+
+    Example below shows usage pass through squid proxy.
+
+    a) Summary of /etc/squid/squid.conf
+        acl SSL_ports port 443
+        acl CONNECT method CONNECT
+        http_access deny CONNECT !SSL_ports
+        http_port 3128
+
+    b) Application side
+        # cd usbip/userspace
+        # websocket/poco/usbwsa --ssl
+
+    c) Device side
+        --- START ---
+        # cd usbip/userspace
+        # websocket/poco/usbws connect -proxy http://proxy.example.com:3128 \
+        --url wss://111.222.333.444/usbip -b 1-2
+        NOTE: it will running while normal operation.
+
+        --- END ... in another window ---
+        # cd usbip/userspace
+        # websocket/poco/usbws disconnect -proxy http://proxy.example.com:3128 
\
+        --url wss://111.222.333.444/usbip -b 1-2
+
diff --git a/tools/usb/usbip/websocket/autogen.sh 
b/tools/usb/usbip/websocket/autogen.sh
new file mode 100755
index 0000000..e1112d3
--- /dev/null
+++ b/tools/usb/usbip/websocket/autogen.sh
@@ -0,0 +1,9 @@
+#!/bin/sh -x
+
+#aclocal
+#autoheader
+#libtoolize --copy --force
+#automake-1.9 -acf
+#autoconf
+
+autoreconf -i -f -v
diff --git a/tools/usb/usbip/websocket/cleanup.sh 
b/tools/usb/usbip/websocket/cleanup.sh
new file mode 100755
index 0000000..810f99c
--- /dev/null
+++ b/tools/usb/usbip/websocket/cleanup.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+if [ -r Makefile ]; then
+       make distclean
+fi
+
+FILES="aclocal.m4 autom4te.cache compile config.guess config.h.in config.log \
+       config.status config.sub configure cscope.out depcomp install-sh      \
+       poco/Makefile poco/Makefile.in libtool ltmain.sh Makefile         \
+       Makefile.in missing"
+
+rm -vRf $FILES
diff --git a/tools/usb/usbip/websocket/configure.ac 
b/tools/usb/usbip/websocket/configure.ac
new file mode 100644
index 0000000..39ea211
--- /dev/null
+++ b/tools/usb/usbip/websocket/configure.ac
@@ -0,0 +1,55 @@
+dnl Process this file with autoconf to produce a configure script.
+
+AC_PREREQ(2.59)
+AC_INIT([usbws-utils], [0.1.0], [linux-usb@vger.kernel.org])
+
+AC_CONFIG_HEADERS([config.h])
+
+AM_INIT_AUTOMAKE([foreign])
+LT_INIT
+
+# Silent build for automake >= 1.11
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+
+AC_SUBST([EXTRA_CFLAGS], ["-Wall -Werror -Wextra -std=gnu99"])
+
+# Checks for programs.
+AC_PROG_CC
+AC_PROG_CXX
+AC_PROG_INSTALL
+AC_PROG_MAKE_SET
+
+# Set language to C++
+AC_LANG_CPLUSPLUS
+
+# Checks for header files.
+AC_HEADER_DIRENT
+AC_HEADER_STDC
+AC_CHECK_HEADERS([fcntl.h unistd.h])
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_TYPE_SIZE_T
+AC_TYPE_SSIZE_T
+
+# Checks for library functions.
+AC_CHECK_FUNCS([fcntl.h unistd.h])
+
+AC_CHECK_HEADER(Poco/Logger.h,,
+       AC_MSG_ERROR([Missing Poco/Logger.h]))
+AC_CHECK_HEADER(Poco/Util/ServerApplication.h,,
+       AC_MSG_ERROR([Missing Poco/Util/ServerApplication.h]))
+AC_CHECK_HEADER(Poco/Net/WebSocket.h,,
+       AC_MSG_ERROR([Missing Poco/Net/WebSocket.h]))
+AC_CHECK_HEADER(Poco/Net/Context.h,,
+       AC_MSG_ERROR([Missing Poco/Net/Context.h]))
+AC_CHECK_LIB(PocoFoundation,main,LIBS="$LIBS -lPocoFoundation",
+       AC_MSG_ERROR([libPocoFoundation not found!]))
+AC_CHECK_LIB(PocoUtil,main,LIBS="$LIBS -lPocoUtil",
+       AC_MSG_ERROR([libPocoUtil not found!]))
+AC_CHECK_LIB(PocoNet,main,LIBS="$LIBS -lPocoNet",
+       AC_MSG_ERROR([libPocNet not found!]))
+AC_CHECK_LIB(PocoNetSSL,main,LIBS="$LIBS -lPocoNetSSL",
+       AC_MSG_ERROR([libPocNetSSL not found!]))
+
+AC_CONFIG_FILES([Makefile poco/Makefile])
+AC_OUTPUT
diff --git a/tools/usb/usbip/websocket/doc/usbws.8 
b/tools/usb/usbip/websocket/doc/usbws.8
new file mode 100644
index 0000000..cc9f8ad
--- /dev/null
+++ b/tools/usb/usbip/websocket/doc/usbws.8
@@ -0,0 +1,192 @@
+.TH USBWS "8" "March 2015" "usbws" "System Administration Utilities"
+.SH NAME
+usbws \- manage USB/IP devices via WebSocket
+.SH SYNOPSIS
+.B usbws
+<\fIcommand\fR> [\fIoptions\fR]
+
+.SH DESCRIPTION
+On a USB/IP device side computer,
+lists local devices, makes a device importable, makes not importable,
+export and unexport.
+On a USB/IP application side computer,
+lists importable devices from device side, import device and unimport device.
+Connect and attach command will not return
+and they transmit USB packets between a daemon
+until disconnect or detach command is executed respectively.
+
+.SH COMMANDS
+.HP
+\fBversion\fR
+.IP
+Show version and exit.
+.PP
+
+.HP
+\fBhelp\fR
+.IP
+Print the program help message, or help on a specific command, and
+then exit.
+.PP
+
+.HP
+\fBattach\fR \-\-url <\fIurl\fR> \-\-busid <\fIbus_id\fR> [\fIoptions\fR]
+.IP
+Attach a importable USB device from remote computer.
+.PP
+
+.HP
+\fBdetach\fR \-\-port <\fIport\fR> [\fIoptions\fR]
+.IP
+Detach an imported USB device.
+.PP
+
+.HP
+\fBbind\fR \-\-busid <\fIbusid\fR> [\fIoptions\fR]
+.IP
+Make a USB device importable from remote computer.
+.PP
+
+.HP
+\fBunbind\fR \-\-busid <\fIbusid\fR> [\fIoptions\fR]
+.IP
+Make a USB device not importable so it can be used by a local driver.
+.PP
+
+.HP
+\fBlist\fR \-\-url <\fIurl\fR> [\fIoptions\fR]
+.IP
+List importable USB devices from a remote computer.
+.PP
+
+.HP
+\fBlist\fR \-\-local [\fIoptions\fR]
+.IP
+List local USB devices.
+.PP
+
+.HP
+\fBport\fR
+.IP
+List imported USB devices.
+.PP
+
+
+.SH OPTIONS
+.HP
+\fB\-d\fR, \fB\-\-debug\fR
+.IP
+Print debugging information.
+.PP
+
+.HP
+\fB\-uURL\fR, \fB\-\-url URL\fR
+.IP
+URL served by remote usbip daemon. Scheme must be \fBws\fR or \fBwss\fR.
+.PP
+
+.HP
+\fB\-xURL\fR, \fB\-\-proxy URL\fR
+.IP
+URL of HTTP proxy server.
+.PP
+
+.HP
+\fB\-bBUS-ID\fR, \fB\-\-busid BUS-ID\fR
+.IP
+Bus ID of a USB device.
+.PP
+
+.HP
+\fB\-oCONN-TOUT\fR, \fB\-\-timeout CONN-TIMEOUT\fR
+.IP
+Connect timeout in seconds. Defult is 5.
+.PP
+
+.HP
+\fB\-iINTERVAL\fR, \fB\-\-interval INTERVAL\fR
+.IP
+Noncommunication time period to send ping-pong in seconds.
+Default is 60. 0 denotes not to use ping-pong.
+.PP
+
+.HP
+\fB\-tPORT\fR, \fB\-\-port PORT\fR
+.IP
+Port number to detach.
+.PP
+
+.HP
+\fB\-l\fR, \fB\-\-local\fR
+.IP
+List local devices.
+.PP
+
+.HP
+\fB\-P\fR, \fB\-\-parsable\fR
+.IP
+Use parsable list format.
+.PP
+
+.HP
+\fB\-cCERT-FILE\fR, \fB\-\-cert CERT-FILE\fR
+.IP
+Certificate file for SSL in PEM format. Default is ./cert/clinet.crt.
+.PP
+
+.HP
+\fB\-kKEY-FILE\fR, \fB\-\-key KEY-FILE\fR
+.IP
+Private key file for SSL in PEM format. Default is ./cert/clinet.key.
+.PP
+
+.HP
+\fB\-Vverification-mode\fR, \fB\-\-verification verification-mode\fR
+.IP
+Verification mode for SSL from 'none' or 'relaxed'. Default is 'none'.
+.PP
+
+.HP
+\fB\-rROOT-CERT-FILE\fR, \fB\-\-root ROOT-CERT-FILE\fR
+.IP
+Root CA certificate file for SSL in PEM format. Default is none.
+.PP
+
+
+.SH EXAMPLES
+
+    dev: - at device side computer.
+    app: - at application side computer.
+
+Import from application side computer.
+    dev:# usbwsd
+        - Start daemon.
+    dev:# usbws list
+        - List local USB devices.
+    dev:# usbws bind --busid 1-2
+        - Make a USB device importable from a remote computer.
+    app:# usbws list --url ws://172.1.2.3/usbip
+        - List importable USB devices from the computer.
+    app:# usbws attach --url ws://172.1.2.3/usbip --busid 1-2
+        - Import the remote USB device.
+    app:# usbws port
+        - List imported USB devices.
+    app:# usbws detach --port 0
+        - Detach a USB device.
+    dev:# usbws unbind --busid 1-2
+        - Make the USB device not importable, then release to local.
+
+Export from device side computer.
+    app:# usbwsa
+        - Start daemon.
+    dev:# usbws list
+        - List local USB devices.
+    dev:# usbws connect --url ws://172.4.5.6 --busid 1-2
+        - Export a USB device to a remote computer.
+    dev:# usbws disconnect --url ws://172.4.5.6 --busid 1-2
+        - Unxport the USB device from a remote computer.
+
+
+.SH "SEE ALSO"
+\fBusbwsd\fP\fB(8)\fB\fP
+\fBusbwsa\fP\fB(8)\fB\fP
diff --git a/tools/usb/usbip/websocket/doc/usbwsa.8 
b/tools/usb/usbip/websocket/doc/usbwsa.8
new file mode 100644
index 0000000..6084a8e
--- /dev/null
+++ b/tools/usb/usbip/websocket/doc/usbwsa.8
@@ -0,0 +1,101 @@
+.TH USBWS "8" "March 2015" "usbws" "System Administration Utilities"
+.SH NAME
+usbwsa \- USB/IP application side WebSocket daemon
+.SH SYNOPSIS
+.B usbwsa
+[\fIoptions\fR]
+
+.SH DESCRIPTION
+.B usbwsa
+runs on application side computer and services exported USB devices from
+device side computer.
+
+Devices are exported using
+.B usbws connect
+at device side computer.
+
+
+.SH OPTIONS
+.HP
+\fB\-d\fR, \fB\-\-debug\fR
+.IP
+Print debugging information.
+.PP
+
+\fB\-tPORT\fR, \fB\-\-tcp\-port PORT\fR
+.IP
+Listen on TCP/IP port PORT. Default is 443 if --ssl option is specified, 
otherwise 443.
+.PP
+
+\fB\-pPATH\fR, \fB\-\-path PATH\fR
+.IP
+Path in URL served by daemon. Default is 'usbip'.
+.PP
+
+.HP
+\fB\-iINTERVAL\fR, \fB\-\-interval INTERVAL\fR
+.IP
+Noncommunication time period to send ping-pong in seconds.
+Default is 60. 0 denotes not to use ping-pong.
+.PP
+
+\fB\-s\fR, \fB\-\-ssl\fR
+.IP
+Enable SSL.
+.PP
+
+.HP
+\fB\-cCERT-FILE\fR, \fB\-\-cert CERT-FILE\fR
+.IP
+Certificate file for SSL in PEM format. Default is ./cert/server.crt.
+.PP
+
+.HP
+\fB\-kKEY-FILE\fR, \fB\-\-key KEY-FILE\fR
+.IP
+Private key file for SSL in PEM format. Default is ./cert/server.key.
+.PP
+
+.HP
+\fB\-Vverification-mode\fR, \fB\-\-verification verification-mode\fR
+.IP
+Verification mode for SSL from 'none', 'relaxed', 'strict' or 'once'. Default 
is 'none'.
+.PP
+
+.HP
+\fB\-rROOT-CERT-FILE\fR, \fB\-\-root ROOT-CERT-FILE\fR
+.IP
+Root CA certificate file for SSL in PEM format. Default is none.
+.PP
+
+\fB\-h\fR, \fB\-\-help\fR
+.IP
+Print the program help message and exit.
+.PP
+
+.HP
+\fB\-v\fR, \fB\-\-version\fR
+.IP
+Show version.
+.PP
+
+
+.SH EXAMPLES
+
+    app: - at application side computer.
+    dev: - at device side computer.
+
+    app:# usbwsa
+        - Start daemon.
+    dev:# usbws list
+        - List local USB devices.
+    dev:# usbws connect --url ws://172.4.5.6 --busid 1-2
+        - Export a USB device to a remote computer.
+    dev:# usbws disconnect --url ws://172.4.5.6 --busid 1-2
+        - Unxport the USB device from a remote computer.
+
+
+.SH "SEE ALSO"
+\fBusbws\fP\fB(8)\fB\fP
+\fBusbwsd\fP\fB(8)\fB\fP
+
diff --git a/tools/usb/usbip/websocket/doc/usbwsd.8 
b/tools/usb/usbip/websocket/doc/usbwsd.8
new file mode 100644
index 0000000..ea745fc
--- /dev/null
+++ b/tools/usb/usbip/websocket/doc/usbwsd.8
@@ -0,0 +1,109 @@
+.TH USBWS "8" "March 2015" "usbws" "System Administration Utilities"
+.SH NAME
+usbwsd \- USB/IP device side WebSocket daemon
+.SH SYNOPSIS
+.B usbwsd
+[\fIoptions\fR]
+
+.SH DESCRIPTION
+.B usbwsd
+runs on divice side computer and provides USB/IP application side computer
+to import USB devices.
+
+Devices have to explicitly be importable from remote computer using
+.B usbip bind
+before usbipd makes them available.
+
+
+.SH OPTIONS
+.HP
+\fB\-d\fR, \fB\-\-debug\fR
+.IP
+Print debugging information.
+.PP
+
+\fB\-tPORT\fR, \fB\-\-tcp\-port PORT\fR
+.IP
+Listen on TCP/IP port PORT. Default is 443 if --ssl option is specified, 
otherwise 443.
+.PP
+
+\fB\-pPATH\fR, \fB\-\-path PATH\fR
+.IP
+Path in URL served by daemon. Default is 'usbip'.
+.PP
+
+.HP
+\fB\-iINTERVAL\fR, \fB\-\-interval INTERVAL\fR
+.IP
+Noncommunication time period to send ping-pong in seconds.
+Default is 60. 0 denotes not to use ping-pong.
+.PP
+
+\fB\-s\fR, \fB\-\-ssl\fR
+.IP
+Enable SSL.
+.PP
+
+.HP
+\fB\-cCERT-FILE\fR, \fB\-\-cert CERT-FILE\fR
+.IP
+Certificate file for SSL in PEM format. Default is ./cert/server.crt.
+.PP
+
+.HP
+\fB\-kKEY-FILE\fR, \fB\-\-key KEY-FILE\fR
+.IP
+Private key file for SSL in PEM format. Default is ./cert/server.key.
+.PP
+
+.HP
+\fB\-Vverification-mode\fR, \fB\-\-verification verification-mode\fR
+.IP
+Verification mode for SSL from 'none', 'relaxed', 'strict' or 'once'. Default 
is 'none'.
+.PP
+
+.HP
+\fB\-rROOT-CERT-FILE\fR, \fB\-\-root ROOT-CERT-FILE\fR
+.IP
+Root CA certificate file for SSL in PEM format. Default is none.
+.PP
+
+\fB\-h\fR, \fB\-\-help\fR
+.IP
+Print the program help message and exit.
+.PP
+
+.HP
+\fB\-v\fR, \fB\-\-version\fR
+.IP
+Show version.
+.PP
+
+
+.SH EXAMPLES
+
+    dev: - at device side computer.
+    app: - at application side computer.
+
+    dev:# usbwsd
+        - Start daemon.
+    dev:# usbws list
+        - List local USB devices.
+    dev:# usbws bind --busid 1-2
+        - Make a USB device importable from a remote computer.
+    app:# usbws list --url ws://172.1.2.3/usbip
+        - List importable USB devices from the computer.
+    app:# usbws attach --url ws://172.1.2.3/usbip --busid 1-2
+        - Import the remote USB device.
+    app:# usbws port
+        - List imported USB devices.
+    app:# usbws detach --port 0
+        - Detach a USB device.
+    dev:# usbws unbind --busid 1-2
+        - Make the USB device not importable, then release to local.
+
+
+.SH "SEE ALSO"
+\fBusbws\fP\fB(8)\fB\fP
+\fBusbwsa\fP\fB(8)\fB\fP
+
diff --git a/tools/usb/usbip/websocket/poco/Makefile.am 
b/tools/usb/usbip/websocket/poco/Makefile.am
new file mode 100644
index 0000000..5ecf53e
--- /dev/null
+++ b/tools/usb/usbip/websocket/poco/Makefile.am
@@ -0,0 +1,18 @@
+AM_CPPFLAGS = -I$(top_srcdir)/../libsrc -I$(top_srcdir)/../src
+
+bin_PROGRAMS = usbws usbwsa usbwsd
+
+usbws_LDFLAGS = -lPocoFoundation -lPocoUtil -lPocoNet -lPocoNetSSL -lstdc++
+usbws_LDADD = $(top_builddir)/../libsrc/libusbiplib.la 
$(top_builddir)/../src/libusbip.la
+usbws_SOURCES = USBWSCommand.cpp USBWSWebSocket.cpp
+
+usbwsa_LDFLAGS = -lPocoFoundation -lPocoUtil -lPocoNet -lPocoNetSSL -lstdc++
+usbwsa_LDADD = $(top_builddir)/../libsrc/libusbiplib.la 
$(top_builddir)/../src/libusbipa.la
+usbwsa_SOURCES = USBWSDaemon.cpp USBWSWebSocket.cpp \
+               USBWSRequestHandlerFactory.cpp USBWSRequestHandler.cpp
+
+usbwsd_LDFLAGS = -lPocoFoundation -lPocoUtil -lPocoNet -lPocoNetSSL -lstdc++
+usbwsd_LDADD = $(top_builddir)/../libsrc/libusbiplib.la 
$(top_builddir)/../src/libusbipd.la
+usbwsd_SOURCES = USBWSDaemon.cpp USBWSWebSocket.cpp \
+               USBWSRequestHandlerFactory.cpp USBWSRequestHandler.cpp
+
diff --git a/tools/usb/usbip/websocket/poco/USBWSCommand.cpp 
b/tools/usb/usbip/websocket/poco/USBWSCommand.cpp
new file mode 100644
index 0000000..9f8cb9f
--- /dev/null
+++ b/tools/usb/usbip/websocket/poco/USBWSCommand.cpp
@@ -0,0 +1,410 @@
+/*
+ * Copyright (C) 2015 Nobuo IWata
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include "USBWSCommand.h"
+#include "USBWSWebSocket.h"
+#include "USBWSUtil.h"
+#include "Poco/Net/HTTPClientSession.h"
+#include "Poco/Net/HTTPSClientSession.h"
+#include "Poco/Net/HTTPRequest.h"
+#include "Poco/Net/HTTPResponse.h"
+#include "Poco/Net/NetException.h"
+#include "Poco/Util/HelpFormatter.h"
+#include "Poco/StringTokenizer.h"
+#include "Poco/Exception.h"
+#include <iostream>
+
+extern "C" {
+#include "usbip_common.h"
+#include "usbip_host_driver.h"
+#include "usbip.h"
+}
+
+using namespace ::Poco;
+using namespace ::Poco::Net;
+using namespace ::Poco::Util;
+using namespace ::Usbip::WebSock::Poco;
+
+const std::string USBWSCommand::kDefaultKey("cert/client.key");
+const std::string USBWSCommand::kDefaultCert("cert/client.crt");
+const int USBWSCommand::kMajorVersion(0);
+const int USBWSCommand::kMinorVersion(0);
+const int USBWSCommand::kRevision(1);
+
+USBWSCommand::USBWSCommand() :
+       fDebug(false),
+       fURL(),
+       fProxy(),
+       fBusID(),
+       fConnTimeout(5),
+       fPingPong(60),
+       fPort(),
+       fLocal(false),
+       fParsable(false),
+       fKey(kDefaultKey),
+       fCert(kDefaultCert),
+       fRootCert(),
+       fVerificationStr(),
+       fVerification(Context::VERIFY_NONE),
+       fSSL(false),
+       fHost(),
+       fTcpPort(0),
+       fPath(),
+       fProxyHost(),
+       fProxyPort(),
+       fProxyUser(),
+       fProxyPwd(),
+       fHelp(false),
+       fVersion(false),
+       fClientSession(0)
+{
+}
+
+USBWSCommand::~USBWSCommand()
+{
+}
+
+void USBWSCommand::initialize(Application& self)
+{
+       Application::initialize(self);
+}
+
+void USBWSCommand::uninitialize(void)
+{
+       Application::uninitialize();
+}
+
+void USBWSCommand::defineOptions(OptionSet& options)
+{
+       Application::defineOptions(options);
+       options.addOption(Option("debug", "d", "Print debug information."));
+       options.addOption(Option("url", "u", "WebSocket URL for USB/IP."
+               ).argument("url"));
+       options.addOption(Option("proxy", "x", "Proxy URL if used."
+               ).argument("proxy"));
+       options.addOption(Option("busid", "b", "Bus ID of a device to export."
+               ).argument("busid"));
+       options.addOption(Option("timeout", "o",
+               "Connect timeout in seconds. Default is 5."
+               ).argument("timeout-sec"));
+       options.addOption(Option("interval", "i",
+               "Noncommunication time period to send ping-pong in seconds."
+               " Default is 60. 0 denotes not to use ping-pong."
+               ).argument("interval-sec"));
+       options.addOption(Option("port", "p", "Attached port to detach."
+               ).argument("port"));
+       options.addOption(Option("local", "l", "List local devices."));
+       options.addOption(Option("parsable", "P", "Parsable list output."));
+       options.addOption(Option("key", "k",
+               "Private key file. Default is " + kDefaultKey + "."
+               ).argument("key-file"));
+       options.addOption(Option("cert", "c",
+               "Certificate file. Default is " + kDefaultCert + "."
+               ).argument("cert-file"));
+       options.addOption(Option("root-cert", "r",
+               "Certificate file of root CA."
+               ).argument("root-cert-file"));
+       options.addOption(Option("verification", "V",
+               "Certificate verification mode - none(default) or relaxed."
+               ).argument("verification-mode"));
+       options.addOption(Option("help", "h", "Print this help."));
+       options.addOption(Option("version", "v", "Show version."));
+}
+
+void USBWSCommand::handleOption(const std::string& name, const std::string & 
value)
+{
+       Application::handleOption(name, value);
+
+       if (name == "debug") {
+               fDebug = true;
+               usbip_use_debug = 1;
+       } else if (name == "url") {
+               fURL = value;
+       } else if (name == "proxy") {
+               fProxy = value;
+       } else if (name == "busid") {
+               fBusID = value;
+       } else if (name == "timeout") {
+               fConnTimeout = USBWSUtil::s2i(value);
+       } else if (name == "interval") {
+               fPingPong = USBWSUtil::s2i(value);
+       } else if (name == "port") {
+               fPort = value;
+       } else if (name == "local") {
+               fLocal = true;
+       } else if (name == "parsable") {
+               fParsable = true;
+       } else if (name == "key") {
+               fKey = value;
+       } else if (name == "cert") {
+               fCert = value;
+       } else if (name == "root-cert") {
+               fRootCert = value;
+       } else if (name == "verification") {
+               fVerificationStr = value;
+       } else if (name == "help") {
+               fHelp = true;
+       } else if (name == "version") {
+               fVersion = true;
+       }
+}
+
+void USBWSCommand::help()
+{
+       HelpFormatter helpFormatter(options());
+       helpFormatter.setCommand(commandName() +
+               " <connect | disconnect | list | port | bind |"
+               " attach | detach | unbind> [options]");
+       helpFormatter.format(std::cout);
+}
+
+void USBWSCommand::version()
+{
+       std::cout << kMajorVersion << "." << kMinorVersion << "." << kRevision 
<< std::endl;
+}
+
+void USBWSCommand::getProxyCredentials(const URI &url)
+{
+       std::string info = url.getUserInfo();
+       if (info.size() > 0) {
+               StringTokenizer t(info, ":");
+               try {
+                       fProxyUser = t[0];
+                       fProxyPwd = t[1];
+               } catch (RangeException& e) {
+               }
+       }
+}
+
+int USBWSCommand::main(const std::vector<std::string>& args)
+{
+       usbip_use_stderr = 1;
+       std::string cmd(args[0]);
+       if (fHelp || cmd == "help") {
+               help();
+               return Application::EXIT_OK;
+       } else if (fVersion || cmd == "version") {
+               version();
+               return Application::EXIT_OK;
+       }
+       if (fURL.size() > 0) {
+               try {
+                       URI url(fURL);
+                       std::string scheme = url.getScheme();
+                       if (scheme == "wss") {
+                               fSSL = true;
+                       } else if (scheme != "ws") {
+                               std::cerr << "Unsupported scheme in URL."
+                                       << std::endl;
+                               return Application::EXIT_USAGE;
+                       }
+                       fHost = url.getHost();
+                       fTcpPort = url.getPort();
+                       fPath = url.getPath();
+               } catch (SyntaxException& e) {
+                       std::cerr << "URL syntax error." << std::endl;
+                       return Application::EXIT_USAGE;
+               }
+       }
+       if (fTcpPort == 0) {
+               if (fSSL) {
+                       fTcpPort = 443;
+               } else {
+                       fTcpPort = 80;
+               }
+               dbg("TCP port has been set to %d", fTcpPort);
+       }
+       if ((cmd == "connect" || cmd == "disconnect" || cmd == "attach" ||
+               (cmd == "list" && fURL.size() > 0)) &&
+               fHost.size() <= 0) {
+               std::cerr << "Missing host." << std::endl;
+               return Application::EXIT_USAGE;
+       }
+       if ((cmd == "connect" || cmd == "disconnect" || cmd == "attach" ||
+               cmd == "bind" || cmd == "unbind") &&
+               fBusID.size() <= 0) {
+               std::cerr << "Missing bus ID." << std::endl;
+               return Application::EXIT_USAGE;
+       }
+       if (cmd == "detach" && fPort.size() <= 0) {
+               std::cerr << "Missing port." << std::endl;
+               return Application::EXIT_USAGE;
+       }
+       if (fVerificationStr.size() > 0) {
+               if (fVerificationStr == "none") {
+                       fVerification = Context::VERIFY_NONE;
+               } else if (fVerificationStr == "relaxed") {
+                       fVerification = Context::VERIFY_RELAXED;
+               } else {
+                       std::cerr << "Unsupported verification mode." << 
std::endl;
+                       return Application::EXIT_USAGE;
+               }
+       }
+       if (fProxy.size() > 0) {
+               try {
+                       URI url(fProxy);
+                       fProxyHost = url.getHost();
+                       fProxyPort = url.getPort();
+                       getProxyCredentials(url);
+                       dbg("Using proxy host:%s port:%d user:%s pwd:%s",
+                               fProxyHost.c_str(), fProxyPort,
+                               fProxyUser.c_str(), fProxyPwd.c_str());
+               } catch (SyntaxException& e) {
+                       std::cerr << "Proxy syntax error." << std::endl;
+                       return Application::EXIT_USAGE;
+               }
+       }
+
+       std::string tcpPortStr = USBWSUtil::i2s(fTcpPort);
+
+       usbip_conn_init(USBWSCommand::connect, USBWSCommand::close);
+
+       if (cmd == "connect") {
+               if (usbip_connect_device(
+                       fHost.c_str(), tcpPortStr.c_str(), fBusID.c_str())) {
+                       return Application::EXIT_SOFTWARE;
+               }
+       } else if (cmd == "disconnect") {
+               if (usbip_disconnect_device(
+                       fHost.c_str(), tcpPortStr.c_str(), fBusID.c_str())) {
+                       return Application::EXIT_SOFTWARE;
+               }
+       } else if (cmd == "attach") {
+               if (usbip_attach_device(
+                       fHost.c_str(), tcpPortStr.c_str(), fBusID.c_str())) {
+                       return Application::EXIT_SOFTWARE;
+               }
+       } else if (cmd == "detach") {
+               if (usbip_detach_port(fPort.c_str())) {
+                       return Application::EXIT_SOFTWARE;
+               }
+       } else if (cmd == "port") {
+               if (usbip_list_imported_devices()) {
+                       return Application::EXIT_SOFTWARE;
+               }
+       } else if (cmd == "list" && fURL.size() > 0) {
+               if (usbip_list_importable_devices(
+                       fHost.c_str(), tcpPortStr.c_str())) {
+                       return Application::EXIT_SOFTWARE;
+               }
+       } else if (cmd == "list") {
+               if (usbip_list_devices(fParsable)) {
+                       return Application::EXIT_SOFTWARE;
+               }
+       } else if (cmd == "bind") {
+               if (usbip_bind_device(fBusID.c_str())) {
+                       return Application::EXIT_SOFTWARE;
+               }
+       } else if (cmd == "unbind") {
+               if (usbip_unbind_device(fBusID.c_str())) {
+                       return Application::EXIT_SOFTWARE;
+               }
+       } else {
+               help();
+               return Application::EXIT_USAGE;
+       }
+       return Application::EXIT_OK;
+}
+
+POCO_APP_MAIN(USBWSCommand)
+
+int USBWSCommand::openSession()
+{
+       if (fSSL) {
+               Context* ctx = new Context(Context::CLIENT_USE, fKey, fCert, 
fRootCert, fVerification);
+               // TODO: manipulate other params.
+               fClientSession = new HTTPSClientSession(fHost, fTcpPort, ctx);
+       } else {
+               fClientSession = new HTTPClientSession(fHost, fTcpPort);
+       }
+       if (fClientSession == NULL) {
+               return -1;
+       }
+       if (fProxy.size() > 0) {
+               fClientSession->setProxy(fProxyHost, fProxyPort);
+               if (fProxyUser.size() > 0) {
+                       fClientSession->setProxyCredentials(fProxyUser, 
fProxyPwd);
+               }
+       }
+       fClientSession->setKeepAlive(true);
+       fClientSession->setTimeout(Timespan(fConnTimeout, 0));
+       return 0;
+}
+
+void USBWSCommand::closeSession()
+{
+       if (fClientSession) {
+               delete fClientSession;
+               fClientSession = 0;
+       }
+}
+
+usbip_sock_t *USBWSCommand::connect(const char *host, const char *port)
+{
+       USBWSCommand& app = (USBWSCommand&)instance();
+
+       usbip_sock_t* sock = (usbip_sock_t*)malloc(sizeof(usbip_sock_t));
+       if (sock == NULL) {
+               app.logger().error("Fail to alloc sock.");
+               return NULL;
+       }
+
+       try {
+               if (app.openSession()) {
+                       app.logger().error("Fail to open session.");
+                       free(sock);
+                       return NULL;
+               }
+
+               USBWSWebSocket* ws;
+               HTTPRequest req(HTTPRequest::HTTP_GET, app.fPath);
+               HTTPResponse rsp;
+               ws = new USBWSWebSocket(*app.fClientSession, req, rsp,
+                                       app.fPingPong);
+               ws->setApp(&app);
+               usbip_sock_init(sock, ws->getSockfd(), ws,
+                       USBWSWebSocket::send, USBWSWebSocket::recv,
+                       USBWSWebSocket::shutdown);
+               return sock;
+       } catch (WebSocketException& e) {
+               app.logger().log(e);
+       } catch (::Poco::IOException& e) {
+               app.logger().log(e);
+       }
+       free(sock);
+       return NULL;
+}
+
+void USBWSCommand::close(usbip_sock_t *sock)
+{
+       if (sock) {
+               USBWSWebSocket* ws = (USBWSWebSocket*)sock->arg;
+               if (ws) {
+                       USBWSCommand* app = (USBWSCommand*)ws->getApp();
+                       try {
+                               app->closeSession();
+                       } catch (::Poco::IOException& e) {
+                               app->logger().log(e);
+                       } 
+                       delete ws;
+               }
+               free(sock);
+       }
+}
+
diff --git a/tools/usb/usbip/websocket/poco/USBWSCommand.h 
b/tools/usb/usbip/websocket/poco/USBWSCommand.h
new file mode 100644
index 0000000..edf7c2f
--- /dev/null
+++ b/tools/usb/usbip/websocket/poco/USBWSCommand.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2015 Nobuo Iwata
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#ifndef _USBIP_WEBSOCK_POCO_USBWS_COMMAND_H
+#define _USBIP_WEBSOCK_POCO_USBWS_COMMAND_H
+
+#include "Poco/Net/HTTPClientSession.h"
+#include "Poco/Net/Context.h"
+#include "Poco/Util/Application.h"
+#include "Poco/Util/Option.h"
+#include "Poco/Util/OptionSet.h"
+#include "Poco/URI.h"
+
+extern "C" {
+#include "usbip_common.h"
+}
+
+namespace Usbip { namespace WebSock { namespace Poco {
+
+using namespace ::Poco;
+using namespace ::Poco::Net;
+using namespace ::Poco::Util;
+
+class USBWSCommand :
+       public ::Poco::Util::Application
+{
+public:
+       USBWSCommand();
+       ~USBWSCommand();
+protected:
+       // For Application
+       void initialize(Application& self);
+       void uninitialize(void);
+       void defineOptions(OptionSet& options);
+       void handleOption(const std::string& name, const std::string & value);
+       int main(const std::vector<std::string>& args);
+public:
+       static usbip_sock_t *connect(const char *host, const char *port);
+       static void close(usbip_sock_t *sock);
+private:
+       void help();
+       void version();
+       void getProxyCredentials(const URI &url);
+       int openSession();
+       void closeSession();
+
+       bool fDebug;
+       std::string fURL;
+       std::string fProxy;
+       std::string fBusID;
+       std::string fPort;
+       int fConnTimeout;
+       int fPingPong;
+       bool fLocal;
+       bool fParsable;
+       std::string fKey;
+       std::string fCert;
+       std::string fRootCert;
+       std::string fVerificationStr;
+       Context::VerificationMode fVerification;
+       bool fSSL;
+       std::string fHost;
+       int fTcpPort;
+       std::string fPath;
+       std::string fProxyHost;
+       int fProxyPort;
+       std::string fProxyUser;
+       std::string fProxyPwd;
+       bool fHelp;
+       bool fVersion;
+       HTTPClientSession* fClientSession;
+
+       static const std::string kDefaultKey;
+       static const std::string kDefaultCert;
+       static const int kMajorVersion;
+       static const int kMinorVersion;
+       static const int kRevision;
+};
+
+}}}
+
+#endif /* !_USBIP_WEBSOCK_POCO_USBWS_COMMAND_H */
+
diff --git a/tools/usb/usbip/websocket/poco/USBWSDaemon.cpp 
b/tools/usb/usbip/websocket/poco/USBWSDaemon.cpp
new file mode 100644
index 0000000..bf46fb0
--- /dev/null
+++ b/tools/usb/usbip/websocket/poco/USBWSDaemon.cpp
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2015 Nobuo Iwata
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include "USBWSDaemon.h"
+#include "USBWSRequestHandlerFactory.h"
+#include "USBWSUtil.h"
+#include "Poco/Net/HTTPServer.h"
+#include "Poco/Net/HTTPServerParams.h"
+#include "Poco/Net/ServerSocket.h"
+#include "Poco/Net/SecureServerSocket.h"
+#include "Poco/Util/HelpFormatter.h"
+#include <iostream>
+
+extern "C" {
+#include "usbip_common.h"
+#include "usbipd.h"
+}
+
+using namespace ::Poco;
+using namespace ::Poco::Net;
+using namespace ::Poco::Util;
+using namespace ::Usbip::WebSock::Poco;
+
+const std::string USBWSDaemon::kDefaultPath("/usbip");
+const std::string USBWSDaemon::kDefaultKey("cert/server.key");
+const std::string USBWSDaemon::kDefaultCert("cert/server.crt");
+const int USBWSDaemon::kMajorVersion(0);
+const int USBWSDaemon::kMinorVersion(0);
+const int USBWSDaemon::kRevision(1);
+
+USBWSDaemon::USBWSDaemon() :
+       fDebug(false),
+       fTcpPort(0),
+       fPath(kDefaultPath),
+       fPingPong(60),
+       fSSL(false),
+       fKey(kDefaultKey),
+       fCert(kDefaultCert),
+       fRootCert(),
+       fVerificationStr(),
+       fVerification(Context::VERIFY_NONE),
+       fHelp(false),
+       fVersion(false),
+       fSocket(0)
+{
+}
+
+USBWSDaemon::~USBWSDaemon()
+{
+}
+
+void USBWSDaemon::initialize(Application& self)
+{
+       ServerApplication::initialize(self);
+}
+
+void USBWSDaemon::uninitialize(void)
+{
+       ServerApplication::uninitialize();
+}
+
+void USBWSDaemon::defineOptions(OptionSet& options)
+{
+       ServerApplication::defineOptions(options);
+       options.addOption(Option("debug", "d", "Print debug information."));
+       options.addOption(Option("tcp-port", "t", "Port number to listen."
+               ).argument("port-number"));
+       options.addOption(Option("path", "p",
+               "WebSocket path to serve USBIP/IP. Default is "
+               + kDefaultPath + "."
+               ).argument("path"));
+       options.addOption(Option("interval", "i",
+               "Noncommunication time period to send ping-pong in seconds."
+               " Default is 60. 0 denotes not to use ping-pong."
+               ).argument("interval-sec"));
+       options.addOption(Option("ssl", "s", "Enable SSL."));
+       options.addOption(Option("key", "k",
+               "Private key file. Default is " + kDefaultKey + "."
+               ).argument("cert-file"));
+       options.addOption(Option("cert", "c",
+               "Certificate file. Default is " + kDefaultCert + "."
+               ).argument("key-file"));
+       options.addOption(Option("root-cert", "r",
+               "Certificate file of root CA."
+               ).argument("root-cert-file"));
+       options.addOption(Option("verification", "V",
+               "Certificate verification mode -"
+               " none(default), relaxed, strict or once."
+               ).argument("verification-mode"));
+       options.addOption(Option("help", "h", "Print this help."));
+       options.addOption(Option("version", "v", "Show version."));
+}
+
+void USBWSDaemon::handleOption(const std::string& name, const std::string & 
value)
+{
+       ServerApplication::handleOption(name, value);
+
+       if (name == "debug") {
+               fDebug = true;
+               usbip_use_debug = 1;
+       } else if (name == "tcp-port") {
+               fTcpPort = USBWSUtil::s2i(value);
+       } else if (name == "path") {
+               fPath = value;
+       } else if (name == "interval") {
+               fPingPong = USBWSUtil::s2i(value);
+       } else if (name == "ssl") {
+               fSSL = true;
+       } else if (name == "key") {
+               fKey = value;
+       } else if (name == "cert") {
+               fCert = value;
+       } else if (name == "root-cert") {
+               fRootCert = value;
+       } else if (name == "verification") {
+               fVerificationStr = value;
+       } else if (name == "help") {
+               fHelp = true;
+       } else if (name == "version") {
+               fVersion = true;
+       }
+}
+
+void USBWSDaemon::help()
+{
+       HelpFormatter helpFormatter(options());
+       helpFormatter.setCommand(commandName());
+       helpFormatter.format(std::cout);
+}
+
+void USBWSDaemon::version()
+{
+       std::cout << kMajorVersion << "." << kMinorVersion << "." << kRevision 
<< std::endl;
+}
+
+int USBWSDaemon::main(const std::vector<std::string>& args)
+{
+       usbip_use_stderr = 1;
+       if (fHelp) {
+               help();
+               return Application::EXIT_OK;
+       }
+       if (fVersion) {
+               version();
+               return Application::EXIT_OK;
+       }
+       if (fTcpPort == 0) {
+               if (fSSL) {
+                       fTcpPort = 443;
+               } else {
+                       fTcpPort = 80;
+               }
+       }
+       if (fVerificationStr.size() > 0) {
+               if (fVerificationStr == "none") {
+                       fVerification = Context::VERIFY_NONE;
+               } else if (fVerificationStr == "relaxed") {
+                       fVerification = Context::VERIFY_RELAXED;
+               } else if (fVerificationStr == "strict") {
+                       fVerification = Context::VERIFY_STRICT;
+               } else if (fVerificationStr == "once") {
+                       fVerification = Context::VERIFY_ONCE;
+               } else {
+                       std::cerr << "Unsupported verification mode." << 
std::endl;
+                       return Application::EXIT_USAGE;
+               }
+       }
+       if (usbip_driver_open()) {
+               logger().error("Fail to open vhci driver.");
+               return Application::EXIT_IOERR;
+       }
+       if (openSocket()) {
+               logger().error("Fail to open socket.");
+               return Application::EXIT_IOERR;
+       }
+       HTTPServer svr(
+               new USBWSRequestHandlerFactory(fPath, fPingPong, logger()),
+               *fSocket, new HTTPServerParams());
+       svr.start();
+       dbg("Waiting at %d:%s %s",
+               fTcpPort, fPath.c_str(), fSSL? "with SSL" : "");
+       waitForTerminationRequest();
+       logger().information("Stopping server.");
+       usbip_break_connections();
+       svr.stop();
+       closeSocket();
+       usbip_driver_close();
+       return Application::EXIT_OK;
+}
+
+POCO_SERVER_MAIN(USBWSDaemon)
+
+int USBWSDaemon::openSocket()
+{
+       if (fSSL) {
+               Context *ctx = new Context(Context::SERVER_USE, fKey, fCert, 
fRootCert, fVerification);
+               // TODO: manipulate other params.
+               fSocket = new SecureServerSocket(fTcpPort, 64, ctx);
+       } else {
+               fSocket = new ServerSocket(fTcpPort, 64);
+       }
+       return 0;
+}
+
+void USBWSDaemon::closeSocket()
+{
+       if (fSocket) {
+               delete fSocket;
+       }
+       fSocket = 0;
+}
+
diff --git a/tools/usb/usbip/websocket/poco/USBWSDaemon.h 
b/tools/usb/usbip/websocket/poco/USBWSDaemon.h
new file mode 100644
index 0000000..84a5a85
--- /dev/null
+++ b/tools/usb/usbip/websocket/poco/USBWSDaemon.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2015 Nobuo Iwata
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#ifndef _USBIP_WEBSOCK_POCO_USBWS_DAEMON_H
+#define _USBIP_WEBSOCK_POCO_USBWS_DAEMON_H
+
+#include "Poco/Net/ServerSocket.h"
+#include "Poco/Net/Context.h"
+#include "Poco/Util/ServerApplication.h"
+#include "Poco/Util/Option.h"
+#include "Poco/Util/OptionSet.h"
+
+namespace Usbip { namespace WebSock { namespace Poco {
+
+using namespace ::Poco;
+using namespace ::Poco::Net;
+using namespace ::Poco::Util;
+
+class USBWSDaemon:
+       public ::Poco::Util::ServerApplication
+{
+public:
+       USBWSDaemon();
+       ~USBWSDaemon();
+protected:
+       // For ServerApplication
+       void initialize(Application& self);
+       void uninitialize(void);
+       void defineOptions(OptionSet& options);
+       void handleOption(const std::string& name, const std::string & value); 
+       int main(const std::vector<std::string>& args);
+private:
+       void help(void);
+       void version(void);
+       int openSocket(void);
+       void closeSocket(void);
+
+       bool fDebug;
+       int fTcpPort;
+       std::string fPath;
+       int fPingPong;
+       bool fSSL;
+       std::string fKey;
+       std::string fCert;
+       std::string fRootCert;
+       std::string fVerificationStr;
+       Context::VerificationMode fVerification;
+       bool fHelp;
+       bool fVersion;
+       ServerSocket* fSocket;
+
+       static const int kDefaultTcpPort;
+       static const std::string kDefaultPath;
+       static const std::string kDefaultKey;
+       static const std::string kDefaultCert;
+       static const int kMajorVersion;
+       static const int kMinorVersion;
+       static const int kRevision;
+};
+
+}}}
+
+#endif /* !_USBIP_WEBSOCK_POCO_USBWS_DAEMON_H */
+
diff --git a/tools/usb/usbip/websocket/poco/USBWSRequestHandler.cpp 
b/tools/usb/usbip/websocket/poco/USBWSRequestHandler.cpp
new file mode 100644
index 0000000..e0e3023
--- /dev/null
+++ b/tools/usb/usbip/websocket/poco/USBWSRequestHandler.cpp
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2015 Nobuo Iwata
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include "USBWSRequestHandler.h"
+#include "USBWSWebSocket.h"
+#include "USBWSUtil.h"
+#include "Poco/Net/Socket.h"
+#include "Poco/Net/NetException.h"
+extern "C" {
+#include "usbip_common.h"
+#include "usbipd.h"
+}
+
+using namespace ::Poco;
+using namespace ::Poco::Net;
+using namespace ::Usbip::WebSock::Poco;
+
+USBWSRequestHandler::USBWSRequestHandler(int pingPong, Logger& logger) :
+       HTTPRequestHandler(),
+       fPingPong(pingPong),
+       fLogger(logger)
+{
+}
+
+USBWSRequestHandler::~USBWSRequestHandler()
+{
+}
+
+void USBWSRequestHandler::handleRequest(
+       HTTPServerRequest& req,
+       HTTPServerResponse& rsp)
+{
+       int interrupted = 0;
+       fLogger.information("WebSocket connection established.");
+       try {
+               USBWSWebSocket ws(req, rsp, fPingPong);
+
+               usbip_sock_t sock;
+               usbip_sock_init(&sock, ws.getSockfd(), &ws,
+                       USBWSWebSocket::send, USBWSWebSocket::recv,
+                       USBWSWebSocket::shutdown);
+
+               SocketAddress addr = ws.address();
+               std::string port = USBWSUtil::i2s(addr.port());
+
+               fLogger.information("Entering to usbip_recv_pdu().");
+               usbip_recv_pdu(&sock,
+                       addr.host().toString().c_str(),
+                       port.c_str());
+               fLogger.information("Exited from usbip_recv_pdu().");
+       } catch (WebSocketException& e) {
+               fLogger.information("WebSocketexception.");
+               fLogger.log(e);
+               switch(e.code()) {
+               case WebSocket::WS_ERR_HANDSHAKE_UNSUPPORTED_VERSION:
+                       rsp.set("Sec-WebSocket-Version", 
WebSocket::WEBSOCKET_VERSION);
+                       // fallthrough
+               case WebSocket::WS_ERR_NO_HANDSHAKE:
+               case WebSocket::WS_ERR_HANDSHAKE_NO_VERSION:
+               case WebSocket::WS_ERR_HANDSHAKE_NO_KEY:
+                       rsp.setContentLength(0);
+                       rsp.send();
+                       break;
+               case WebSocket::WS_ERR_HANDSHAKE_ACCEPT:
+               case WebSocket::WS_ERR_UNAUTHORIZED:
+               case WebSocket::WS_ERR_PAYLOAD_TOO_BIG:
+               case WebSocket::WS_ERR_INCOMPLETE_FRAME:
+               default:
+                       break;
+               }
+       }
+       fLogger.information("WebSocket connection terminated.");
+}
+
diff --git a/tools/usb/usbip/websocket/poco/USBWSRequestHandler.h 
b/tools/usb/usbip/websocket/poco/USBWSRequestHandler.h
new file mode 100644
index 0000000..fa8f8ba
--- /dev/null
+++ b/tools/usb/usbip/websocket/poco/USBWSRequestHandler.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2015 Nobuo Iwata
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#ifndef _USBIP_WEBSOCK_POCO_USBWS_REQUEST_HANDLER_H
+#define _USBIP_WEBSOCK_POCO_USBWS_REQUEST_HANDLER_H
+
+#include "Poco/Net/HTTPRequestHandler.h"
+#include "Poco/Net/HTTPServerRequest.h"
+#include "Poco/Net/HTTPServerResponse.h"
+#include "Poco/Logger.h"
+
+namespace Usbip { namespace WebSock { namespace Poco {
+
+using namespace ::Poco;
+using namespace ::Poco::Net;
+
+class USBWSRequestHandler:
+       public ::Poco::Net::HTTPRequestHandler
+{
+public:
+       USBWSRequestHandler(int pingPong, Logger& logger);
+       ~USBWSRequestHandler();
+       bool hasError();
+       void handleRequest(HTTPServerRequest& req, HTTPServerResponse& rsp);
+private:
+       int fPingPong;
+       Logger &fLogger;
+};
+
+}}}
+
+#endif /* !_USBIP_WS_POCO_USBWS_REQUEST_HANDLER_H */
+
diff --git a/tools/usb/usbip/websocket/poco/USBWSRequestHandlerFactory.cpp 
b/tools/usb/usbip/websocket/poco/USBWSRequestHandlerFactory.cpp
new file mode 100644
index 0000000..19bed7a
--- /dev/null
+++ b/tools/usb/usbip/websocket/poco/USBWSRequestHandlerFactory.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2015 Nobuo Iwata
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include "USBWSRequestHandlerFactory.h"
+#include "USBWSRequestHandler.h"
+
+using namespace ::Poco::Net;
+using namespace ::Usbip::WebSock::Poco;
+
+USBWSRequestHandlerFactory::USBWSRequestHandlerFactory(
+       std::string& path, int pingPong, Logger& logger) :
+               fPath(path),
+               fPingPong(pingPong),
+               fLogger(logger)
+{
+}
+
+USBWSRequestHandlerFactory::~USBWSRequestHandlerFactory()
+{
+}
+
+HTTPRequestHandler* USBWSRequestHandlerFactory::createRequestHandler(const 
HTTPServerRequest& req)
+{
+       const std::string& path = req.getURI(); 
+       fLogger.information("Handling path:" + path);
+       if (path == fPath) {
+               return new USBWSRequestHandler(fPingPong, fLogger);
+       }
+       return 0;
+}
+
diff --git a/tools/usb/usbip/websocket/poco/USBWSRequestHandlerFactory.h 
b/tools/usb/usbip/websocket/poco/USBWSRequestHandlerFactory.h
new file mode 100644
index 0000000..ae5aacd
--- /dev/null
+++ b/tools/usb/usbip/websocket/poco/USBWSRequestHandlerFactory.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2015 Nobuo Iwata
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#ifndef _USBIP_WEBSOCK_POCO_USBWS_REQUEST_HANDLER_FACTORY_H
+#define _USBIP_WEBSOCK_POCO_USBWS_REQUEST_HANDLER_FACTORY_H
+
+#include "Poco/Net/HTTPRequestHandlerFactory.h"
+#include "Poco/Net/HTTPServerRequest.h"
+#include "Poco/Logger.h"
+
+namespace Usbip { namespace WebSock { namespace Poco {
+
+using namespace ::Poco;
+using namespace ::Poco::Net;
+
+class USBWSRequestHandlerFactory:
+       public ::Poco::Net::HTTPRequestHandlerFactory
+{
+public:
+       USBWSRequestHandlerFactory(std::string& path, int pingPong, Logger& 
logger);
+       ~USBWSRequestHandlerFactory();
+       HTTPRequestHandler* createRequestHandler(const HTTPServerRequest& req);
+private:
+       std::string& fPath;
+       int fPingPong;
+       Logger& fLogger;
+};
+
+}}}
+
+#endif /* !_USBIP_WEBSOCK_POCO_USBWS_REQUEST_HANDLER_FACTORY_H */
+
diff --git a/tools/usb/usbip/websocket/poco/USBWSUtil.h 
b/tools/usb/usbip/websocket/poco/USBWSUtil.h
new file mode 100644
index 0000000..fe95270
--- /dev/null
+++ b/tools/usb/usbip/websocket/poco/USBWSUtil.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2015 Nobuo Iwata
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#ifndef _USBIP_WEBSOCK_POCO_USBWS_UTIL_H
+#define _USBIP_WEBSOCK_POCO_USBWS_UTIL_H
+
+#include <sstream>
+
+namespace Usbip { namespace WebSock { namespace Poco {
+
+using namespace ::Poco::Net;
+
+class USBWSUtil
+{
+public:
+       static int s2i(const std::string& s) {
+               int i;
+               std::stringstream ss(s);
+                ss >> i;
+               return i;
+       };
+       static int c2i(const char* c) {
+               std::string s(c);
+               return USBWSUtil::s2i(s);
+       };
+       static std::string i2s(int i) {
+               std::stringstream ss;
+               ss << i;
+               return ss.str();
+       };
+};
+
+}}}
+
+#endif /* !_USBIP_WEBSOCK_POCO_USBWS_UTIL_H */
+
diff --git a/tools/usb/usbip/websocket/poco/USBWSWebSocket.cpp 
b/tools/usb/usbip/websocket/poco/USBWSWebSocket.cpp
new file mode 100644
index 0000000..ded6c9d
--- /dev/null
+++ b/tools/usb/usbip/websocket/poco/USBWSWebSocket.cpp
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2015 Nobuo Iwata
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include "USBWSWebSocket.h"
+#include "USBWSUtil.h"
+#include "Poco/Exception.h"
+#include "Poco/Net/NetException.h"
+
+extern "C" {
+#include "usbip_common.h"
+}
+
+using namespace ::Poco::Net;
+using namespace ::Usbip::WebSock::Poco;
+
+USBWSWebSocket::USBWSWebSocket(
+       HTTPServerRequest& req,
+       HTTPServerResponse& rsp,
+       int pingPong) :
+       WebSocket(req, rsp),
+       Timer(0, pingPong * 1000),
+       fApp(0),
+       fPingPongStarted(false),
+       fFirstTimeout(true),
+       fSendLock()
+{
+       setKeepAlive(true);
+       if (pingPong > 0) {
+               setReceiveTimeout(Timespan(pingPong + 60, 0));
+               startPingPong();
+               fPingPongStarted = true;
+       }       
+}
+
+USBWSWebSocket::USBWSWebSocket(
+       HTTPClientSession& cs,
+       HTTPRequest& req,
+       HTTPResponse& rsp,
+       int pingPong) :
+       WebSocket(cs, req, rsp),
+       Timer(0, 0),
+       fApp(0),
+       fPingPongStarted(false),
+       fFirstTimeout(true),
+       fSendLock()
+{
+       setKeepAlive(true);
+       if (pingPong > 0) {
+               setReceiveTimeout(Timespan(pingPong + 60, 0));
+       }       
+}
+
+ssize_t USBWSWebSocket::send(void *arg, void *buf, size_t len)
+{
+       ssize_t ret;
+       USBWSWebSocket *ws = (USBWSWebSocket*)arg;
+       return ws->send(buf, len);
+}
+
+ssize_t USBWSWebSocket::recv(void *arg, void *buf, size_t len, int all)
+{
+       USBWSWebSocket *ws = (USBWSWebSocket*)arg;
+       return ws->recv(buf, len, all);
+}
+
+void USBWSWebSocket::shutdown(void *arg)
+{
+       USBWSWebSocket *ws = (USBWSWebSocket*)arg;
+       ws->shutdown();
+}
+
+ssize_t USBWSWebSocket::send(void *buf, size_t len)
+{
+       ssize_t ret;
+       fSendLock.lock();
+       try {
+               ret = sendFrame(buf, len, WebSocket::FRAME_OP_BINARY);
+       } catch (::Poco::IOException& e) {
+               dbg("Send IOException %s", e.message().c_str());
+               ret = -1;
+               errno = EIO;
+       }
+       fSendLock.unlock();
+       return ret;
+}
+
+ssize_t USBWSWebSocket::recv(void *buf, size_t len, int all)
+{
+       char *p = (char*)buf;
+       try {
+               ssize_t received = 0;
+               int op, flags;
+               do {
+                       ssize_t bytes =
+                               receiveFrame(p+received, len-received, flags);
+                       op = flags & WebSocket::FRAME_OP_BITMASK;
+                       if (op == WebSocket::FRAME_OP_BINARY) {
+                               if (bytes == 0) {
+                                       return received;
+                               }
+                               received += bytes;
+                       } else if (op == WebSocket::FRAME_OP_PING) {
+                               sendPong();
+                       } else if (op == WebSocket::FRAME_OP_PONG) {
+                               restartPingPong();
+                       } else if (op == WebSocket::FRAME_OP_CLOSE) {
+                               throw ::Poco::IOException(
+                                       "Recieved close frame");
+                       } else {
+                               throw ::Poco::Net::WebSocketException(
+                                       "Unsupported op code:" +
+                                       USBWSUtil::i2s(op));
+                       }       
+               } while((all && received < len) ||
+                       op != WebSocket::FRAME_OP_BINARY);
+               restartPingPong();
+               return received;
+       } catch (::Poco::Net::WebSocketException& e) {
+               dbg("Recv WebSocketException %s", e.message().c_str());
+               errno = EINVAL;
+       } catch (::Poco::TimeoutException& e) {
+               dbg("Recv TimeoutException %s", e.message().c_str());
+               errno = ETIMEDOUT;
+       } catch (::Poco::Net::NetException& e) {
+               dbg("Recv NetException %s", e.message().c_str());
+               errno = EIO;
+       } catch (::Poco::IOException& e) {
+               dbg("Recv IOException %s", e.message().c_str());
+               errno = EIO;
+       }
+       return -1;
+}
+
+void USBWSWebSocket::shutdown(void)
+{
+       dbg("Shutting down websocket.");
+       shutdownReceive();
+}
+
+void USBWSWebSocket::startPingPong(void)
+{
+       TimerCallback<USBWSWebSocket> callback(*this, &USBWSWebSocket::onTimer);
+       start(callback);
+}
+
+void USBWSWebSocket::restartPingPong(void)
+{
+       if (fPingPongStarted) {
+               restart();
+       }
+}
+
+void USBWSWebSocket::onTimer(Timer& timer)
+{
+       USBWSWebSocket& ws = (USBWSWebSocket&)timer; 
+       if (ws.fFirstTimeout) {
+               ws.fFirstTimeout = false;
+       } else {
+               ws.sendPing();
+       }
+}
+
+void USBWSWebSocket::sendPing()
+{
+       dbg("Ping");
+       sendPingPong(WebSocket::FRAME_OP_PING);
+}
+
+void USBWSWebSocket::sendPong(void)
+{
+       dbg("Pong");
+       sendPingPong(WebSocket::FRAME_OP_PONG);
+}
+
+void USBWSWebSocket::sendPingPong(int op)
+{
+       fSendLock.lock();
+       try {
+               sendFrame(NULL, 0, op);
+       } catch (::Poco::IOException& e) {
+               dbg("Send IOException %s", e.message().c_str());
+       }
+       fSendLock.unlock();
+}
+
diff --git a/tools/usb/usbip/websocket/poco/USBWSWebSocket.h 
b/tools/usb/usbip/websocket/poco/USBWSWebSocket.h
new file mode 100644
index 0000000..d6bae0b
--- /dev/null
+++ b/tools/usb/usbip/websocket/poco/USBWSWebSocket.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2015 Nobuo Iwata
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#ifndef _USBIP_WEBSOCK_POCO_USBWS_WEBSOCKET_H
+#define _USBIP_WEBSOCK_POCO_USBWS_WEBSOCKET_H
+
+#include "Poco/Net/WebSocket.h"
+#include "Poco/Util/Application.h"
+#include "Poco/Timer.h"
+#include "Poco/Mutex.h"
+
+namespace Usbip { namespace WebSock { namespace Poco {
+
+using namespace ::Poco;
+using namespace ::Poco::Net;
+using namespace ::Poco::Util;
+
+class USBWSWebSocket :
+       public ::Poco::Net::WebSocket,
+       public ::Poco::Timer
+{
+public:
+       USBWSWebSocket(HTTPServerRequest& req, HTTPServerResponse& rsp,
+                       int pingPong);
+       USBWSWebSocket(HTTPClientSession& cs,
+                       HTTPRequest& req, HTTPResponse& rsp, int pingPong);
+       static ssize_t send(void *arg, void *buf, size_t len);
+       static ssize_t recv(void *arg, void *buf, size_t len, int wait_all);
+       static void shutdown(void *arg);
+       int getSockfd(void) { return sockfd(); };
+       void setApp(Application* app) { fApp = app; };
+       Application* getApp(void) { return fApp; };
+private:
+       Application* fApp;
+       bool fPingPongStarted;
+       bool fFirstTimeout;
+       Mutex fSendLock;
+
+       ssize_t send(void *buf, size_t len);
+       ssize_t recv(void *buf, size_t len, int wait_all);
+       void shutdown(void);
+       void startPingPong(void);
+       void restartPingPong(void);
+       void onTimer(Timer& timer);
+       void sendPing(void);
+       void sendPong(void);
+       void sendPingPong(int op);
+};
+
+}}}
+
+#endif /* !_USBIP_WEBSOCK_POCO_USBWS_WEBSOCKET_H */
+
-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to