diff options
author | yoz@chromium.org <yoz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-21 00:25:28 +0000 |
---|---|---|
committer | yoz@chromium.org <yoz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-21 00:25:28 +0000 |
commit | 211b80bf18ff553288d28696edeb444fe126ba50 (patch) | |
tree | 52c466520e96868c0abd0a101a784fbfa271220c | |
parent | b48641366de449bb8fcbd3cc401420f65daae63b (diff) | |
download | chromium_src-211b80bf18ff553288d28696edeb444fe126ba50.zip chromium_src-211b80bf18ff553288d28696edeb444fe126ba50.tar.gz chromium_src-211b80bf18ff553288d28696edeb444fe126ba50.tar.bz2 |
Revert 152439 - Initial checkin for devtools-based automation
It fails check_licenses.
Review URL: https://chromiumcodereview.appspot.com/10825463
TBR=nduca@chromium.org
Review URL: https://chromiumcodereview.appspot.com/10831399
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@152445 0039d316-1c4b-4281-b951-d872f2087c98
15 files changed, 0 insertions, 1955 deletions
diff --git a/tools/devtools_auto/OWNERS b/tools/devtools_auto/OWNERS deleted file mode 100644 index 5f68319..0000000 --- a/tools/devtools_auto/OWNERS +++ /dev/null @@ -1,5 +0,0 @@ -# The set noparent is temporary until src/OWNERS isn't *. -set noparent -nduca@chromium.org -alokp@chromium.org -dtu@chromium.org diff --git a/tools/devtools_auto/README b/tools/devtools_auto/README deleted file mode 100644 index 0d1d5f2..0000000 --- a/tools/devtools_auto/README +++ /dev/null @@ -1,4 +0,0 @@ -devtools_auto provides automation of chrome instances on top of the chrome developer tools protocol. - -The protocol we use: -https://developers.google.com/chrome-developer-tools/docs/remote-debugging diff --git a/tools/devtools_auto/third_party/websocket-client/.gitignore b/tools/devtools_auto/third_party/websocket-client/.gitignore deleted file mode 100644 index c7d73ad..0000000 --- a/tools/devtools_auto/third_party/websocket-client/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -*.pyc -*~ -*\# -.\#* - -build -dist -websocket_client.egg-info diff --git a/tools/devtools_auto/third_party/websocket-client/LICENSE b/tools/devtools_auto/third_party/websocket-client/LICENSE deleted file mode 100644 index c255f4a..0000000 --- a/tools/devtools_auto/third_party/websocket-client/LICENSE +++ /dev/null @@ -1,506 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -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 and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, 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 library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete 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 distribute a copy of this License along with the -Library. - 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 Library or any portion -of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -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 Library, 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 Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you 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. - - If distribution of 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 satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be 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. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library 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. - - 9. 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 Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -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 with -this License. - - 11. 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 Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library 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 Library. - -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. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library 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. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser 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 Library -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 Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -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 - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "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 -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. 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 LIBRARY 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 -LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), 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 Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. 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 library's name and a brief idea of what it does.> - Copyright (C) <year> <name of author> - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - <signature of Ty Coon>, 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! - diff --git a/tools/devtools_auto/third_party/websocket-client/MANIFEST.in b/tools/devtools_auto/third_party/websocket-client/MANIFEST.in deleted file mode 100644 index 9d5d250..0000000 --- a/tools/devtools_auto/third_party/websocket-client/MANIFEST.in +++ /dev/null @@ -1,2 +0,0 @@ -include LICENSE -include README.rst diff --git a/tools/devtools_auto/third_party/websocket-client/README.chromium b/tools/devtools_auto/third_party/websocket-client/README.chromium deleted file mode 100644 index 0ef7731..0000000 --- a/tools/devtools_auto/third_party/websocket-client/README.chromium +++ /dev/null @@ -1,19 +0,0 @@ -Name: Python websocket-client -Short Name: websocket-client -URL: https://github.com/liris/websocket-client -Version: 0 -Revision: 861f9cf354833fe3992315b60292865c5245c821 -Date: Tue Jul 10 19:57:00 2012 -0700 -License: LGPL-2.1 -License File: NOT_SHIPPED -Security Critical: no - -Description: - -websocket-client module is WebSocket client for python. This provide the low -level APIs for WebSocket. All APIs are the synchronous functions. - -Used by the python code in devtools-auto to communicate with a running Chrome instance. - -Local Modifications: -None. diff --git a/tools/devtools_auto/third_party/websocket-client/README.rst b/tools/devtools_auto/third_party/websocket-client/README.rst deleted file mode 100644 index 1b7faeb..0000000 --- a/tools/devtools_auto/third_party/websocket-client/README.rst +++ /dev/null @@ -1,140 +0,0 @@ -================= -websocket-client -================= - -websocket-client module is WebSocket client for python. This provide the low level APIs for WebSocket. All APIs are the synchronous functions. - -websocket-client supports only hybi-13. - -License -============ - - - LGPL - -Installation -============= - -This module is tested on only Python 2.7. - -Type "python setup.py install" or "pip install websocket-client" to install. - -This module does not depend on any other module. - -Example -============ - -Low Level API example:: - - from websocket import create_connection - ws = create_connection("ws://echo.websocket.org/") - print "Sending 'Hello, World'..." - ws.send("Hello, World") - print "Sent" - print "Reeiving..." - result = ws.recv() - print "Received '%s'" % result - ws.close() - - -JavaScript websocket-like API example:: - - import websocket - import thread - import time - - def on_message(ws, message): - print message - - def on_error(ws, error): - print error - - def on_close(ws): - print "### closed ###" - - def on_open(ws): - def run(*args): - for i in range(3): - time.sleep(1) - ws.send("Hello %d" % i) - time.sleep(1) - ws.close() - print "thread terminating..." - thread.start_new_thread(run, ()) - - - if __name__ == "__main__": - websocket.enableTrace(True) - ws = websocket.WebSocketApp("ws://echo.websocket.org/", - on_message = on_message, - on_error = on_error, - on_close = on_close) - ws.on_open = on_open - - ws.run_forever() - - -wsdump.py -============ - -wsdump.py is simple WebSocket test(debug) tool. - -sample for echo.websocket.org:: - - $ wsdump.py ws://echo.websocket.org/ - Press Ctrl+C to quit - > Hello, WebSocket - < Hello, WebSocket - > How are you? - < How are you? - -Usage ---------- - -usage:: - wsdump.py [-h] [-v [VERBOSE]] ws_url - -WebSocket Simple Dump Tool - -positional arguments: - ws_url websocket url. ex. ws://echo.websocket.org/ - -optional arguments: - -h, --help show this help message and exit - - -v VERBOSE, --verbose VERBOSE set verbose mode. If set to 1, show opcode. If set to 2, enable to trace websocket module - -example:: - - $ wsdump.py ws://echo.websocket.org/ - $ wsdump.py ws://echo.websocket.org/ -v - $ wsdump.py ws://echo.websocket.org/ -vv - -ChangeLog -============ - -- v0.7.0 - - - fixed problem to read long data.(ISSUE#12) - - fix buffer size boundary violation - -- v0.6.0 - - - Patches: UUID4, self.keep_running, mask_key (ISSUE#11) - - add wsdump.py tool - -- v0.5.2 - - - fix Echo App Demo Throw Error: 'NoneType' object has no attribute 'opcode (ISSUE#10) - -- v0.5.1 - - - delete invalid print statement. - -- v0.5.0 - - - support hybi-13 protocol. - -- v0.4.1 - - - fix incorrect custom header order(ISSUE#1) - diff --git a/tools/devtools_auto/third_party/websocket-client/bin/wsdump.py b/tools/devtools_auto/third_party/websocket-client/bin/wsdump.py deleted file mode 100755 index 02b40af..0000000 --- a/tools/devtools_auto/third_party/websocket-client/bin/wsdump.py +++ /dev/null @@ -1,111 +0,0 @@ -#!/usr/bin/env python - -import argparse -import code -import sys -import threading -import websocket -try: - import readline -except: - pass - - -OPCODE_DATA = (websocket.ABNF.OPCODE_TEXT, websocket.ABNF.OPCODE_BINARY) -ENCODING = getattr(sys.stdin, "encoding", "").lower() - -class VAction(argparse.Action): - def __call__(self, parser, args, values, option_string=None): - if values==None: - values = "1" - try: - values = int(values) - except ValueError: - values = values.count("v")+1 - setattr(args, self.dest, values) - -def parse_args(): - parser = argparse.ArgumentParser(description="WebSocket Simple Dump Tool") - parser.add_argument("url", metavar="ws_url", - help="websocket url. ex. ws://echo.websocket.org/") - parser.add_argument("-v", "--verbose", default=0, nargs='?', action=VAction, - dest="verbose", - help="set verbose mode. If set to 1, show opcode. " - "If set to 2, enable to trace websocket module") - - return parser.parse_args() - - -class InteractiveConsole(code.InteractiveConsole): - def write(self, data): - sys.stdout.write("\033[2K\033[E") - # sys.stdout.write("\n") - sys.stdout.write("\033[34m" + data + "\033[39m") - sys.stdout.write("\n> ") - sys.stdout.flush() - - - def raw_input(self, prompt): - line = raw_input(prompt) - if ENCODING and ENCODING != "utf-8" and not isinstance(line, unicode): - line = line.decode(ENCODING).encode("utf-8") - elif isinstance(line, unicode): - line = encode("utf-8") - - return line - - -def main(): - args = parse_args() - console = InteractiveConsole() - ws = websocket.create_connection(args.url) - if args.verbose > 1: - websocket.enableTrace(True) - print "Press Ctrl+C to quit" - - def recv(): - frame = ws.recv_frame() - if not frame: - raise websocket.WebSocketException("Not a valid frame %s" % frame) - elif frame.opcode in OPCODE_DATA: - return (frame.opcode, frame.data) - elif frame.opcode == websocket.ABNF.OPCODE_CLOSE: - ws.send_close() - return (frame.opcode, None) - elif frame.opcode == websocket.ABNF.OPCODE_PING: - ws.pong("Hi!") - - return None, None - - - def recv_ws(): - while True: - opcode, data = recv() - msg = None - if not args.verbose and opcode in OPCODE_DATA: - msg = "< %s" % data - elif args.verbose: - msg = "< %s: %s" % (websocket.ABNF.OPCODE_MAP.get(opcode), data) - - if msg: - console.write(msg) - - thread = threading.Thread(target=recv_ws) - thread.daemon = True - thread.start() - - while True: - try: - message = console.raw_input("> ") - ws.send(message) - except KeyboardInterrupt: - return - except EOFError: - return - - -if __name__ == "__main__": - try: - main() - except Exception, e: - print e diff --git a/tools/devtools_auto/third_party/websocket-client/data/header01.txt b/tools/devtools_auto/third_party/websocket-client/data/header01.txt deleted file mode 100644 index 3142b43..0000000 --- a/tools/devtools_auto/third_party/websocket-client/data/header01.txt +++ /dev/null @@ -1,6 +0,0 @@ -HTTP/1.1 101 WebSocket Protocol Handshake
-Connection: Upgrade
-Upgrade: WebSocket
-Sec-WebSocket-Accept: Kxep+hNu9n51529fGidYu7a3wO0=
-some_header: something
-
diff --git a/tools/devtools_auto/third_party/websocket-client/data/header02.txt b/tools/devtools_auto/third_party/websocket-client/data/header02.txt deleted file mode 100644 index a9dd2ce..0000000 --- a/tools/devtools_auto/third_party/websocket-client/data/header02.txt +++ /dev/null @@ -1,6 +0,0 @@ -HTTP/1.1 101 WebSocket Protocol Handshake
-Connection: Upgrade
-Upgrade WebSocket
-Sec-WebSocket-Accept: Kxep+hNu9n51529fGidYu7a3wO0=
-some_header: something
-
diff --git a/tools/devtools_auto/third_party/websocket-client/examples/echo_client.py b/tools/devtools_auto/third_party/websocket-client/examples/echo_client.py deleted file mode 100644 index 1eb5f1b..0000000 --- a/tools/devtools_auto/third_party/websocket-client/examples/echo_client.py +++ /dev/null @@ -1,12 +0,0 @@ -import websocket - -if __name__ == "__main__": - websocket.enableTrace(True) - ws = websocket.create_connection("ws://echo.websocket.org/") - print "Sending 'Hello, World'..." - ws.send("Hello, World") - print "Sent" - print "Receiving..." - result = ws.recv() - print "Received '%s'" % result - ws.close() diff --git a/tools/devtools_auto/third_party/websocket-client/examples/echoapp_client.py b/tools/devtools_auto/third_party/websocket-client/examples/echoapp_client.py deleted file mode 100644 index 438e4b3..0000000 --- a/tools/devtools_auto/third_party/websocket-client/examples/echoapp_client.py +++ /dev/null @@ -1,41 +0,0 @@ -import websocket -import thread -import time -import sys - -def on_message(ws, message): - print message - -def on_error(ws, error): - print error - -def on_close(ws): - print "### closed ###" - -def on_open(ws): - def run(*args): - for i in range(3): - # send the message, then wait - # so thread doesnt exit and socket - # isnt closed - ws.send("Hello %d" % i) - time.sleep(1) - - time.sleep(1) - ws.close() - print "Thread terminating..." - - thread.start_new_thread(run, ()) - -if __name__ == "__main__": - websocket.enableTrace(True) - if len(sys.argv) < 2: - host = "ws://echo.websocket.org/" - else: - host = sys.argv[1] - ws = websocket.WebSocketApp(host, - on_message = on_message, - on_error = on_error, - on_close = on_close) - ws.on_open = on_open - ws.run_forever() diff --git a/tools/devtools_auto/third_party/websocket-client/setup.py b/tools/devtools_auto/third_party/websocket-client/setup.py deleted file mode 100644 index e11400e..0000000 --- a/tools/devtools_auto/third_party/websocket-client/setup.py +++ /dev/null @@ -1,28 +0,0 @@ -from setuptools import setup - -VERSION = "0.7.0" - - -setup( - name="websocket-client", - version=VERSION, - description="WebSocket client for python. hybi13 is supported.", - long_description=open("README.rst").read(), - author="liris", - author_email="liris.pp@gmail.com", - license="LGPL", - url="https://github.com/liris/websocket-client", - classifiers = [ - "Development Status :: 3 - Alpha", - "License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)", - "Programming Language :: Python", - "Operating System :: MacOS :: MacOS X", - "Operating System :: POSIX", - "Operating System :: Microsoft :: Windows", - "Topic :: Internet", - "Topic :: Software Development :: Libraries :: Python Modules", - "Intended Audience :: Developers", - ], - py_modules=["websocket"], - scripts=["bin/wsdump.py"] -) diff --git a/tools/devtools_auto/third_party/websocket-client/test_websocket.py b/tools/devtools_auto/third_party/websocket-client/test_websocket.py deleted file mode 100644 index 3471f4e..0000000 --- a/tools/devtools_auto/third_party/websocket-client/test_websocket.py +++ /dev/null @@ -1,311 +0,0 @@ -# -*- coding: utf-8 -*- -# - -import base64 -import uuid -import unittest - -# websocket-client -import websocket as ws - -TRACABLE=False - -def create_mask_key(n): - return "abcd" - -class StringSockMock: - def __init__(self): - self.set_data("") - self.sent = [] - - def set_data(self, data): - self.data = data - self.pos = 0 - self.len = len(data) - - def recv(self, bufsize): - if self.len < self.pos: - return - buf = self.data[self.pos: self.pos + bufsize] - self.pos += bufsize - return buf - - def send(self, data): - self.sent.append(data) - - -class HeaderSockMock(StringSockMock): - def __init__(self, fname): - self.set_data(open(fname).read()) - self.sent = [] - - -class WebSocketTest(unittest.TestCase): - def setUp(self): - ws.enableTrace(TRACABLE) - - def tearDown(self): - pass - - def testDefaultTimeout(self): - self.assertEquals(ws.getdefaulttimeout(), None) - ws.setdefaulttimeout(10) - self.assertEquals(ws.getdefaulttimeout(), 10) - ws.setdefaulttimeout(None) - - def testParseUrl(self): - p = ws._parse_url("ws://www.example.com/r") - self.assertEquals(p[0], "www.example.com") - self.assertEquals(p[1], 80) - self.assertEquals(p[2], "/r") - self.assertEquals(p[3], False) - - p = ws._parse_url("ws://www.example.com/r/") - self.assertEquals(p[0], "www.example.com") - self.assertEquals(p[1], 80) - self.assertEquals(p[2], "/r/") - self.assertEquals(p[3], False) - - p = ws._parse_url("ws://www.example.com/") - self.assertEquals(p[0], "www.example.com") - self.assertEquals(p[1], 80) - self.assertEquals(p[2], "/") - self.assertEquals(p[3], False) - - p = ws._parse_url("ws://www.example.com") - self.assertEquals(p[0], "www.example.com") - self.assertEquals(p[1], 80) - self.assertEquals(p[2], "/") - self.assertEquals(p[3], False) - - p = ws._parse_url("ws://www.example.com:8080/r") - self.assertEquals(p[0], "www.example.com") - self.assertEquals(p[1], 8080) - self.assertEquals(p[2], "/r") - self.assertEquals(p[3], False) - - p = ws._parse_url("ws://www.example.com:8080/") - self.assertEquals(p[0], "www.example.com") - self.assertEquals(p[1], 8080) - self.assertEquals(p[2], "/") - self.assertEquals(p[3], False) - - p = ws._parse_url("ws://www.example.com:8080") - self.assertEquals(p[0], "www.example.com") - self.assertEquals(p[1], 8080) - self.assertEquals(p[2], "/") - self.assertEquals(p[3], False) - - p = ws._parse_url("wss://www.example.com:8080/r") - self.assertEquals(p[0], "www.example.com") - self.assertEquals(p[1], 8080) - self.assertEquals(p[2], "/r") - self.assertEquals(p[3], True) - - p = ws._parse_url("wss://www.example.com:8080/r?key=value") - self.assertEquals(p[0], "www.example.com") - self.assertEquals(p[1], 8080) - self.assertEquals(p[2], "/r?key=value") - self.assertEquals(p[3], True) - - self.assertRaises(ValueError, ws._parse_url, "http://www.example.com/r") - - def testWSKey(self): - key = ws._create_sec_websocket_key() - self.assert_(key != 24) - self.assert_("¥n" not in key) - - def testWsUtils(self): - sock = ws.WebSocket() - - key = "c6b8hTg4EeGb2gQMztV1/g==" - required_header = { - "upgrade": "websocket", - "connection": "upgrade", - "sec-websocket-accept": "Kxep+hNu9n51529fGidYu7a3wO0=", - } - self.assertEquals(sock._validate_header(required_header, key), True) - - header = required_header.copy() - header["upgrade"] = "http" - self.assertEquals(sock._validate_header(header, key), False) - del header["upgrade"] - self.assertEquals(sock._validate_header(header, key), False) - - header = required_header.copy() - header["connection"] = "something" - self.assertEquals(sock._validate_header(header, key), False) - del header["connection"] - self.assertEquals(sock._validate_header(header, key), False) - - - header = required_header.copy() - header["sec-websocket-accept"] = "something" - self.assertEquals(sock._validate_header(header, key), False) - del header["sec-websocket-accept"] - self.assertEquals(sock._validate_header(header, key), False) - - def testReadHeader(self): - sock = ws.WebSocket() - sock.io_sock = sock.sock = HeaderSockMock("data/header01.txt") - status, header = sock._read_headers() - self.assertEquals(status, 101) - self.assertEquals(header["connection"], "upgrade") - - sock.io_sock = sock.sock = HeaderSockMock("data/header02.txt") - self.assertRaises(ws.WebSocketException, sock._read_headers) - - def testSend(self): - # TODO: add longer frame data - sock = ws.WebSocket() - sock.set_mask_key(create_mask_key) - s = sock.io_sock = sock.sock = HeaderSockMock("data/header01.txt") - sock.send("Hello") - self.assertEquals(s.sent[0], "\x81\x85abcd)\x07\x0f\x08\x0e") - - sock.send("こんにちは") - self.assertEquals(s.sent[1], "\x81\x8fabcd\x82\xe3\xf0\x87\xe3\xf1\x80\xe5\xca\x81\xe2\xc5\x82\xe3\xcc") - - sock.send(u"こんにちは") - self.assertEquals(s.sent[1], "\x81\x8fabcd\x82\xe3\xf0\x87\xe3\xf1\x80\xe5\xca\x81\xe2\xc5\x82\xe3\xcc") - - def testRecv(self): - # TODO: add longer frame data - sock = ws.WebSocket() - s = sock.io_sock = sock.sock = StringSockMock() - s.set_data("\x81\x8fabcd\x82\xe3\xf0\x87\xe3\xf1\x80\xe5\xca\x81\xe2\xc5\x82\xe3\xcc") - data = sock.recv() - self.assertEquals(data, "こんにちは") - - s.set_data("\x81\x85abcd)\x07\x0f\x08\x0e") - data = sock.recv() - self.assertEquals(data, "Hello") - - def testWebSocket(self): - s = ws.create_connection("ws://echo.websocket.org/") #ws://localhost:8080/echo") - self.assertNotEquals(s, None) - s.send("Hello, World") - result = s.recv() - self.assertEquals(result, "Hello, World") - - s.send("こにゃにゃちは、世界") - result = s.recv() - self.assertEquals(result, "こにゃにゃちは、世界") - s.close() - - def testPingPong(self): - s = ws.create_connection("ws://echo.websocket.org/") - self.assertNotEquals(s, None) - s.ping("Hello") - s.pong("Hi") - s.close() - - def testSecureWebSocket(self): - s = ws.create_connection("wss://echo.websocket.org/") - self.assertNotEquals(s, None) - self.assert_(isinstance(s.io_sock, ws._SSLSocketWrapper)) - s.send("Hello, World") - result = s.recv() - self.assertEquals(result, "Hello, World") - s.send("こにゃにゃちは、世界") - result = s.recv() - self.assertEquals(result, "こにゃにゃちは、世界") - s.close() - - def testWebSocketWihtCustomHeader(self): - s = ws.create_connection("ws://echo.websocket.org/", - headers={"User-Agent": "PythonWebsocketClient"}) - self.assertNotEquals(s, None) - s.send("Hello, World") - result = s.recv() - self.assertEquals(result, "Hello, World") - s.close() - - def testAfterClose(self): - from socket import error - s = ws.create_connection("ws://echo.websocket.org/") - self.assertNotEquals(s, None) - s.close() - self.assertRaises(error, s.send, "Hello") - self.assertRaises(error, s.recv) - - def testUUID4(self): - """ WebSocket key should be a UUID4. - """ - key = ws._create_sec_websocket_key() - u = uuid.UUID(bytes=base64.b64decode(key)) - self.assertEquals(4, u.version) - -class WebSocketAppTest(unittest.TestCase): - - class NotSetYet(object): - """ A marker class for signalling that a value hasn't been set yet. - """ - - def setUp(self): - ws.enableTrace(TRACABLE) - - WebSocketAppTest.keep_running_open = WebSocketAppTest.NotSetYet() - WebSocketAppTest.keep_running_close = WebSocketAppTest.NotSetYet() - WebSocketAppTest.get_mask_key_id = WebSocketAppTest.NotSetYet() - - def tearDown(self): - - WebSocketAppTest.keep_running_open = WebSocketAppTest.NotSetYet() - WebSocketAppTest.keep_running_close = WebSocketAppTest.NotSetYet() - WebSocketAppTest.get_mask_key_id = WebSocketAppTest.NotSetYet() - - def testKeepRunning(self): - """ A WebSocketApp should keep running as long as its self.keep_running - is not False (in the boolean context). - """ - - def on_open(self, *args, **kwargs): - """ Set the keep_running flag for later inspection and immediately - close the connection. - """ - WebSocketAppTest.keep_running_open = self.keep_running - self.close() - - def on_close(self, *args, **kwargs): - """ Set the keep_running flag for the test to use. - """ - WebSocketAppTest.keep_running_close = self.keep_running - - app = ws.WebSocketApp('ws://echo.websocket.org/', on_open=on_open, on_close=on_close) - app.run_forever() - - self.assertFalse(isinstance(WebSocketAppTest.keep_running_open, - WebSocketAppTest.NotSetYet)) - - self.assertFalse(isinstance(WebSocketAppTest.keep_running_close, - WebSocketAppTest.NotSetYet)) - - self.assertEquals(True, WebSocketAppTest.keep_running_open) - self.assertEquals(False, WebSocketAppTest.keep_running_close) - - def testSockMaskKey(self): - """ A WebSocketApp should forward the received mask_key function down - to the actual socket. - """ - - def my_mask_key_func(): - pass - - def on_open(self, *args, **kwargs): - """ Set the value so the test can use it later on and immediately - close the connection. - """ - WebSocketAppTest.get_mask_key_id = id(self.get_mask_key) - self.close() - - app = ws.WebSocketApp('ws://echo.websocket.org/', on_open=on_open, get_mask_key=my_mask_key_func) - app.run_forever() - - # Note: We can't use 'is' for comparing the functions directly, need to use 'id'. - self.assertEquals(WebSocketAppTest.get_mask_key_id, id(my_mask_key_func)) - - -if __name__ == "__main__": - unittest.main() - diff --git a/tools/devtools_auto/third_party/websocket-client/websocket.py b/tools/devtools_auto/third_party/websocket-client/websocket.py deleted file mode 100644 index 480bfc0..0000000 --- a/tools/devtools_auto/third_party/websocket-client/websocket.py +++ /dev/null @@ -1,756 +0,0 @@ -""" -websocket - WebSocket client library for Python - -Copyright (C) 2010 Hiroki Ohtani(liris) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -""" - - -import socket -from urlparse import urlparse -import os -import struct -import uuid -import hashlib -import base64 -import logging - -""" -websocket python client. -========================= - -This version support only hybi-13. -Please see http://tools.ietf.org/html/rfc6455 for protocol. -""" - - -# websocket supported version. -VERSION = 13 - -# closing frame status codes. -STATUS_NORMAL = 1000 -STATUS_GOING_AWAY = 1001 -STATUS_PROTOCOL_ERROR = 1002 -STATUS_UNSUPPORTED_DATA_TYPE = 1003 -STATUS_STATUS_NOT_AVAILABLE = 1005 -STATUS_ABNORMAL_CLOSED = 1006 -STATUS_INVALID_PAYLOAD = 1007 -STATUS_POLICY_VIOLATION = 1008 -STATUS_MESSAGE_TOO_BIG = 1009 -STATUS_INVALID_EXTENSION = 1010 -STATUS_UNEXPECTED_CONDITION = 1011 -STATUS_TLS_HANDSHAKE_ERROR = 1015 - -logger = logging.getLogger() - -class WebSocketException(Exception): - """ - websocket exeception class. - """ - pass - -class WebSocketConnectionClosedException(WebSocketException): - """ - If remote host closed the connection or some network error happened, - this exception will be raised. - """ - pass - -default_timeout = None -traceEnabled = False - -def enableTrace(tracable): - """ - turn on/off the tracability. - - tracable: boolean value. if set True, tracability is enabled. - """ - global traceEnabled - traceEnabled = tracable - if tracable: - if not logger.handlers: - logger.addHandler(logging.StreamHandler()) - logger.setLevel(logging.DEBUG) - -def setdefaulttimeout(timeout): - """ - Set the global timeout setting to connect. - - timeout: default socket timeout time. This value is second. - """ - global default_timeout - default_timeout = timeout - -def getdefaulttimeout(): - """ - Return the global timeout setting(second) to connect. - """ - return default_timeout - -def _parse_url(url): - """ - parse url and the result is tuple of - (hostname, port, resource path and the flag of secure mode) - - url: url string. - """ - if ":" not in url: - raise ValueError("url is invalid") - - scheme, url = url.split(":", 1) - - parsed = urlparse(url, scheme="http") - if parsed.hostname: - hostname = parsed.hostname - else: - raise ValueError("hostname is invalid") - port = 0 - if parsed.port: - port = parsed.port - - is_secure = False - if scheme == "ws": - if not port: - port = 80 - elif scheme == "wss": - is_secure = True - if not port: - port = 443 - else: - raise ValueError("scheme %s is invalid" % scheme) - - if parsed.path: - resource = parsed.path - else: - resource = "/" - - if parsed.query: - resource += "?" + parsed.query - - return (hostname, port, resource, is_secure) - -def create_connection(url, timeout=None, **options): - """ - connect to url and return websocket object. - - Connect to url and return the WebSocket object. - Passing optional timeout parameter will set the timeout on the socket. - If no timeout is supplied, the global default timeout setting returned by getdefauttimeout() is used. - You can customize using 'options'. - If you set "header" dict object, you can set your own custom header. - - >>> conn = create_connection("ws://echo.websocket.org/", - ... header={"User-Agent: MyProgram", - ... "x-custom: header"}) - - - timeout: socket timeout time. This value is integer. - if you set None for this value, it means "use default_timeout value" - - options: current support option is only "header". - if you set header as dict value, the custom HTTP headers are added. - """ - websock = WebSocket() - websock.settimeout(timeout != None and timeout or default_timeout) - websock.connect(url, **options) - return websock - -_MAX_INTEGER = (1 << 32) -1 -_AVAILABLE_KEY_CHARS = range(0x21, 0x2f + 1) + range(0x3a, 0x7e + 1) -_MAX_CHAR_BYTE = (1<<8) -1 - -# ref. Websocket gets an update, and it breaks stuff. -# http://axod.blogspot.com/2010/06/websocket-gets-update-and-it-breaks.html - -def _create_sec_websocket_key(): - uid = uuid.uuid4() - return base64.encodestring(uid.bytes).strip() - -_HEADERS_TO_CHECK = { - "upgrade": "websocket", - "connection": "upgrade", - } - -class _SSLSocketWrapper(object): - def __init__(self, sock): - self.ssl = socket.ssl(sock) - - def recv(self, bufsize): - return self.ssl.read(bufsize) - - def send(self, payload): - return self.ssl.write(payload) - -_BOOL_VALUES = (0, 1) -def _is_bool(*values): - for v in values: - if v not in _BOOL_VALUES: - return False - - return True - -class ABNF(object): - """ - ABNF frame class. - see http://tools.ietf.org/html/rfc5234 - and http://tools.ietf.org/html/rfc6455#section-5.2 - """ - - # operation code values. - OPCODE_TEXT = 0x1 - OPCODE_BINARY = 0x2 - OPCODE_CLOSE = 0x8 - OPCODE_PING = 0x9 - OPCODE_PONG = 0xa - - # available operation code value tuple - OPCODES = (OPCODE_TEXT, OPCODE_BINARY, OPCODE_CLOSE, - OPCODE_PING, OPCODE_PONG) - - # opcode human readable string - OPCODE_MAP = { - OPCODE_TEXT: "text", - OPCODE_BINARY: "binary", - OPCODE_CLOSE: "close", - OPCODE_PING: "ping", - OPCODE_PONG: "pong" - } - - # data length threashold. - LENGTH_7 = 0x7d - LENGTH_16 = 1 << 16 - LENGTH_63 = 1 << 63 - - def __init__(self, fin = 0, rsv1 = 0, rsv2 = 0, rsv3 = 0, - opcode = OPCODE_TEXT, mask = 1, data = ""): - """ - Constructor for ABNF. - please check RFC for arguments. - """ - self.fin = fin - self.rsv1 = rsv1 - self.rsv2 = rsv2 - self.rsv3 = rsv3 - self.opcode = opcode - self.mask = mask - self.data = data - self.get_mask_key = os.urandom - - @staticmethod - def create_frame(data, opcode): - """ - create frame to send text, binary and other data. - - data: data to send. This is string value(byte array). - if opcode is OPCODE_TEXT and this value is uniocde, - data value is conveted into unicode string, automatically. - - opcode: operation code. please see OPCODE_XXX. - """ - if opcode == ABNF.OPCODE_TEXT and isinstance(data, unicode): - data = data.encode("utf-8") - # mask must be set if send data from client - return ABNF(1, 0, 0, 0, opcode, 1, data) - - def format(self): - """ - format this object to string(byte array) to send data to server. - """ - if not _is_bool(self.fin, self.rsv1, self.rsv2, self.rsv3): - raise ValueError("not 0 or 1") - if self.opcode not in ABNF.OPCODES: - raise ValueError("Invalid OPCODE") - length = len(self.data) - if length >= ABNF.LENGTH_63: - raise ValueError("data is too long") - - frame_header = chr(self.fin << 7 - | self.rsv1 << 6 | self.rsv2 << 5 | self.rsv3 << 4 - | self.opcode) - if length < ABNF.LENGTH_7: - frame_header += chr(self.mask << 7 | length) - elif length < ABNF.LENGTH_16: - frame_header += chr(self.mask << 7 | 0x7e) - frame_header += struct.pack("!H", length) - else: - frame_header += chr(self.mask << 7 | 0x7f) - frame_header += struct.pack("!Q", length) - - if not self.mask: - return frame_header + self.data - else: - mask_key = self.get_mask_key(4) - return frame_header + self._get_masked(mask_key) - - def _get_masked(self, mask_key): - s = ABNF.mask(mask_key, self.data) - return mask_key + "".join(s) - - @staticmethod - def mask(mask_key, data): - """ - mask or unmask data. Just do xor for each byte - - mask_key: 4 byte string(byte). - - data: data to mask/unmask. - """ - _m = map(ord, mask_key) - _d = map(ord, data) - for i in range(len(_d)): - _d[i] ^= _m[i % 4] - s = map(chr, _d) - return "".join(s) - -class WebSocket(object): - """ - Low level WebSocket interface. - This class is based on - The WebSocket protocol draft-hixie-thewebsocketprotocol-76 - http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76 - - We can connect to the websocket server and send/recieve data. - The following example is a echo client. - - >>> import websocket - >>> ws = websocket.WebSocket() - >>> ws.connect("ws://echo.websocket.org") - >>> ws.send("Hello, Server") - >>> ws.recv() - 'Hello, Server' - >>> ws.close() - - get_mask_key: a callable to produce new mask keys, see the set_mask_key - function's docstring for more details - """ - def __init__(self, get_mask_key = None): - """ - Initalize WebSocket object. - """ - self.connected = False - self.io_sock = self.sock = socket.socket() - self.get_mask_key = get_mask_key - - def set_mask_key(self, func): - """ - set function to create musk key. You can custumize mask key generator. - Mainly, this is for testing purpose. - - func: callable object. the fuct must 1 argument as integer. - The argument means length of mask key. - This func must be return string(byte array), - which length is argument specified. - """ - self.get_mask_key = func - - def settimeout(self, timeout): - """ - Set the timeout to the websocket. - - timeout: timeout time(second). - """ - self.sock.settimeout(timeout) - - def gettimeout(self): - """ - Get the websocket timeout(second). - """ - return self.sock.gettimeout() - - def connect(self, url, **options): - """ - Connect to url. url is websocket url scheme. ie. ws://host:port/resource - You can customize using 'options'. - If you set "header" dict object, you can set your own custom header. - - >>> ws = WebSocket() - >>> ws.connect("ws://echo.websocket.org/", - ... header={"User-Agent: MyProgram", - ... "x-custom: header"}) - - timeout: socket timeout time. This value is integer. - if you set None for this value, - it means "use default_timeout value" - - options: current support option is only "header". - if you set header as dict value, - the custom HTTP headers are added. - - """ - hostname, port, resource, is_secure = _parse_url(url) - # TODO: we need to support proxy - self.sock.connect((hostname, port)) - if is_secure: - self.io_sock = _SSLSocketWrapper(self.sock) - self._handshake(hostname, port, resource, **options) - - def _handshake(self, host, port, resource, **options): - sock = self.io_sock - headers = [] - headers.append("GET %s HTTP/1.1" % resource) - headers.append("Upgrade: websocket") - headers.append("Connection: Upgrade") - if port == 80: - hostport = host - else: - hostport = "%s:%d" % (host, port) - headers.append("Host: %s" % hostport) - headers.append("Origin: %s" % hostport) - - key = _create_sec_websocket_key() - headers.append("Sec-WebSocket-Key: %s" % key) - headers.append("Sec-WebSocket-Version: %s" % VERSION) - if "header" in options: - headers.extend(options["header"]) - - headers.append("") - headers.append("") - - header_str = "\r\n".join(headers) - sock.send(header_str) - if traceEnabled: - logger.debug( "--- request header ---") - logger.debug( header_str) - logger.debug("-----------------------") - - status, resp_headers = self._read_headers() - if status != 101: - self.close() - raise WebSocketException("Handshake Status %d" % status) - - success = self._validate_header(resp_headers, key) - if not success: - self.close() - raise WebSocketException("Invalid WebSocket Header") - - self.connected = True - - def _validate_header(self, headers, key): - for k, v in _HEADERS_TO_CHECK.iteritems(): - r = headers.get(k, None) - if not r: - return False - r = r.lower() - if v != r: - return False - - result = headers.get("sec-websocket-accept", None) - if not result: - return False - result = result.lower() - - value = key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" - hashed = base64.encodestring(hashlib.sha1(value).digest()).strip().lower() - return hashed == result - - def _read_headers(self): - status = None - headers = {} - if traceEnabled: - logger.debug("--- response header ---") - - while True: - line = self._recv_line() - if line == "\r\n": - break - line = line.strip() - if traceEnabled: - logger.debug(line) - if not status: - status_info = line.split(" ", 2) - status = int(status_info[1]) - else: - kv = line.split(":", 1) - if len(kv) == 2: - key, value = kv - headers[key.lower()] = value.strip().lower() - else: - raise WebSocketException("Invalid header") - - if traceEnabled: - logger.debug("-----------------------") - - return status, headers - - def send(self, payload, opcode = ABNF.OPCODE_TEXT): - """ - Send the data as string. - - payload: Payload must be utf-8 string or unicoce, - if the opcode is OPCODE_TEXT. - Otherwise, it must be string(byte array) - - opcode: operation code to send. Please see OPCODE_XXX. - """ - frame = ABNF.create_frame(payload, opcode) - if self.get_mask_key: - frame.get_mask_key = self.get_mask_key - data = frame.format() - self.io_sock.send(data) - if traceEnabled: - logger.debug("send: " + repr(data)) - - def ping(self, payload = ""): - """ - send ping data. - - payload: data payload to send server. - """ - self.send(payload, ABNF.OPCODE_PING) - - def pong(self, payload): - """ - send pong data. - - payload: data payload to send server. - """ - self.send(payload, ABNF.OPCODE_PONG) - - def recv(self): - """ - Receive string data(byte array) from the server. - - return value: string(byte array) value. - """ - opcode, data = self.recv_data() - return data - - def recv_data(self): - """ - Recieve data with operation code. - - return value: tuple of operation code and string(byte array) value. - """ - while True: - frame = self.recv_frame() - if not frame: - # handle error: - # 'NoneType' object has no attribute 'opcode' - raise WebSocketException("Not a valid frame %s" % frame) - elif frame.opcode in (ABNF.OPCODE_TEXT, ABNF.OPCODE_BINARY): - return (frame.opcode, frame.data) - elif frame.opcode == ABNF.OPCODE_CLOSE: - self.send_close() - return (frame.opcode, None) - elif frame.opcode == ABNF.OPCODE_PING: - self.pong("Hi!") - - - def recv_frame(self): - """ - recieve data as frame from server. - - return value: ABNF frame object. - """ - header_bytes = self._recv(2) - if not header_bytes: - return None - b1 = ord(header_bytes[0]) - fin = b1 >> 7 & 1 - rsv1 = b1 >> 6 & 1 - rsv2 = b1 >> 5 & 1 - rsv3 = b1 >> 4 & 1 - opcode = b1 & 0xf - b2 = ord(header_bytes[1]) - mask = b2 >> 7 & 1 - length = b2 & 0x7f - - length_data = "" - if length == 0x7e: - length_data = self._recv(2) - length = struct.unpack("!H", length_data)[0] - elif length == 0x7f: - length_data = self._recv(8) - length = struct.unpack("!Q", length_data)[0] - - mask_key = "" - if mask: - mask_key = self._recv(4) - data = self._recv_strict(length) - if traceEnabled: - recieved = header_bytes + length_data + mask_key + data - logger.debug("recv: " + repr(recieved)) - - if mask: - data = ABNF.mask(mask_key, data) - - frame = ABNF(fin, rsv1, rsv2, rsv3, opcode, mask, data) - return frame - - def send_close(self, status = STATUS_NORMAL, reason = ""): - """ - send close data to the server. - - status: status code to send. see STATUS_XXX. - - reason: the reason to close. This must be string. - """ - if status < 0 or status >= ABNF.LENGTH_16: - raise ValueError("code is invalid range") - self.send(struct.pack('!H', status) + reason, ABNF.OPCODE_CLOSE) - - - - def close(self, status = STATUS_NORMAL, reason = ""): - """ - Close Websocket object - - status: status code to send. see STATUS_XXX. - - reason: the reason to close. This must be string. - """ - if self.connected: - if status < 0 or status >= ABNF.LENGTH_16: - raise ValueError("code is invalid range") - - try: - self.send(struct.pack('!H', status) + reason, ABNF.OPCODE_CLOSE) - timeout = self.sock.gettimeout() - self.sock.settimeout(3) - try: - frame = self.recv_frame() - if logger.isEnabledFor(logging.DEBUG): - logger.error("close status: " + repr(frame.data)) - except: - pass - self.sock.settimeout(timeout) - self.sock.shutdown(socket.SHUT_RDWR) - except: - pass - self._closeInternal() - - def _closeInternal(self): - self.connected = False - self.sock.close() - self.io_sock = self.sock - - def _recv(self, bufsize): - bytes = self.io_sock.recv(bufsize) - if bytes == 0: - raise WebSocketConnectionClosedException() - return bytes - - def _recv_strict(self, bufsize): - remaining = bufsize - bytes = "" - while remaining: - bytes += self._recv(remaining) - remaining = bufsize - len(bytes) - - return bytes - - def _recv_line(self): - line = [] - while True: - c = self._recv(1) - line.append(c) - if c == "\n": - break - return "".join(line) - -class WebSocketApp(object): - """ - Higher level of APIs are provided. - The interface is like JavaScript WebSocket object. - """ - def __init__(self, url, - on_open = None, on_message = None, on_error = None, - on_close = None, keep_running = True, get_mask_key = None): - """ - url: websocket url. - on_open: callable object which is called at opening websocket. - this function has one argument. The arugment is this class object. - on_message: callbale object which is called when recieved data. - on_message has 2 arguments. - The 1st arugment is this class object. - The passing 2nd arugment is utf-8 string which we get from the server. - on_error: callable object which is called when we get error. - on_error has 2 arguments. - The 1st arugment is this class object. - The passing 2nd arugment is exception object. - on_close: callable object which is called when closed the connection. - this function has one argument. The arugment is this class object. - keep_running: a boolean flag indicating whether the app's main loop should - keep running, defaults to True - get_mask_key: a callable to produce new mask keys, see the WebSocket.set_mask_key's - docstring for more information - """ - self.url = url - self.on_open = on_open - self.on_message = on_message - self.on_error = on_error - self.on_close = on_close - self.keep_running = keep_running - self.get_mask_key = get_mask_key - self.sock = None - - def send(self, data): - """ - send message. data must be utf-8 string or unicode. - """ - if self.sock.send(data) == 0: - raise WebSocketConnectionClosedException() - - def close(self): - """ - close websocket connection. - """ - self.keep_running = False - self.sock.close() - - def run_forever(self): - """ - run event loop for WebSocket framework. - This loop is infinite loop and is alive during websocket is available. - """ - if self.sock: - raise WebSocketException("socket is already opened") - try: - self.sock = WebSocket(self.get_mask_key) - self.sock.connect(self.url) - self._run_with_no_err(self.on_open) - while self.keep_running: - data = self.sock.recv() - if data is None: - break - self._run_with_no_err(self.on_message, data) - except Exception, e: - self._run_with_no_err(self.on_error, e) - finally: - self.sock.close() - self._run_with_no_err(self.on_close) - self.sock = None - - def _run_with_no_err(self, callback, *args): - if callback: - try: - callback(self, *args) - except Exception, e: - if logger.isEnabledFor(logging.DEBUG): - logger.error(e) - - -if __name__ == "__main__": - enableTrace(True) - ws = create_connection("ws://echo.websocket.org/") - print "Sending 'Hello, World'..." - ws.send("Hello, World") - print "Sent" - print "Receiving..." - result = ws.recv() - print "Received '%s'" % result - ws.close() |