[PATCH v6 11/11] usbip: USB over WebSocket

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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.iwata@xxxxxxxxxxxxxxx>
---
 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       |  49 +++
 .../poco/USBWSRequestHandlerFactory.h         |  48 ++
 tools/usb/usbip/websocket/poco/USBWSUtil.h    |  52 +++
 .../usbip/websocket/poco/USBWSWebSocket.cpp   | 204 +++++++++
 .../usb/usbip/websocket/poco/USBWSWebSocket.h |  69 +++
 21 files changed, 2298 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@xxxxxxxxxxxxxxx])
+
+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..3cb8783
--- /dev/null
+++ b/tools/usb/usbip/websocket/doc/usbwsa.8
@@ -0,0 +1,101 @@
+.TH USBWS "8" "March 2015" "usbwsa" "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..b5c1ae1
--- /dev/null
+++ b/tools/usb/usbip/websocket/doc/usbwsd.8
@@ -0,0 +1,109 @@
+.TH USBWS "8" "March 2015" "usbwsd" "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..f4ea39f
--- /dev/null
+++ b/tools/usb/usbip/websocket/poco/USBWSRequestHandlerFactory.cpp
@@ -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.
+ */
+
+#include "USBWSRequestHandlerFactory.h"
+#include "USBWSRequestHandler.h"
+#include "Poco/URI.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)
+{
+	URI uri(req.getURI());
+	const std::string& path = uri.getPath();
+	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..cccd984
--- /dev/null
+++ b/tools/usb/usbip/websocket/poco/USBWSWebSocket.cpp
@@ -0,0 +1,204 @@
+/*
+ * 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)
+{
+	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.");
+	fPingPongStarted = false;
+	shutdownReceive();
+	close();
+}
+
+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()
+{
+	if (fPingPongStarted) {
+		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 majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux