about summary refs log tree commit diff
diff options
context:
space:
mode:
authoreeeee <eeeee@qwe123.info>2015-02-07 14:15:19 -0800
committerdef <dennis@felsin9.de>2015-04-19 16:05:13 +0200
commit424ce4987ced7deda3e355b7b6373680bf506646 (patch)
tree239537b1938ac18c6542a05088bc26c6a2860408
parent9bbe115c522835c34c29196f2595c29c6bf00701 (diff)
downloadzcatch-424ce4987ced7deda3e355b7b6373680bf506646.tar.gz
zcatch-424ce4987ced7deda3e355b7b6373680bf506646.zip
added libwebsockets source code
-rw-r--r--src/engine/external/libwebsockets/LICENSE526
-rw-r--r--src/engine/external/libwebsockets/alloc.c30
-rw-r--r--src/engine/external/libwebsockets/base64-decode.c185
-rw-r--r--src/engine/external/libwebsockets/config.h174
-rw-r--r--src/engine/external/libwebsockets/context.c337
-rw-r--r--src/engine/external/libwebsockets/extension-deflate-frame.c288
-rw-r--r--src/engine/external/libwebsockets/extension-deflate-frame.h25
-rw-r--r--src/engine/external/libwebsockets/extension-deflate-stream.c166
-rw-r--r--src/engine/external/libwebsockets/extension-deflate-stream.h20
-rw-r--r--src/engine/external/libwebsockets/extension.c208
-rw-r--r--src/engine/external/libwebsockets/getifaddrs.h76
-rw-r--r--src/engine/external/libwebsockets/handshake.c232
-rw-r--r--src/engine/external/libwebsockets/huftable.h530
-rw-r--r--src/engine/external/libwebsockets/lextable-strings.h86
-rw-r--r--src/engine/external/libwebsockets/lextable.h745
-rw-r--r--src/engine/external/libwebsockets/libwebsockets.c850
-rw-r--r--src/engine/external/libwebsockets/libwebsockets.h1371
-rw-r--r--src/engine/external/libwebsockets/lws-plat-unix.c442
-rw-r--r--src/engine/external/libwebsockets/output.c606
-rw-r--r--src/engine/external/libwebsockets/parsers.c1015
-rw-r--r--src/engine/external/libwebsockets/pollfd.c293
-rwxr-xr-xsrc/engine/external/libwebsockets/private-libwebsockets.h1211
-rw-r--r--src/engine/external/libwebsockets/server-handshake.c274
-rw-r--r--src/engine/external/libwebsockets/server.c1162
-rw-r--r--src/engine/external/libwebsockets/service.c636
-rw-r--r--src/engine/external/libwebsockets/sha-1.c301
26 files changed, 11789 insertions, 0 deletions
diff --git a/src/engine/external/libwebsockets/LICENSE b/src/engine/external/libwebsockets/LICENSE
new file mode 100644
index 00000000..7c898655
--- /dev/null
+++ b/src/engine/external/libwebsockets/LICENSE
@@ -0,0 +1,526 @@
+Libwebsockets and included programs are provided under the terms of the GNU
+Library General Public License (LGPL) 2.1, with the following exceptions:
+
+1) Static linking of programs with the libwebsockets library does not
+constitute a derivative work and does not require the author to provide 
+source code for the program, use the shared libwebsockets libraries, or
+link their program against a user-supplied version of libwebsockets.
+
+If you link the program to a modified version of libwebsockets, then the
+changes to libwebsockets must be provided under the terms of the LGPL in
+sections 1, 2, and 4.
+
+2) You do not have to provide a copy of the libwebsockets license with
+programs that are linked to the libwebsockets library, nor do you have to
+identify the libwebsockets license in your program or documentation as
+required by section 6 of the LGPL.
+
+However, programs must still identify their use of libwebsockets. The
+following example statement can be included in user documentation to
+satisfy this requirement:
+
+"[program] is based in part on the work of the libwebsockets  project
+(http://libwebsockets.org)"
+
+                  GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 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.
+
+[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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  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/src/engine/external/libwebsockets/alloc.c b/src/engine/external/libwebsockets/alloc.c
new file mode 100644
index 00000000..3bc5260e
--- /dev/null
+++ b/src/engine/external/libwebsockets/alloc.c
@@ -0,0 +1,30 @@
+#include "private-libwebsockets.h"
+
+static void *_realloc(void *ptr, size_t size)
+{
+	if (size)
+		return realloc(ptr, size);
+	else if (ptr)
+		free(ptr);
+	return NULL;
+}
+
+void *(*_lws_realloc)(void *ptr, size_t size) = _realloc;
+
+void *lws_realloc(void *ptr, size_t size)
+{
+	return _lws_realloc(ptr, size);
+}
+
+void *lws_zalloc(size_t size)
+{
+	void *ptr = _lws_realloc(NULL, size);
+	if (ptr)
+		memset(ptr, 0, size);
+	return ptr;
+}
+
+void lws_set_allocator(void *(*cb)(void *ptr, size_t size))
+{
+	_lws_realloc = cb;
+}
diff --git a/src/engine/external/libwebsockets/base64-decode.c b/src/engine/external/libwebsockets/base64-decode.c
new file mode 100644
index 00000000..92501b03
--- /dev/null
+++ b/src/engine/external/libwebsockets/base64-decode.c
@@ -0,0 +1,185 @@
+/*
+ * This code originally came from here
+ *
+ * http://base64.sourceforge.net/b64.c
+ *
+ * with the following license:
+ *
+ * LICENCE:        Copyright (c) 2001 Bob Trower, Trantor Standard Systems Inc.
+ *
+ *                Permission is hereby granted, free of charge, to any person
+ *                obtaining a copy of this software and associated
+ *                documentation files (the "Software"), to deal in the
+ *                Software without restriction, including without limitation
+ *                the rights to use, copy, modify, merge, publish, distribute,
+ *                sublicense, and/or sell copies of the Software, and to
+ *                permit persons to whom the Software is furnished to do so,
+ *                subject to the following conditions:
+ *
+ *                The above copyright notice and this permission notice shall
+ *                be included in all copies or substantial portions of the
+ *                Software.
+ *
+ *                THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ *                KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ *                WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ *                PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
+ *                OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ *                OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ *                OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ *                SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * VERSION HISTORY:
+ *               Bob Trower 08/04/01 -- Create Version 0.00.00B
+ *
+ * I cleaned it up quite a bit to match the (linux kernel) style of the rest
+ * of libwebsockets; this version is under LGPL2 like the rest of libwebsockets
+ * since he explictly allows sublicensing, but I give the URL above so you can
+ * get the original with Bob's super-liberal terms directly if you prefer.
+ */
+
+
+#include <stdio.h>
+#include <string.h>
+#include "private-libwebsockets.h"
+
+static const char encode[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+			     "abcdefghijklmnopqrstuvwxyz0123456789+/";
+static const char decode[] = "|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW"
+			     "$$$$$$XYZ[\\]^_`abcdefghijklmnopq";
+
+LWS_VISIBLE int
+lws_b64_encode_string(const char *in, int in_len, char *out, int out_size)
+{
+	unsigned char triple[3];
+	int i;
+	int len;
+	int line = 0;
+	int done = 0;
+
+	while (in_len) {
+		len = 0;
+		for (i = 0; i < 3; i++) {
+			if (in_len) {
+				triple[i] = *in++;
+				len++;
+				in_len--;
+			} else
+				triple[i] = 0;
+		}
+
+		if (done + 4 >= out_size)
+			return -1;
+
+		*out++ = encode[triple[0] >> 2];
+		*out++ = encode[((triple[0] & 0x03) << 4) |
+					     ((triple[1] & 0xf0) >> 4)];
+		*out++ = (len > 1 ? encode[((triple[1] & 0x0f) << 2) |
+					     ((triple[2] & 0xc0) >> 6)] : '=');
+		*out++ = (len > 2 ? encode[triple[2] & 0x3f] : '=');
+
+		done += 4;
+		line += 4;
+	}
+
+	if (done + 1 >= out_size)
+		return -1;
+
+	*out++ = '\0';
+
+	return done;
+}
+
+/*
+ * returns length of decoded string in out, or -1 if out was too small
+ * according to out_size
+ */
+
+LWS_VISIBLE int
+lws_b64_decode_string(const char *in, char *out, int out_size)
+{
+	int len;
+	int i;
+	int done = 0;
+	unsigned char v;
+	unsigned char quad[4];
+
+	while (*in) {
+
+		len = 0;
+		for (i = 0; i < 4 && *in; i++) {
+
+			v = 0;
+			while (*in && !v) {
+
+				v = *in++;
+				v = (v < 43 || v > 122) ? 0 : decode[v - 43];
+				if (v)
+					v = (v == '$') ? 0 : v - 61;
+				if (*in) {
+					len++;
+					if (v)
+						quad[i] = v - 1;
+				} else
+					quad[i] = 0;
+			}
+		}
+
+		if (out_size < (done + len - 1))
+			/* out buffer is too small */
+			return -1;
+
+		if (len >= 2)
+			*out++ = quad[0] << 2 | quad[1] >> 4;
+		if (len >= 3)
+			*out++ = quad[1] << 4 | quad[2] >> 2;
+		if (len >= 4)
+			*out++ = ((quad[2] << 6) & 0xc0) | quad[3];
+
+		done += len - 1;
+	}
+
+	if (done + 1 >= out_size)
+		return -1;
+
+	*out++ = '\0';
+
+	return done;
+}
+
+int
+lws_b64_selftest(void)
+{
+	char buf[64];
+	int n;
+	int test;
+	static const char * const plaintext[] = {
+		"sanity check base 64"
+	};
+	static const char * const coded[] = {
+		"c2FuaXR5IGNoZWNrIGJhc2UgNjQ="
+	};
+
+	for (test = 0; test < sizeof plaintext / sizeof(plaintext[0]); test++) {
+
+		buf[sizeof(buf) - 1] = '\0';
+		n = lws_b64_encode_string(plaintext[test],
+				      strlen(plaintext[test]), buf, sizeof buf);
+		if (n != strlen(coded[test]) || strcmp(buf, coded[test])) {
+			lwsl_err("Failed lws_b64 encode selftest "
+					   "%d result '%s' %d\n", test, buf, n);
+			return -1;
+		}
+
+		buf[sizeof(buf) - 1] = '\0';
+		n = lws_b64_decode_string(coded[test], buf, sizeof buf);
+		if (n != strlen(plaintext[test]) ||
+						 strcmp(buf, plaintext[test])) {
+			lwsl_err("Failed lws_b64 decode selftest "
+					   "%d result '%s' %d\n", test, buf, n);
+			return -1;
+		}
+	}
+
+	return 0;
+}
diff --git a/src/engine/external/libwebsockets/config.h b/src/engine/external/libwebsockets/config.h
new file mode 100644
index 00000000..617c897b
--- /dev/null
+++ b/src/engine/external/libwebsockets/config.h
@@ -0,0 +1,174 @@
+/* config.h.in.  Generated from configure.ac by autoheader.  */
+
+#ifndef WIN32
+/* #undef _DEBUG */
+#endif
+
+/* Define to 1 to use CyaSSL as a replacement for OpenSSL. 
+ * LWS_OPENSSL_SUPPORT needs to be set also for this to work. */
+/* #undef USE_CYASSL */
+
+/* The Libwebsocket version */
+#define LWS_LIBRARY_VERSION "1.3"
+
+/* The current git commit hash that we're building from */
+#define LWS_BUILD_HASH "080e6dd"
+
+/* Build with OpenSSL support */
+/* #undef LWS_OPENSSL_SUPPORT */
+
+/* The client should load and trust CA root certs it finds in the OS */
+/* #undef LWS_SSL_CLIENT_USE_OS_CA_CERTS */
+
+/* Sets the path where the client certs should be installed. */
+#define LWS_OPENSSL_CLIENT_CERTS "../share"
+
+/* Turn off websocket extensions */
+/* #undef LWS_NO_EXTENSIONS */
+
+/* Enable libev io loop */
+/* #undef LWS_USE_LIBEV */
+
+/* Build with support for ipv6 */
+/* #undef LWS_USE_IPV6 */
+
+/* Build with support for HTTP2 */
+/* #undef LWS_USE_HTTP2 */
+
+/* Turn on latency measuring code */
+/* #undef LWS_LATENCY */
+
+/* Don't build the daemonizeation api */
+#define LWS_NO_DAEMONIZE
+
+/* Build without server support */
+/* #undef LWS_NO_SERVER */
+
+/* Build without client support */
+#define LWS_NO_CLIENT
+
+/* If we should compile with MinGW support */
+/* #undef LWS_MINGW_SUPPORT */
+
+/* Use the BSD getifaddrs that comes with libwebsocket, for uclibc support */
+/* #undef LWS_BUILTIN_GETIFADDRS */
+
+/* Define to 1 if you have the `bzero' function. */
+#define HAVE_BZERO
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H
+
+/* Define to 1 if you have the `fork' function. */
+#define HAVE_FORK
+
+/* Define to 1 if you have the `getenv’ function. */
+#define HAVE_GETENV
+
+/* Define to 1 if you have the <in6addr.h> header file. */
+/* #undef HAVE_IN6ADDR_H */
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H
+
+/* Define to 1 if you have the `ssl' library (-lssl). */
+/* #undef HAVE_LIBSSL */
+
+/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
+   to 0 otherwise. */
+#define HAVE_MALLOC
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H
+
+/* Define to 1 if you have the `memset' function. */
+#define HAVE_MEMSET
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H
+
+/* Define to 1 if your system has a GNU libc compatible `realloc' function,
+   and to 0 otherwise. */
+#define HAVE_REALLOC
+
+/* Define to 1 if you have the `socket' function. */
+#define HAVE_SOCKET
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H
+
+/* Define to 1 if you have the `strerror' function. */
+#define HAVE_STRERROR
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/prctl.h> header file. */
+/* #undef HAVE_SYS_PRCTL_H */
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H
+
+/* Define to 1 if you have the `vfork' function. */
+#define HAVE_VFORK
+
+/* Define to 1 if you have the <vfork.h> header file. */
+/* #undef HAVE_VFORK_H */
+
+/* Define to 1 if `fork' works. */
+#define HAVE_WORKING_FORK
+
+/* Define to 1 if `vfork' works. */
+#define HAVE_WORKING_VFORK
+
+/* Define to 1 if you have the <zlib.h> header file. */
+#define HAVE_ZLIB_H
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+   */
+#undef LT_OBJDIR // We're not using libtool
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS
+
+/* Version number of package */
+#define VERSION
+
+/* Define to rpl_malloc if the replacement function should be used. */
+/* #undef malloc */
+
+/* Define to `int' if <sys/types.h> does not define. */
+/* #undef pid_t */
+
+/* Define to rpl_realloc if the replacement function should be used. */
+/* #undef realloc */
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+/* Define to 1 if we have getifaddrs */
+#define HAVE_GETIFADDRS
+
+/* Define as `fork' if `vfork' does not work. */
+/* #undef vfork */
+
+/* Define if the inline keyword doesn't exist. */
+/* #undef inline */
diff --git a/src/engine/external/libwebsockets/context.c b/src/engine/external/libwebsockets/context.c
new file mode 100644
index 00000000..2ea9c60d
--- /dev/null
+++ b/src/engine/external/libwebsockets/context.c
@@ -0,0 +1,337 @@
+/*
+ * libwebsockets - small server side websockets and web server implementation
+ *
+ * Copyright (C) 2010-2014 Andy Green <andy@warmcat.com>
+ *
+ *  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:
+ *  version 2.1 of the License.
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston,
+ *  MA  02110-1301  USA
+ */
+
+#include "private-libwebsockets.h"
+
+#ifndef LWS_BUILD_HASH
+#define LWS_BUILD_HASH "unknown-build-hash"
+#endif
+
+static const char *library_version = LWS_LIBRARY_VERSION " " LWS_BUILD_HASH;
+
+/**
+ * lws_get_library_version: get version and git hash library built from
+ *
+ *	returns a const char * to a string like "1.1 178d78c"
+ *	representing the library version followed by the git head hash it
+ *	was built from
+ */
+
+LWS_VISIBLE const char *
+lws_get_library_version(void)
+{
+	return library_version;
+}
+
+/**
+ * libwebsocket_create_context() - Create the websocket handler
+ * @info:	pointer to struct with parameters
+ *
+ *	This function creates the listening socket (if serving) and takes care
+ *	of all initialization in one step.
+ *
+ *	After initialization, it returns a struct libwebsocket_context * that
+ *	represents this server.  After calling, user code needs to take care
+ *	of calling libwebsocket_service() with the context pointer to get the
+ *	server's sockets serviced.  This must be done in the same process
+ *	context as the initialization call.
+ *
+ *	The protocol callback functions are called for a handful of events
+ *	including http requests coming in, websocket connections becoming
+ *	established, and data arriving; it's also called periodically to allow
+ *	async transmission.
+ *
+ *	HTTP requests are sent always to the FIRST protocol in @protocol, since
+ *	at that time websocket protocol has not been negotiated.  Other
+ *	protocols after the first one never see any HTTP callack activity.
+ *
+ *	The server created is a simple http server by default; part of the
+ *	websocket standard is upgrading this http connection to a websocket one.
+ *
+ *	This allows the same server to provide files like scripts and favicon /
+ *	images or whatever over http and dynamic data over websockets all in
+ *	one place; they're all handled in the user callback.
+ */
+
+LWS_VISIBLE struct libwebsocket_context *
+libwebsocket_create_context(struct lws_context_creation_info *info)
+{
+	struct libwebsocket_context *context = NULL;
+	char *p;
+
+	int pid_daemon = get_daemonize_pid();
+
+	lwsl_notice("Initial logging level %d\n", log_level);
+	lwsl_notice("Library version: %s\n", library_version);
+#ifdef LWS_USE_IPV6
+	if (!(info->options & LWS_SERVER_OPTION_DISABLE_IPV6))
+		lwsl_notice("IPV6 compiled in and enabled\n");
+	else
+		lwsl_notice("IPV6 compiled in but disabled\n");
+#else
+	lwsl_notice("IPV6 not compiled in\n");
+#endif
+	lws_feature_status_libev(info);
+	lwsl_info(" LWS_MAX_HEADER_LEN: %u\n", LWS_MAX_HEADER_LEN);
+	lwsl_info(" LWS_MAX_PROTOCOLS: %u\n", LWS_MAX_PROTOCOLS);
+
+	lwsl_info(" SPEC_LATEST_SUPPORTED: %u\n", SPEC_LATEST_SUPPORTED);
+	lwsl_info(" AWAITING_TIMEOUT: %u\n", AWAITING_TIMEOUT);
+	lwsl_info(" SYSTEM_RANDOM_FILEPATH: '%s'\n", SYSTEM_RANDOM_FILEPATH);
+	lwsl_info(" LWS_MAX_ZLIB_CONN_BUFFER: %u\n", LWS_MAX_ZLIB_CONN_BUFFER);
+
+	if (lws_plat_context_early_init())
+		return NULL;
+
+	context = lws_zalloc(sizeof(struct libwebsocket_context));
+	if (!context) {
+		lwsl_err("No memory for websocket context\n");
+		return NULL;
+	}
+
+	if (pid_daemon) {
+		context->started_with_parent = pid_daemon;
+		lwsl_notice(" Started with daemon pid %d\n", pid_daemon);
+	}
+
+	context->listen_service_extraseen = 0;
+	context->protocols = info->protocols;
+	context->token_limits = info->token_limits;
+	context->listen_port = info->port;
+	context->http_proxy_port = 0;
+	context->http_proxy_address[0] = '\0';
+	context->options = info->options;
+	context->iface = info->iface;
+	context->ka_time = info->ka_time;
+	context->ka_interval = info->ka_interval;
+	context->ka_probes = info->ka_probes;
+
+	/* to reduce this allocation, */
+	context->max_fds = getdtablesize();
+	lwsl_notice(" static allocation: %u + (%u x %u fds) = %u bytes\n",
+		sizeof(struct libwebsocket_context),
+		sizeof(struct libwebsocket_pollfd) +
+					sizeof(struct libwebsocket *),
+		context->max_fds,
+		sizeof(struct libwebsocket_context) +
+		((sizeof(struct libwebsocket_pollfd) +
+					sizeof(struct libwebsocket *)) *
+							     context->max_fds));
+
+	context->fds = lws_zalloc(sizeof(struct libwebsocket_pollfd) *
+				  context->max_fds);
+	if (context->fds == NULL) {
+		lwsl_err("Unable to allocate fds array for %d connections\n",
+							      context->max_fds);
+		lws_free(context);
+		return NULL;
+	}
+
+	context->lws_lookup = lws_zalloc(sizeof(struct libwebsocket *) * context->max_fds);
+	if (context->lws_lookup == NULL) {
+		lwsl_err(
+		  "Unable to allocate lws_lookup array for %d connections\n",
+							      context->max_fds);
+		lws_free(context->fds);
+		lws_free(context);
+		return NULL;
+	}
+
+	if (lws_plat_init_fd_tables(context)) {
+		lws_free(context->lws_lookup);
+		lws_free(context->fds);
+		lws_free(context);
+		return NULL;
+	}
+
+	lws_context_init_extensions(info, context);
+
+	context->user_space = info->user;
+
+	strcpy(context->canonical_hostname, "unknown");
+
+	lws_server_get_canonical_hostname(context, info);
+
+	/* split the proxy ads:port if given */
+
+	if (info->http_proxy_address) {
+		strncpy(context->http_proxy_address, info->http_proxy_address,
+				      sizeof(context->http_proxy_address) - 1);
+		context->http_proxy_address[
+				sizeof(context->http_proxy_address) - 1] = '\0';
+		context->http_proxy_port = info->http_proxy_port;
+	} else {
+#ifdef HAVE_GETENV
+		p = getenv("http_proxy");
+		if (p) {
+			strncpy(context->http_proxy_address, p,
+				       sizeof(context->http_proxy_address) - 1);
+			context->http_proxy_address[
+				sizeof(context->http_proxy_address) - 1] = '\0';
+
+			p = strchr(context->http_proxy_address, ':');
+			if (p == NULL) {
+				lwsl_err("http_proxy needs to be ads:port\n");
+				goto bail;
+			}
+			*p = '\0';
+			context->http_proxy_port = atoi(p + 1);
+		}
+#endif
+	}
+
+	if (context->http_proxy_address[0])
+		lwsl_notice(" Proxy %s:%u\n",
+				context->http_proxy_address,
+						      context->http_proxy_port);
+
+	lwsl_notice(
+		" per-conn mem: %u + %u headers + protocol rx buf\n",
+				sizeof(struct libwebsocket),
+					      sizeof(struct allocated_headers));
+
+	if (lws_context_init_server_ssl(info, context))
+		goto bail;
+
+	if (lws_context_init_client_ssl(info, context))
+		goto bail;
+
+	if (lws_context_init_server(info, context))
+		goto bail;
+
+	/*
+	 * drop any root privs for this process
+	 * to listen on port < 1023 we would have needed root, but now we are
+	 * listening, we don't want the power for anything else
+	 */
+	lws_plat_drop_app_privileges(info);
+
+	/* initialize supported protocols */
+
+	for (context->count_protocols = 0;
+		info->protocols[context->count_protocols].callback;
+						   context->count_protocols++) {
+
+		lwsl_parser("  Protocol: %s\n",
+				info->protocols[context->count_protocols].name);
+
+		info->protocols[context->count_protocols].owning_server =
+									context;
+		info->protocols[context->count_protocols].protocol_index =
+						       context->count_protocols;
+
+		/*
+		 * inform all the protocols that they are doing their one-time
+		 * initialization if they want to
+		 */
+		info->protocols[context->count_protocols].callback(context,
+			       NULL, LWS_CALLBACK_PROTOCOL_INIT, NULL, NULL, 0);
+	}
+
+	/*
+	 * give all extensions a chance to create any per-context
+	 * allocations they need
+	 */
+
+	if (info->port != CONTEXT_PORT_NO_LISTEN) {
+		if (lws_ext_callback_for_each_extension_type(context, NULL,
+				LWS_EXT_CALLBACK_SERVER_CONTEXT_CONSTRUCT,
+								   NULL, 0) < 0)
+			goto bail;
+	} else
+		if (lws_ext_callback_for_each_extension_type(context, NULL,
+				LWS_EXT_CALLBACK_CLIENT_CONTEXT_CONSTRUCT,
+								   NULL, 0) < 0)
+			goto bail;
+
+	return context;
+
+bail:
+	libwebsocket_context_destroy(context);
+	return NULL;
+}
+
+/**
+ * libwebsocket_context_destroy() - Destroy the websocket context
+ * @context:	Websocket context
+ *
+ *	This function closes any active connections and then frees the
+ *	context.  After calling this, any further use of the context is
+ *	undefined.
+ */
+LWS_VISIBLE void
+libwebsocket_context_destroy(struct libwebsocket_context *context)
+{
+	int n;
+	struct libwebsocket_protocols *protocol = context->protocols;
+
+	lwsl_notice("%s\n", __func__);
+
+#ifdef LWS_LATENCY
+	if (context->worst_latency_info[0])
+		lwsl_notice("Worst latency: %s\n", context->worst_latency_info);
+#endif
+
+	for (n = 0; n < context->fds_count; n++) {
+		struct libwebsocket *wsi =
+					context->lws_lookup[context->fds[n].fd];
+		if (!wsi)
+			continue;
+		libwebsocket_close_and_free_session(context,
+			wsi, LWS_CLOSE_STATUS_NOSTATUS /* no protocol close */);
+		n--;
+	}
+
+	/*
+	 * give all extensions a chance to clean up any per-context
+	 * allocations they might have made
+	 */
+	if (context->listen_port != CONTEXT_PORT_NO_LISTEN) {
+		if (lws_ext_callback_for_each_extension_type(context, NULL,
+			 LWS_EXT_CALLBACK_SERVER_CONTEXT_DESTRUCT, NULL, 0) < 0)
+			return;
+	} else
+		if (lws_ext_callback_for_each_extension_type(context, NULL,
+			 LWS_EXT_CALLBACK_CLIENT_CONTEXT_DESTRUCT, NULL, 0) < 0)
+			return;
+
+	/*
+	 * inform all the protocols that they are done and will have no more
+	 * callbacks
+	 */
+
+	while (protocol->callback) {
+		protocol->callback(context, NULL, LWS_CALLBACK_PROTOCOL_DESTROY,
+				NULL, NULL, 0);
+		protocol++;
+	}
+
+	lws_plat_context_early_destroy(context);
+
+	lws_ssl_context_destroy(context);
+
+	lws_free(context->fds);
+	lws_free(context->lws_lookup);
+
+	lws_plat_context_late_destroy(context);
+
+	lws_free(context);
+}
diff --git a/src/engine/external/libwebsockets/extension-deflate-frame.c b/src/engine/external/libwebsockets/extension-deflate-frame.c
new file mode 100644
index 00000000..13b2b8de
--- /dev/null
+++ b/src/engine/external/libwebsockets/extension-deflate-frame.c
@@ -0,0 +1,288 @@
+#include "private-libwebsockets.h"
+#include "extension-deflate-frame.h"
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#define LWS_ZLIB_WINDOW_BITS 15
+#define LWS_ZLIB_MEMLEVEL 8
+
+int lws_extension_callback_deflate_frame(
+		struct libwebsocket_context *context,
+		struct libwebsocket_extension *ext,
+		struct libwebsocket *wsi,
+		enum libwebsocket_extension_callback_reasons reason,
+		void *user, void *in, size_t len)
+{
+	struct lws_ext_deflate_frame_conn *conn =
+				     (struct lws_ext_deflate_frame_conn *)user;
+	struct lws_tokens *eff_buf = (struct lws_tokens *)in;
+	size_t current_payload, remaining_payload, total_payload;
+	int n;
+	size_t len_so_far;
+
+	switch (reason) {
+
+	/*
+	 * for deflate-frame, both client and server sides act the same
+	 */
+
+	case LWS_EXT_CALLBACK_CLIENT_CONSTRUCT:
+	case LWS_EXT_CALLBACK_CONSTRUCT:
+		conn->zs_in.zalloc = conn->zs_out.zalloc = Z_NULL;
+		conn->zs_in.zfree = conn->zs_out.zfree = Z_NULL;
+		conn->zs_in.opaque = conn->zs_out.opaque = Z_NULL;
+		n = inflateInit2(&conn->zs_in, -LWS_ZLIB_WINDOW_BITS);
+		if (n != Z_OK) {
+			lwsl_ext("deflateInit returned %d\n", n);
+			return 1;
+		}
+		n = deflateInit2(&conn->zs_out,
+				 (context->listen_port ?
+					DEFLATE_FRAME_COMPRESSION_LEVEL_SERVER :
+					DEFLATE_FRAME_COMPRESSION_LEVEL_CLIENT),
+				 Z_DEFLATED,
+				 -LWS_ZLIB_WINDOW_BITS, LWS_ZLIB_MEMLEVEL,
+				 Z_DEFAULT_STRATEGY);
+		if (n != Z_OK) {
+			lwsl_ext("deflateInit2 returned %d\n", n);
+			return 1;
+		}
+		conn->buf_pre_used = 0;
+		conn->buf_pre_length = 0;
+		conn->buf_in_length = sizeof(conn->buf_in);
+		conn->buf_out_length = sizeof(conn->buf_out);
+		conn->compressed_out = 0;
+		conn->buf_pre = NULL;
+		conn->buf_in = lws_malloc(LWS_SEND_BUFFER_PRE_PADDING +
+					  conn->buf_in_length +
+					  LWS_SEND_BUFFER_POST_PADDING);
+		if (!conn->buf_in)
+			goto bail;
+		conn->buf_out = lws_malloc(LWS_SEND_BUFFER_PRE_PADDING +
+					   conn->buf_out_length +
+					   LWS_SEND_BUFFER_POST_PADDING);
+		if (!conn->buf_out)
+			goto bail;
+		lwsl_ext("zlibs constructed\n");
+		break;
+bail:
+		lwsl_err("Out of mem\n");
+		(void)inflateEnd(&conn->zs_in);
+		(void)deflateEnd(&conn->zs_out);
+		return -1;
+
+	case LWS_EXT_CALLBACK_DESTROY:
+		lws_free(conn->buf_pre);
+		lws_free(conn->buf_in);
+		lws_free(conn->buf_out);
+		conn->buf_pre_used = 0;
+		conn->buf_pre_length = 0;
+		conn->buf_in_length = 0;
+		conn->buf_out_length = 0;
+		conn->compressed_out = 0;
+		(void)inflateEnd(&conn->zs_in);
+		(void)deflateEnd(&conn->zs_out);
+		lwsl_ext("zlibs destructed\n");
+		break;
+
+	case LWS_EXT_CALLBACK_PAYLOAD_RX:
+		if (!(wsi->u.ws.rsv & 0x40))
+			return 0;
+
+		/*
+		 * inflate the incoming payload
+		 */
+		current_payload = eff_buf->token_len;
+
+		remaining_payload = wsi->u.ws.rx_packet_length;
+		if (remaining_payload) {
+			total_payload = conn->buf_pre_used +
+					current_payload +
+					remaining_payload;
+
+			if (conn->buf_pre_length < total_payload) {
+				conn->buf_pre_length = total_payload;
+				lws_free(conn->buf_pre);
+				conn->buf_pre = lws_malloc(total_payload + 4);
+				if (!conn->buf_pre) {
+					lwsl_err("Out of memory\n");
+					return -1;
+				}
+			}
+
+			memcpy(conn->buf_pre + conn->buf_pre_used,
+					      eff_buf->token, current_payload);
+			conn->buf_pre_used += current_payload;
+
+			eff_buf->token = NULL;
+			eff_buf->token_len = 0;
+
+			return 0;
+		}
+		if (conn->buf_pre_used) {
+			total_payload = conn->buf_pre_used +
+					current_payload;
+
+			memcpy(conn->buf_pre + conn->buf_pre_used,
+					      eff_buf->token, current_payload);
+			conn->buf_pre_used = 0;
+
+			conn->zs_in.next_in = conn->buf_pre;
+		} else {
+			total_payload = current_payload;
+
+			conn->zs_in.next_in = (unsigned char *)eff_buf->token;
+		}
+
+		conn->zs_in.next_in[total_payload + 0] = 0;
+		conn->zs_in.next_in[total_payload + 1] = 0;
+		conn->zs_in.next_in[total_payload + 2] = 0xff;
+		conn->zs_in.next_in[total_payload + 3] = 0xff;
+
+		conn->zs_in.avail_in = total_payload + 4;
+
+		conn->zs_in.next_out =
+				conn->buf_in + LWS_SEND_BUFFER_PRE_PADDING;
+		conn->zs_in.avail_out = conn->buf_in_length;
+
+		while (1) {
+			n = inflate(&conn->zs_in, Z_SYNC_FLUSH);
+			switch (n) {
+			case Z_NEED_DICT:
+			case Z_STREAM_ERROR:
+			case Z_DATA_ERROR:
+			case Z_MEM_ERROR:
+				/*
+				 * screwed.. close the connection...
+				 * we will get a destroy callback to take care
+				 * of closing nicely
+				 */
+				lwsl_info("zlib error inflate %d: %s\n",
+							   n, conn->zs_in.msg);
+				return -1;
+			}
+
+			if (conn->zs_in.avail_out)
+				break;
+
+			len_so_far = conn->zs_in.next_out -
+				(conn->buf_in + LWS_SEND_BUFFER_PRE_PADDING);
+
+			conn->buf_in_length *= 2;
+			if (conn->buf_in_length > LWS_MAX_ZLIB_CONN_BUFFER) {
+				lwsl_ext("zlib in buffer hit limit %u\n",
+						LWS_MAX_ZLIB_CONN_BUFFER);
+				return -1;
+			}
+			conn->buf_in = lws_realloc(conn->buf_in,
+						   LWS_SEND_BUFFER_PRE_PADDING +
+						   conn->buf_in_length +
+						   LWS_SEND_BUFFER_POST_PADDING);
+			if (!conn->buf_in) {
+				lwsl_err("Out of memory\n");
+				return -1;
+			}
+			lwsl_debug(
+				"deflate-frame ext RX did realloc to %ld\n",
+					conn->buf_in_length);
+			conn->zs_in.next_out = conn->buf_in +
+				LWS_SEND_BUFFER_PRE_PADDING + len_so_far;
+			conn->zs_in.avail_out =
+					conn->buf_in_length - len_so_far;
+		}
+
+		/* rewrite the buffer pointers and length */
+		eff_buf->token =
+			(char *)(conn->buf_in + LWS_SEND_BUFFER_PRE_PADDING);
+		eff_buf->token_len = (int)(conn->zs_in.next_out -
+				 (conn->buf_in + LWS_SEND_BUFFER_PRE_PADDING));
+
+		return 0;
+
+	case LWS_EXT_CALLBACK_PAYLOAD_TX:
+		/*
+		 * deflate the outgoing payload
+		 */
+		current_payload = eff_buf->token_len;
+
+		conn->zs_out.next_in = (unsigned char *)eff_buf->token;
+		conn->zs_out.avail_in = current_payload;
+
+		conn->zs_out.next_out =
+				conn->buf_out + LWS_SEND_BUFFER_PRE_PADDING;
+		conn->zs_out.avail_out = conn->buf_out_length;
+
+		while (1) {
+			n = deflate(&conn->zs_out, Z_SYNC_FLUSH);
+			if (n == Z_STREAM_ERROR) {
+				/*
+				 * screwed.. close the connection... we will
+				 * get a destroy callback to take care of
+				 * closing nicely
+				 */
+				lwsl_ext("zlib error deflate\n");
+
+				return -1;
+			}
+
+			if (conn->zs_out.avail_out)
+				break;
+
+			len_so_far = (conn->zs_out.next_out -
+					(conn->buf_out +
+						 LWS_SEND_BUFFER_PRE_PADDING));
+			conn->buf_out_length *= 2;
+			if (conn->buf_out_length > LWS_MAX_ZLIB_CONN_BUFFER) {
+				lwsl_ext("zlib out hit limit %u\n",
+						LWS_MAX_ZLIB_CONN_BUFFER);
+				return -1;
+			}
+			conn->buf_out = lws_realloc(conn->buf_out,
+						    LWS_SEND_BUFFER_PRE_PADDING +
+						    conn->buf_out_length +
+						    LWS_SEND_BUFFER_POST_PADDING);
+			if (!conn->buf_out) {
+				lwsl_err("Out of memory\n");
+				return -1;
+			}
+			lwsl_debug(
+				"deflate-frame ext TX did realloc to %ld\n",
+					conn->buf_in_length);
+
+			conn->zs_out.next_out = (conn->buf_out +
+				     LWS_SEND_BUFFER_PRE_PADDING + len_so_far);
+			conn->zs_out.avail_out =
+					   (conn->buf_out_length - len_so_far);
+		}
+
+		conn->compressed_out = 1;
+
+		/* rewrite the buffer pointers and length */
+		eff_buf->token = (char *)(conn->buf_out +
+						LWS_SEND_BUFFER_PRE_PADDING);
+		eff_buf->token_len = (int)(conn->zs_out.next_out -
+			    (conn->buf_out + LWS_SEND_BUFFER_PRE_PADDING)) - 4;
+
+		return 0;
+
+	case LWS_EXT_CALLBACK_PACKET_TX_PRESEND:
+		if (conn->compressed_out) {
+			conn->compressed_out = 0;
+			*((unsigned char *)eff_buf->token) |= 0x40;
+		}
+		break;
+
+	case LWS_EXT_CALLBACK_CHECK_OK_TO_PROPOSE_EXTENSION:
+		/* Avoid x-webkit-deflate-frame extension on client */
+		if (!strcmp((char *)in, "x-webkit-deflate-frame"))
+			return 1;
+		break;
+
+	default:
+		break;
+	}
+
+	return 0;
+}
+
diff --git a/src/engine/external/libwebsockets/extension-deflate-frame.h b/src/engine/external/libwebsockets/extension-deflate-frame.h
new file mode 100644
index 00000000..00a4447a
--- /dev/null
+++ b/src/engine/external/libwebsockets/extension-deflate-frame.h
@@ -0,0 +1,25 @@
+
+#include <zlib.h>
+
+#define DEFLATE_FRAME_COMPRESSION_LEVEL_SERVER 1
+#define DEFLATE_FRAME_COMPRESSION_LEVEL_CLIENT Z_DEFAULT_COMPRESSION
+
+struct lws_ext_deflate_frame_conn {
+	z_stream zs_in;
+	z_stream zs_out;
+	size_t buf_pre_used;
+	size_t buf_pre_length;
+	size_t buf_in_length;
+	size_t buf_out_length;
+	int compressed_out;
+	unsigned char *buf_pre;
+	unsigned char *buf_in;
+	unsigned char *buf_out;
+};
+
+extern int lws_extension_callback_deflate_frame(
+		struct libwebsocket_context *context,
+		struct libwebsocket_extension *ext,
+		struct libwebsocket *wsi,
+		enum libwebsocket_extension_callback_reasons reason,
+		void *user, void *in, size_t len);
diff --git a/src/engine/external/libwebsockets/extension-deflate-stream.c b/src/engine/external/libwebsockets/extension-deflate-stream.c
new file mode 100644
index 00000000..addaa2c7
--- /dev/null
+++ b/src/engine/external/libwebsockets/extension-deflate-stream.c
@@ -0,0 +1,166 @@
+#include "private-libwebsockets.h"
+#include "extension-deflate-stream.h"
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#define LWS_ZLIB_WINDOW_BITS 15
+#define LWS_ZLIB_MEMLEVEL 8
+
+int lws_extension_callback_deflate_stream(
+		struct libwebsocket_context *context,
+		struct libwebsocket_extension *ext,
+		struct libwebsocket *wsi,
+			enum libwebsocket_extension_callback_reasons reason,
+					       void *user, void *in, size_t len)
+{
+	struct lws_ext_deflate_stream_conn *conn =
+				     (struct lws_ext_deflate_stream_conn *)user;
+	int n;
+	struct lws_tokens *eff_buf = (struct lws_tokens *)in;
+
+	switch (reason) {
+
+	/*
+	 * for deflate-stream, both client and server sides act the same
+	 */
+
+	case LWS_EXT_CALLBACK_CLIENT_CONSTRUCT:
+	case LWS_EXT_CALLBACK_CONSTRUCT:
+		conn->zs_in.zalloc = conn->zs_out.zalloc = Z_NULL;
+		conn->zs_in.zfree = conn->zs_out.zfree = Z_NULL;
+		conn->zs_in.opaque = conn->zs_out.opaque = Z_NULL;
+		n = inflateInit2(&conn->zs_in, -LWS_ZLIB_WINDOW_BITS);
+		if (n != Z_OK) {
+			lwsl_err("deflateInit returned %d\n", n);
+			return 1;
+		}
+		n = deflateInit2(&conn->zs_out,
+				 DEFLATE_STREAM_COMPRESSION_LEVEL, Z_DEFLATED,
+				 -LWS_ZLIB_WINDOW_BITS, LWS_ZLIB_MEMLEVEL,
+							    Z_DEFAULT_STRATEGY);
+		if (n != Z_OK) {
+			lwsl_err("deflateInit returned %d\n", n);
+			return 1;
+		}
+		lwsl_ext("zlibs constructed\n");
+		conn->remaining_in = 0;
+		break;
+
+	case LWS_EXT_CALLBACK_DESTROY:
+		(void)inflateEnd(&conn->zs_in);
+		(void)deflateEnd(&conn->zs_out);
+		lwsl_ext("zlibs destructed\n");
+		break;
+
+	case LWS_EXT_CALLBACK_PACKET_RX_PREPARSE:
+
+		/*
+		 * inflate the incoming compressed data
+		 * Notice, length may be 0 and pointer NULL
+		 * in the case we are flushing with nothing new coming in
+		 */
+		if (conn->remaining_in) {
+			conn->zs_in.next_in = conn->buf_in;
+			conn->zs_in.avail_in = conn->remaining_in;
+			conn->remaining_in = 0;
+		} else {
+			conn->zs_in.next_in = (unsigned char *)eff_buf->token;
+			conn->zs_in.avail_in = eff_buf->token_len;
+		}
+
+		conn->zs_in.next_out = conn->buf_out;
+		conn->zs_in.avail_out = sizeof(conn->buf_out);
+
+		n = inflate(&conn->zs_in, Z_SYNC_FLUSH);
+		switch (n) {
+		case Z_NEED_DICT:
+		case Z_DATA_ERROR:
+		case Z_MEM_ERROR:
+			/*
+			 * screwed.. close the connection... we will get a
+			 * destroy callback to take care of closing nicely
+			 */
+			lwsl_err("zlib error inflate %d\n", n);
+			return -1;
+		}
+
+		/* rewrite the buffer pointers and length */
+
+		eff_buf->token = (char *)conn->buf_out;
+		eff_buf->token_len =
+			sizeof(conn->buf_out) - conn->zs_in.avail_out;
+
+		/* copy avail data if not consumed */
+		if (conn->zs_in.avail_in > 0) {
+			conn->remaining_in = conn->zs_in.avail_in;
+			memcpy(conn->buf_in, conn->zs_in.next_in,
+							conn->zs_in.avail_in);
+			return 1;
+		}
+
+		/*
+		 * if we filled the output buffer, signal that we likely have
+		 * more and need to be called again
+		 */
+
+		if (eff_buf->token_len == sizeof(conn->buf_out))
+			return 1;
+
+		/* we don't need calling again until new input data comes */
+
+		return 0;
+
+	case LWS_EXT_CALLBACK_FLUSH_PENDING_TX:
+	case LWS_EXT_CALLBACK_PACKET_TX_PRESEND:
+
+		/*
+		 * deflate the outgoing compressed data
+		 */
+
+		conn->zs_out.next_in = (unsigned char *)eff_buf->token;
+		conn->zs_out.avail_in = eff_buf->token_len;
+
+		conn->zs_out.next_out = conn->buf_out;
+		conn->zs_out.avail_out = sizeof(conn->buf_out);
+
+		n = Z_PARTIAL_FLUSH;
+		if (reason == LWS_EXT_CALLBACK_FLUSH_PENDING_TX)
+			n = Z_FULL_FLUSH;
+
+		n = deflate(&conn->zs_out, n);
+		if (n == Z_STREAM_ERROR) {
+			/*
+			 * screwed.. close the connection... we will get a
+			 * destroy callback to take care of closing nicely
+			 */
+			lwsl_ext("zlib error deflate\n");
+
+			return -1;
+		}
+
+		/* rewrite the buffer pointers and length */
+
+		eff_buf->token = (char *)conn->buf_out;
+		eff_buf->token_len =
+				sizeof(conn->buf_out) - conn->zs_out.avail_out;
+
+		/*
+		 * if we filled the output buffer, signal that we likely have
+		 * more and need to be called again... even in deflate case
+		 * we might sometimes need to spill more than came in
+		 */
+
+		if (eff_buf->token_len == sizeof(conn->buf_out))
+			return 1;
+
+		/* we don't need calling again until new input data comes */
+
+		return 0;
+
+	default:
+		break;
+	}
+
+	return 0;
+}
diff --git a/src/engine/external/libwebsockets/extension-deflate-stream.h b/src/engine/external/libwebsockets/extension-deflate-stream.h
new file mode 100644
index 00000000..fcadc07a
--- /dev/null
+++ b/src/engine/external/libwebsockets/extension-deflate-stream.h
@@ -0,0 +1,20 @@
+
+#include <zlib.h>
+
+#define DEFLATE_STREAM_CHUNK 128
+#define DEFLATE_STREAM_COMPRESSION_LEVEL 1
+
+struct lws_ext_deflate_stream_conn {
+	z_stream zs_in;
+	z_stream zs_out;
+	int remaining_in;
+	unsigned char buf_in[LWS_MAX_SOCKET_IO_BUF];
+	unsigned char buf_out[LWS_MAX_SOCKET_IO_BUF];
+};
+
+extern int lws_extension_callback_deflate_stream(
+		struct libwebsocket_context *context,
+		struct libwebsocket_extension *ext,
+		struct libwebsocket *wsi,
+		enum libwebsocket_extension_callback_reasons reason,
+					      void *user, void *in, size_t len);
diff --git a/src/engine/external/libwebsockets/extension.c b/src/engine/external/libwebsockets/extension.c
new file mode 100644
index 00000000..b7a5792b
--- /dev/null
+++ b/src/engine/external/libwebsockets/extension.c
@@ -0,0 +1,208 @@
+#include "private-libwebsockets.h"
+
+#include "extension-deflate-frame.h"
+#include "extension-deflate-stream.h"
+
+struct libwebsocket_extension libwebsocket_internal_extensions[] = {
+#ifdef LWS_EXT_DEFLATE_STREAM
+	{
+		"deflate-stream",
+		lws_extension_callback_deflate_stream,
+		sizeof(struct lws_ext_deflate_stream_conn)
+	},
+#else
+	{
+		"x-webkit-deflate-frame",
+		lws_extension_callback_deflate_frame,
+		sizeof(struct lws_ext_deflate_frame_conn)
+	},
+	{
+		"deflate-frame",
+		lws_extension_callback_deflate_frame,
+		sizeof(struct lws_ext_deflate_frame_conn)
+	},
+#endif
+	{ /* terminator */
+		NULL, NULL, 0
+	}
+};
+
+LWS_VISIBLE void
+lws_context_init_extensions(struct lws_context_creation_info *info,
+				    struct libwebsocket_context *context)
+{
+	context->extensions = info->extensions;
+	lwsl_info(" LWS_MAX_EXTENSIONS_ACTIVE: %u\n", LWS_MAX_EXTENSIONS_ACTIVE);
+}
+
+LWS_VISIBLE struct libwebsocket_extension *libwebsocket_get_internal_extensions()
+{
+	return libwebsocket_internal_extensions;
+}
+
+
+/* 0 = nobody had nonzero return, 1 = somebody had positive return, -1 = fail */
+
+int lws_ext_callback_for_each_active(struct libwebsocket *wsi, int reason,
+				void *arg, int len)
+{
+	int n, m, handled = 0;
+
+	for (n = 0; n < wsi->count_active_extensions; n++) {
+		m = wsi->active_extensions[n]->callback(
+			wsi->protocol->owning_server,
+			wsi->active_extensions[n], wsi,
+			reason,
+			wsi->active_extensions_user[n],
+			arg, len);
+		if (m < 0) {
+			lwsl_ext(
+			 "Extension '%s' failed to handle callback %d!\n",
+				      wsi->active_extensions[n]->name, reason);
+			return -1;
+		}
+		if (m > handled)
+			handled = m;
+	}
+	
+	return handled;
+}
+
+int lws_ext_callback_for_each_extension_type(
+		struct libwebsocket_context *context, struct libwebsocket *wsi,
+				int reason, void *arg, int len)
+{
+	int n = 0, m, handled = 0;
+	struct libwebsocket_extension *ext = context->extensions;
+
+	while (ext && ext->callback && !handled) {
+		m = ext->callback(context, ext, wsi, reason,
+						(void *)(long)n, arg, len);
+		if (m < 0) {
+			lwsl_ext(
+			 "Extension '%s' failed to handle callback %d!\n",
+				      wsi->active_extensions[n]->name, reason);
+			return -1;
+		}
+		if (m)
+			handled = 1;
+
+		ext++;
+		n++;
+	}
+	
+	return 0;
+}
+
+int
+lws_issue_raw_ext_access(struct libwebsocket *wsi,
+						 unsigned char *buf, size_t len)
+{
+	int ret;
+	struct lws_tokens eff_buf;
+	int m;
+	int n = 0;
+
+	eff_buf.token = (char *)buf;
+	eff_buf.token_len = len;
+
+	/*
+	 * while we have original buf to spill ourselves, or extensions report
+	 * more in their pipeline
+	 */
+
+	ret = 1;
+	while (ret == 1) {
+
+		/* default to nobody has more to spill */
+
+		ret = 0;
+
+		/* show every extension the new incoming data */
+		m = lws_ext_callback_for_each_active(wsi,
+			       LWS_EXT_CALLBACK_PACKET_TX_PRESEND, &eff_buf, 0);
+		if (m < 0)
+			return -1;
+		if (m) /* handled */
+			ret = 1;
+
+		if ((char *)buf != eff_buf.token)
+			/*
+			 * extension recreated it:
+			 * need to buffer this if not all sent
+			 */
+			wsi->u.ws.clean_buffer = 0;
+
+		/* assuming they left us something to send, send it */
+
+		if (eff_buf.token_len) {
+			n = lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
+							    eff_buf.token_len);
+			if (n < 0) {
+				lwsl_info("closing from ext access\n");
+				return -1;
+			}
+
+			/* always either sent it all or privately buffered */
+			if (wsi->u.ws.clean_buffer)
+				len = n;
+		}
+
+		lwsl_parser("written %d bytes to client\n", n);
+
+		/* no extension has more to spill?  Then we can go */
+
+		if (!ret)
+			break;
+
+		/* we used up what we had */
+
+		eff_buf.token = NULL;
+		eff_buf.token_len = 0;
+
+		/*
+		 * Did that leave the pipe choked?
+		 * Or we had to hold on to some of it?
+		 */
+
+		if (!lws_send_pipe_choked(wsi) && !wsi->truncated_send_len)
+			/* no we could add more, lets's do that */
+			continue;
+
+		lwsl_debug("choked\n");
+
+		/*
+		 * Yes, he's choked.  Don't spill the rest now get a callback
+		 * when he is ready to send and take care of it there
+		 */
+		libwebsocket_callback_on_writable(
+					     wsi->protocol->owning_server, wsi);
+		wsi->extension_data_pending = 1;
+		ret = 0;
+	}
+
+	return len;
+}
+
+int
+lws_any_extension_handled(struct libwebsocket_context *context,
+			  struct libwebsocket *wsi,
+			  enum libwebsocket_extension_callback_reasons r,
+						       void *v, size_t len)
+{
+	int n;
+	int handled = 0;
+
+	/* maybe an extension will take care of it for us */
+
+	for (n = 0; n < wsi->count_active_extensions && !handled; n++) {
+		if (!wsi->active_extensions[n]->callback)
+			continue;
+
+		handled |= wsi->active_extensions[n]->callback(context,
+			wsi->active_extensions[n], wsi,
+			r, wsi->active_extensions_user[n], v, len);
+	}
+
+	return handled;
+}
diff --git a/src/engine/external/libwebsockets/getifaddrs.h b/src/engine/external/libwebsockets/getifaddrs.h
new file mode 100644
index 00000000..da69b50e
--- /dev/null
+++ b/src/engine/external/libwebsockets/getifaddrs.h
@@ -0,0 +1,76 @@
+#if HAVE_GETIFADDRS
+#include <sys/types.h>
+#include <ifaddrs.h>
+#else
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Copyright (c) 2000 Kungliga Tekniska H�gskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $KTH: ifaddrs.hin,v 1.3 2000/12/11 00:01:13 assar Exp $ */
+
+#ifndef ifaddrs_h_7467027A95AD4B5C8DDD40FE7D973791
+#define ifaddrs_h_7467027A95AD4B5C8DDD40FE7D973791
+
+/*
+ * the interface is defined in terms of the fields below, and this is
+ * sometimes #define'd, so there seems to be no simple way of solving
+ * this and this seemed the best. */
+
+#undef ifa_dstaddr
+
+struct ifaddrs {
+	struct ifaddrs *ifa_next;
+	char *ifa_name;
+	unsigned int ifa_flags;
+	struct sockaddr *ifa_addr;
+	struct sockaddr *ifa_netmask;
+	struct sockaddr *ifa_dstaddr;
+	void *ifa_data;
+};
+
+#ifndef ifa_broadaddr
+#define ifa_broadaddr ifa_dstaddr
+#endif
+
+int getifaddrs(struct ifaddrs **);
+
+void freeifaddrs(struct ifaddrs *);
+
+#endif /* __ifaddrs_h__ */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/engine/external/libwebsockets/handshake.c b/src/engine/external/libwebsockets/handshake.c
new file mode 100644
index 00000000..856297db
--- /dev/null
+++ b/src/engine/external/libwebsockets/handshake.c
@@ -0,0 +1,232 @@
+/*
+ * libwebsockets - small server side websockets and web server implementation
+ *
+ * Copyright (C) 2010-2013 Andy Green <andy@warmcat.com>
+ *
+ *  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:
+ *  version 2.1 of the License.
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston,
+ *  MA  02110-1301  USA
+ */
+
+#include "private-libwebsockets.h"
+
+/*
+ * -04 of the protocol (actually the 80th version) has a radically different
+ * handshake.  The 04 spec gives the following idea
+ *
+ *    The handshake from the client looks as follows:
+ *
+ *      GET /chat HTTP/1.1
+ *      Host: server.example.com
+ *      Upgrade: websocket
+ *      Connection: Upgrade
+ *      Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
+ *      Sec-WebSocket-Origin: http://example.com
+ *      Sec-WebSocket-Protocol: chat, superchat
+ *	Sec-WebSocket-Version: 4
+ *
+ *  The handshake from the server looks as follows:
+ *
+ *       HTTP/1.1 101 Switching Protocols
+ *       Upgrade: websocket
+ *       Connection: Upgrade
+ *       Sec-WebSocket-Accept: me89jWimTRKTWwrS3aRrL53YZSo=
+ *       Sec-WebSocket-Nonce: AQIDBAUGBwgJCgsMDQ4PEC==
+ *       Sec-WebSocket-Protocol: chat
+ */
+
+#ifndef min
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#endif
+/*
+ * We have to take care about parsing because the headers may be split
+ * into multiple fragments.  They may contain unknown headers with arbitrary
+ * argument lengths.  So, we parse using a single-character at a time state
+ * machine that is completely independent of packet size.
+ */
+
+LWS_VISIBLE int
+libwebsocket_read(struct libwebsocket_context *context,
+		     struct libwebsocket *wsi, unsigned char *buf, size_t len)
+{
+	size_t n;
+	int body_chunk_len;
+	unsigned char *last_char;
+
+	switch (wsi->state) {
+#ifdef LWS_USE_HTTP2
+	case WSI_STATE_HTTP2_AWAIT_CLIENT_PREFACE:
+	case WSI_STATE_HTTP2_ESTABLISHED_PRE_SETTINGS:
+	case WSI_STATE_HTTP2_ESTABLISHED:
+		n = 0;
+		while (n < len) {
+			/*
+			 * we were accepting input but now we stopped doing so
+			 */
+			if (!(wsi->rxflow_change_to & LWS_RXFLOW_ALLOW)) {
+				lws_rxflow_cache(wsi, buf, n, len);
+
+				return 1;
+			}
+
+			/* account for what we're using in rxflow buffer */
+			if (wsi->rxflow_buffer)
+				wsi->rxflow_pos++;
+			if (lws_http2_parser(context, wsi, buf[n++]))
+				goto bail;
+		}
+		break;
+#endif
+http_new:
+	case WSI_STATE_HTTP:
+		wsi->hdr_parsing_completed = 0;
+		/* fallthru */
+	case WSI_STATE_HTTP_ISSUING_FILE:
+		wsi->state = WSI_STATE_HTTP_HEADERS;
+		wsi->u.hdr.parser_state = WSI_TOKEN_NAME_PART;
+		wsi->u.hdr.lextable_pos = 0;
+		/* fallthru */
+	case WSI_STATE_HTTP_HEADERS:
+		lwsl_parser("issuing %d bytes to parser\n", (int)len);
+
+		if (lws_handshake_client(wsi, &buf, len))
+			goto bail;
+
+		last_char = buf;
+		if (lws_handshake_server(context, wsi, &buf, len))
+			/* Handshake indicates this session is done. */
+			goto bail;
+
+		/* It's possible that we've exhausted our data already, but
+		 * lws_handshake_server doesn't update len for us. Figure out how
+		 * much was read, so that we can proceed appropriately: */
+		len -= (buf - last_char);
+
+		if (!wsi->hdr_parsing_completed)
+			/* More header content on the way */
+			goto read_ok;
+
+		switch (wsi->state) {
+			case WSI_STATE_HTTP:
+			case WSI_STATE_HTTP_HEADERS:
+				goto http_complete;
+			case WSI_STATE_HTTP_ISSUING_FILE:
+				goto read_ok;
+			case WSI_STATE_HTTP_BODY:
+				wsi->u.http.content_remain = wsi->u.http.content_length;
+				goto http_postbody;
+			default:
+				break;
+		}
+		break;
+
+	case WSI_STATE_HTTP_BODY:
+http_postbody:
+		while (len && wsi->u.http.content_remain) {
+			/* Copy as much as possible, up to the limit of:
+			 * what we have in the read buffer (len)
+			 * remaining portion of the POST body (content_remain)
+			 */
+			body_chunk_len = min(wsi->u.http.content_remain,len);
+			wsi->u.http.content_remain -= body_chunk_len;
+			len -= body_chunk_len;
+
+			if (wsi->protocol->callback) {
+				n = wsi->protocol->callback(
+					wsi->protocol->owning_server, wsi,
+					LWS_CALLBACK_HTTP_BODY, wsi->user_space,
+					buf, body_chunk_len);
+				if (n)
+					goto bail;
+			}
+			buf += body_chunk_len;
+
+			if (!wsi->u.http.content_remain)  {
+				/* he sent the content in time */
+				libwebsocket_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
+				if (wsi->protocol->callback) {
+					n = wsi->protocol->callback(
+						wsi->protocol->owning_server, wsi,
+						LWS_CALLBACK_HTTP_BODY_COMPLETION,
+						wsi->user_space, NULL, 0);
+					if (n)
+						goto bail;
+				}
+				goto http_complete;
+			} else
+				libwebsocket_set_timeout(wsi,
+					PENDING_TIMEOUT_HTTP_CONTENT,
+					AWAITING_TIMEOUT);
+		}
+		break;
+
+	case WSI_STATE_ESTABLISHED:
+	case WSI_STATE_AWAITING_CLOSE_ACK:
+		if (lws_handshake_client(wsi, &buf, len))
+			goto bail;
+		switch (wsi->mode) {
+		case LWS_CONNMODE_WS_SERVING:
+
+			if (libwebsocket_interpret_incoming_packet(wsi, buf, len) < 0) {
+				lwsl_info("interpret_incoming_packet has bailed\n");
+				goto bail;
+			}
+			break;
+		}
+		break;
+	default:
+		lwsl_err("libwebsocket_read: Unhandled state\n");
+		break;
+	}
+
+read_ok:
+	/* Nothing more to do for now. */
+	lwsl_debug("libwebsocket_read: read_ok\n");
+
+	return 0;
+
+http_complete:
+	lwsl_debug("libwebsocket_read: http_complete\n");
+
+	/* Did the client want to keep the HTTP connection going? */
+
+	if (wsi->u.http.connection_type == HTTP_CONNECTION_KEEP_ALIVE) {
+		lwsl_debug("libwebsocket_read: keep-alive\n");
+		wsi->state = WSI_STATE_HTTP;
+		wsi->mode = LWS_CONNMODE_HTTP_SERVING;
+
+		/* He asked for it to stay alive indefinitely */
+		libwebsocket_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
+
+		if (lws_allocate_header_table(wsi))
+			goto bail;
+
+		/* If we're (re)starting on headers, need other implied init */
+		wsi->u.hdr.ues = URIES_IDLE;
+
+		/* If we have more data, loop back around: */
+		if (len)
+			goto http_new;
+
+		return 0;
+	}
+
+bail:
+	lwsl_debug("closing connection at libwebsocket_read bail:\n");
+
+	libwebsocket_close_and_free_session(context, wsi,
+						     LWS_CLOSE_STATUS_NOSTATUS);
+
+	return -1;
+}
diff --git a/src/engine/external/libwebsockets/huftable.h b/src/engine/external/libwebsockets/huftable.h
new file mode 100644
index 00000000..385a83be
--- /dev/null
+++ b/src/engine/external/libwebsockets/huftable.h
@@ -0,0 +1,530 @@
+static unsigned char lextable[] = {
+/* pos 0000:   0 */    /* 0 */ 0x42  /* (to 0x0084 state  98) */,
+                       /* 1 */ 0x01  /* (to 0x0002 state   1) */,
+/* pos 0002:   1 */    /* 0 */ 0x5C  /* (to 0x00BA state 151) */,
+                       /* 1 */ 0x01  /* (to 0x0004 state   2) */,
+/* pos 0004:   2 */    /* 0 */ 0x66  /* (to 0x00D0 state 173) */,
+                       /* 1 */ 0x01  /* (to 0x0006 state   3) */,
+/* pos 0006:   3 */    /* 0 */ 0x74  /* (to 0x00EE state 204) */,
+                       /* 1 */ 0x01  /* (to 0x0008 state   4) */,
+/* pos 0008:   4 */    /* 0 */ 0x8C  /* (to 0x0120 state 263) */,
+                       /* 1 */ 0x01  /* (to 0x000A state   5) */,
+/* pos 000a:   5 */    /* 0 */ 0x46  /* (to 0x0096 state 113) */,
+                       /* 1 */ 0x01  /* (to 0x000C state   6) */,
+/* pos 000c:   6 */    /* 0 */ 0x75  /* (to 0x00F6 state 211) */,
+                       /* 1 */ 0x01  /* (to 0x000E state   7) */,
+/* pos 000e:   7 */    /* 0 */ 0x40  /* (to 0x008E state 104) */,
+                       /* 1 */ 0x01  /* (to 0x0010 state   8) */,
+/* pos 0010:   8 */    /* 0 */ 0x45  /* (to 0x009A state 116) */,
+                       /* 1 */ 0x01  /* (to 0x0012 state   9) */,
+/* pos 0012:   9 */    /* 0 */ 0x40  /* (to 0x0092 state 108) */,
+                       /* 1 */ 0x01  /* (to 0x0014 state  10) */,
+/* pos 0014:  10 */    /* 0 */ 0x01  /* (to 0x0016 state  11) */,
+                       /* 1 */ 0x03  /* (to 0x001A state  14) */,
+/* pos 0016:  11 */    /* 0 */ 0x01  /* (to 0x0018 state  12) */,
+                       /* 1 */ 0x5B  /* (to 0x00CC state 166) */,
+/* pos 0018:  12 */     /* terminal 0 */ 0x00,
+                        /* terminal 36 */ 0x24,
+/* pos 001a:  14 */    /* 0 */ 0x72  /* (to 0x00FE state 220) */,
+                       /* 1 */ 0x01  /* (to 0x001C state  15) */,
+/* pos 001c:  15 */    /* 0 */ 0x72  /* (to 0x0100 state 222) */,
+                       /* 1 */ 0x01  /* (to 0x001E state  16) */,
+/* pos 001e:  16 */    /* 0 */ 0x53  /* (to 0x00C4 state 158) */,
+                       /* 1 */ 0x01  /* (to 0x0020 state  17) */,
+/* pos 0020:  17 */     /* terminal 123 */ 0x7B,
+                       /* 1 */ 0x01  /* (to 0x0022 state  18) */,
+/* pos 0022:  18 */    /* 0 */ 0x6B  /* (to 0x00F8 state 216) */,
+                       /* 1 */ 0x01  /* (to 0x0024 state  19) */,
+/* pos 0024:  19 */    /* 0 */ 0x84  /* (to 0x012C state 279) */,
+                       /* 1 */ 0x01  /* (to 0x0026 state  20) */,
+/* pos 0026:  20 */    /* 0 */ 0x01  /* (to 0x0028 state  21) */,
+                       /* 1 */ 0x06  /* (to 0x0032 state  27) */,
+/* pos 0028:  21 */    /* 0 */ 0xB3  /* (to 0x018E state 377) */,
+                       /* 1 */ 0x01  /* (to 0x002A state  22) */,
+/* pos 002a:  22 */    /* 0 */ 0xC3  /* (to 0x01B0 state 414) */,
+                       /* 1 */ 0x01  /* (to 0x002C state  23) */,
+/* pos 002c:  23 */    /* 0 */ 0x01  /* (to 0x002E state  24) */,
+                       /* 1 */ 0x8C  /* (to 0x0144 state 301) */,
+/* pos 002e:  24 */    /* 0 */ 0x01  /* (to 0x0030 state  25) */,
+                       /* 1 */ 0x8A  /* (to 0x0142 state 298) */,
+/* pos 0030:  25 */     /* terminal 1 */ 0x01,
+                        /* terminal 135 */ 0x87,
+/* pos 0032:  27 */    /* 0 */ 0x8E  /* (to 0x014E state 314) */,
+                       /* 1 */ 0x01  /* (to 0x0034 state  28) */,
+/* pos 0034:  28 */    /* 0 */ 0x0F  /* (to 0x0052 state  50) */,
+                       /* 1 */ 0x01  /* (to 0x0036 state  29) */,
+/* pos 0036:  29 */    /* 0 */ 0xA4  /* (to 0x017E state 362) */,
+                       /* 1 */ 0x01  /* (to 0x0038 state  30) */,
+/* pos 0038:  30 */    /* 0 */ 0xB7  /* (to 0x01A6 state 403) */,
+                       /* 1 */ 0x01  /* (to 0x003A state  31) */,
+/* pos 003a:  31 */    /* 0 */ 0xC8  /* (to 0x01CA state 440) */,
+                       /* 1 */ 0x01  /* (to 0x003C state  32) */,
+/* pos 003c:  32 */    /* 0 */ 0x01  /* (to 0x003E state  33) */,
+                       /* 1 */ 0x0F  /* (to 0x005A state  55) */,
+/* pos 003e:  33 */    /* 0 */ 0x01  /* (to 0x0040 state  34) */,
+                       /* 1 */ 0x07  /* (to 0x004C state  46) */,
+/* pos 0040:  34 */    /* 0 */ 0x01  /* (to 0x0042 state  35) */,
+                       /* 1 */ 0x03  /* (to 0x0046 state  39) */,
+/* pos 0042:  35 */     /* terminal 254 */ 0xFE,
+                       /* 1 */ 0x01  /* (to 0x0044 state  36) */,
+/* pos 0044:  36 */     /* terminal 2 */ 0x02,
+                        /* terminal 3 */ 0x03,
+/* pos 0046:  39 */    /* 0 */ 0x01  /* (to 0x0048 state  40) */,
+                       /* 1 */ 0x02  /* (to 0x004A state  43) */,
+/* pos 0048:  40 */     /* terminal 4 */ 0x04,
+                        /* terminal 5 */ 0x05,
+/* pos 004a:  43 */     /* terminal 6 */ 0x06,
+                        /* terminal 7 */ 0x07,
+/* pos 004c:  46 */    /* 0 */ 0x01  /* (to 0x004E state  47) */,
+                       /* 1 */ 0x0E  /* (to 0x0068 state  67) */,
+/* pos 004e:  47 */    /* 0 */ 0x01  /* (to 0x0050 state  48) */,
+                       /* 1 */ 0x0C  /* (to 0x0066 state  63) */,
+/* pos 0050:  48 */     /* terminal 8 */ 0x08,
+                        /* terminal 11 */ 0x0B,
+/* pos 0052:  50 */    /* 0 */ 0xA7  /* (to 0x01A0 state 396) */,
+                       /* 1 */ 0x01  /* (to 0x0054 state  51) */,
+/* pos 0054:  51 */    /* 0 */ 0x01  /* (to 0x0056 state  52) */,
+                       /* 1 */ 0x7B  /* (to 0x014A state 309) */,
+/* pos 0056:  52 */     /* terminal 239 */ 0xEF,
+                       /* 1 */ 0x01  /* (to 0x0058 state  53) */,
+/* pos 0058:  53 */     /* terminal 9 */ 0x09,
+                        /* terminal 142 */ 0x8E,
+/* pos 005a:  55 */    /* 0 */ 0x0A  /* (to 0x006E state  74) */,
+                       /* 1 */ 0x01  /* (to 0x005C state  56) */,
+/* pos 005c:  56 */    /* 0 */ 0x11  /* (to 0x007E state  91) */,
+                       /* 1 */ 0x01  /* (to 0x005E state  57) */,
+/* pos 005e:  57 */    /* 0 */ 0x64  /* (to 0x0126 state 274) */,
+                       /* 1 */ 0x01  /* (to 0x0060 state  58) */,
+/* pos 0060:  58 */     /* terminal 249 */ 0xF9,
+                       /* 1 */ 0x01  /* (to 0x0062 state  59) */,
+/* pos 0062:  59 */    /* 0 */ 0x01  /* (to 0x0064 state  60) */,
+                       /* 1 */ 0x0A  /* (to 0x0076 state  81) */,
+/* pos 0064:  60 */     /* terminal 10 */ 0x0A,
+                        /* terminal 13 */ 0x0D,
+/* pos 0066:  63 */     /* terminal 12 */ 0x0C,
+                        /* terminal 14 */ 0x0E,
+/* pos 0068:  67 */    /* 0 */ 0x01  /* (to 0x006A state  68) */,
+                       /* 1 */ 0x02  /* (to 0x006C state  71) */,
+/* pos 006a:  68 */     /* terminal 15 */ 0x0F,
+                        /* terminal 16 */ 0x10,
+/* pos 006c:  71 */     /* terminal 17 */ 0x11,
+                        /* terminal 18 */ 0x12,
+/* pos 006e:  74 */    /* 0 */ 0x01  /* (to 0x0070 state  75) */,
+                       /* 1 */ 0x05  /* (to 0x0078 state  84) */,
+/* pos 0070:  75 */    /* 0 */ 0x01  /* (to 0x0072 state  76) */,
+                       /* 1 */ 0x02  /* (to 0x0074 state  79) */,
+/* pos 0072:  76 */     /* terminal 19 */ 0x13,
+                        /* terminal 20 */ 0x14,
+/* pos 0074:  79 */     /* terminal 21 */ 0x15,
+                        /* terminal 23 */ 0x17,
+/* pos 0076:  81 */     /* terminal 22 */ 0x16,
+                        /* terminal 256 */ 0x00,
+/* pos 0078:  84 */    /* 0 */ 0x01  /* (to 0x007A state  85) */,
+                       /* 1 */ 0x02  /* (to 0x007C state  88) */,
+/* pos 007a:  85 */     /* terminal 24 */ 0x18,
+                        /* terminal 25 */ 0x19,
+/* pos 007c:  88 */     /* terminal 26 */ 0x1A,
+                        /* terminal 27 */ 0x1B,
+/* pos 007e:  91 */    /* 0 */ 0x01  /* (to 0x0080 state  92) */,
+                       /* 1 */ 0x02  /* (to 0x0082 state  95) */,
+/* pos 0080:  92 */     /* terminal 28 */ 0x1C,
+                        /* terminal 29 */ 0x1D,
+/* pos 0082:  95 */     /* terminal 30 */ 0x1E,
+                        /* terminal 31 */ 0x1F,
+/* pos 0084:  98 */    /* 0 */ 0x13  /* (to 0x00AA state 133) */,
+                       /* 1 */ 0x01  /* (to 0x0086 state  99) */,
+/* pos 0086:  99 */    /* 0 */ 0x01  /* (to 0x0088 state 100) */,
+                       /* 1 */ 0x0F  /* (to 0x00A4 state 129) */,
+/* pos 0088: 100 */    /* 0 */ 0x4B  /* (to 0x011E state 258) */,
+                       /* 1 */ 0x01  /* (to 0x008A state 101) */,
+/* pos 008a: 101 */    /* 0 */ 0x01  /* (to 0x008C state 102) */,
+                       /* 1 */ 0x0C  /* (to 0x00A2 state 126) */,
+/* pos 008c: 102 */     /* terminal 32 */ 0x20,
+                        /* terminal 37 */ 0x25,
+/* pos 008e: 104 */    /* 0 */ 0x01  /* (to 0x0090 state 105) */,
+                       /* 1 */ 0x08  /* (to 0x009E state 119) */,
+/* pos 0090: 105 */     /* terminal 33 */ 0x21,
+                        /* terminal 34 */ 0x22,
+/* pos 0092: 108 */     /* terminal 124 */ 0x7C,
+                       /* 1 */ 0x01  /* (to 0x0094 state 109) */,
+/* pos 0094: 109 */     /* terminal 35 */ 0x23,
+                        /* terminal 62 */ 0x3E,
+/* pos 0096: 113 */    /* 0 */ 0x01  /* (to 0x0098 state 114) */,
+                       /* 1 */ 0x05  /* (to 0x00A0 state 124) */,
+/* pos 0098: 114 */     /* terminal 38 */ 0x26,
+                        /* terminal 42 */ 0x2A,
+/* pos 009a: 116 */     /* terminal 63 */ 0x3F,
+                       /* 1 */ 0x01  /* (to 0x009C state 117) */,
+/* pos 009c: 117 */     /* terminal 39 */ 0x27,
+                        /* terminal 43 */ 0x2B,
+/* pos 009e: 119 */     /* terminal 40 */ 0x28,
+                        /* terminal 41 */ 0x29,
+/* pos 00a0: 124 */     /* terminal 44 */ 0x2C,
+                        /* terminal 59 */ 0x3B,
+/* pos 00a2: 126 */     /* terminal 45 */ 0x2D,
+                        /* terminal 46 */ 0x2E,
+/* pos 00a4: 129 */    /* 0 */ 0x01  /* (to 0x00A6 state 130) */,
+                       /* 1 */ 0x08  /* (to 0x00B4 state 144) */,
+/* pos 00a6: 130 */    /* 0 */ 0x01  /* (to 0x00A8 state 131) */,
+                       /* 1 */ 0x06  /* (to 0x00B2 state 141) */,
+/* pos 00a8: 131 */     /* terminal 47 */ 0x2F,
+                        /* terminal 51 */ 0x33,
+/* pos 00aa: 133 */    /* 0 */ 0x01  /* (to 0x00AC state 134) */,
+                       /* 1 */ 0x2D  /* (to 0x0104 state 229) */,
+/* pos 00ac: 134 */    /* 0 */ 0x01  /* (to 0x00AE state 135) */,
+                       /* 1 */ 0x02  /* (to 0x00B0 state 138) */,
+/* pos 00ae: 135 */     /* terminal 48 */ 0x30,
+                        /* terminal 49 */ 0x31,
+/* pos 00b0: 138 */     /* terminal 50 */ 0x32,
+                        /* terminal 97 */ 0x61,
+/* pos 00b2: 141 */     /* terminal 52 */ 0x34,
+                        /* terminal 53 */ 0x35,
+/* pos 00b4: 144 */    /* 0 */ 0x01  /* (to 0x00B6 state 145) */,
+                       /* 1 */ 0x02  /* (to 0x00B8 state 148) */,
+/* pos 00b6: 145 */     /* terminal 54 */ 0x36,
+                        /* terminal 55 */ 0x37,
+/* pos 00b8: 148 */     /* terminal 56 */ 0x38,
+                        /* terminal 57 */ 0x39,
+/* pos 00ba: 151 */    /* 0 */ 0x06  /* (to 0x00C6 state 160) */,
+                       /* 1 */ 0x01  /* (to 0x00BC state 152) */,
+/* pos 00bc: 152 */    /* 0 */ 0x2C  /* (to 0x0114 state 246) */,
+                       /* 1 */ 0x01  /* (to 0x00BE state 153) */,
+/* pos 00be: 153 */    /* 0 */ 0x2F  /* (to 0x011C state 256) */,
+                       /* 1 */ 0x01  /* (to 0x00C0 state 154) */,
+/* pos 00c0: 154 */    /* 0 */ 0x01  /* (to 0x00C2 state 155) */,
+                       /* 1 */ 0x07  /* (to 0x00CE state 170) */,
+/* pos 00c2: 155 */     /* terminal 58 */ 0x3A,
+                        /* terminal 66 */ 0x42,
+/* pos 00c4: 158 */     /* terminal 60 */ 0x3C,
+                        /* terminal 96 */ 0x60,
+/* pos 00c6: 160 */    /* 0 */ 0x01  /* (to 0x00C8 state 161) */,
+                       /* 1 */ 0x21  /* (to 0x0108 state 232) */,
+/* pos 00c8: 161 */    /* 0 */ 0x01  /* (to 0x00CA state 162) */,
+                       /* 1 */ 0x1D  /* (to 0x0102 state 224) */,
+/* pos 00ca: 162 */     /* terminal 61 */ 0x3D,
+                        /* terminal 65 */ 0x41,
+/* pos 00cc: 166 */     /* terminal 64 */ 0x40,
+                        /* terminal 91 */ 0x5B,
+/* pos 00ce: 170 */     /* terminal 67 */ 0x43,
+                        /* terminal 68 */ 0x44,
+/* pos 00d0: 173 */    /* 0 */ 0x01  /* (to 0x00D2 state 174) */,
+                       /* 1 */ 0x08  /* (to 0x00E0 state 189) */,
+/* pos 00d2: 174 */    /* 0 */ 0x01  /* (to 0x00D4 state 175) */,
+                       /* 1 */ 0x04  /* (to 0x00DA state 182) */,
+/* pos 00d4: 175 */    /* 0 */ 0x01  /* (to 0x00D6 state 176) */,
+                       /* 1 */ 0x02  /* (to 0x00D8 state 179) */,
+/* pos 00d6: 176 */     /* terminal 69 */ 0x45,
+                        /* terminal 70 */ 0x46,
+/* pos 00d8: 179 */     /* terminal 71 */ 0x47,
+                        /* terminal 72 */ 0x48,
+/* pos 00da: 182 */    /* 0 */ 0x01  /* (to 0x00DC state 183) */,
+                       /* 1 */ 0x02  /* (to 0x00DE state 186) */,
+/* pos 00dc: 183 */     /* terminal 73 */ 0x49,
+                        /* terminal 74 */ 0x4A,
+/* pos 00de: 186 */     /* terminal 75 */ 0x4B,
+                        /* terminal 76 */ 0x4C,
+/* pos 00e0: 189 */    /* 0 */ 0x01  /* (to 0x00E2 state 190) */,
+                       /* 1 */ 0x04  /* (to 0x00E8 state 197) */,
+/* pos 00e2: 190 */    /* 0 */ 0x01  /* (to 0x00E4 state 191) */,
+                       /* 1 */ 0x02  /* (to 0x00E6 state 194) */,
+/* pos 00e4: 191 */     /* terminal 77 */ 0x4D,
+                        /* terminal 78 */ 0x4E,
+/* pos 00e6: 194 */     /* terminal 79 */ 0x4F,
+                        /* terminal 80 */ 0x50,
+/* pos 00e8: 197 */    /* 0 */ 0x01  /* (to 0x00EA state 198) */,
+                       /* 1 */ 0x02  /* (to 0x00EC state 201) */,
+/* pos 00ea: 198 */     /* terminal 81 */ 0x51,
+                        /* terminal 82 */ 0x52,
+/* pos 00ec: 201 */     /* terminal 83 */ 0x53,
+                        /* terminal 84 */ 0x54,
+/* pos 00ee: 204 */    /* 0 */ 0x01  /* (to 0x00F0 state 205) */,
+                       /* 1 */ 0x11  /* (to 0x0110 state 242) */,
+/* pos 00f0: 205 */    /* 0 */ 0x01  /* (to 0x00F2 state 206) */,
+                       /* 1 */ 0x02  /* (to 0x00F4 state 209) */,
+/* pos 00f2: 206 */     /* terminal 85 */ 0x55,
+                        /* terminal 86 */ 0x56,
+/* pos 00f4: 209 */     /* terminal 87 */ 0x57,
+                        /* terminal 89 */ 0x59,
+/* pos 00f6: 211 */     /* terminal 88 */ 0x58,
+                        /* terminal 90 */ 0x5A,
+/* pos 00f8: 216 */    /* 0 */ 0x01  /* (to 0x00FA state 217) */,
+                       /* 1 */ 0x1F  /* (to 0x0136 state 286) */,
+/* pos 00fa: 217 */    /* 0 */ 0x01  /* (to 0x00FC state 218) */,
+                       /* 1 */ 0x17  /* (to 0x0128 state 276) */,
+/* pos 00fc: 218 */     /* terminal 92 */ 0x5C,
+                        /* terminal 195 */ 0xC3,
+/* pos 00fe: 220 */     /* terminal 93 */ 0x5D,
+                        /* terminal 126 */ 0x7E,
+/* pos 0100: 222 */     /* terminal 94 */ 0x5E,
+                        /* terminal 125 */ 0x7D,
+/* pos 0102: 224 */     /* terminal 95 */ 0x5F,
+                        /* terminal 98 */ 0x62,
+/* pos 0104: 229 */    /* 0 */ 0x01  /* (to 0x0106 state 230) */,
+                       /* 1 */ 0x05  /* (to 0x010E state 240) */,
+/* pos 0106: 230 */     /* terminal 99 */ 0x63,
+                        /* terminal 101 */ 0x65,
+/* pos 0108: 232 */    /* 0 */ 0x01  /* (to 0x010A state 233) */,
+                       /* 1 */ 0x02  /* (to 0x010C state 237) */,
+/* pos 010a: 233 */     /* terminal 100 */ 0x64,
+                        /* terminal 102 */ 0x66,
+/* pos 010c: 237 */     /* terminal 103 */ 0x67,
+                        /* terminal 104 */ 0x68,
+/* pos 010e: 240 */     /* terminal 105 */ 0x69,
+                        /* terminal 111 */ 0x6F,
+/* pos 0110: 242 */    /* 0 */ 0x01  /* (to 0x0112 state 243) */,
+                       /* 1 */ 0x05  /* (to 0x011A state 254) */,
+/* pos 0112: 243 */     /* terminal 106 */ 0x6A,
+                        /* terminal 107 */ 0x6B,
+/* pos 0114: 246 */    /* 0 */ 0x01  /* (to 0x0116 state 247) */,
+                       /* 1 */ 0x02  /* (to 0x0118 state 250) */,
+/* pos 0116: 247 */     /* terminal 108 */ 0x6C,
+                        /* terminal 109 */ 0x6D,
+/* pos 0118: 250 */     /* terminal 110 */ 0x6E,
+                        /* terminal 112 */ 0x70,
+/* pos 011a: 254 */     /* terminal 113 */ 0x71,
+                        /* terminal 118 */ 0x76,
+/* pos 011c: 256 */     /* terminal 114 */ 0x72,
+                        /* terminal 117 */ 0x75,
+/* pos 011e: 258 */     /* terminal 115 */ 0x73,
+                        /* terminal 116 */ 0x74,
+/* pos 0120: 263 */    /* 0 */ 0x01  /* (to 0x0122 state 264) */,
+                       /* 1 */ 0x02  /* (to 0x0124 state 267) */,
+/* pos 0122: 264 */     /* terminal 119 */ 0x77,
+                        /* terminal 120 */ 0x78,
+/* pos 0124: 267 */     /* terminal 121 */ 0x79,
+                        /* terminal 122 */ 0x7A,
+/* pos 0126: 274 */     /* terminal 127 */ 0x7F,
+                        /* terminal 220 */ 0xDC,
+/* pos 0128: 276 */     /* terminal 208 */ 0xD0,
+                       /* 1 */ 0x01  /* (to 0x012A state 277) */,
+/* pos 012a: 277 */     /* terminal 128 */ 0x80,
+                        /* terminal 130 */ 0x82,
+/* pos 012c: 279 */    /* 0 */ 0x2E  /* (to 0x0188 state 372) */,
+                       /* 1 */ 0x01  /* (to 0x012E state 280) */,
+/* pos 012e: 280 */    /* 0 */ 0x01  /* (to 0x0130 state 281) */,
+                       /* 1 */ 0x1B  /* (to 0x0164 state 332) */,
+/* pos 0130: 281 */    /* 0 */ 0x01  /* (to 0x0132 state 282) */,
+                       /* 1 */ 0x06  /* (to 0x013C state 291) */,
+/* pos 0132: 282 */     /* terminal 230 */ 0xE6,
+                       /* 1 */ 0x01  /* (to 0x0134 state 283) */,
+/* pos 0134: 283 */     /* terminal 129 */ 0x81,
+                        /* terminal 132 */ 0x84,
+/* pos 0136: 286 */    /* 0 */ 0x01  /* (to 0x0138 state 287) */,
+                       /* 1 */ 0x14  /* (to 0x015E state 328) */,
+/* pos 0138: 287 */    /* 0 */ 0x01  /* (to 0x013A state 288) */,
+                       /* 1 */ 0x30  /* (to 0x0198 state 388) */,
+/* pos 013a: 288 */     /* terminal 131 */ 0x83,
+                        /* terminal 162 */ 0xA2,
+/* pos 013c: 291 */    /* 0 */ 0x01  /* (to 0x013E state 292) */,
+                       /* 1 */ 0x02  /* (to 0x0140 state 296) */,
+/* pos 013e: 292 */     /* terminal 133 */ 0x85,
+                        /* terminal 134 */ 0x86,
+/* pos 0140: 296 */     /* terminal 136 */ 0x88,
+                        /* terminal 146 */ 0x92,
+/* pos 0142: 298 */     /* terminal 137 */ 0x89,
+                        /* terminal 138 */ 0x8A,
+/* pos 0144: 301 */    /* 0 */ 0x01  /* (to 0x0146 state 302) */,
+                       /* 1 */ 0x02  /* (to 0x0148 state 305) */,
+/* pos 0146: 302 */     /* terminal 139 */ 0x8B,
+                        /* terminal 140 */ 0x8C,
+/* pos 0148: 305 */     /* terminal 141 */ 0x8D,
+                        /* terminal 143 */ 0x8F,
+/* pos 014a: 309 */    /* 0 */ 0x01  /* (to 0x014C state 310) */,
+                       /* 1 */ 0x06  /* (to 0x0156 state 319) */,
+/* pos 014c: 310 */     /* terminal 144 */ 0x90,
+                        /* terminal 145 */ 0x91,
+/* pos 014e: 314 */    /* 0 */ 0x01  /* (to 0x0150 state 315) */,
+                       /* 1 */ 0x12  /* (to 0x0172 state 350) */,
+/* pos 0150: 315 */    /* 0 */ 0x01  /* (to 0x0152 state 316) */,
+                       /* 1 */ 0x05  /* (to 0x015A state 325) */,
+/* pos 0152: 316 */    /* 0 */ 0x01  /* (to 0x0154 state 317) */,
+                       /* 1 */ 0x03  /* (to 0x0158 state 322) */,
+/* pos 0154: 317 */     /* terminal 147 */ 0x93,
+                        /* terminal 149 */ 0x95,
+/* pos 0156: 319 */     /* terminal 148 */ 0x94,
+                        /* terminal 159 */ 0x9F,
+/* pos 0158: 322 */     /* terminal 150 */ 0x96,
+                        /* terminal 151 */ 0x97,
+/* pos 015a: 325 */    /* 0 */ 0x01  /* (to 0x015C state 326) */,
+                       /* 1 */ 0x08  /* (to 0x016A state 338) */,
+/* pos 015c: 326 */     /* terminal 152 */ 0x98,
+                        /* terminal 155 */ 0x9B,
+/* pos 015e: 328 */    /* 0 */ 0x42  /* (to 0x01E2 state 465) */,
+                       /* 1 */ 0x01  /* (to 0x0160 state 329) */,
+/* pos 0160: 329 */    /* 0 */ 0x01  /* (to 0x0162 state 330) */,
+                       /* 1 */ 0x0C  /* (to 0x0178 state 355) */,
+/* pos 0162: 330 */     /* terminal 153 */ 0x99,
+                        /* terminal 161 */ 0xA1,
+/* pos 0164: 332 */    /* 0 */ 0x01  /* (to 0x0166 state 333) */,
+                       /* 1 */ 0x05  /* (to 0x016E state 347) */,
+/* pos 0166: 333 */    /* 0 */ 0x01  /* (to 0x0168 state 334) */,
+                       /* 1 */ 0x03  /* (to 0x016C state 342) */,
+/* pos 0168: 334 */     /* terminal 154 */ 0x9A,
+                        /* terminal 156 */ 0x9C,
+/* pos 016a: 338 */     /* terminal 157 */ 0x9D,
+                        /* terminal 158 */ 0x9E,
+/* pos 016c: 342 */     /* terminal 160 */ 0xA0,
+                        /* terminal 163 */ 0xA3,
+/* pos 016e: 347 */    /* 0 */ 0x01  /* (to 0x0170 state 348) */,
+                       /* 1 */ 0x07  /* (to 0x017C state 360) */,
+/* pos 0170: 348 */     /* terminal 164 */ 0xA4,
+                        /* terminal 169 */ 0xA9,
+/* pos 0172: 350 */    /* 0 */ 0x01  /* (to 0x0174 state 351) */,
+                       /* 1 */ 0x09  /* (to 0x0184 state 369) */,
+/* pos 0174: 351 */    /* 0 */ 0x01  /* (to 0x0176 state 352) */,
+                       /* 1 */ 0x03  /* (to 0x017A state 357) */,
+/* pos 0176: 352 */     /* terminal 165 */ 0xA5,
+                        /* terminal 166 */ 0xA6,
+/* pos 0178: 355 */     /* terminal 167 */ 0xA7,
+                        /* terminal 172 */ 0xAC,
+/* pos 017a: 357 */     /* terminal 168 */ 0xA8,
+                        /* terminal 174 */ 0xAE,
+/* pos 017c: 360 */     /* terminal 170 */ 0xAA,
+                        /* terminal 173 */ 0xAD,
+/* pos 017e: 362 */    /* 0 */ 0x01  /* (to 0x0180 state 363) */,
+                       /* 1 */ 0x1B  /* (to 0x01B4 state 417) */,
+/* pos 0180: 363 */    /* 0 */ 0x01  /* (to 0x0182 state 364) */,
+                       /* 1 */ 0x2A  /* (to 0x01D4 state 449) */,
+/* pos 0182: 364 */     /* terminal 171 */ 0xAB,
+                        /* terminal 206 */ 0xCE,
+/* pos 0184: 369 */    /* 0 */ 0x01  /* (to 0x0186 state 370) */,
+                       /* 1 */ 0x09  /* (to 0x0196 state 385) */,
+/* pos 0186: 370 */     /* terminal 175 */ 0xAF,
+                        /* terminal 180 */ 0xB4,
+/* pos 0188: 372 */    /* 0 */ 0x01  /* (to 0x018A state 373) */,
+                       /* 1 */ 0x27  /* (to 0x01D6 state 451) */,
+/* pos 018a: 373 */    /* 0 */ 0x01  /* (to 0x018C state 374) */,
+                       /* 1 */ 0x05  /* (to 0x0194 state 381) */,
+/* pos 018c: 374 */     /* terminal 176 */ 0xB0,
+                        /* terminal 177 */ 0xB1,
+/* pos 018e: 377 */    /* 0 */ 0x01  /* (to 0x0190 state 378) */,
+                       /* 1 */ 0x07  /* (to 0x019C state 393) */,
+/* pos 0190: 378 */    /* 0 */ 0x01  /* (to 0x0192 state 379) */,
+                       /* 1 */ 0x05  /* (to 0x019A state 390) */,
+/* pos 0192: 379 */     /* terminal 178 */ 0xB2,
+                        /* terminal 181 */ 0xB5,
+/* pos 0194: 381 */     /* terminal 179 */ 0xB3,
+                        /* terminal 209 */ 0xD1,
+/* pos 0196: 385 */     /* terminal 182 */ 0xB6,
+                        /* terminal 183 */ 0xB7,
+/* pos 0198: 388 */     /* terminal 184 */ 0xB8,
+                        /* terminal 194 */ 0xC2,
+/* pos 019a: 390 */     /* terminal 185 */ 0xB9,
+                        /* terminal 186 */ 0xBA,
+/* pos 019c: 393 */    /* 0 */ 0x01  /* (to 0x019E state 394) */,
+                       /* 1 */ 0x04  /* (to 0x01A4 state 400) */,
+/* pos 019e: 394 */     /* terminal 187 */ 0xBB,
+                        /* terminal 189 */ 0xBD,
+/* pos 01a0: 396 */    /* 0 */ 0x01  /* (to 0x01A2 state 397) */,
+                       /* 1 */ 0x07  /* (to 0x01AE state 412) */,
+/* pos 01a2: 397 */     /* terminal 188 */ 0xBC,
+                        /* terminal 191 */ 0xBF,
+/* pos 01a4: 400 */     /* terminal 190 */ 0xBE,
+                        /* terminal 196 */ 0xC4,
+/* pos 01a6: 403 */    /* 0 */ 0x01  /* (to 0x01A8 state 404) */,
+                       /* 1 */ 0x0D  /* (to 0x01C0 state 427) */,
+/* pos 01a8: 404 */    /* 0 */ 0x01  /* (to 0x01AA state 405) */,
+                       /* 1 */ 0x0A  /* (to 0x01BC state 424) */,
+/* pos 01aa: 405 */    /* 0 */ 0x01  /* (to 0x01AC state 406) */,
+                       /* 1 */ 0x08  /* (to 0x01BA state 421) */,
+/* pos 01ac: 406 */     /* terminal 192 */ 0xC0,
+                        /* terminal 193 */ 0xC1,
+/* pos 01ae: 412 */     /* terminal 197 */ 0xC5,
+                        /* terminal 231 */ 0xE7,
+/* pos 01b0: 414 */    /* 0 */ 0x01  /* (to 0x01B2 state 415) */,
+                       /* 1 */ 0x1B  /* (to 0x01E6 state 475) */,
+/* pos 01b2: 415 */     /* terminal 198 */ 0xC6,
+                        /* terminal 228 */ 0xE4,
+/* pos 01b4: 417 */    /* 0 */ 0x1B  /* (to 0x01EA state 481) */,
+                       /* 1 */ 0x01  /* (to 0x01B6 state 418) */,
+/* pos 01b6: 418 */    /* 0 */ 0x01  /* (to 0x01B8 state 419) */,
+                       /* 1 */ 0x19  /* (to 0x01E8 state 478) */,
+/* pos 01b8: 419 */     /* terminal 199 */ 0xC7,
+                        /* terminal 207 */ 0xCF,
+/* pos 01ba: 421 */     /* terminal 200 */ 0xC8,
+                        /* terminal 201 */ 0xC9,
+/* pos 01bc: 424 */    /* 0 */ 0x01  /* (to 0x01BE state 425) */,
+                       /* 1 */ 0x06  /* (to 0x01C8 state 438) */,
+/* pos 01be: 425 */     /* terminal 202 */ 0xCA,
+                        /* terminal 205 */ 0xCD,
+/* pos 01c0: 427 */    /* 0 */ 0x0D  /* (to 0x01DA state 455) */,
+                       /* 1 */ 0x01  /* (to 0x01C2 state 428) */,
+/* pos 01c2: 428 */    /* 0 */ 0x17  /* (to 0x01F0 state 490) */,
+                       /* 1 */ 0x01  /* (to 0x01C4 state 429) */,
+/* pos 01c4: 429 */     /* terminal 255 */ 0xFF,
+                       /* 1 */ 0x01  /* (to 0x01C6 state 430) */,
+/* pos 01c6: 430 */     /* terminal 203 */ 0xCB,
+                        /* terminal 204 */ 0xCC,
+/* pos 01c8: 438 */     /* terminal 210 */ 0xD2,
+                        /* terminal 213 */ 0xD5,
+/* pos 01ca: 440 */    /* 0 */ 0x01  /* (to 0x01CC state 441) */,
+                       /* 1 */ 0x14  /* (to 0x01F2 state 494) */,
+/* pos 01cc: 441 */    /* 0 */ 0x01  /* (to 0x01CE state 442) */,
+                       /* 1 */ 0x09  /* (to 0x01DE state 461) */,
+/* pos 01ce: 442 */    /* 0 */ 0x01  /* (to 0x01D0 state 443) */,
+                       /* 1 */ 0x02  /* (to 0x01D2 state 447) */,
+/* pos 01d0: 443 */     /* terminal 211 */ 0xD3,
+                        /* terminal 212 */ 0xD4,
+/* pos 01d2: 447 */     /* terminal 214 */ 0xD6,
+                        /* terminal 221 */ 0xDD,
+/* pos 01d4: 449 */     /* terminal 215 */ 0xD7,
+                        /* terminal 225 */ 0xE1,
+/* pos 01d6: 451 */    /* 0 */ 0x01  /* (to 0x01D8 state 452) */,
+                       /* 1 */ 0x07  /* (to 0x01E4 state 469) */,
+/* pos 01d8: 452 */     /* terminal 216 */ 0xD8,
+                        /* terminal 217 */ 0xD9,
+/* pos 01da: 455 */    /* 0 */ 0x01  /* (to 0x01DC state 456) */,
+                       /* 1 */ 0x09  /* (to 0x01EC state 484) */,
+/* pos 01dc: 456 */     /* terminal 218 */ 0xDA,
+                        /* terminal 219 */ 0xDB,
+/* pos 01de: 461 */    /* 0 */ 0x01  /* (to 0x01E0 state 462) */,
+                       /* 1 */ 0x08  /* (to 0x01EE state 488) */,
+/* pos 01e0: 462 */     /* terminal 222 */ 0xDE,
+                        /* terminal 223 */ 0xDF,
+/* pos 01e2: 465 */     /* terminal 224 */ 0xE0,
+                        /* terminal 226 */ 0xE2,
+/* pos 01e4: 469 */     /* terminal 227 */ 0xE3,
+                        /* terminal 229 */ 0xE5,
+/* pos 01e6: 475 */     /* terminal 232 */ 0xE8,
+                        /* terminal 233 */ 0xE9,
+/* pos 01e8: 478 */     /* terminal 234 */ 0xEA,
+                        /* terminal 235 */ 0xEB,
+/* pos 01ea: 481 */     /* terminal 236 */ 0xEC,
+                        /* terminal 237 */ 0xED,
+/* pos 01ec: 484 */     /* terminal 238 */ 0xEE,
+                        /* terminal 240 */ 0xF0,
+/* pos 01ee: 488 */     /* terminal 241 */ 0xF1,
+                        /* terminal 244 */ 0xF4,
+/* pos 01f0: 490 */     /* terminal 242 */ 0xF2,
+                        /* terminal 243 */ 0xF3,
+/* pos 01f2: 494 */    /* 0 */ 0x01  /* (to 0x01F4 state 495) */,
+                       /* 1 */ 0x04  /* (to 0x01FA state 503) */,
+/* pos 01f4: 495 */    /* 0 */ 0x01  /* (to 0x01F6 state 496) */,
+                       /* 1 */ 0x02  /* (to 0x01F8 state 499) */,
+/* pos 01f6: 496 */     /* terminal 245 */ 0xF5,
+                        /* terminal 246 */ 0xF6,
+/* pos 01f8: 499 */     /* terminal 247 */ 0xF7,
+                        /* terminal 248 */ 0xF8,
+/* pos 01fa: 503 */    /* 0 */ 0x01  /* (to 0x01FC state 504) */,
+                       /* 1 */ 0x02  /* (to 0x01FE state 507) */,
+/* pos 01fc: 504 */     /* terminal 250 */ 0xFA,
+                        /* terminal 251 */ 0xFB,
+/* pos 01fe: 507 */     /* terminal 252 */ 0xFC,
+                        /* terminal 253 */ 0xFD,
+/* total size 512 bytes, biggest jump 200/256, fails=0 */
+};
+
+ static unsigned char lextable_terms[] = {
+
+	0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x03, 0x00, 
+	0x34, 0x0f, 0x43, 0x03, 0xf1, 0x3c, 0xfc, 0x3c, 
+	0x0f, 0x30, 0x37, 0xf7, 0x0f, 0xc3, 0xcf, 0x03, 
+	0x3c, 0xfc, 0xc0, 0xf3, 0xf0, 0x3c, 0xfc, 0xf0, 
+	0xcf, 0xfc, 0xcc, 0xff, 0xfc, 0x0d, 0x34, 0xcc, 
+	0xcf, 0x33, 0xf0, 0x33, 0x0c, 0x3f, 0xc3, 0x3f, 
+	0xcc, 0x30, 0xfc, 0xcf, 0x3c, 0xf0, 0x0c, 0xcf, 
+	0xd0, 0x03, 0x3f, 0x33, 0xff, 0xff, 0xc3, 0xf3, 
+};
+
+/* state that points to 0x100 for disambiguation with 0x0 */
+#define HUFTABLE_0x100_PREV 118
diff --git a/src/engine/external/libwebsockets/lextable-strings.h b/src/engine/external/libwebsockets/lextable-strings.h
new file mode 100644
index 00000000..c0f1f2ee
--- /dev/null
+++ b/src/engine/external/libwebsockets/lextable-strings.h
@@ -0,0 +1,86 @@
+/* set of parsable strings -- ALL LOWER CASE */
+
+static const char *set[] = {
+	"get ",
+	"post ",
+	"options ",
+	"host:",
+	"connection:",
+	"upgrade:",
+	"origin:",
+	"sec-websocket-draft:",
+	"\x0d\x0a",
+
+	"sec-websocket-extensions:",
+	"sec-websocket-key1:",
+	"sec-websocket-key2:",
+	"sec-websocket-protocol:",
+
+	"sec-websocket-accept:",
+	"sec-websocket-nonce:",
+	"http/1.1 ",
+	"http2-settings:",
+
+	"accept:",
+	"access-control-request-headers:",
+	"if-modified-since:",
+	"if-none-match:",
+	"accept-encoding:",
+	"accept-language:",
+	"pragma:",
+	"cache-control:",
+	"authorization:",
+	"cookie:",
+	"content-length:",
+	"content-type:",
+	"date:",
+	"range:",
+	"referer:",
+	"sec-websocket-key:",
+	"sec-websocket-version:",
+	"sec-websocket-origin:",
+	
+	":authority:",
+	":method:",
+	":path:",
+	":scheme:",
+	":status:",
+	
+	"accept-charset:",
+	"accept-ranges:",
+	"access-control-allow-origin:",
+	"age:",
+	"allow:",
+	"content-disposition:",
+	"content-encoding:",
+	"content-language:",
+	"content-location:",
+	"content-range:",
+	"etag:",
+	"expect:",
+	"expires:",
+	"from:",
+	"if-match:",
+	"if-range:",
+	"if-unmodified-since:",
+	"last-modified:",
+	"link:",
+	"location:",
+	"max-forwards:",
+	"proxy-authenticate:",
+	"proxy-authorization:",
+	"refresh:",
+	"retry-after:",
+	"server:",
+	"set-cookie:",
+	"strict-transport-security:",
+	"transfer-encoding:",
+	"user-agent:",
+	"vary:",
+	"via:",
+	"www-authenticate:",
+	"proxy ",
+
+	"", /* not matchable */
+
+};
diff --git a/src/engine/external/libwebsockets/lextable.h b/src/engine/external/libwebsockets/lextable.h
new file mode 100644
index 00000000..80d318ef
--- /dev/null
+++ b/src/engine/external/libwebsockets/lextable.h
@@ -0,0 +1,745 @@
+/* pos 0000:   0 */    0x67 /* 'g' */, 0x3D, 0x00  /* (to 0x003D state   1) */,
+                       0x70 /* 'p' */, 0x3F, 0x00  /* (to 0x0042 state   5) */,
+                       0x6F /* 'o' */, 0x48, 0x00  /* (to 0x004E state  10) */,
+                       0x68 /* 'h' */, 0x54, 0x00  /* (to 0x005D state  18) */,
+                       0x63 /* 'c' */, 0x5D, 0x00  /* (to 0x0069 state  23) */,
+                       0x75 /* 'u' */, 0x78, 0x00  /* (to 0x0087 state  34) */,
+                       0x73 /* 's' */, 0x8B, 0x00  /* (to 0x009D state  48) */,
+                       0x0D /* '.' */, 0xC4, 0x00  /* (to 0x00D9 state  68) */,
+                       0x61 /* 'a' */, 0x16, 0x01  /* (to 0x012E state 129) */,
+                       0x69 /* 'i' */, 0x55, 0x01  /* (to 0x0170 state 163) */,
+                       0x64 /* 'd' */, 0xFE, 0x01  /* (to 0x021C state 265) */,
+                       0x72 /* 'r' */, 0x01, 0x02  /* (to 0x0222 state 270) */,
+                       0x3A /* ':' */, 0x32, 0x02  /* (to 0x0256 state 299) */,
+                       0x65 /* 'e' */, 0xC3, 0x02  /* (to 0x02EA state 414) */,
+                       0x66 /* 'f' */, 0xDF, 0x02  /* (to 0x0309 state 430) */,
+                       0x6C /* 'l' */, 0x01, 0x03  /* (to 0x032E state 463) */,
+                       0x6D /* 'm' */, 0x24, 0x03  /* (to 0x0354 state 489) */,
+                       0x74 /* 't' */, 0x93, 0x03  /* (to 0x03C6 state 583) */,
+                       0x76 /* 'v' */, 0xAE, 0x03  /* (to 0x03E4 state 611) */,
+                       0x77 /* 'w' */, 0xBB, 0x03  /* (to 0x03F4 state 619) */,
+                       0x08, /* fail */
+/* pos 003d:   1 */    0xE5 /* 'e' -> */,
+/* pos 003e:   2 */    0xF4 /* 't' -> */,
+/* pos 003f:   3 */    0xA0 /* ' ' -> */,
+/* pos 0040:   4 */    0x00, 0x00                  /* - terminal marker  0 - */,
+/* pos 0042:   5 */    0x6F /* 'o' */, 0x07, 0x00  /* (to 0x0049 state   6) */,
+                       0x72 /* 'r' */, 0x7D, 0x01  /* (to 0x01C2 state 211) */,
+                       0x08, /* fail */
+/* pos 0049:   6 */    0xF3 /* 's' -> */,
+/* pos 004a:   7 */    0xF4 /* 't' -> */,
+/* pos 004b:   8 */    0xA0 /* ' ' -> */,
+/* pos 004c:   9 */    0x00, 0x01                  /* - terminal marker  1 - */,
+/* pos 004e:  10 */    0x70 /* 'p' */, 0x07, 0x00  /* (to 0x0055 state  11) */,
+                       0x72 /* 'r' */, 0x45, 0x00  /* (to 0x0096 state  42) */,
+                       0x08, /* fail */
+/* pos 0055:  11 */    0xF4 /* 't' -> */,
+/* pos 0056:  12 */    0xE9 /* 'i' -> */,
+/* pos 0057:  13 */    0xEF /* 'o' -> */,
+/* pos 0058:  14 */    0xEE /* 'n' -> */,
+/* pos 0059:  15 */    0xF3 /* 's' -> */,
+/* pos 005a:  16 */    0xA0 /* ' ' -> */,
+/* pos 005b:  17 */    0x00, 0x02                  /* - terminal marker  2 - */,
+/* pos 005d:  18 */    0x6F /* 'o' */, 0x07, 0x00  /* (to 0x0064 state  19) */,
+                       0x74 /* 't' */, 0xB3, 0x00  /* (to 0x0113 state 110) */,
+                       0x08, /* fail */
+/* pos 0064:  19 */    0xF3 /* 's' -> */,
+/* pos 0065:  20 */    0xF4 /* 't' -> */,
+/* pos 0066:  21 */    0xBA /* ':' -> */,
+/* pos 0067:  22 */    0x00, 0x03                  /* - terminal marker  3 - */,
+/* pos 0069:  23 */    0x6F /* 'o' */, 0x07, 0x00  /* (to 0x0070 state  24) */,
+                       0x61 /* 'a' */, 0x63, 0x01  /* (to 0x01CF state 217) */,
+                       0x08, /* fail */
+/* pos 0070:  24 */    0x6E /* 'n' */, 0x07, 0x00  /* (to 0x0077 state  25) */,
+                       0x6F /* 'o' */, 0x78, 0x01  /* (to 0x01EB state 243) */,
+                       0x08, /* fail */
+/* pos 0077:  25 */    0x6E /* 'n' */, 0x07, 0x00  /* (to 0x007E state  26) */,
+                       0x74 /* 't' */, 0x77, 0x01  /* (to 0x01F1 state 248) */,
+                       0x08, /* fail */
+/* pos 007e:  26 */    0xE5 /* 'e' -> */,
+/* pos 007f:  27 */    0xE3 /* 'c' -> */,
+/* pos 0080:  28 */    0xF4 /* 't' -> */,
+/* pos 0081:  29 */    0xE9 /* 'i' -> */,
+/* pos 0082:  30 */    0xEF /* 'o' -> */,
+/* pos 0083:  31 */    0xEE /* 'n' -> */,
+/* pos 0084:  32 */    0xBA /* ':' -> */,
+/* pos 0085:  33 */    0x00, 0x04                  /* - terminal marker  4 - */,
+/* pos 0087:  34 */    0x70 /* 'p' */, 0x07, 0x00  /* (to 0x008E state  35) */,
+                       0x73 /* 's' */, 0x4F, 0x03  /* (to 0x03D9 state 601) */,
+                       0x08, /* fail */
+/* pos 008e:  35 */    0xE7 /* 'g' -> */,
+/* pos 008f:  36 */    0xF2 /* 'r' -> */,
+/* pos 0090:  37 */    0xE1 /* 'a' -> */,
+/* pos 0091:  38 */    0xE4 /* 'd' -> */,
+/* pos 0092:  39 */    0xE5 /* 'e' -> */,
+/* pos 0093:  40 */    0xBA /* ':' -> */,
+/* pos 0094:  41 */    0x00, 0x05                  /* - terminal marker  5 - */,
+/* pos 0096:  42 */    0xE9 /* 'i' -> */,
+/* pos 0097:  43 */    0xE7 /* 'g' -> */,
+/* pos 0098:  44 */    0xE9 /* 'i' -> */,
+/* pos 0099:  45 */    0xEE /* 'n' -> */,
+/* pos 009a:  46 */    0xBA /* ':' -> */,
+/* pos 009b:  47 */    0x00, 0x06                  /* - terminal marker  6 - */,
+/* pos 009d:  48 */    0x65 /* 'e' */, 0x07, 0x00  /* (to 0x00A4 state  49) */,
+                       0x74 /* 't' */, 0x0C, 0x03  /* (to 0x03AC state 558) */,
+                       0x08, /* fail */
+/* pos 00a4:  49 */    0x63 /* 'c' */, 0x0A, 0x00  /* (to 0x00AE state  50) */,
+                       0x72 /* 'r' */, 0xF5, 0x02  /* (to 0x039C state 544) */,
+                       0x74 /* 't' */, 0xF8, 0x02  /* (to 0x03A2 state 549) */,
+                       0x08, /* fail */
+/* pos 00ae:  50 */    0xAD /* '-' -> */,
+/* pos 00af:  51 */    0xF7 /* 'w' -> */,
+/* pos 00b0:  52 */    0xE5 /* 'e' -> */,
+/* pos 00b1:  53 */    0xE2 /* 'b' -> */,
+/* pos 00b2:  54 */    0xF3 /* 's' -> */,
+/* pos 00b3:  55 */    0xEF /* 'o' -> */,
+/* pos 00b4:  56 */    0xE3 /* 'c' -> */,
+/* pos 00b5:  57 */    0xEB /* 'k' -> */,
+/* pos 00b6:  58 */    0xE5 /* 'e' -> */,
+/* pos 00b7:  59 */    0xF4 /* 't' -> */,
+/* pos 00b8:  60 */    0xAD /* '-' -> */,
+/* pos 00b9:  61 */    0x64 /* 'd' */, 0x19, 0x00  /* (to 0x00D2 state  62) */,
+                       0x65 /* 'e' */, 0x20, 0x00  /* (to 0x00DC state  70) */,
+                       0x6B /* 'k' */, 0x29, 0x00  /* (to 0x00E8 state  81) */,
+                       0x70 /* 'p' */, 0x38, 0x00  /* (to 0x00FA state  88) */,
+                       0x61 /* 'a' */, 0x3F, 0x00  /* (to 0x0104 state  97) */,
+                       0x6E /* 'n' */, 0x44, 0x00  /* (to 0x010C state 104) */,
+                       0x76 /* 'v' */, 0x7A, 0x01  /* (to 0x0245 state 284) */,
+                       0x6F /* 'o' */, 0x80, 0x01  /* (to 0x024E state 292) */,
+                       0x08, /* fail */
+/* pos 00d2:  62 */    0xF2 /* 'r' -> */,
+/* pos 00d3:  63 */    0xE1 /* 'a' -> */,
+/* pos 00d4:  64 */    0xE6 /* 'f' -> */,
+/* pos 00d5:  65 */    0xF4 /* 't' -> */,
+/* pos 00d6:  66 */    0xBA /* ':' -> */,
+/* pos 00d7:  67 */    0x00, 0x07                  /* - terminal marker  7 - */,
+/* pos 00d9:  68 */    0x8A /* '.' -> */,
+/* pos 00da:  69 */    0x00, 0x08                  /* - terminal marker  8 - */,
+/* pos 00dc:  70 */    0xF8 /* 'x' -> */,
+/* pos 00dd:  71 */    0xF4 /* 't' -> */,
+/* pos 00de:  72 */    0xE5 /* 'e' -> */,
+/* pos 00df:  73 */    0xEE /* 'n' -> */,
+/* pos 00e0:  74 */    0xF3 /* 's' -> */,
+/* pos 00e1:  75 */    0xE9 /* 'i' -> */,
+/* pos 00e2:  76 */    0xEF /* 'o' -> */,
+/* pos 00e3:  77 */    0xEE /* 'n' -> */,
+/* pos 00e4:  78 */    0xF3 /* 's' -> */,
+/* pos 00e5:  79 */    0xBA /* ':' -> */,
+/* pos 00e6:  80 */    0x00, 0x09                  /* - terminal marker  9 - */,
+/* pos 00e8:  81 */    0xE5 /* 'e' -> */,
+/* pos 00e9:  82 */    0xF9 /* 'y' -> */,
+/* pos 00ea:  83 */    0x31 /* '1' */, 0x0A, 0x00  /* (to 0x00F4 state  84) */,
+                       0x32 /* '2' */, 0x0A, 0x00  /* (to 0x00F7 state  86) */,
+                       0x3A /* ':' */, 0x53, 0x01  /* (to 0x0243 state 283) */,
+                       0x08, /* fail */
+/* pos 00f4:  84 */    0xBA /* ':' -> */,
+/* pos 00f5:  85 */    0x00, 0x0A                  /* - terminal marker 10 - */,
+/* pos 00f7:  86 */    0xBA /* ':' -> */,
+/* pos 00f8:  87 */    0x00, 0x0B                  /* - terminal marker 11 - */,
+/* pos 00fa:  88 */    0xF2 /* 'r' -> */,
+/* pos 00fb:  89 */    0xEF /* 'o' -> */,
+/* pos 00fc:  90 */    0xF4 /* 't' -> */,
+/* pos 00fd:  91 */    0xEF /* 'o' -> */,
+/* pos 00fe:  92 */    0xE3 /* 'c' -> */,
+/* pos 00ff:  93 */    0xEF /* 'o' -> */,
+/* pos 0100:  94 */    0xEC /* 'l' -> */,
+/* pos 0101:  95 */    0xBA /* ':' -> */,
+/* pos 0102:  96 */    0x00, 0x0C                  /* - terminal marker 12 - */,
+/* pos 0104:  97 */    0xE3 /* 'c' -> */,
+/* pos 0105:  98 */    0xE3 /* 'c' -> */,
+/* pos 0106:  99 */    0xE5 /* 'e' -> */,
+/* pos 0107: 100 */    0xF0 /* 'p' -> */,
+/* pos 0108: 101 */    0xF4 /* 't' -> */,
+/* pos 0109: 102 */    0xBA /* ':' -> */,
+/* pos 010a: 103 */    0x00, 0x0D                  /* - terminal marker 13 - */,
+/* pos 010c: 104 */    0xEF /* 'o' -> */,
+/* pos 010d: 105 */    0xEE /* 'n' -> */,
+/* pos 010e: 106 */    0xE3 /* 'c' -> */,
+/* pos 010f: 107 */    0xE5 /* 'e' -> */,
+/* pos 0110: 108 */    0xBA /* ':' -> */,
+/* pos 0111: 109 */    0x00, 0x0E                  /* - terminal marker 14 - */,
+/* pos 0113: 110 */    0xF4 /* 't' -> */,
+/* pos 0114: 111 */    0xF0 /* 'p' -> */,
+/* pos 0115: 112 */    0x2F /* '/' */, 0x07, 0x00  /* (to 0x011C state 113) */,
+                       0x32 /* '2' */, 0x0A, 0x00  /* (to 0x0122 state 118) */,
+                       0x08, /* fail */
+/* pos 011c: 113 */    0xB1 /* '1' -> */,
+/* pos 011d: 114 */    0xAE /* '.' -> */,
+/* pos 011e: 115 */    0xB1 /* '1' -> */,
+/* pos 011f: 116 */    0xA0 /* ' ' -> */,
+/* pos 0120: 117 */    0x00, 0x0F                  /* - terminal marker 15 - */,
+/* pos 0122: 118 */    0xAD /* '-' -> */,
+/* pos 0123: 119 */    0xF3 /* 's' -> */,
+/* pos 0124: 120 */    0xE5 /* 'e' -> */,
+/* pos 0125: 121 */    0xF4 /* 't' -> */,
+/* pos 0126: 122 */    0xF4 /* 't' -> */,
+/* pos 0127: 123 */    0xE9 /* 'i' -> */,
+/* pos 0128: 124 */    0xEE /* 'n' -> */,
+/* pos 0129: 125 */    0xE7 /* 'g' -> */,
+/* pos 012a: 126 */    0xF3 /* 's' -> */,
+/* pos 012b: 127 */    0xBA /* ':' -> */,
+/* pos 012c: 128 */    0x00, 0x10                  /* - terminal marker 16 - */,
+/* pos 012e: 129 */    0x63 /* 'c' */, 0x0D, 0x00  /* (to 0x013B state 130) */,
+                       0x75 /* 'u' */, 0xAC, 0x00  /* (to 0x01DD state 230) */,
+                       0x67 /* 'g' */, 0x7C, 0x01  /* (to 0x02B0 state 363) */,
+                       0x6C /* 'l' */, 0x7D, 0x01  /* (to 0x02B4 state 366) */,
+                       0x08, /* fail */
+/* pos 013b: 130 */    0xE3 /* 'c' -> */,
+/* pos 013c: 131 */    0xE5 /* 'e' -> */,
+/* pos 013d: 132 */    0x70 /* 'p' */, 0x07, 0x00  /* (to 0x0144 state 133) */,
+                       0x73 /* 's' */, 0x0E, 0x00  /* (to 0x014E state 136) */,
+                       0x08, /* fail */
+/* pos 0144: 133 */    0xF4 /* 't' -> */,
+/* pos 0145: 134 */    0x3A /* ':' */, 0x07, 0x00  /* (to 0x014C state 135) */,
+                       0x2D /* '-' */, 0x59, 0x00  /* (to 0x01A1 state 192) */,
+                       0x08, /* fail */
+/* pos 014c: 135 */    0x00, 0x11                  /* - terminal marker 17 - */,
+/* pos 014e: 136 */    0xF3 /* 's' -> */,
+/* pos 014f: 137 */    0xAD /* '-' -> */,
+/* pos 0150: 138 */    0xE3 /* 'c' -> */,
+/* pos 0151: 139 */    0xEF /* 'o' -> */,
+/* pos 0152: 140 */    0xEE /* 'n' -> */,
+/* pos 0153: 141 */    0xF4 /* 't' -> */,
+/* pos 0154: 142 */    0xF2 /* 'r' -> */,
+/* pos 0155: 143 */    0xEF /* 'o' -> */,
+/* pos 0156: 144 */    0xEC /* 'l' -> */,
+/* pos 0157: 145 */    0xAD /* '-' -> */,
+/* pos 0158: 146 */    0x72 /* 'r' */, 0x07, 0x00  /* (to 0x015F state 147) */,
+                       0x61 /* 'a' */, 0x47, 0x01  /* (to 0x02A2 state 350) */,
+                       0x08, /* fail */
+/* pos 015f: 147 */    0xE5 /* 'e' -> */,
+/* pos 0160: 148 */    0xF1 /* 'q' -> */,
+/* pos 0161: 149 */    0xF5 /* 'u' -> */,
+/* pos 0162: 150 */    0xE5 /* 'e' -> */,
+/* pos 0163: 151 */    0xF3 /* 's' -> */,
+/* pos 0164: 152 */    0xF4 /* 't' -> */,
+/* pos 0165: 153 */    0xAD /* '-' -> */,
+/* pos 0166: 154 */    0xE8 /* 'h' -> */,
+/* pos 0167: 155 */    0xE5 /* 'e' -> */,
+/* pos 0168: 156 */    0xE1 /* 'a' -> */,
+/* pos 0169: 157 */    0xE4 /* 'd' -> */,
+/* pos 016a: 158 */    0xE5 /* 'e' -> */,
+/* pos 016b: 159 */    0xF2 /* 'r' -> */,
+/* pos 016c: 160 */    0xF3 /* 's' -> */,
+/* pos 016d: 161 */    0xBA /* ':' -> */,
+/* pos 016e: 162 */    0x00, 0x12                  /* - terminal marker 18 - */,
+/* pos 0170: 163 */    0xE6 /* 'f' -> */,
+/* pos 0171: 164 */    0xAD /* '-' -> */,
+/* pos 0172: 165 */    0x6D /* 'm' */, 0x0D, 0x00  /* (to 0x017F state 166) */,
+                       0x6E /* 'n' */, 0x20, 0x00  /* (to 0x0195 state 181) */,
+                       0x72 /* 'r' */, 0x9D, 0x01  /* (to 0x0315 state 440) */,
+                       0x75 /* 'u' */, 0xA1, 0x01  /* (to 0x031C state 446) */,
+                       0x08, /* fail */
+/* pos 017f: 166 */    0x6F /* 'o' */, 0x07, 0x00  /* (to 0x0186 state 167) */,
+                       0x61 /* 'a' */, 0x8D, 0x01  /* (to 0x030F state 435) */,
+                       0x08, /* fail */
+/* pos 0186: 167 */    0xE4 /* 'd' -> */,
+/* pos 0187: 168 */    0xE9 /* 'i' -> */,
+/* pos 0188: 169 */    0xE6 /* 'f' -> */,
+/* pos 0189: 170 */    0xE9 /* 'i' -> */,
+/* pos 018a: 171 */    0xE5 /* 'e' -> */,
+/* pos 018b: 172 */    0xE4 /* 'd' -> */,
+/* pos 018c: 173 */    0xAD /* '-' -> */,
+/* pos 018d: 174 */    0xF3 /* 's' -> */,
+/* pos 018e: 175 */    0xE9 /* 'i' -> */,
+/* pos 018f: 176 */    0xEE /* 'n' -> */,
+/* pos 0190: 177 */    0xE3 /* 'c' -> */,
+/* pos 0191: 178 */    0xE5 /* 'e' -> */,
+/* pos 0192: 179 */    0xBA /* ':' -> */,
+/* pos 0193: 180 */    0x00, 0x13                  /* - terminal marker 19 - */,
+/* pos 0195: 181 */    0xEF /* 'o' -> */,
+/* pos 0196: 182 */    0xEE /* 'n' -> */,
+/* pos 0197: 183 */    0xE5 /* 'e' -> */,
+/* pos 0198: 184 */    0xAD /* '-' -> */,
+/* pos 0199: 185 */    0xED /* 'm' -> */,
+/* pos 019a: 186 */    0xE1 /* 'a' -> */,
+/* pos 019b: 187 */    0xF4 /* 't' -> */,
+/* pos 019c: 188 */    0xE3 /* 'c' -> */,
+/* pos 019d: 189 */    0xE8 /* 'h' -> */,
+/* pos 019e: 190 */    0xBA /* ':' -> */,
+/* pos 019f: 191 */    0x00, 0x14                  /* - terminal marker 20 - */,
+/* pos 01a1: 192 */    0x65 /* 'e' */, 0x0D, 0x00  /* (to 0x01AE state 193) */,
+                       0x6C /* 'l' */, 0x14, 0x00  /* (to 0x01B8 state 202) */,
+                       0x63 /* 'c' */, 0xEA, 0x00  /* (to 0x0291 state 335) */,
+                       0x72 /* 'r' */, 0xF0, 0x00  /* (to 0x029A state 343) */,
+                       0x08, /* fail */
+/* pos 01ae: 193 */    0xEE /* 'n' -> */,
+/* pos 01af: 194 */    0xE3 /* 'c' -> */,
+/* pos 01b0: 195 */    0xEF /* 'o' -> */,
+/* pos 01b1: 196 */    0xE4 /* 'd' -> */,
+/* pos 01b2: 197 */    0xE9 /* 'i' -> */,
+/* pos 01b3: 198 */    0xEE /* 'n' -> */,
+/* pos 01b4: 199 */    0xE7 /* 'g' -> */,
+/* pos 01b5: 200 */    0xBA /* ':' -> */,
+/* pos 01b6: 201 */    0x00, 0x15                  /* - terminal marker 21 - */,
+/* pos 01b8: 202 */    0xE1 /* 'a' -> */,
+/* pos 01b9: 203 */    0xEE /* 'n' -> */,
+/* pos 01ba: 204 */    0xE7 /* 'g' -> */,
+/* pos 01bb: 205 */    0xF5 /* 'u' -> */,
+/* pos 01bc: 206 */    0xE1 /* 'a' -> */,
+/* pos 01bd: 207 */    0xE7 /* 'g' -> */,
+/* pos 01be: 208 */    0xE5 /* 'e' -> */,
+/* pos 01bf: 209 */    0xBA /* ':' -> */,
+/* pos 01c0: 210 */    0x00, 0x16                  /* - terminal marker 22 - */,
+/* pos 01c2: 211 */    0x61 /* 'a' */, 0x07, 0x00  /* (to 0x01C9 state 212) */,
+                       0x6F /* 'o' */, 0x9D, 0x01  /* (to 0x0362 state 502) */,
+                       0x08, /* fail */
+/* pos 01c9: 212 */    0xE7 /* 'g' -> */,
+/* pos 01ca: 213 */    0xED /* 'm' -> */,
+/* pos 01cb: 214 */    0xE1 /* 'a' -> */,
+/* pos 01cc: 215 */    0xBA /* ':' -> */,
+/* pos 01cd: 216 */    0x00, 0x17                  /* - terminal marker 23 - */,
+/* pos 01cf: 217 */    0xE3 /* 'c' -> */,
+/* pos 01d0: 218 */    0xE8 /* 'h' -> */,
+/* pos 01d1: 219 */    0xE5 /* 'e' -> */,
+/* pos 01d2: 220 */    0xAD /* '-' -> */,
+/* pos 01d3: 221 */    0xE3 /* 'c' -> */,
+/* pos 01d4: 222 */    0xEF /* 'o' -> */,
+/* pos 01d5: 223 */    0xEE /* 'n' -> */,
+/* pos 01d6: 224 */    0xF4 /* 't' -> */,
+/* pos 01d7: 225 */    0xF2 /* 'r' -> */,
+/* pos 01d8: 226 */    0xEF /* 'o' -> */,
+/* pos 01d9: 227 */    0xEC /* 'l' -> */,
+/* pos 01da: 228 */    0xBA /* ':' -> */,
+/* pos 01db: 229 */    0x00, 0x18                  /* - terminal marker 24 - */,
+/* pos 01dd: 230 */    0xF4 /* 't' -> */,
+/* pos 01de: 231 */    0xE8 /* 'h' -> */,
+/* pos 01df: 232 */    0xEF /* 'o' -> */,
+/* pos 01e0: 233 */    0xF2 /* 'r' -> */,
+/* pos 01e1: 234 */    0xE9 /* 'i' -> */,
+/* pos 01e2: 235 */    0xFA /* 'z' -> */,
+/* pos 01e3: 236 */    0xE1 /* 'a' -> */,
+/* pos 01e4: 237 */    0xF4 /* 't' -> */,
+/* pos 01e5: 238 */    0xE9 /* 'i' -> */,
+/* pos 01e6: 239 */    0xEF /* 'o' -> */,
+/* pos 01e7: 240 */    0xEE /* 'n' -> */,
+/* pos 01e8: 241 */    0xBA /* ':' -> */,
+/* pos 01e9: 242 */    0x00, 0x19                  /* - terminal marker 25 - */,
+/* pos 01eb: 243 */    0xEB /* 'k' -> */,
+/* pos 01ec: 244 */    0xE9 /* 'i' -> */,
+/* pos 01ed: 245 */    0xE5 /* 'e' -> */,
+/* pos 01ee: 246 */    0xBA /* ':' -> */,
+/* pos 01ef: 247 */    0x00, 0x1A                  /* - terminal marker 26 - */,
+/* pos 01f1: 248 */    0xE5 /* 'e' -> */,
+/* pos 01f2: 249 */    0xEE /* 'n' -> */,
+/* pos 01f3: 250 */    0xF4 /* 't' -> */,
+/* pos 01f4: 251 */    0xAD /* '-' -> */,
+/* pos 01f5: 252 */    0x6C /* 'l' */, 0x10, 0x00  /* (to 0x0205 state 253) */,
+                       0x74 /* 't' */, 0x1E, 0x00  /* (to 0x0216 state 260) */,
+                       0x64 /* 'd' */, 0xBF, 0x00  /* (to 0x02BA state 371) */,
+                       0x65 /* 'e' */, 0xC9, 0x00  /* (to 0x02C7 state 383) */,
+                       0x72 /* 'r' */, 0xE2, 0x00  /* (to 0x02E3 state 408) */,
+                       0x08, /* fail */
+/* pos 0205: 253 */    0x65 /* 'e' */, 0x0A, 0x00  /* (to 0x020F state 254) */,
+                       0x61 /* 'a' */, 0xC9, 0x00  /* (to 0x02D1 state 392) */,
+                       0x6F /* 'o' */, 0xCF, 0x00  /* (to 0x02DA state 400) */,
+                       0x08, /* fail */
+/* pos 020f: 254 */    0xEE /* 'n' -> */,
+/* pos 0210: 255 */    0xE7 /* 'g' -> */,
+/* pos 0211: 256 */    0xF4 /* 't' -> */,
+/* pos 0212: 257 */    0xE8 /* 'h' -> */,
+/* pos 0213: 258 */    0xBA /* ':' -> */,
+/* pos 0214: 259 */    0x00, 0x1B                  /* - terminal marker 27 - */,
+/* pos 0216: 260 */    0xF9 /* 'y' -> */,
+/* pos 0217: 261 */    0xF0 /* 'p' -> */,
+/* pos 0218: 262 */    0xE5 /* 'e' -> */,
+/* pos 0219: 263 */    0xBA /* ':' -> */,
+/* pos 021a: 264 */    0x00, 0x1C                  /* - terminal marker 28 - */,
+/* pos 021c: 265 */    0xE1 /* 'a' -> */,
+/* pos 021d: 266 */    0xF4 /* 't' -> */,
+/* pos 021e: 267 */    0xE5 /* 'e' -> */,
+/* pos 021f: 268 */    0xBA /* ':' -> */,
+/* pos 0220: 269 */    0x00, 0x1D                  /* - terminal marker 29 - */,
+/* pos 0222: 270 */    0x61 /* 'a' */, 0x07, 0x00  /* (to 0x0229 state 271) */,
+                       0x65 /* 'e' */, 0x0A, 0x00  /* (to 0x022F state 276) */,
+                       0x08, /* fail */
+/* pos 0229: 271 */    0xEE /* 'n' -> */,
+/* pos 022a: 272 */    0xE7 /* 'g' -> */,
+/* pos 022b: 273 */    0xE5 /* 'e' -> */,
+/* pos 022c: 274 */    0xBA /* ':' -> */,
+/* pos 022d: 275 */    0x00, 0x1E                  /* - terminal marker 30 - */,
+/* pos 022f: 276 */    0x66 /* 'f' */, 0x07, 0x00  /* (to 0x0236 state 277) */,
+                       0x74 /* 't' */, 0x5F, 0x01  /* (to 0x0391 state 534) */,
+                       0x08, /* fail */
+/* pos 0236: 277 */    0x65 /* 'e' */, 0x07, 0x00  /* (to 0x023D state 278) */,
+                       0x72 /* 'r' */, 0x52, 0x01  /* (to 0x038B state 529) */,
+                       0x08, /* fail */
+/* pos 023d: 278 */    0xF2 /* 'r' -> */,
+/* pos 023e: 279 */    0xE5 /* 'e' -> */,
+/* pos 023f: 280 */    0xF2 /* 'r' -> */,
+/* pos 0240: 281 */    0xBA /* ':' -> */,
+/* pos 0241: 282 */    0x00, 0x1F                  /* - terminal marker 31 - */,
+/* pos 0243: 283 */    0x00, 0x20                  /* - terminal marker 32 - */,
+/* pos 0245: 284 */    0xE5 /* 'e' -> */,
+/* pos 0246: 285 */    0xF2 /* 'r' -> */,
+/* pos 0247: 286 */    0xF3 /* 's' -> */,
+/* pos 0248: 287 */    0xE9 /* 'i' -> */,
+/* pos 0249: 288 */    0xEF /* 'o' -> */,
+/* pos 024a: 289 */    0xEE /* 'n' -> */,
+/* pos 024b: 290 */    0xBA /* ':' -> */,
+/* pos 024c: 291 */    0x00, 0x21                  /* - terminal marker 33 - */,
+/* pos 024e: 292 */    0xF2 /* 'r' -> */,
+/* pos 024f: 293 */    0xE9 /* 'i' -> */,
+/* pos 0250: 294 */    0xE7 /* 'g' -> */,
+/* pos 0251: 295 */    0xE9 /* 'i' -> */,
+/* pos 0252: 296 */    0xEE /* 'n' -> */,
+/* pos 0253: 297 */    0xBA /* ':' -> */,
+/* pos 0254: 298 */    0x00, 0x22                  /* - terminal marker 34 - */,
+/* pos 0256: 299 */    0x61 /* 'a' */, 0x0D, 0x00  /* (to 0x0263 state 300) */,
+                       0x6D /* 'm' */, 0x15, 0x00  /* (to 0x026E state 310) */,
+                       0x70 /* 'p' */, 0x1A, 0x00  /* (to 0x0276 state 317) */,
+                       0x73 /* 's' */, 0x1D, 0x00  /* (to 0x027C state 322) */,
+                       0x08, /* fail */
+/* pos 0263: 300 */    0xF5 /* 'u' -> */,
+/* pos 0264: 301 */    0xF4 /* 't' -> */,
+/* pos 0265: 302 */    0xE8 /* 'h' -> */,
+/* pos 0266: 303 */    0xEF /* 'o' -> */,
+/* pos 0267: 304 */    0xF2 /* 'r' -> */,
+/* pos 0268: 305 */    0xE9 /* 'i' -> */,
+/* pos 0269: 306 */    0xF4 /* 't' -> */,
+/* pos 026a: 307 */    0xF9 /* 'y' -> */,
+/* pos 026b: 308 */    0xBA /* ':' -> */,
+/* pos 026c: 309 */    0x00, 0x23                  /* - terminal marker 35 - */,
+/* pos 026e: 310 */    0xE5 /* 'e' -> */,
+/* pos 026f: 311 */    0xF4 /* 't' -> */,
+/* pos 0270: 312 */    0xE8 /* 'h' -> */,
+/* pos 0271: 313 */    0xEF /* 'o' -> */,
+/* pos 0272: 314 */    0xE4 /* 'd' -> */,
+/* pos 0273: 315 */    0xBA /* ':' -> */,
+/* pos 0274: 316 */    0x00, 0x24                  /* - terminal marker 36 - */,
+/* pos 0276: 317 */    0xE1 /* 'a' -> */,
+/* pos 0277: 318 */    0xF4 /* 't' -> */,
+/* pos 0278: 319 */    0xE8 /* 'h' -> */,
+/* pos 0279: 320 */    0xBA /* ':' -> */,
+/* pos 027a: 321 */    0x00, 0x25                  /* - terminal marker 37 - */,
+/* pos 027c: 322 */    0x63 /* 'c' */, 0x07, 0x00  /* (to 0x0283 state 323) */,
+                       0x74 /* 't' */, 0x0B, 0x00  /* (to 0x028A state 329) */,
+                       0x08, /* fail */
+/* pos 0283: 323 */    0xE8 /* 'h' -> */,
+/* pos 0284: 324 */    0xE5 /* 'e' -> */,
+/* pos 0285: 325 */    0xED /* 'm' -> */,
+/* pos 0286: 326 */    0xE5 /* 'e' -> */,
+/* pos 0287: 327 */    0xBA /* ':' -> */,
+/* pos 0288: 328 */    0x00, 0x26                  /* - terminal marker 38 - */,
+/* pos 028a: 329 */    0xE1 /* 'a' -> */,
+/* pos 028b: 330 */    0xF4 /* 't' -> */,
+/* pos 028c: 331 */    0xF5 /* 'u' -> */,
+/* pos 028d: 332 */    0xF3 /* 's' -> */,
+/* pos 028e: 333 */    0xBA /* ':' -> */,
+/* pos 028f: 334 */    0x00, 0x27                  /* - terminal marker 39 - */,
+/* pos 0291: 335 */    0xE8 /* 'h' -> */,
+/* pos 0292: 336 */    0xE1 /* 'a' -> */,
+/* pos 0293: 337 */    0xF2 /* 'r' -> */,
+/* pos 0294: 338 */    0xF3 /* 's' -> */,
+/* pos 0295: 339 */    0xE5 /* 'e' -> */,
+/* pos 0296: 340 */    0xF4 /* 't' -> */,
+/* pos 0297: 341 */    0xBA /* ':' -> */,
+/* pos 0298: 342 */    0x00, 0x28                  /* - terminal marker 40 - */,
+/* pos 029a: 343 */    0xE1 /* 'a' -> */,
+/* pos 029b: 344 */    0xEE /* 'n' -> */,
+/* pos 029c: 345 */    0xE7 /* 'g' -> */,
+/* pos 029d: 346 */    0xE5 /* 'e' -> */,
+/* pos 029e: 347 */    0xF3 /* 's' -> */,
+/* pos 029f: 348 */    0xBA /* ':' -> */,
+/* pos 02a0: 349 */    0x00, 0x29                  /* - terminal marker 41 - */,
+/* pos 02a2: 350 */    0xEC /* 'l' -> */,
+/* pos 02a3: 351 */    0xEC /* 'l' -> */,
+/* pos 02a4: 352 */    0xEF /* 'o' -> */,
+/* pos 02a5: 353 */    0xF7 /* 'w' -> */,
+/* pos 02a6: 354 */    0xAD /* '-' -> */,
+/* pos 02a7: 355 */    0xEF /* 'o' -> */,
+/* pos 02a8: 356 */    0xF2 /* 'r' -> */,
+/* pos 02a9: 357 */    0xE9 /* 'i' -> */,
+/* pos 02aa: 358 */    0xE7 /* 'g' -> */,
+/* pos 02ab: 359 */    0xE9 /* 'i' -> */,
+/* pos 02ac: 360 */    0xEE /* 'n' -> */,
+/* pos 02ad: 361 */    0xBA /* ':' -> */,
+/* pos 02ae: 362 */    0x00, 0x2A                  /* - terminal marker 42 - */,
+/* pos 02b0: 363 */    0xE5 /* 'e' -> */,
+/* pos 02b1: 364 */    0xBA /* ':' -> */,
+/* pos 02b2: 365 */    0x00, 0x2B                  /* - terminal marker 43 - */,
+/* pos 02b4: 366 */    0xEC /* 'l' -> */,
+/* pos 02b5: 367 */    0xEF /* 'o' -> */,
+/* pos 02b6: 368 */    0xF7 /* 'w' -> */,
+/* pos 02b7: 369 */    0xBA /* ':' -> */,
+/* pos 02b8: 370 */    0x00, 0x2C                  /* - terminal marker 44 - */,
+/* pos 02ba: 371 */    0xE9 /* 'i' -> */,
+/* pos 02bb: 372 */    0xF3 /* 's' -> */,
+/* pos 02bc: 373 */    0xF0 /* 'p' -> */,
+/* pos 02bd: 374 */    0xEF /* 'o' -> */,
+/* pos 02be: 375 */    0xF3 /* 's' -> */,
+/* pos 02bf: 376 */    0xE9 /* 'i' -> */,
+/* pos 02c0: 377 */    0xF4 /* 't' -> */,
+/* pos 02c1: 378 */    0xE9 /* 'i' -> */,
+/* pos 02c2: 379 */    0xEF /* 'o' -> */,
+/* pos 02c3: 380 */    0xEE /* 'n' -> */,
+/* pos 02c4: 381 */    0xBA /* ':' -> */,
+/* pos 02c5: 382 */    0x00, 0x2D                  /* - terminal marker 45 - */,
+/* pos 02c7: 383 */    0xEE /* 'n' -> */,
+/* pos 02c8: 384 */    0xE3 /* 'c' -> */,
+/* pos 02c9: 385 */    0xEF /* 'o' -> */,
+/* pos 02ca: 386 */    0xE4 /* 'd' -> */,
+/* pos 02cb: 387 */    0xE9 /* 'i' -> */,
+/* pos 02cc: 388 */    0xEE /* 'n' -> */,
+/* pos 02cd: 389 */    0xE7 /* 'g' -> */,
+/* pos 02ce: 390 */    0xBA /* ':' -> */,
+/* pos 02cf: 391 */    0x00, 0x2E                  /* - terminal marker 46 - */,
+/* pos 02d1: 392 */    0xEE /* 'n' -> */,
+/* pos 02d2: 393 */    0xE7 /* 'g' -> */,
+/* pos 02d3: 394 */    0xF5 /* 'u' -> */,
+/* pos 02d4: 395 */    0xE1 /* 'a' -> */,
+/* pos 02d5: 396 */    0xE7 /* 'g' -> */,
+/* pos 02d6: 397 */    0xE5 /* 'e' -> */,
+/* pos 02d7: 398 */    0xBA /* ':' -> */,
+/* pos 02d8: 399 */    0x00, 0x2F                  /* - terminal marker 47 - */,
+/* pos 02da: 400 */    0xE3 /* 'c' -> */,
+/* pos 02db: 401 */    0xE1 /* 'a' -> */,
+/* pos 02dc: 402 */    0xF4 /* 't' -> */,
+/* pos 02dd: 403 */    0xE9 /* 'i' -> */,
+/* pos 02de: 404 */    0xEF /* 'o' -> */,
+/* pos 02df: 405 */    0xEE /* 'n' -> */,
+/* pos 02e0: 406 */    0xBA /* ':' -> */,
+/* pos 02e1: 407 */    0x00, 0x30                  /* - terminal marker 48 - */,
+/* pos 02e3: 408 */    0xE1 /* 'a' -> */,
+/* pos 02e4: 409 */    0xEE /* 'n' -> */,
+/* pos 02e5: 410 */    0xE7 /* 'g' -> */,
+/* pos 02e6: 411 */    0xE5 /* 'e' -> */,
+/* pos 02e7: 412 */    0xBA /* ':' -> */,
+/* pos 02e8: 413 */    0x00, 0x31                  /* - terminal marker 49 - */,
+/* pos 02ea: 414 */    0x74 /* 't' */, 0x07, 0x00  /* (to 0x02F1 state 415) */,
+                       0x78 /* 'x' */, 0x09, 0x00  /* (to 0x02F6 state 419) */,
+                       0x08, /* fail */
+/* pos 02f1: 415 */    0xE1 /* 'a' -> */,
+/* pos 02f2: 416 */    0xE7 /* 'g' -> */,
+/* pos 02f3: 417 */    0xBA /* ':' -> */,
+/* pos 02f4: 418 */    0x00, 0x32                  /* - terminal marker 50 - */,
+/* pos 02f6: 419 */    0xF0 /* 'p' -> */,
+/* pos 02f7: 420 */    0x65 /* 'e' */, 0x07, 0x00  /* (to 0x02FE state 421) */,
+                       0x69 /* 'i' */, 0x09, 0x00  /* (to 0x0303 state 425) */,
+                       0x08, /* fail */
+/* pos 02fe: 421 */    0xE3 /* 'c' -> */,
+/* pos 02ff: 422 */    0xF4 /* 't' -> */,
+/* pos 0300: 423 */    0xBA /* ':' -> */,
+/* pos 0301: 424 */    0x00, 0x33                  /* - terminal marker 51 - */,
+/* pos 0303: 425 */    0xF2 /* 'r' -> */,
+/* pos 0304: 426 */    0xE5 /* 'e' -> */,
+/* pos 0305: 427 */    0xF3 /* 's' -> */,
+/* pos 0306: 428 */    0xBA /* ':' -> */,
+/* pos 0307: 429 */    0x00, 0x34                  /* - terminal marker 52 - */,
+/* pos 0309: 430 */    0xF2 /* 'r' -> */,
+/* pos 030a: 431 */    0xEF /* 'o' -> */,
+/* pos 030b: 432 */    0xED /* 'm' -> */,
+/* pos 030c: 433 */    0xBA /* ':' -> */,
+/* pos 030d: 434 */    0x00, 0x35                  /* - terminal marker 53 - */,
+/* pos 030f: 435 */    0xF4 /* 't' -> */,
+/* pos 0310: 436 */    0xE3 /* 'c' -> */,
+/* pos 0311: 437 */    0xE8 /* 'h' -> */,
+/* pos 0312: 438 */    0xBA /* ':' -> */,
+/* pos 0313: 439 */    0x00, 0x36                  /* - terminal marker 54 - */,
+/* pos 0315: 440 */    0xE1 /* 'a' -> */,
+/* pos 0316: 441 */    0xEE /* 'n' -> */,
+/* pos 0317: 442 */    0xE7 /* 'g' -> */,
+/* pos 0318: 443 */    0xE5 /* 'e' -> */,
+/* pos 0319: 444 */    0xBA /* ':' -> */,
+/* pos 031a: 445 */    0x00, 0x37                  /* - terminal marker 55 - */,
+/* pos 031c: 446 */    0xEE /* 'n' -> */,
+/* pos 031d: 447 */    0xED /* 'm' -> */,
+/* pos 031e: 448 */    0xEF /* 'o' -> */,
+/* pos 031f: 449 */    0xE4 /* 'd' -> */,
+/* pos 0320: 450 */    0xE9 /* 'i' -> */,
+/* pos 0321: 451 */    0xE6 /* 'f' -> */,
+/* pos 0322: 452 */    0xE9 /* 'i' -> */,
+/* pos 0323: 453 */    0xE5 /* 'e' -> */,
+/* pos 0324: 454 */    0xE4 /* 'd' -> */,
+/* pos 0325: 455 */    0xAD /* '-' -> */,
+/* pos 0326: 456 */    0xF3 /* 's' -> */,
+/* pos 0327: 457 */    0xE9 /* 'i' -> */,
+/* pos 0328: 458 */    0xEE /* 'n' -> */,
+/* pos 0329: 459 */    0xE3 /* 'c' -> */,
+/* pos 032a: 460 */    0xE5 /* 'e' -> */,
+/* pos 032b: 461 */    0xBA /* ':' -> */,
+/* pos 032c: 462 */    0x00, 0x38                  /* - terminal marker 56 - */,
+/* pos 032e: 463 */    0x61 /* 'a' */, 0x0A, 0x00  /* (to 0x0338 state 464) */,
+                       0x69 /* 'i' */, 0x15, 0x00  /* (to 0x0346 state 477) */,
+                       0x6F /* 'o' */, 0x17, 0x00  /* (to 0x034B state 481) */,
+                       0x08, /* fail */
+/* pos 0338: 464 */    0xF3 /* 's' -> */,
+/* pos 0339: 465 */    0xF4 /* 't' -> */,
+/* pos 033a: 466 */    0xAD /* '-' -> */,
+/* pos 033b: 467 */    0xED /* 'm' -> */,
+/* pos 033c: 468 */    0xEF /* 'o' -> */,
+/* pos 033d: 469 */    0xE4 /* 'd' -> */,
+/* pos 033e: 470 */    0xE9 /* 'i' -> */,
+/* pos 033f: 471 */    0xE6 /* 'f' -> */,
+/* pos 0340: 472 */    0xE9 /* 'i' -> */,
+/* pos 0341: 473 */    0xE5 /* 'e' -> */,
+/* pos 0342: 474 */    0xE4 /* 'd' -> */,
+/* pos 0343: 475 */    0xBA /* ':' -> */,
+/* pos 0344: 476 */    0x00, 0x39                  /* - terminal marker 57 - */,
+/* pos 0346: 477 */    0xEE /* 'n' -> */,
+/* pos 0347: 478 */    0xEB /* 'k' -> */,
+/* pos 0348: 479 */    0xBA /* ':' -> */,
+/* pos 0349: 480 */    0x00, 0x3A                  /* - terminal marker 58 - */,
+/* pos 034b: 481 */    0xE3 /* 'c' -> */,
+/* pos 034c: 482 */    0xE1 /* 'a' -> */,
+/* pos 034d: 483 */    0xF4 /* 't' -> */,
+/* pos 034e: 484 */    0xE9 /* 'i' -> */,
+/* pos 034f: 485 */    0xEF /* 'o' -> */,
+/* pos 0350: 486 */    0xEE /* 'n' -> */,
+/* pos 0351: 487 */    0xBA /* ':' -> */,
+/* pos 0352: 488 */    0x00, 0x3B                  /* - terminal marker 59 - */,
+/* pos 0354: 489 */    0xE1 /* 'a' -> */,
+/* pos 0355: 490 */    0xF8 /* 'x' -> */,
+/* pos 0356: 491 */    0xAD /* '-' -> */,
+/* pos 0357: 492 */    0xE6 /* 'f' -> */,
+/* pos 0358: 493 */    0xEF /* 'o' -> */,
+/* pos 0359: 494 */    0xF2 /* 'r' -> */,
+/* pos 035a: 495 */    0xF7 /* 'w' -> */,
+/* pos 035b: 496 */    0xE1 /* 'a' -> */,
+/* pos 035c: 497 */    0xF2 /* 'r' -> */,
+/* pos 035d: 498 */    0xE4 /* 'd' -> */,
+/* pos 035e: 499 */    0xF3 /* 's' -> */,
+/* pos 035f: 500 */    0xBA /* ':' -> */,
+/* pos 0360: 501 */    0x00, 0x3C                  /* - terminal marker 60 - */,
+/* pos 0362: 502 */    0xF8 /* 'x' -> */,
+/* pos 0363: 503 */    0xF9 /* 'y' -> */,
+/* pos 0364: 504 */    0x2D /* '-' */, 0x07, 0x00  /* (to 0x036B state 505) */,
+                       0x20 /* ' ' */, 0x9F, 0x00  /* (to 0x0406 state 636) */,
+                       0x08, /* fail */
+/* pos 036b: 505 */    0xE1 /* 'a' -> */,
+/* pos 036c: 506 */    0xF5 /* 'u' -> */,
+/* pos 036d: 507 */    0xF4 /* 't' -> */,
+/* pos 036e: 508 */    0xE8 /* 'h' -> */,
+/* pos 036f: 509 */    0x65 /* 'e' */, 0x07, 0x00  /* (to 0x0376 state 510) */,
+                       0x6F /* 'o' */, 0x0E, 0x00  /* (to 0x0380 state 519) */,
+                       0x08, /* fail */
+/* pos 0376: 510 */    0xEE /* 'n' -> */,
+/* pos 0377: 511 */    0xF4 /* 't' -> */,
+/* pos 0378: 512 */    0xE9 /* 'i' -> */,
+/* pos 0379: 513 */    0xE3 /* 'c' -> */,
+/* pos 037a: 514 */    0xE1 /* 'a' -> */,
+/* pos 037b: 515 */    0xF4 /* 't' -> */,
+/* pos 037c: 516 */    0xE5 /* 'e' -> */,
+/* pos 037d: 517 */    0xBA /* ':' -> */,
+/* pos 037e: 518 */    0x00, 0x3D                  /* - terminal marker 61 - */,
+/* pos 0380: 519 */    0xF2 /* 'r' -> */,
+/* pos 0381: 520 */    0xE9 /* 'i' -> */,
+/* pos 0382: 521 */    0xFA /* 'z' -> */,
+/* pos 0383: 522 */    0xE1 /* 'a' -> */,
+/* pos 0384: 523 */    0xF4 /* 't' -> */,
+/* pos 0385: 524 */    0xE9 /* 'i' -> */,
+/* pos 0386: 525 */    0xEF /* 'o' -> */,
+/* pos 0387: 526 */    0xEE /* 'n' -> */,
+/* pos 0388: 527 */    0xBA /* ':' -> */,
+/* pos 0389: 528 */    0x00, 0x3E                  /* - terminal marker 62 - */,
+/* pos 038b: 529 */    0xE5 /* 'e' -> */,
+/* pos 038c: 530 */    0xF3 /* 's' -> */,
+/* pos 038d: 531 */    0xE8 /* 'h' -> */,
+/* pos 038e: 532 */    0xBA /* ':' -> */,
+/* pos 038f: 533 */    0x00, 0x3F                  /* - terminal marker 63 - */,
+/* pos 0391: 534 */    0xF2 /* 'r' -> */,
+/* pos 0392: 535 */    0xF9 /* 'y' -> */,
+/* pos 0393: 536 */    0xAD /* '-' -> */,
+/* pos 0394: 537 */    0xE1 /* 'a' -> */,
+/* pos 0395: 538 */    0xE6 /* 'f' -> */,
+/* pos 0396: 539 */    0xF4 /* 't' -> */,
+/* pos 0397: 540 */    0xE5 /* 'e' -> */,
+/* pos 0398: 541 */    0xF2 /* 'r' -> */,
+/* pos 0399: 542 */    0xBA /* ':' -> */,
+/* pos 039a: 543 */    0x00, 0x40                  /* - terminal marker 64 - */,
+/* pos 039c: 544 */    0xF6 /* 'v' -> */,
+/* pos 039d: 545 */    0xE5 /* 'e' -> */,
+/* pos 039e: 546 */    0xF2 /* 'r' -> */,
+/* pos 039f: 547 */    0xBA /* ':' -> */,
+/* pos 03a0: 548 */    0x00, 0x41                  /* - terminal marker 65 - */,
+/* pos 03a2: 549 */    0xAD /* '-' -> */,
+/* pos 03a3: 550 */    0xE3 /* 'c' -> */,
+/* pos 03a4: 551 */    0xEF /* 'o' -> */,
+/* pos 03a5: 552 */    0xEF /* 'o' -> */,
+/* pos 03a6: 553 */    0xEB /* 'k' -> */,
+/* pos 03a7: 554 */    0xE9 /* 'i' -> */,
+/* pos 03a8: 555 */    0xE5 /* 'e' -> */,
+/* pos 03a9: 556 */    0xBA /* ':' -> */,
+/* pos 03aa: 557 */    0x00, 0x42                  /* - terminal marker 66 - */,
+/* pos 03ac: 558 */    0xF2 /* 'r' -> */,
+/* pos 03ad: 559 */    0xE9 /* 'i' -> */,
+/* pos 03ae: 560 */    0xE3 /* 'c' -> */,
+/* pos 03af: 561 */    0xF4 /* 't' -> */,
+/* pos 03b0: 562 */    0xAD /* '-' -> */,
+/* pos 03b1: 563 */    0xF4 /* 't' -> */,
+/* pos 03b2: 564 */    0xF2 /* 'r' -> */,
+/* pos 03b3: 565 */    0xE1 /* 'a' -> */,
+/* pos 03b4: 566 */    0xEE /* 'n' -> */,
+/* pos 03b5: 567 */    0xF3 /* 's' -> */,
+/* pos 03b6: 568 */    0xF0 /* 'p' -> */,
+/* pos 03b7: 569 */    0xEF /* 'o' -> */,
+/* pos 03b8: 570 */    0xF2 /* 'r' -> */,
+/* pos 03b9: 571 */    0xF4 /* 't' -> */,
+/* pos 03ba: 572 */    0xAD /* '-' -> */,
+/* pos 03bb: 573 */    0xF3 /* 's' -> */,
+/* pos 03bc: 574 */    0xE5 /* 'e' -> */,
+/* pos 03bd: 575 */    0xE3 /* 'c' -> */,
+/* pos 03be: 576 */    0xF5 /* 'u' -> */,
+/* pos 03bf: 577 */    0xF2 /* 'r' -> */,
+/* pos 03c0: 578 */    0xE9 /* 'i' -> */,
+/* pos 03c1: 579 */    0xF4 /* 't' -> */,
+/* pos 03c2: 580 */    0xF9 /* 'y' -> */,
+/* pos 03c3: 581 */    0xBA /* ':' -> */,
+/* pos 03c4: 582 */    0x00, 0x43                  /* - terminal marker 67 - */,
+/* pos 03c6: 583 */    0xF2 /* 'r' -> */,
+/* pos 03c7: 584 */    0xE1 /* 'a' -> */,
+/* pos 03c8: 585 */    0xEE /* 'n' -> */,
+/* pos 03c9: 586 */    0xF3 /* 's' -> */,
+/* pos 03ca: 587 */    0xE6 /* 'f' -> */,
+/* pos 03cb: 588 */    0xE5 /* 'e' -> */,
+/* pos 03cc: 589 */    0xF2 /* 'r' -> */,
+/* pos 03cd: 590 */    0xAD /* '-' -> */,
+/* pos 03ce: 591 */    0xE5 /* 'e' -> */,
+/* pos 03cf: 592 */    0xEE /* 'n' -> */,
+/* pos 03d0: 593 */    0xE3 /* 'c' -> */,
+/* pos 03d1: 594 */    0xEF /* 'o' -> */,
+/* pos 03d2: 595 */    0xE4 /* 'd' -> */,
+/* pos 03d3: 596 */    0xE9 /* 'i' -> */,
+/* pos 03d4: 597 */    0xEE /* 'n' -> */,
+/* pos 03d5: 598 */    0xE7 /* 'g' -> */,
+/* pos 03d6: 599 */    0xBA /* ':' -> */,
+/* pos 03d7: 600 */    0x00, 0x44                  /* - terminal marker 68 - */,
+/* pos 03d9: 601 */    0xE5 /* 'e' -> */,
+/* pos 03da: 602 */    0xF2 /* 'r' -> */,
+/* pos 03db: 603 */    0xAD /* '-' -> */,
+/* pos 03dc: 604 */    0xE1 /* 'a' -> */,
+/* pos 03dd: 605 */    0xE7 /* 'g' -> */,
+/* pos 03de: 606 */    0xE5 /* 'e' -> */,
+/* pos 03df: 607 */    0xEE /* 'n' -> */,
+/* pos 03e0: 608 */    0xF4 /* 't' -> */,
+/* pos 03e1: 609 */    0xBA /* ':' -> */,
+/* pos 03e2: 610 */    0x00, 0x45                  /* - terminal marker 69 - */,
+/* pos 03e4: 611 */    0x61 /* 'a' */, 0x07, 0x00  /* (to 0x03EB state 612) */,
+                       0x69 /* 'i' */, 0x09, 0x00  /* (to 0x03F0 state 616) */,
+                       0x08, /* fail */
+/* pos 03eb: 612 */    0xF2 /* 'r' -> */,
+/* pos 03ec: 613 */    0xF9 /* 'y' -> */,
+/* pos 03ed: 614 */    0xBA /* ':' -> */,
+/* pos 03ee: 615 */    0x00, 0x46                  /* - terminal marker 70 - */,
+/* pos 03f0: 616 */    0xE1 /* 'a' -> */,
+/* pos 03f1: 617 */    0xBA /* ':' -> */,
+/* pos 03f2: 618 */    0x00, 0x47                  /* - terminal marker 71 - */,
+/* pos 03f4: 619 */    0xF7 /* 'w' -> */,
+/* pos 03f5: 620 */    0xF7 /* 'w' -> */,
+/* pos 03f6: 621 */    0xAD /* '-' -> */,
+/* pos 03f7: 622 */    0xE1 /* 'a' -> */,
+/* pos 03f8: 623 */    0xF5 /* 'u' -> */,
+/* pos 03f9: 624 */    0xF4 /* 't' -> */,
+/* pos 03fa: 625 */    0xE8 /* 'h' -> */,
+/* pos 03fb: 626 */    0xE5 /* 'e' -> */,
+/* pos 03fc: 627 */    0xEE /* 'n' -> */,
+/* pos 03fd: 628 */    0xF4 /* 't' -> */,
+/* pos 03fe: 629 */    0xE9 /* 'i' -> */,
+/* pos 03ff: 630 */    0xE3 /* 'c' -> */,
+/* pos 0400: 631 */    0xE1 /* 'a' -> */,
+/* pos 0401: 632 */    0xF4 /* 't' -> */,
+/* pos 0402: 633 */    0xE5 /* 'e' -> */,
+/* pos 0403: 634 */    0xBA /* ':' -> */,
+/* pos 0404: 635 */    0x00, 0x48                  /* - terminal marker 72 - */,
+/* pos 0406: 636 */    0x00, 0x49                  /* - terminal marker 73 - */,
+/* total size 1032 bytes */
diff --git a/src/engine/external/libwebsockets/libwebsockets.c b/src/engine/external/libwebsockets/libwebsockets.c
new file mode 100644
index 00000000..b9be442f
--- /dev/null
+++ b/src/engine/external/libwebsockets/libwebsockets.c
@@ -0,0 +1,850 @@
+/*
+ * libwebsockets - small server side websockets and web server implementation
+ *
+ * Copyright (C) 2010-2014 Andy Green <andy@warmcat.com>
+ *
+ *  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:
+ *  version 2.1 of the License.
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston,
+ *  MA  02110-1301  USA
+ */
+
+#include "private-libwebsockets.h"
+
+int log_level = LLL_ERR | LLL_WARN | LLL_NOTICE;
+static void (*lwsl_emit)(int level, const char *line) = lwsl_emit_stderr;
+
+static const char * const log_level_names[] = {
+	"ERR",
+	"WARN",
+	"NOTICE",
+	"INFO",
+	"DEBUG",
+	"PARSER",
+	"HEADER",
+	"EXTENSION",
+	"CLIENT",
+	"LATENCY",
+};
+
+
+void
+libwebsocket_close_and_free_session(struct libwebsocket_context *context,
+			 struct libwebsocket *wsi, enum lws_close_status reason)
+{
+	int n, m, ret;
+	int old_state;
+	unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 2 +
+						  LWS_SEND_BUFFER_POST_PADDING];
+	struct lws_tokens eff_buf;
+
+	if (!wsi)
+		return;
+
+	old_state = wsi->state;
+
+	if (wsi->socket_is_permanently_unusable)
+		goto just_kill_connection;
+
+	switch (old_state) {
+	case WSI_STATE_DEAD_SOCKET:
+		return;
+
+	/* we tried the polite way... */
+	case WSI_STATE_AWAITING_CLOSE_ACK:
+		goto just_kill_connection;
+
+	case WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE:
+		if (wsi->truncated_send_len) {
+			libwebsocket_callback_on_writable(context, wsi);
+			return;
+		}
+		lwsl_info("wsi %p completed WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE\n", wsi);
+		goto just_kill_connection;
+	default:
+		if (wsi->truncated_send_len) {
+			lwsl_info("wsi %p entering WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE\n", wsi);
+			wsi->state = WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE;
+			return;
+		}
+		break;
+	}
+
+	wsi->u.ws.close_reason = reason;
+
+	if (wsi->mode == LWS_CONNMODE_WS_CLIENT_WAITING_CONNECT ||
+			wsi->mode == LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE) {
+
+		context->protocols[0].callback(context, wsi,
+			LWS_CALLBACK_CLIENT_CONNECTION_ERROR, wsi->user_space, NULL, 0);
+
+		lws_free_header_table(wsi);
+		goto just_kill_connection;
+	}
+
+	if (wsi->mode == LWS_CONNMODE_HTTP_SERVING_ACCEPTED) {
+		if (wsi->u.http.fd != LWS_INVALID_FILE) {
+			lwsl_debug("closing http file\n");
+			compatible_file_close(wsi->u.http.fd);
+			wsi->u.http.fd = LWS_INVALID_FILE;
+			context->protocols[0].callback(context, wsi,
+				LWS_CALLBACK_CLOSED_HTTP, wsi->user_space, NULL, 0);
+		}
+	}
+
+	/*
+	 * are his extensions okay with him closing?  Eg he might be a mux
+	 * parent and just his ch1 aspect is closing?
+	 */
+	
+	if (lws_ext_callback_for_each_active(wsi,
+		      LWS_EXT_CALLBACK_CHECK_OK_TO_REALLY_CLOSE, NULL, 0) > 0) {
+		lwsl_ext("extension vetoed close\n");
+		return;
+	}
+
+	/*
+	 * flush any tx pending from extensions, since we may send close packet
+	 * if there are problems with send, just nuke the connection
+	 */
+
+	do {
+		ret = 0;
+		eff_buf.token = NULL;
+		eff_buf.token_len = 0;
+
+		/* show every extension the new incoming data */
+
+		m = lws_ext_callback_for_each_active(wsi,
+			  LWS_EXT_CALLBACK_FLUSH_PENDING_TX, &eff_buf, 0);
+		if (m < 0) {
+			lwsl_ext("Extension reports fatal error\n");
+			goto just_kill_connection;
+		}
+		if (m)
+			/*
+			 * at least one extension told us he has more
+			 * to spill, so we will go around again after
+			 */
+			ret = 1;
+
+		/* assuming they left us something to send, send it */
+
+		if (eff_buf.token_len)
+			if (lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
+				      eff_buf.token_len) != eff_buf.token_len) {
+				lwsl_debug("close: ext spill failed\n");
+				goto just_kill_connection;
+			}
+	} while (ret);
+
+	/*
+	 * signal we are closing, libwebsocket_write will
+	 * add any necessary version-specific stuff.  If the write fails,
+	 * no worries we are closing anyway.  If we didn't initiate this
+	 * close, then our state has been changed to
+	 * WSI_STATE_RETURNED_CLOSE_ALREADY and we will skip this.
+	 *
+	 * Likewise if it's a second call to close this connection after we
+	 * sent the close indication to the peer already, we are in state
+	 * WSI_STATE_AWAITING_CLOSE_ACK and will skip doing this a second time.
+	 */
+
+	if (old_state == WSI_STATE_ESTABLISHED &&
+					  reason != LWS_CLOSE_STATUS_NOSTATUS) {
+
+		lwsl_debug("sending close indication...\n");
+
+		/* make valgrind happy */
+		memset(buf, 0, sizeof(buf));
+		n = libwebsocket_write(wsi,
+				&buf[LWS_SEND_BUFFER_PRE_PADDING + 2],
+							    0, LWS_WRITE_CLOSE);
+		if (n >= 0) {
+			/*
+			 * we have sent a nice protocol level indication we
+			 * now wish to close, we should not send anything more
+			 */
+
+			wsi->state = WSI_STATE_AWAITING_CLOSE_ACK;
+
+			/*
+			 * ...and we should wait for a reply for a bit
+			 * out of politeness
+			 */
+
+			libwebsocket_set_timeout(wsi,
+						  PENDING_TIMEOUT_CLOSE_ACK, 1);
+
+			lwsl_debug("sent close indication, awaiting ack\n");
+
+			return;
+		}
+
+		lwsl_info("close: sending close packet failed, hanging up\n");
+
+		/* else, the send failed and we should just hang up */
+	}
+
+just_kill_connection:
+
+	lwsl_debug("close: just_kill_connection\n");
+
+	/*
+	 * we won't be servicing or receiving anything further from this guy
+	 * delete socket from the internal poll list if still present
+	 */
+
+	remove_wsi_socket_from_fds(context, wsi);
+
+	wsi->state = WSI_STATE_DEAD_SOCKET;
+
+	lws_free2(wsi->rxflow_buffer);
+
+	if (wsi->mode == LWS_CONNMODE_HTTP2_SERVING && wsi->u.hdr.ah) {
+		lws_free2(wsi->u.hdr.ah);
+	}
+
+	if ((old_state == WSI_STATE_ESTABLISHED ||
+	     wsi->mode == LWS_CONNMODE_WS_SERVING ||
+	     wsi->mode == LWS_CONNMODE_WS_CLIENT)) {
+
+		lws_free2(wsi->u.ws.rx_user_buffer);
+
+		if (wsi->truncated_send_malloc) {
+			/* not going to be completed... nuke it */
+			lws_free2(wsi->truncated_send_malloc);
+			wsi->truncated_send_len = 0;
+		}
+		if (wsi->u.ws.ping_payload_buf) {
+			lws_free2(wsi->u.ws.ping_payload_buf);
+			wsi->u.ws.ping_payload_alloc = 0;
+			wsi->u.ws.ping_payload_len = 0;
+		}
+	}
+
+	/* tell the user it's all over for this guy */
+
+	if (wsi->protocol && wsi->protocol->callback &&
+			((old_state == WSI_STATE_ESTABLISHED) ||
+			 (old_state == WSI_STATE_RETURNED_CLOSE_ALREADY) ||
+			 (old_state == WSI_STATE_AWAITING_CLOSE_ACK) ||
+			 (old_state == WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE))) {
+		lwsl_debug("calling back CLOSED\n");
+		wsi->protocol->callback(context, wsi, LWS_CALLBACK_CLOSED,
+						      wsi->user_space, NULL, 0);
+	} else if (wsi->mode == LWS_CONNMODE_HTTP_SERVING_ACCEPTED) {
+		lwsl_debug("calling back CLOSED_HTTP\n");
+		context->protocols[0].callback(context, wsi,
+			LWS_CALLBACK_CLOSED_HTTP, wsi->user_space, NULL, 0 );
+	} else
+		lwsl_debug("not calling back closed\n");
+
+	/* deallocate any active extension contexts */
+	
+	if (lws_ext_callback_for_each_active(wsi, LWS_EXT_CALLBACK_DESTROY, NULL, 0) < 0)
+		lwsl_warn("extension destruction failed\n");
+#ifndef LWS_NO_EXTENSIONS
+	for (n = 0; n < wsi->count_active_extensions; n++)
+		lws_free(wsi->active_extensions_user[n]);
+#endif
+	/*
+	 * inform all extensions in case they tracked this guy out of band
+	 * even though not active on him specifically
+	 */
+	if (lws_ext_callback_for_each_extension_type(context, wsi,
+		       LWS_EXT_CALLBACK_DESTROY_ANY_WSI_CLOSING, NULL, 0) < 0)
+		lwsl_warn("ext destroy wsi failed\n");
+
+/*	lwsl_info("closing fd=%d\n", wsi->sock); */
+
+	if (!lws_ssl_close(wsi) && wsi->sock >= 0) {
+		n = shutdown(wsi->sock, SHUT_RDWR);
+		if (n)
+			lwsl_debug("closing: shutdown ret %d\n", LWS_ERRNO);
+
+		n = compatible_close(wsi->sock);
+		if (n)
+			lwsl_debug("closing: close ret %d\n", LWS_ERRNO);
+	}
+
+	/* outermost destroy notification for wsi (user_space still intact) */
+	context->protocols[0].callback(context, wsi,
+			LWS_CALLBACK_WSI_DESTROY, wsi->user_space, NULL, 0);
+
+	if (wsi->protocol && wsi->protocol->per_session_data_size &&
+	    wsi->user_space && !wsi->user_space_externally_allocated)
+		lws_free(wsi->user_space);
+
+	/* As a precaution, free the header table in case it lingered: */
+	lws_free_header_table(wsi);
+	lws_free(wsi);
+}
+
+/**
+ * libwebsockets_get_peer_addresses() - Get client address information
+ * @context:	Libwebsockets context
+ * @wsi:	Local struct libwebsocket associated with
+ * @fd:		Connection socket descriptor
+ * @name:	Buffer to take client address name
+ * @name_len:	Length of client address name buffer
+ * @rip:	Buffer to take client address IP dotted quad
+ * @rip_len:	Length of client address IP buffer
+ *
+ *	This function fills in @name and @rip with the name and IP of
+ *	the client connected with socket descriptor @fd.  Names may be
+ *	truncated if there is not enough room.  If either cannot be
+ *	determined, they will be returned as valid zero-length strings.
+ */
+
+LWS_VISIBLE void
+libwebsockets_get_peer_addresses(struct libwebsocket_context *context,
+	struct libwebsocket *wsi, int fd, char *name, int name_len,
+					char *rip, int rip_len)
+{
+	socklen_t len;
+#ifdef LWS_USE_IPV6
+	struct sockaddr_in6 sin6;
+#endif
+	struct sockaddr_in sin4;
+	struct hostent *host;
+	struct hostent *host1;
+	char ip[128];
+	unsigned char *p;
+	int n;
+#ifdef AF_LOCAL
+	struct sockaddr_un *un;
+#endif
+	int ret = -1;
+
+	rip[0] = '\0';
+	name[0] = '\0';
+
+	lws_latency_pre(context, wsi);
+
+#ifdef LWS_USE_IPV6
+	if (LWS_IPV6_ENABLED(context)) {
+
+		len = sizeof(sin6);
+		if (getpeername(fd, (struct sockaddr *) &sin6, &len) < 0) {
+			lwsl_warn("getpeername: %s\n", strerror(LWS_ERRNO));
+			goto bail;
+		}
+
+		if (!lws_plat_inet_ntop(AF_INET6, &sin6.sin6_addr, rip, rip_len)) {
+			lwsl_err("inet_ntop", strerror(LWS_ERRNO));
+			goto bail;
+		}
+
+		// Strip off the IPv4 to IPv6 header if one exists
+		if (strncmp(rip, "::ffff:", 7) == 0)
+			memmove(rip, rip + 7, strlen(rip) - 6);
+
+		getnameinfo((struct sockaddr *)&sin6,
+				sizeof(struct sockaddr_in6), name,
+							name_len, NULL, 0, 0);
+
+	} else
+#endif
+	{
+		len = sizeof(sin4);
+		if (getpeername(fd, (struct sockaddr *) &sin4, &len) < 0) {
+			lwsl_warn("getpeername: %s\n", strerror(LWS_ERRNO));
+			goto bail;
+		}
+		host = gethostbyaddr((char *) &sin4.sin_addr,
+						sizeof(sin4.sin_addr), AF_INET);
+		if (host == NULL) {
+			lwsl_warn("gethostbyaddr: %s\n", strerror(LWS_ERRNO));
+			goto bail;
+		}
+
+		strncpy(name, host->h_name, name_len);
+		name[name_len - 1] = '\0';
+
+		host1 = gethostbyname(host->h_name);
+		if (host1 == NULL)
+			goto bail;
+		p = (unsigned char *)host1;
+		n = 0;
+		while (p != NULL) {
+			p = (unsigned char *)host1->h_addr_list[n++];
+			if (p == NULL)
+				continue;
+			if ((host1->h_addrtype != AF_INET)
+#ifdef AF_LOCAL
+				&& (host1->h_addrtype != AF_LOCAL)
+#endif
+				)
+				continue;
+
+			if (host1->h_addrtype == AF_INET)
+				sprintf(ip, "%u.%u.%u.%u",
+						p[0], p[1], p[2], p[3]);
+#ifdef AF_LOCAL
+			else {
+				un = (struct sockaddr_un *)p;
+				strncpy(ip, un->sun_path, sizeof(ip) - 1);
+				ip[sizeof(ip) - 1] = '\0';
+			}
+#endif
+			p = NULL;
+			strncpy(rip, ip, rip_len);
+			rip[rip_len - 1] = '\0';
+		}
+	}
+
+	ret = 0;
+bail:
+	lws_latency(context, wsi, "libwebsockets_get_peer_addresses", ret, 1);
+}
+
+
+
+/**
+ * libwebsocket_context_user() - get the user data associated with the context
+ * @context: Websocket context
+ *
+ *	This returns the optional user allocation that can be attached to
+ *	the context the sockets live in at context_create time.  It's a way
+ *	to let all sockets serviced in the same context share data without
+ *	using globals statics in the user code.
+ */
+LWS_EXTERN void *
+libwebsocket_context_user(struct libwebsocket_context *context)
+{
+	return context->user_space;
+}
+
+
+/**
+ * libwebsocket_callback_all_protocol() - Callback all connections using
+ *				the given protocol with the given reason
+ *
+ * @protocol:	Protocol whose connections will get callbacks
+ * @reason:	Callback reason index
+ */
+
+LWS_VISIBLE int
+libwebsocket_callback_all_protocol(
+		const struct libwebsocket_protocols *protocol, int reason)
+{
+	struct libwebsocket_context *context = protocol->owning_server;
+	int n;
+	struct libwebsocket *wsi;
+
+	for (n = 0; n < context->fds_count; n++) {
+		wsi = context->lws_lookup[context->fds[n].fd];
+		if (!wsi)
+			continue;
+		if (wsi->protocol == protocol)
+			protocol->callback(context, wsi,
+					reason, wsi->user_space, NULL, 0);
+	}
+
+	return 0;
+}
+
+/**
+ * libwebsocket_set_timeout() - marks the wsi as subject to a timeout
+ *
+ * You will not need this unless you are doing something special
+ *
+ * @wsi:	Websocket connection instance
+ * @reason:	timeout reason
+ * @secs:	how many seconds
+ */
+
+LWS_VISIBLE void
+libwebsocket_set_timeout(struct libwebsocket *wsi,
+					  enum pending_timeout reason, int secs)
+{
+	time_t now;
+
+	time(&now);
+
+	wsi->pending_timeout_limit = now + secs;
+	wsi->pending_timeout = reason;
+}
+
+
+/**
+ * libwebsocket_get_socket_fd() - returns the socket file descriptor
+ *
+ * You will not need this unless you are doing something special
+ *
+ * @wsi:	Websocket connection instance
+ */
+
+LWS_VISIBLE int
+libwebsocket_get_socket_fd(struct libwebsocket *wsi)
+{
+	return wsi->sock;
+}
+
+#ifdef LWS_LATENCY
+void
+lws_latency(struct libwebsocket_context *context, struct libwebsocket *wsi,
+				     const char *action, int ret, int completed)
+{
+	unsigned long long u;
+	char buf[256];
+
+	u = time_in_microseconds();
+
+	if (!action) {
+		wsi->latency_start = u;
+		if (!wsi->action_start)
+			wsi->action_start = u;
+		return;
+	}
+	if (completed) {
+		if (wsi->action_start == wsi->latency_start)
+			sprintf(buf,
+			  "Completion first try lat %lluus: %p: ret %d: %s\n",
+					u - wsi->latency_start,
+						      (void *)wsi, ret, action);
+		else
+			sprintf(buf,
+			  "Completion %lluus: lat %lluus: %p: ret %d: %s\n",
+				u - wsi->action_start,
+					u - wsi->latency_start,
+						      (void *)wsi, ret, action);
+		wsi->action_start = 0;
+	} else
+		sprintf(buf, "lat %lluus: %p: ret %d: %s\n",
+			      u - wsi->latency_start, (void *)wsi, ret, action);
+
+	if (u - wsi->latency_start > context->worst_latency) {
+		context->worst_latency = u - wsi->latency_start;
+		strcpy(context->worst_latency_info, buf);
+	}
+	lwsl_latency("%s", buf);
+}
+#endif
+
+
+
+/**
+ * libwebsocket_rx_flow_control() - Enable and disable socket servicing for
+ *				received packets.
+ *
+ * If the output side of a server process becomes choked, this allows flow
+ * control for the input side.
+ *
+ * @wsi:	Websocket connection instance to get callback for
+ * @enable:	0 = disable read servicing for this connection, 1 = enable
+ */
+
+LWS_VISIBLE int
+libwebsocket_rx_flow_control(struct libwebsocket *wsi, int enable)
+{
+	if (enable == (wsi->rxflow_change_to & LWS_RXFLOW_ALLOW))
+		return 0;
+
+	lwsl_info("libwebsocket_rx_flow_control(0x%p, %d)\n", wsi, enable);
+	wsi->rxflow_change_to = LWS_RXFLOW_PENDING_CHANGE | !!enable;
+
+	return 0;
+}
+
+/**
+ * libwebsocket_rx_flow_allow_all_protocol() - Allow all connections with this protocol to receive
+ *
+ * When the user server code realizes it can accept more input, it can
+ * call this to have the RX flow restriction removed from all connections using
+ * the given protocol.
+ *
+ * @protocol:	all connections using this protocol will be allowed to receive
+ */
+
+LWS_VISIBLE void
+libwebsocket_rx_flow_allow_all_protocol(
+				const struct libwebsocket_protocols *protocol)
+{
+	struct libwebsocket_context *context = protocol->owning_server;
+	int n;
+	struct libwebsocket *wsi;
+
+	for (n = 0; n < context->fds_count; n++) {
+		wsi = context->lws_lookup[context->fds[n].fd];
+		if (!wsi)
+			continue;
+		if (wsi->protocol == protocol)
+			libwebsocket_rx_flow_control(wsi, LWS_RXFLOW_ALLOW);
+	}
+}
+
+
+/**
+ * libwebsocket_canonical_hostname() - returns this host's hostname
+ *
+ * This is typically used by client code to fill in the host parameter
+ * when making a client connection.  You can only call it after the context
+ * has been created.
+ *
+ * @context:	Websocket context
+ */
+LWS_VISIBLE extern const char *
+libwebsocket_canonical_hostname(struct libwebsocket_context *context)
+{
+	return (const char *)context->canonical_hostname;
+}
+
+int user_callback_handle_rxflow(callback_function callback_function,
+		struct libwebsocket_context *context,
+			struct libwebsocket *wsi,
+			 enum libwebsocket_callback_reasons reason, void *user,
+							  void *in, size_t len)
+{
+	int n;
+
+	n = callback_function(context, wsi, reason, user, in, len);
+	if (!n)
+		n = _libwebsocket_rx_flow_control(wsi);
+
+	return n;
+}
+
+
+/**
+ * libwebsocket_set_proxy() - Setups proxy to libwebsocket_context.
+ * @context:	pointer to struct libwebsocket_context you want set proxy to
+ * @proxy: pointer to c string containing proxy in format address:port
+ *
+ * Returns 0 if proxy string was parsed and proxy was setup. 
+ * Returns -1 if @proxy is NULL or has incorrect format.
+ *
+ * This is only required if your OS does not provide the http_proxy
+ * environment variable (eg, OSX)
+ *
+ *   IMPORTANT! You should call this function right after creation of the
+ *   libwebsocket_context and before call to connect. If you call this
+ *   function after connect behavior is undefined.
+ *   This function will override proxy settings made on libwebsocket_context
+ *   creation with genenv() call.
+ */
+
+LWS_VISIBLE int
+libwebsocket_set_proxy(struct libwebsocket_context *context, const char *proxy)
+{
+	char *p;
+	
+	if (!proxy)
+		return -1;
+
+	strncpy(context->http_proxy_address, proxy,
+				sizeof(context->http_proxy_address) - 1);
+	context->http_proxy_address[
+				sizeof(context->http_proxy_address) - 1] = '\0';
+	
+	p = strchr(context->http_proxy_address, ':');
+	if (!p) {
+		lwsl_err("http_proxy needs to be ads:port\n");
+
+		return -1;
+	}
+	*p = '\0';
+	context->http_proxy_port = atoi(p + 1);
+	
+	lwsl_notice(" Proxy %s:%u\n", context->http_proxy_address,
+						context->http_proxy_port);
+
+	return 0;
+}
+
+/**
+ * libwebsockets_get_protocol() - Returns a protocol pointer from a websocket
+ *				  connection.
+ * @wsi:	pointer to struct websocket you want to know the protocol of
+ *
+ *
+ *	Some apis can act on all live connections of a given protocol,
+ *	this is how you can get a pointer to the active protocol if needed.
+ */
+
+LWS_VISIBLE const struct libwebsocket_protocols *
+libwebsockets_get_protocol(struct libwebsocket *wsi)
+{
+	return wsi->protocol;
+}
+
+LWS_VISIBLE int
+libwebsocket_is_final_fragment(struct libwebsocket *wsi)
+{
+	return wsi->u.ws.final;
+}
+
+LWS_VISIBLE unsigned char
+libwebsocket_get_reserved_bits(struct libwebsocket *wsi)
+{
+	return wsi->u.ws.rsv;
+}
+
+int
+libwebsocket_ensure_user_space(struct libwebsocket *wsi)
+{
+	lwsl_info("%s: %p protocol %p\n", __func__, wsi, wsi->protocol);
+	if (!wsi->protocol)
+		return 1;
+
+	/* allocate the per-connection user memory (if any) */
+
+	if (wsi->protocol->per_session_data_size && !wsi->user_space) {
+		wsi->user_space = lws_zalloc(wsi->protocol->per_session_data_size);
+		if (wsi->user_space  == NULL) {
+			lwsl_err("Out of memory for conn user space\n");
+			return 1;
+		}
+	} else
+		lwsl_info("%s: %p protocol pss %u, user_space=%d\n", __func__, wsi, wsi->protocol->per_session_data_size, wsi->user_space);
+	return 0;
+}
+
+LWS_VISIBLE void lwsl_emit_stderr(int level, const char *line)
+{
+	char buf[300];
+	unsigned long long now;
+	int n;
+
+	buf[0] = '\0';
+	for (n = 0; n < LLL_COUNT; n++)
+		if (level == (1 << n)) {
+			now = time_in_microseconds() / 100;
+			sprintf(buf, "[%lu:%04d] %s: ", (unsigned long) now / 10000,
+				(int)(now % 10000), log_level_names[n]);
+			break;
+		}
+
+	fprintf(stderr, "%s%s", buf, line);
+}
+
+
+LWS_VISIBLE void _lws_logv(int filter, const char *format, va_list vl)
+{
+	char buf[256];
+
+	if (!(log_level & filter))
+		return;
+
+	vsnprintf(buf, sizeof(buf), format, vl);
+	buf[sizeof(buf) - 1] = '\0';
+
+	lwsl_emit(filter, buf);
+}
+
+LWS_VISIBLE void _lws_log(int filter, const char *format, ...)
+{
+	va_list ap;
+
+	va_start(ap, format);
+	_lws_logv(filter, format, ap);
+	va_end(ap);
+}
+
+/**
+ * lws_set_log_level() - Set the logging bitfield
+ * @level:	OR together the LLL_ debug contexts you want output from
+ * @log_emit_function:	NULL to leave it as it is, or a user-supplied
+ *			function to perform log string emission instead of
+ *			the default stderr one.
+ *
+ *	log level defaults to "err", "warn" and "notice" contexts enabled and
+ *	emission on stderr.
+ */
+
+LWS_VISIBLE void lws_set_log_level(int level, void (*log_emit_function)(int level,
+							      const char *line))
+{
+	log_level = level;
+	if (log_emit_function)
+		lwsl_emit = log_emit_function;
+}
+
+/**
+ * lws_use_ssl() - Find out if connection is using SSL
+ * @wsi:	websocket connection to check
+ *
+ *	Returns 0 if the connection is not using SSL, 1 if using SSL and
+ *	using verified cert, and 2 if using SSL but the cert was not
+ *	checked (appears for client wsi told to skip check on connection)
+ */
+LWS_VISIBLE int
+lws_is_ssl(struct libwebsocket *wsi)
+{
+#ifdef LWS_OPENSSL_SUPPORT
+	return wsi->use_ssl;
+#else
+	return 0;
+#endif
+}
+
+/**
+ * lws_partial_buffered() - find out if lws buffered the last write
+ * @wsi:	websocket connection to check
+ *
+ * Returns 1 if you cannot use libwebsocket_write because the last
+ * write on this connection is still buffered, and can't be cleared without
+ * returning to the service loop and waiting for the connection to be
+ * writeable again.
+ * 
+ * If you will try to do >1 libwebsocket_write call inside a single
+ * WRITEABLE callback, you must check this after every write and bail if
+ * set, ask for a new writeable callback and continue writing from there.
+ * 
+ * This is never set at the start of a writeable callback, but any write
+ * may set it.
+ */
+
+LWS_VISIBLE int
+lws_partial_buffered(struct libwebsocket *wsi)
+{
+	return !!wsi->truncated_send_len;	
+}
+
+void lws_set_protocol_write_pending(struct libwebsocket_context *context,
+				    struct libwebsocket *wsi,
+				    enum lws_pending_protocol_send pend)
+{
+	lwsl_info("setting pps %d\n", pend);
+	
+	if (wsi->pps)
+		lwsl_err("pps overwrite\n");
+	wsi->pps = pend;
+	libwebsocket_rx_flow_control(wsi, 0);
+	libwebsocket_callback_on_writable(context, wsi);
+}
+
+LWS_VISIBLE size_t
+lws_get_peer_write_allowance(struct libwebsocket *wsi)
+{
+#ifdef LWS_USE_HTTP2
+	/* only if we are using HTTP2 on this connection */
+	if (wsi->mode != LWS_CONNMODE_HTTP2_SERVING)
+		return -1;
+	/* user is only interested in how much he can send, or that he can't  */
+	if (wsi->u.http2.tx_credit <= 0)
+		return 0;
+	
+	return wsi->u.http2.tx_credit;
+#else
+	return -1;
+#endif
+}
+
+LWS_VISIBLE void
+lws_union_transition(struct libwebsocket *wsi, enum connection_mode mode)
+{
+	memset(&wsi->u, 0, sizeof(wsi->u));
+	wsi->mode = mode;
+}
diff --git a/src/engine/external/libwebsockets/libwebsockets.h b/src/engine/external/libwebsockets/libwebsockets.h
new file mode 100644
index 00000000..3c717ff4
--- /dev/null
+++ b/src/engine/external/libwebsockets/libwebsockets.h
@@ -0,0 +1,1371 @@
+/*
+ * libwebsockets - small server side websockets and web server implementation
+ *
+ * Copyright (C) 2010-2013 Andy Green <andy@warmcat.com>
+ *
+ *  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:
+ *  version 2.1 of the License.
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston,
+ *  MA  02110-1301  USA
+ */
+
+#ifndef LIBWEBSOCKET_H_3060898B846849FF9F88F5DB59B5950C
+#define LIBWEBSOCKET_H_3060898B846849FF9F88F5DB59B5950C
+
+#ifdef __cplusplus
+#include <cstddef>
+#include <cstdarg>
+extern "C" {
+#endif
+	
+#ifdef CMAKE_BUILD
+#include "lws_config.h"
+#endif
+
+#if defined(WIN32) || defined(_WIN32)
+
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <basetsd.h>
+
+#define strcasecmp stricmp
+#define getdtablesize() 30000
+
+#define LWS_VISIBLE
+
+#ifdef LWS_DLL
+#ifdef LWS_INTERNAL
+#define LWS_EXTERN extern __declspec(dllexport)
+#else
+#define LWS_EXTERN extern __declspec(dllimport)
+#endif
+#else
+#define LWS_EXTERN
+#endif
+
+#else // NOT WIN32
+
+#include <poll.h>
+#include <unistd.h>
+
+#if defined(__GNUC__)
+#define LWS_VISIBLE __attribute__((visibility("default")))
+#else
+#define LWS_VISIBLE
+#endif
+
+#endif
+
+#ifdef LWS_USE_LIBEV
+#include <ev.h>
+#endif /* LWS_USE_LIBEV */
+
+#include <assert.h>
+
+#ifndef LWS_EXTERN
+#define LWS_EXTERN extern
+#endif
+	
+#ifdef _WIN32
+#define random rand
+#else
+#include <sys/time.h>
+#include <unistd.h>
+#endif
+
+#ifdef LWS_OPENSSL_SUPPORT
+#ifdef USE_CYASSL
+#include <cyassl/openssl/ssl.h>
+#else
+#include <openssl/ssl.h>
+#endif /* not USE_CYASSL */
+#endif
+
+#define CONTEXT_PORT_NO_LISTEN -1
+#define MAX_MUX_RECURSION 2
+
+enum lws_log_levels {
+	LLL_ERR = 1 << 0,
+	LLL_WARN = 1 << 1,
+	LLL_NOTICE = 1 << 2,
+	LLL_INFO = 1 << 3,
+	LLL_DEBUG = 1 << 4,
+	LLL_PARSER = 1 << 5,
+	LLL_HEADER = 1 << 6,
+	LLL_EXT = 1 << 7,
+	LLL_CLIENT = 1 << 8,
+	LLL_LATENCY = 1 << 9,
+
+	LLL_COUNT = 10 /* set to count of valid flags */
+};
+
+LWS_VISIBLE LWS_EXTERN void _lws_log(int filter, const char *format, ...);
+LWS_VISIBLE LWS_EXTERN void _lws_logv(int filter, const char *format, va_list vl);
+
+/* notice, warn and log are always compiled in */
+#define lwsl_notice(...) _lws_log(LLL_NOTICE, __VA_ARGS__)
+#define lwsl_warn(...) _lws_log(LLL_WARN, __VA_ARGS__)
+#define lwsl_err(...) _lws_log(LLL_ERR, __VA_ARGS__)
+/*
+ *  weaker logging can be deselected at configure time using --disable-debug
+ *  that gets rid of the overhead of checking while keeping _warn and _err
+ *  active
+ */
+#ifdef _DEBUG
+
+#define lwsl_info(...) _lws_log(LLL_INFO, __VA_ARGS__)
+#define lwsl_debug(...) _lws_log(LLL_DEBUG, __VA_ARGS__)
+#define lwsl_parser(...) _lws_log(LLL_PARSER, __VA_ARGS__)
+#define lwsl_header(...)  _lws_log(LLL_HEADER, __VA_ARGS__)
+#define lwsl_ext(...)  _lws_log(LLL_EXT, __VA_ARGS__)
+#define lwsl_client(...) _lws_log(LLL_CLIENT, __VA_ARGS__)
+#define lwsl_latency(...) _lws_log(LLL_LATENCY, __VA_ARGS__)
+LWS_VISIBLE LWS_EXTERN void lwsl_hexdump(void *buf, size_t len);
+
+#else /* no debug */
+
+#define lwsl_info(...)
+#define lwsl_debug(...)
+#define lwsl_parser(...)
+#define lwsl_header(...)
+#define lwsl_ext(...)
+#define lwsl_client(...)
+#define lwsl_latency(...)
+#define lwsl_hexdump(a, b)
+
+#endif
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
+
+/* api change list for user code to test against */
+
+#define LWS_FEATURE_SERVE_HTTP_FILE_HAS_OTHER_HEADERS_ARG
+
+/* the struct libwebsocket_protocols has the id field present */
+#define LWS_FEATURE_PROTOCOLS_HAS_ID_FIELD
+
+/* you can call lws_get_peer_write_allowance */
+#define LWS_FEATURE_PROTOCOLS_HAS_PEER_WRITE_ALLOWANCE
+
+/* extra parameter introduced in 917f43ab821 */
+#define LWS_FEATURE_SERVE_HTTP_FILE_HAS_OTHER_HEADERS_LEN
+
+enum libwebsocket_context_options {
+	LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT = 2,
+	LWS_SERVER_OPTION_SKIP_SERVER_CANONICAL_NAME = 4,
+	LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT = 8,
+	LWS_SERVER_OPTION_LIBEV = 16,
+	LWS_SERVER_OPTION_DISABLE_IPV6 = 32,
+	LWS_SERVER_OPTION_DISABLE_OS_CA_CERTS = 64,
+};
+
+enum libwebsocket_callback_reasons {
+	LWS_CALLBACK_ESTABLISHED,
+	LWS_CALLBACK_CLIENT_CONNECTION_ERROR,
+	LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH,
+	LWS_CALLBACK_CLIENT_ESTABLISHED,
+	LWS_CALLBACK_CLOSED,
+	LWS_CALLBACK_CLOSED_HTTP,
+	LWS_CALLBACK_RECEIVE,
+	LWS_CALLBACK_CLIENT_RECEIVE,
+	LWS_CALLBACK_CLIENT_RECEIVE_PONG,
+	LWS_CALLBACK_CLIENT_WRITEABLE,
+	LWS_CALLBACK_SERVER_WRITEABLE,
+	LWS_CALLBACK_HTTP,
+	LWS_CALLBACK_HTTP_BODY,
+	LWS_CALLBACK_HTTP_BODY_COMPLETION,
+	LWS_CALLBACK_HTTP_FILE_COMPLETION,
+	LWS_CALLBACK_HTTP_WRITEABLE,
+	LWS_CALLBACK_FILTER_NETWORK_CONNECTION,
+	LWS_CALLBACK_FILTER_HTTP_CONNECTION,
+	LWS_CALLBACK_SERVER_NEW_CLIENT_INSTANTIATED,
+	LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION,
+	LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS,
+	LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS,
+	LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION,
+	LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER,
+	LWS_CALLBACK_CONFIRM_EXTENSION_OKAY,
+	LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED,
+	LWS_CALLBACK_PROTOCOL_INIT,
+	LWS_CALLBACK_PROTOCOL_DESTROY,
+	LWS_CALLBACK_WSI_CREATE, /* always protocol[0] */
+	LWS_CALLBACK_WSI_DESTROY, /* always protocol[0] */
+	LWS_CALLBACK_GET_THREAD_ID,
+
+	/* external poll() management support */
+	LWS_CALLBACK_ADD_POLL_FD,
+	LWS_CALLBACK_DEL_POLL_FD,
+	LWS_CALLBACK_CHANGE_MODE_POLL_FD,
+	LWS_CALLBACK_LOCK_POLL,
+	LWS_CALLBACK_UNLOCK_POLL,
+
+	LWS_CALLBACK_OPENSSL_CONTEXT_REQUIRES_PRIVATE_KEY,
+	
+	LWS_CALLBACK_USER = 1000, /* user code can use any including / above */
+};
+
+// argument structure for all external poll related calls
+// passed in via 'in'
+struct libwebsocket_pollargs {
+    int fd;            // applicable file descriptor
+    int events;        // the new event mask
+    int prev_events;   // the previous event mask
+};
+
+#ifdef _WIN32
+struct libwebsocket_pollfd {
+	SOCKET fd;
+	SHORT events;
+	SHORT revents;
+};
+#else
+#define libwebsocket_pollfd pollfd
+#endif
+
+enum libwebsocket_extension_callback_reasons {
+	LWS_EXT_CALLBACK_SERVER_CONTEXT_CONSTRUCT,
+	LWS_EXT_CALLBACK_CLIENT_CONTEXT_CONSTRUCT,
+	LWS_EXT_CALLBACK_SERVER_CONTEXT_DESTRUCT,
+	LWS_EXT_CALLBACK_CLIENT_CONTEXT_DESTRUCT,
+	LWS_EXT_CALLBACK_CONSTRUCT,
+	LWS_EXT_CALLBACK_CLIENT_CONSTRUCT,
+	LWS_EXT_CALLBACK_CHECK_OK_TO_REALLY_CLOSE,
+	LWS_EXT_CALLBACK_CHECK_OK_TO_PROPOSE_EXTENSION,
+	LWS_EXT_CALLBACK_DESTROY,
+	LWS_EXT_CALLBACK_DESTROY_ANY_WSI_CLOSING,
+	LWS_EXT_CALLBACK_ANY_WSI_ESTABLISHED,
+	LWS_EXT_CALLBACK_PACKET_RX_PREPARSE,
+	LWS_EXT_CALLBACK_PACKET_TX_PRESEND,
+	LWS_EXT_CALLBACK_PACKET_TX_DO_SEND,
+	LWS_EXT_CALLBACK_HANDSHAKE_REPLY_TX,
+	LWS_EXT_CALLBACK_FLUSH_PENDING_TX,
+	LWS_EXT_CALLBACK_EXTENDED_PAYLOAD_RX,
+	LWS_EXT_CALLBACK_CAN_PROXY_CLIENT_CONNECTION,
+	LWS_EXT_CALLBACK_1HZ,
+	LWS_EXT_CALLBACK_REQUEST_ON_WRITEABLE,
+	LWS_EXT_CALLBACK_IS_WRITEABLE,
+	LWS_EXT_CALLBACK_PAYLOAD_TX,
+	LWS_EXT_CALLBACK_PAYLOAD_RX,
+};
+
+enum libwebsocket_write_protocol {
+	LWS_WRITE_TEXT,
+	LWS_WRITE_BINARY,
+	LWS_WRITE_CONTINUATION,
+	LWS_WRITE_HTTP,
+
+	/* special 04+ opcodes */
+
+	LWS_WRITE_CLOSE,
+	LWS_WRITE_PING,
+	LWS_WRITE_PONG,
+
+	/* Same as write_http but we know this write ends the transaction */
+	LWS_WRITE_HTTP_FINAL,
+	
+	/* HTTP2 */
+
+	LWS_WRITE_HTTP_HEADERS,
+	
+	/* flags */
+
+	LWS_WRITE_NO_FIN = 0x40,
+	/*
+	 * client packet payload goes out on wire unmunged
+	 * only useful for security tests since normal servers cannot
+	 * decode the content if used
+	 */
+	LWS_WRITE_CLIENT_IGNORE_XOR_MASK = 0x80
+};
+
+/*
+ * you need these to look at headers that have been parsed if using the
+ * LWS_CALLBACK_FILTER_CONNECTION callback.  If a header from the enum
+ * list below is absent, .token = NULL and token_len = 0.  Otherwise .token
+ * points to .token_len chars containing that header content.
+ */
+
+struct lws_tokens {
+	char *token;
+	int token_len;
+};
+
+/*
+ * don't forget to update test server header dump accordingly
+ *
+ * these have to be kept in sync with lextable.h / minilex.c
+ */
+
+enum lws_token_indexes {
+	WSI_TOKEN_GET_URI,
+	WSI_TOKEN_POST_URI,
+	WSI_TOKEN_OPTIONS_URI,
+	WSI_TOKEN_HOST,
+	WSI_TOKEN_CONNECTION,
+	WSI_TOKEN_UPGRADE,
+	WSI_TOKEN_ORIGIN,
+	WSI_TOKEN_DRAFT,
+	WSI_TOKEN_CHALLENGE,
+	WSI_TOKEN_EXTENSIONS,
+	WSI_TOKEN_KEY1,
+	WSI_TOKEN_KEY2,
+	WSI_TOKEN_PROTOCOL,
+	WSI_TOKEN_ACCEPT,
+	WSI_TOKEN_NONCE,
+	WSI_TOKEN_HTTP,
+	WSI_TOKEN_HTTP2_SETTINGS,
+	WSI_TOKEN_HTTP_ACCEPT,
+	WSI_TOKEN_HTTP_AC_REQUEST_HEADERS,
+	WSI_TOKEN_HTTP_IF_MODIFIED_SINCE,
+	WSI_TOKEN_HTTP_IF_NONE_MATCH,
+	WSI_TOKEN_HTTP_ACCEPT_ENCODING,
+	WSI_TOKEN_HTTP_ACCEPT_LANGUAGE,
+	WSI_TOKEN_HTTP_PRAGMA,
+	WSI_TOKEN_HTTP_CACHE_CONTROL,
+	WSI_TOKEN_HTTP_AUTHORIZATION,
+	WSI_TOKEN_HTTP_COOKIE,
+	WSI_TOKEN_HTTP_CONTENT_LENGTH,
+	WSI_TOKEN_HTTP_CONTENT_TYPE,
+	WSI_TOKEN_HTTP_DATE,
+	WSI_TOKEN_HTTP_RANGE,
+	WSI_TOKEN_HTTP_REFERER,
+	WSI_TOKEN_KEY,
+	WSI_TOKEN_VERSION,
+	WSI_TOKEN_SWORIGIN,
+
+	WSI_TOKEN_HTTP_COLON_AUTHORITY,
+	WSI_TOKEN_HTTP_COLON_METHOD,
+	WSI_TOKEN_HTTP_COLON_PATH,
+	WSI_TOKEN_HTTP_COLON_SCHEME,
+	WSI_TOKEN_HTTP_COLON_STATUS,
+	
+	WSI_TOKEN_HTTP_ACCEPT_CHARSET,
+	WSI_TOKEN_HTTP_ACCEPT_RANGES,
+	WSI_TOKEN_HTTP_ACCESS_CONTROL_ALLOW_ORIGIN,
+	WSI_TOKEN_HTTP_AGE,
+	WSI_TOKEN_HTTP_ALLOW,
+	WSI_TOKEN_HTTP_CONTENT_DISPOSITION,
+	WSI_TOKEN_HTTP_CONTENT_ENCODING,
+	WSI_TOKEN_HTTP_CONTENT_LANGUAGE,
+	WSI_TOKEN_HTTP_CONTENT_LOCATION,
+	WSI_TOKEN_HTTP_CONTENT_RANGE,
+	WSI_TOKEN_HTTP_ETAG,
+	WSI_TOKEN_HTTP_EXPECT,
+	WSI_TOKEN_HTTP_EXPIRES,
+	WSI_TOKEN_HTTP_FROM,
+	WSI_TOKEN_HTTP_IF_MATCH,
+	WSI_TOKEN_HTTP_IF_RANGE,
+	WSI_TOKEN_HTTP_IF_UNMODIFIED_SINCE,
+	WSI_TOKEN_HTTP_LAST_MODIFIED,
+	WSI_TOKEN_HTTP_LINK,
+	WSI_TOKEN_HTTP_LOCATION,
+	WSI_TOKEN_HTTP_MAX_FORWARDS,
+	WSI_TOKEN_HTTP_PROXY_AUTHENTICATE,
+	WSI_TOKEN_HTTP_PROXY_AUTHORIZATION,
+	WSI_TOKEN_HTTP_REFRESH,
+	WSI_TOKEN_HTTP_RETRY_AFTER,
+	WSI_TOKEN_HTTP_SERVER,
+	WSI_TOKEN_HTTP_SET_COOKIE,
+	WSI_TOKEN_HTTP_STRICT_TRANSPORT_SECURITY,
+	WSI_TOKEN_HTTP_TRANSFER_ENCODING,
+	WSI_TOKEN_HTTP_USER_AGENT,
+	WSI_TOKEN_HTTP_VARY,
+	WSI_TOKEN_HTTP_VIA,
+	WSI_TOKEN_HTTP_WWW_AUTHENTICATE,
+	WSI_TOKEN_PROXY,
+	
+	WSI_TOKEN_HTTP_URI_ARGS,
+
+	/* use token storage to stash these */
+
+	_WSI_TOKEN_CLIENT_SENT_PROTOCOLS,
+	_WSI_TOKEN_CLIENT_PEER_ADDRESS,
+	_WSI_TOKEN_CLIENT_URI,
+	_WSI_TOKEN_CLIENT_HOST,
+	_WSI_TOKEN_CLIENT_ORIGIN,
+	
+	/* always last real token index*/
+	WSI_TOKEN_COUNT,
+	/* parser state additions */
+	WSI_TOKEN_NAME_PART,
+	WSI_TOKEN_SKIPPING,
+	WSI_TOKEN_SKIPPING_SAW_CR,
+	WSI_PARSING_COMPLETE,
+	WSI_INIT_TOKEN_MUXURL,
+};
+
+struct lws_token_limits {
+    unsigned short token_limit[WSI_TOKEN_COUNT];
+};
+
+/*
+ * From RFC 6455
+   1000
+
+      1000 indicates a normal closure, meaning that the purpose for
+      which the connection was established has been fulfilled.
+
+   1001
+
+      1001 indicates that an endpoint is "going away", such as a server
+      going down or a browser having navigated away from a page.
+
+   1002
+
+      1002 indicates that an endpoint is terminating the connection due
+      to a protocol error.
+
+   1003
+
+      1003 indicates that an endpoint is terminating the connection
+      because it has received a type of data it cannot accept (e.g., an
+      endpoint that understands only text data MAY send this if it
+      receives a binary message).
+
+   1004
+
+      Reserved.  The specific meaning might be defined in the future.
+
+   1005
+
+      1005 is a reserved value and MUST NOT be set as a status code in a
+      Close control frame by an endpoint.  It is designated for use in
+      applications expecting a status code to indicate that no status
+      code was actually present.
+
+   1006
+
+      1006 is a reserved value and MUST NOT be set as a status code in a
+      Close control frame by an endpoint.  It is designated for use in
+      applications expecting a status code to indicate that the
+      connection was closed abnormally, e.g., without sending or
+      receiving a Close control frame.
+
+   1007
+
+      1007 indicates that an endpoint is terminating the connection
+      because it has received data within a message that was not
+      consistent with the type of the message (e.g., non-UTF-8 [RFC3629]
+      data within a text message).
+
+   1008
+
+      1008 indicates that an endpoint is terminating the connection
+      because it has received a message that violates its policy.  This
+      is a generic status code that can be returned when there is no
+      other more suitable status code (e.g., 1003 or 1009) or if there
+      is a need to hide specific details about the policy.
+
+   1009
+
+      1009 indicates that an endpoint is terminating the connection
+      because it has received a message that is too big for it to
+      process.
+
+   1010
+
+      1010 indicates that an endpoint (client) is terminating the
+      connection because it has expected the server to negotiate one or
+      more extension, but the server didn't return them in the response
+      message of the WebSocket handshake.  The list of extensions that
+      are needed SHOULD appear in the /reason/ part of the Close frame.
+      Note that this status code is not used by the server, because it
+      can fail the WebSocket handshake instead.
+
+   1011
+
+      1011 indicates that a server is terminating the connection because
+      it encountered an unexpected condition that prevented it from
+      fulfilling the request.
+
+   1015
+
+      1015 is a reserved value and MUST NOT be set as a status code in a
+      Close control frame by an endpoint.  It is designated for use in
+      applications expecting a status code to indicate that the
+      connection was closed due to a failure to perform a TLS handshake
+      (e.g., the server certificate can't be verified).
+*/
+
+enum lws_close_status {
+	LWS_CLOSE_STATUS_NOSTATUS = 0,
+	LWS_CLOSE_STATUS_NORMAL = 1000,
+	LWS_CLOSE_STATUS_GOINGAWAY = 1001,
+	LWS_CLOSE_STATUS_PROTOCOL_ERR = 1002,
+	LWS_CLOSE_STATUS_UNACCEPTABLE_OPCODE = 1003,
+	LWS_CLOSE_STATUS_RESERVED = 1004,
+	LWS_CLOSE_STATUS_NO_STATUS = 1005,
+	LWS_CLOSE_STATUS_ABNORMAL_CLOSE = 1006,
+	LWS_CLOSE_STATUS_INVALID_PAYLOAD = 1007,
+	LWS_CLOSE_STATUS_POLICY_VIOLATION = 1008,
+	LWS_CLOSE_STATUS_MESSAGE_TOO_LARGE = 1009,
+	LWS_CLOSE_STATUS_EXTENSION_REQUIRED = 1010,
+	LWS_CLOSE_STATUS_UNEXPECTED_CONDITION = 1011,
+	LWS_CLOSE_STATUS_TLS_FAILURE = 1015,
+};
+
+enum http_status {
+	HTTP_STATUS_OK = 200,
+	HTTP_STATUS_NO_CONTENT = 204,
+
+	HTTP_STATUS_BAD_REQUEST = 400,
+	HTTP_STATUS_UNAUTHORIZED,
+	HTTP_STATUS_PAYMENT_REQUIRED,
+	HTTP_STATUS_FORBIDDEN,
+	HTTP_STATUS_NOT_FOUND,
+	HTTP_STATUS_METHOD_NOT_ALLOWED,
+	HTTP_STATUS_NOT_ACCEPTABLE,
+	HTTP_STATUS_PROXY_AUTH_REQUIRED,
+	HTTP_STATUS_REQUEST_TIMEOUT,
+	HTTP_STATUS_CONFLICT,
+	HTTP_STATUS_GONE,
+	HTTP_STATUS_LENGTH_REQUIRED,
+	HTTP_STATUS_PRECONDITION_FAILED,
+	HTTP_STATUS_REQ_ENTITY_TOO_LARGE,
+	HTTP_STATUS_REQ_URI_TOO_LONG,
+	HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE,
+	HTTP_STATUS_REQ_RANGE_NOT_SATISFIABLE,
+	HTTP_STATUS_EXPECTATION_FAILED,
+
+	HTTP_STATUS_INTERNAL_SERVER_ERROR = 500,
+	HTTP_STATUS_NOT_IMPLEMENTED,
+	HTTP_STATUS_BAD_GATEWAY,
+	HTTP_STATUS_SERVICE_UNAVAILABLE,
+	HTTP_STATUS_GATEWAY_TIMEOUT,
+	HTTP_STATUS_HTTP_VERSION_NOT_SUPPORTED,
+};
+
+struct libwebsocket;
+struct libwebsocket_context;
+/* needed even with extensions disabled for create context */
+struct libwebsocket_extension;
+
+/**
+ * callback_function() - User server actions
+ * @context:	Websockets context
+ * @wsi:	Opaque websocket instance pointer
+ * @reason:	The reason for the call
+ * @user:	Pointer to per-session user data allocated by library
+ * @in:		Pointer used for some callback reasons
+ * @len:	Length set for some callback reasons
+ *
+ *	This callback is the way the user controls what is served.  All the
+ *	protocol detail is hidden and handled by the library.
+ *
+ *	For each connection / session there is user data allocated that is
+ *	pointed to by "user".  You set the size of this user data area when
+ *	the library is initialized with libwebsocket_create_server.
+ *
+ *	You get an opportunity to initialize user data when called back with
+ *	LWS_CALLBACK_ESTABLISHED reason.
+ *
+ *  LWS_CALLBACK_ESTABLISHED:  after the server completes a handshake with
+ *				an incoming client
+ *
+ *  LWS_CALLBACK_CLIENT_CONNECTION_ERROR: the request client connection has
+ *        been unable to complete a handshake with the remote server
+ *
+ *  LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH: this is the last chance for the
+ *				client user code to examine the http headers
+ *				and decide to reject the connection.  If the
+ *				content in the headers is interesting to the
+ *				client (url, etc) it needs to copy it out at
+ *				this point since it will be destroyed before
+ *				the CLIENT_ESTABLISHED call
+ *
+ *  LWS_CALLBACK_CLIENT_ESTABLISHED: after your client connection completed
+ *				a handshake with the remote server
+ *
+ *	LWS_CALLBACK_CLOSED: when the websocket session ends
+ *
+ *	LWS_CALLBACK_CLOSED_HTTP: when a HTTP (non-websocket) session ends
+ *
+ *	LWS_CALLBACK_RECEIVE: data has appeared for this server endpoint from a
+ *				remote client, it can be found at *in and is
+ *				len bytes long
+ *
+ *	LWS_CALLBACK_CLIENT_RECEIVE_PONG: if you elected to see PONG packets,
+ *				they appear with this callback reason.  PONG
+ *				packets only exist in 04+ protocol
+ *
+ *	LWS_CALLBACK_CLIENT_RECEIVE: data has appeared from the server for the
+ *				client connection, it can be found at *in and
+ *				is len bytes long
+ *
+ *	LWS_CALLBACK_HTTP: an http request has come from a client that is not
+ *				asking to upgrade the connection to a websocket
+ *				one.  This is a chance to serve http content,
+ *				for example, to send a script to the client
+ *				which will then open the websockets connection.
+ *				@in points to the URI path requested and
+ *				libwebsockets_serve_http_file() makes it very
+ *				simple to send back a file to the client.
+ *				Normally after sending the file you are done
+ *				with the http connection, since the rest of the
+ *				activity will come by websockets from the script
+ *				that was delivered by http, so you will want to
+ *				return 1; to close and free up the connection.
+ *				That's important because it uses a slot in the
+ *				total number of client connections allowed set
+ *				by MAX_CLIENTS.
+ *
+ *	LWS_CALLBACK_HTTP_BODY: the next @len bytes data from the http
+ *		request body HTTP connection is now available in @in.
+ *
+ *	LWS_CALLBACK_HTTP_BODY_COMPLETION: the expected amount of http request
+ *		body has been delivered
+ *
+ *	LWS_CALLBACK_HTTP_WRITEABLE: you can write more down the http protocol
+ *		link now.
+ *
+ *	LWS_CALLBACK_HTTP_FILE_COMPLETION: a file requested to be send down
+ *				http link has completed.
+ *
+ *	LWS_CALLBACK_CLIENT_WRITEABLE:
+ *      LWS_CALLBACK_SERVER_WRITEABLE:   If you call
+ *		libwebsocket_callback_on_writable() on a connection, you will
+ *		get one of these callbacks coming when the connection socket
+ *		is able to accept another write packet without blocking.
+ *		If it already was able to take another packet without blocking,
+ *		you'll get this callback at the next call to the service loop
+ *		function.  Notice that CLIENTs get LWS_CALLBACK_CLIENT_WRITEABLE
+ *		and servers get LWS_CALLBACK_SERVER_WRITEABLE.
+ *
+ *	LWS_CALLBACK_FILTER_NETWORK_CONNECTION: called when a client connects to
+ *		the server at network level; the connection is accepted but then
+ *		passed to this callback to decide whether to hang up immediately
+ *		or not, based on the client IP.  @in contains the connection
+ *		socket's descriptor. Since the client connection information is
+ *		not available yet, @wsi still pointing to the main server socket.
+ *		Return non-zero to terminate the connection before sending or
+ *		receiving anything. Because this happens immediately after the
+ *		network connection from the client, there's no websocket protocol
+ *		selected yet so this callback is issued only to protocol 0.
+ * 
+ *	LWS_CALLBACK_SERVER_NEW_CLIENT_INSTANTIATED: A new client just had
+ *		been connected, accepted, and instantiated into the pool. This
+ *		callback allows setting any relevant property to it. Because this
+ *		happens immediately after the instantiation of a new client,
+ *		there's no websocket protocol selected yet so this callback is
+ *		issued only to protocol 0. Only @wsi is defined, pointing to the
+ *		new client, and the return value is ignored.
+ *
+ *	LWS_CALLBACK_FILTER_HTTP_CONNECTION: called when the request has
+ *		been received and parsed from the client, but the response is
+ *		not sent yet.  Return non-zero to disallow the connection.
+ *		@user is a pointer to the connection user space allocation,
+ *		@in is the URI, eg, "/"
+ *		In your handler you can use the public APIs
+ *		lws_hdr_total_length() / lws_hdr_copy() to access all of the
+ *		headers using the header enums lws_token_indexes from
+ *		libwebsockets.h to check for and read the supported header
+ *		presence and content before deciding to allow the http
+ *		connection to proceed or to kill the connection.
+ *
+ *	LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION: called when the handshake has
+ *		been received and parsed from the client, but the response is
+ *		not sent yet.  Return non-zero to disallow the connection.
+ *		@user is a pointer to the connection user space allocation,
+ *		@in is the requested protocol name
+ *		In your handler you can use the public APIs
+ *		lws_hdr_total_length() / lws_hdr_copy() to access all of the
+ *		headers using the header enums lws_token_indexes from
+ *		libwebsockets.h to check for and read the supported header
+ *		presence and content before deciding to allow the handshake
+ *		to proceed or to kill the connection.
+ *
+ *	LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS: if configured for
+ *		including OpenSSL support, this callback allows your user code
+ *		to perform extra SSL_CTX_load_verify_locations() or similar
+ *		calls to direct OpenSSL where to find certificates the client
+ *		can use to confirm the remote server identity.  @user is the
+ *		OpenSSL SSL_CTX*
+ *
+ *	LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS: if configured for
+ *		including OpenSSL support, this callback allows your user code
+ *		to load extra certifcates into the server which allow it to
+ *		verify the validity of certificates returned by clients.  @user
+ *		is the server's OpenSSL SSL_CTX*
+ *
+ *	LWS_CALLBACK_OPENSSL_CONTEXT_REQUIRES_PRIVATE_KEY: if configured for
+ *		including OpenSSL support but no private key file has been specified
+ *		(ssl_private_key_filepath is NULL), this callback is called to
+ *		allow the user to set the private key directly via libopenssl
+ *		and perform further operations if required; this might be useful
+ *		in situations where the private key is not directly accessible by
+ *		the OS, for example if it is stored on a smartcard
+ *		@user is the server's OpenSSL SSL_CTX*
+ *
+ *	LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION: if the
+ *		libwebsockets context was created with the option
+ *		LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT, then this
+ *		callback is generated during OpenSSL verification of the cert
+ *		sent from the client.  It is sent to protocol[0] callback as
+ *		no protocol has been negotiated on the connection yet.
+ *		Notice that the libwebsockets context and wsi are both NULL
+ *		during this callback.  See
+ *		 http://www.openssl.org/docs/ssl/SSL_CTX_set_verify.html
+ *		to understand more detail about the OpenSSL callback that
+ *		generates this libwebsockets callback and the meanings of the
+ *		arguments passed.  In this callback, @user is the x509_ctx,
+ *		@in is the ssl pointer and @len is preverify_ok
+ *		Notice that this callback maintains libwebsocket return
+ *		conventions, return 0 to mean the cert is OK or 1 to fail it.
+ *		This also means that if you don't handle this callback then
+ *		the default callback action of returning 0 allows the client
+ *		certificates.
+ *
+ *	LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER: this callback happens
+ *		when a client handshake is being compiled.  @user is NULL,
+ *		@in is a char **, it's pointing to a char * which holds the
+ *		next location in the header buffer where you can add
+ *		headers, and @len is the remaining space in the header buffer,
+ *		which is typically some hundreds of bytes.  So, to add a canned
+ *		cookie, your handler code might look similar to:
+ *
+ *		char **p = (char **)in;
+ *
+ *		if (len < 100)
+ *			return 1;
+ *
+ *		*p += sprintf(*p, "Cookie: a=b\x0d\x0a");
+ *
+ *		return 0;
+ *
+ *		Notice if you add anything, you just have to take care about
+ *		the CRLF on the line you added.  Obviously this callback is
+ *		optional, if you don't handle it everything is fine.
+ *
+ *		Notice the callback is coming to protocols[0] all the time,
+ *		because there is no specific protocol handshook yet.
+ *
+ *	LWS_CALLBACK_CONFIRM_EXTENSION_OKAY: When the server handshake code
+ *		sees that it does support a requested extension, before
+ *		accepting the extension by additing to the list sent back to
+ *		the client it gives this callback just to check that it's okay
+ *		to use that extension.  It calls back to the requested protocol
+ *		and with @in being the extension name, @len is 0 and @user is
+ *		valid.  Note though at this time the ESTABLISHED callback hasn't
+ *		happened yet so if you initialize @user content there, @user
+ *		content during this callback might not be useful for anything.
+ *		Notice this callback comes to protocols[0].
+ *
+ *	LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED:	When a client
+ *		connection is being prepared to start a handshake to a server,
+ *		each supported extension is checked with protocols[0] callback
+ *		with this reason, giving the user code a chance to suppress the
+ *		claim to support that extension by returning non-zero.  If
+ *		unhandled, by default 0 will be returned and the extension
+ *		support included in the header to the server.  Notice this
+ *		callback comes to protocols[0].
+ *
+ *	LWS_CALLBACK_PROTOCOL_INIT:	One-time call per protocol so it can
+ *		do initial setup / allocations etc
+ *
+ *	LWS_CALLBACK_PROTOCOL_DESTROY:	One-time call per protocol indicating
+ *		this protocol won't get used at all after this callback, the
+ *		context is getting destroyed.  Take the opportunity to
+ *		deallocate everything that was allocated by the protocol.
+ *
+ *	LWS_CALLBACK_WSI_CREATE: outermost (earliest) wsi create notification
+ *
+ *	LWS_CALLBACK_WSI_DESTROY: outermost (latest) wsi destroy notification
+ *
+ *	The next five reasons are optional and only need taking care of if you
+ *	will be integrating libwebsockets sockets into an external polling
+ *	array.
+ *
+ *	For these calls, @in points to a struct libwebsocket_pollargs that
+ *	contains @fd, @events and @prev_events members
+ *
+ *	LWS_CALLBACK_ADD_POLL_FD: libwebsocket deals with its poll() loop
+ *		internally, but in the case you are integrating with another
+ *		server you will need to have libwebsocket sockets share a
+ *		polling array with the other server.  This and the other
+ *		POLL_FD related callbacks let you put your specialized
+ *		poll array interface code in the callback for protocol 0, the
+ *		first protocol you support, usually the HTTP protocol in the
+ *		serving case.
+ *		This callback happens when a socket needs to be
+ *		added to the polling loop: @in points to a struct
+ *		libwebsocket_pollargs; the @fd member of the struct is the file
+ *		descriptor, and @events contains the active events.
+ *
+ *		If you are using the internal polling loop (the "service"
+ *		callback), you can just ignore these callbacks.
+ *
+ *	LWS_CALLBACK_DEL_POLL_FD: This callback happens when a socket descriptor
+ *		needs to be removed from an external polling array.  @in is
+ *		again the struct libwebsocket_pollargs containing the @fd member
+ *		to be removed.  If you are using the internal polling
+ *		loop, you can just ignore it.
+ *
+ *	LWS_CALLBACK_CHANGE_MODE_POLL_FD: This callback happens when
+ *		libwebsockets wants to modify the events for a connectiion.
+ *		@in is the struct libwebsocket_pollargs with the @fd to change.
+ *		The new event mask is in @events member and the old mask is in
+ *		the @prev_events member.
+ *		If you are using the internal polling loop, you can just ignore
+ *		it.
+ *
+ *	LWS_CALLBACK_LOCK_POLL:
+ *	LWS_CALLBACK_UNLOCK_POLL: These allow the external poll changes driven
+ *		by libwebsockets to participate in an external thread locking
+ *		scheme around the changes, so the whole thing is threadsafe.
+ */
+LWS_VISIBLE LWS_EXTERN int callback(struct libwebsocket_context *context,
+			struct libwebsocket *wsi,
+			 enum libwebsocket_callback_reasons reason, void *user,
+							  void *in, size_t len);
+
+typedef int (callback_function)(struct libwebsocket_context *context,
+			struct libwebsocket *wsi,
+			 enum libwebsocket_callback_reasons reason, void *user,
+							  void *in, size_t len);
+
+#ifndef LWS_NO_EXTENSIONS
+/**
+ * extension_callback_function() - Hooks to allow extensions to operate
+ * @context:	Websockets context
+ * @ext:	This extension
+ * @wsi:	Opaque websocket instance pointer
+ * @reason:	The reason for the call
+ * @user:	Pointer to per-session user data allocated by library
+ * @in:		Pointer used for some callback reasons
+ * @len:	Length set for some callback reasons
+ *
+ *	Each extension that is active on a particular connection receives
+ *	callbacks during the connection lifetime to allow the extension to
+ *	operate on websocket data and manage itself.
+ *
+ *	Libwebsockets takes care of allocating and freeing "user" memory for
+ *	each active extension on each connection.  That is what is pointed to
+ *	by the @user parameter.
+ *
+ *	LWS_EXT_CALLBACK_CONSTRUCT:  called when the server has decided to
+ *		select this extension from the list provided by the client,
+ *		just before the server will send back the handshake accepting
+ *		the connection with this extension active.  This gives the
+ *		extension a chance to initialize its connection context found
+ *		in @user.
+ *
+ *	LWS_EXT_CALLBACK_CLIENT_CONSTRUCT: same as LWS_EXT_CALLBACK_CONSTRUCT
+ *		but called when client is instantiating this extension.  Some
+ *		extensions will work the same on client and server side and then
+ *		you can just merge handlers for both CONSTRUCTS.
+ *
+ *	LWS_EXT_CALLBACK_DESTROY:  called when the connection the extension was
+ *		being used on is about to be closed and deallocated.  It's the
+ *		last chance for the extension to deallocate anything it has
+ *		allocated in the user data (pointed to by @user) before the
+ *		user data is deleted.  This same callback is used whether you
+ *		are in client or server instantiation context.
+ *
+ *	LWS_EXT_CALLBACK_PACKET_RX_PREPARSE: when this extension was active on
+ *		a connection, and a packet of data arrived at the connection,
+ *		it is passed to this callback to give the extension a chance to
+ *		change the data, eg, decompress it.  @user is pointing to the
+ *		extension's private connection context data, @in is pointing
+ *		to an lws_tokens struct, it consists of a char * pointer called
+ *		token, and an int called token_len.  At entry, these are
+ *		set to point to the received buffer and set to the content
+ *		length.  If the extension will grow the content, it should use
+ *		a new buffer allocated in its private user context data and
+ *		set the pointed-to lws_tokens members to point to its buffer.
+ *
+ *	LWS_EXT_CALLBACK_PACKET_TX_PRESEND: this works the same way as
+ *		LWS_EXT_CALLBACK_PACKET_RX_PREPARSE above, except it gives the
+ *		extension a chance to change websocket data just before it will
+ *		be sent out.  Using the same lws_token pointer scheme in @in,
+ *		the extension can change the buffer and the length to be
+ *		transmitted how it likes.  Again if it wants to grow the
+ *		buffer safely, it should copy the data into its own buffer and
+ *		set the lws_tokens token pointer to it.
+ */
+LWS_VISIBLE LWS_EXTERN int extension_callback(struct libwebsocket_context *context,
+			struct libwebsocket_extension *ext,
+			struct libwebsocket *wsi,
+			enum libwebsocket_extension_callback_reasons reason,
+			void *user, void *in, size_t len);
+
+typedef int (extension_callback_function)(struct libwebsocket_context *context,
+			struct libwebsocket_extension *ext,
+			struct libwebsocket *wsi,
+			enum libwebsocket_extension_callback_reasons reason,
+			void *user, void *in, size_t len);
+#endif
+
+/**
+ * struct libwebsocket_protocols -	List of protocols and handlers server
+ *					supports.
+ * @name:	Protocol name that must match the one given in the client
+ *		Javascript new WebSocket(url, 'protocol') name.
+ * @callback:	The service callback used for this protocol.  It allows the
+ *		service action for an entire protocol to be encapsulated in
+ *		the protocol-specific callback
+ * @per_session_data_size:	Each new connection using this protocol gets
+ *		this much memory allocated on connection establishment and
+ *		freed on connection takedown.  A pointer to this per-connection
+ *		allocation is passed into the callback in the 'user' parameter
+ * @rx_buffer_size: if you want atomic frames delivered to the callback, you
+ *		should set this to the size of the biggest legal frame that
+ *		you support.  If the frame size is exceeded, there is no
+ *		error, but the buffer will spill to the user callback when
+ *		full, which you can detect by using
+ *		libwebsockets_remaining_packet_payload().  Notice that you
+ *		just talk about frame size here, the LWS_SEND_BUFFER_PRE_PADDING
+ *		and post-padding are automatically also allocated on top.
+ * @id:		ignored by lws, but useful to contain user information bound
+ *		to the selected protocol.  For example if this protocol was
+ *		called "myprotocol-v2", you might set id to 2, and the user
+ *		code that acts differently according to the version can do so by
+ *		switch (wsi->protocol->id), user code might use some bits as
+ *		capability flags based on selected protocol version, etc.
+ * @user:	User provided context data at the protocol level.
+ *		Accessible via libwebsockets_get_protocol(wsi)->user
+ *		This should not be confused with wsi->user, it is not the same.
+ *		The library completely ignores any value in here.
+ * @owning_server:	the server init call fills in this opaque pointer when
+ *		registering this protocol with the server.
+ * @protocol_index: which protocol we are starting from zero
+ *
+ *	This structure represents one protocol supported by the server.  An
+ *	array of these structures is passed to libwebsocket_create_server()
+ *	allows as many protocols as you like to be handled by one server.
+ *
+ *	The first protocol given has its callback used for user callbacks when
+ *	there is no agreed protocol name, that's true during HTTP part of the
+ *	connection and true if the client did not send a Protocol: header.
+ */
+
+struct libwebsocket_protocols {
+	const char *name;
+	callback_function *callback;
+	size_t per_session_data_size;
+	size_t rx_buffer_size;
+	unsigned int id;
+	void *user;
+
+	/*
+	 * below are filled in on server init and can be left uninitialized,
+	 * no need for user to use them directly either
+	 */
+
+	struct libwebsocket_context *owning_server;
+	int protocol_index;
+};
+
+#ifndef LWS_NO_EXTENSIONS
+/**
+ * struct libwebsocket_extension -	An extension we know how to cope with
+ *
+ * @name:			Formal extension name, eg, "deflate-stream"
+ * @callback:			Service callback
+ * @per_session_data_size:	Libwebsockets will auto-malloc this much
+ *				memory for the use of the extension, a pointer
+ *				to it comes in the @user callback parameter
+ * @per_context_private_data:   Optional storage for this extension that
+ *				is per-context, so it can track stuff across
+ *				all sessions, etc, if it wants
+ */
+
+struct libwebsocket_extension {
+	const char *name;
+	extension_callback_function *callback;
+	size_t per_session_data_size;
+	void *per_context_private_data;
+};
+#endif
+
+/**
+ * struct lws_context_creation_info: parameters to create context with
+ *
+ * @port:	Port to listen on... you can use CONTEXT_PORT_NO_LISTEN to
+ *		suppress listening on any port, that's what you want if you are
+ *		not running a websocket server at all but just using it as a
+ *		client
+ * @iface:	NULL to bind the listen socket to all interfaces, or the
+ *		interface name, eg, "eth2"
+ * @protocols:	Array of structures listing supported protocols and a protocol-
+ *		specific callback for each one.  The list is ended with an
+ *		entry that has a NULL callback pointer.
+ *		It's not const because we write the owning_server member
+ * @extensions: NULL or array of libwebsocket_extension structs listing the
+ *		extensions this context supports.  If you configured with
+ *		--without-extensions, you should give NULL here.
+ * @token_limits: NULL or struct lws_token_limits pointer which is initialized
+ *      with a token length limit for each possible WSI_TOKEN_*** 
+ * @ssl_cert_filepath:	If libwebsockets was compiled to use ssl, and you want
+ *			to listen using SSL, set to the filepath to fetch the
+ *			server cert from, otherwise NULL for unencrypted
+ * @ssl_private_key_filepath: filepath to private key if wanting SSL mode;
+ *			if this is set to NULL but sll_cert_filepath is set, the
+ *			OPENSSL_CONTEXT_REQUIRES_PRIVATE_KEY callback is called to allow
+ *			setting of the private key directly via openSSL library calls
+ * @ssl_ca_filepath: CA certificate filepath or NULL
+ * @ssl_cipher_list:	List of valid ciphers to use (eg,
+ * 			"RC4-MD5:RC4-SHA:AES128-SHA:AES256-SHA:HIGH:!DSS:!aNULL"
+ * 			or you can leave it as NULL to get "DEFAULT"
+ * @gid:	group id to change to after setting listen socket, or -1.
+ * @uid:	user id to change to after setting listen socket, or -1.
+ * @options:	0, or LWS_SERVER_OPTION_DEFEAT_CLIENT_MASK
+ * @user:	optional user pointer that can be recovered via the context
+ *		pointer using libwebsocket_context_user
+ * @ka_time:	0 for no keepalive, otherwise apply this keepalive timeout to
+ *		all libwebsocket sockets, client or server
+ * @ka_probes:	if ka_time was nonzero, after the timeout expires how many
+ *		times to try to get a response from the peer before giving up
+ *		and killing the connection
+ * @ka_interval: if ka_time was nonzero, how long to wait before each ka_probes
+ *		attempt
+ * @provided_client_ssl_ctx: If non-null, swap out libwebsockets ssl
+ *		implementation for the one provided by provided_ssl_ctx.
+ *		Libwebsockets no longer is responsible for freeing the context
+ *		if this option is selected.
+ */
+
+struct lws_context_creation_info {
+	int port;
+	const char *iface;
+	struct libwebsocket_protocols *protocols;
+	struct libwebsocket_extension *extensions;
+	struct lws_token_limits *token_limits;
+	const char *ssl_private_key_password;
+	const char *ssl_cert_filepath;
+	const char *ssl_private_key_filepath;
+	const char *ssl_ca_filepath;
+	const char *ssl_cipher_list;
+	const char *http_proxy_address;
+	unsigned int http_proxy_port;
+	int gid;
+	int uid;
+	unsigned int options;
+	void *user;
+	int ka_time;
+	int ka_probes;
+	int ka_interval;
+#ifdef LWS_OPENSSL_SUPPORT
+	SSL_CTX *provided_client_ssl_ctx;
+#else /* maintain structure layout either way */
+    	void *provided_client_ssl_ctx;
+#endif
+};
+
+LWS_VISIBLE LWS_EXTERN
+void lws_set_log_level(int level,
+			void (*log_emit_function)(int level, const char *line));
+
+LWS_VISIBLE LWS_EXTERN void
+lwsl_emit_syslog(int level, const char *line);
+
+LWS_VISIBLE LWS_EXTERN struct libwebsocket_context *
+libwebsocket_create_context(struct lws_context_creation_info *info);
+	
+LWS_VISIBLE LWS_EXTERN int
+libwebsocket_set_proxy(struct libwebsocket_context *context, const char *proxy);
+
+LWS_VISIBLE LWS_EXTERN void
+libwebsocket_context_destroy(struct libwebsocket_context *context);
+
+LWS_VISIBLE LWS_EXTERN int
+libwebsocket_service(struct libwebsocket_context *context, int timeout_ms);
+
+LWS_VISIBLE LWS_EXTERN void
+libwebsocket_cancel_service(struct libwebsocket_context *context);
+
+LWS_VISIBLE LWS_EXTERN const unsigned char *
+lws_token_to_string(enum lws_token_indexes token);
+
+LWS_VISIBLE LWS_EXTERN int
+lws_add_http_header_by_name(struct libwebsocket_context *context,
+			    struct libwebsocket *wsi,
+			    const unsigned char *name,
+			    const unsigned char *value,
+			    int length,
+			    unsigned char **p,
+			    unsigned char *end);
+LWS_VISIBLE LWS_EXTERN int 
+lws_finalize_http_header(struct libwebsocket_context *context,
+			    struct libwebsocket *wsi,
+			    unsigned char **p,
+			    unsigned char *end);
+LWS_VISIBLE LWS_EXTERN int
+lws_add_http_header_by_token(struct libwebsocket_context *context,
+			    struct libwebsocket *wsi,
+			    enum lws_token_indexes token,
+			    const unsigned char *value,
+			    int length,
+			    unsigned char **p,
+			    unsigned char *end);
+LWS_VISIBLE LWS_EXTERN int lws_add_http_header_content_length(struct libwebsocket_context *context,
+			    struct libwebsocket *wsi,
+			    unsigned long content_length,
+			    unsigned char **p,
+			    unsigned char *end);
+LWS_VISIBLE LWS_EXTERN int
+lws_add_http_header_status(struct libwebsocket_context *context,
+			    struct libwebsocket *wsi,
+			    unsigned int code,
+			    unsigned char **p,
+			    unsigned char *end);
+
+LWS_EXTERN int lws_http_transaction_completed(struct libwebsocket *wsi);
+
+#ifdef LWS_USE_LIBEV
+LWS_VISIBLE LWS_EXTERN int
+libwebsocket_initloop(
+	struct libwebsocket_context *context, struct ev_loop *loop);
+
+LWS_VISIBLE void
+libwebsocket_sigint_cb(
+	struct ev_loop *loop, struct ev_signal *watcher, int revents);
+#endif /* LWS_USE_LIBEV */
+
+LWS_VISIBLE LWS_EXTERN int
+libwebsocket_service_fd(struct libwebsocket_context *context,
+							 struct libwebsocket_pollfd *pollfd);
+
+LWS_VISIBLE LWS_EXTERN void *
+libwebsocket_context_user(struct libwebsocket_context *context);
+
+enum pending_timeout {
+	NO_PENDING_TIMEOUT = 0,
+	PENDING_TIMEOUT_AWAITING_PROXY_RESPONSE,
+	PENDING_TIMEOUT_AWAITING_CONNECT_RESPONSE,
+	PENDING_TIMEOUT_ESTABLISH_WITH_SERVER,
+	PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE,
+	PENDING_TIMEOUT_AWAITING_PING,
+	PENDING_TIMEOUT_CLOSE_ACK,
+	PENDING_TIMEOUT_AWAITING_EXTENSION_CONNECT_RESPONSE,
+	PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE,
+	PENDING_TIMEOUT_SSL_ACCEPT,
+	PENDING_TIMEOUT_HTTP_CONTENT,
+	PENDING_TIMEOUT_AWAITING_CLIENT_HS_SEND,
+};
+
+LWS_VISIBLE LWS_EXTERN void
+libwebsocket_set_timeout(struct libwebsocket *wsi,
+					 enum pending_timeout reason, int secs);
+
+/*
+ * IMPORTANT NOTICE!
+ *
+ * When sending with websocket protocol (LWS_WRITE_TEXT or LWS_WRITE_BINARY)
+ * the send buffer has to have LWS_SEND_BUFFER_PRE_PADDING bytes valid BEFORE
+ * buf, and LWS_SEND_BUFFER_POST_PADDING bytes valid AFTER (buf + len).
+ *
+ * This allows us to add protocol info before and after the data, and send as
+ * one packet on the network without payload copying, for maximum efficiency.
+ *
+ * So for example you need this kind of code to use libwebsocket_write with a
+ * 128-byte payload
+ *
+ *   char buf[LWS_SEND_BUFFER_PRE_PADDING + 128 + LWS_SEND_BUFFER_POST_PADDING];
+ *
+ *   // fill your part of the buffer... for example here it's all zeros
+ *   memset(&buf[LWS_SEND_BUFFER_PRE_PADDING], 0, 128);
+ *
+ *   libwebsocket_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING], 128,
+ *   								LWS_WRITE_TEXT);
+ *
+ * When sending LWS_WRITE_HTTP, there is no protocol addition and you can just
+ * use the whole buffer without taking care of the above.
+ */
+
+/*
+ * this is the frame nonce plus two header plus 8 length
+ *   there's an additional two for mux extension per mux nesting level
+ * 2 byte prepend on close will already fit because control frames cannot use
+ * the big length style
+ */
+
+#define LWS_SEND_BUFFER_PRE_PADDING (4 + 10 + (2 * MAX_MUX_RECURSION))
+#define LWS_SEND_BUFFER_POST_PADDING 4
+
+LWS_VISIBLE LWS_EXTERN int
+libwebsocket_write(struct libwebsocket *wsi, unsigned char *buf, size_t len,
+				     enum libwebsocket_write_protocol protocol);
+
+/* helper for case where buffer may be const */
+#define libwebsocket_write_http(wsi, buf, len) \
+	libwebsocket_write(wsi, (unsigned char *)(buf), len, LWS_WRITE_HTTP)
+
+LWS_VISIBLE LWS_EXTERN int
+libwebsockets_serve_http_file(struct libwebsocket_context *context,
+			struct libwebsocket *wsi, const char *file,
+			const char *content_type, const char *other_headers,
+			int other_headers_len);
+LWS_VISIBLE LWS_EXTERN int
+libwebsockets_serve_http_file_fragment(struct libwebsocket_context *context,
+			struct libwebsocket *wsi);
+
+LWS_VISIBLE LWS_EXTERN int libwebsockets_return_http_status(
+		struct libwebsocket_context *context,
+			struct libwebsocket *wsi, unsigned int code,
+							const char *html_body);
+
+LWS_VISIBLE LWS_EXTERN const struct libwebsocket_protocols *
+libwebsockets_get_protocol(struct libwebsocket *wsi);
+
+LWS_VISIBLE LWS_EXTERN int
+libwebsocket_callback_on_writable(struct libwebsocket_context *context,
+						      struct libwebsocket *wsi);
+
+LWS_VISIBLE LWS_EXTERN int
+libwebsocket_callback_on_writable_all_protocol(
+				 const struct libwebsocket_protocols *protocol);
+
+LWS_VISIBLE LWS_EXTERN int
+libwebsocket_callback_all_protocol(
+		const struct libwebsocket_protocols *protocol, int reason);
+
+LWS_VISIBLE LWS_EXTERN int
+libwebsocket_get_socket_fd(struct libwebsocket *wsi);
+
+LWS_VISIBLE LWS_EXTERN int
+libwebsocket_is_final_fragment(struct libwebsocket *wsi);
+
+LWS_VISIBLE LWS_EXTERN unsigned char
+libwebsocket_get_reserved_bits(struct libwebsocket *wsi);
+
+LWS_VISIBLE LWS_EXTERN int
+libwebsocket_rx_flow_control(struct libwebsocket *wsi, int enable);
+
+LWS_VISIBLE LWS_EXTERN void
+libwebsocket_rx_flow_allow_all_protocol(
+				const struct libwebsocket_protocols *protocol);
+
+LWS_VISIBLE LWS_EXTERN size_t
+libwebsockets_remaining_packet_payload(struct libwebsocket *wsi);
+
+/*
+ * if the protocol does not have any guidence, returns -1.  Currently only
+ * http2 connections get send window information from this API.  But your code
+ * should use it so it can work properly with any protocol.
+ * 
+ * If nonzero return is the amount of payload data the peer or intermediary has
+ * reported it has buffer space for.  That has NO relationship with the amount
+ * of buffer space your OS can accept on this connection for a write action.
+ * 
+ * This number represents the maximum you could send to the peer or intermediary
+ * on this connection right now without it complaining.
+ * 
+ * lws manages accounting for send window updates and payload writes
+ * automatically, so this number reflects the situation at the peer or
+ * intermediary dynamically.
+ */
+LWS_VISIBLE LWS_EXTERN size_t
+lws_get_peer_write_allowance(struct libwebsocket *wsi);
+
+LWS_VISIBLE LWS_EXTERN struct libwebsocket *
+libwebsocket_client_connect(struct libwebsocket_context *clients,
+			      const char *address,
+			      int port,
+			      int ssl_connection,
+			      const char *path,
+			      const char *host,
+			      const char *origin,
+			      const char *protocol,
+			      int ietf_version_or_minus_one);
+
+LWS_VISIBLE LWS_EXTERN struct libwebsocket *
+libwebsocket_client_connect_extended(struct libwebsocket_context *clients,
+			      const char *address,
+			      int port,
+			      int ssl_connection,
+			      const char *path,
+			      const char *host,
+			      const char *origin,
+			      const char *protocol,
+			      int ietf_version_or_minus_one,
+			      void *userdata);
+
+LWS_VISIBLE LWS_EXTERN const char *
+libwebsocket_canonical_hostname(struct libwebsocket_context *context);
+
+
+LWS_VISIBLE LWS_EXTERN void
+libwebsockets_get_peer_addresses(struct libwebsocket_context *context,
+		struct libwebsocket *wsi, int fd, char *name, int name_len,
+					char *rip, int rip_len);
+
+LWS_VISIBLE LWS_EXTERN int
+libwebsockets_get_random(struct libwebsocket_context *context,
+							    void *buf, int len);
+
+LWS_VISIBLE LWS_EXTERN int
+lws_daemonize(const char *_lock_path);
+
+LWS_VISIBLE LWS_EXTERN int
+lws_send_pipe_choked(struct libwebsocket *wsi);
+
+LWS_VISIBLE LWS_EXTERN int
+lws_partial_buffered(struct libwebsocket *wsi);
+
+LWS_VISIBLE LWS_EXTERN int
+lws_frame_is_binary(struct libwebsocket *wsi);
+
+LWS_VISIBLE LWS_EXTERN int
+lws_is_ssl(struct libwebsocket *wsi);
+
+LWS_VISIBLE LWS_EXTERN unsigned char *
+libwebsockets_SHA1(const unsigned char *d, size_t n, unsigned char *md);
+
+LWS_VISIBLE LWS_EXTERN int
+lws_b64_encode_string(const char *in, int in_len, char *out, int out_size);
+
+LWS_VISIBLE LWS_EXTERN int
+lws_b64_decode_string(const char *in, char *out, int out_size);
+
+LWS_VISIBLE LWS_EXTERN const char *
+lws_get_library_version(void);
+
+/* access to headers... only valid while headers valid */
+
+LWS_VISIBLE LWS_EXTERN int
+lws_hdr_total_length(struct libwebsocket *wsi, enum lws_token_indexes h);
+
+LWS_VISIBLE LWS_EXTERN int
+lws_hdr_copy(struct libwebsocket *wsi, char *dest, int len,
+						enum lws_token_indexes h);
+
+/*
+ * Note: this is not normally needed as a user api.  It's provided in case it is
+ * useful when integrating with other app poll loop service code.
+ */
+
+LWS_VISIBLE LWS_EXTERN int
+libwebsocket_read(struct libwebsocket_context *context,
+				struct libwebsocket *wsi,
+					       unsigned char *buf, size_t len);
+
+#ifndef LWS_NO_EXTENSIONS
+LWS_VISIBLE LWS_EXTERN struct libwebsocket_extension *libwebsocket_get_internal_extensions();
+#endif
+
+/*
+ * custom allocator support
+ */
+LWS_VISIBLE LWS_EXTERN void
+lws_set_allocator(void *(*realloc)(void *ptr, size_t size));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/engine/external/libwebsockets/lws-plat-unix.c b/src/engine/external/libwebsockets/lws-plat-unix.c
new file mode 100644
index 00000000..9af4bdfd
--- /dev/null
+++ b/src/engine/external/libwebsockets/lws-plat-unix.c
@@ -0,0 +1,442 @@
+#include "private-libwebsockets.h"
+
+/*
+ * included from libwebsockets.c for unix builds
+ */
+
+unsigned long long time_in_microseconds(void)
+{
+	struct timeval tv;
+	gettimeofday(&tv, NULL);
+	return (tv.tv_sec * 1000000) + tv.tv_usec;
+}
+
+LWS_VISIBLE int libwebsockets_get_random(struct libwebsocket_context *context,
+							     void *buf, int len)
+{
+	return read(context->fd_random, (char *)buf, len);
+}
+
+LWS_VISIBLE int lws_send_pipe_choked(struct libwebsocket *wsi)
+{
+	struct libwebsocket_pollfd fds;
+
+	/* treat the fact we got a truncated send pending as if we're choked */
+	if (wsi->truncated_send_len)
+		return 1;
+
+	fds.fd = wsi->sock;
+	fds.events = POLLOUT;
+	fds.revents = 0;
+
+	if (poll(&fds, 1, 0) != 1)
+		return 1;
+
+	if ((fds.revents & POLLOUT) == 0)
+		return 1;
+
+	/* okay to send another packet without blocking */
+
+	return 0;
+}
+
+LWS_VISIBLE int
+lws_poll_listen_fd(struct libwebsocket_pollfd *fd)
+{
+	return poll(fd, 1, 0);
+}
+
+/*
+ * This is just used to interrupt poll waiting
+ * we don't have to do anything with it.
+ */
+static void lws_sigusr2(int sig)
+{
+}
+
+/**
+ * libwebsocket_cancel_service() - Cancel servicing of pending websocket activity
+ * @context:	Websocket context
+ *
+ *	This function let a call to libwebsocket_service() waiting for a timeout
+ *	immediately return.
+ */
+LWS_VISIBLE void
+libwebsocket_cancel_service(struct libwebsocket_context *context)
+{
+	char buf = 0;
+
+	if (write(context->dummy_pipe_fds[1], &buf, sizeof(buf)) != 1)
+		lwsl_err("Cannot write to dummy pipe");
+}
+
+LWS_VISIBLE void lwsl_emit_syslog(int level, const char *line)
+{
+	int syslog_level = LOG_DEBUG;
+
+	switch (level) {
+	case LLL_ERR:
+		syslog_level = LOG_ERR;
+		break;
+	case LLL_WARN:
+		syslog_level = LOG_WARNING;
+		break;
+	case LLL_NOTICE:
+		syslog_level = LOG_NOTICE;
+		break;
+	case LLL_INFO:
+		syslog_level = LOG_INFO;
+		break;
+	}
+	syslog(syslog_level, "%s", line);
+}
+
+LWS_VISIBLE int
+lws_plat_service(struct libwebsocket_context *context, int timeout_ms)
+{
+	int n;
+	int m;
+	char buf;
+
+	/* stay dead once we are dead */
+
+	if (!context)
+		return 1;
+
+	lws_libev_run(context);
+
+	context->service_tid = context->protocols[0].callback(context, NULL,
+				     LWS_CALLBACK_GET_THREAD_ID, NULL, NULL, 0);
+
+#ifdef LWS_OPENSSL_SUPPORT
+	/* if we know we have non-network pending data, do not wait in poll */
+	if (context->ssl_flag_buffered_reads)
+		timeout_ms = 0;
+#endif
+	n = poll(context->fds, context->fds_count, timeout_ms);
+	context->service_tid = 0;
+
+#ifdef LWS_OPENSSL_SUPPORT
+	if (!context->ssl_flag_buffered_reads && n == 0) {
+#else
+	if (n == 0) /* poll timeout */ {
+#endif
+		libwebsocket_service_fd(context, NULL);
+		return 0;
+	}
+	
+#ifdef LWS_OPENSSL_SUPPORT
+	/* any more will have to set it fresh this time around */
+	context->ssl_flag_buffered_reads = 0;
+#endif
+
+	if (n < 0) {
+		if (LWS_ERRNO != LWS_EINTR)
+			return -1;
+		return 0;
+	}
+
+	/* any socket with events to service? */
+
+	for (n = 0; n < context->fds_count; n++) {
+#ifdef LWS_OPENSSL_SUPPORT
+		struct libwebsocket *wsi;
+		
+		wsi = context->lws_lookup[context->fds[n].fd];
+		if (wsi == NULL)
+			continue;
+		/* 
+		 * if he's not flowcontrolled, make sure we service ssl
+		 * pending read data
+		 */
+		if (wsi->ssl && wsi->buffered_reads_pending) {
+			lwsl_debug("wsi %p: forcing POLLIN\n", wsi);
+			context->fds[n].revents |= context->fds[n].events & POLLIN;
+			if (context->fds[n].revents & POLLIN)
+				wsi->buffered_reads_pending = 0;
+			else
+				/* somebody left with pending SSL read data */
+				context->ssl_flag_buffered_reads = 1;
+		}
+#endif
+		if (!context->fds[n].revents)
+			continue;
+
+		if (context->fds[n].fd == context->dummy_pipe_fds[0]) {
+			if (read(context->fds[n].fd, &buf, 1) != 1)
+				lwsl_err("Cannot read from dummy pipe.");
+			continue;
+		}
+
+		m = libwebsocket_service_fd(context, &context->fds[n]);
+		if (m < 0)
+			return -1;
+		/* if something closed, retry this slot */
+		if (m)
+			n--;
+	}
+
+	return 0;
+}
+
+LWS_VISIBLE int
+lws_plat_set_socket_options(struct libwebsocket_context *context, int fd)
+{
+	int optval = 1;
+	socklen_t optlen = sizeof(optval);
+
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || \
+    defined(__OpenBSD__)
+	struct protoent *tcp_proto;
+#endif
+
+	if (context->ka_time) {
+		/* enable keepalive on this socket */
+		optval = 1;
+		if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE,
+					     (const void *)&optval, optlen) < 0)
+			return 1;
+
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || \
+        defined(__CYGWIN__) || defined(__OpenBSD__)
+
+		/*
+		 * didn't find a way to set these per-socket, need to
+		 * tune kernel systemwide values
+		 */
+#else
+		/* set the keepalive conditions we want on it too */
+		optval = context->ka_time;
+		if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE,
+					     (const void *)&optval, optlen) < 0)
+			return 1;
+
+		optval = context->ka_interval;
+		if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL,
+					     (const void *)&optval, optlen) < 0)
+			return 1;
+
+		optval = context->ka_probes;
+		if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT,
+					     (const void *)&optval, optlen) < 0)
+			return 1;
+#endif
+	}
+
+	/* Disable Nagle */
+	optval = 1;
+#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__NetBSD__) && \
+    !defined(__OpenBSD__)
+	if (setsockopt(fd, SOL_TCP, TCP_NODELAY, (const void *)&optval, optlen) < 0)
+		return 1;
+#else
+	tcp_proto = getprotobyname("TCP");
+	if (setsockopt(fd, tcp_proto->p_proto, TCP_NODELAY, &optval, optlen) < 0)
+		return 1;
+#endif
+
+	/* We are nonblocking... */
+	if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
+		return 1;
+
+	return 0;
+}
+
+LWS_VISIBLE void
+lws_plat_drop_app_privileges(struct lws_context_creation_info *info)
+{
+	if (info->gid != -1)
+		if (setgid(info->gid))
+			lwsl_warn("setgid: %s\n", strerror(LWS_ERRNO));
+	if (info->uid != -1)
+		if (setuid(info->uid))
+			lwsl_warn("setuid: %s\n", strerror(LWS_ERRNO));
+}
+
+LWS_VISIBLE int
+lws_plat_init_fd_tables(struct libwebsocket_context *context)
+{
+	if (lws_libev_init_fd_table(context))
+		/* libev handled it instead */
+		return 0;
+
+	if (pipe(context->dummy_pipe_fds)) {
+		lwsl_err("Unable to create pipe\n");
+		return 1;
+	}
+
+	/* use the read end of pipe as first item */
+	context->fds[0].fd = context->dummy_pipe_fds[0];
+	context->fds[0].events = LWS_POLLIN;
+	context->fds[0].revents = 0;
+	context->fds_count = 1;
+
+	context->fd_random = open(SYSTEM_RANDOM_FILEPATH, O_RDONLY);
+	if (context->fd_random < 0) {
+		lwsl_err("Unable to open random device %s %d\n",
+				    SYSTEM_RANDOM_FILEPATH, context->fd_random);
+		return 1;
+	}
+
+	return 0;
+}
+
+static void sigpipe_handler(int x)
+{
+}
+
+
+LWS_VISIBLE int
+lws_plat_context_early_init(void)
+{
+	sigset_t mask;
+
+	signal(SIGUSR2, lws_sigusr2);
+	sigemptyset(&mask);
+	sigaddset(&mask, SIGUSR2);
+
+	sigprocmask(SIG_BLOCK, &mask, NULL);
+
+	signal(SIGPIPE, sigpipe_handler);
+
+	return 0;
+}
+
+LWS_VISIBLE void
+lws_plat_context_early_destroy(struct libwebsocket_context *context)
+{
+}
+
+LWS_VISIBLE void
+lws_plat_context_late_destroy(struct libwebsocket_context *context)
+{
+	close(context->dummy_pipe_fds[0]);
+	close(context->dummy_pipe_fds[1]);
+	close(context->fd_random);
+}
+
+/* cast a struct sockaddr_in6 * into addr for ipv6 */
+
+LWS_VISIBLE int
+interface_to_sa(struct libwebsocket_context *context,
+		const char *ifname, struct sockaddr_in *addr, size_t addrlen)
+{
+	int rc = -1;
+
+	struct ifaddrs *ifr;
+	struct ifaddrs *ifc;
+#ifdef LWS_USE_IPV6
+	struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
+#endif
+
+	getifaddrs(&ifr);
+	for (ifc = ifr; ifc != NULL && rc; ifc = ifc->ifa_next) {
+		if (!ifc->ifa_addr)
+			continue;
+
+		lwsl_info(" interface %s vs %s\n", ifc->ifa_name, ifname);
+
+		if (strcmp(ifc->ifa_name, ifname))
+			continue;
+
+		switch (ifc->ifa_addr->sa_family) {
+		case AF_INET:
+#ifdef LWS_USE_IPV6
+			if (LWS_IPV6_ENABLED(context)) {
+				/* map IPv4 to IPv6 */
+				bzero((char *)&addr6->sin6_addr,
+						sizeof(struct in6_addr));
+				addr6->sin6_addr.s6_addr[10] = 0xff;
+				addr6->sin6_addr.s6_addr[11] = 0xff;
+				memcpy(&addr6->sin6_addr.s6_addr[12],
+					&((struct sockaddr_in *)ifc->ifa_addr)->sin_addr,
+							sizeof(struct in_addr));
+			} else
+#endif
+				memcpy(addr,
+					(struct sockaddr_in *)ifc->ifa_addr,
+						    sizeof(struct sockaddr_in));
+			break;
+#ifdef LWS_USE_IPV6
+		case AF_INET6:
+			memcpy(&addr6->sin6_addr,
+			  &((struct sockaddr_in6 *)ifc->ifa_addr)->sin6_addr,
+						       sizeof(struct in6_addr));
+			break;
+#endif
+		default:
+			continue;
+		}
+		rc = 0;
+	}
+
+	freeifaddrs(ifr);
+
+	if (rc == -1) {
+		/* check if bind to IP adddress */
+#ifdef LWS_USE_IPV6
+		if (inet_pton(AF_INET6, ifname, &addr6->sin6_addr) == 1)
+			rc = 0;
+		else
+#endif
+		if (inet_pton(AF_INET, ifname, &addr->sin_addr) == 1)
+			rc = 0;
+	}
+
+	return rc;
+}
+
+LWS_VISIBLE void
+lws_plat_insert_socket_into_fds(struct libwebsocket_context *context,
+						       struct libwebsocket *wsi)
+{
+	lws_libev_io(context, wsi, LWS_EV_START | LWS_EV_READ);
+	context->fds[context->fds_count++].revents = 0;
+}
+
+LWS_VISIBLE void
+lws_plat_delete_socket_from_fds(struct libwebsocket_context *context,
+						struct libwebsocket *wsi, int m)
+{
+}
+
+LWS_VISIBLE void
+lws_plat_service_periodic(struct libwebsocket_context *context)
+{
+	/* if our parent went down, don't linger around */
+	if (context->started_with_parent &&
+			      kill(context->started_with_parent, 0) < 0)
+		kill(getpid(), SIGTERM);
+}
+
+LWS_VISIBLE int
+lws_plat_change_pollfd(struct libwebsocket_context *context,
+		      struct libwebsocket *wsi, struct libwebsocket_pollfd *pfd)
+{
+	return 0;
+}
+
+LWS_VISIBLE int
+lws_plat_open_file(const char* filename, unsigned long* filelen)
+{
+	struct stat stat_buf;
+	int ret = open(filename, O_RDONLY);
+
+	if (ret < 0)
+		return LWS_INVALID_FILE;
+
+	if (fstat(ret, &stat_buf) < 0) {
+		close(ret);
+		return LWS_INVALID_FILE;
+	}
+	*filelen = stat_buf.st_size;
+	return ret;
+}
+
+#ifdef LWS_USE_IPV6
+LWS_VISIBLE const char *
+lws_plat_inet_ntop(int af, const void *src, char *dst, int cnt)
+{
+	return inet_ntop(af, src, dst, cnt);
+}
+#endif
diff --git a/src/engine/external/libwebsockets/output.c b/src/engine/external/libwebsockets/output.c
new file mode 100644
index 00000000..b914f281
--- /dev/null
+++ b/src/engine/external/libwebsockets/output.c
@@ -0,0 +1,606 @@
+/*
+ * libwebsockets - small server side websockets and web server implementation
+ *
+ * Copyright (C) 2010-2014 Andy Green <andy@warmcat.com>
+ *
+ *  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:
+ *  version 2.1 of the License.
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston,
+ *  MA  02110-1301  USA
+ */
+
+#include "private-libwebsockets.h"
+
+static int
+libwebsocket_0405_frame_mask_generate(struct libwebsocket *wsi)
+{
+	int n;
+
+	/* fetch the per-frame nonce */
+
+	n = libwebsockets_get_random(wsi->protocol->owning_server,
+					   wsi->u.ws.frame_masking_nonce_04, 4);
+	if (n != 4) {
+		lwsl_parser("Unable to read from random device %s %d\n",
+						     SYSTEM_RANDOM_FILEPATH, n);
+		return 1;
+	}
+
+	/* start masking from first byte of masking key buffer */
+	wsi->u.ws.frame_mask_index = 0;
+
+	return 0;
+}
+
+#ifdef _DEBUG
+
+LWS_VISIBLE void lwsl_hexdump(void *vbuf, size_t len)
+{
+	int n;
+	int m;
+	int start;
+	unsigned char *buf = (unsigned char *)vbuf;
+	char line[80];
+	char *p;
+
+	lwsl_parser("\n");
+
+	for (n = 0; n < len;) {
+		start = n;
+		p = line;
+
+		p += sprintf(p, "%04X: ", start);
+
+		for (m = 0; m < 16 && n < len; m++)
+			p += sprintf(p, "%02X ", buf[n++]);
+		while (m++ < 16)
+			p += sprintf(p, "   ");
+
+		p += sprintf(p, "   ");
+
+		for (m = 0; m < 16 && (start + m) < len; m++) {
+			if (buf[start + m] >= ' ' && buf[start + m] < 127)
+				*p++ = buf[start + m];
+			else
+				*p++ = '.';
+		}
+		while (m++ < 16)
+			*p++ = ' ';
+
+		*p++ = '\n';
+		*p = '\0';
+		lwsl_debug("%s", line);
+	}
+	lwsl_debug("\n");
+}
+
+#endif
+
+/*
+ * notice this returns number of bytes consumed, or -1
+ */
+
+int lws_issue_raw(struct libwebsocket *wsi, unsigned char *buf, size_t len)
+{
+	struct libwebsocket_context *context = wsi->protocol->owning_server;
+	int n;
+	size_t real_len = len;
+	int m;
+	
+	if (!len)
+		return 0;
+	/* just ignore sends after we cleared the truncation buffer */
+	if (wsi->state == WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE &&
+						!wsi->truncated_send_len)
+		return len;
+
+	if (wsi->truncated_send_len && (buf < wsi->truncated_send_malloc ||
+			buf > (wsi->truncated_send_malloc +
+				wsi->truncated_send_len +
+				wsi->truncated_send_offset))) {
+		lwsl_err("****** %x Sending new, pending truncated ...\n", wsi);
+		assert(0);
+	}
+
+	m = lws_ext_callback_for_each_active(wsi,
+			LWS_EXT_CALLBACK_PACKET_TX_DO_SEND, &buf, len);
+	if (m < 0)
+		return -1;
+	if (m) /* handled */ {
+		n = m;
+		goto handle_truncated_send;
+	}
+	if (wsi->sock < 0)
+		lwsl_warn("** error invalid sock but expected to send\n");
+
+	/*
+	 * nope, send it on the socket directly
+	 */
+	lws_latency_pre(context, wsi);
+	n = lws_ssl_capable_write(wsi, buf, len);
+	lws_latency(context, wsi, "send lws_issue_raw", n, n == len);
+
+	switch (n) {
+	case LWS_SSL_CAPABLE_ERROR:
+		/* we're going to close, let close know sends aren't possible */
+		wsi->socket_is_permanently_unusable = 1;
+		return -1;
+	case LWS_SSL_CAPABLE_MORE_SERVICE:
+		/* nothing got sent, not fatal, retry the whole thing later */
+		n = 0;
+		break;
+	}
+
+handle_truncated_send:
+	/*
+	 * we were already handling a truncated send?
+	 */
+	if (wsi->truncated_send_len) {
+		lwsl_info("***** %x partial send moved on by %d (vs %d)\n",
+							     wsi, n, real_len);
+		wsi->truncated_send_offset += n;
+		wsi->truncated_send_len -= n;
+
+		if (!wsi->truncated_send_len) {
+			lwsl_info("***** %x partial send completed\n", wsi);
+			/* done with it, but don't free it */
+			n = real_len;
+			if (wsi->state == WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE) {
+				lwsl_info("***** %x signalling to close now\n", wsi);
+				return -1; /* retry closing now */
+			}
+		}
+		/* always callback on writeable */
+		libwebsocket_callback_on_writable(
+					     wsi->protocol->owning_server, wsi);
+
+		return n;
+	}
+
+	if (n == real_len)
+		/* what we just sent went out cleanly */
+		return n;
+
+	if (n && wsi->u.ws.clean_buffer)
+		/*
+		 * This buffer unaffected by extension rewriting.
+		 * It means the user code is expected to deal with
+		 * partial sends.  (lws knows the header was already
+		 * sent, so on next send will just resume sending
+		 * payload)
+		 */
+		 return n;
+
+	/*
+	 * Newly truncated send.  Buffer the remainder (it will get
+	 * first priority next time the socket is writable)
+	 */
+	lwsl_info("***** %x new partial sent %d from %d total\n",
+						      wsi, n, real_len);
+
+	/*
+	 *  - if we still have a suitable malloc lying around, use it
+	 *  - or, if too small, reallocate it
+	 *  - or, if no buffer, create it
+	 */
+	if (!wsi->truncated_send_malloc ||
+			real_len - n > wsi->truncated_send_allocation) {
+		lws_free(wsi->truncated_send_malloc);
+
+		wsi->truncated_send_allocation = real_len - n;
+		wsi->truncated_send_malloc = lws_malloc(real_len - n);
+		if (!wsi->truncated_send_malloc) {
+			lwsl_err("truncated send: unable to malloc %d\n",
+							  real_len - n);
+			return -1;
+		}
+	}
+	wsi->truncated_send_offset = 0;
+	wsi->truncated_send_len = real_len - n;
+	memcpy(wsi->truncated_send_malloc, buf + n, real_len - n);
+
+	/* since something buffered, force it to get another chance to send */
+	libwebsocket_callback_on_writable(wsi->protocol->owning_server, wsi);
+
+	return real_len;
+}
+
+/**
+ * libwebsocket_write() - Apply protocol then write data to client
+ * @wsi:	Websocket instance (available from user callback)
+ * @buf:	The data to send.  For data being sent on a websocket
+ *		connection (ie, not default http), this buffer MUST have
+ *		LWS_SEND_BUFFER_PRE_PADDING bytes valid BEFORE the pointer
+ *		and an additional LWS_SEND_BUFFER_POST_PADDING bytes valid
+ *		in the buffer after (buf + len).  This is so the protocol
+ *		header and trailer data can be added in-situ.
+ * @len:	Count of the data bytes in the payload starting from buf
+ * @protocol:	Use LWS_WRITE_HTTP to reply to an http connection, and one
+ *		of LWS_WRITE_BINARY or LWS_WRITE_TEXT to send appropriate
+ *		data on a websockets connection.  Remember to allow the extra
+ *		bytes before and after buf if LWS_WRITE_BINARY or LWS_WRITE_TEXT
+ *		are used.
+ *
+ *	This function provides the way to issue data back to the client
+ *	for both http and websocket protocols.
+ *
+ *	In the case of sending using websocket protocol, be sure to allocate
+ *	valid storage before and after buf as explained above.  This scheme
+ *	allows maximum efficiency of sending data and protocol in a single
+ *	packet while not burdening the user code with any protocol knowledge.
+ *
+ *	Return may be -1 for a fatal error needing connection close, or a
+ *	positive number reflecting the amount of bytes actually sent.  This
+ *	can be less than the requested number of bytes due to OS memory
+ *	pressure at any given time.
+ */
+
+LWS_VISIBLE int libwebsocket_write(struct libwebsocket *wsi, unsigned char *buf,
+			  size_t len, enum libwebsocket_write_protocol protocol)
+{
+	int n;
+	int pre = 0;
+	int post = 0;
+	int masked7 = wsi->mode == LWS_CONNMODE_WS_CLIENT;
+	unsigned char *dropmask = NULL;
+	unsigned char is_masked_bit = 0;
+	size_t orig_len = len;
+	struct lws_tokens eff_buf;
+
+	if (len == 0 && protocol != LWS_WRITE_CLOSE &&
+		     protocol != LWS_WRITE_PING && protocol != LWS_WRITE_PONG) {
+		lwsl_warn("zero length libwebsocket_write attempt\n");
+		return 0;
+	}
+
+	if (protocol == LWS_WRITE_HTTP ||
+	    protocol == LWS_WRITE_HTTP_FINAL ||
+	    protocol == LWS_WRITE_HTTP_HEADERS)
+		goto send_raw;
+
+	/* websocket protocol, either binary or text */
+
+	if (wsi->state != WSI_STATE_ESTABLISHED)
+		return -1;
+
+	/* if we are continuing a frame that already had its header done */
+
+	if (wsi->u.ws.inside_frame)
+		goto do_more_inside_frame;
+
+	wsi->u.ws.clean_buffer = 1;
+
+	/*
+	 * give a chance to the extensions to modify payload
+	 * pre-TX mangling is not allowed to truncate
+	 */
+	eff_buf.token = (char *)buf;
+	eff_buf.token_len = len;
+
+	switch (protocol) {
+	case LWS_WRITE_PING:
+	case LWS_WRITE_PONG:
+	case LWS_WRITE_CLOSE:
+		break;
+	default:
+		if (lws_ext_callback_for_each_active(wsi,
+			       LWS_EXT_CALLBACK_PAYLOAD_TX, &eff_buf, 0) < 0)
+			return -1;
+	}
+
+	/*
+	 * an extension did something we need to keep... for example, if
+	 * compression extension, it has already updated its state according
+	 * to this being issued
+	 */
+	if ((char *)buf != eff_buf.token)
+		/*
+		 * extension recreated it:
+		 * need to buffer this if not all sent
+		 */
+		wsi->u.ws.clean_buffer = 0;
+
+	buf = (unsigned char *)eff_buf.token;
+	len = eff_buf.token_len;
+
+	switch (wsi->ietf_spec_revision) {
+	case 13:
+
+		if (masked7) {
+			pre += 4;
+			dropmask = &buf[0 - pre];
+			is_masked_bit = 0x80;
+		}
+
+		switch (protocol & 0xf) {
+		case LWS_WRITE_TEXT:
+			n = LWS_WS_OPCODE_07__TEXT_FRAME;
+			break;
+		case LWS_WRITE_BINARY:
+			n = LWS_WS_OPCODE_07__BINARY_FRAME;
+			break;
+		case LWS_WRITE_CONTINUATION:
+			n = LWS_WS_OPCODE_07__CONTINUATION;
+			break;
+
+		case LWS_WRITE_CLOSE:
+			n = LWS_WS_OPCODE_07__CLOSE;
+
+			/*
+			 * 06+ has a 2-byte status code in network order
+			 * we can do this because we demand post-buf
+			 */
+
+			if (wsi->u.ws.close_reason) {
+				/* reason codes count as data bytes */
+				buf -= 2;
+				buf[0] = wsi->u.ws.close_reason >> 8;
+				buf[1] = wsi->u.ws.close_reason;
+				len += 2;
+			}
+			break;
+		case LWS_WRITE_PING:
+			n = LWS_WS_OPCODE_07__PING;
+			break;
+		case LWS_WRITE_PONG:
+			n = LWS_WS_OPCODE_07__PONG;
+			break;
+		default:
+			lwsl_warn("lws_write: unknown write opc / protocol\n");
+			return -1;
+		}
+
+		if (!(protocol & LWS_WRITE_NO_FIN))
+			n |= 1 << 7;
+
+		if (len < 126) {
+			pre += 2;
+			buf[-pre] = n;
+			buf[-pre + 1] = len | is_masked_bit;
+		} else {
+			if (len < 65536) {
+				pre += 4;
+				buf[-pre] = n;
+				buf[-pre + 1] = 126 | is_masked_bit;
+				buf[-pre + 2] = len >> 8;
+				buf[-pre + 3] = len;
+			} else {
+				pre += 10;
+				buf[-pre] = n;
+				buf[-pre + 1] = 127 | is_masked_bit;
+#if defined __LP64__
+					buf[-pre + 2] = (len >> 56) & 0x7f;
+					buf[-pre + 3] = len >> 48;
+					buf[-pre + 4] = len >> 40;
+					buf[-pre + 5] = len >> 32;
+#else
+					buf[-pre + 2] = 0;
+					buf[-pre + 3] = 0;
+					buf[-pre + 4] = 0;
+					buf[-pre + 5] = 0;
+#endif
+				buf[-pre + 6] = len >> 24;
+				buf[-pre + 7] = len >> 16;
+				buf[-pre + 8] = len >> 8;
+				buf[-pre + 9] = len;
+			}
+		}
+		break;
+	}
+
+do_more_inside_frame:
+
+	/*
+	 * Deal with masking if we are in client -> server direction and
+	 * the protocol demands it
+	 */
+
+	if (wsi->mode == LWS_CONNMODE_WS_CLIENT) {
+
+		if (!wsi->u.ws.inside_frame)
+			if (libwebsocket_0405_frame_mask_generate(wsi)) {
+				lwsl_err("frame mask generation failed\n");
+				return -1;
+			}
+
+		/*
+		 * in v7, just mask the payload
+		 */
+		if (dropmask) { /* never set if already inside frame */
+			for (n = 4; n < (int)len + 4; n++)
+				dropmask[n] = dropmask[n] ^
+				wsi->u.ws.frame_masking_nonce_04[
+					(wsi->u.ws.frame_mask_index++) & 3];
+
+			/* copy the frame nonce into place */
+			memcpy(dropmask, wsi->u.ws.frame_masking_nonce_04, 4);
+		}
+	}
+
+send_raw:
+	switch (protocol) {
+	case LWS_WRITE_CLOSE:
+/*		lwsl_hexdump(&buf[-pre], len + post); */
+	case LWS_WRITE_HTTP:
+	case LWS_WRITE_HTTP_FINAL:
+	case LWS_WRITE_HTTP_HEADERS:
+	case LWS_WRITE_PONG:
+	case LWS_WRITE_PING:
+#ifdef LWS_USE_HTTP2
+		if (wsi->mode == LWS_CONNMODE_HTTP2_SERVING) {
+			unsigned char flags = 0;
+
+			n = LWS_HTTP2_FRAME_TYPE_DATA;
+			if (protocol == LWS_WRITE_HTTP_HEADERS) {
+				n = LWS_HTTP2_FRAME_TYPE_HEADERS;
+				flags = LWS_HTTP2_FLAG_END_HEADERS;
+				if (wsi->u.http2.send_END_STREAM)
+					flags |= LWS_HTTP2_FLAG_END_STREAM;
+			}
+			
+			if ((protocol == LWS_WRITE_HTTP || protocol == LWS_WRITE_HTTP_FINAL) && wsi->u.http.content_length) {
+				wsi->u.http.content_remain -= len;
+				lwsl_info("%s: content_remain = %lu\n", __func__, wsi->u.http.content_remain);
+				if (!wsi->u.http.content_remain) {
+					lwsl_info("%s: selecting final write mode\n", __func__);
+					protocol = LWS_WRITE_HTTP_FINAL;
+				}
+			}
+			
+			if (protocol == LWS_WRITE_HTTP_FINAL && wsi->u.http2.END_STREAM) {
+				lwsl_info("%s: setting END_STREAM\n", __func__);
+				flags |= LWS_HTTP2_FLAG_END_STREAM;
+			}
+
+			return lws_http2_frame_write(wsi, n, flags, wsi->u.http2.my_stream_id, len, buf);
+		}
+#endif
+		return lws_issue_raw(wsi, (unsigned char *)buf - pre,
+							      len + pre + post);
+	default:
+		break;
+	}
+
+	wsi->u.ws.inside_frame = 1;
+
+	/*
+	 * give any active extensions a chance to munge the buffer
+	 * before send.  We pass in a pointer to an lws_tokens struct
+	 * prepared with the default buffer and content length that's in
+	 * there.  Rather than rewrite the default buffer, extensions
+	 * that expect to grow the buffer can adapt .token to
+	 * point to their own per-connection buffer in the extension
+	 * user allocation.  By default with no extensions or no
+	 * extension callback handling, just the normal input buffer is
+	 * used then so it is efficient.
+	 *
+	 * callback returns 1 in case it wants to spill more buffers
+	 *
+	 * This takes care of holding the buffer if send is incomplete, ie,
+	 * if wsi->u.ws.clean_buffer is 0 (meaning an extension meddled with
+	 * the buffer).  If wsi->u.ws.clean_buffer is 1, it will instead
+	 * return to the user code how much OF THE USER BUFFER was consumed.
+	 */
+
+	n = lws_issue_raw_ext_access(wsi, buf - pre, len + pre + post);
+	if (n <= 0)
+		return n;
+
+	if (n == len + pre + post) {
+		/* everything in the buffer was handled (or rebuffered...) */
+		wsi->u.ws.inside_frame = 0;
+		return orig_len;
+	}
+
+	/*
+	 * it is how many bytes of user buffer got sent... may be < orig_len
+	 * in which case callback when writable has already been arranged
+	 * and user code can call libwebsocket_write() again with the rest
+	 * later.
+	 */
+
+	return n - (pre + post);
+}
+
+LWS_VISIBLE int libwebsockets_serve_http_file_fragment(
+		struct libwebsocket_context *context, struct libwebsocket *wsi)
+{
+	int n;
+	int m;
+
+	while (!lws_send_pipe_choked(wsi)) {
+
+		if (wsi->truncated_send_len) {
+			if (lws_issue_raw(wsi, wsi->truncated_send_malloc +
+					wsi->truncated_send_offset,
+						       wsi->truncated_send_len) < 0) {
+				lwsl_info("closing from libwebsockets_serve_http_file_fragment\n");
+				return -1;
+			}
+			continue;
+		}
+
+		if (wsi->u.http.filepos == wsi->u.http.filelen)
+			goto all_sent;
+
+		compatible_file_read(n, wsi->u.http.fd, context->service_buffer,
+					       sizeof(context->service_buffer));
+		if (n < 0)
+			return -1; /* caller will close */
+		if (n) {
+			wsi->u.http.filepos += n;
+			m = libwebsocket_write(wsi, context->service_buffer, n,
+					       wsi->u.http.filepos == wsi->u.http.filelen ? LWS_WRITE_HTTP_FINAL : LWS_WRITE_HTTP);
+			if (m < 0)
+				return -1;
+
+			if (m != n)
+				/* adjust for what was not sent */
+				if (compatible_file_seek_cur(wsi->u.http.fd, m - n) < 0)
+					return -1;
+		}
+all_sent:
+		if (!wsi->truncated_send_len &&
+				wsi->u.http.filepos == wsi->u.http.filelen) {
+			wsi->state = WSI_STATE_HTTP;
+
+			if (wsi->protocol->callback)
+				/* ignore callback returned value */
+				user_callback_handle_rxflow(
+					wsi->protocol->callback, context, wsi,
+					LWS_CALLBACK_HTTP_FILE_COMPLETION,
+					wsi->user_space, NULL, 0);
+			return 1;  /* >0 indicates completed */
+		}
+	}
+
+	lwsl_info("choked before able to send whole file (post)\n");
+	libwebsocket_callback_on_writable(context, wsi);
+
+	return 0; /* indicates further processing must be done */
+}
+
+LWS_VISIBLE int
+lws_ssl_capable_read_no_ssl(struct libwebsocket_context *context,
+			    struct libwebsocket *wsi, unsigned char *buf, int len)
+{
+	int n;
+
+	n = recv(wsi->sock, buf, len, 0);
+	if (n >= 0)
+		return n;
+
+	lwsl_warn("error on reading from skt\n");
+	return LWS_SSL_CAPABLE_ERROR;
+}
+
+LWS_VISIBLE int
+lws_ssl_capable_write_no_ssl(struct libwebsocket *wsi, unsigned char *buf, int len)
+{
+	int n;
+	
+	n = send(wsi->sock, buf, len, 0);
+	if (n >= 0)
+		return n;
+
+	if (LWS_ERRNO == LWS_EAGAIN ||
+	    LWS_ERRNO == LWS_EWOULDBLOCK ||
+	    LWS_ERRNO == LWS_EINTR) {
+		if (LWS_ERRNO == LWS_EWOULDBLOCK)
+			lws_set_blocking_send(wsi);
+
+		return LWS_SSL_CAPABLE_MORE_SERVICE;
+	}
+	lwsl_debug("ERROR writing len %d to skt %d\n", len, n);
+	return LWS_SSL_CAPABLE_ERROR;
+}
diff --git a/src/engine/external/libwebsockets/parsers.c b/src/engine/external/libwebsockets/parsers.c
new file mode 100644
index 00000000..2b4a900b
--- /dev/null
+++ b/src/engine/external/libwebsockets/parsers.c
@@ -0,0 +1,1015 @@
+/*
+ * libwebsockets - small server side websockets and web server implementation
+ *
+ * Copyright (C) 2010-2013 Andy Green <andy@warmcat.com>
+ *
+ *  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:
+ *  version 2.1 of the License.
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston,
+ *  MA  02110-1301  USA
+ */
+
+#include "private-libwebsockets.h"
+
+unsigned char lextable[] = {
+	#include "lextable.h"
+};
+
+#define FAIL_CHAR 0x08
+
+int lextable_decode(int pos, char c)
+{
+
+	c = tolower(c);
+
+	while (1) {
+		if (lextable[pos] & (1 << 7)) { /* 1-byte, fail on mismatch */
+			if ((lextable[pos] & 0x7f) != c)
+				return -1;
+			/* fall thru */
+			pos++;
+			if (lextable[pos] == FAIL_CHAR)
+				return -1;
+			return pos;
+		}
+
+		if (lextable[pos] == FAIL_CHAR)
+			return -1;
+
+		/* b7 = 0, end or 3-byte */
+		if (lextable[pos] < FAIL_CHAR) /* terminal marker */
+			return pos;
+
+		if (lextable[pos] == c) /* goto */
+			return pos + (lextable[pos + 1]) +
+						(lextable[pos + 2] << 8);
+		/* fall thru goto */
+		pos += 3;
+		/* continue */
+	}
+}
+
+int lws_allocate_header_table(struct libwebsocket *wsi)
+{
+	/* Be sure to free any existing header data to avoid mem leak: */
+	lws_free_header_table(wsi);
+	wsi->u.hdr.ah = lws_malloc(sizeof(*wsi->u.hdr.ah));
+	if (wsi->u.hdr.ah == NULL) {
+		lwsl_err("Out of memory\n");
+		return -1;
+	}
+	memset(wsi->u.hdr.ah->frag_index, 0, sizeof(wsi->u.hdr.ah->frag_index));
+	wsi->u.hdr.ah->next_frag_index = 0;
+	wsi->u.hdr.ah->pos = 0;
+
+	return 0;
+}
+
+int lws_free_header_table(struct libwebsocket *wsi)
+{
+	lws_free2(wsi->u.hdr.ah);
+	wsi->u.hdr.ah = NULL;
+	return 0;
+};
+
+LWS_VISIBLE int lws_hdr_total_length(struct libwebsocket *wsi, enum lws_token_indexes h)
+{
+	int n;
+	int len = 0;
+
+	n = wsi->u.hdr.ah->frag_index[h];
+	if (!n)
+		return 0;
+	do {
+		len += wsi->u.hdr.ah->frags[n].len;
+		n = wsi->u.hdr.ah->frags[n].next_frag_index;
+	} while (n);
+
+	return len;
+}
+
+LWS_VISIBLE int lws_hdr_copy(struct libwebsocket *wsi, char *dest, int len,
+						enum lws_token_indexes h)
+{
+	int toklen = lws_hdr_total_length(wsi, h);
+	int n;
+
+	if (toklen >= len)
+		return -1;
+
+	n = wsi->u.hdr.ah->frag_index[h];
+	if (!n)
+		return 0;
+
+	do {
+		strcpy(dest,
+			&wsi->u.hdr.ah->data[wsi->u.hdr.ah->frags[n].offset]);
+		dest += wsi->u.hdr.ah->frags[n].len;
+		n = wsi->u.hdr.ah->frags[n].next_frag_index;
+	} while (n);
+
+	return toklen;
+}
+
+char *lws_hdr_simple_ptr(struct libwebsocket *wsi, enum lws_token_indexes h)
+{
+	int n;
+
+	n = wsi->u.hdr.ah->frag_index[h];
+	if (!n)
+		return NULL;
+
+	return &wsi->u.hdr.ah->data[wsi->u.hdr.ah->frags[n].offset];
+}
+
+int lws_hdr_simple_create(struct libwebsocket *wsi,
+				enum lws_token_indexes h, const char *s)
+{
+	wsi->u.hdr.ah->next_frag_index++;
+	if (wsi->u.hdr.ah->next_frag_index ==
+	       sizeof(wsi->u.hdr.ah->frags) / sizeof(wsi->u.hdr.ah->frags[0])) {
+		lwsl_warn("More hdr frags than we can deal with, dropping\n");
+		return -1;
+	}
+
+	wsi->u.hdr.ah->frag_index[h] = wsi->u.hdr.ah->next_frag_index;
+
+	wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].offset =
+							     wsi->u.hdr.ah->pos;
+	wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len = 0;
+	wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].next_frag_index =
+									      0;
+
+	do {
+		if (wsi->u.hdr.ah->pos == sizeof(wsi->u.hdr.ah->data)) {
+			lwsl_err("Ran out of header data space\n");
+			return -1;
+		}
+		wsi->u.hdr.ah->data[wsi->u.hdr.ah->pos++] = *s;
+		if (*s)
+			wsi->u.hdr.ah->frags[
+					wsi->u.hdr.ah->next_frag_index].len++;
+	} while (*s++);
+
+	return 0;
+}
+
+static char char_to_hex(const char c)
+{
+	if (c >= '0' && c <= '9')
+		return c - '0';
+
+	if (c >= 'a' && c <= 'f')
+		return c - 'a' + 10;
+
+	if (c >= 'A' && c <= 'F')
+		return c - 'A' + 10;
+
+	return -1;
+}
+
+static int issue_char(struct libwebsocket *wsi, unsigned char c)
+{
+	if (wsi->u.hdr.ah->pos == sizeof(wsi->u.hdr.ah->data)) {
+		lwsl_warn("excessive header content\n");
+		return -1;
+	}
+
+	if( wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len >= 
+		wsi->u.hdr.current_token_limit) {
+		lwsl_warn("header %i exceeds limit\n", wsi->u.hdr.parser_state);
+		return 1;
+	};
+
+	wsi->u.hdr.ah->data[wsi->u.hdr.ah->pos++] = c;
+	if (c)
+		wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len++;
+
+	return 0;
+}
+
+int libwebsocket_parse(
+		struct libwebsocket_context *context,
+		struct libwebsocket *wsi, unsigned char c)
+{
+	int n;
+
+	switch (wsi->u.hdr.parser_state) {
+	default:
+
+		lwsl_parser("WSI_TOK_(%d) '%c'\n", wsi->u.hdr.parser_state, c);
+
+		/* collect into malloc'd buffers */
+		/* optional initial space swallow */
+		if (!wsi->u.hdr.ah->frags[wsi->u.hdr.ah->frag_index[
+				      wsi->u.hdr.parser_state]].len && c == ' ')
+			break;
+
+		if ((wsi->u.hdr.parser_state != WSI_TOKEN_GET_URI) &&
+			(wsi->u.hdr.parser_state != WSI_TOKEN_POST_URI) &&
+			(wsi->u.hdr.parser_state != WSI_TOKEN_OPTIONS_URI))
+			goto check_eol;
+
+		/* special URI processing... end at space */
+
+		if (c == ' ') {
+			/* enforce starting with / */
+			if (!wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len)
+				if (issue_char(wsi, '/') < 0)
+					return -1;
+
+			/* begin parsing HTTP version: */
+			if (issue_char(wsi, '\0') < 0)
+				return -1;
+			wsi->u.hdr.parser_state = WSI_TOKEN_HTTP;
+			goto start_fragment;
+		}
+
+		/* special URI processing... convert %xx */
+
+		switch (wsi->u.hdr.ues) {
+		case URIES_IDLE:
+			if (c == '%') {
+				wsi->u.hdr.ues = URIES_SEEN_PERCENT;
+				goto swallow;
+			}
+			break;
+		case URIES_SEEN_PERCENT:
+			if (char_to_hex(c) < 0) {
+				/* regurgitate */
+				if (issue_char(wsi, '%') < 0)
+					return -1;
+				wsi->u.hdr.ues = URIES_IDLE;
+				/* continue on to assess c */
+				break;
+			}
+			wsi->u.hdr.esc_stash = c;
+			wsi->u.hdr.ues = URIES_SEEN_PERCENT_H1;
+			goto swallow;
+			
+		case URIES_SEEN_PERCENT_H1:
+			if (char_to_hex(c) < 0) {
+				/* regurgitate */
+				issue_char(wsi, '%');
+				wsi->u.hdr.ues = URIES_IDLE;
+				/* regurgitate + assess */
+				if (libwebsocket_parse(context, wsi, wsi->u.hdr.esc_stash) < 0)
+					return -1;
+				/* continue on to assess c */
+				break;
+			}
+			c = (char_to_hex(wsi->u.hdr.esc_stash) << 4) |
+					char_to_hex(c);
+			wsi->u.hdr.ues = URIES_IDLE;
+			break;
+		}
+
+		/*
+		 * special URI processing... 
+		 *  convert /.. or /... or /../ etc to /
+		 *  convert /./ to /
+		 *  convert // or /// etc to /
+		 *  leave /.dir or whatever alone
+		 */
+
+		switch (wsi->u.hdr.ups) {
+		case URIPS_IDLE:
+			/* issue the first / always */
+			if (c == '/')
+				wsi->u.hdr.ups = URIPS_SEEN_SLASH;
+			break;
+		case URIPS_SEEN_SLASH:
+			/* swallow subsequent slashes */
+			if (c == '/')
+				goto swallow;
+			/* track and swallow the first . after / */
+			if (c == '.') {
+				wsi->u.hdr.ups = URIPS_SEEN_SLASH_DOT;
+				goto swallow;
+			}
+			wsi->u.hdr.ups = URIPS_IDLE;
+			break;
+		case URIPS_SEEN_SLASH_DOT:
+			/* swallow second . */
+			if (c == '.') {
+				/* 
+				 * back up one dir level if possible
+				 * safe against header fragmentation because
+				 * the method URI can only be in 1 fragment
+				 */
+				if (wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len > 2) {
+					wsi->u.hdr.ah->pos--;
+					wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len--;
+					do {
+						wsi->u.hdr.ah->pos--;
+						wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len--;
+					} while (wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len > 1 &&
+							wsi->u.hdr.ah->data[wsi->u.hdr.ah->pos] != '/');
+				}
+				wsi->u.hdr.ups = URIPS_SEEN_SLASH_DOT_DOT;
+				goto swallow;
+			}
+			/* change /./ to / */
+			if (c == '/') {
+				wsi->u.hdr.ups = URIPS_SEEN_SLASH;
+				goto swallow;
+			}
+			/* it was like /.dir ... regurgitate the . */
+			wsi->u.hdr.ups = URIPS_IDLE;
+			issue_char(wsi, '.');
+			break;
+			
+		case URIPS_SEEN_SLASH_DOT_DOT:
+			/* swallow prior .. chars and any subsequent . */
+			if (c == '.')
+				goto swallow;
+			/* last issued was /, so another / == // */
+			if (c == '/')
+				goto swallow;
+			/* last we issued was / so SEEN_SLASH */
+			wsi->u.hdr.ups = URIPS_SEEN_SLASH;
+			break;
+		case URIPS_ARGUMENTS:
+			/* leave them alone */
+			break;
+		}
+
+		if (c == '?') { /* start of URI arguments */
+			/* seal off uri header */
+			wsi->u.hdr.ah->data[wsi->u.hdr.ah->pos++] = '\0';
+
+			/* move to using WSI_TOKEN_HTTP_URI_ARGS */
+			wsi->u.hdr.ah->next_frag_index++;
+			wsi->u.hdr.ah->frags[
+				wsi->u.hdr.ah->next_frag_index].offset =
+							     wsi->u.hdr.ah->pos;
+			wsi->u.hdr.ah->frags[
+					wsi->u.hdr.ah->next_frag_index].len = 0;
+			wsi->u.hdr.ah->frags[
+			    wsi->u.hdr.ah->next_frag_index].next_frag_index = 0;
+
+			wsi->u.hdr.ah->frag_index[WSI_TOKEN_HTTP_URI_ARGS] =
+						 wsi->u.hdr.ah->next_frag_index;
+
+			/* defeat normal uri path processing */
+			wsi->u.hdr.ups = URIPS_ARGUMENTS;
+			goto swallow;
+		}
+
+check_eol:
+
+		/* bail at EOL */
+		if (wsi->u.hdr.parser_state != WSI_TOKEN_CHALLENGE &&
+								  c == '\x0d') {
+			c = '\0';
+			wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING_SAW_CR;
+			lwsl_parser("*\n");
+		}
+
+		n = issue_char(wsi, c);
+		if (n < 0)
+			return -1;
+		if (n > 0)
+			wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING;
+
+swallow:
+		/* per-protocol end of headers management */
+
+		if (wsi->u.hdr.parser_state == WSI_TOKEN_CHALLENGE)
+			goto set_parsing_complete;
+		break;
+
+		/* collecting and checking a name part */
+	case WSI_TOKEN_NAME_PART:
+		lwsl_parser("WSI_TOKEN_NAME_PART '%c'\n", c);
+
+		wsi->u.hdr.lextable_pos =
+				lextable_decode(wsi->u.hdr.lextable_pos, c);
+
+		if (wsi->u.hdr.lextable_pos < 0) {
+			/* this is not a header we know about */
+			if (wsi->u.hdr.ah->frag_index[WSI_TOKEN_GET_URI] ||
+				wsi->u.hdr.ah->frag_index[WSI_TOKEN_POST_URI] ||
+				wsi->u.hdr.ah->frag_index[WSI_TOKEN_OPTIONS_URI] ||
+				wsi->u.hdr.ah->frag_index[WSI_TOKEN_HTTP]) {
+				/*
+				 * already had the method, no idea what
+				 * this crap is, ignore
+				 */
+				wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING;
+				break;
+			}
+			/*
+			 * hm it's an unknown http method in fact,
+			 * treat as dangerous
+			 */
+
+			lwsl_info("Unknown method - dropping\n");
+			return -1;
+		}
+		if (lextable[wsi->u.hdr.lextable_pos] < FAIL_CHAR) {
+
+			/* terminal state */
+
+			n = ((unsigned int)lextable[wsi->u.hdr.lextable_pos] << 8) |
+					lextable[wsi->u.hdr.lextable_pos + 1];
+
+			lwsl_parser("known hdr %d\n", n);
+			if (n == WSI_TOKEN_GET_URI &&
+				wsi->u.hdr.ah->frag_index[WSI_TOKEN_GET_URI]) {
+				lwsl_warn("Duplicated GET\n");
+				return -1;
+			}
+			if (n == WSI_TOKEN_POST_URI &&
+				wsi->u.hdr.ah->frag_index[WSI_TOKEN_POST_URI]) {
+				lwsl_warn("Duplicated POST\n");
+				return -1;
+			}
+			if (n == WSI_TOKEN_OPTIONS_URI &&
+				wsi->u.hdr.ah->frag_index[WSI_TOKEN_OPTIONS_URI]) {
+				lwsl_warn("Duplicated OPTIONS\n");
+				return -1;
+			}
+
+			/*
+			 * WSORIGIN is protocol equiv to ORIGIN,
+			 * JWebSocket likes to send it, map to ORIGIN
+			 */
+			if (n == WSI_TOKEN_SWORIGIN)
+				n = WSI_TOKEN_ORIGIN;
+
+			wsi->u.hdr.parser_state = (enum lws_token_indexes)
+							(WSI_TOKEN_GET_URI + n);
+
+			if (context->token_limits)
+				wsi->u.hdr.current_token_limit =
+					context->token_limits->token_limit[wsi->u.hdr.parser_state];
+			else
+				wsi->u.hdr.current_token_limit = sizeof(wsi->u.hdr.ah->data);
+
+			if (wsi->u.hdr.parser_state == WSI_TOKEN_CHALLENGE)
+				goto set_parsing_complete;
+
+			goto start_fragment;
+		}
+		break;
+
+start_fragment:
+		wsi->u.hdr.ah->next_frag_index++;
+		if (wsi->u.hdr.ah->next_frag_index ==
+				sizeof(wsi->u.hdr.ah->frags) /
+					      sizeof(wsi->u.hdr.ah->frags[0])) {
+			lwsl_warn("More hdr frags than we can deal with\n");
+			return -1;
+		}
+
+		wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].offset =
+							     wsi->u.hdr.ah->pos;
+		wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len = 0;
+		wsi->u.hdr.ah->frags[
+			    wsi->u.hdr.ah->next_frag_index].next_frag_index = 0;
+
+		n = wsi->u.hdr.ah->frag_index[wsi->u.hdr.parser_state];
+		if (!n) { /* first fragment */
+			wsi->u.hdr.ah->frag_index[wsi->u.hdr.parser_state] =
+						 wsi->u.hdr.ah->next_frag_index;
+			break;
+		}
+		/* continuation */
+		while (wsi->u.hdr.ah->frags[n].next_frag_index)
+				n = wsi->u.hdr.ah->frags[n].next_frag_index;
+		wsi->u.hdr.ah->frags[n].next_frag_index =
+						 wsi->u.hdr.ah->next_frag_index;
+
+		if (wsi->u.hdr.ah->pos == sizeof(wsi->u.hdr.ah->data)) {
+			lwsl_warn("excessive header content\n");
+			return -1;
+		}
+
+		wsi->u.hdr.ah->data[wsi->u.hdr.ah->pos++] = ' ';
+		wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len++;
+		break;
+
+		/* skipping arg part of a name we didn't recognize */
+	case WSI_TOKEN_SKIPPING:
+		lwsl_parser("WSI_TOKEN_SKIPPING '%c'\n", c);
+
+		if (c == '\x0d')
+			wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING_SAW_CR;
+		break;
+
+	case WSI_TOKEN_SKIPPING_SAW_CR:
+		lwsl_parser("WSI_TOKEN_SKIPPING_SAW_CR '%c'\n", c);
+		if (c == '\x0a') {
+			wsi->u.hdr.parser_state = WSI_TOKEN_NAME_PART;
+			wsi->u.hdr.lextable_pos = 0;
+		} else
+			wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING;
+		break;
+		/* we're done, ignore anything else */
+
+	case WSI_PARSING_COMPLETE:
+		lwsl_parser("WSI_PARSING_COMPLETE '%c'\n", c);
+		break;
+	}
+
+	return 0;
+
+set_parsing_complete:
+
+	if (lws_hdr_total_length(wsi, WSI_TOKEN_UPGRADE)) {
+		if (lws_hdr_total_length(wsi, WSI_TOKEN_VERSION))
+			wsi->ietf_spec_revision =
+			       atoi(lws_hdr_simple_ptr(wsi, WSI_TOKEN_VERSION));
+
+		lwsl_parser("v%02d hdrs completed\n", wsi->ietf_spec_revision);
+	}
+	wsi->u.hdr.parser_state = WSI_PARSING_COMPLETE;
+	wsi->hdr_parsing_completed = 1;
+
+	return 0;
+}
+
+
+/**
+ * lws_frame_is_binary: true if the current frame was sent in binary mode
+ *
+ * @wsi: the connection we are inquiring about
+ *
+ * This is intended to be called from the LWS_CALLBACK_RECEIVE callback if
+ * it's interested to see if the frame it's dealing with was sent in binary
+ * mode.
+ */
+
+LWS_VISIBLE int lws_frame_is_binary(struct libwebsocket *wsi)
+{
+	return wsi->u.ws.frame_is_binary;
+}
+
+int
+libwebsocket_rx_sm(struct libwebsocket *wsi, unsigned char c)
+{
+	int n;
+	struct lws_tokens eff_buf;
+	int ret = 0;
+
+	switch (wsi->lws_rx_parse_state) {
+	case LWS_RXPS_NEW:
+
+		switch (wsi->ietf_spec_revision) {
+		case 13:
+			/*
+			 * no prepended frame key any more
+			 */
+			wsi->u.ws.all_zero_nonce = 1;
+			goto handle_first;
+
+		default:
+			lwsl_warn("lws_rx_sm: unknown spec version %d\n",
+						       wsi->ietf_spec_revision);
+			break;
+		}
+		break;
+	case LWS_RXPS_04_MASK_NONCE_1:
+		wsi->u.ws.frame_masking_nonce_04[1] = c;
+		if (c)
+			wsi->u.ws.all_zero_nonce = 0;
+		wsi->lws_rx_parse_state = LWS_RXPS_04_MASK_NONCE_2;
+		break;
+	case LWS_RXPS_04_MASK_NONCE_2:
+		wsi->u.ws.frame_masking_nonce_04[2] = c;
+		if (c)
+			wsi->u.ws.all_zero_nonce = 0;
+		wsi->lws_rx_parse_state = LWS_RXPS_04_MASK_NONCE_3;
+		break;
+	case LWS_RXPS_04_MASK_NONCE_3:
+		wsi->u.ws.frame_masking_nonce_04[3] = c;
+		if (c)
+			wsi->u.ws.all_zero_nonce = 0;
+
+		/*
+		 * start from the zero'th byte in the XOR key buffer since
+		 * this is the start of a frame with a new key
+		 */
+
+		wsi->u.ws.frame_mask_index = 0;
+
+		wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_1;
+		break;
+
+	/*
+	 *  04 logical framing from the spec (all this is masked when incoming
+	 *  and has to be unmasked)
+	 *
+	 * We ignore the possibility of extension data because we don't
+	 * negotiate any extensions at the moment.
+	 *
+	 *    0                   1                   2                   3
+	 *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+	 *   +-+-+-+-+-------+-+-------------+-------------------------------+
+	 *   |F|R|R|R| opcode|R| Payload len |    Extended payload length    |
+	 *   |I|S|S|S|  (4)  |S|     (7)     |             (16/63)           |
+	 *   |N|V|V|V|       |V|             |   (if payload len==126/127)   |
+	 *   | |1|2|3|       |4|             |                               |
+	 *   +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
+	 *   |     Extended payload length continued, if payload len == 127  |
+	 *   + - - - - - - - - - - - - - - - +-------------------------------+
+	 *   |                               |         Extension data        |
+	 *   +-------------------------------+ - - - - - - - - - - - - - - - +
+	 *   :                                                               :
+	 *   +---------------------------------------------------------------+
+	 *   :                       Application data                        :
+	 *   +---------------------------------------------------------------+
+	 *
+	 *  We pass payload through to userland as soon as we get it, ignoring
+	 *  FIN.  It's up to userland to buffer it up if it wants to see a
+	 *  whole unfragmented block of the original size (which may be up to
+	 *  2^63 long!)
+	 */
+
+	case LWS_RXPS_04_FRAME_HDR_1:
+handle_first:
+
+		wsi->u.ws.opcode = c & 0xf;
+		wsi->u.ws.rsv = c & 0x70;
+		wsi->u.ws.final = !!((c >> 7) & 1);
+
+		switch (wsi->u.ws.opcode) {
+		case LWS_WS_OPCODE_07__TEXT_FRAME:
+		case LWS_WS_OPCODE_07__BINARY_FRAME:
+			wsi->u.ws.frame_is_binary =
+			     wsi->u.ws.opcode == LWS_WS_OPCODE_07__BINARY_FRAME;
+			break;
+		}
+		wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN;
+		break;
+
+	case LWS_RXPS_04_FRAME_HDR_LEN:
+
+		wsi->u.ws.this_frame_masked = !!(c & 0x80);
+
+		switch (c & 0x7f) {
+		case 126:
+			/* control frames are not allowed to have big lengths */
+			if (wsi->u.ws.opcode & 8)
+				goto illegal_ctl_length;
+
+			wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN16_2;
+			break;
+		case 127:
+			/* control frames are not allowed to have big lengths */
+			if (wsi->u.ws.opcode & 8)
+				goto illegal_ctl_length;
+
+			wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_8;
+			break;
+		default:
+			wsi->u.ws.rx_packet_length = c & 0x7f;
+			if (wsi->u.ws.this_frame_masked)
+				wsi->lws_rx_parse_state =
+						LWS_RXPS_07_COLLECT_FRAME_KEY_1;
+			else
+				if (wsi->u.ws.rx_packet_length)
+					wsi->lws_rx_parse_state =
+					LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
+				else {
+					wsi->lws_rx_parse_state = LWS_RXPS_NEW;
+					goto spill;
+				}
+			break;
+		}
+		break;
+
+	case LWS_RXPS_04_FRAME_HDR_LEN16_2:
+		wsi->u.ws.rx_packet_length = c << 8;
+		wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN16_1;
+		break;
+
+	case LWS_RXPS_04_FRAME_HDR_LEN16_1:
+		wsi->u.ws.rx_packet_length |= c;
+		if (wsi->u.ws.this_frame_masked)
+			wsi->lws_rx_parse_state =
+					LWS_RXPS_07_COLLECT_FRAME_KEY_1;
+		else
+			wsi->lws_rx_parse_state =
+				LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
+		break;
+
+	case LWS_RXPS_04_FRAME_HDR_LEN64_8:
+		if (c & 0x80) {
+			lwsl_warn("b63 of length must be zero\n");
+			/* kill the connection */
+			return -1;
+		}
+#if defined __LP64__
+		wsi->u.ws.rx_packet_length = ((size_t)c) << 56;
+#else
+		wsi->u.ws.rx_packet_length = 0;
+#endif
+		wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_7;
+		break;
+
+	case LWS_RXPS_04_FRAME_HDR_LEN64_7:
+#if defined __LP64__
+		wsi->u.ws.rx_packet_length |= ((size_t)c) << 48;
+#endif
+		wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_6;
+		break;
+
+	case LWS_RXPS_04_FRAME_HDR_LEN64_6:
+#if defined __LP64__
+		wsi->u.ws.rx_packet_length |= ((size_t)c) << 40;
+#endif
+		wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_5;
+		break;
+
+	case LWS_RXPS_04_FRAME_HDR_LEN64_5:
+#if defined __LP64__
+		wsi->u.ws.rx_packet_length |= ((size_t)c) << 32;
+#endif
+		wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_4;
+		break;
+
+	case LWS_RXPS_04_FRAME_HDR_LEN64_4:
+		wsi->u.ws.rx_packet_length |= ((size_t)c) << 24;
+		wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_3;
+		break;
+
+	case LWS_RXPS_04_FRAME_HDR_LEN64_3:
+		wsi->u.ws.rx_packet_length |= ((size_t)c) << 16;
+		wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_2;
+		break;
+
+	case LWS_RXPS_04_FRAME_HDR_LEN64_2:
+		wsi->u.ws.rx_packet_length |= ((size_t)c) << 8;
+		wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_1;
+		break;
+
+	case LWS_RXPS_04_FRAME_HDR_LEN64_1:
+		wsi->u.ws.rx_packet_length |= ((size_t)c);
+		if (wsi->u.ws.this_frame_masked)
+			wsi->lws_rx_parse_state =
+					LWS_RXPS_07_COLLECT_FRAME_KEY_1;
+		else
+			wsi->lws_rx_parse_state =
+				LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
+		break;
+
+	case LWS_RXPS_07_COLLECT_FRAME_KEY_1:
+		wsi->u.ws.frame_masking_nonce_04[0] = c;
+		if (c)
+			wsi->u.ws.all_zero_nonce = 0;
+		wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_2;
+		break;
+
+	case LWS_RXPS_07_COLLECT_FRAME_KEY_2:
+		wsi->u.ws.frame_masking_nonce_04[1] = c;
+		if (c)
+			wsi->u.ws.all_zero_nonce = 0;
+		wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_3;
+		break;
+
+	case LWS_RXPS_07_COLLECT_FRAME_KEY_3:
+		wsi->u.ws.frame_masking_nonce_04[2] = c;
+		if (c)
+			wsi->u.ws.all_zero_nonce = 0;
+		wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_4;
+		break;
+
+	case LWS_RXPS_07_COLLECT_FRAME_KEY_4:
+		wsi->u.ws.frame_masking_nonce_04[3] = c;
+		if (c)
+			wsi->u.ws.all_zero_nonce = 0;
+		wsi->lws_rx_parse_state =
+					LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
+		wsi->u.ws.frame_mask_index = 0;
+		if (wsi->u.ws.rx_packet_length == 0) {
+			wsi->lws_rx_parse_state = LWS_RXPS_NEW;
+			goto spill;
+		}
+		break;
+
+
+	case LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED:
+
+		if (!wsi->u.ws.rx_user_buffer) {
+			lwsl_err("NULL user buffer...\n");
+			return 1;
+		}
+
+		if (wsi->u.ws.all_zero_nonce)
+			wsi->u.ws.rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING +
+			       (wsi->u.ws.rx_user_buffer_head++)] = c;
+		else
+			wsi->u.ws.rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING +
+			       (wsi->u.ws.rx_user_buffer_head++)] =
+				   c ^ wsi->u.ws.frame_masking_nonce_04[
+					    (wsi->u.ws.frame_mask_index++) & 3];
+
+		if (--wsi->u.ws.rx_packet_length == 0) {
+			/* spill because we have the whole frame */
+			wsi->lws_rx_parse_state = LWS_RXPS_NEW;
+			goto spill;
+		}
+
+		/*
+		 * if there's no protocol max frame size given, we are
+		 * supposed to default to LWS_MAX_SOCKET_IO_BUF
+		 */
+
+		if (!wsi->protocol->rx_buffer_size &&
+			 		wsi->u.ws.rx_user_buffer_head !=
+			 				  LWS_MAX_SOCKET_IO_BUF)
+			break;
+		else
+			if (wsi->protocol->rx_buffer_size &&
+					wsi->u.ws.rx_user_buffer_head !=
+						  wsi->protocol->rx_buffer_size)
+			break;
+
+		/* spill because we filled our rx buffer */
+spill:
+		/*
+		 * is this frame a control packet we should take care of at this
+		 * layer?  If so service it and hide it from the user callback
+		 */
+
+		lwsl_parser("spill on %s\n", wsi->protocol->name);
+
+		switch (wsi->u.ws.opcode) {
+		case LWS_WS_OPCODE_07__CLOSE:
+			/* is this an acknowledgement of our close? */
+			if (wsi->state == WSI_STATE_AWAITING_CLOSE_ACK) {
+				/*
+				 * fine he has told us he is closing too, let's
+				 * finish our close
+				 */
+				lwsl_parser("seen client close ack\n");
+				return -1;
+			}
+			lwsl_parser("server sees client close packet\n");
+			/* parrot the close packet payload back */
+			n = libwebsocket_write(wsi, (unsigned char *)
+				&wsi->u.ws.rx_user_buffer[
+					LWS_SEND_BUFFER_PRE_PADDING],
+					wsi->u.ws.rx_user_buffer_head,
+							       LWS_WRITE_CLOSE);
+			if (n < 0)
+				lwsl_info("write of close ack failed %d\n", n);
+			wsi->state = WSI_STATE_RETURNED_CLOSE_ALREADY;
+			/* close the connection */
+			return -1;
+
+		case LWS_WS_OPCODE_07__PING:
+			lwsl_info("received %d byte ping, sending pong\n",
+						 wsi->u.ws.rx_user_buffer_head);
+
+			if (wsi->u.ws.ping_payload_len) {
+				/* 
+				 * there is already a pending ping payload
+				 * we should just log and drop
+				 */
+				lwsl_parser("DROP PING since one pending\n");
+				goto ping_drop;
+			}
+			
+			/* control packets can only be < 128 bytes long */
+			if (wsi->u.ws.ping_payload_len > 128 - 4) {
+				lwsl_parser("DROP PING payload too large\n");
+				goto ping_drop;
+			}
+			
+			/* if existing buffer is too small, drop it */
+			if (wsi->u.ws.ping_payload_buf &&
+			    wsi->u.ws.ping_payload_alloc < wsi->u.ws.rx_user_buffer_head) {
+				lws_free2(wsi->u.ws.ping_payload_buf);
+			}
+
+			/* if no buffer, allocate it */
+			if (!wsi->u.ws.ping_payload_buf) {
+				wsi->u.ws.ping_payload_buf = lws_malloc(wsi->u.ws.rx_user_buffer_head
+									+ LWS_SEND_BUFFER_PRE_PADDING);
+				wsi->u.ws.ping_payload_alloc = wsi->u.ws.rx_user_buffer_head;
+			}
+			
+			/* stash the pong payload */
+			memcpy(wsi->u.ws.ping_payload_buf + LWS_SEND_BUFFER_PRE_PADDING,
+			       &wsi->u.ws.rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING],
+				wsi->u.ws.rx_user_buffer_head);
+			
+			wsi->u.ws.ping_payload_len = wsi->u.ws.rx_user_buffer_head;
+			
+			/* get it sent as soon as possible */
+			libwebsocket_callback_on_writable(wsi->protocol->owning_server, wsi);
+ping_drop:
+			wsi->u.ws.rx_user_buffer_head = 0;
+			return 0;
+
+		case LWS_WS_OPCODE_07__PONG:
+			/* ... then just drop it */
+			wsi->u.ws.rx_user_buffer_head = 0;
+			return 0;
+
+		case LWS_WS_OPCODE_07__TEXT_FRAME:
+		case LWS_WS_OPCODE_07__BINARY_FRAME:
+		case LWS_WS_OPCODE_07__CONTINUATION:
+			break;
+
+		default:
+			lwsl_parser("passing opc %x up to exts\n",
+							wsi->u.ws.opcode);
+			/*
+			 * It's something special we can't understand here.
+			 * Pass the payload up to the extension's parsing
+			 * state machine.
+			 */
+
+			eff_buf.token = &wsi->u.ws.rx_user_buffer[
+						   LWS_SEND_BUFFER_PRE_PADDING];
+			eff_buf.token_len = wsi->u.ws.rx_user_buffer_head;
+
+			if (lws_ext_callback_for_each_active(wsi,
+				LWS_EXT_CALLBACK_EXTENDED_PAYLOAD_RX,
+					&eff_buf, 0) <= 0) /* not handle or fail */
+				lwsl_ext("ext opc opcode 0x%x unknown\n",
+							      wsi->u.ws.opcode);
+
+			wsi->u.ws.rx_user_buffer_head = 0;
+			return 0;
+		}
+
+		/*
+		 * No it's real payload, pass it up to the user callback.
+		 * It's nicely buffered with the pre-padding taken care of
+		 * so it can be sent straight out again using libwebsocket_write
+		 */
+
+		eff_buf.token = &wsi->u.ws.rx_user_buffer[
+						LWS_SEND_BUFFER_PRE_PADDING];
+		eff_buf.token_len = wsi->u.ws.rx_user_buffer_head;
+		
+		if (lws_ext_callback_for_each_active(wsi,
+				LWS_EXT_CALLBACK_PAYLOAD_RX, &eff_buf, 0) < 0)
+			return -1;
+
+		if (eff_buf.token_len > 0) {
+			eff_buf.token[eff_buf.token_len] = '\0';
+
+			if (wsi->protocol->callback)
+				ret = user_callback_handle_rxflow(
+						wsi->protocol->callback,
+						wsi->protocol->owning_server,
+						wsi, LWS_CALLBACK_RECEIVE,
+						wsi->user_space,
+						eff_buf.token,
+						eff_buf.token_len);
+		    else
+			    lwsl_err("No callback on payload spill!\n");
+		}
+
+		wsi->u.ws.rx_user_buffer_head = 0;
+		break;
+	}
+
+	return ret;
+
+illegal_ctl_length:
+
+	lwsl_warn("Control frame with xtended length is illegal\n");
+	/* kill the connection */
+	return -1;
+}
+
+
+/**
+ * libwebsockets_remaining_packet_payload() - Bytes to come before "overall"
+ *					      rx packet is complete
+ * @wsi:		Websocket instance (available from user callback)
+ *
+ *	This function is intended to be called from the callback if the
+ *  user code is interested in "complete packets" from the client.
+ *  libwebsockets just passes through payload as it comes and issues a buffer
+ *  additionally when it hits a built-in limit.  The LWS_CALLBACK_RECEIVE
+ *  callback handler can use this API to find out if the buffer it has just
+ *  been given is the last piece of a "complete packet" from the client --
+ *  when that is the case libwebsockets_remaining_packet_payload() will return
+ *  0.
+ *
+ *  Many protocols won't care becuse their packets are always small.
+ */
+
+LWS_VISIBLE size_t
+libwebsockets_remaining_packet_payload(struct libwebsocket *wsi)
+{
+	return wsi->u.ws.rx_packet_length;
+}
diff --git a/src/engine/external/libwebsockets/pollfd.c b/src/engine/external/libwebsockets/pollfd.c
new file mode 100644
index 00000000..b09127e0
--- /dev/null
+++ b/src/engine/external/libwebsockets/pollfd.c
@@ -0,0 +1,293 @@
+/*
+ * libwebsockets - small server side websockets and web server implementation
+ *
+ * Copyright (C) 2010-2014 Andy Green <andy@warmcat.com>
+ *
+ *  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:
+ *  version 2.1 of the License.
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston,
+ *  MA  02110-1301  USA
+ */
+
+#include "private-libwebsockets.h"
+
+int
+insert_wsi_socket_into_fds(struct libwebsocket_context *context,
+						       struct libwebsocket *wsi)
+{
+	struct libwebsocket_pollargs pa = { wsi->sock, LWS_POLLIN, 0 };
+
+	if (context->fds_count >= context->max_fds) {
+		lwsl_err("Too many fds (%d)\n", context->max_fds);
+		return 1;
+	}
+
+	if (wsi->sock >= context->max_fds) {
+		lwsl_err("Socket fd %d is too high (%d)\n",
+						wsi->sock, context->max_fds);
+		return 1;
+	}
+
+	assert(wsi);
+	assert(wsi->sock >= 0);
+
+	lwsl_info("insert_wsi_socket_into_fds: wsi=%p, sock=%d, fds pos=%d\n",
+					    wsi, wsi->sock, context->fds_count);
+
+	context->protocols[0].callback(context, wsi,
+		LWS_CALLBACK_LOCK_POLL,
+		wsi->user_space, (void *) &pa, 0);
+
+	context->lws_lookup[wsi->sock] = wsi;
+	wsi->position_in_fds_table = context->fds_count;
+	context->fds[context->fds_count].fd = wsi->sock;
+	context->fds[context->fds_count].events = LWS_POLLIN;
+	
+	lws_plat_insert_socket_into_fds(context, wsi);
+
+	/* external POLL support via protocol 0 */
+	context->protocols[0].callback(context, wsi,
+		LWS_CALLBACK_ADD_POLL_FD,
+		wsi->user_space, (void *) &pa, 0);
+
+	context->protocols[0].callback(context, wsi,
+		LWS_CALLBACK_UNLOCK_POLL,
+		wsi->user_space, (void *)&pa, 0);
+
+	return 0;
+}
+
+int
+remove_wsi_socket_from_fds(struct libwebsocket_context *context,
+						      struct libwebsocket *wsi)
+{
+	int m;
+	struct libwebsocket_pollargs pa = { wsi->sock, 0, 0 };
+
+	lws_libev_io(context, wsi, LWS_EV_STOP | LWS_EV_READ | LWS_EV_WRITE);
+
+	if (!--context->fds_count) {
+		context->protocols[0].callback(context, wsi,
+			LWS_CALLBACK_LOCK_POLL,
+			wsi->user_space, (void *) &pa, 0);
+		goto do_ext;
+	}
+
+	if (wsi->sock > context->max_fds) {
+		lwsl_err("Socket fd %d too high (%d)\n",
+						   wsi->sock, context->max_fds);
+		return 1;
+	}
+
+	lwsl_info("%s: wsi=%p, sock=%d, fds pos=%d\n", __func__,
+				    wsi, wsi->sock, wsi->position_in_fds_table);
+
+	context->protocols[0].callback(context, wsi,
+		LWS_CALLBACK_LOCK_POLL,
+		wsi->user_space, (void *)&pa, 0);
+
+	m = wsi->position_in_fds_table; /* replace the contents for this */
+
+	/* have the last guy take up the vacant slot */
+	context->fds[m] = context->fds[context->fds_count];
+
+	lws_plat_delete_socket_from_fds(context, wsi, m);
+
+	/*
+	 * end guy's fds_lookup entry remains unchanged
+	 * (still same fd pointing to same wsi)
+	 */
+	/* end guy's "position in fds table" changed */
+	context->lws_lookup[context->fds[context->fds_count].fd]->
+						position_in_fds_table = m;
+	/* deletion guy's lws_lookup entry needs nuking */
+	context->lws_lookup[wsi->sock] = NULL;
+	/* removed wsi has no position any more */
+	wsi->position_in_fds_table = -1;
+
+do_ext:
+	/* remove also from external POLL support via protocol 0 */
+	if (wsi->sock) {
+		context->protocols[0].callback(context, wsi,
+		    LWS_CALLBACK_DEL_POLL_FD, wsi->user_space,
+		    (void *) &pa, 0);
+	}
+	context->protocols[0].callback(context, wsi,
+				       LWS_CALLBACK_UNLOCK_POLL,
+				       wsi->user_space, (void *) &pa, 0);
+	return 0;
+}
+
+int
+lws_change_pollfd(struct libwebsocket *wsi, int _and, int _or)
+{
+	struct libwebsocket_context *context;
+	int tid;
+	int sampled_tid;
+	struct libwebsocket_pollfd *pfd;
+	struct libwebsocket_pollargs pa;
+
+	if (!wsi || !wsi->protocol || wsi->position_in_fds_table < 0)
+		return 1;
+	
+	context = wsi->protocol->owning_server;
+	if (!context)
+		return 1;
+
+	pfd = &context->fds[wsi->position_in_fds_table];
+	pa.fd = wsi->sock;
+
+	context->protocols[0].callback(context, wsi,
+		LWS_CALLBACK_LOCK_POLL, wsi->user_space,  (void *) &pa, 0);
+
+	pa.prev_events = pfd->events;
+	pa.events = pfd->events = (pfd->events & ~_and) | _or;
+
+	context->protocols[0].callback(context, wsi,
+			LWS_CALLBACK_CHANGE_MODE_POLL_FD,
+				wsi->user_space, (void *) &pa, 0);
+
+	/*
+	 * if we changed something in this pollfd...
+	 *   ... and we're running in a different thread context
+	 *     than the service thread...
+	 *       ... and the service thread is waiting ...
+	 *         then cancel it to force a restart with our changed events
+	 */
+	if (pa.prev_events != pa.events) {
+		
+		if (lws_plat_change_pollfd(context, wsi, pfd)) {
+			lwsl_info("%s failed\n", __func__);
+			return 1;
+		}
+
+		sampled_tid = context->service_tid;
+		if (sampled_tid) {
+			tid = context->protocols[0].callback(context, NULL,
+				     LWS_CALLBACK_GET_THREAD_ID, NULL, NULL, 0);
+			if (tid != sampled_tid)
+				libwebsocket_cancel_service(context);
+		}
+	}
+
+	context->protocols[0].callback(context, wsi,
+		LWS_CALLBACK_UNLOCK_POLL, wsi->user_space, (void *) &pa, 0);
+	
+	return 0;
+}
+
+
+/**
+ * libwebsocket_callback_on_writable() - Request a callback when this socket
+ *					 becomes able to be written to without
+ *					 blocking
+ *
+ * @context:	libwebsockets context
+ * @wsi:	Websocket connection instance to get callback for
+ */
+
+LWS_VISIBLE int
+libwebsocket_callback_on_writable(struct libwebsocket_context *context,
+						      struct libwebsocket *wsi)
+{
+#ifdef LWS_USE_HTTP2
+	struct libwebsocket *network_wsi, *wsi2;
+	int already;
+
+	lwsl_info("%s: %p\n", __func__, wsi);
+	
+	if (wsi->mode != LWS_CONNMODE_HTTP2_SERVING)
+		goto network_sock;
+	
+	if (wsi->u.http2.requested_POLLOUT) {
+		lwsl_info("already pending writable\n");
+		return 1;
+	}
+	
+	if (wsi->u.http2.tx_credit <= 0) {
+		/*
+		 * other side is not able to cope with us sending
+		 * anything so no matter if we have POLLOUT on our side.
+		 * 
+		 * Delay waiting for our POLLOUT until peer indicates he has
+		 * space for more using tx window command in http2 layer
+		 */
+		lwsl_info("%s: %p: waiting_tx_credit (%d)\n", __func__, wsi, wsi->u.http2.tx_credit);
+		wsi->u.http2.waiting_tx_credit = 1;
+		return 0;
+	}
+	
+	network_wsi = lws_http2_get_network_wsi(wsi);
+	already = network_wsi->u.http2.requested_POLLOUT;
+	
+	/* mark everybody above him as requesting pollout */
+	
+	wsi2 = wsi;
+	while (wsi2) {
+		wsi2->u.http2.requested_POLLOUT = 1;
+		lwsl_info("mark %p pending writable\n", wsi2);
+		wsi2 = wsi2->u.http2.parent_wsi;
+	}
+	
+	/* for network action, act only on the network wsi */
+	
+	wsi = network_wsi;
+	if (already)
+		return 1;
+network_sock:
+#endif
+
+	if (lws_ext_callback_for_each_active(wsi,
+				LWS_EXT_CALLBACK_REQUEST_ON_WRITEABLE, NULL, 0))
+		return 1;
+
+	if (wsi->position_in_fds_table < 0) {
+		lwsl_err("%s: failed to find socket %d\n", __func__, wsi->sock);
+		return -1;
+	}
+
+	if (lws_change_pollfd(wsi, 0, LWS_POLLOUT))
+		return -1;
+
+	lws_libev_io(context, wsi, LWS_EV_START | LWS_EV_WRITE);
+
+	return 1;
+}
+
+/**
+ * libwebsocket_callback_on_writable_all_protocol() - Request a callback for
+ *			all connections using the given protocol when it
+ *			becomes possible to write to each socket without
+ *			blocking in turn.
+ *
+ * @protocol:	Protocol whose connections will get callbacks
+ */
+
+LWS_VISIBLE int
+libwebsocket_callback_on_writable_all_protocol(
+				  const struct libwebsocket_protocols *protocol)
+{
+	struct libwebsocket_context *context = protocol->owning_server;
+	int n;
+	struct libwebsocket *wsi;
+
+	for (n = 0; n < context->fds_count; n++) {
+		wsi = context->lws_lookup[context->fds[n].fd];
+		if (!wsi)
+			continue;
+		if (wsi->protocol == protocol)
+			libwebsocket_callback_on_writable(context, wsi);
+	}
+
+	return 0;
+}
diff --git a/src/engine/external/libwebsockets/private-libwebsockets.h b/src/engine/external/libwebsockets/private-libwebsockets.h
new file mode 100755
index 00000000..de43ec42
--- /dev/null
+++ b/src/engine/external/libwebsockets/private-libwebsockets.h
@@ -0,0 +1,1211 @@
+/*
+ * libwebsockets - small server side websockets and web server implementation
+ *
+ * Copyright (C) 2010 - 2013 Andy Green <andy@warmcat.com>
+ *
+ *  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:
+ *  version 2.1 of the License.
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston,
+ *  MA  02110-1301  USA
+ */
+
+/* System introspection configs */
+#ifdef CMAKE_BUILD
+#include "lws_config.h"
+#else
+#if defined(WIN32) || defined(_WIN32)
+#define inline __inline
+#else /* not WIN32 */
+#include "config.h"
+
+#endif /* not WIN32 */
+#endif /* not CMAKE */
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdarg.h>
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+#if defined(WIN32) || defined(_WIN32)
+#define LWS_NO_DAEMONIZE
+#define LWS_ERRNO WSAGetLastError()
+#define LWS_EAGAIN WSAEWOULDBLOCK
+#define LWS_EALREADY WSAEALREADY
+#define LWS_EINPROGRESS WSAEINPROGRESS
+#define LWS_EINTR WSAEINTR
+#define LWS_EISCONN WSAEISCONN
+#define LWS_EWOULDBLOCK WSAEWOULDBLOCK
+#define LWS_POLLHUP (FD_CLOSE)
+#define LWS_POLLIN (FD_READ | FD_ACCEPT)
+#define LWS_POLLOUT (FD_WRITE)
+#define MSG_NOSIGNAL 0
+#define SHUT_RDWR SD_BOTH
+#define SOL_TCP IPPROTO_TCP
+
+#define compatible_close(fd) closesocket(fd)
+#define compatible_file_close(fd) CloseHandle(fd)
+#define compatible_file_seek_cur(fd, offset) SetFilePointer(fd, offset, NULL, FILE_CURRENT)
+#define compatible_file_read(amount, fd, buf, len) {\
+	DWORD _amount; \
+	if (!ReadFile(fd, buf, len, &_amount, NULL)) \
+		amount = -1; \
+	else \
+		amount = _amount; \
+	}
+#define lws_set_blocking_send(wsi) wsi->sock_send_blocking = TRUE
+#include <winsock2.h>
+#include <windows.h>
+#include <tchar.h>
+#ifdef HAVE_IN6ADDR_H
+#include <in6addr.h>
+#endif
+#include <mstcpip.h>
+
+#ifndef __func__
+#define __func__ __FUNCTION__
+#endif
+
+#ifdef _WIN32_WCE
+#define vsnprintf _vsnprintf
+#endif
+
+#define LWS_INVALID_FILE INVALID_HANDLE_VALUE
+#else /* not windows --> */
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <signal.h>
+#include <strings.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#ifdef LWS_BUILTIN_GETIFADDRS
+ #include <getifaddrs.h>
+#else
+ #include <ifaddrs.h>
+#endif
+#if defined (__ANDROID__)
+#include <syslog.h>
+#else
+#include <sys/syslog.h>
+#endif
+#include <sys/un.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#ifndef LWS_NO_FORK
+#ifdef HAVE_SYS_PRCTL_H
+#include <sys/prctl.h>
+#endif
+#endif
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <poll.h>
+#ifdef LWS_USE_LIBEV
+#include <ev.h>
+#endif /* LWS_USE_LIBEV */
+
+#include <sys/mman.h>
+#include <sys/time.h>
+
+#define LWS_ERRNO errno
+#define LWS_EAGAIN EAGAIN
+#define LWS_EALREADY EALREADY
+#define LWS_EINPROGRESS EINPROGRESS
+#define LWS_EINTR EINTR
+#define LWS_EISCONN EISCONN
+#define LWS_EWOULDBLOCK EWOULDBLOCK
+#define LWS_INVALID_FILE -1
+#define LWS_POLLHUP (POLLHUP|POLLERR)
+#define LWS_POLLIN (POLLIN)
+#define LWS_POLLOUT (POLLOUT)
+#define compatible_close(fd) close(fd)
+#define compatible_file_close(fd) close(fd)
+#define compatible_file_seek_cur(fd, offset) lseek(fd, offset, SEEK_CUR)
+#define compatible_file_read(amount, fd, buf, len) \
+		amount = read(fd, buf, len);
+#define lws_set_blocking_send(wsi)
+#endif
+
+#ifndef HAVE_BZERO
+#ifndef bzero
+#define bzero(b, len) (memset((b), '\0', (len)), (void) 0)
+#endif
+#endif
+
+#ifndef HAVE_STRERROR
+#define strerror(x) ""
+#endif
+
+#ifdef LWS_OPENSSL_SUPPORT
+#ifdef USE_CYASSL
+#include <cyassl/openssl/ssl.h>
+#include <cyassl/error-ssl.h>
+#else
+#include <openssl/ssl.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/md5.h>
+#include <openssl/sha.h>
+#endif /* not USE_CYASSL */
+#endif
+
+#include "libwebsockets.h"
+
+#if defined(WIN32) || defined(_WIN32)
+
+#ifndef BIG_ENDIAN
+#define BIG_ENDIAN    4321  /* to show byte order (taken from gcc) */
+#endif
+#ifndef LITTLE_ENDIAN
+#define LITTLE_ENDIAN 1234
+#endif
+#ifndef BYTE_ORDER
+#define BYTE_ORDER LITTLE_ENDIAN
+#endif
+typedef unsigned __int64 u_int64_t;
+
+#undef __P
+#ifndef __P
+#if __STDC__
+#define __P(protos) protos
+#else
+#define __P(protos) ()
+#endif
+#endif
+
+#else
+
+#include <sys/stat.h>
+#include <sys/cdefs.h>
+#include <sys/time.h>
+
+#if defined(__APPLE__)
+#include <machine/endian.h>
+#elif defined(__FreeBSD__)
+#include <sys/endian.h>
+#elif defined(__linux__)
+#include <endian.h>
+#endif
+
+#include <stddef.h>
+
+#ifndef container_of
+#define container_of(P,T,M)	((T *)((char *)(P) - offsetof(T, M)))
+#endif
+
+#if defined(__QNX__)
+	#include <gulliver.h>
+	#if defined(__LITTLEENDIAN__)
+		#define BYTE_ORDER __LITTLEENDIAN__
+		#define LITTLE_ENDIAN __LITTLEENDIAN__
+		#define BIG_ENDIAN 4321  /* to show byte order (taken from gcc); for suppres warning that BIG_ENDIAN is not defined. */
+	#endif
+	#if defined(__BIGENDIAN__)
+		#define BYTE_ORDER __BIGENDIAN__
+		#define LITTLE_ENDIAN 1234  /* to show byte order (taken from gcc); for suppres warning that LITTLE_ENDIAN is not defined. */
+		#define BIG_ENDIAN __BIGENDIAN__
+	#endif
+#endif
+
+#if !defined(BYTE_ORDER)
+# define BYTE_ORDER __BYTE_ORDER
+#endif
+#if !defined(LITTLE_ENDIAN)
+# define LITTLE_ENDIAN __LITTLE_ENDIAN
+#endif
+#if !defined(BIG_ENDIAN)
+# define BIG_ENDIAN __BIG_ENDIAN
+#endif
+
+#endif
+
+/*
+ * Mac OSX as well as iOS do not define the MSG_NOSIGNAL flag,
+ * but happily have something equivalent in the SO_NOSIGPIPE flag.
+ */
+#ifdef __APPLE__
+#define MSG_NOSIGNAL SO_NOSIGPIPE
+#endif
+
+#ifndef LWS_MAX_HEADER_LEN
+#define LWS_MAX_HEADER_LEN 1024
+#endif
+#ifndef LWS_MAX_PROTOCOLS
+#define LWS_MAX_PROTOCOLS 5
+#endif
+#ifndef LWS_MAX_EXTENSIONS_ACTIVE
+#define LWS_MAX_EXTENSIONS_ACTIVE 3
+#endif
+#ifndef SPEC_LATEST_SUPPORTED
+#define SPEC_LATEST_SUPPORTED 13
+#endif
+#ifndef AWAITING_TIMEOUT
+#define AWAITING_TIMEOUT 5
+#endif
+#ifndef CIPHERS_LIST_STRING
+#define CIPHERS_LIST_STRING "DEFAULT"
+#endif
+#ifndef LWS_SOMAXCONN
+#define LWS_SOMAXCONN SOMAXCONN
+#endif
+
+#define MAX_WEBSOCKET_04_KEY_LEN 128
+#define LWS_MAX_SOCKET_IO_BUF 4096
+
+#ifndef SYSTEM_RANDOM_FILEPATH
+#define SYSTEM_RANDOM_FILEPATH "/dev/urandom"
+#endif
+#ifndef LWS_MAX_ZLIB_CONN_BUFFER
+#define LWS_MAX_ZLIB_CONN_BUFFER (64 * 1024)
+#endif
+
+/*
+ * if not in a connection storm, check for incoming
+ * connections this many normal connection services
+ */
+#define LWS_LISTEN_SERVICE_MODULO 10
+
+enum lws_websocket_opcodes_07 {
+	LWS_WS_OPCODE_07__CONTINUATION = 0,
+	LWS_WS_OPCODE_07__TEXT_FRAME = 1,
+	LWS_WS_OPCODE_07__BINARY_FRAME = 2,
+
+	LWS_WS_OPCODE_07__NOSPEC__MUX = 7,
+
+	/* control extensions 8+ */
+
+	LWS_WS_OPCODE_07__CLOSE = 8,
+	LWS_WS_OPCODE_07__PING = 9,
+	LWS_WS_OPCODE_07__PONG = 0xa,
+};
+
+
+enum lws_connection_states {
+	WSI_STATE_HTTP,
+	WSI_STATE_HTTP_ISSUING_FILE,
+	WSI_STATE_HTTP_HEADERS,
+	WSI_STATE_HTTP_BODY,
+	WSI_STATE_DEAD_SOCKET,
+	WSI_STATE_ESTABLISHED,
+	WSI_STATE_CLIENT_UNCONNECTED,
+	WSI_STATE_RETURNED_CLOSE_ALREADY,
+	WSI_STATE_AWAITING_CLOSE_ACK,
+	WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE,
+	
+	WSI_STATE_HTTP2_AWAIT_CLIENT_PREFACE,
+	WSI_STATE_HTTP2_ESTABLISHED_PRE_SETTINGS,
+	WSI_STATE_HTTP2_ESTABLISHED,
+};
+
+enum http_version {
+	HTTP_VERSION_1_0,
+	HTTP_VERSION_1_1,
+};
+
+enum http_connection_type {
+	HTTP_CONNECTION_CLOSE,
+	HTTP_CONNECTION_KEEP_ALIVE
+};
+
+enum lws_pending_protocol_send {
+	LWS_PPS_NONE,
+	LWS_PPS_HTTP2_MY_SETTINGS,
+	LWS_PPS_HTTP2_ACK_SETTINGS,
+	LWS_PPS_HTTP2_PONG,
+};
+
+enum lws_rx_parse_state {
+	LWS_RXPS_NEW,
+
+	LWS_RXPS_04_MASK_NONCE_1,
+	LWS_RXPS_04_MASK_NONCE_2,
+	LWS_RXPS_04_MASK_NONCE_3,
+
+	LWS_RXPS_04_FRAME_HDR_1,
+	LWS_RXPS_04_FRAME_HDR_LEN,
+	LWS_RXPS_04_FRAME_HDR_LEN16_2,
+	LWS_RXPS_04_FRAME_HDR_LEN16_1,
+	LWS_RXPS_04_FRAME_HDR_LEN64_8,
+	LWS_RXPS_04_FRAME_HDR_LEN64_7,
+	LWS_RXPS_04_FRAME_HDR_LEN64_6,
+	LWS_RXPS_04_FRAME_HDR_LEN64_5,
+	LWS_RXPS_04_FRAME_HDR_LEN64_4,
+	LWS_RXPS_04_FRAME_HDR_LEN64_3,
+	LWS_RXPS_04_FRAME_HDR_LEN64_2,
+	LWS_RXPS_04_FRAME_HDR_LEN64_1,
+
+	LWS_RXPS_07_COLLECT_FRAME_KEY_1,
+	LWS_RXPS_07_COLLECT_FRAME_KEY_2,
+	LWS_RXPS_07_COLLECT_FRAME_KEY_3,
+	LWS_RXPS_07_COLLECT_FRAME_KEY_4,
+
+	LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED
+};
+
+
+enum connection_mode {
+	LWS_CONNMODE_HTTP_SERVING,
+	LWS_CONNMODE_HTTP_SERVING_ACCEPTED, /* actual HTTP service going on */
+	LWS_CONNMODE_PRE_WS_SERVING_ACCEPT,
+
+	LWS_CONNMODE_WS_SERVING,
+	LWS_CONNMODE_WS_CLIENT,
+	
+	LWS_CONNMODE_HTTP2_SERVING,
+
+	/* transient, ssl delay hiding */
+	LWS_CONNMODE_SSL_ACK_PENDING,
+
+	/* transient modes */
+	LWS_CONNMODE_WS_CLIENT_WAITING_CONNECT,
+	LWS_CONNMODE_WS_CLIENT_WAITING_PROXY_REPLY,
+	LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE,
+	LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE2,
+	LWS_CONNMODE_WS_CLIENT_WAITING_SSL,
+	LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY,
+	LWS_CONNMODE_WS_CLIENT_WAITING_EXTENSION_CONNECT,
+	LWS_CONNMODE_WS_CLIENT_PENDING_CANDIDATE_CHILD,
+
+	/* special internal types */
+	LWS_CONNMODE_SERVER_LISTENER,
+};
+
+enum {
+	LWS_RXFLOW_ALLOW = (1 << 0),
+	LWS_RXFLOW_PENDING_CHANGE = (1 << 1),
+};
+
+struct libwebsocket_protocols;
+struct libwebsocket;
+
+#ifdef LWS_USE_LIBEV
+struct lws_io_watcher {
+	struct ev_io watcher;
+	struct libwebsocket_context* context;
+};
+
+struct lws_signal_watcher {
+	struct ev_signal watcher;
+	struct libwebsocket_context* context;
+};
+#endif /* LWS_USE_LIBEV */
+
+struct libwebsocket_context {
+#ifdef _WIN32
+	WSAEVENT *events;
+#endif
+	struct libwebsocket_pollfd *fds;
+	struct libwebsocket **lws_lookup; /* fd to wsi */
+	int fds_count;
+#ifdef LWS_USE_LIBEV
+	struct ev_loop* io_loop;
+	struct lws_io_watcher w_accept;
+	struct lws_signal_watcher w_sigint;
+#endif /* LWS_USE_LIBEV */
+	int max_fds;
+	int listen_port;
+	const char *iface;
+	char http_proxy_address[128];
+	char canonical_hostname[128];
+	unsigned int http_proxy_port;
+	unsigned int options;
+	time_t last_timeout_check_s;
+
+	/*
+	 * usable by anything in the service code, but only if the scope
+	 * does not last longer than the service action (since next service
+	 * of any socket can likewise use it and overwrite)
+	 */
+	unsigned char service_buffer[LWS_MAX_SOCKET_IO_BUF];
+
+	int started_with_parent;
+
+	int fd_random;
+	int listen_service_modulo;
+	int listen_service_count;
+	int listen_service_fd;
+	int listen_service_extraseen;
+
+	/*
+	 * set to the Thread ID that's doing the service loop just before entry
+	 * to poll indicates service thread likely idling in poll()
+	 * volatile because other threads may check it as part of processing
+	 * for pollfd event change.
+	 */
+	volatile int service_tid;
+#ifndef _WIN32
+	int dummy_pipe_fds[2];
+#endif
+
+	int ka_time;
+	int ka_probes;
+	int ka_interval;
+
+#ifdef LWS_LATENCY
+	unsigned long worst_latency;
+	char worst_latency_info[256];
+#endif
+
+#ifdef LWS_OPENSSL_SUPPORT
+	int use_ssl;
+	int allow_non_ssl_on_ssl_port;
+	unsigned int user_supplied_ssl_ctx:1;
+	SSL_CTX *ssl_ctx;
+	SSL_CTX *ssl_client_ctx;
+	unsigned int ssl_flag_buffered_reads:1;
+#endif
+	struct libwebsocket_protocols *protocols;
+	int count_protocols;
+#ifndef LWS_NO_EXTENSIONS
+	struct libwebsocket_extension *extensions;
+#endif
+    struct lws_token_limits *token_limits;
+	void *user_space;
+};
+
+enum {
+	LWS_EV_READ = (1 << 0),
+	LWS_EV_WRITE = (1 << 1),
+	LWS_EV_START = (1 << 2),
+	LWS_EV_STOP = (1 << 3),
+};
+
+#ifdef LWS_USE_LIBEV
+#define LWS_LIBEV_ENABLED(context) (context->options & LWS_SERVER_OPTION_LIBEV)
+LWS_EXTERN void lws_feature_status_libev(struct lws_context_creation_info *info);
+LWS_EXTERN void
+lws_libev_accept(struct libwebsocket_context *context,
+		 struct libwebsocket *new_wsi, int accept_fd);
+LWS_EXTERN void
+lws_libev_io(struct libwebsocket_context *context,
+				struct libwebsocket *wsi, int flags);
+LWS_EXTERN int
+lws_libev_init_fd_table(struct libwebsocket_context *context);
+LWS_EXTERN void
+lws_libev_run(struct libwebsocket_context *context);
+#else
+#define LWS_LIBEV_ENABLED(context) (0)
+#define lws_feature_status_libev(_a) \
+			lwsl_notice("libev support not compiled in\n")
+#define lws_libev_accept(_a, _b, _c) ((void) 0)
+#define lws_libev_io(_a, _b, _c) ((void) 0)
+#define lws_libev_init_fd_table(_a) (0)
+#define lws_libev_run(_a) ((void) 0)
+#endif
+
+#ifdef LWS_USE_IPV6
+#define LWS_IPV6_ENABLED(context) (!(context->options & LWS_SERVER_OPTION_DISABLE_IPV6))
+#else
+#define LWS_IPV6_ENABLED(context) (0)
+#endif
+
+enum uri_path_states {
+	URIPS_IDLE,
+	URIPS_SEEN_SLASH,
+	URIPS_SEEN_SLASH_DOT,
+	URIPS_SEEN_SLASH_DOT_DOT,
+	URIPS_ARGUMENTS,
+};
+
+enum uri_esc_states {
+	URIES_IDLE,
+	URIES_SEEN_PERCENT,
+	URIES_SEEN_PERCENT_H1,
+};
+
+/*
+ * This is totally opaque to code using the library.  It's exported as a
+ * forward-reference pointer-only declaration; the user can use the pointer with
+ * other APIs to get information out of it.
+ */
+
+struct lws_fragments {
+	unsigned short offset;
+	unsigned short len;
+	unsigned char next_frag_index;
+};
+
+/* notice that these union members:
+ * 
+ *  hdr
+ *  http
+ *  http2
+ * 
+ * all have a pointer to allocated_headers struct as their first member.
+ * 
+ * It means for allocated_headers access, the three union paths can all be
+ * used interchangably to access the same data
+ */
+
+struct allocated_headers {
+	unsigned short next_frag_index;
+	unsigned short pos;
+	unsigned char frag_index[WSI_TOKEN_COUNT];
+	struct lws_fragments frags[WSI_TOKEN_COUNT * 2];
+	char data[LWS_MAX_HEADER_LEN];
+#ifndef LWS_NO_CLIENT
+	char initial_handshake_hash_base64[30];
+	unsigned short c_port;
+#endif
+};
+
+struct _lws_http_mode_related {
+	/* MUST be first in struct */
+	struct allocated_headers *ah; /* mirroring  _lws_header_related */
+#if defined(WIN32) || defined(_WIN32)
+	HANDLE fd;
+#else
+	int fd;
+#endif
+	unsigned long filepos;
+	unsigned long filelen;
+
+	enum http_version request_version;
+	enum http_connection_type connection_type;
+	int content_length;
+	int content_remain;
+};
+
+
+#ifdef LWS_USE_HTTP2
+
+enum lws_http2_settings {
+	LWS_HTTP2_SETTINGS__HEADER_TABLE_SIZE = 1,
+	LWS_HTTP2_SETTINGS__ENABLE_PUSH,
+	LWS_HTTP2_SETTINGS__MAX_CONCURRENT_STREAMS,
+	LWS_HTTP2_SETTINGS__INITIAL_WINDOW_SIZE,
+	LWS_HTTP2_SETTINGS__MAX_FRAME_SIZE,
+	LWS_HTTP2_SETTINGS__MAX_HEADER_LIST_SIZE,
+	
+	LWS_HTTP2_SETTINGS__COUNT /* always last */
+};
+
+enum lws_http2_wellknown_frame_types {
+	LWS_HTTP2_FRAME_TYPE_DATA,
+	LWS_HTTP2_FRAME_TYPE_HEADERS,
+	LWS_HTTP2_FRAME_TYPE_PRIORITY,
+	LWS_HTTP2_FRAME_TYPE_RST_STREAM,
+	LWS_HTTP2_FRAME_TYPE_SETTINGS,
+	LWS_HTTP2_FRAME_TYPE_PUSH_PROMISE,
+	LWS_HTTP2_FRAME_TYPE_PING,
+	LWS_HTTP2_FRAME_TYPE_GOAWAY,
+	LWS_HTTP2_FRAME_TYPE_WINDOW_UPDATE,
+	LWS_HTTP2_FRAME_TYPE_CONTINUATION,
+	
+	LWS_HTTP2_FRAME_TYPE_COUNT /* always last */
+};
+
+enum lws_http2_flags {
+	LWS_HTTP2_FLAG_END_STREAM = 1,
+	LWS_HTTP2_FLAG_END_HEADERS = 4,
+	LWS_HTTP2_FLAG_PADDED = 8,
+	LWS_HTTP2_FLAG_PRIORITY = 0x20,
+
+	LWS_HTTP2_FLAG_SETTINGS_ACK = 1,
+};
+
+#define LWS_HTTP2_STREAM_ID_MASTER 0
+#define LWS_HTTP2_FRAME_HEADER_LENGTH 9
+#define LWS_HTTP2_SETTINGS_LENGTH 6
+
+struct http2_settings {
+	unsigned int setting[LWS_HTTP2_SETTINGS__COUNT];
+};
+
+enum http2_hpack_state {
+	
+	/* optional before first header block */
+	HPKS_OPT_PADDING,
+	HKPS_OPT_E_DEPENDENCY,
+	HKPS_OPT_WEIGHT,
+	
+	/* header block */
+	HPKS_TYPE,
+	
+	HPKS_IDX_EXT,
+	
+	HPKS_HLEN,
+	HPKS_HLEN_EXT,
+
+	HPKS_DATA,
+	
+	/* optional after last header block */
+	HKPS_OPT_DISCARD_PADDING,
+};
+
+enum http2_hpack_type {
+	HPKT_INDEXED_HDR_7,
+	HPKT_INDEXED_HDR_6_VALUE_INCR,
+	HPKT_LITERAL_HDR_VALUE_INCR,
+	HPKT_INDEXED_HDR_4_VALUE,
+	HPKT_LITERAL_HDR_VALUE,
+	HPKT_SIZE_5
+};
+
+struct hpack_dt_entry {
+	int token; /* additions that don't map to a token are ignored */
+	int arg_offset;
+	int arg_len;
+};
+
+struct hpack_dynamic_table {
+	struct hpack_dt_entry *entries;
+	char *args;
+	int pos;
+	int next;
+	int num_entries;
+	int args_length;
+};
+
+struct _lws_http2_related {
+	/* 
+	 * having this first lets us also re-use all HTTP union code
+	 * and in turn, http_mode_related has allocated headers in right
+	 * place so we can use the header apis on the wsi directly still
+	 */
+	struct _lws_http_mode_related http; /* MUST BE FIRST IN STRUCT */
+
+	struct http2_settings my_settings;
+	struct http2_settings peer_settings;
+	
+	struct libwebsocket *parent_wsi;
+	struct libwebsocket *next_child_wsi;
+
+	struct hpack_dynamic_table *hpack_dyn_table;
+	
+	unsigned int count;
+	
+	/* frame */
+	unsigned int length;
+	unsigned int stream_id;
+	struct libwebsocket *stream_wsi;
+	unsigned char type;
+	unsigned char flags;
+	unsigned char frame_state;
+	unsigned char padding;
+
+	unsigned char ping_payload[8];
+	
+	unsigned short round_robin_POLLOUT;
+	unsigned short count_POLLOUT_children;
+
+	unsigned int END_STREAM:1;
+	unsigned int END_HEADERS:1;
+	unsigned int send_END_STREAM:1;
+	unsigned int GOING_AWAY;
+	unsigned int requested_POLLOUT:1;
+	unsigned int waiting_tx_credit:1;
+
+	/* hpack */
+	enum http2_hpack_state hpack;
+	enum http2_hpack_type hpack_type;
+	unsigned int header_index;
+	unsigned int hpack_len;
+	unsigned short hpack_pos;
+	unsigned char hpack_m;
+	unsigned int hpack_e_dep;
+	unsigned int huff:1;
+	unsigned int value:1;
+	
+	/* negative credit is mandated by the spec */
+	int tx_credit;
+	unsigned int my_stream_id;
+	unsigned int child_count;
+	int my_priority;
+	unsigned char initialized;
+	unsigned char one_setting[LWS_HTTP2_SETTINGS_LENGTH];
+};
+
+#define HTTP2_IS_TOPLEVEL_WSI(wsi) (!wsi->u.http2.parent_wsi)
+
+#endif
+
+struct _lws_header_related {
+	/* MUST be first in struct */
+	struct allocated_headers *ah;
+	short lextable_pos;
+	unsigned short current_token_limit;
+	unsigned char parser_state; /* enum lws_token_indexes */
+	enum uri_path_states ups;
+	enum uri_esc_states ues;
+	char esc_stash;
+};
+
+struct _lws_websocket_related {
+	char *rx_user_buffer;
+	int rx_user_buffer_head;
+	unsigned char frame_masking_nonce_04[4];
+	unsigned char frame_mask_index;
+	size_t rx_packet_length;
+	unsigned char opcode;
+	unsigned int final:1;
+	unsigned char rsv;
+	unsigned int frame_is_binary:1;
+	unsigned int all_zero_nonce:1;
+	short close_reason; /* enum lws_close_status */
+
+	unsigned int this_frame_masked:1;
+	unsigned int inside_frame:1; /* next write will be more of frame */
+	unsigned int clean_buffer:1; /* buffer not rewritten by extension */
+
+	unsigned char *ping_payload_buf; /* non-NULL if malloc'd */
+	unsigned int ping_payload_alloc; /* length malloc'd */
+	unsigned int ping_payload_len; /* nonzero if PONG pending */
+};
+
+struct libwebsocket {
+
+	/* lifetime members */
+
+#ifdef LWS_USE_LIBEV
+    struct lws_io_watcher w_read;
+    struct lws_io_watcher w_write;
+#endif /* LWS_USE_LIBEV */
+	const struct libwebsocket_protocols *protocol;
+#ifndef LWS_NO_EXTENSIONS
+	struct libwebsocket_extension *
+				   active_extensions[LWS_MAX_EXTENSIONS_ACTIVE];
+	void *active_extensions_user[LWS_MAX_EXTENSIONS_ACTIVE];
+	unsigned char count_active_extensions;
+	unsigned int extension_data_pending:1;
+#endif
+	unsigned char ietf_spec_revision;
+	enum lws_pending_protocol_send pps;
+
+	char mode; /* enum connection_mode */
+	char state; /* enum lws_connection_states */
+	char lws_rx_parse_state; /* enum lws_rx_parse_state */
+	char rx_frame_type; /* enum libwebsocket_write_protocol */
+
+	unsigned int hdr_parsing_completed:1;
+	unsigned int user_space_externally_allocated:1;
+	unsigned int socket_is_permanently_unusable:1;
+
+	char pending_timeout; /* enum pending_timeout */
+	time_t pending_timeout_limit;
+
+	int sock;
+	int position_in_fds_table;
+#ifdef LWS_LATENCY
+	unsigned long action_start;
+	unsigned long latency_start;
+#endif
+	/* rxflow handling */
+	unsigned char *rxflow_buffer;
+	int rxflow_len;
+	int rxflow_pos;
+	unsigned int rxflow_change_to:2;
+
+	/* truncated send handling */
+	unsigned char *truncated_send_malloc; /* non-NULL means buffering in progress */
+	unsigned int truncated_send_allocation; /* size of malloc */
+	unsigned int truncated_send_offset; /* where we are in terms of spilling */
+	unsigned int truncated_send_len; /* how much is buffered */
+
+	void *user_space;
+
+	/* members with mutually exclusive lifetimes are unionized */
+
+	union u {
+		struct _lws_http_mode_related http;
+#ifdef LWS_USE_HTTP2
+		struct _lws_http2_related http2;
+#endif
+		struct _lws_header_related hdr;
+		struct _lws_websocket_related ws;
+	} u;
+
+#ifdef LWS_OPENSSL_SUPPORT
+	SSL *ssl;
+	BIO *client_bio;
+	unsigned int use_ssl:2;
+	unsigned int buffered_reads_pending:1;
+	unsigned int upgraded:1;
+#endif
+
+#ifdef _WIN32
+	BOOL sock_send_blocking;
+#endif
+};
+
+LWS_EXTERN int log_level;
+
+LWS_EXTERN void
+libwebsocket_close_and_free_session(struct libwebsocket_context *context,
+			       struct libwebsocket *wsi, enum lws_close_status);
+
+LWS_EXTERN int
+remove_wsi_socket_from_fds(struct libwebsocket_context *context,
+						      struct libwebsocket *wsi);
+LWS_EXTERN int
+lws_rxflow_cache(struct libwebsocket *wsi, unsigned char *buf, int n, int len);
+
+#ifndef LWS_LATENCY
+static inline void lws_latency(struct libwebsocket_context *context,
+		struct libwebsocket *wsi, const char *action,
+					 int ret, int completion) { do { } while (0); }
+static inline void lws_latency_pre(struct libwebsocket_context *context,
+					struct libwebsocket *wsi) { do { } while (0); }
+#else
+#define lws_latency_pre(_context, _wsi) lws_latency(_context, _wsi, NULL, 0, 0)
+extern void
+lws_latency(struct libwebsocket_context *context,
+			struct libwebsocket *wsi, const char *action,
+						       int ret, int completion);
+#endif
+
+LWS_EXTERN void lws_set_protocol_write_pending(struct libwebsocket_context *context,
+				    struct libwebsocket *wsi,
+				    enum lws_pending_protocol_send pend);
+LWS_EXTERN int
+libwebsocket_client_rx_sm(struct libwebsocket *wsi, unsigned char c);
+
+LWS_EXTERN int
+libwebsocket_parse(struct libwebsocket_context *context,
+		struct libwebsocket *wsi, unsigned char c);
+
+LWS_EXTERN int
+lws_http_action(struct libwebsocket_context *context, struct libwebsocket *wsi);
+
+LWS_EXTERN int
+lws_b64_selftest(void);
+
+LWS_EXTERN struct libwebsocket *
+wsi_from_fd(struct libwebsocket_context *context, int fd);
+
+LWS_EXTERN int
+insert_wsi_socket_into_fds(struct libwebsocket_context *context,
+						      struct libwebsocket *wsi);
+
+LWS_EXTERN int
+lws_issue_raw(struct libwebsocket *wsi, unsigned char *buf, size_t len);
+
+
+LWS_EXTERN int
+libwebsocket_service_timeout_check(struct libwebsocket_context *context,
+				    struct libwebsocket *wsi, unsigned int sec);
+
+LWS_EXTERN struct libwebsocket *
+libwebsocket_client_connect_2(struct libwebsocket_context *context,
+	struct libwebsocket *wsi);
+
+LWS_EXTERN struct libwebsocket *
+libwebsocket_create_new_server_wsi(struct libwebsocket_context *context);
+
+LWS_EXTERN char *
+libwebsockets_generate_client_handshake(struct libwebsocket_context *context,
+		struct libwebsocket *wsi, char *pkt);
+
+LWS_EXTERN int
+lws_handle_POLLOUT_event(struct libwebsocket_context *context,
+			      struct libwebsocket *wsi, struct libwebsocket_pollfd *pollfd);
+
+/*
+ * EXTENSIONS
+ */
+
+#ifndef LWS_NO_EXTENSIONS
+LWS_VISIBLE void
+lws_context_init_extensions(struct lws_context_creation_info *info,
+				    struct libwebsocket_context *context);
+LWS_EXTERN int
+lws_any_extension_handled(struct libwebsocket_context *context,
+			  struct libwebsocket *wsi,
+			  enum libwebsocket_extension_callback_reasons r,
+			  void *v, size_t len);
+
+LWS_EXTERN int
+lws_ext_callback_for_each_active(struct libwebsocket *wsi, int reason,
+						    void *buf, int len);
+LWS_EXTERN int
+lws_ext_callback_for_each_extension_type(
+		struct libwebsocket_context *context, struct libwebsocket *wsi,
+			int reason, void *arg, int len);
+#else
+#define lws_any_extension_handled(_a, _b, _c, _d, _e) (0)
+#define lws_ext_callback_for_each_active(_a, _b, _c, _d) (0)
+#define lws_ext_callback_for_each_extension_type(_a, _b, _c, _d, _e) (0)
+#define lws_issue_raw_ext_access lws_issue_raw
+#define lws_context_init_extensions(_a, _b)
+#endif
+
+LWS_EXTERN int
+lws_client_interpret_server_handshake(struct libwebsocket_context *context,
+		struct libwebsocket *wsi);
+
+LWS_EXTERN int
+libwebsocket_rx_sm(struct libwebsocket *wsi, unsigned char c);
+
+LWS_EXTERN int
+lws_issue_raw_ext_access(struct libwebsocket *wsi,
+						unsigned char *buf, size_t len);
+
+LWS_EXTERN int
+_libwebsocket_rx_flow_control(struct libwebsocket *wsi);
+
+LWS_EXTERN void
+lws_union_transition(struct libwebsocket *wsi, enum connection_mode mode);
+
+LWS_EXTERN int
+user_callback_handle_rxflow(callback_function,
+		struct libwebsocket_context *context,
+			struct libwebsocket *wsi,
+			 enum libwebsocket_callback_reasons reason, void *user,
+							  void *in, size_t len);
+#ifdef LWS_USE_HTTP2
+LWS_EXTERN struct libwebsocket *lws_http2_get_network_wsi(struct libwebsocket *wsi);
+struct libwebsocket * lws_http2_get_nth_child(struct libwebsocket *wsi, int n);
+LWS_EXTERN int
+lws_http2_interpret_settings_payload(struct http2_settings *settings, unsigned char *buf, int len);
+LWS_EXTERN void lws_http2_init(struct http2_settings *settings);
+LWS_EXTERN int
+lws_http2_parser(struct libwebsocket_context *context,
+		     struct libwebsocket *wsi, unsigned char c);
+LWS_EXTERN int lws_http2_do_pps_send(struct libwebsocket_context *context, struct libwebsocket *wsi);
+LWS_EXTERN int lws_http2_frame_write(struct libwebsocket *wsi, int type, int flags, unsigned int sid, unsigned int len, unsigned char *buf);
+LWS_EXTERN struct libwebsocket *
+lws_http2_wsi_from_id(struct libwebsocket *wsi, unsigned int sid);
+LWS_EXTERN int lws_hpack_interpret(struct libwebsocket_context *context,
+				   struct libwebsocket *wsi,
+				   unsigned char c);
+LWS_EXTERN int
+lws_add_http2_header_by_name(struct libwebsocket_context *context,
+			    struct libwebsocket *wsi,
+			    const unsigned char *name,
+			    const unsigned char *value,
+			    int length,
+			    unsigned char **p,
+			    unsigned char *end);
+LWS_EXTERN int
+lws_add_http2_header_by_token(struct libwebsocket_context *context,
+			    struct libwebsocket *wsi,
+			    enum lws_token_indexes token,
+			    const unsigned char *value,
+			    int length,
+			    unsigned char **p,
+			    unsigned char *end);
+LWS_EXTERN int
+lws_add_http2_header_status(struct libwebsocket_context *context,
+			    struct libwebsocket *wsi,
+			    unsigned int code,
+			    unsigned char **p,
+			    unsigned char *end);
+LWS_EXTERN
+void lws_http2_configure_if_upgraded(struct libwebsocket *wsi);
+#else
+#define lws_http2_configure_if_upgraded(x)
+#endif
+
+LWS_EXTERN int
+lws_plat_set_socket_options(struct libwebsocket_context *context, int fd);
+
+LWS_EXTERN int
+lws_allocate_header_table(struct libwebsocket *wsi);
+
+LWS_EXTERN int
+lws_free_header_table(struct libwebsocket *wsi);
+
+LWS_EXTERN char *
+lws_hdr_simple_ptr(struct libwebsocket *wsi, enum lws_token_indexes h);
+
+LWS_EXTERN int
+lws_hdr_simple_create(struct libwebsocket *wsi,
+				enum lws_token_indexes h, const char *s);
+
+LWS_EXTERN int
+libwebsocket_ensure_user_space(struct libwebsocket *wsi);
+
+LWS_EXTERN int
+lws_change_pollfd(struct libwebsocket *wsi, int _and, int _or);
+
+#ifndef LWS_NO_SERVER
+int lws_context_init_server(struct lws_context_creation_info *info,
+			    struct libwebsocket_context *context);
+LWS_EXTERN int handshake_0405(struct libwebsocket_context *context,
+						      struct libwebsocket *wsi);
+LWS_EXTERN int
+libwebsocket_interpret_incoming_packet(struct libwebsocket *wsi,
+						unsigned char *buf, size_t len);
+LWS_EXTERN void
+lws_server_get_canonical_hostname(struct libwebsocket_context *context,
+				struct lws_context_creation_info *info);
+#else
+#define lws_context_init_server(_a, _b) (0)
+#define libwebsocket_interpret_incoming_packet(_a, _b, _c) (0)
+#define lws_server_get_canonical_hostname(_a, _b)
+#endif
+
+#ifndef LWS_NO_DAEMONIZE
+LWS_EXTERN int get_daemonize_pid();
+#else
+#define get_daemonize_pid() (0)
+#endif
+
+LWS_EXTERN int interface_to_sa(struct libwebsocket_context *context,
+		const char *ifname, struct sockaddr_in *addr, size_t addrlen);
+
+LWS_EXTERN void lwsl_emit_stderr(int level, const char *line);
+
+#ifdef _WIN32
+LWS_EXTERN HANDLE lws_plat_open_file(const char* filename, unsigned long* filelen);
+#else
+LWS_EXTERN int lws_plat_open_file(const char* filename, unsigned long* filelen);
+#endif
+
+enum lws_ssl_capable_status {
+	LWS_SSL_CAPABLE_ERROR = -1,
+	LWS_SSL_CAPABLE_MORE_SERVICE = -2,
+};
+
+#ifndef LWS_OPENSSL_SUPPORT
+#define LWS_SSL_ENABLED(context) (0)
+#define lws_context_init_server_ssl(_a, _b) (0)
+#define lws_ssl_destroy(_a)
+#define lws_context_init_http2_ssl(_a)
+#define lws_ssl_capable_read lws_ssl_capable_read_no_ssl
+#define lws_ssl_capable_write lws_ssl_capable_write_no_ssl
+#define lws_server_socket_service_ssl(_a, _b, _c, _d, _e) (0)
+#define lws_ssl_close(_a) (0)
+#define lws_ssl_context_destroy(_a)
+#else
+#define LWS_SSL_ENABLED(context) (context->use_ssl)
+LWS_EXTERN int openssl_websocket_private_data_index;
+LWS_EXTERN int
+lws_ssl_capable_read(struct libwebsocket_context *context,
+		     struct libwebsocket *wsi, unsigned char *buf, int len);
+
+LWS_EXTERN int
+lws_ssl_capable_write(struct libwebsocket *wsi, unsigned char *buf, int len);
+LWS_EXTERN int
+lws_server_socket_service_ssl(struct libwebsocket_context *context,
+		struct libwebsocket **wsi, struct libwebsocket *new_wsi,
+		int accept_fd, struct libwebsocket_pollfd *pollfd);
+LWS_EXTERN int
+lws_ssl_close(struct libwebsocket *wsi);
+LWS_EXTERN void
+lws_ssl_context_destroy(struct libwebsocket_context *context);
+#ifndef LWS_NO_SERVER
+LWS_EXTERN int
+lws_context_init_server_ssl(struct lws_context_creation_info *info,
+		     struct libwebsocket_context *context);
+#else
+#define lws_context_init_server_ssl(_a, _b) (0)
+#endif
+LWS_EXTERN void
+lws_ssl_destroy(struct libwebsocket_context *context);
+
+/* HTTP2-related */
+
+#ifdef LWS_USE_HTTP2
+LWS_EXTERN void
+lws_context_init_http2_ssl(struct libwebsocket_context *context);
+#else
+#define lws_context_init_http2_ssl(_a)
+#endif
+#endif
+
+LWS_EXTERN int
+lws_ssl_capable_read_no_ssl(struct libwebsocket_context *context,
+			    struct libwebsocket *wsi, unsigned char *buf, int len);
+
+LWS_EXTERN int
+lws_ssl_capable_write_no_ssl(struct libwebsocket *wsi, unsigned char *buf, int len);
+
+#ifndef LWS_NO_CLIENT
+	LWS_EXTERN int lws_client_socket_service(
+		struct libwebsocket_context *context,
+		struct libwebsocket *wsi, struct libwebsocket_pollfd *pollfd);
+#ifdef LWS_OPENSSL_SUPPORT
+	LWS_EXTERN int lws_context_init_client_ssl(struct lws_context_creation_info *info,
+			    struct libwebsocket_context *context);
+#else
+	#define lws_context_init_client_ssl(_a, _b) (0)
+#endif
+	LWS_EXTERN int lws_handshake_client(struct libwebsocket *wsi, unsigned char **buf, size_t len);
+	LWS_EXTERN void
+	libwebsockets_decode_ssl_error(void);
+#else
+#define lws_context_init_client_ssl(_a, _b) (0)
+#define lws_handshake_client(_a, _b, _c) (0)
+#endif
+#ifndef LWS_NO_SERVER
+	LWS_EXTERN int lws_server_socket_service(
+		struct libwebsocket_context *context,
+		struct libwebsocket *wsi, struct libwebsocket_pollfd *pollfd);
+	LWS_EXTERN int _libwebsocket_rx_flow_control(struct libwebsocket *wsi);
+	LWS_EXTERN int lws_handshake_server(struct libwebsocket_context *context,
+		     struct libwebsocket *wsi, unsigned char **buf, size_t len);
+#else
+#define lws_server_socket_service(_a, _b, _c) (0)
+#define _libwebsocket_rx_flow_control(_a) (0)
+#define lws_handshake_server(_a, _b, _c, _d) (0)
+#endif
+
+/*
+ * custom allocator
+ */
+LWS_EXTERN void*
+lws_realloc(void *ptr, size_t size);
+
+LWS_EXTERN void*
+lws_zalloc(size_t size);
+
+#define lws_malloc(S)	lws_realloc(NULL, S)
+#define lws_free(P)	lws_realloc(P, 0)
+#define lws_free2(P)	do { lws_realloc(P, 0); (P) = NULL; } while(0)
+
+/*
+ * lws_plat_
+ */
+LWS_EXTERN void
+lws_plat_delete_socket_from_fds(struct libwebsocket_context *context,
+					       struct libwebsocket *wsi, int m);
+LWS_EXTERN void
+lws_plat_insert_socket_into_fds(struct libwebsocket_context *context,
+						      struct libwebsocket *wsi);
+LWS_EXTERN void
+lws_plat_service_periodic(struct libwebsocket_context *context);
+
+LWS_EXTERN int
+lws_plat_change_pollfd(struct libwebsocket_context *context,
+		     struct libwebsocket *wsi, struct libwebsocket_pollfd *pfd);
+LWS_EXTERN int
+lws_plat_context_early_init(void);
+LWS_EXTERN void
+lws_plat_context_early_destroy(struct libwebsocket_context *context);
+LWS_EXTERN void
+lws_plat_context_late_destroy(struct libwebsocket_context *context);
+LWS_EXTERN int
+lws_poll_listen_fd(struct libwebsocket_pollfd *fd);
+LWS_EXTERN int
+lws_plat_service(struct libwebsocket_context *context, int timeout_ms);
+LWS_EXTERN int
+lws_plat_init_fd_tables(struct libwebsocket_context *context);
+LWS_EXTERN void
+lws_plat_drop_app_privileges(struct lws_context_creation_info *info);
+LWS_EXTERN unsigned long long
+time_in_microseconds(void);
+LWS_EXTERN const char *
+lws_plat_inet_ntop(int af, const void *src, char *dst, int cnt);
diff --git a/src/engine/external/libwebsockets/server-handshake.c b/src/engine/external/libwebsockets/server-handshake.c
new file mode 100644
index 00000000..b4641d1b
--- /dev/null
+++ b/src/engine/external/libwebsockets/server-handshake.c
@@ -0,0 +1,274 @@
+/*
+ * libwebsockets - small server side websockets and web server implementation
+ *
+ * Copyright (C) 2010-2013 Andy Green <andy@warmcat.com>
+ *
+ *  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:
+ *  version 2.1 of the License.
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston,
+ *  MA  02110-1301  USA
+ */
+
+#include "private-libwebsockets.h"
+
+#define LWS_CPYAPP(ptr, str) { strcpy(ptr, str); ptr += strlen(str); }
+#ifndef LWS_NO_EXTENSIONS
+LWS_VISIBLE int
+lws_extension_server_handshake(struct libwebsocket_context *context,
+			  struct libwebsocket *wsi, char **p)
+{
+	int n;
+	char *c;
+	char ext_name[128];
+	struct libwebsocket_extension *ext;
+	int ext_count = 0;
+	int more = 1;
+
+	/*
+	 * Figure out which extensions the client has that we want to
+	 * enable on this connection, and give him back the list
+	 */
+
+	if (!lws_hdr_total_length(wsi, WSI_TOKEN_EXTENSIONS))
+		return 0;
+
+	/*
+	 * break down the list of client extensions
+	 * and go through them
+	 */
+
+	if (lws_hdr_copy(wsi, (char *)context->service_buffer,
+			sizeof(context->service_buffer),
+					      WSI_TOKEN_EXTENSIONS) < 0)
+		return 1;
+
+	c = (char *)context->service_buffer;
+	lwsl_parser("WSI_TOKEN_EXTENSIONS = '%s'\n", c);
+	wsi->count_active_extensions = 0;
+	n = 0;
+	while (more) {
+
+		if (*c && (*c != ',' && *c != ' ' && *c != '\t')) {
+			ext_name[n] = *c++;
+			if (n < sizeof(ext_name) - 1)
+				n++;
+			continue;
+		}
+		ext_name[n] = '\0';
+		if (!*c)
+			more = 0;
+		else {
+			c++;
+			if (!n)
+				continue;
+		}
+
+		/* check a client's extension against our support */
+
+		ext = wsi->protocol->owning_server->extensions;
+
+		while (ext && ext->callback) {
+
+			if (strcmp(ext_name, ext->name)) {
+				ext++;
+				continue;
+			}
+
+			/*
+			 * oh, we do support this one he
+			 * asked for... but let's ask user
+			 * code if it's OK to apply it on this
+			 * particular connection + protocol
+			 */
+
+			n = wsi->protocol->owning_server->
+				protocols[0].callback(
+					wsi->protocol->owning_server,
+					wsi,
+				  LWS_CALLBACK_CONFIRM_EXTENSION_OKAY,
+					  wsi->user_space, ext_name, 0);
+
+			/*
+			 * zero return from callback means
+			 * go ahead and allow the extension,
+			 * it's what we get if the callback is
+			 * unhandled
+			 */
+
+			if (n) {
+				ext++;
+				continue;
+			}
+
+			/* apply it */
+
+			if (ext_count)
+				*(*p)++ = ',';
+			else
+				LWS_CPYAPP(*p,
+				 "\x0d\x0aSec-WebSocket-Extensions: ");
+			*p += sprintf(*p, "%s", ext_name);
+			ext_count++;
+
+			/* instantiate the extension on this conn */
+
+			wsi->active_extensions_user[
+				wsi->count_active_extensions] =
+				     lws_zalloc(ext->per_session_data_size);
+			if (wsi->active_extensions_user[
+			     wsi->count_active_extensions] == NULL) {
+				lwsl_err("Out of mem\n");
+				return 1;
+			}
+
+			wsi->active_extensions[
+				  wsi->count_active_extensions] = ext;
+
+			/* allow him to construct his context */
+
+			ext->callback(wsi->protocol->owning_server,
+					ext, wsi,
+					LWS_EXT_CALLBACK_CONSTRUCT,
+					wsi->active_extensions_user[
+				wsi->count_active_extensions], NULL, 0);
+
+			wsi->count_active_extensions++;
+			lwsl_parser("count_active_extensions <- %d\n",
+					  wsi->count_active_extensions);
+
+			ext++;
+		}
+
+		n = 0;
+	}
+
+	return 0;
+}
+#endif
+int
+handshake_0405(struct libwebsocket_context *context, struct libwebsocket *wsi)
+{
+	unsigned char hash[20];
+	int n;
+	char *response;
+	char *p;
+	int accept_len;
+
+	if (!lws_hdr_total_length(wsi, WSI_TOKEN_HOST) ||
+				!lws_hdr_total_length(wsi, WSI_TOKEN_KEY)) {
+		lwsl_parser("handshake_04 missing pieces\n");
+		/* completed header processing, but missing some bits */
+		goto bail;
+	}
+
+	if (lws_hdr_total_length(wsi, WSI_TOKEN_KEY) >=
+						     MAX_WEBSOCKET_04_KEY_LEN) {
+		lwsl_warn("Client key too long %d\n", MAX_WEBSOCKET_04_KEY_LEN);
+		goto bail;
+	}
+
+	/*
+	 * since key length is restricted above (currently 128), cannot
+	 * overflow
+	 */
+	n = sprintf((char *)context->service_buffer,
+				"%s258EAFA5-E914-47DA-95CA-C5AB0DC85B11",
+				lws_hdr_simple_ptr(wsi, WSI_TOKEN_KEY));
+
+	libwebsockets_SHA1(context->service_buffer, n, hash);
+
+	accept_len = lws_b64_encode_string((char *)hash, 20,
+			(char *)context->service_buffer,
+			sizeof(context->service_buffer));
+	if (accept_len < 0) {
+		lwsl_warn("Base64 encoded hash too long\n");
+		goto bail;
+	}
+
+	/* allocate the per-connection user memory (if any) */
+	if (libwebsocket_ensure_user_space(wsi))
+		goto bail;
+
+	/* create the response packet */
+
+	/* make a buffer big enough for everything */
+
+	response = (char *)context->service_buffer + MAX_WEBSOCKET_04_KEY_LEN + LWS_SEND_BUFFER_PRE_PADDING;
+	p = response;
+	LWS_CPYAPP(p, "HTTP/1.1 101 Switching Protocols\x0d\x0a"
+		      "Upgrade: WebSocket\x0d\x0a"
+		      "Connection: Upgrade\x0d\x0a"
+		      "Sec-WebSocket-Accept: ");
+	strcpy(p, (char *)context->service_buffer);
+	p += accept_len;
+
+	if (lws_hdr_total_length(wsi, WSI_TOKEN_PROTOCOL)) {
+		LWS_CPYAPP(p, "\x0d\x0aSec-WebSocket-Protocol: ");
+		n = lws_hdr_copy(wsi, p, 128, WSI_TOKEN_PROTOCOL);
+		if (n < 0)
+			goto bail;
+		p += n;
+	}
+
+#ifndef LWS_NO_EXTENSIONS
+	/*
+	 * Figure out which extensions the client has that we want to
+	 * enable on this connection, and give him back the list
+	 */
+	if (lws_extension_server_handshake(context, wsi, &p))
+		goto bail;
+#endif
+	/* end of response packet */
+
+	LWS_CPYAPP(p, "\x0d\x0a\x0d\x0a");
+	
+	if (!lws_any_extension_handled(context, wsi,
+			LWS_EXT_CALLBACK_HANDSHAKE_REPLY_TX,
+						     response, p - response)) {
+
+		/* okay send the handshake response accepting the connection */
+
+		lwsl_parser("issuing resp pkt %d len\n", (int)(p - response));
+#ifdef DEBUG
+		fwrite(response, 1,  p - response, stderr);
+#endif
+		n = libwebsocket_write(wsi, (unsigned char *)response,
+						  p - response, LWS_WRITE_HTTP_HEADERS);
+		if (n != (p - response)) {
+			lwsl_debug("handshake_0405: ERROR writing to socket\n");
+			goto bail;
+		}
+
+	}
+
+	/* alright clean up and set ourselves into established state */
+
+	wsi->state = WSI_STATE_ESTABLISHED;
+	wsi->lws_rx_parse_state = LWS_RXPS_NEW;
+
+	/* notify user code that we're ready to roll */
+
+	if (wsi->protocol->callback)
+		wsi->protocol->callback(wsi->protocol->owning_server,
+				wsi, LWS_CALLBACK_ESTABLISHED,
+					  wsi->user_space, NULL, 0);
+
+	return 0;
+
+
+bail:
+	/* free up his parsing allocations */
+	lws_free_header_table(wsi);
+	return -1;
+}
+
diff --git a/src/engine/external/libwebsockets/server.c b/src/engine/external/libwebsockets/server.c
new file mode 100644
index 00000000..ed5c47b2
--- /dev/null
+++ b/src/engine/external/libwebsockets/server.c
@@ -0,0 +1,1162 @@
+/*
+ * libwebsockets - small server side websockets and web server implementation
+ *
+ * Copyright (C) 2010-2013 Andy Green <andy@warmcat.com>
+ *
+ *  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:
+ *  version 2.1 of the License.
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston,
+ *  MA  02110-1301  USA
+ */
+
+
+#include "private-libwebsockets.h"
+
+int lws_context_init_server(struct lws_context_creation_info *info,
+			    struct libwebsocket_context *context)
+{
+	int n;
+	int sockfd;
+	struct sockaddr_in sin;
+	socklen_t len = sizeof(sin);
+	int opt = 1;
+	struct libwebsocket *wsi;
+#ifdef LWS_USE_IPV6
+	struct sockaddr_in6 serv_addr6;
+#endif
+	struct sockaddr_in serv_addr4;
+	struct sockaddr *v;
+
+	/* set up our external listening socket we serve on */
+
+	if (info->port == CONTEXT_PORT_NO_LISTEN)
+		return 0;
+
+#ifdef LWS_USE_IPV6
+	if (LWS_IPV6_ENABLED(context))
+		sockfd = socket(AF_INET6, SOCK_STREAM, 0);
+	else
+#endif
+		sockfd = socket(AF_INET, SOCK_STREAM, 0);
+
+	if (sockfd < 0) {
+		lwsl_err("ERROR opening socket\n");
+		return 1;
+	}
+
+	/*
+	 * allow us to restart even if old sockets in TIME_WAIT
+	 */
+	if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
+				      (const void *)&opt, sizeof(opt)) < 0) {
+		compatible_close(sockfd);
+		return 1;
+	}
+
+	lws_plat_set_socket_options(context, sockfd);
+
+#ifdef LWS_USE_IPV6
+	if (LWS_IPV6_ENABLED(context)) {
+		v = (struct sockaddr *)&serv_addr6;
+		n = sizeof(struct sockaddr_in6);
+		bzero((char *) &serv_addr6, sizeof(serv_addr6));
+		serv_addr6.sin6_addr = in6addr_any;
+		serv_addr6.sin6_family = AF_INET6;
+		serv_addr6.sin6_port = htons(info->port);
+	} else
+#endif
+	{
+		v = (struct sockaddr *)&serv_addr4;
+		n = sizeof(serv_addr4);
+		bzero((char *) &serv_addr4, sizeof(serv_addr4));
+		serv_addr4.sin_addr.s_addr = INADDR_ANY;
+		serv_addr4.sin_family = AF_INET;
+
+		if (info->iface) {
+			if (interface_to_sa(context, info->iface,
+				   (struct sockaddr_in *)v, n) < 0) {
+				lwsl_err("Unable to find interface %s\n",
+							info->iface);
+				compatible_close(sockfd);
+				return 1;
+			}
+		}
+
+		serv_addr4.sin_port = htons(info->port);
+	} /* ipv4 */
+
+	n = bind(sockfd, v, n);
+	if (n < 0) {
+		lwsl_err("ERROR on binding to port %d (%d %d)\n",
+					      info->port, n, LWS_ERRNO);
+		compatible_close(sockfd);
+		return 1;
+	}
+
+	if (getsockname(sockfd, (struct sockaddr *)&sin, &len) == -1)
+		lwsl_warn("getsockname: %s\n", strerror(LWS_ERRNO));
+	else
+		info->port = ntohs(sin.sin_port);
+
+	context->listen_port = info->port;
+
+	wsi = lws_zalloc(sizeof(struct libwebsocket));
+	if (wsi == NULL) {
+		lwsl_err("Out of mem\n");
+		compatible_close(sockfd);
+		return 1;
+	}
+	wsi->sock = sockfd;
+	wsi->mode = LWS_CONNMODE_SERVER_LISTENER;
+
+	insert_wsi_socket_into_fds(context, wsi);
+
+	context->listen_service_modulo = LWS_LISTEN_SERVICE_MODULO;
+	context->listen_service_count = 0;
+	context->listen_service_fd = sockfd;
+
+	listen(sockfd, LWS_SOMAXCONN);
+	lwsl_notice(" Listening on port %d\n", info->port);
+
+	return 0;
+}
+
+int
+_libwebsocket_rx_flow_control(struct libwebsocket *wsi)
+{
+	struct libwebsocket_context *context = wsi->protocol->owning_server;
+
+	/* there is no pending change */
+	if (!(wsi->rxflow_change_to & LWS_RXFLOW_PENDING_CHANGE))
+		return 0;
+
+	/* stuff is still buffered, not ready to really accept new input */
+	if (wsi->rxflow_buffer) {
+		/* get ourselves called back to deal with stashed buffer */
+		libwebsocket_callback_on_writable(context, wsi);
+		return 0;
+	}
+
+	/* pending is cleared, we can change rxflow state */
+
+	wsi->rxflow_change_to &= ~LWS_RXFLOW_PENDING_CHANGE;
+
+	lwsl_info("rxflow: wsi %p change_to %d\n", wsi,
+			      wsi->rxflow_change_to & LWS_RXFLOW_ALLOW);
+
+	/* adjust the pollfd for this wsi */
+
+	if (wsi->rxflow_change_to & LWS_RXFLOW_ALLOW) {
+		if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) {
+			lwsl_info("%s: fail\n", __func__);
+			return -1;
+		}
+	} else
+		if (lws_change_pollfd(wsi, LWS_POLLIN, 0))
+			return -1;
+
+	return 0;
+}
+
+int lws_http_action(struct libwebsocket_context *context,
+		    struct libwebsocket *wsi)
+{
+	char *uri_ptr = NULL;
+	int uri_len = 0;
+	enum http_version request_version;
+	enum http_connection_type connection_type;
+	int http_version_len;
+	char content_length_str[32];
+	char http_version_str[10];
+	char http_conn_str[20];
+	int n;
+
+	/* it's not websocket.... shall we accept it as http? */
+
+	if (!lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI) &&
+		!lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI) &&
+#ifdef LWS_USE_HTTP2
+		!lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COLON_PATH) &&
+#endif
+		!lws_hdr_total_length(wsi, WSI_TOKEN_OPTIONS_URI)) {
+		lwsl_warn("Missing URI in HTTP request\n");
+		goto bail_nuke_ah;
+	}
+
+	if (lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI) &&
+		lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI)) {
+		lwsl_warn("GET and POST methods?\n");
+		goto bail_nuke_ah;
+	}
+
+	if (libwebsocket_ensure_user_space(wsi))
+		goto bail_nuke_ah;
+
+#ifdef LWS_USE_HTTP2
+	if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COLON_PATH)) {
+		uri_ptr = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COLON_PATH);
+		uri_len = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COLON_PATH);
+		lwsl_info("HTTP2 request for '%s'\n", uri_ptr);
+		goto got_uri;
+	}
+#endif
+	if (lws_hdr_total_length(wsi, WSI_TOKEN_OPTIONS_URI)) {
+		uri_ptr = lws_hdr_simple_ptr(wsi, WSI_TOKEN_OPTIONS_URI);
+		uri_len = lws_hdr_total_length(wsi, WSI_TOKEN_OPTIONS_URI);
+		lwsl_info("HTTP OPTIONS request for '%s'\n", uri_ptr);
+		goto got_uri;
+	}
+	if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI)) {
+		uri_ptr = lws_hdr_simple_ptr(wsi, WSI_TOKEN_POST_URI);
+		uri_len = lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI);
+		lwsl_info("HTTP POST request for '%s'\n", uri_ptr);
+		goto got_uri;
+	}
+	if (lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI)) {
+		uri_ptr = lws_hdr_simple_ptr(wsi, WSI_TOKEN_GET_URI);
+		uri_len = lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI);
+		lwsl_info("HTTP GET request for '%s'\n", uri_ptr);
+	}
+
+got_uri:
+	/* HTTP header had a content length? */
+
+	wsi->u.http.content_length = 0;
+	if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI))
+		wsi->u.http.content_length = 100 * 1024 * 1024;
+
+	if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH)) {
+		lws_hdr_copy(wsi, content_length_str,
+				sizeof(content_length_str) - 1,
+						WSI_TOKEN_HTTP_CONTENT_LENGTH);
+		wsi->u.http.content_length = atoi(content_length_str);
+	}
+
+	/* http_version? Default to 1.0, override with token: */
+	request_version = HTTP_VERSION_1_0;
+
+	/* Works for single digit HTTP versions. : */
+	http_version_len = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP);
+	if (http_version_len > 7) {
+		lws_hdr_copy(wsi, http_version_str,
+				sizeof(http_version_str) - 1, WSI_TOKEN_HTTP);
+		if (http_version_str[5] == '1' && http_version_str[7] == '1')
+			request_version = HTTP_VERSION_1_1;
+	}
+	wsi->u.http.request_version = request_version;
+
+	/* HTTP/1.1 defaults to "keep-alive", 1.0 to "close" */
+	if (request_version == HTTP_VERSION_1_1)
+		connection_type = HTTP_CONNECTION_KEEP_ALIVE;
+	else
+		connection_type = HTTP_CONNECTION_CLOSE;
+
+	/* Override default if http "Connection:" header: */
+	if (lws_hdr_total_length(wsi, WSI_TOKEN_CONNECTION)) {
+		lws_hdr_copy(wsi, http_conn_str, sizeof(http_conn_str) - 1,
+			     WSI_TOKEN_CONNECTION);
+		http_conn_str[sizeof(http_conn_str) - 1] = '\0';
+		if (!strcasecmp(http_conn_str, "keep-alive"))
+			connection_type = HTTP_CONNECTION_KEEP_ALIVE;
+		else
+			if (strcasecmp(http_conn_str, "close"))
+				connection_type = HTTP_CONNECTION_CLOSE;
+	}
+	wsi->u.http.connection_type = connection_type;
+
+	n = 0;
+	if (wsi->protocol->callback)
+		n = wsi->protocol->callback(context, wsi,
+					LWS_CALLBACK_FILTER_HTTP_CONNECTION,
+					     wsi->user_space, uri_ptr, uri_len);
+
+	if (!n) {
+		/*
+		 * if there is content supposed to be coming,
+		 * put a timeout on it having arrived
+		 */
+		libwebsocket_set_timeout(wsi, PENDING_TIMEOUT_HTTP_CONTENT,
+							      AWAITING_TIMEOUT);
+
+		if (wsi->protocol->callback)
+			n = wsi->protocol->callback(context, wsi,
+			    LWS_CALLBACK_HTTP,
+			    wsi->user_space, uri_ptr, uri_len);
+	}
+
+	/* now drop the header info we kept a pointer to */
+	lws_free2(wsi->u.http.ah);
+
+	if (n) {
+		lwsl_info("LWS_CALLBACK_HTTP closing\n");
+		return 1; /* struct ah ptr already nuked */		}
+
+	/* 
+	 * If we're not issuing a file, check for content_length or
+	 * HTTP keep-alive. No keep-alive header allocation for
+	 * ISSUING_FILE, as this uses HTTP/1.0. 
+	 * 
+	 * In any case, return 0 and let libwebsocket_read decide how to
+	 * proceed based on state
+	 */
+	if (wsi->state != WSI_STATE_HTTP_ISSUING_FILE)
+		/* Prepare to read body if we have a content length: */
+		if (wsi->u.http.content_length > 0)
+			wsi->state = WSI_STATE_HTTP_BODY;
+
+	return 0;
+
+bail_nuke_ah:
+	/* drop the header info */
+	lws_free2(wsi->u.hdr.ah);
+
+	return 1;
+}
+
+
+int lws_handshake_server(struct libwebsocket_context *context,
+		struct libwebsocket *wsi, unsigned char **buf, size_t len)
+{
+	struct allocated_headers *ah;
+	int protocol_len;
+	char protocol_list[128];
+	char protocol_name[32];
+	char *p;
+	int n, hit;
+
+	/* LWS_CONNMODE_WS_SERVING */
+
+	while (len--) {
+		if (libwebsocket_parse(context, wsi, *(*buf)++)) {
+			lwsl_info("libwebsocket_parse failed\n");
+			goto bail_nuke_ah;
+		}
+
+		if (wsi->u.hdr.parser_state != WSI_PARSING_COMPLETE)
+			continue;
+
+		lwsl_parser("libwebsocket_parse sees parsing complete\n");
+
+		wsi->mode = LWS_CONNMODE_PRE_WS_SERVING_ACCEPT;
+		libwebsocket_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
+
+		/* is this websocket protocol or normal http 1.0? */
+
+		if (!lws_hdr_total_length(wsi, WSI_TOKEN_UPGRADE) ||
+			     !lws_hdr_total_length(wsi, WSI_TOKEN_CONNECTION)) {
+			
+			ah = wsi->u.hdr.ah;
+			
+			lws_union_transition(wsi, LWS_CONNMODE_HTTP_SERVING_ACCEPTED);
+			wsi->state = WSI_STATE_HTTP;
+			wsi->u.http.fd = LWS_INVALID_FILE;
+
+			/* expose it at the same offset as u.hdr */
+			wsi->u.http.ah = ah;
+			
+			n = lws_http_action(context, wsi);
+
+			return n;
+		}
+
+		if (!strcasecmp(lws_hdr_simple_ptr(wsi, WSI_TOKEN_UPGRADE),
+								"websocket"))
+			goto upgrade_ws;
+#ifdef LWS_USE_HTTP2
+		if (!strcasecmp(lws_hdr_simple_ptr(wsi, WSI_TOKEN_UPGRADE),
+								"h2c-14"))
+			goto upgrade_h2c;
+#endif
+		/* dunno what he wanted to upgrade to */
+		goto bail_nuke_ah;
+
+#ifdef LWS_USE_HTTP2
+upgrade_h2c:
+		if (!lws_hdr_total_length(wsi, WSI_TOKEN_HTTP2_SETTINGS)) {
+			lwsl_err("missing http2_settings\n");
+			goto bail_nuke_ah;
+		}
+
+		lwsl_err("h2c upgrade...\n");
+
+		p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP2_SETTINGS);
+		/* convert the peer's HTTP-Settings */
+		n = lws_b64_decode_string(p, protocol_list, sizeof(protocol_list));
+		if (n < 0) {
+			lwsl_parser("HTTP2_SETTINGS too long\n");
+			return 1;
+		}
+
+		/* adopt the header info */
+
+		ah = wsi->u.hdr.ah;
+
+		lws_union_transition(wsi, LWS_CONNMODE_HTTP2_SERVING);
+		
+		/* http2 union member has http union struct at start */
+		wsi->u.http.ah = ah;
+		
+		lws_http2_init(&wsi->u.http2.peer_settings);
+		lws_http2_init(&wsi->u.http2.my_settings);
+		
+		/* HTTP2 union */
+		
+		lws_http2_interpret_settings_payload(&wsi->u.http2.peer_settings, (unsigned char *)protocol_list, n);
+
+		strcpy(protocol_list,
+		       "HTTP/1.1 101 Switching Protocols\x0d\x0a"
+		      "Connection: Upgrade\x0d\x0a"
+		      "Upgrade: h2c\x0d\x0a\x0d\x0a");
+		n = lws_issue_raw(wsi, (unsigned char *)protocol_list,
+					strlen(protocol_list));
+		if (n != strlen(protocol_list)) {
+			lwsl_debug("http2 switch: ERROR writing to socket\n");
+			return 1;
+		}
+		
+		wsi->state = WSI_STATE_HTTP2_AWAIT_CLIENT_PREFACE;
+		
+		return 0;
+#endif
+
+upgrade_ws:
+		if (!wsi->protocol)
+			lwsl_err("NULL protocol at libwebsocket_read\n");
+
+		/*
+		 * It's websocket
+		 *
+		 * Select the first protocol we support from the list
+		 * the client sent us.
+		 *
+		 * Copy it to remove header fragmentation
+		 */
+
+		if (lws_hdr_copy(wsi, protocol_list, sizeof(protocol_list) - 1,
+				 WSI_TOKEN_PROTOCOL) < 0) {
+			lwsl_err("protocol list too long");
+			goto bail_nuke_ah;
+		}
+
+		protocol_len = lws_hdr_total_length(wsi, WSI_TOKEN_PROTOCOL);
+		protocol_list[protocol_len] = '\0';
+		p = protocol_list;
+		hit = 0;
+
+		while (*p && !hit) {
+			n = 0;
+			while (n < sizeof(protocol_name) - 1 && *p && *p !=',')
+				protocol_name[n++] = *p++;
+			protocol_name[n] = '\0';
+			if (*p)
+				p++;
+
+			lwsl_info("checking %s\n", protocol_name);
+
+			n = 0;
+			while (wsi->protocol && context->protocols[n].callback) {
+				if (!wsi->protocol->name) {
+					n++;
+					continue;
+				}
+				if (!strcmp(context->protocols[n].name,
+					    protocol_name)) {
+					lwsl_info("prot match %d\n", n);
+					wsi->protocol = &context->protocols[n];
+					hit = 1;
+					break;
+				}
+
+				n++;
+			}
+		}
+
+		/* we didn't find a protocol he wanted? */
+
+		if (!hit) {
+			if (lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL) ==
+									 NULL) {
+				/*
+				 * some clients only have one protocol and
+				 * do not sent the protocol list header...
+				 * allow it and match to protocol 0
+				 */
+				lwsl_info("defaulting to prot 0 handler\n");
+				wsi->protocol = &context->protocols[0];
+			} else {
+				lwsl_err("No protocol from list \"%s\" supported\n",
+					 protocol_list);
+				goto bail_nuke_ah;
+			}
+		}
+
+		/* allocate wsi->user storage */
+		if (libwebsocket_ensure_user_space(wsi))
+			goto bail_nuke_ah;
+
+		/*
+		 * Give the user code a chance to study the request and
+		 * have the opportunity to deny it
+		 */
+
+		if ((wsi->protocol->callback)(wsi->protocol->owning_server, wsi,
+				LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION,
+				wsi->user_space,
+			      lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL), 0)) {
+			lwsl_warn("User code denied connection\n");
+			goto bail_nuke_ah;
+		}
+
+
+		/*
+		 * Perform the handshake according to the protocol version the
+		 * client announced
+		 */
+
+		switch (wsi->ietf_spec_revision) {
+		case 13:
+			lwsl_parser("lws_parse calling handshake_04\n");
+			if (handshake_0405(context, wsi)) {
+				lwsl_info("hs0405 has failed the connection\n");
+				goto bail_nuke_ah;
+			}
+			break;
+
+		default:
+			lwsl_warn("Unknown client spec version %d\n",
+						       wsi->ietf_spec_revision);
+			goto bail_nuke_ah;
+		}
+
+		/* drop the header info -- no bail_nuke_ah after this */
+		lws_free_header_table(wsi);
+
+		lws_union_transition(wsi, LWS_CONNMODE_WS_SERVING);
+
+		/*
+		 * create the frame buffer for this connection according to the
+		 * size mentioned in the protocol definition.  If 0 there, use
+		 * a big default for compatibility
+		 */
+
+		n = wsi->protocol->rx_buffer_size;
+		if (!n)
+			n = LWS_MAX_SOCKET_IO_BUF;
+		n += LWS_SEND_BUFFER_PRE_PADDING + LWS_SEND_BUFFER_POST_PADDING;
+		wsi->u.ws.rx_user_buffer = lws_malloc(n);
+		if (!wsi->u.ws.rx_user_buffer) {
+			lwsl_err("Out of Mem allocating rx buffer %d\n", n);
+			return 1;
+		}
+		lwsl_info("Allocating RX buffer %d\n", n);
+
+		if (setsockopt(wsi->sock, SOL_SOCKET, SO_SNDBUF, (const char *)&n, sizeof n)) {
+			lwsl_warn("Failed to set SNDBUF to %d", n);
+			return 1;
+		}
+
+		lwsl_parser("accepted v%02d connection\n",
+						       wsi->ietf_spec_revision);
+	} /* while all chars are handled */
+
+	return 0;
+
+bail_nuke_ah:
+	/* drop the header info */
+	lws_free_header_table(wsi);
+	return 1;
+}
+
+struct libwebsocket *
+libwebsocket_create_new_server_wsi(struct libwebsocket_context *context)
+{
+	struct libwebsocket *new_wsi;
+
+	new_wsi = lws_zalloc(sizeof(struct libwebsocket));
+	if (new_wsi == NULL) {
+		lwsl_err("Out of memory for new connection\n");
+		return NULL;
+	}
+
+	new_wsi->pending_timeout = NO_PENDING_TIMEOUT;
+	new_wsi->rxflow_change_to = LWS_RXFLOW_ALLOW;
+
+	/* intialize the instance struct */
+
+	new_wsi->state = WSI_STATE_HTTP;
+	new_wsi->mode = LWS_CONNMODE_HTTP_SERVING;
+	new_wsi->hdr_parsing_completed = 0;
+
+	if (lws_allocate_header_table(new_wsi)) {
+		lws_free(new_wsi);
+		return NULL;
+	}
+
+	/*
+	 * these can only be set once the protocol is known
+	 * we set an unestablished connection's protocol pointer
+	 * to the start of the supported list, so it can look
+	 * for matching ones during the handshake
+	 */
+	new_wsi->protocol = context->protocols;
+	new_wsi->user_space = NULL;
+	new_wsi->ietf_spec_revision = 0;
+
+	/*
+	 * outermost create notification for wsi
+	 * no user_space because no protocol selection
+	 */
+	context->protocols[0].callback(context, new_wsi,
+			LWS_CALLBACK_WSI_CREATE, NULL, NULL, 0);
+
+	return new_wsi;
+}
+
+/**
+ * lws_http_transaction_completed() - wait for new http transaction or close
+ * @wsi:	websocket connection
+ *
+ *	Returns 1 if the HTTP connection must close now
+ *	Returns 0 and resets connection to wait for new HTTP header /
+ *	  transaction if possible
+ */
+
+LWS_VISIBLE
+int lws_http_transaction_completed(struct libwebsocket *wsi)
+{
+	/* if we can't go back to accept new headers, drop the connection */
+	if (wsi->u.http.connection_type != HTTP_CONNECTION_KEEP_ALIVE) {
+		lwsl_info("%s: close connection\n", __func__);
+		return 1;
+	}
+
+	/* otherwise set ourselves up ready to go again */
+	wsi->state = WSI_STATE_HTTP;
+	
+	lwsl_info("%s: await new transaction\n", __func__);
+	
+	return 0;
+}
+
+int lws_server_socket_service(struct libwebsocket_context *context,
+			struct libwebsocket *wsi, struct libwebsocket_pollfd *pollfd)
+{
+	struct libwebsocket *new_wsi = NULL;
+	int accept_fd = 0;
+	socklen_t clilen;
+	struct sockaddr_in cli_addr;
+	int n;
+	int len;
+
+	switch (wsi->mode) {
+
+	case LWS_CONNMODE_HTTP_SERVING:
+	case LWS_CONNMODE_HTTP_SERVING_ACCEPTED:
+	case LWS_CONNMODE_HTTP2_SERVING:
+
+		/* handle http headers coming in */
+
+		/* pending truncated sends have uber priority */
+
+		if (wsi->truncated_send_len) {
+			if (pollfd->revents & LWS_POLLOUT)
+				if (lws_issue_raw(wsi, wsi->truncated_send_malloc +
+					wsi->truncated_send_offset,
+							wsi->truncated_send_len) < 0) {
+					lwsl_info("closing from socket service\n");
+					return -1;
+				}
+			/*
+			 * we can't afford to allow input processing send
+			 * something new, so spin around he event loop until
+			 * he doesn't have any partials
+			 */
+			break;
+		}
+
+		/* any incoming data ready? */
+
+		if (pollfd->revents & LWS_POLLIN) {
+			len = lws_ssl_capable_read(context, wsi,
+					context->service_buffer,
+						       sizeof(context->service_buffer));
+			switch (len) {
+			case 0:
+				lwsl_info("lws_server_skt_srv: read 0 len\n");
+				/* lwsl_info("   state=%d\n", wsi->state); */
+				if (!wsi->hdr_parsing_completed)
+					lws_free_header_table(wsi);
+				/* fallthru */
+			case LWS_SSL_CAPABLE_ERROR:
+				libwebsocket_close_and_free_session(
+						context, wsi,
+						LWS_CLOSE_STATUS_NOSTATUS);
+				return 0;
+			case LWS_SSL_CAPABLE_MORE_SERVICE:
+				goto try_pollout;
+			}
+
+			/* just ignore incoming if waiting for close */
+			if (wsi->state != WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE) {
+			
+				/* hm this may want to send (via HTTP callback for example) */
+				n = libwebsocket_read(context, wsi,
+							context->service_buffer, len);
+				if (n < 0)
+					/* we closed wsi */
+					return 0;
+
+				/* hum he may have used up the writability above */
+				break;
+			}
+		}
+
+try_pollout:
+		/* this handles POLLOUT for http serving fragments */
+
+		if (!(pollfd->revents & LWS_POLLOUT))
+			break;
+
+		/* one shot */
+		if (lws_change_pollfd(wsi, LWS_POLLOUT, 0))
+			goto fail;
+		
+		lws_libev_io(context, wsi, LWS_EV_STOP | LWS_EV_WRITE);
+
+		if (wsi->state != WSI_STATE_HTTP_ISSUING_FILE) {
+			n = user_callback_handle_rxflow(
+					wsi->protocol->callback,
+					wsi->protocol->owning_server,
+					wsi, LWS_CALLBACK_HTTP_WRITEABLE,
+					wsi->user_space,
+					NULL,
+					0);
+			if (n < 0)
+				goto fail;
+			break;
+		}
+
+		/* >0 == completion, <0 == error */
+		n = libwebsockets_serve_http_file_fragment(context, wsi);
+		if (n < 0 || (n > 0 && lws_http_transaction_completed(wsi)))
+			goto fail;
+		break;
+
+	case LWS_CONNMODE_SERVER_LISTENER:
+
+		/* pollin means a client has connected to us then */
+
+		if (!(pollfd->revents & LWS_POLLIN))
+			break;
+
+		/* listen socket got an unencrypted connection... */
+
+		clilen = sizeof(cli_addr);
+		lws_latency_pre(context, wsi);
+		accept_fd  = accept(pollfd->fd, (struct sockaddr *)&cli_addr,
+								       &clilen);
+		lws_latency(context, wsi,
+			"unencrypted accept LWS_CONNMODE_SERVER_LISTENER",
+						     accept_fd, accept_fd >= 0);
+		if (accept_fd < 0) {
+			if (LWS_ERRNO == LWS_EAGAIN || LWS_ERRNO == LWS_EWOULDBLOCK) {
+				lwsl_debug("accept asks to try again\n");
+				break;
+			}
+			lwsl_warn("ERROR on accept: %s\n", strerror(LWS_ERRNO));
+			break;
+		}
+
+		lws_plat_set_socket_options(context, accept_fd);
+
+		/*
+		 * look at who we connected to and give user code a chance
+		 * to reject based on client IP.  There's no protocol selected
+		 * yet so we issue this to protocols[0]
+		 */
+
+		if ((context->protocols[0].callback)(context, wsi,
+				LWS_CALLBACK_FILTER_NETWORK_CONNECTION,
+					   NULL, (void *)(long)accept_fd, 0)) {
+			lwsl_debug("Callback denied network connection\n");
+			compatible_close(accept_fd);
+			break;
+		}
+
+		new_wsi = libwebsocket_create_new_server_wsi(context);
+		if (new_wsi == NULL) {
+			compatible_close(accept_fd);
+			break;
+		}
+
+		new_wsi->sock = accept_fd;
+
+		/* the transport is accepted... give him time to negotiate */
+		libwebsocket_set_timeout(new_wsi,
+			PENDING_TIMEOUT_ESTABLISH_WITH_SERVER,
+							AWAITING_TIMEOUT);
+
+		/*
+		 * A new connection was accepted. Give the user a chance to
+		 * set properties of the newly created wsi. There's no protocol
+		 * selected yet so we issue this to protocols[0]
+		 */
+
+		(context->protocols[0].callback)(context, new_wsi,
+			LWS_CALLBACK_SERVER_NEW_CLIENT_INSTANTIATED, NULL, NULL, 0);
+
+		lws_libev_accept(context, new_wsi, accept_fd);
+
+		if (!LWS_SSL_ENABLED(context)) {
+			lwsl_debug("accepted new conn  port %u on fd=%d\n",
+					  ntohs(cli_addr.sin_port), accept_fd);
+
+			insert_wsi_socket_into_fds(context, new_wsi);
+		}
+		break;
+
+	default:
+		break;
+	}
+
+	if (lws_server_socket_service_ssl(context, &wsi, new_wsi,
+							  accept_fd, pollfd))
+		goto fail;
+
+	return 0;
+	
+fail:
+	libwebsocket_close_and_free_session(context, wsi,
+						 LWS_CLOSE_STATUS_NOSTATUS);
+	return 1;
+}
+
+#include "lextable-strings.h"
+
+const unsigned char *lws_token_to_string(enum lws_token_indexes token)
+{
+	if ((unsigned int)token >= ARRAY_SIZE(set))
+		return NULL;
+	
+	return (unsigned char *)set[token];
+}
+
+int lws_add_http_header_by_name(struct libwebsocket_context *context,
+			    struct libwebsocket *wsi,
+			    const unsigned char *name,
+			    const unsigned char *value,
+			    int length,
+			    unsigned char **p,
+			    unsigned char *end)
+{
+#ifdef LWS_USE_HTTP2
+	if (wsi->mode == LWS_CONNMODE_HTTP2_SERVING)
+		return lws_add_http2_header_by_name(context, wsi, name, value, length, p, end);
+#endif
+	if (name) {
+		while (*p < end && *name)
+			*((*p)++) = *name++;
+	
+		if (*p == end)
+			return 1;
+	
+		*((*p)++) = ' ';
+	}
+	if (*p + length + 3 >= end)
+		return 1;
+
+	memcpy(*p, value, length);
+	*p += length;
+	
+	*((*p)++) = '\x0d';
+	*((*p)++) = '\x0a';
+		
+	return 0;
+}
+
+int lws_finalize_http_header(struct libwebsocket_context *context,
+			    struct libwebsocket *wsi,
+			    unsigned char **p,
+			    unsigned char *end)
+{
+#ifdef LWS_USE_HTTP2
+	if (wsi->mode == LWS_CONNMODE_HTTP2_SERVING)
+		return 0;
+#endif
+	
+	if ((long)(end - *p) < 3)
+		return 1;
+	
+	*((*p)++) = '\x0d';
+	*((*p)++) = '\x0a';
+		
+	return 0;
+}
+
+int lws_add_http_header_by_token(struct libwebsocket_context *context,
+			    struct libwebsocket *wsi,
+			    enum lws_token_indexes token,
+			    const unsigned char *value,
+			    int length,
+			    unsigned char **p,
+			    unsigned char *end)
+{
+	const unsigned char *name;
+#ifdef LWS_USE_HTTP2
+	if (wsi->mode == LWS_CONNMODE_HTTP2_SERVING)
+		return lws_add_http2_header_by_token(context, wsi, token, value, length, p, end);
+#endif
+	name = lws_token_to_string(token);
+	if (!name)
+		return 1;
+	
+	return lws_add_http_header_by_name(context, wsi, name, value, length, p, end);
+}
+
+int lws_add_http_header_content_length(struct libwebsocket_context *context,
+			    struct libwebsocket *wsi,
+			    unsigned long content_length,
+			    unsigned char **p,
+			    unsigned char *end)
+{
+	char b[24];
+	int n;
+
+	n = sprintf(b, "%lu", content_length);
+	if (lws_add_http_header_by_token(context, wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH, (unsigned char *)b, n, p, end))
+		return 1;
+	wsi->u.http.content_length = content_length;
+	wsi->u.http.content_remain = content_length;
+
+	return 0;
+}
+
+static const char *err400[] = {
+	"Bad Request",
+	"Unauthorized",
+	"Payment Required",
+	"Forbidden",
+	"Not Found",
+	"Method Not Allowed",
+	"Not Acceptable",
+	"Proxy Auth Required",
+	"Request Timeout",
+	"Conflict",
+	"Gone",
+	"Length Required",
+	"Precondition Failed",
+	"Request Entity Too Large",
+	"Request URI too Long",
+	"Unsupported Media Type",
+	"Requested Range Not Satisfiable",
+	"Expectation Failed"
+};
+
+static const char *err500[] = {
+	"Internal Server Error",
+	"Not Implemented",
+	"Bad Gateway",
+	"Service Unavailable",
+	"Gateway Timeout",
+	"HTTP Version Not Supported"
+};
+
+int lws_add_http_header_status(struct libwebsocket_context *context,
+			    struct libwebsocket *wsi,
+			    unsigned int code,
+			    unsigned char **p,
+			    unsigned char *end)
+{
+	unsigned char code_and_desc[60];
+	const char *description = "";
+	int n;
+
+#ifdef LWS_USE_HTTP2
+	if (wsi->mode == LWS_CONNMODE_HTTP2_SERVING)
+		return lws_add_http2_header_status(context, wsi, code, p, end);
+#endif
+	if (code >= 400 && code < (400 + ARRAY_SIZE(err400)))
+		description = err400[code - 400];
+	if (code >= 500 && code < (500 + ARRAY_SIZE(err500)))
+		description = err500[code - 500];
+
+	n = sprintf((char *)code_and_desc, "HTTP/1.0 %u %s", code, description);
+	
+	return lws_add_http_header_by_name(context, wsi, NULL, code_and_desc, n, p, end);
+}
+
+/**
+ * libwebsockets_return_http_status() - Return simple http status
+ * @context:		libwebsockets context
+ * @wsi:		Websocket instance (available from user callback)
+ * @code:		Status index, eg, 404
+ * @html_body:		User-readable HTML description < 1KB, or NULL
+ *
+ *	Helper to report HTTP errors back to the client cleanly and
+ *	consistently
+ */
+LWS_VISIBLE int libwebsockets_return_http_status(
+		struct libwebsocket_context *context, struct libwebsocket *wsi,
+				       unsigned int code, const char *html_body)
+{
+	int n, m;
+
+	unsigned char *p = context->service_buffer + LWS_SEND_BUFFER_PRE_PADDING;
+	unsigned char *start = p;
+	unsigned char *end = p + sizeof(context->service_buffer) -
+					LWS_SEND_BUFFER_PRE_PADDING;
+
+	if (!html_body)
+		html_body = "";
+
+	if (lws_add_http_header_status(context, wsi, code, &p, end))
+		return 1;
+	if (lws_add_http_header_by_token(context, wsi, WSI_TOKEN_HTTP_SERVER, (unsigned char *)"libwebsockets", 13, &p, end))
+		return 1;
+	if (lws_add_http_header_by_token(context, wsi, WSI_TOKEN_HTTP_CONTENT_TYPE, (unsigned char *)"text/html", 9, &p, end))
+		return 1;
+	if (lws_finalize_http_header(context, wsi, &p, end))
+		return 1;
+
+	m = libwebsocket_write(wsi, start, p - start, LWS_WRITE_HTTP_HEADERS);
+	if (m != (int)(p - start))
+		return 1;
+
+	n = sprintf((char *)start, "<html><body><h1>%u</h1>%s</body></html>", code, html_body);
+	m = libwebsocket_write(wsi, start, n, LWS_WRITE_HTTP);
+
+	return m != n;
+}
+
+/**
+ * libwebsockets_serve_http_file() - Send a file back to the client using http
+ * @context:		libwebsockets context
+ * @wsi:		Websocket instance (available from user callback)
+ * @file:		The file to issue over http
+ * @content_type:	The http content type, eg, text/html
+ * @other_headers:	NULL or pointer to \0-terminated other header string
+ *
+ *	This function is intended to be called from the callback in response
+ *	to http requests from the client.  It allows the callback to issue
+ *	local files down the http link in a single step.
+ *
+ *	Returning <0 indicates error and the wsi should be closed.  Returning
+ *	>0 indicates the file was completely sent and
+ *	lws_http_transaction_completed() called on the wsi (and close if != 0)
+ *	==0 indicates the file transfer is started and needs more service later,
+ *	the wsi should be left alone.
+ */
+
+LWS_VISIBLE int libwebsockets_serve_http_file(
+		struct libwebsocket_context *context,
+			struct libwebsocket *wsi, const char *file,
+			   const char *content_type, const char *other_headers,
+			   int other_headers_len)
+{
+	unsigned char *response = context->service_buffer + LWS_SEND_BUFFER_PRE_PADDING;
+	unsigned char *p = response;
+	unsigned char *end = p + sizeof(context->service_buffer) -
+					LWS_SEND_BUFFER_PRE_PADDING;
+	int ret = 0;
+
+	wsi->u.http.fd = lws_plat_open_file(file, &wsi->u.http.filelen);
+
+	if (wsi->u.http.fd == LWS_INVALID_FILE) {
+		lwsl_err("Unable to open '%s'\n", file);
+		libwebsockets_return_http_status(context, wsi,
+						HTTP_STATUS_NOT_FOUND, NULL);
+		return -1;
+	}
+
+	if (lws_add_http_header_status(context, wsi, 200, &p, end))
+		return -1;
+	if (lws_add_http_header_by_token(context, wsi, WSI_TOKEN_HTTP_SERVER, (unsigned char *)"libwebsockets", 13, &p, end))
+		return -1;
+	if (lws_add_http_header_by_token(context, wsi, WSI_TOKEN_HTTP_CONTENT_TYPE, (unsigned char *)content_type, strlen(content_type), &p, end))
+		return -1;
+	if (lws_add_http_header_content_length(context, wsi, wsi->u.http.filelen, &p, end))
+		return -1;
+
+	if (other_headers) {
+		if ((end - p) < other_headers_len)
+			return -1;
+		memcpy(p, other_headers, other_headers_len);
+		p += other_headers_len;
+	}
+
+	if (lws_finalize_http_header(context, wsi, &p, end))
+		return -1;
+	
+	ret = libwebsocket_write(wsi, response,
+				   p - response, LWS_WRITE_HTTP_HEADERS);
+	if (ret != (p - response)) {
+		lwsl_err("_write returned %d from %d\n", ret, (p - response));
+		return -1;
+	}
+
+	wsi->u.http.filepos = 0;
+	wsi->state = WSI_STATE_HTTP_ISSUING_FILE;
+
+	return libwebsockets_serve_http_file_fragment(context, wsi);
+}
+
+
+int libwebsocket_interpret_incoming_packet(struct libwebsocket *wsi,
+						 unsigned char *buf, size_t len)
+{
+	size_t n = 0;
+	int m;
+
+#if 0
+	lwsl_parser("received %d byte packet\n", (int)len);
+	lwsl_hexdump(buf, len);
+#endif
+
+	/* let the rx protocol state machine have as much as it needs */
+
+	while (n < len) {
+		/*
+		 * we were accepting input but now we stopped doing so
+		 */
+		if (!(wsi->rxflow_change_to & LWS_RXFLOW_ALLOW)) {
+			lws_rxflow_cache(wsi, buf, n, len);
+
+			return 1;
+		}
+
+		/* account for what we're using in rxflow buffer */
+		if (wsi->rxflow_buffer)
+			wsi->rxflow_pos++;
+
+		/* process the byte */
+		m = libwebsocket_rx_sm(wsi, buf[n++]);
+		if (m < 0)
+			return -1;
+	}
+
+	return 0;
+}
+
+LWS_VISIBLE void
+lws_server_get_canonical_hostname(struct libwebsocket_context *context,
+				struct lws_context_creation_info *info)
+{
+	if (info->options & LWS_SERVER_OPTION_SKIP_SERVER_CANONICAL_NAME)
+		return;
+
+	/* find canonical hostname */
+	gethostname((char *)context->canonical_hostname,
+				       sizeof(context->canonical_hostname) - 1);
+
+	lwsl_notice(" canonical_hostname = %s\n", context->canonical_hostname);
+}
diff --git a/src/engine/external/libwebsockets/service.c b/src/engine/external/libwebsockets/service.c
new file mode 100644
index 00000000..f905a605
--- /dev/null
+++ b/src/engine/external/libwebsockets/service.c
@@ -0,0 +1,636 @@
+/*
+ * libwebsockets - small server side websockets and web server implementation
+ *
+ * Copyright (C) 2010-2014 Andy Green <andy@warmcat.com>
+ *
+ *  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:
+ *  version 2.1 of the License.
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston,
+ *  MA  02110-1301  USA
+ */
+
+#include "private-libwebsockets.h"
+
+static int
+lws_calllback_as_writeable(struct libwebsocket_context *context,
+		   struct libwebsocket *wsi)
+{
+	int n;
+
+	switch (wsi->mode) {
+	case LWS_CONNMODE_WS_CLIENT:
+		n = LWS_CALLBACK_CLIENT_WRITEABLE;
+		break;
+	case LWS_CONNMODE_WS_SERVING:
+		n = LWS_CALLBACK_SERVER_WRITEABLE;
+		break;
+	default:
+		n = LWS_CALLBACK_HTTP_WRITEABLE;
+		break;
+	}
+	lwsl_info("%s: %p (user=%p)\n", __func__, wsi, wsi->user_space);
+	return user_callback_handle_rxflow(wsi->protocol->callback, context,
+			wsi, (enum libwebsocket_callback_reasons) n,
+						      wsi->user_space, NULL, 0);
+}
+
+int
+lws_handle_POLLOUT_event(struct libwebsocket_context *context,
+		   struct libwebsocket *wsi, struct libwebsocket_pollfd *pollfd)
+{
+	int n;
+	struct lws_tokens eff_buf;
+#ifdef LWS_USE_HTTP2
+	struct libwebsocket *wsi2;
+#endif
+	int ret;
+	int m;
+
+	/* pending truncated sends have uber priority */
+
+	if (wsi->truncated_send_len) {
+		if (lws_issue_raw(wsi, wsi->truncated_send_malloc +
+				wsi->truncated_send_offset,
+						wsi->truncated_send_len) < 0) {
+			lwsl_info("lws_handle_POLLOUT_event signalling to close\n");
+			return -1;
+		}
+		/* leave POLLOUT active either way */
+		return 0;
+	} else
+		if (wsi->state == WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE) {
+			lwsl_info("***** %x signalling to close in POLLOUT handler\n", wsi);
+			return -1; /* retry closing now */
+		}
+#ifdef LWS_USE_HTTP2
+	/* protocol packets are next */
+	if (wsi->pps) {
+		lwsl_info("servicing pps %d\n", wsi->pps);
+		switch (wsi->pps) {
+		case LWS_PPS_HTTP2_MY_SETTINGS:
+		case LWS_PPS_HTTP2_ACK_SETTINGS:
+			lws_http2_do_pps_send(context, wsi);
+			break;
+		default:
+			break;
+		}
+		wsi->pps = LWS_PPS_NONE;
+		libwebsocket_rx_flow_control(wsi, 1);
+		
+		return 0; /* leave POLLOUT active */
+	}
+#endif
+	/* pending control packets have next priority */
+	
+	if (wsi->state == WSI_STATE_ESTABLISHED && wsi->u.ws.ping_payload_len) {
+		n = libwebsocket_write(wsi, 
+				&wsi->u.ws.ping_payload_buf[
+					LWS_SEND_BUFFER_PRE_PADDING],
+					wsi->u.ws.ping_payload_len,
+							       LWS_WRITE_PONG);
+		if (n < 0)
+			return -1;
+		/* well he is sent, mark him done */
+		wsi->u.ws.ping_payload_len = 0;
+		/* leave POLLOUT active either way */
+		return 0;
+	}
+
+	/* if nothing critical, user can get the callback */
+	
+	m = lws_ext_callback_for_each_active(wsi, LWS_EXT_CALLBACK_IS_WRITEABLE,
+								       NULL, 0);
+#ifndef LWS_NO_EXTENSIONS
+	if (!wsi->extension_data_pending)
+		goto user_service;
+#endif
+	/*
+	 * check in on the active extensions, see if they
+	 * had pending stuff to spill... they need to get the
+	 * first look-in otherwise sequence will be disordered
+	 *
+	 * NULL, zero-length eff_buf means just spill pending
+	 */
+
+	ret = 1;
+	while (ret == 1) {
+
+		/* default to nobody has more to spill */
+
+		ret = 0;
+		eff_buf.token = NULL;
+		eff_buf.token_len = 0;
+
+		/* give every extension a chance to spill */
+		
+		m = lws_ext_callback_for_each_active(wsi,
+					LWS_EXT_CALLBACK_PACKET_TX_PRESEND,
+							           &eff_buf, 0);
+		if (m < 0) {
+			lwsl_err("ext reports fatal error\n");
+			return -1;
+		}
+		if (m)
+			/*
+			 * at least one extension told us he has more
+			 * to spill, so we will go around again after
+			 */
+			ret = 1;
+
+		/* assuming they gave us something to send, send it */
+
+		if (eff_buf.token_len) {
+			n = lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
+							     eff_buf.token_len);
+			if (n < 0) {
+				lwsl_info("closing from POLLOUT spill\n");
+				return -1;
+			}
+			/*
+			 * Keep amount spilled small to minimize chance of this
+			 */
+			if (n != eff_buf.token_len) {
+				lwsl_err("Unable to spill ext %d vs %s\n",
+							  eff_buf.token_len, n);
+				return -1;
+			}
+		} else
+			continue;
+
+		/* no extension has more to spill */
+
+		if (!ret)
+			continue;
+
+		/*
+		 * There's more to spill from an extension, but we just sent
+		 * something... did that leave the pipe choked?
+		 */
+
+		if (!lws_send_pipe_choked(wsi))
+			/* no we could add more */
+			continue;
+
+		lwsl_info("choked in POLLOUT service\n");
+
+		/*
+		 * Yes, he's choked.  Leave the POLLOUT masked on so we will
+		 * come back here when he is unchoked.  Don't call the user
+		 * callback to enforce ordering of spilling, he'll get called
+		 * when we come back here and there's nothing more to spill.
+		 */
+
+		return 0;
+	}
+#ifndef LWS_NO_EXTENSIONS
+	wsi->extension_data_pending = 0;
+
+user_service:
+#endif
+	/* one shot */
+
+	if (pollfd) {
+		if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) {
+			lwsl_info("failled at set pollfd\n");
+			return 1;
+		}
+
+		lws_libev_io(context, wsi, LWS_EV_STOP | LWS_EV_WRITE);
+	}
+
+#ifdef LWS_USE_HTTP2
+	/* 
+	 * we are the 'network wsi' for potentially many muxed child wsi with
+	 * no network connection of their own, who have to use us for all their
+	 * network actions.  So we use a round-robin scheme to share out the
+	 * POLLOUT notifications to our children.
+	 * 
+	 * But because any child could exhaust the socket's ability to take
+	 * writes, we can only let one child get notified each time.
+	 * 
+	 * In addition children may be closed / deleted / added between POLLOUT
+	 * notifications, so we can't hold pointers
+	 */
+	
+	if (wsi->mode != LWS_CONNMODE_HTTP2_SERVING) {
+		lwsl_info("%s: non http2\n", __func__);
+		goto notify;
+	}
+
+	wsi->u.http2.requested_POLLOUT = 0;
+	if (!wsi->u.http2.initialized) {
+		lwsl_info("pollout on uninitialized http2 conn\n");
+		return 0;
+	}
+	
+	lwsl_info("%s: doing children\n", __func__);
+
+	wsi2 = wsi;
+	do {
+		wsi2 = wsi2->u.http2.next_child_wsi;
+		lwsl_info("%s: child %p\n", __func__, wsi2);
+		if (!wsi2)
+			continue;
+		if (!wsi2->u.http2.requested_POLLOUT)
+			continue;
+		wsi2->u.http2.requested_POLLOUT = 0;
+		if (lws_calllback_as_writeable(context, wsi2)) {
+			lwsl_debug("Closing POLLOUT child\n");
+			libwebsocket_close_and_free_session(context, wsi2,
+						LWS_CLOSE_STATUS_NOSTATUS);
+		}
+		wsi2 = wsi;
+	} while (wsi2 != NULL && !lws_send_pipe_choked(wsi));
+	
+	lwsl_info("%s: completed\n", __func__);
+	
+	return 0;
+notify:
+#endif
+	return lws_calllback_as_writeable(context, wsi);
+}
+
+
+
+int
+libwebsocket_service_timeout_check(struct libwebsocket_context *context,
+				     struct libwebsocket *wsi, unsigned int sec)
+{
+	/*
+	 * if extensions want in on it (eg, we are a mux parent)
+	 * give them a chance to service child timeouts
+	 */
+	if (lws_ext_callback_for_each_active(wsi, LWS_EXT_CALLBACK_1HZ, NULL, sec) < 0)
+		return 0;
+
+	if (!wsi->pending_timeout)
+		return 0;
+
+	/*
+	 * if we went beyond the allowed time, kill the
+	 * connection
+	 */
+	if (sec > wsi->pending_timeout_limit) {
+		lwsl_info("TIMEDOUT WAITING on %d\n", wsi->pending_timeout);
+		libwebsocket_close_and_free_session(context,
+						wsi, LWS_CLOSE_STATUS_NOSTATUS);
+		return 1;
+	}
+
+	return 0;
+}
+
+int lws_rxflow_cache(struct libwebsocket *wsi, unsigned char *buf, int n, int len)
+{
+	/* his RX is flowcontrolled, don't send remaining now */
+	if (wsi->rxflow_buffer) {
+		/* rxflow while we were spilling prev rxflow */
+		lwsl_info("stalling in existing rxflow buf\n");
+		return 1;
+	}
+
+	/* a new rxflow, buffer it and warn caller */
+	lwsl_info("new rxflow input buffer len %d\n", len - n);
+	wsi->rxflow_buffer = lws_malloc(len - n);
+	wsi->rxflow_len = len - n;
+	wsi->rxflow_pos = 0;
+	memcpy(wsi->rxflow_buffer, buf + n, len - n);
+
+	return 0;
+}
+
+/**
+ * libwebsocket_service_fd() - Service polled socket with something waiting
+ * @context:	Websocket context
+ * @pollfd:	The pollfd entry describing the socket fd and which events
+ *		happened.
+ *
+ *	This function takes a pollfd that has POLLIN or POLLOUT activity and
+ *	services it according to the state of the associated
+ *	struct libwebsocket.
+ *
+ *	The one call deals with all "service" that might happen on a socket
+ *	including listen accepts, http files as well as websocket protocol.
+ *
+ *	If a pollfd says it has something, you can just pass it to
+ *	libwebsocket_serice_fd() whether it is a socket handled by lws or not.
+ *	If it sees it is a lws socket, the traffic will be handled and
+ *	pollfd->revents will be zeroed now.
+ *
+ *	If the socket is foreign to lws, it leaves revents alone.  So you can
+ *	see if you should service yourself by checking the pollfd revents
+ *	after letting lws try to service it.
+ */
+
+LWS_VISIBLE int
+libwebsocket_service_fd(struct libwebsocket_context *context,
+							  struct libwebsocket_pollfd *pollfd)
+{
+	struct libwebsocket *wsi;
+	int n;
+	int m;
+	int listen_socket_fds_index = 0;
+	time_t now;
+	int timed_out = 0;
+	int our_fd = 0;
+	char draining_flow = 0;
+	int more;
+	struct lws_tokens eff_buf;
+
+	if (context->listen_service_fd)
+		listen_socket_fds_index = context->lws_lookup[
+			     context->listen_service_fd]->position_in_fds_table;
+
+	/*
+	 * you can call us with pollfd = NULL to just allow the once-per-second
+	 * global timeout checks; if less than a second since the last check
+	 * it returns immediately then.
+	 */
+
+	time(&now);
+
+	/* TODO: if using libev, we should probably use timeout watchers... */
+	if (context->last_timeout_check_s != now) {
+		context->last_timeout_check_s = now;
+
+		lws_plat_service_periodic(context);
+
+		/* global timeout check once per second */
+
+		if (pollfd)
+			our_fd = pollfd->fd;
+
+		for (n = 0; n < context->fds_count; n++) {
+			m = context->fds[n].fd;
+			wsi = context->lws_lookup[m];
+			if (!wsi)
+				continue;
+
+			if (libwebsocket_service_timeout_check(context, wsi, now))
+				/* he did time out... */
+				if (m == our_fd) {
+					/* it was the guy we came to service! */
+					timed_out = 1;
+					/* mark as handled */
+					if (pollfd)
+						pollfd->revents = 0;
+				}
+		}
+	}
+
+	/* the socket we came to service timed out, nothing to do */
+	if (timed_out)
+		return 0;
+
+	/* just here for timeout management? */
+	if (pollfd == NULL)
+		return 0;
+
+	/* no, here to service a socket descriptor */
+	wsi = context->lws_lookup[pollfd->fd];
+	if (wsi == NULL)
+		/* not lws connection ... leave revents alone and return */
+		return 0;
+
+	/*
+	 * so that caller can tell we handled, past here we need to
+	 * zero down pollfd->revents after handling
+	 */
+
+	/*
+	 * deal with listen service piggybacking
+	 * every listen_service_modulo services of other fds, we
+	 * sneak one in to service the listen socket if there's anything waiting
+	 *
+	 * To handle connection storms, as found in ab, if we previously saw a
+	 * pending connection here, it causes us to check again next time.
+	 */
+
+	if (context->listen_service_fd && pollfd !=
+				       &context->fds[listen_socket_fds_index]) {
+		context->listen_service_count++;
+		if (context->listen_service_extraseen ||
+				context->listen_service_count ==
+					       context->listen_service_modulo) {
+			context->listen_service_count = 0;
+			m = 1;
+			if (context->listen_service_extraseen > 5)
+				m = 2;
+			while (m--) {
+				/*
+				 * even with extpoll, we prepared this
+				 * internal fds for listen
+				 */
+				n = lws_poll_listen_fd(&context->fds[listen_socket_fds_index]);
+				if (n > 0) { /* there's a conn waiting for us */
+					libwebsocket_service_fd(context,
+						&context->
+						  fds[listen_socket_fds_index]);
+					context->listen_service_extraseen++;
+				} else {
+					if (context->listen_service_extraseen)
+						context->
+						     listen_service_extraseen--;
+					break;
+				}
+			}
+		}
+
+	}
+
+	/* handle session socket closed */
+
+	if ((!(pollfd->revents & LWS_POLLIN)) &&
+			(pollfd->revents & LWS_POLLHUP)) {
+
+		lwsl_debug("Session Socket %p (fd=%d) dead\n",
+						       (void *)wsi, pollfd->fd);
+
+		goto close_and_handled;
+	}
+
+	/* okay, what we came here to do... */
+
+	switch (wsi->mode) {
+	case LWS_CONNMODE_HTTP_SERVING:
+	case LWS_CONNMODE_HTTP_SERVING_ACCEPTED:
+	case LWS_CONNMODE_SERVER_LISTENER:
+	case LWS_CONNMODE_SSL_ACK_PENDING:
+		n = lws_server_socket_service(context, wsi, pollfd);
+		if (n < 0)
+			goto close_and_handled;
+		goto handled;
+
+	case LWS_CONNMODE_WS_SERVING:
+	case LWS_CONNMODE_WS_CLIENT:
+	case LWS_CONNMODE_HTTP2_SERVING:
+
+		/* the guy requested a callback when it was OK to write */
+
+		if ((pollfd->revents & LWS_POLLOUT) &&
+			(wsi->state == WSI_STATE_ESTABLISHED || wsi->state == WSI_STATE_HTTP2_ESTABLISHED || wsi->state == WSI_STATE_HTTP2_ESTABLISHED_PRE_SETTINGS ||
+				wsi->state == WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE) &&
+			   lws_handle_POLLOUT_event(context, wsi, pollfd)) {
+			lwsl_info("libwebsocket_service_fd: closing\n");
+			goto close_and_handled;
+		}
+
+		if (wsi->rxflow_buffer &&
+			      (wsi->rxflow_change_to & LWS_RXFLOW_ALLOW)) {
+			lwsl_info("draining rxflow\n");
+			/* well, drain it */
+			eff_buf.token = (char *)wsi->rxflow_buffer +
+						wsi->rxflow_pos;
+			eff_buf.token_len = wsi->rxflow_len - wsi->rxflow_pos;
+			draining_flow = 1;
+			goto drain;
+		}
+
+		/* any incoming data ready? */
+
+		if (!(pollfd->revents & LWS_POLLIN))
+			break;
+
+		eff_buf.token_len = lws_ssl_capable_read(context, wsi,
+				context->service_buffer,
+					       sizeof(context->service_buffer));
+		switch (eff_buf.token_len) {
+		case 0:
+			lwsl_info("service_fd: closing due to 0 length read\n");
+			goto close_and_handled;
+		case LWS_SSL_CAPABLE_MORE_SERVICE:
+			lwsl_info("SSL Capable more service\n");
+			n = 0;
+			goto handled;
+		case LWS_SSL_CAPABLE_ERROR:
+			lwsl_info("Closing when error\n");
+			goto close_and_handled;
+		}
+
+		/*
+		 * give any active extensions a chance to munge the buffer
+		 * before parse.  We pass in a pointer to an lws_tokens struct
+		 * prepared with the default buffer and content length that's in
+		 * there.  Rather than rewrite the default buffer, extensions
+		 * that expect to grow the buffer can adapt .token to
+		 * point to their own per-connection buffer in the extension
+		 * user allocation.  By default with no extensions or no
+		 * extension callback handling, just the normal input buffer is
+		 * used then so it is efficient.
+		 */
+
+		eff_buf.token = (char *)context->service_buffer;
+drain:
+
+		do {
+
+			more = 0;
+			
+			m = lws_ext_callback_for_each_active(wsi,
+				LWS_EXT_CALLBACK_PACKET_RX_PREPARSE, &eff_buf, 0);
+			if (m < 0)
+				goto close_and_handled;
+			if (m)
+				more = 1;
+
+			/* service incoming data */
+
+			if (eff_buf.token_len) {
+				n = libwebsocket_read(context, wsi,
+					(unsigned char *)eff_buf.token,
+							    eff_buf.token_len);
+				if (n < 0) {
+					/* we closed wsi */
+					n = 0;
+					goto handled;
+				}
+			}
+
+			eff_buf.token = NULL;
+			eff_buf.token_len = 0;
+		} while (more);
+
+		if (draining_flow && wsi->rxflow_buffer &&
+				 wsi->rxflow_pos == wsi->rxflow_len) {
+			lwsl_info("flow buffer: drained\n");
+			lws_free2(wsi->rxflow_buffer);
+			/* having drained the rxflow buffer, can rearm POLLIN */
+#ifdef LWS_NO_SERVER
+			n =
+#endif
+			_libwebsocket_rx_flow_control(wsi); /* n ignored, needed for NO_SERVER case */
+		}
+
+		break;
+
+	default:
+#ifdef LWS_NO_CLIENT
+		break;
+#else
+		n = lws_client_socket_service(context, wsi, pollfd);
+		goto handled;
+#endif
+	}
+
+	n = 0;
+	goto handled;
+
+close_and_handled:
+	lwsl_debug("Close and handled\n");
+	libwebsocket_close_and_free_session(context, wsi,
+						LWS_CLOSE_STATUS_NOSTATUS);
+	n = 1;
+
+handled:
+	pollfd->revents = 0;
+	return n;
+}
+
+/**
+ * libwebsocket_service() - Service any pending websocket activity
+ * @context:	Websocket context
+ * @timeout_ms:	Timeout for poll; 0 means return immediately if nothing needed
+ *		service otherwise block and service immediately, returning
+ *		after the timeout if nothing needed service.
+ *
+ *	This function deals with any pending websocket traffic, for three
+ *	kinds of event.  It handles these events on both server and client
+ *	types of connection the same.
+ *
+ *	1) Accept new connections to our context's server
+ *
+ *	2) Call the receive callback for incoming frame data received by
+ *	    server or client connections.
+ *
+ *	You need to call this service function periodically to all the above
+ *	functions to happen; if your application is single-threaded you can
+ *	just call it in your main event loop.
+ *
+ *	Alternatively you can fork a new process that asynchronously handles
+ *	calling this service in a loop.  In that case you are happy if this
+ *	call blocks your thread until it needs to take care of something and
+ *	would call it with a large nonzero timeout.  Your loop then takes no
+ *	CPU while there is nothing happening.
+ *
+ *	If you are calling it in a single-threaded app, you don't want it to
+ *	wait around blocking other things in your loop from happening, so you
+ *	would call it with a timeout_ms of 0, so it returns immediately if
+ *	nothing is pending, or as soon as it services whatever was pending.
+ */
+
+LWS_VISIBLE int
+libwebsocket_service(struct libwebsocket_context *context, int timeout_ms)
+{
+	return lws_plat_service(context, timeout_ms);
+}
+
diff --git a/src/engine/external/libwebsockets/sha-1.c b/src/engine/external/libwebsockets/sha-1.c
new file mode 100644
index 00000000..e68ee38d
--- /dev/null
+++ b/src/engine/external/libwebsockets/sha-1.c
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ * FIPS pub 180-1: Secure Hash Algorithm (SHA-1)
+ * based on: http://csrc.nist.gov/fips/fip180-1.txt
+ * implemented by Jun-ichiro itojun Itoh <itojun@itojun.org>
+ */
+
+#include "private-libwebsockets.h"
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+struct sha1_ctxt {
+	union {
+		unsigned char		b8[20];
+		unsigned int		b32[5];
+	} h;
+	union {
+		unsigned char		b8[8];
+		u_int64_t		b64[1];
+	} c;
+	union {
+		unsigned char		b8[64];
+		unsigned int		b32[16];
+	} m;
+	unsigned char			count;
+};
+
+/* sanity check */
+#if !defined(BYTE_ORDER) || !defined(LITTLE_ENDIAN) || !defined(BIG_ENDIAN)
+# define unsupported 1
+#elif BYTE_ORDER != BIG_ENDIAN
+# if BYTE_ORDER != LITTLE_ENDIAN
+#  define unsupported 1
+# endif
+#endif
+
+#ifndef unsupported
+
+/* constant table */
+static const unsigned int _K[] =
+			{ 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6 };
+#define	K(t)	_K[(t) / 20]
+
+#define	F0(b, c, d)	(((b) & (c)) | ((~(b)) & (d)))
+#define	F1(b, c, d)	(((b) ^ (c)) ^ (d))
+#define	F2(b, c, d)	(((b) & (c)) | ((b) & (d)) | ((c) & (d)))
+#define	F3(b, c, d)	(((b) ^ (c)) ^ (d))
+
+#define	S(n, x)		(((x) << (n)) | ((x) >> (32 - n)))
+
+#define	H(n)	(ctxt->h.b32[(n)])
+#define	COUNT	(ctxt->count)
+#define	BCOUNT	(ctxt->c.b64[0] / 8)
+#define	W(n)	(ctxt->m.b32[(n)])
+
+#define	PUTBYTE(x)	{ \
+	ctxt->m.b8[(COUNT % 64)] = (x);		\
+	COUNT++;				\
+	COUNT %= 64;				\
+	ctxt->c.b64[0] += 8;			\
+	if (COUNT % 64 == 0)			\
+		sha1_step(ctxt);		\
+	}
+
+#define	PUTPAD(x)	{ \
+	ctxt->m.b8[(COUNT % 64)] = (x);		\
+	COUNT++;				\
+	COUNT %= 64;				\
+	if (COUNT % 64 == 0)			\
+		sha1_step(ctxt);		\
+	}
+
+static void sha1_step __P((struct sha1_ctxt *));
+
+static void
+sha1_step(struct sha1_ctxt *ctxt)
+{
+	unsigned int	a, b, c, d, e, tmp;
+	size_t t, s;
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+	struct sha1_ctxt tctxt;
+
+	memcpy(&tctxt.m.b8[0], &ctxt->m.b8[0], 64);
+	ctxt->m.b8[0] = tctxt.m.b8[3]; ctxt->m.b8[1] = tctxt.m.b8[2];
+	ctxt->m.b8[2] = tctxt.m.b8[1]; ctxt->m.b8[3] = tctxt.m.b8[0];
+	ctxt->m.b8[4] = tctxt.m.b8[7]; ctxt->m.b8[5] = tctxt.m.b8[6];
+	ctxt->m.b8[6] = tctxt.m.b8[5]; ctxt->m.b8[7] = tctxt.m.b8[4];
+	ctxt->m.b8[8] = tctxt.m.b8[11]; ctxt->m.b8[9] = tctxt.m.b8[10];
+	ctxt->m.b8[10] = tctxt.m.b8[9]; ctxt->m.b8[11] = tctxt.m.b8[8];
+	ctxt->m.b8[12] = tctxt.m.b8[15]; ctxt->m.b8[13] = tctxt.m.b8[14];
+	ctxt->m.b8[14] = tctxt.m.b8[13]; ctxt->m.b8[15] = tctxt.m.b8[12];
+	ctxt->m.b8[16] = tctxt.m.b8[19]; ctxt->m.b8[17] = tctxt.m.b8[18];
+	ctxt->m.b8[18] = tctxt.m.b8[17]; ctxt->m.b8[19] = tctxt.m.b8[16];
+	ctxt->m.b8[20] = tctxt.m.b8[23]; ctxt->m.b8[21] = tctxt.m.b8[22];
+	ctxt->m.b8[22] = tctxt.m.b8[21]; ctxt->m.b8[23] = tctxt.m.b8[20];
+	ctxt->m.b8[24] = tctxt.m.b8[27]; ctxt->m.b8[25] = tctxt.m.b8[26];
+	ctxt->m.b8[26] = tctxt.m.b8[25]; ctxt->m.b8[27] = tctxt.m.b8[24];
+	ctxt->m.b8[28] = tctxt.m.b8[31]; ctxt->m.b8[29] = tctxt.m.b8[30];
+	ctxt->m.b8[30] = tctxt.m.b8[29]; ctxt->m.b8[31] = tctxt.m.b8[28];
+	ctxt->m.b8[32] = tctxt.m.b8[35]; ctxt->m.b8[33] = tctxt.m.b8[34];
+	ctxt->m.b8[34] = tctxt.m.b8[33]; ctxt->m.b8[35] = tctxt.m.b8[32];
+	ctxt->m.b8[36] = tctxt.m.b8[39]; ctxt->m.b8[37] = tctxt.m.b8[38];
+	ctxt->m.b8[38] = tctxt.m.b8[37]; ctxt->m.b8[39] = tctxt.m.b8[36];
+	ctxt->m.b8[40] = tctxt.m.b8[43]; ctxt->m.b8[41] = tctxt.m.b8[42];
+	ctxt->m.b8[42] = tctxt.m.b8[41]; ctxt->m.b8[43] = tctxt.m.b8[40];
+	ctxt->m.b8[44] = tctxt.m.b8[47]; ctxt->m.b8[45] = tctxt.m.b8[46];
+	ctxt->m.b8[46] = tctxt.m.b8[45]; ctxt->m.b8[47] = tctxt.m.b8[44];
+	ctxt->m.b8[48] = tctxt.m.b8[51]; ctxt->m.b8[49] = tctxt.m.b8[50];
+	ctxt->m.b8[50] = tctxt.m.b8[49]; ctxt->m.b8[51] = tctxt.m.b8[48];
+	ctxt->m.b8[52] = tctxt.m.b8[55]; ctxt->m.b8[53] = tctxt.m.b8[54];
+	ctxt->m.b8[54] = tctxt.m.b8[53]; ctxt->m.b8[55] = tctxt.m.b8[52];
+	ctxt->m.b8[56] = tctxt.m.b8[59]; ctxt->m.b8[57] = tctxt.m.b8[58];
+	ctxt->m.b8[58] = tctxt.m.b8[57]; ctxt->m.b8[59] = tctxt.m.b8[56];
+	ctxt->m.b8[60] = tctxt.m.b8[63]; ctxt->m.b8[61] = tctxt.m.b8[62];
+	ctxt->m.b8[62] = tctxt.m.b8[61]; ctxt->m.b8[63] = tctxt.m.b8[60];
+#endif
+
+	a = H(0); b = H(1); c = H(2); d = H(3); e = H(4);
+
+	for (t = 0; t < 20; t++) {
+		s = t & 0x0f;
+		if (t >= 16)
+			W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^
+							W((s+2) & 0x0f) ^ W(s));
+
+		tmp = S(5, a) + F0(b, c, d) + e + W(s) + K(t);
+		e = d; d = c; c = S(30, b); b = a; a = tmp;
+	}
+	for (t = 20; t < 40; t++) {
+		s = t & 0x0f;
+		W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^
+							W((s+2) & 0x0f) ^ W(s));
+		tmp = S(5, a) + F1(b, c, d) + e + W(s) + K(t);
+		e = d; d = c; c = S(30, b); b = a; a = tmp;
+	}
+	for (t = 40; t < 60; t++) {
+		s = t & 0x0f;
+		W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^
+							W((s+2) & 0x0f) ^ W(s));
+		tmp = S(5, a) + F2(b, c, d) + e + W(s) + K(t);
+		e = d; d = c; c = S(30, b); b = a; a = tmp;
+	}
+	for (t = 60; t < 80; t++) {
+		s = t & 0x0f;
+		W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^
+							W((s+2) & 0x0f) ^ W(s));
+		tmp = S(5, a) + F3(b, c, d) + e + W(s) + K(t);
+		e = d; d = c; c = S(30, b); b = a; a = tmp;
+	}
+
+	H(0) = H(0) + a;
+	H(1) = H(1) + b;
+	H(2) = H(2) + c;
+	H(3) = H(3) + d;
+	H(4) = H(4) + e;
+
+	bzero(&ctxt->m.b8[0], 64);
+}
+
+/*------------------------------------------------------------*/
+
+static void
+sha1_init(struct sha1_ctxt *ctxt)
+{
+	bzero(ctxt, sizeof(struct sha1_ctxt));
+	H(0) = 0x67452301;
+	H(1) = 0xefcdab89;
+	H(2) = 0x98badcfe;
+	H(3) = 0x10325476;
+	H(4) = 0xc3d2e1f0;
+}
+
+void
+sha1_pad(struct sha1_ctxt *ctxt)
+{
+	size_t padlen;		/*pad length in bytes*/
+	size_t padstart;
+
+	PUTPAD(0x80);
+
+	padstart = COUNT % 64;
+	padlen = 64 - padstart;
+	if (padlen < 8) {
+		bzero(&ctxt->m.b8[padstart], padlen);
+		COUNT += padlen;
+		COUNT %= 64;
+		sha1_step(ctxt);
+		padstart = COUNT % 64;	/* should be 0 */
+		padlen = 64 - padstart;	/* should be 64 */
+	}
+	bzero(&ctxt->m.b8[padstart], padlen - 8);
+	COUNT += (padlen - 8);
+	COUNT %= 64;
+#if BYTE_ORDER == BIG_ENDIAN
+	PUTPAD(ctxt->c.b8[0]); PUTPAD(ctxt->c.b8[1]);
+	PUTPAD(ctxt->c.b8[2]); PUTPAD(ctxt->c.b8[3]);
+	PUTPAD(ctxt->c.b8[4]); PUTPAD(ctxt->c.b8[5]);
+	PUTPAD(ctxt->c.b8[6]); PUTPAD(ctxt->c.b8[7]);
+#else
+	PUTPAD(ctxt->c.b8[7]); PUTPAD(ctxt->c.b8[6]);
+	PUTPAD(ctxt->c.b8[5]); PUTPAD(ctxt->c.b8[4]);
+	PUTPAD(ctxt->c.b8[3]); PUTPAD(ctxt->c.b8[2]);
+	PUTPAD(ctxt->c.b8[1]); PUTPAD(ctxt->c.b8[0]);
+#endif
+}
+
+void
+sha1_loop(struct sha1_ctxt *ctxt, const unsigned char *input, size_t len)
+{
+	size_t gaplen;
+	size_t gapstart;
+	size_t off;
+	size_t copysiz;
+
+	off = 0;
+
+	while (off < len) {
+		gapstart = COUNT % 64;
+		gaplen = 64 - gapstart;
+
+		copysiz = (gaplen < len - off) ? gaplen : len - off;
+		memcpy(&ctxt->m.b8[gapstart], &input[off], copysiz);
+		COUNT += copysiz;
+		COUNT %= 64;
+		ctxt->c.b64[0] += copysiz * 8;
+		if (COUNT % 64 == 0)
+			sha1_step(ctxt);
+		off += copysiz;
+	}
+}
+
+void
+sha1_result(struct sha1_ctxt *ctxt, void *digest0)
+{
+	unsigned char *digest;
+
+	digest = (unsigned char *)digest0;
+	sha1_pad(ctxt);
+#if BYTE_ORDER == BIG_ENDIAN
+	memcpy(digest, &ctxt->h.b8[0], 20);
+#else
+	digest[0] = ctxt->h.b8[3]; digest[1] = ctxt->h.b8[2];
+	digest[2] = ctxt->h.b8[1]; digest[3] = ctxt->h.b8[0];
+	digest[4] = ctxt->h.b8[7]; digest[5] = ctxt->h.b8[6];
+	digest[6] = ctxt->h.b8[5]; digest[7] = ctxt->h.b8[4];
+	digest[8] = ctxt->h.b8[11]; digest[9] = ctxt->h.b8[10];
+	digest[10] = ctxt->h.b8[9]; digest[11] = ctxt->h.b8[8];
+	digest[12] = ctxt->h.b8[15]; digest[13] = ctxt->h.b8[14];
+	digest[14] = ctxt->h.b8[13]; digest[15] = ctxt->h.b8[12];
+	digest[16] = ctxt->h.b8[19]; digest[17] = ctxt->h.b8[18];
+	digest[18] = ctxt->h.b8[17]; digest[19] = ctxt->h.b8[16];
+#endif
+}
+
+/*
+ * This should look and work like the libcrypto implementation
+ */
+
+LWS_VISIBLE unsigned char *
+libwebsockets_SHA1(const unsigned char *d, size_t n, unsigned char *md)
+{
+	struct sha1_ctxt ctx;
+
+	sha1_init(&ctx);
+	sha1_loop(&ctx, d, n);
+	sha1_result(&ctx, (void *)md);
+
+	return md;
+}
+
+#endif /*unsupported*/