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/AUTHORS | 1 + tools/usb/usbip/websocket/COPYING | 340 +++++++++++++++ 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 | 61 +++ 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 +++ 23 files changed, 2640 insertions(+) diff --git a/tools/usb/usbip/websocket/AUTHORS b/tools/usb/usbip/websocket/AUTHORS new file mode 100644 index 0000000..be60f78 --- /dev/null +++ b/tools/usb/usbip/websocket/AUTHORS @@ -0,0 +1 @@ +Nobuo Iwata diff --git a/tools/usb/usbip/websocket/COPYING b/tools/usb/usbip/websocket/COPYING new file mode 100644 index 0000000..c5611e4 --- /dev/null +++ b/tools/usb/usbip/websocket/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program 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 program 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. 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..4429822 --- /dev/null +++ b/tools/usb/usbip/websocket/configure.ac @@ -0,0 +1,61 @@ +dnl Process this file with autoconf to produce a configure script. + +AC_PREREQ(2.59) +AC_INIT([usbip-utils], [1.1.1], [linux-usb@xxxxxxxxxxxxxxx]) +AC_DEFINE([USBIP_VERSION], [0x00000111], [binary-coded decimal version number]) + +CURRENT=0 +REVISION=1 +AGE=0 +AC_SUBST([LIBUSBIP_VERSION], [$CURRENT:$REVISION:$AGE], [library version]) + +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..ba3bec1 --- /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..487c5db --- /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..172f4a8 --- /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 majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html