From 7604511fcfe4481900fc82a92424e5ceef65d6b3 Mon Sep 17 00:00:00 2001 From: Khoi Hoang <57012152+khoih-prog@users.noreply.github.com> Date: Fri, 18 Feb 2022 00:01:55 -0500 Subject: [PATCH] v2.14.0 to optimize library ### Release v2.14.0 1. Suppress unnecessary warnings. 2. Don't use `deprecated sha.h` for ESP32 core v1.0.6+. Check [warning sha.h is deprecated, use sha_parallel_engine.h #738](https://github.com/Links2004/arduinoWebSockets/issues/738) 3. Optimize code by passing by `reference` instead of `value` 4. Modify nearly all examples 5. Update `Packages' Patches` --- src/CONTRIBUTING.md | 54 + src/LICENSE | 674 +++++ src/README.md | 2996 +++++++++++++++++++++++ src/changelog.md | 288 +++ src/keywords.txt | 91 + src/library.json | 157 ++ src/library.properties | 11 + src/platformio/platformio.ini | 379 +++ src/src/SocketIOclient_Generic-Impl.h | 400 +++ src/src/SocketIOclient_Generic.h | 201 ++ src/src/WebSockets4WebServer_Generic.h | 127 + src/src/WebSocketsClient_Generic-Impl.h | 1406 +++++++++++ src/src/WebSocketsClient_Generic.h | 268 ++ src/src/WebSocketsDebug_Generic.h | 192 ++ src/src/WebSocketsServer_Generic-Impl.h | 1289 ++++++++++ src/src/WebSocketsServer_Generic.h | 309 +++ src/src/WebSockets_Generic-Impl.h | 1058 ++++++++ src/src/WebSockets_Generic.h | 915 +++++++ src/src/libb64/AUTHORS | 7 + src/src/libb64/LICENSE | 29 + src/src/libb64/cdecode-Impl.h | 166 ++ src/src/libb64/cdecode_inc.h | 47 + src/src/libb64/cencode-Impl.h | 166 ++ src/src/libb64/cencode_inc.h | 56 + src/src/libsha1/libsha1.c | 224 ++ src/src/libsha1/libsha1.h | 29 + 26 files changed, 11539 insertions(+) create mode 100644 src/CONTRIBUTING.md create mode 100644 src/LICENSE create mode 100644 src/README.md create mode 100644 src/changelog.md create mode 100644 src/keywords.txt create mode 100644 src/library.json create mode 100644 src/library.properties create mode 100644 src/platformio/platformio.ini create mode 100644 src/src/SocketIOclient_Generic-Impl.h create mode 100644 src/src/SocketIOclient_Generic.h create mode 100644 src/src/WebSockets4WebServer_Generic.h create mode 100644 src/src/WebSocketsClient_Generic-Impl.h create mode 100644 src/src/WebSocketsClient_Generic.h create mode 100644 src/src/WebSocketsDebug_Generic.h create mode 100644 src/src/WebSocketsServer_Generic-Impl.h create mode 100644 src/src/WebSocketsServer_Generic.h create mode 100644 src/src/WebSockets_Generic-Impl.h create mode 100644 src/src/WebSockets_Generic.h create mode 100644 src/src/libb64/AUTHORS create mode 100644 src/src/libb64/LICENSE create mode 100644 src/src/libb64/cdecode-Impl.h create mode 100644 src/src/libb64/cdecode_inc.h create mode 100644 src/src/libb64/cencode-Impl.h create mode 100644 src/src/libb64/cencode_inc.h create mode 100644 src/src/libsha1/libsha1.c create mode 100644 src/src/libsha1/libsha1.h diff --git a/src/CONTRIBUTING.md b/src/CONTRIBUTING.md new file mode 100644 index 00000000..db7075ff --- /dev/null +++ b/src/CONTRIBUTING.md @@ -0,0 +1,54 @@ +## Contributing to WebSockets_Generic + +### Reporting Bugs + +Please report bugs in WebSockets_Generic if you find them. + +However, before reporting a bug please check through the following: + +* [Existing Open Issues](https://github.com/khoih-prog/WebSockets_Generic/issues) - someone might have already encountered this. + +If you don't find anything, please [open a new issue](https://github.com/khoih-prog/WebSockets_Generic/issues/new). + +### How to submit a bug report + +Please ensure to specify the following: + +* Arduino IDE version (e.g. 1.8.19) or Platform.io version +* Board Core Version (e.g. Arduino SAMDUE core v1.6.12, ESP8266 core v3.0.2, ArduinoCore-mbed v2.7.2, etc.) +* Contextual information (e.g. what you were trying to achieve) +* Simplest possible steps to reproduce +* Anything that might be relevant in your opinion, such as: + * Operating system (Windows, Ubuntu, etc.) and the output of `uname -a` + * Network configuration + + +### Example + +``` +Arduino IDE version: 1.8.19 +RASPBERRY_PI_PICO board +ArduinoCore-mbed v2.7.2 +OS: Ubuntu 20.04 LTS +Linux xy-Inspiron-3593 5.4.0-99-generic #112-Ubuntu SMP Thu Feb 3 13:50:55 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux + +Context: +I encountered an endless loop while trying to connect to Local WiFi. + +Steps to reproduce: +1. ... +2. ... +3. ... +4. ... +``` + +### Sending Feature Requests + +Feel free to post feature requests. It's helpful if you can explain exactly why the feature would be useful. + +There are usually some outstanding feature requests in the [existing issues list](https://github.com/khoih-prog/WebSockets_Generic/issues?q=is%3Aopen+is%3Aissue+label%3Aenhancement), feel free to add comments to them. + +### Sending Pull Requests + +Pull Requests with changes and fixes are also welcome! + diff --git a/src/LICENSE b/src/LICENSE new file mode 100644 index 00000000..94a9ed02 --- /dev/null +++ b/src/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If 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 convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/src/README.md b/src/README.md new file mode 100644 index 00000000..5c0c0ab8 --- /dev/null +++ b/src/README.md @@ -0,0 +1,2996 @@ +## WebSockets_Generic + +[![arduino-library-badge](https://www.ardu-badge.com/badge/WebSockets_Generic.svg?)](https://www.ardu-badge.com/WebSockets_Generic) +[![GitHub release](https://img.shields.io/github/release/khoih-prog/WebSockets_Generic.svg)](https://github.com/khoih-prog/WebSockets_Generic/releases) +[![GitHub](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/khoih-prog/WebSockets_Generic/blob/master/LICENSE) +[![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](#Contributing) +[![GitHub issues](https://img.shields.io/github/issues/khoih-prog/WebSockets_Generic.svg)](http://github.com/khoih-prog/WebSockets_Generic/issues) + +--- +--- + +## Table of Contents + +* [Why do we need this WebSockets_Generic library](#why-do-we-need-this-websockets_generic-library) + * [Features](#features) + * [Supported features of RFC6455](#supported-features-of-rfc6455) + * [Important Notes](#important-notes) + * [Currently supported Boards](#currently-supported-boards) + * [Currently supported WiFi shields/modules](#currently-supported-wifi-shieldsmodules) + * [Currently supported Ethernet shields/modules](#currently-supported-ethernet-shieldsmodules) +* [Changelog](changelog.md) +* [Prerequisites](#prerequisites) +* [Installation](#installation) + * [Use Arduino Library Manager](#use-arduino-library-manager) + * [Manual Install](#manual-install) + * [VS Code & PlatformIO](#vs-code--platformio) +* [Installation](#installation) + * [Use Arduino Library Manager](#use-arduino-library-manager) + * [Manual Install](#manual-install) + * [VS Code & PlatformIO](#vs-code--platformio) +* [Packages' Patches](#packages-patches) + * [1. For Adafruit nRF52840 and nRF52832 boards](#1-for-adafruit-nRF52840-and-nRF52832-boards) + * [2. For Teensy boards](#2-for-teensy-boards) + * [3. For Arduino SAM DUE boards](#3-for-arduino-sam-due-boards) + * [4. For Arduino SAMD boards](#4-for-arduino-samd-boards) + * [For core version v1.8.10+](#for-core-version-v1810) + * [For core version v1.8.9-](#for-core-version-v189-) + * [5. For Adafruit SAMD boards](#5-for-adafruit-samd-boards) + * [6. For Seeeduino SAMD boards](#6-for-seeeduino-samd-boards) + * [7. For STM32 boards](#7-for-stm32-boards) + * [7.1. For STM32 boards to use LAN8720](#71-for-stm32-boards-to-use-lan8720) + * [7.2. For STM32 boards to use Serial1](#72-for-stm32-boards-to-use-serial1) + * [8. For RP2040-based boards using Earle Philhower arduino-pico core](#8-for-rp2040-based-boards-using-earle-philhower-arduino-pico-core) + * [8.1. To use BOARD_NAME](#81-to-use-board_name) + * [8.2. To avoid compile error relating to microsecondsToClockCycles](#82-to-avoid-compile-error-relating-to-microsecondstoclockcycles) + * [9. For Portenta_H7 boards using Arduino IDE in Linux](#9-for-portenta_h7-boards-using-arduino-ide-in-linux) + * [10. For RTL8720DN boards using AmebaD core](#10-for-rtl8720dn-boards-using-amebad-core) +* [Libraries' Patches](#libraries-patches) + * [1. For application requiring 2K+ HTML page](#1-for-application-requiring-2k-html-page) + * [2. For Ethernet library](#2-for-ethernet-library) + * [3. For EthernetLarge library](#3-for-ethernetlarge-library) + * [4. For Etherne2 library](#4-for-ethernet2-library) + * [5. For Ethernet3 library](#5-for-ethernet3-library) + * [6. For UIPEthernet library](#6-for-uipethernet-library) + * [7. For fixing ESP32 compile error](#7-for-fixing-esp32-compile-error) + * [8. For fixing ESP8266 compile error](#8-for-fixing-esp8266-compile-error) +* [HOWTO Use analogRead() with ESP32 running WiFi and/or BlueTooth (BT/BLE)](#howto-use-analogread-with-esp32-running-wifi-andor-bluetooth-btble) +* [Important Notes](#important-notes-1) + * [Limitations](#limitations) + * [Limitations for Async](#limitations-for-async) + * [Originally Supported Hardware](#originally-supported-hardware) + * [wss / SSL](#wss--ssl) + * [ESP Async TCP](#esp-async-tcp) +* [How to use](#how-to-use) +* [High Level Client API](#high-level-client-api) +* [Examples](#examples) + * [For Generic boards using W5x00 Ethernet shield](#for-generic-boards-using-w5x00-ethernet-shield) + * [For Generic boards using WiFiNINA](#for-generic-boards-using-wifinina) + * [For Generic boards using ENC28J60 Ethernet shield and EthernetENC library](#for-generic-boards-using-enc28j60-ethernet-shield-and-ethernetenc-library) + * [For WiFiNINA](#for-wifinina) + * [For WiFi101](#for-wifi101) + * [For W5x00 Ethernet shield](#for-w5x00-ethernet-shield) + * [For ENC28J60 Ethernet shield using UIPEthernet library](#for-enc28j60-ethernet-shield-using-uipethernet-library) + * [For ESP32 board](#for-esp32-board) + * [For ESP8266 board](#for-esp8266-board) + * [For SeeedStudio WIO Terminal using Realtek RTL8720DN WiFi](#for-seeedstudio-wio-terminal-using-realtek-rtl8720dn-wifi) + * [For STM32 boards using built-in LAN8742A Ethernet](#for-stm32-boards-using-built-in-lan8742a-ethernet) + * [For Teensy boards using ENC28J60 Ethernet shield and EthernetENC library](#for-teensy-boards-using-enc28j60-ethernet-shield-and-ethernetenc-library) + * [For Teensy 4.1 boards using NativeEthernet](#for-teensy-41-boards-using-nativeethernet) + * [For Teensy boards using W5x00 Ethernet shield](#for-teensy-boards-using-w5x00-ethernet-shield) + * [For Teensy boards using WiFiNINA](#for-teensy-boards-using-wifinina) + * [For Teensy 4.1 boards using QNEthernet](#for-teensy-41-boards-using-qnethernet) + * [Nodejs Socket.IO Test Server to use with examples](#nodejs-socketio-test-server-to-use-with-examples) + * [For WT32_ETH01 board](#for-wt32_eth01-board) **New** + * [For Portenta_H7 board](#for-Portenta_H7-board). **New** + * [Portenta_Ethernet](#Portenta_Ethernet). + * [WiFi](#WiFi) +* [Example Generic_WebSocketClient_WiFiNINA](#example-generic_websocketclient_wifinina) +* [Debug Terminal Output Samples](#debug-terminal-output-samples) + * [1. Generic_WebSocketClient_EthernetENC on NRF52840_FEATHER](#1-generic_websocketclient_ethernetenc-on-nrf52840_feather) + * [2. Generic_Ethernet_Blinds on NRF52840_FEATHER with ENC28J60 using EthernetENC Library](#2-generic_ethernet_blinds-on-nrf52840_feather-with-enc28j60-using-ethernetenc-library) + * [3. WebSocketClientSocketIO_W5500 on NRF52840_FEATHER with W5500 using Ethernet2 Library](#3-websocketclientsocketio_w5500-on-nrf52840_feather-with-w5500-using-ethernet2-library) + * [4. Generic_WebSocketClientSocketIO_EthernetENC on NRF52840_FEATHER with ENC28J60 using EthernetENC Library](#4-generic_websocketclientsocketio_ethernetenc-on-nrf52840_feather-with-enc28j60-using-ethernetenc-library) + * [5. WIOTerminal_WebSocketClientSSL on SeeedStudio SAMD51 WIO_TERMINAL with Realtek RTL8720DN WiFi using Seeed_Arduino_rpcWiFi Library](#5-wioterminal_websocketclientssl-on-seeedstudio-samd51-wio_terminal-with-realtek-rtl8720dn-wifi-using-seeed_arduino_rpcwifi-library) + * [6. Generic_WebSocketClientSSL_WiFiNINA on Arduino SAMD21 Nano-33-IoT with WiFiNINA using WiFiNINA_Generic Library](#6-generic_websocketclientssl_wifinina-on-arduino-samd21-nano-33-iot-with-wifinina-using-wifinina_generic-library) + * [7. WebSocketClientSocketIO_NINA on Arduino SAMD21 Nano-33-IoT with WiFiNINA using WiFiNINA_Generic Library](#7-websocketclientsocketio_nina-on-arduino-samd21-nano-33-iot-with-wifinina-using-wifinina_generic-library) + * [7.1 Client](#71-client) + * [7.2 Server](#72-server) + * [8. Generic_WebSocketClientSocketIO_W5500 on NRF52840_FEATHER with W5x00 using EthernetLarge Library](#8-generic_websocketclientsocketio_w5500-on-nrf52840_feather-with-w5x00-using-ethernetlarge-library) + * [8.1 Client](#81-client) + * [8.2 Server](#82-server) + * [9. WebSocketClientSocketIO_W5500 on RASPBERRY_PI_PICO with W5x00 using Ethernet2 Library](#9-websocketclientsocketio_w5500-on-raspberry_pi_pico-with-w5x00-using-ethernet2-library) + * [9.1 Client](#91-client) + * [9.2 Server](#92-server) + * [10. WebSocketClientSocketIO_W5500 on MBED RASPBERRY_PI_PICO with W5x00 using Ethernet2 Library](#10-websocketclientsocketio_w5500-on-mbed-raspberry_pi_pico-with-w5x00-using-ethernet2-library) + * [10.1 Client](#101-client) + * [10.2 Server](#102-server) + * [11. WT32_ETH01_WebSocketClientSocketIO on WT32_ETH01](#11-wt32_eth01_websocketclientsocketio-on-wt32_eth01) + * [11.1 Client](#111-client) + * [11.2 Server](#112-server) + * [12. Teensy_WebSocketClientSocketIO_QNEthernet on TEENSY 4.1 using QNEthernet](#12-teensy_websocketclientsocketio_qnethernet-on-teensy-41-using-qnethernet) + * [12.1 Client](#121-client) + * [12.2 Server](#122-server) + * [13. Portenta_H7_WebSocketClientSocketIO on PORTENTA_H7_M7 with Ethernet](#13-Portenta_H7_WebSocketClientSocketIO-on-PORTENTA_H7_M7-with-Ethernet) + * [13.1 Client](#131-client) + * [13.2 Server](#132-server) + * [14. WebSocketClientSocketIO_WiFi on Portenta_H7 using WiFi](#14-WebSocketClientSocketIO_WiFi-on-Portenta_H7-using-WiFi) + * [14.1 Client](#141-client) + * [14.2 Server](#142-server) + * [15. Portenta_H7_WebSocketClient_Sticky_SocketIO on PORTENTA_H7_M7 using Ethernet](#15-Portenta_H7_WebSocketClient_Sticky_SocketIO-on-PORTENTA_H7_M7-using-Ethernet) + * [16. ESP32_WebSocketClientSocketIO on ESP32S3_DEV](#16-ESP32_WebSocketClientSocketIO-on-ESP32S3_DEV) **New** +* [Debug](#debug) +* [Troubleshooting](#troubleshooting) +* [Issues](#issues) +* [TO DO](#to-do) +* [DONE](#done) +* [Contributions and Thanks](#contributions-and-thanks) +* [Contributing](#contributing) +* [License and credits](#license-and-credits) + +--- +--- + +### Why do we need this [WebSockets_Generic library](https://github.com/khoih-prog/WebSockets_Generic) + +#### Features + +Many Web services require WebSockets library, which is so far written only for ESP8266/ESP32 boards. The ESP boards rely on this [Markus Sattler's **WebSockets Library**](https://github.com/Links2004/arduinoWebSockets) to connect to Alexa via Sinric or SinricPro skills. + +This [WebSockets_Generic library](https://github.com/khoih-prog/WebSockets_Generic) is a RFC6455-based WebSocket Server and Client for Arduino boards. It is based on and modified from [Markus Sattler's **WebSockets Library**](https://github.com/Links2004/arduinoWebSockets) to provide support to many more boards, such as **WT32_ETH01 (ESP32 + LAN8720), Arduino SAMD21, Adafruit SAMD21/SAMD51, nRF52, STM32F/L/H/G/WB/MP1, Teensy, SAM DUE, RP2040-based boards, etc.** and enable those boards to use WebSockets services, including voice-control Alexa along with Blynk. Those supported boards can also run **WebSockets Server.** The WebSockets can be used with **ESP’s WiFi, WiFiNINA, WiFi101, W5x00, ENC28J60 Ethernet and Teensy 4.1 NativeEthernet/QNEthernet.** + + +#### Supported features of RFC6455 + + - text frame + - binary frame + - connection close + - ping + - pong + - continuation frame + +#### Important Notes + +1. Currently, the WebSocketServer feature is usable only for ESP8266/ESP32 (ESP32, ESP32_S2, ESP32_S3 and ESP32_C3) and WT32_ETH01 (ESP32 + LAN8720). +2. The timeline when to fix and reintroduce the WebSocketServer feature to other boards is not determined yet. +3. Please use the new [**WebSockets2_Generic Library**](https://github.com/khoih-prog/WebSockets2_Generic) if WebSocketServer is necessary. See [Issue 2](https://github.com/khoih-prog/WebSockets_Generic/issues/2), [Issue 3](https://github.com/khoih-prog/WebSockets_Generic/issues/3) and [Issue 4](https://github.com/khoih-prog/WebSockets_Generic/issues/4) + +--- + + +#### Currently supported Boards + +This [**WebSockets_Generic** library](https://github.com/khoih-prog/WebSockets_Generic) currently supports these following boards: + + 1. **nRF52 boards**, such as **AdaFruit Feather nRF52832, nRF52840 Express, BlueFruit Sense, Itsy-Bitsy nRF52840 Express, Metro nRF52840 Express, NINA_B302_ublox, NINA_B112_ublox, etc.** + + 2. **SAMD21** + - Arduino SAMD21: ZERO, MKRs, NANO_33_IOT, etc. + - Adafruit SAMD21 (M0): ItsyBitsy M0, Feather M0, Feather M0 Express, Metro M0 Express, Circuit Playground Express, Trinket M0, PIRkey, Hallowing M0, Crickit M0, etc. + - Seeeduino: LoRaWAN, Zero, Femto M0, XIAO M0, Wio GPS Board, etc. + + 3. **SAMD51** + - Adafruit SAMD51 (M4): Metro M4, Grand Central M4, ItsyBitsy M4, Feather M4 Express, Trellis M4, Metro M4 AirLift Lite, MONSTER M4SK Express, Hallowing M4, etc. + - Seeeduino: Wio Terminal, Grove UI Wireless + + 4. **SAM DUE** + 5. **Teensy (4.1, 4.0, 3.6, 3.5, 3,2, 3.1, 3.0)** + 6. **STM32F/L/H/G/WB/MP1 boards (with 32+K Flash)** + - Nucleo-144 + - Nucleo-64 + - Discovery + - Generic STM32F0, STM32F1, STM32F2, STM32F3, STM32F4, STM32F7 (with 64+K Flash): x8 and up + - STM32L0, STM32L1, STM32L4 + - STM32G0, STM32G4 + - STM32H7 + - STM32WB + - STM32MP1 + - LoRa boards + - 3-D printer boards + - Generic Flight Controllers + - Midatronics boards + + 7. **ESP32** + + - ESP32 boards, such as `ESP32_DEV`, etc. + - ESP32_S2-based boards, such as `ESP32S2_DEV`, `ESP32_S2 Saola`, etc. + - ESP32_C3-based boards, such as `ESP32C3_DEV`, etc. **New** + - ESP32_S3 (ESP32S3_DEV, ESP32_S3_BOX, UM TINYS3, UM PROS3, UM FEATHERS3, etc.) **New** + + 8. **ESP8266** + + 9. RP2040-based boards, such as **RASPBERRY_PI_PICO, ADAFRUIT_FEATHER_RP2040 and GENERIC_RP2040**, using [**Arduino-mbed RP2040** v2.1.0+ core](https://github.com/arduino/ArduinoCore-mbed) or [**Earle Philhower's arduino-pico** core v1.5.1+](https://github.com/earlephilhower/arduino-pico). + +10. **WT32_ETH01 boards** using ESP32-based boards and LAN8720 Ethernet + +11. **Portenta_H7** using either `Murata WiFi` or `Vision-shield Ethernet` + +--- + +#### Currently supported WiFi shields/modules + +1. WiFiNINA using [`WiFiNINA_Generic library`](https://github.com/khoih-prog/WiFiNINA_Generic) +2. WiFi101 using [`WiFi101 library v0.16.1+`](https://github.com/arduino-libraries/WiFi101) +3. U-Blox W101, W102 using [`WiFiNINA_Generic library`](https://github.com/khoih-prog/WiFiNINA_Generic) +4. ESP8266-AT command using [`WiFiEspAT library`](https://github.com/jandrassy/WiFiEspAT) +5. ESP8266/ESP32-AT command using [`ESP_AT_Lib library`](https://github.com/khoih-prog/ESP_AT_Lib) and [`ESP8266_AT_WebServer`](ESP8266_AT_WebServer) +6. ESP32 and ESP8266 WiFi +7. **Portenta_H7 built-in Murata WiFi** + +--- + +#### Currently supported Ethernet shields/modules + +1. W5x00 using [`Ethernet`](https://www.arduino.cc/en/Reference/Ethernet), [`EthernetLarge`](https://github.com/OPEnSLab-OSU/EthernetLarge), [`Ethernet2`](https://github.com/adafruit/Ethernet2) or [`Ethernet3`](https://github.com/sstaub/Ethernet3) library +2. ENC28J60 using [`EthernetENC`](https://github.com/jandrassy/EthernetENC) or [`UIPEthernet`](https://github.com/UIPEthernet/UIPEthernet) library +3. LAN8720 Ethernet used in WT32_ETH01 (ESP32 + LAN8720) boards +4. Teensy 4.1 built-in Ethernet using [`NativeEthernet`](https://github.com/vjmuzik/NativeEthernet) library +5. Teensy 4.1 built-in Ethernet using [`QNEthernet`](https://github.com/ssilverman/QNEthernet) library +6. Portenta_H7 using Ethernet from [Portenta Vision shields](https://store-usa.arduino.cc/products/arduino-portenta-vision-shield-ethernet) + +

+ +

+ + +--- +--- + + +## Prerequisites + + 1. [`Arduino IDE 1.8.19+` for Arduino](https://github.com/arduino/Arduino). [![GitHub release](https://img.shields.io/github/release/arduino/Arduino.svg)](https://github.com/arduino/Arduino/releases/latest) + 2. [`Arduino AVR core 1.8.5+`](https://github.com/arduino/ArduinoCore-avr) for Arduino (Use Arduino Board Manager) AVR boards. [![GitHub release](https://img.shields.io/github/release/arduino/ArduinoCore-avr.svg)](https://github.com/arduino/ArduinoCore-avr/releases/latest) + 3. [`Teensy core v1.56+`](https://www.pjrc.com/teensy/td_download.html) for Teensy (4.1, 4.0, 3.6, 3.5, 3,2, 3.1, 3.0) boards. + 4. [`Arduino SAM DUE core v1.6.12+`](https://github.com/arduino/ArduinoCore-sam) for SAM DUE ARM Cortex-M3 boards. + 5. [`Arduino SAMD core 1.8.12+`](https://github.com/arduino/ArduinoCore-samd) for SAMD ARM Cortex-M0+ boards. [![GitHub release](https://img.shields.io/github/release/arduino/ArduinoCore-samd.svg)](https://github.com/arduino/ArduinoCore-samd/releases/latest) + 6. [`Adafruit SAMD core 1.7.10+`](https://github.com/adafruit/ArduinoCore-samd) for SAMD ARM Cortex-M0+ and M4 boards (Nano 33 IoT, etc.). [![GitHub release](https://img.shields.io/github/release/adafruit/ArduinoCore-samd.svg)](https://github.com/adafruit/ArduinoCore-samd/releases/latest) + 7. [`Seeeduino SAMD core 1.8.2+`](https://github.com/Seeed-Studio/ArduinoCore-samd) for SAMD21/SAMD51 boards (XIAO M0, Wio Terminal, etc.). [![Latest release](https://img.shields.io/github/release/Seeed-Studio/ArduinoCore-samd.svg)](https://github.com/Seeed-Studio/ArduinoCore-samd/releases/latest/) + 8. [`Adafruit nRF52 v1.3.0+`](https://github.com/adafruit/Adafruit_nRF52_Arduino) for nRF52 boards such as Adafruit NRF52840_FEATHER, NRF52832_FEATHER, NRF52840_FEATHER_SENSE, NRF52840_ITSYBITSY, NRF52840_CIRCUITPLAY, NRF52840_CLUE, NRF52840_METRO, NRF52840_PCA10056, PARTICLE_XENON, **NINA_B302_ublox**, etc. [![GitHub release](https://img.shields.io/github/release/adafruit/Adafruit_nRF52_Arduino.svg)](https://github.com/adafruit/Adafruit_nRF52_Arduino/releases/latest) + 9. [`ESP32 Core 2.0.2+`](https://github.com/espressif/arduino-esp32) for ESP32-based boards. [![Latest release](https://img.shields.io/github/release/espressif/arduino-esp32.svg)](https://github.com/espressif/arduino-esp32/releases/latest/) +10. [`ESP8266 Core 3.0.2+`](https://github.com/esp8266/Arduino) for ESP8266-based boards. [![Latest release](https://img.shields.io/github/release/esp8266/Arduino.svg)](https://github.com/esp8266/Arduino/releases/latest/). To use ESP8266 core 2.7.1+ for LittleFS. +11. [`ArduinoCore-mbed mbed_rp2040, mbed_nano, mbed_portenta core 2.7.2+`](https://github.com/arduino/ArduinoCore-mbed) for Arduino (Use Arduino Board Manager) **Portenta_H7, RP2040-based boards, such as Nano_RP2040_Connect, RASPBERRY_PI_PICO**. [![GitHub release](https://img.shields.io/github/release/arduino/ArduinoCore-mbed.svg)](https://github.com/arduino/ArduinoCore-mbed/releases/latest) +12. [`Earle Philhower's arduino-pico core v1.12.0+`](https://github.com/earlephilhower/arduino-pico) for RP2040-based boards such as **RASPBERRY_PI_PICO, ADAFRUIT_FEATHER_RP2040 and GENERIC_RP2040**, etc. [![GitHub release](https://img.shields.io/github/release/earlephilhower/arduino-pico.svg)](https://github.com/earlephilhower/arduino-pico/releases/latest) +13. [`Arduino Core for STM32 v2.2.0+`](https://github.com/stm32duino/Arduino_Core_STM32) for STM32F/L/H/G/WB/MP1 boards. [![GitHub release](https://img.shields.io/github/release/stm32duino/Arduino_Core_STM32.svg)](https://github.com/stm32duino/Arduino_Core_STM32/releases/latest) +14. [`Arduino AmebaD core 3.1.2+`](https://github.com/ambiot/ambd_arduino) for Realtek RTL8720DN, RTL8722DM and RTL8722CSM. [![GitHub release](https://img.shields.io/github/release/ambiot/ambd_arduino.svg)](https://github.com/ambiot/ambd_arduino/releases/latest) + + +15. [`WiFiNINA_Generic library v1.8.14-3+`](https://github.com/khoih-prog/WiFiNINA_Generic) if for WiFiNINA. To install. check [![arduino-library-badge](https://www.ardu-badge.com/badge/WiFiNINA_Generic.svg?)](https://www.ardu-badge.com/WiFiNINA_Generic). +16. [`EthernetWebServer library v2.0.0+`](https://github.com/khoih-prog/EthernetWebServer) if necessary to use Ethernet modules/shields. To install, check [![arduino-library-badge](https://www.ardu-badge.com/badge/EthernetWebServer.svg?)](https://www.ardu-badge.com/EthernetWebServer) +17. [`EthernetWebServer_STM32 library v1.3.3+`](https://github.com/khoih-prog/EthernetWebServer_STM32) if necessary to use Ethernet modules/shields. To install, check [![arduino-library-badge](https://www.ardu-badge.com/badge/EthernetWebServer_STM32.svg?)](https://www.ardu-badge.com/EthernetWebServer_STM32) +18. [`WebServer_WT32_ETH01 library v1.4.1+`](https://github.com/khoih-prog/WebServer_WT32_ETH01) if necessary to use WT32_ETH01 boards. To install, check [![arduino-library-badge](https://www.ardu-badge.com/badge/WebServer_WT32_ETH01.svg?)](https://www.ardu-badge.com/WebServer_WT32_ETH01) +19. Depending on which Ethernet card you're using: + - [`Ethernet library v2.0.0+`](https://github.com/arduino-libraries/Ethernet) for W5100, W5200 and W5500. [![GitHub release](https://img.shields.io/github/release/arduino-libraries/Ethernet.svg)](https://github.com/arduino-libraries/Ethernet/releases/latest). You can also use the forked and modified library at [Patched Ethernet](https://github.com/khoih-prog/Ethernet) + - [`EthernetLarge library v2.0.0+`](https://github.com/OPEnSLab-OSU/EthernetLarge) for W5100, W5200 and W5500. You can also use the forked and modified library at [Patched EthernetLarge](https://github.com/khoih-prog/EthernetLarge) + - [`Ethernet2 library v1.0.4+`](https://github.com/khoih-prog/Ethernet2) for W5500. [![GitHub release](https://img.shields.io/github/release/adafruit/Ethernet2.svg)](https://github.com/adafruit/Ethernet2/releases/latest). You can also use the forked and modified library at [Patched Ethernet2](https://github.com/khoih-prog/Ethernet2) + - [`Ethernet3 library v1.5.5+`](https://github.com/sstaub/Ethernet3) for W5500/WIZ550io/WIZ850io/USR-ES1 with Wiznet W5500 chip. [![GitHub release](https://img.shields.io/github/release/sstaub/Ethernet3.svg)](https://github.com/sstaub/Ethernet3/releases/latest). You can also use the forked and modified library at [Patched Ethernet3](https://github.com/khoih-prog/Ethernet3) + - [`EthernetENC library v2.0.2+`](https://github.com/jandrassy/EthernetENC) for ENC28J60. [![GitHub release](https://img.shields.io/github/release/jandrassy/EthernetENC.svg)](https://github.com/jandrassy/EthernetENC/releases/latest). **New and Better** + - [`UIPEthernet library v2.0.11+`](https://github.com/UIPEthernet/UIPEthernet) for ENC28J60. [![GitHub release](https://img.shields.io/github/release/UIPEthernet/UIPEthernet.svg)](https://github.com/UIPEthernet/UIPEthernet/releases/latest) + - [`STM32Ethernet library v1.2.0+`](https://github.com/stm32duino/STM32Ethernet) for built-in LAN8742A Ethernet on (Nucleo-144, Discovery). [![GitHub release](https://img.shields.io/github/release/stm32duino/STM32Ethernet.svg)](https://github.com/stm32duino/STM32Ethernet/releases/latest). To be used with [`LwIP library v2.1.2+`](https://github.com/stm32duino/LwIP). [![GitHub release](https://img.shields.io/github/release/stm32duino/LwIP.svg)](https://github.com/stm32duino/LwIP/releases/latest). + - [`NativeEthernet Library version stable111+`](https://github.com/vjmuzik/NativeEthernet) for Teensy 4.1 built-in Ethernet. + - [`QNEthernet Library version v0.13.0+`](https://github.com/ssilverman/QNEthernet) Teensy 4.1 built-in Ethernet. **New** + +20. [`WiFiWebServer library v1.6.1+`](https://github.com/khoih-prog/WiFiWebServer) if necessary to use certain WiFi/WiFiNINA features. To install, check [![arduino-library-badge](https://www.ardu-badge.com/badge/WiFiWebServer.svg?)](https://www.ardu-badge.com/WiFiWebServer) +21. [`FlashStorage_SAMD library v1.3.2+`](https://github.com/khoih-prog/FlashStorage_SAMD) for SAMD21 and SAMD51 boards (ZERO, MKR, NANO_33_IOT, M0, M0 Pro, AdaFruit Itsy-Bitsy M4, etc.) if necessary to use certain features. [![GitHub release](https://img.shields.io/github/release/khoih-prog/FlashStorage_SAMD.svg)](https://github.com/khoih-prog/FlashStorage_SAMD/releases/latest) +22. [`FlashStorage_STM32 library v1.2.0+`](https://github.com/khoih-prog/FlashStorage_STM32) for STM32F/L/H/G/WB/MP1 boards. [![GitHub release](https://img.shields.io/github/release/khoih-prog/FlashStorage_STM32.svg)](https://github.com/khoih-prog/FlashStorage_STM32/releases/latest) if necessary to use certain features. +23. [`DueFlashStorage library v1.0.0+`](https://github.com/sebnil/DueFlashStorage) for SAM DUE if necessary to use certain features. To install, check [![arduino-library-badge](https://www.ardu-badge.com/badge/DueFlashStorage.svg?)](https://www.ardu-badge.com/DueFlashStorage). +24. [`Adafruit's LittleFS/InternalFS`](https://www.adafruit.com) for nRF52. Already included if you already installed Adafruit **nRF52 board package** from Boards Manager. +25. [`DoubleResetDetector_Generic v1.8.0+`](https://github.com/khoih-prog/DoubleResetDetector_Generic) if necessary to use some examples. To install. check [![arduino-library-badge](https://www.ardu-badge.com/badge/DoubleResetDetector_Generic.svg?)](https://www.ardu-badge.com/DoubleResetDetector_Generic) if necessary to use certain features. +26. [`Modified WiFi101 Library v0.16.1+`](https://github.com/khoih-prog/WiFi101) to use SAMD MKR1000, etc. boards with WiFi101. +27. [`SinricPro_Generic v2.8.4+`](https://github.com/khoih-prog/SinricPro_Generic) if necessary to use some examples. To install. check [![arduino-library-badge](https://www.ardu-badge.com/badge/SinricPro_Generic.svg?)](https://www.ardu-badge.com/SinricPro_Generic) if necessary to use certain features. + + +--- +--- + +## Installation + +### Use Arduino Library Manager + +The best and easiest way is to use `Arduino Library Manager`. Search for [**WebSockets_Generic**](https://github.com/khoih-prog/WebSockets_Generic), then select / install the latest version. +You can also use this link [![arduino-library-badge](https://www.ardu-badge.com/badge/WebSockets_Generic.svg?)](https://www.ardu-badge.com/WebSockets_Generic) for more detailed instructions. + +### Manual Install + +Another way to install is to: + +1. Navigate to [**WebSockets_Generic**](https://github.com/khoih-prog/WebSockets_Generic) page. +2. Download the latest release `WebSockets_Generic-master.zip`. +3. Extract the zip file to `WebSockets_Generic-master` directory +4. Copy whole `WebSockets_Generic-master` folder to Arduino libraries' directory such as `~/Arduino/libraries/`. + +### VS Code & PlatformIO: + +1. Install [VS Code](https://code.visualstudio.com/) +2. Install [PlatformIO](https://platformio.org/platformio-ide) +3. Install [**WebSockets_Generic** library](https://registry.platformio.org/libraries/khoih-prog/WebSockets_Generic) by using [**Library Manager**](https://registry.platformio.org/libraries/khoih-prog/WebSockets_Generic/installation). Search for [**WebSockets_Generic**](https://platformio.org/lib/show/11283/WebSockets_Generic) in [Platform.io Author's Libraries](https://platformio.org/lib/search?query=author:%22Khoi%20Hoang%22) +4. Use included [platformio.ini](platformio/platformio.ini) file from examples to ensure that all dependent libraries will installed automatically. Please visit documentation for the other options and examples at [Project Configuration File](https://docs.platformio.org/page/projectconf.html) + +--- +--- + +### Packages' Patches + +#### 1. For Adafruit nRF52840 and nRF52832 boards + +**To be able to compile, run and automatically detect and display BOARD_NAME on nRF52840/nRF52832 boards**, you have to copy the whole [nRF52 Packages_Patches](Packages_Patches/adafruit/hardware/nrf52/1.3.0) directory into Adafruit nRF52 directory (~/.arduino15/packages/adafruit/hardware/nrf52/1.3.0). + +Supposing the Adafruit nRF52 version is 1.3.0. These files must be copied into the directory: +- `~/.arduino15/packages/adafruit/hardware/nrf52/1.3.0/platform.txt` +- `~/.arduino15/packages/adafruit/hardware/nrf52/1.3.0/boards.txt` +- `~/.arduino15/packages/adafruit/hardware/nrf52/1.3.0/cores/nRF5/Udp.h` +- `~/.arduino15/packages/adafruit/hardware/nrf52/1.3.0/cores/nRF5/Print.h` +- `~/.arduino15/packages/adafruit/hardware/nrf52/1.3.0/cores/nRF5/Print.cpp` +- `~/.arduino15/packages/adafruit/hardware/nrf52/1.3.0/variants/NINA_B302_ublox/variant.h` +- `~/.arduino15/packages/adafruit/hardware/nrf52/1.3.0/variants/NINA_B302_ublox/variant.cpp` +- `~/.arduino15/packages/adafruit/hardware/nrf52/1.3.0/variants/NINA_B112_ublox/variant.h` +- `~/.arduino15/packages/adafruit/hardware/nrf52/1.3.0/variants/NINA_B112_ublox/variant.cpp` +- **`~/.arduino15/packages/adafruit/hardware/nrf52/1.3.0/cores/nRF5/Udp.h`** + +Whenever a new version is installed, remember to copy these files into the new version directory. For example, new version is x.yy.z +These files must be copied into the directory: + +- `~/.arduino15/packages/adafruit/hardware/nrf52/x.yy.z/platform.txt` +- `~/.arduino15/packages/adafruit/hardware/nrf52/x.yy.z/boards.txt` +- `~/.arduino15/packages/adafruit/hardware/nrf52/x.yy.z/cores/nRF5/Udp.h` +- `~/.arduino15/packages/adafruit/hardware/nrf52/x.yy.z/cores/nRF5/Print.h` +- `~/.arduino15/packages/adafruit/hardware/nrf52/x.yy.z/cores/nRF5/Print.cpp` +- `~/.arduino15/packages/adafruit/hardware/nrf52/x.yy.z/variants/NINA_B302_ublox/variant.h` +- `~/.arduino15/packages/adafruit/hardware/nrf52/x.yy.z/variants/NINA_B302_ublox/variant.cpp` +- `~/.arduino15/packages/adafruit/hardware/nrf52/x.yy.z/variants/NINA_B112_ublox/variant.h` +- `~/.arduino15/packages/adafruit/hardware/nrf52/x.yy.z/variants/NINA_B112_ublox/variant.cpp` +- **`~/.arduino15/packages/adafruit/hardware/nrf52/x.yy.z/cores/nRF5/Udp.h`** + +#### 2. For Teensy boards + + **To be able to compile and run on Teensy boards**, you have to copy the files in [**Packages_Patches for Teensy directory**](Packages_Patches/hardware/teensy/avr) into Teensy hardware directory (./arduino-1.8.19/hardware/teensy/avr/boards.txt). + +Supposing the Arduino version is 1.8.19. These files must be copied into the directory: + +- `./arduino-1.8.19/hardware/teensy/avr/boards.txt` +- `./arduino-1.8.19/hardware/teensy/avr/cores/teensy/Stream.h` +- `./arduino-1.8.19/hardware/teensy/avr/cores/teensy3/Stream.h` +- `./arduino-1.8.19/hardware/teensy/avr/cores/teensy4/Stream.h` + +Whenever a new version is installed, remember to copy this file into the new version directory. For example, new version is x.yy.zz +These files must be copied into the directory: + +- `./arduino-x.yy.zz/hardware/teensy/avr/boards.txt` +- `./arduino-x.yy.zz/hardware/teensy/avr/cores/teensy/Stream.h` +- `./arduino-x.yy.zz/hardware/teensy/avr/cores/teensy3/Stream.h` +- `./arduino-x.yy.zz/hardware/teensy/avr/cores/teensy4/Stream.h` + +#### 3. For Arduino SAM DUE boards + + **To be able to compile and run on SAM DUE boards**, you have to copy the whole [SAM DUE](Packages_Patches/arduino/hardware/sam/1.6.12) directory into Arduino sam directory (~/.arduino15/packages/arduino/hardware/sam/1.6.12). + +Supposing the Arduino SAM core version is 1.6.12. This file must be copied into the directory: + +- `~/.arduino15/packages/arduino/hardware/sam/1.6.12/platform.txt` + +Whenever a new version is installed, remember to copy this file into the new version directory. For example, new version is x.yy.zz +This file must be copied into the directory: + +- `~/.arduino15/packages/arduino/hardware/sam/x.yy.zz/platform.txt` + +#### 4. For Arduino SAMD boards + + ***To be able to compile, run and automatically detect and display BOARD_NAME on Arduino SAMD (Nano-33-IoT, etc) boards***, you have to copy the whole [Arduino SAMD Packages_Patches](Packages_Patches/arduino/hardware/samd/1.8.12) directory into Arduino SAMD directory (~/.arduino15/packages/arduino/hardware/samd/1.8.12). + +#### For core version v1.8.10+ + +Supposing the Arduino SAMD version is 1.8.12. Now only one file must be copied into the directory: + +- `~/.arduino15/packages/arduino/hardware/samd/1.8.12/platform.txt` + +Whenever a new version is installed, remember to copy this files into the new version directory. For example, new version is x.yy.zz + +This file must be copied into the directory: + +- `~/.arduino15/packages/arduino/hardware/samd/x.yy.zz/platform.txt` + +#### For core version v1.8.9- + +Supposing the Arduino SAMD version is 1.8.9. These files must be copied into the directory: + +- `~/.arduino15/packages/arduino/hardware/samd/1.8.9/platform.txt` +- ***`~/.arduino15/packages/arduino/hardware/samd/1.8.9/cores/arduino/Arduino.h`*** + +Whenever a new version is installed, remember to copy these files into the new version directory. For example, new version is x.yy.z + +These files must be copied into the directory: + +- `~/.arduino15/packages/arduino/hardware/samd/x.yy.z/platform.txt` +- ***`~/.arduino15/packages/arduino/hardware/samd/x.yy.z/cores/arduino/Arduino.h`*** + + This is mandatory to fix the ***notorious Arduino SAMD compiler error***. See [Improve Arduino compatibility with the STL (min and max macro)](https://github.com/arduino/ArduinoCore-samd/pull/399) + +``` + ...\arm-none-eabi\include\c++\7.2.1\bits\stl_algobase.h:243:56: error: macro "min" passed 3 arguments, but takes just 2 + min(const _Tp& __a, const _Tp& __b, _Compare __comp) +``` + +Whenever the above-mentioned compiler error issue is fixed with the new Arduino SAMD release, you don't need to copy the `Arduino.h` file anymore. + +#### 5. For Adafruit SAMD boards + + ***To be able to compile, run and automatically detect and display BOARD_NAME on Adafruit SAMD (Itsy-Bitsy M4, etc) boards***, you have to copy the whole [Adafruit SAMD Packages_Patches](Packages_Patches/adafruit/hardware/samd/1.7.10) directory into Adafruit samd directory (~/.arduino15/packages/adafruit/hardware/samd/1.7.10). + +Supposing the Adafruit SAMD core version is 1.7.10. This file must be copied into the directory: + +- `~/.arduino15/packages/adafruit/hardware/samd/1.7.10/platform.txt` +- `~/.arduino15/packages/adafruit/hardware/samd/1.7.10/cores/arduino/Print.h` +- `~/.arduino15/packages/adafruit/hardware/samd/1.7.10/cores/arduino/Print.cpp` + +Whenever a new version is installed, remember to copy this file into the new version directory. For example, new version is x.yy.zz +This file must be copied into the directory: + +- `~/.arduino15/packages/adafruit/hardware/samd/x.yy.zz/platform.txt` +- `~/.arduino15/packages/adafruit/hardware/samd/x.yy.zz/cores/arduino/Print.h` +- `~/.arduino15/packages/adafruit/hardware/samd/x.yy.zz/cores/arduino/Print.cpp` + +#### 6. For Seeeduino SAMD boards + + ***To be able to compile, run and automatically detect and display BOARD_NAME on Seeeduino SAMD (XIAO M0, Wio Terminal, etc) boards***, you have to copy the whole [Seeeduino SAMD Packages_Patches](Packages_Patches/Seeeduino/hardware/samd/1.8.2) directory into Seeeduino samd directory (~/.arduino15/packages/Seeeduino/hardware/samd/1.8.2). + +Supposing the Seeeduino SAMD core version is 1.8.2. This file must be copied into the directory: + +- `~/.arduino15/packages/Seeeduino/hardware/samd/1.8.2/platform.txt` +- `~/.arduino15/packages/Seeeduino/hardware/samd/1.8.2/cores/arduino/Arduino.h` +- `~/.arduino15/packages/Seeeduino/hardware/samd/1.8.2/cores/arduino/Print.h` +- `~/.arduino15/packages/Seeeduino/hardware/samd/1.8.2/cores/arduino/Print.cpp` + +Whenever a new version is installed, remember to copy this file into the new version directory. For example, new version is x.yy.zz +This file must be copied into the directory: + +- `~/.arduino15/packages/Seeeduino/hardware/samd/x.yy.zz/platform.txt` +- `~/.arduino15/packages/Seeeduino/hardware/samd/x.yy.zz/cores/arduino/Arduino.h` +- `~/.arduino15/packages/Seeeduino/hardware/samd/x.yy.zz/cores/arduino/Print.h` +- `~/.arduino15/packages/Seeeduino/hardware/samd/x.yy.zz/cores/arduino/Print.cpp` + +#### 7. For STM32 boards + +#### 7.1 For STM32 boards to use LAN8720 + +To use LAN8720 on some STM32 boards + +- **Nucleo-144 (F429ZI, NUCLEO_F746NG, NUCLEO_F746ZG, NUCLEO_F756ZG)** +- **Discovery (DISCO_F746NG)** +- **STM32F4 boards (BLACK_F407VE, BLACK_F407VG, BLACK_F407ZE, BLACK_F407ZG, BLACK_F407VE_Mini, DIYMORE_F407VGT, FK407M1)** + +you have to copy the files [stm32f4xx_hal_conf_default.h](Packages_Patches/STM32/hardware/stm32/2.2.0/system/STM32F4xx) and [stm32f7xx_hal_conf_default.h](Packages_Patches/STM32/hardware/stm32/2.2.0/system/STM32F7xx) into STM32 stm32 directory (~/.arduino15/packages/STM32/hardware/stm32/2.2.0/system) to overwrite the old files. + +Supposing the STM32 stm32 core version is 2.2.0. These files must be copied into the directory: + +- `~/.arduino15/packages/STM32/hardware/stm32/2.2.0/system/STM32F4xx/stm32f4xx_hal_conf_default.h` for STM32F4. +- `~/.arduino15/packages/STM32/hardware/stm32/2.2.0/system/STM32F7xx/stm32f7xx_hal_conf_default.h` for Nucleo-144 STM32F7. + +Whenever a new version is installed, remember to copy this file into the new version directory. For example, new version is x.yy.zz, +theses files must be copied into the corresponding directory: + +- `~/.arduino15/packages/STM32/hardware/stm32/x.yy.zz/system/STM32F4xx/stm32f4xx_hal_conf_default.h` +- `~/.arduino15/packages/STM32/hardware/stm32/x.yy.zz/system/STM32F7xx/stm32f7xx_hal_conf_default.h + + +#### 7.2 For STM32 boards to use Serial1 + +**To use Serial1 on some STM32 boards without Serial1 definition (Nucleo-144 NUCLEO_F767ZI, Nucleo-64 NUCLEO_L053R8, etc.) boards**, you have to copy the files [STM32 variant.h](Packages_Patches/STM32/hardware/stm32/2.2.0) into STM32 stm32 directory (~/.arduino15/packages/STM32/hardware/stm32/2.2.0). You have to modify the files corresponding to your boards, this is just an illustration how to do. + +Supposing the STM32 stm32 core version is 2.2.0. These files must be copied into the directory: + +- `~/.arduino15/packages/STM32/hardware/stm32/2.2.0/variants/STM32F7xx/F765Z(G-I)T_F767Z(G-I)T_F777ZIT/NUCLEO_F767ZI/variant.h` for Nucleo-144 NUCLEO_F767ZI. +- `~/.arduino15/packages/STM32/hardware/stm32/2.2.0/variants/STM32L0xx/L052R(6-8)T_L053R(6-8)T_L063R8T/NUCLEO_L053R8/variant.h` for Nucleo-64 NUCLEO_L053R8. + +Whenever a new version is installed, remember to copy this file into the new version directory. For example, new version is x.yy.zz, +theses files must be copied into the corresponding directory: + +- `~/.arduino15/packages/STM32/hardware/stm32/x.yy.zz/variants/STM32F7xx/F765Z(G-I)T_F767Z(G-I)T_F777ZIT/NUCLEO_F767ZI/variant.h` +- `~/.arduino15/packages/STM32/hardware/stm32/x.yy.zz/variants/STM32L0xx/L052R(6-8)T_L053R(6-8)T_L063R8T/NUCLEO_L053R8/variant.h` + +#### 8. For RP2040-based boards using [Earle Philhower arduino-pico core](https://github.com/earlephilhower/arduino-pico) + +#### 8.1 To use BOARD_NAME + + **To be able to automatically detect and display BOARD_NAME on RP2040-based boards (RASPBERRY_PI_PICO, ADAFRUIT_FEATHER_RP2040, GENERIC_RP2040, etc) boards**, you have to copy the file [RP2040 platform.txt](Packages_Patches/rp2040/hardware/rp2040/1.4.0) into rp2040 directory (~/.arduino15/packages/rp2040/hardware/rp2040/1.4.0). + +Supposing the rp2040 core version is 1.4.0. This file must be copied into the directory: + +- `~/.arduino15/packages/rp2040/hardware/rp2040/1.4.0/platform.txt` + +Whenever a new version is installed, remember to copy this file into the new version directory. For example, new version is x.yy.zz +This file must be copied into the directory: + +- `~/.arduino15/packages/rp2040/hardware/rp2040/x.yy.zz/platform.txt` + +With core after v1.5.0, this step is not necessary anymore thanks to the PR [Add -DBOARD_NAME="{build.board}" #136](https://github.com/earlephilhower/arduino-pico/pull/136). + +#### 8.2 To avoid compile error relating to microsecondsToClockCycles + +Some libraries, such as [Adafruit DHT-sensor-library](https://github.com/adafruit/DHT-sensor-library), require the definition of microsecondsToClockCycles(). **To be able to compile and run on RP2040-based boards**, you have to copy the files in [**RP2040 Arduino.h**](Packages_Patches/rp2040/hardware/rp2040/1.4.0/cores/rp2040/Arduino.h) into rp2040 directory (~/.arduino15/packages/rp2040/hardware/rp2040/1.4.0). + +Supposing the rp2040 core version is 1.4.0. This file must be copied to replace: + +- `~/.arduino15/packages/rp2040/hardware/rp2040/1.4.0/cores/rp2040/Arduino.h` + +Whenever a new version is installed, remember to copy this file into the new version directory. For example, new version is x.yy.zz +This file must be copied to replace: + +- `~/.arduino15/packages/rp2040/hardware/rp2040/x.yy.zz/cores/rp2040/Arduino.h` + +With core after v1.5.0, this step is not necessary anymore thanks to the PR [Add defs for compatibility #142](https://github.com/earlephilhower/arduino-pico/pull/142). + + +#### 9. For Portenta_H7 boards using Arduino IDE in Linux + + **To be able to upload firmware to Portenta_H7 using Arduino IDE in Linux (Ubuntu, etc.)**, you have to copy the file [portenta_post_install.sh](Packages_Patches/arduino/hardware/mbed_portenta/2.7.2/portenta_post_install.sh) into mbed_portenta directory (~/.arduino15/packages/arduino/hardware/mbed_portenta/2.7.2/portenta_post_install.sh). + + Then run the following command using `sudo` + +``` +$ cd ~/.arduino15/packages/arduino/hardware/mbed_portenta/2.7.2 +$ chmod 755 portenta_post_install.sh +$ sudo ./portenta_post_install.sh +``` + +This will create the file `/etc/udev/rules.d/49-portenta_h7.rules` as follows: + +``` +# Portenta H7 bootloader mode UDEV rules + +SUBSYSTEMS=="usb", ATTRS{idVendor}=="2341", ATTRS{idProduct}=="035b", GROUP="plugdev", MODE="0666" +``` + +Supposing the ArduinoCore-mbed core version is 2.7.2. Now only one file must be copied into the directory: + +- `~/.arduino15/packages/arduino/hardware/mbed_portenta/2.7.2/portenta_post_install.sh` + +Whenever a new version is installed, remember to copy this files into the new version directory. For example, new version is x.yy.zz + +This file must be copied into the directory: + +- `~/.arduino15/packages/arduino/hardware/mbed_portenta/x.yy.zz/portenta_post_install.sh` + + + +#### 10. For RTL8720DN boards using AmebaD core + + To avoid compile error relating to PROGMEM, you have to copy the file [Realtek AmebaD core pgmspace.h](Packages_Patches/realtek/hardware/AmebaD/3.1.2/cores/arduino/avr/pgmspace.h) into Realtek AmebaD directory (~/.arduino15/packages/realtek/hardware/AmebaD/3.1.2/cores/arduino/avr/pgmspace.h). + +Supposing the Realtek AmebaD core version is 3.1.2. This file must be copied into the directory: + +- `~/.arduino15/packages/realtek/hardware/AmebaD/3.1.2/cores/arduino/avr/pgmspace.h` + +Whenever a new version is installed, remember to copy this file into the new version directory. For example, new version is x.yy.zz +This file must be copied into the directory: + +- `~/.arduino15/packages/realtek/hardware/AmebaD/x.yy.zz/cores/arduino/avr/pgmspace.h` + + +--- +--- + +### Libraries' Patches + +#### 1. For application requiring 2K+ HTML page + +If your application requires 2K+ HTML page, the current [`Ethernet library`](https://www.arduino.cc/en/Reference/Ethernet) must be modified if you are using W5200/W5500 Ethernet shields. W5100 is not supported for 2K+ buffer. If you use boards requiring different CS/SS pin for W5x00 Ethernet shield, for example ESP32, ESP8266, nRF52, etc., you also have to modify the following libraries to be able to specify the CS/SS pin correctly. + +#### 2. For Ethernet library + +To fix [`Ethernet library`](https://www.arduino.cc/en/Reference/Ethernet), just copy these following files into the [`Ethernet library`](https://www.arduino.cc/en/Reference/Ethernet) directory to overwrite the old files: +- [Ethernet.h](LibraryPatches/Ethernet/src/Ethernet.h) +- [Ethernet.cpp](LibraryPatches/Ethernet/src/Ethernet.cpp) +- [EthernetServer.cpp](LibraryPatches/Ethernet/src/EthernetServer.cpp) +- [w5100.h](LibraryPatches/Ethernet/src/utility/w5100.h) +- [w5100.cpp](LibraryPatches/Ethernet/src/utility/w5100.cpp) + +You can also use the forked and modified library at [Patched Ethernet](https://github.com/khoih-prog/Ethernet) + +#### 3. For EthernetLarge library + +To fix [`EthernetLarge library`](https://github.com/OPEnSLab-OSU/EthernetLarge), just copy these following files into the [`EthernetLarge library`](https://github.com/OPEnSLab-OSU/EthernetLarge) directory to overwrite the old files: +- [EthernetLarge.h](LibraryPatches/EthernetLarge/src/EthernetLarge.h) +- [EthernetLarge.cpp](LibraryPatches/EthernetLarge/src/EthernetLarge.cpp) +- [EthernetServer.cpp](LibraryPatches/EthernetLarge/src/EthernetServer.cpp) +- [w5100.h](LibraryPatches/EthernetLarge/src/utility/w5100.h) +- [w5100.cpp](LibraryPatches/EthernetLarge/src/utility/w5100.cpp) + +You can also use the forked and modified library at [Patched EthernetLarge](https://github.com/khoih-prog/EthernetLarge) + +#### 4. For Ethernet2 library + +To fix [`Ethernet2 library`](https://github.com/khoih-prog/Ethernet2), just copy these following files into the [`Ethernet2 library`](https://github.com/khoih-prog/Ethernet2) directory to overwrite the old files: + +- [Ethernet2.h](LibraryPatches/Ethernet2/src/Ethernet2.h) +- [Ethernet2.cpp](LibraryPatches/Ethernet2/src/Ethernet2.cpp) + +To add UDP Multicast support, necessary for the [**UPnP_Generic library**](https://github.com/khoih-prog/UPnP_Generic): + +- [EthernetUdp2.h](LibraryPatches/Ethernet2/src/EthernetUdp2.h) +- [EthernetUdp2.cpp](LibraryPatches/Ethernet2/src/EthernetUdp2.cpp) + +You can also use the forked and modified library at [Patched Ethernet2](https://github.com/khoih-prog/Ethernet2) + +#### 5. For Ethernet3 library + +5. To fix [`Ethernet3 library`](https://github.com/sstaub/Ethernet3), just copy these following files into the [`Ethernet3 library`](https://github.com/sstaub/Ethernet3) directory to overwrite the old files: +- [Ethernet3.h](LibraryPatches/Ethernet3/src/Ethernet3.h) +- [Ethernet3.cpp](LibraryPatches/Ethernet3/src/Ethernet3.cpp) + +You can also use the forked and modified library at [Patched Ethernet3](https://github.com/khoih-prog/Ethernet3) + +#### 6. For UIPEthernet library + +***To be able to compile and run on nRF52 boards with ENC28J60 using UIPEthernet library***, you have to copy these following files into the UIPEthernet `utility` directory to overwrite the old files: + +- [UIPEthernet.h](LibraryPatches/UIPEthernet/UIPEthernet.h) +- [UIPEthernet.cpp](LibraryPatches/UIPEthernet/UIPEthernet.cpp) +- [Enc28J60Network.h](LibraryPatches/UIPEthernet/utility/Enc28J60Network.h) +- [Enc28J60Network.cpp](LibraryPatches/UIPEthernet/utility/Enc28J60Network.cpp) + +#### 7. For fixing ESP32 compile error + +To fix [`ESP32 compile error`](https://github.com/espressif/arduino-esp32), just copy the following file into the [`ESP32`](https://github.com/espressif/arduino-esp32) cores/esp32 directory (e.g. ./arduino-1.8.13/hardware/espressif/cores/esp32) to overwrite the old file: +- [Server.h](LibraryPatches/esp32/cores/esp32/Server.h) + +#### 8. For fixing ESP8266 compile error + +To fix `ESP8266 compile error` such as + +``` +error: 'class EthernetClass' has no member named 'init' +Ethernet.init (USE_THIS_SS_PIN); +``` + +just rename the following file in ./arduino-1.8.13/hardware/esp8266com/esp8266/libraries/Ethernet directory + +- From `Ethernet.h` to `Ethernet_ESP8266.h` + +--- +--- + +### HOWTO Use analogRead() with ESP32 running WiFi and/or BlueTooth (BT/BLE) + +Please have a look at [**ESP_WiFiManager Issue 39: Not able to read analog port when using the autoconnect example**](https://github.com/khoih-prog/ESP_WiFiManager/issues/39) to have more detailed description and solution of the issue. + +#### 1. ESP32 has 2 ADCs, named ADC1 and ADC2 + +#### 2. ESP32 ADCs functions + +- ADC1 controls ADC function for pins **GPIO32-GPIO39** +- ADC2 controls ADC function for pins **GPIO0, 2, 4, 12-15, 25-27** + +#### 3.. ESP32 WiFi uses ADC2 for WiFi functions + +Look in file [**adc_common.c**](https://github.com/espressif/esp-idf/blob/master/components/driver/adc_common.c#L61) + +> In ADC2, there're two locks used for different cases: +> 1. lock shared with app and Wi-Fi: +> ESP32: +> When Wi-Fi using the ADC2, we assume it will never stop, so app checks the lock and returns immediately if failed. +> ESP32S2: +> The controller's control over the ADC is determined by the arbiter. There is no need to control by lock. +> +> 2. lock shared between tasks: +> when several tasks sharing the ADC2, we want to guarantee +> all the requests will be handled. +> Since conversions are short (about 31us), app returns the lock very soon, +> we use a spinlock to stand there waiting to do conversions one by one. +> +> adc2_spinlock should be acquired first, then adc2_wifi_lock or rtc_spinlock. + + +- In order to use ADC2 for other functions, we have to **acquire complicated firmware locks and very difficult to do** +- So, it's not advisable to use ADC2 with WiFi/BlueTooth (BT/BLE). +- Use ADC1, and pins GPIO32-GPIO39 +- If somehow it's a must to use those pins serviced by ADC2 (**GPIO0, 2, 4, 12, 13, 14, 15, 25, 26 and 27**), use the **fix mentioned at the end** of [**ESP_WiFiManager Issue 39: Not able to read analog port when using the autoconnect example**](https://github.com/khoih-prog/ESP_WiFiManager/issues/39) to work with ESP32 WiFi/BlueTooth (BT/BLE). + +--- +--- + +### Important Notes + +1. Code is restructured to provide flexibility to make it easy to support many more **WiFi/Ethernet** modules/shields in the future. Please delete the *.cpp files, replaced by *.hpp files, in the src directory, if *.cpp files still exist after installing new version. + +2. For **Adafruit nRF52**, use the SPI's pin as follows: + + - SS/CS = 10 + - SPI_MOSI = MO(SI) + - SPI_MISO = MI(SO) + - SPI_SCK = SCK + +3. For **Adafruit SAMD21/SAMD51**, use the SPI's CS/SS pin as follows: + + - Itsy-Bitsy M0/M4, Feather M0 (Express), Hallowing M0 Express, Zero, Metro M0 => use CS = 16 = pin A2 + - Feather M4 (SAMD51) => use SS/CS = 9 + - Grand Central M4 => use SS/CS = 53 + - Hallowing M4 => use SS/CS = 10 + - Metro M4 AirLift => use SS/CS = 36 + +To know the default CS/SS pins of not listed boards, check the related `variant.h` files in + +`~/.arduino15/packages/adafruit/hardware/samd/x.y.zz/variants/board_name/variant.h` + +4. For **Arduino SAM DUE**, use the SPI's pin as follows: + + - SS/CS = 10 + - SPI_MOSI = 75 ( pin 4 @ [ICSP connector](pics/ICSP_connector.jpg) ) + - SPI_MISO = 74 ( pin 1 @ [ICSP connector](pics/ICSP_connector.jpg) ) + - SPI_SCK = 76 ( pin 3 @ [ICSP connector](pics/ICSP_connector.jpg) ) + +

+ +

+ +--- +--- + +#### Limitations + + - max input length is limited to the ram size and the `WEBSOCKETS_MAX_DATA_SIZE` define + - max output length has no limit (the hardware is the limit) + - Client send big frames with mask 0x00000000 (on AVR all frames) + - continuation frame reassembly need to be handled in the application code + +#### Limitations for Async + + - Functions called from within the context of the websocket event might not honor `yield()` and/or `delay()`. See [this issue](https://github.com/Links2004/arduinoWebSockets/issues/58#issuecomment-192376395) for more info and a potential workaround. + - wss / SSL is not possible. + +--- +--- + +### wss / SS + + supported for: + + - wss client on the ESP8266 + - wss / SSL is not natively supported in WebSocketsServer. However it is possible to achieve secure websockets + by running the device behind an SSL proxy. See [Nginx](examples/Nginx/esp8266.ssl.reverse.proxy.conf) for a + sample Nginx server configuration file to enable this. + +### ESP Async TCP + +This libary can run in Async TCP mode on the ESP. + +The mode can be activated in the [WebSockets_Generic.h](src/WebSockets_Generic.h) (see WEBSOCKETS_NETWORK_TYPE define). + +[ESPAsyncTCP](https://github.com/me-no-dev/ESPAsyncTCP) library is required. + +--- +--- + +### How to use + +In your code, select one of the currently supported network connection from the following list: + + 1. **NETWORK_ESP8266_ASYNC** for ESP8266 Async + 2. **NETWORK_W5100** for W5x00 Ethernet + 3. **NETWORK_ENC28J60** for ENC28J60 Ethernet using UIPEthernet library + 4. **NETWORK_ESP32** for ESP32 WiFi + 5. **NETWORK_ESP32_ETH** for ESP32 Ethernet + 6. **NETWORK_WIFININA** for WiFiNINA + 7. **NETWORK_ETHERNET_ENC** for ENC28J60 Ethernet using EthernetENC library + 8. **NETWORK_RTL8720DN** for NETWORK_RTL8720DN Ethernet using [`Seeed_Arduino_rpcWiFi`](https://github.com/Seeed-Studio/Seeed_Arduino_rpcWiFi) and [`Seeed_Arduino_rpcUnified`](https://github.com/khoih-prog/Seeed_Arduino_rpcUnified) libraries + 9. **NETWORK_NATIVEETHERNET** for Teeensy 4.1 NativeEthernet +10. **NETWORK_LAN8742A** for STM32 with LAN8742A Ethernet using STM32Ethernet library +11. **NETWORK_WIFI101** for SAMD_MKR1000 and SAMD_MKRWIFI1010 using WiFi101 library +12. **NETWORK_QN_ETHERNET** for Teeensy 4.1 built-in Ethernet using [QNEthernet Library](https://github.com/ssilverman/QNEthernet) +13. **NETWORK_PORTENTA_H7_WIFI** for Portenta_H7 using `Murata` WiFi +14. **NETWORK_PORTENTA_H7_ETHERNET** for Portenta_H7 using Vision-shield Ethernet + +then add `#define WEBSOCKETS_NETWORK_TYPE` before `#include ` + +For example: + +``` +#define WEBSOCKETS_NETWORK_TYPE NETWORK_WIFININA + +#include +``` + +### High Level Client API + + - `begin` : Initiate connection sequence to the WebSocket host. + +``` +void begin(const char * host, uint16_t port, const char * url = "/", const char * protocol = "arduino"); +void begin(String host, uint16_t port, String url = "/", String protocol = "arduino"); +void begin(IPAddress host, uint16_t port, const char * url = "/", const char * protocol = "arduino"); + +void begin(IPAddress host, uint16_t port, String url = "/", String protocol = "arduino"); +``` + + - `beginSSL` : Initiate SSL connection sequence to the WebSocket host. + +``` +#if defined(HAS_SSL) +#ifdef SSL_AXTLS + + void beginSSL(const char * host, uint16_t port, const char * url = "/", const char * fingerprint = "", const char * protocol = "arduino"); + void beginSSL(IPAddress host, uint16_t port, String url = "/", String fingerprint = "", String protocol = "arduino"); + void beginSSL(String host, uint16_t port, String url = "/", String fingerprint = "", String protocol = "arduino"); + +#else + + void beginSSL(const char * host, uint16_t port, const char * url = "/", const uint8_t * fingerprint = NULL, const char * protocol = "arduino"); + void beginSSL(IPAddress host, uint16_t port, String url = "/", String fingerprint = "", String protocol = "arduino"); + void beginSslWithCA(const char * host, uint16_t port, const char * url = "/", BearSSL::X509List * CA_cert = NULL, const char * protocol = "arduino"); + +#endif // SSL_AXTLS + + void beginSslWithCA(const char * host, uint16_t port, const char * url = "/", const char * CA_cert = NULL, const char * protocol = "arduino"); + +#endif // HAS_SSL +``` + + - `beginSocketIO` : Initiate connection sequence to the WebSocketIO host. + +``` +void beginSocketIO(const char * host, uint16_t port, const char * url = "/socket.io/?EIO=3", const char * protocol = "arduino"); +void beginSocketIO(String host, uint16_t port, String url = "/socket.io/?EIO=3", String protocol = "arduino"); + +void beginSocketIO(IPAddress host, uint16_t port, String url = "/socket.io/?EIO=3", String protocol = "arduino"); +``` + +--- + + - `onEvent`: Callback to handle for websocket events + +``` +void onEvent(WebSocketClientEvent cbEvent); +``` + + - `WebSocketClientEvent`: Handler for websocket events + +``` +void (*WebSocketClientEvent)(WStype_t type, uint8_t * payload, size_t length) +``` + +Where `WStype_t type` is defined as: + +``` +typedef enum +{ + WStype_ERROR, + WStype_DISCONNECTED, + WStype_CONNECTED, + WStype_TEXT, + WStype_BIN, + WStype_FRAGMENT_TEXT_START, + WStype_FRAGMENT_BIN_START, + WStype_FRAGMENT, + WStype_FRAGMENT_FIN, + WStype_PING, + WStype_PONG, +} WStype_t; +``` + +--- +--- + +### Examples + +#### For Generic boards using W5x00 Ethernet shield + +1. [Generic_WebSocketClientSocketIO_W5500](examples/Generic/W5500/Generic_WebSocketClientSocketIO_W5500) +2. [Generic_WebSocketClientStompOverSockJs_W5500](examples/Generic/W5500/Generic_WebSocketClientStompOverSockJs_W5500) +3. [Generic_WebSocketClientStomp_W5500](examples/Generic/W5500/Generic_WebSocketClientStomp_W5500) +4. [Generic_WebSocketClient_W5500](examples/Generic/W5500/Generic_WebSocketClient_W5500). +5. [Generic_WebSocketServerAllFunctionsDemo_W5500](examples/Generic/W5500/Generic_WebSocketServerAllFunctionsDemo_W5500) +6. [Generic_WebSocketServerFragmentation_W5500](examples/Generic/W5500/Generic_WebSocketServerFragmentation_W5500) +7. [Generic_WebSocketServerHttpHeaderValidation_W5500](examples/Generic/W5500/Generic_WebSocketServerHttpHeaderValidation_W5500) +8. [Generic_WebSocketServer_LEDcontrol_W5500](examples/Generic/W5500/Generic_WebSocketServer_LEDcontrol_W5500) +9. [Generic_WebSocketServer_W5500](examples/Generic/W5500/Generic_WebSocketServer_W5500) + +#### For Generic boards using WiFiNINA + + 1. [Generic_WebSocketClientSocketIO_WiFiNINA](examples/Generic/WiFiNINA/Generic_WebSocketClientSocketIO_WiFiNINA) + 2. [Generic_WebSocketClientStompOverSockJs_WiFiNINA](examples/Generic/WiFiNINA/Generic_WebSocketClientStompOverSockJs_WiFiNINA) + 3. [Generic_WebSocketClientStomp_WiFiNINA](examples/Generic/WiFiNINA/Generic_WebSocketClientStomp_WiFiNINA) + 4. [Generic_WebSocketClient_WiFiNINA](examples/Generic/WiFiNINA/Generic_WebSocketClient_WiFiNINA). + 5. [Generic_WebSocketServerAllFunctionsDemo_WiFiNINA](examples/Generic/WiFiNINA/Generic_WebSocketServerAllFunctionsDemo_WiFiNINA) + 6. [Generic_WebSocketServerFragmentation_WiFiNINA](examples/Generic/WiFiNINA/Generic_WebSocketServerFragmentation_WiFiNINA) + 7. [Generic_WebSocketServerHttpHeaderValidation_WiFiNINA](examples/Generic/WiFiNINA/Generic_WebSocketServerHttpHeaderValidation_WiFiNINA) + 8. [Generic_WebSocketServer_LEDcontrol_WiFiNINA](examples/Generic/WiFiNINA/Generic_WebSocketServer_LEDcontrol_WiFiNINA) + 9. [Generic_WebSocketServer_WiFiNINA](examples/Generic/WiFiNINA/Generic_WebSocketServer_WiFiNINA) +10. [Generic_WebSocketClientSSL_WiFiNINA](examples/Generic/WiFiNINA/Generic_WebSocketClientSSL_WiFiNINA). + +#### For Generic boards using ENC28J60 Ethernet shield and EthernetENC library + +1. [Generic_WebSocketClientSocketIO_EthernetENC](examples/Generic/EthernetENC/Generic_WebSocketClientSocketIO_EthernetENC) +2. [Generic_WebSocketClientStompOverSockJs_EthernetENC](examples/Generic/EthernetENC/Generic_WebSocketClientStompOverSockJs_EthernetENC) +3. [Generic_WebSocketClientStomp_EthernetENC](examples/Generic/EthernetENC/Generic_WebSocketClientStomp_EthernetENC) +4. [Generic_WebSocketClient_EthernetENC](examples/Generic/EthernetENC/Generic_WebSocketClient_EthernetENC). +5. [Generic_WebSocketServerAllFunctionsDemo_EthernetENC](examples/Generic/EthernetENC/Generic_WebSocketServerAllFunctionsDemo_EthernetENC) +6. [Generic_WebSocketServerFragmentation_EthernetENC](examples/Generic/EthernetENC/Generic_WebSocketServerFragmentation_EthernetENC) +7. [Generic_WebSocketServerHttpHeaderValidation_EthernetENC](examples/Generic/EthernetENC/Generic_WebSocketServerHttpHeaderValidation_EthernetENC) +8. [Generic_WebSocketServer_LEDcontrol_EthernetENC](examples/Generic/EthernetENC/Generic_WebSocketServer_LEDcontrol_EthernetENC) +9. [Generic_WebSocketServer_EthernetENC](examples/Generic/EthernetENC/Generic_WebSocketServer_EthernetENC) + +--- + +#### For WiFiNINA + +1. [WebSocketClient_NINA](examples/WiFiNINA/WebSocketClient_NINA). +2. [WebSocketClientSocketIO_NINA](examples/WiFiNINA/WebSocketClientSocketIO_NINA) +3. [WebSocketClientStomp_NINA](examples/WiFiNINA/WebSocketClientStomp_NINA) +4. [WebSocketClientStompOverSockJs_NINA](examples/WiFiNINA/WebSocketClientStompOverSockJs_NINA) +5. [WebSocketClientSSL_NINA](examples/WiFiNINA/WebSocketClientSSL_NINA) +6. [WebSocketClient_Sticky_SocketIO_NINA](examples/WiFiNINA/WebSocketClient_Sticky_SocketIO_NINA). **New** + +--- + +#### For WiFi101 + +1. [WebSocketClient_WiFi101](examples/WiFi101/WebSocketClient_WiFi101). +2. [WebSocketClientSocketIO_WiFi101](examples/WiFi101/WebSocketClientSocketIO_WiFi101) +3. [WebSocketClientStomp_WiFi101](examples/WiFi101/WebSocketClientStomp_WiFi101) +4. [WebSocketClientStompOverSockJs_WiFi101](examples/WiFi101/WebSocketClientStompOverSockJs_WiFi101) +5. [WebSocketClientSSL_WiFi101](examples/WiFi101/WebSocketClientSSL_WiFi101). + +--- + +#### For W5x00 Ethernet shield + +1. [WebSocketClient_W5500](examples/W5500/WebSocketClient_W5500). +2. [WebSocketClientSocketIO_W5500](examples/W5500/WebSocketClientSocketIO_W5500) +3. [WebSocketClientStomp_W5500](examples/W5500/WebSocketClientStomp_W5500) +4. [WebSocketClientStompOverSockJs_W5500](examples/W5500/WebSocketClientStompOverSockJs_W5500) +5. [WebSocketClient_Sticky_SocketIO_W5500](examples/W5500/WebSocketClient_Sticky_SocketIO_W5500). **New** + +--- + +#### For ENC28J60 Ethernet shield using UIPEthernet library + +1. [WebSocketClient_ENC](examples/ENC28J60/WebSocketClient_ENC). +2. [WebSocketClientSocketIO_ENC](examples/ENC28J60/WebSocketClientSocketIO_ENC) +3. [WebSocketClientStomp_ENC](examples/ENC28J60/WebSocketClientStomp_ENC) +4. [WebSocketClientStompOverSockJs_ENC](examples/ENC28J60/WebSocketClientStompOverSockJs_ENC) + +--- + +#### For ESP32 board + +1. [ESP32_WebSocketClient](examples/esp32/ESP32_WebSocketClient) +2. [ESP32_WebSocketClientSocketIO](examples/esp32/ESP32_WebSocketClientSocketIO) **New** +3. [ESP32_WebSocketClientSSL](examples/esp32/ESP32_WebSocketClientSSL) +4. [ESP32_WebSocketServer](examples/esp32/ESP32_WebSocketServer) + +--- + +#### For ESP8266 board + + 1. [ESP8266_WebSocketClient](examples/esp8266/ESP8266_WebSocketClient). + 2. [ESP8266_WebSocketClientSocketIO](examples/esp8266/ESP8266_WebSocketClientSocketIO) + 3. [ESP8266_WebSocketClientSocketIOack](examples/esp8266/ESP8266_WebSocketClientSocketIOack) + 4. [ESP8266_WebSocketClientSSL](examples/esp8266/ESP8266_WebSocketClientSSL). + 5. [ESP8266_WebSocketClientStomp](examples/esp8266/ESP8266_WebSocketClientStomp) + 6. [ESP8266_WebSocketClientStompOverSockJs](examples/esp8266/ESP8266_WebSocketClientStompOverSockJs) + 7. [ESP8266_WebSocketServer](examples/esp8266/ESP8266_WebSocketServer) + 8. [ESP8266_WebSocketServerAllFunctionsDemo](examples/esp8266/ESP8266_WebSocketServerAllFunctionsDemo) + 9. [ESP8266_WebSocketServerFragmentation](examples/esp8266/ESP8266_WebSocketServerFragmentation) +10. [ESP8266_WebSocketServerHttpHeaderValidation](examples/esp8266/ESP8266_WebSocketServerHttpHeaderValidation) +11. [ESP8266_WebSocketServer_LEDcontrol](examples/esp8266/ESP8266_WebSocketServer_LEDcontrol) +12. [ESP8266_WebSocketClient_Sticky_SocketIO](examples/esp8266/ESP8266_WebSocketClient_Sticky_SocketIO). **New** + +--- + +#### For SeeedStudio WIO Terminal using Realtek RTL8720DN WiFi + + 1. [WIOTerminal_WebSocketClient](examples/WIO_Terminal/WIOTerminal_WebSocketClient) + 2. [WIOTerminal_WebSocketClientSSL](examples/WIO_Terminal/WIOTerminal_WebSocketClientSSL). + 3. [WIOTerminal_WebSocketServer](examples/WIO_Terminal/WIOTerminal_WebSocketServer) + +--- + +#### For STM32 boards using built-in LAN8742A Ethernet + +1. [STM32_WebSocketClient_LAN8742A](examples/STM32_LAN8742A/LAN8742A/STM32_WebSocketClient_LAN8742A) +2. [STM32_WebSocketClientSocketIO_LAN8742A](examples/STM32_LAN8742A/LAN8742A/STM32_WebSocketClientSocketIO_LAN8742A) +3. [STM32_WebSocketClientStomp_LAN8742A](examples/STM32_LAN8742A/LAN8742A/STM32_WebSocketClientStomp_LAN8742A) +4. [STM32_WebSocketClientStompOverSockJs_LAN8742A](examples/STM32_LAN8742A/LAN8742A/STM32_WebSocketClientStompOverSockJs_LAN8742A) +5. [STM32_WebSocketServerAllFunctionsDemo_LAN8742A](examples/STM32_LAN8742A/LAN8742A/STM32_WebSocketServerAllFunctionsDemo_LAN8742A) +6. [STM32_WebSocketServerFragmentation_LAN8742A](examples/STM32_LAN8742A/LAN8742A/STM32_WebSocketServerFragmentation_LAN8742A) +7. [STM32_WebSocketServerHttpHeaderValidation_LAN8742A](examples/STM32_LAN8742A/LAN8742A/STM32_WebSocketServerHttpHeaderValidation_LAN8742A) +8. [STM32_WebSocketServer_LAN8742A](examples/STM32_LAN8742A/LAN8742A/STM32_WebSocketServer_LAN8742A) +9. [STM32_WebSocketServer_LEDcontrol_LAN8742A](examples/STM32_LAN8742A/LAN8742A/STM32_WebSocketServer_LEDcontrol_LAN8742A) + +--- + +#### For Teensy boards using ENC28J60 Ethernet shield and EthernetENC library + +1. [Teensy_WebSocketClientSocketIO_EthernetENC](examples/Teensy/EthernetENC/Teensy_WebSocketClientSocketIO_EthernetENC) +2. [Teensy_WebSocketClientStompOverSockJs_EthernetENC](examples/Teensy/EthernetENC/Teensy_WebSocketClientStompOverSockJs_EthernetENC) +3. [Teensy_WebSocketClientStomp_EthernetENC](examples/Teensy/EthernetENC/Teensy_WebSocketClientStomp_EthernetENC) +4. [Teensy_WebSocketClient_EthernetENC](examples/Teensy/EthernetENC/Teensy_WebSocketClient_EthernetENC). +5. [Teensy_WebSocketServerAllFunctionsDemo_EthernetENC](examples/Teensy/EthernetENC/Teensy_WebSocketServerAllFunctionsDemo_EthernetENC) +6. [Teensy_WebSocketServerFragmentation_EthernetENC](examples/Teensy/EthernetENC/Teensy_WebSocketServerFragmentation_EthernetENC) +7. [Teensy_WebSocketServerHttpHeaderValidation_EthernetENC](examples/Teensy/EthernetENC/Teensy_WebSocketServerHttpHeaderValidation_EthernetENC) +8. [Teensy_WebSocketServer_LEDcontrol_EthernetENC](examples/Teensy/EthernetENC/Teensy_WebSocketServer_LEDcontrol_EthernetENC) +9. [Teensy_WebSocketServer_EthernetENC](examples/Teensy/EthernetENC/Teensy_WebSocketServer_EthernetENC) + +#### For Teensy 4.1 boards using NativeEthernet + +1. [Teensy_WebSocketClient_NativeEthernet](examples/Teensy/NativeEthernet/Teensy_WebSocketClient_NativeEthernet) +2. [Teensy_WebSocketClientStompOverSockJs_NativeEthernet](examples/Teensy/NativeEthernet/Teensy_WebSocketClientStompOverSockJs_NativeEthernet) +3. [Teensy_WebSocketClientStomp_NativeEthernet](examples/Teensy/NativeEthernet/Teensy_WebSocketClientStomp_NativeEthernet) +4. [Teensy_WebSocketClient_NativeEthernet](examples/Teensy/NativeEthernet/Teensy_WebSocketClient_NativeEthernet). +5. [Teensy_WebSocketServerAllFunctionsDemo_NativeEthernet](examples/Teensy/NativeEthernet/Teensy_WebSocketServerAllFunctionsDemo_NativeEthernet) +6. [Teensy_WebSocketServerFragmentation_NativeEthernet](examples/Teensy/NativeEthernet/Teensy_WebSocketServerFragmentation_NativeEthernet) +7. [Teensy_WebSocketServerHttpHeaderValidation_NativeEthernet](examples/Teensy/NativeEthernet/Teensy_WebSocketServerHttpHeaderValidation_NativeEthernet) +8. [Teensy_WebSocketServer_LEDcontrol_NativeEthernet](examples/Teensy/NativeEthernet/Teensy_WebSocketServer_LEDcontrol_NativeEthernet) +9. [Teensy_WebSocketServer_NativeEthernet](examples/Teensy/NativeEthernet/Teensy_WebSocketServer_NativeEthernet) + + +#### For Teensy boards using W5x00 Ethernet shield + +1. [Teensy_WebSocketClientSocketIO_W5500](examples/Teensy/W5500/Teensy_WebSocketClientSocketIO_W5500) +2. [Teensy_WebSocketClientStompOverSockJs_W5500](examples/Teensy/W5500/Teensy_WebSocketClientStompOverSockJs_W5500) +3. [Teensy_WebSocketClientStomp_W5500](examples/Teensy/W5500/Teensy_WebSocketClientStomp_W5500) +4. [Teensy_WebSocketClient_W5500](examples/Teensy/W5500/Teensy_WebSocketClient_W5500). +5. [Teensy_WebSocketServerAllFunctionsDemo_W5500](examples/Teensy/W5500/Teensy_WebSocketServerAllFunctionsDemo_W5500) +6. [Teensy_WebSocketServerFragmentation_W5500](examples/Teensy/W5500/Teensy_WebSocketServerFragmentation_W5500) +7. [Teensy_WebSocketServerHttpHeaderValidation_W5500](examples/Teensy/W5500/Teensy_WebSocketServerHttpHeaderValidation_W5500) +8. [Teensy_WebSocketServer_LEDcontrol_W5500](examples/Teensy/W5500/Teensy_WebSocketServer_LEDcontrol_W5500) +9. [Teensy_WebSocketServer_W5500](examples/Teensy/W5500/Teensy_WebSocketServer_W5500) + +#### For Teensy boards using WiFiNINA + + 1. [Teensy_WebSocketClientSocketIO_WiFiNINA](examples/Teensy/WiFiNINA/Teensy_WebSocketClientSocketIO_WiFiNINA) + 2. [Teensy_WebSocketClientStompOverSockJs_WiFiNINA](examples/Teensy/WiFiNINA/Teensy_WebSocketClientStompOverSockJs_WiFiNINA) + 3. [Teensy_WebSocketClientStomp_WiFiNINA](examples/Teensy/WiFiNINA/Teensy_WebSocketClientStomp_WiFiNINA) + 4. [Teensy_WebSocketClient_WiFiNINA](examples/Teensy/WiFiNINA/Teensy_WebSocketClient_WiFiNINA). + 5. [Teensy_WebSocketServerAllFunctionsDemo_WiFiNINA](examples/Teensy/WiFiNINA/Teensy_WebSocketServerAllFunctionsDemo_WiFiNINA) + 6. [Teensy_WebSocketServerFragmentation_WiFiNINA](examples/Teensy/WiFiNINA/Teensy_WebSocketServerFragmentation_WiFiNINA) + 7. [Teensy_WebSocketServerHttpHeaderValidation_WiFiNINA](examples/Teensy/WiFiNINA/Teensy_WebSocketServerHttpHeaderValidation_WiFiNINA) + 8. [Teensy_WebSocketServer_LEDcontrol_WiFiNINA](examples/Teensy/WiFiNINA/Teensy_WebSocketServer_LEDcontrol_WiFiNINA) + 9. [Teensy_WebSocketServer_WiFiNINA](examples/Teensy/WiFiNINA/Teensy_WebSocketServer_WiFiNINA) +10. [Teensy_WebSocketClientSSL_WiFiNINA](examples/Teensy/WiFiNINA/Teensy_WebSocketClientSSL_WiFiNINA). + +#### For Teensy 4.1 boards using QNEthernet + +1. [Teensy_WebSocketClient_QNEthernet](examples/Teensy/QNEthernet/Teensy_WebSocketClient_QNEthernet) +2. [Teensy_WebSocketClientSocketIO_QNEthernet](examples/Teensy/QNEthernet/Teensy_WebSocketClientSocketIO_QNEthernet) +3. [Teensy_WebSocketServerAllFunctionsDemo_QNEthernet](examples/Teensy/QNEthernet/Teensy_WebSocketServerAllFunctionsDemo_QNEthernet) +4. [Teensy_WebSocketServerFragmentation_QNEthernet](examples/Teensy/QNEthernet/Teensy_WebSocketServerFragmentation_QNEthernet) +5. [Teensy_WebSocketServerHttpHeaderValidation_QNEthernet](examples/Teensy/QNEthernet/Teensy_WebSocketServerHttpHeaderValidation_QNEthernet) +6. [Teensy_WebSocketServer_LEDcontrol_QNEthernet](examples/Teensy/QNEthernet/Teensy_WebSocketServer_LEDcontrol_QNEthernet) +7. [Teensy_WebSocketServer_QNEthernet](examples/Teensy/QNEthernet/Teensy_WebSocketServer_QNEthernet) + +--- + +#### Nodejs Socket.IO Test Server to use with examples + +1. [app.js](examples/Nodejs_SocketIO_TestServer/app.js) +2. [SIO_server.sh](examples/Nodejs_SocketIO_TestServer/SIO_server.sh) +3. [HOWTO.md](examples/Nodejs_SocketIO_TestServer/HOWTO.md) +4. [package.json](examples/Nodejs_SocketIO_TestServer/package.json) +5. [package-lock.json](examples/Nodejs_SocketIO_TestServer/package-lock.json) + +--- + +#### Nodejs_Sticky_SocketIO_TestServer to use with examples + +1. [Multi_Sticky_SIO.js](examples/Nodejs_Sticky_SocketIO_TestServer/Multi_Sticky_SIO.js) +2. [Multi_Sticky_SIO_server.sh](examples/Nodejs_Sticky_SocketIO_TestServer/Multi_Sticky_SIO_server.sh) +3. [HOWTO.md](examples/Nodejs_Sticky_SocketIO_TestServer/HOWTO.md) +4. [package.json](examples/Nodejs_Sticky_SocketIO_TestServer/package.json) +5. [package-lock.json](examples/Nodejs_Sticky_SocketIO_TestServer/package-lock.json) + +--- + +#### For WT32_ETH01 board + +1. [WT32_ETH01_WebSocketClient](examples/WT32_ETH01/WT32_ETH01_WebSocketClient). +2. [WT32_ETH01_WebSocketClientSocketIO](examples/WT32_ETH01/WT32_ETH01_WebSocketClientSocketIO) +3. [WT32_ETH01_WebSocketClientSSL](examples/WT32_ETH01/WT32_ETH01_WebSocketClientSSL) +4. [WT32_ETH01_WebSocketServer](examples/WT32_ETH01/WT32_ETH01_WebSocketServer) +5. [WT32_ETH01_WebSocketClient_Sticky_SocketIO](examples/WT32_ETH01/WT32_ETH01_WebSocketClient_Sticky_SocketIO). **New** +6. [WT32_ETH01_SSL_SIO](examples/WT32_ETH01/WT32_ETH01_SSL_SIO). **New** + +--- + + +#### For Portenta_H7 board + +##### Portenta_Ethernet + +1. [Portenta_H7_WebSocketClient](examples/Portenta_H7/Ethernet/Portenta_H7_WebSocketClient). +2. [Portenta_H7_WebSocketClientSocketIO](examples/Portenta_H7/Ethernet/Portenta_H7_WebSocketClientSocketIO) +3. [Portenta_H7_WebSocketClient_Sticky_SocketIO](examples/Portenta_H7/Ethernet/Portenta_H7_WebSocketClient_Sticky_SocketIO). **New** + +##### WiFi + +1. [WebSocketClientSocketIO_WiFi](examples/Portenta_H7/WiFi/WebSocketClientSocketIO_WiFi) +2. [WebSocketClient_WiFi](examples/Portenta_H7/WiFi/WebSocketClient_WiFi) +3. [WebSocketClient_Sticky_SocketIO_WiFi](examples/Portenta_H7/WiFi/WebSocketClient_Sticky_SocketIO_WiFi). **New** + + +--- +--- + +### Example [Generic_WebSocketClient_WiFiNINA](examples/Generic/WiFiNINA/Generic_WebSocketClient_WiFiNINA) + +```cpp +#if ( defined(ARDUINO_SAM_DUE) || defined(__SAM3X8E__) ) + // Default pin 10 to SS/CS + #define USE_THIS_SS_PIN 10 + #define BOARD_TYPE "SAM DUE" +#elif ( defined(CORE_TEENSY) ) + #error You have to use examples written for Teensy +#endif + +#ifndef BOARD_NAME + #define BOARD_NAME BOARD_TYPE +#endif + +#define _WEBSOCKETS_LOGLEVEL_ 2 +#define WEBSOCKETS_NETWORK_TYPE NETWORK_WIFININA + +#include + +WebSocketsClient webSocket; + +#define USE_SSL false + +#if USE_SSL + // Deprecated echo.websocket.org to be replaced + #define WS_SERVER "wss://echo.websocket.org" + #define WS_PORT 443 +#else + // To run a local WebSocket Server + #define WS_SERVER "192.168.2.30" + #define WS_PORT 8080 +#endif + +int status = WL_IDLE_STATUS; + +///////please enter your sensitive data in the Secret tab/arduino_secrets.h + +char ssid[] = "your_ssid"; // your network SSID (name) +char pass[] = "12345678"; // your network password (use for WPA, or use as key for WEP), length must be 8+ + +bool alreadyConnected = false; + +void webSocketEvent(const WStype_t& type, uint8_t * payload, const size_t& length) +{ + switch (type) + { + case WStype_DISCONNECTED: + if (alreadyConnected) + { + Serial.println("[WSc] Disconnected!"); + alreadyConnected = false; + } + + break; + case WStype_CONNECTED: + { + alreadyConnected = true; + + Serial.print("[WSc] Connected to url: "); + Serial.println((char *) payload); + + // send message to server when Connected + webSocket.sendTXT("Connected"); + } + break; + case WStype_TEXT: + Serial.print("[WSc] get text: "); + Serial.println((char *) payload); + + // send message to server + // webSocket.sendTXT("message here"); + break; + case WStype_BIN: + Serial.print("[WSc] get binary length: "); + Serial.println(length); + + // KH, To check + // hexdump(payload, length); + + // send data to server + webSocket.sendBIN(payload, length); + break; + + case WStype_PING: + // pong will be send automatically + Serial.println("[WSc] get ping"); + break; + case WStype_PONG: + // answer to a ping we send + Serial.println("[WSc] get pong"); + break; + + default: + break; + } +} + +void printWifiStatus() +{ + // print the SSID of the network you're attached to: + Serial.print("SSID: "); + Serial.println(WiFi.SSID()); + + // print your board's IP address: + IPAddress ip = WiFi.localIP(); + Serial.print("WebSockets Client @ IP Address: "); + Serial.println(ip); + + // print the received signal strength: + long rssi = WiFi.RSSI(); + Serial.print("signal strength (RSSI):"); + Serial.print(rssi); + Serial.println(" dBm"); +} + +void setup() +{ + // Serial.begin(921600); + Serial.begin(115200); + while (!Serial); + + Serial.print("\nStart Generic_WebSocketClient_WiFiNINA on "); Serial.println(BOARD_NAME); + Serial.println(WEBSOCKETS_GENERIC_VERSION); + + Serial.println("Used/default SPI pinout:"); + Serial.print("MOSI:"); + Serial.println(MOSI); + Serial.print("MISO:"); + Serial.println(MISO); + Serial.print("SCK:"); + Serial.println(SCK); + Serial.print("SS:"); + Serial.println(SS); + + // check for the WiFi module: + if (WiFi.status() == WL_NO_MODULE) + { + Serial.println("Communication with WiFi module failed!"); + // don't continue + while (true); + } + + String fv = WiFi.firmwareVersion(); + if (fv < WIFI_FIRMWARE_LATEST_VERSION) + { + Serial.println("Please upgrade the firmware"); + } + + // attempt to connect to Wifi network: + while (status != WL_CONNECTED) + { + Serial.print("Attempting to connect to SSID: "); + Serial.println(ssid); + // Connect to WPA/WPA2 network. Change this line if using open or WEP network: + status = WiFi.begin(ssid, pass); + + // wait 10 seconds for connection: + //delay(10000); + } + + printWifiStatus(); + + // server address, port and URL + Serial.print("WebSockets Server : "); + Serial.println(WS_SERVER); + + // server address, port and URL +#if USE_SSL + webSocket.beginSSL(WS_SERVER, WS_PORT); +#else + webSocket.begin(WS_SERVER, WS_PORT, "/"); +#endif + + // event handler + webSocket.onEvent(webSocketEvent); + + // use HTTP Basic Authorization this is optional remove if not needed + //webSocket.setAuthorization("user", "Password"); + + // try ever 5000 again if connection has failed + webSocket.setReconnectInterval(5000); + + // start heartbeat (optional) + // ping server every 15000 ms + // expect pong from server within 3000 ms + // consider connection disconnected if pong is not received 2 times + webSocket.enableHeartbeat(15000, 3000, 2); + + // server address, port and URL + Serial.print("Connected to WebSockets Server @ "); + Serial.println(WS_SERVER); +} + +void loop() +{ + webSocket.loop(); +} +``` + +--- +--- + +### Debug Terminal Output Samples + + +#### 1. [Generic_WebSocketClient_EthernetENC](examples/Generic/EthernetENC/Generic_WebSocketClient_EthernetENC) on NRF52840_FEATHER + +``` +Start Generic_WebSocketClient_EthernetENC on NRF52840_FEATHER +WebSockets_Generic v2.14.0 +[WS] Board : NRF52840_FEATHER , setCsPin: 10 +[WS] Default SPI pinout: +[WS] MOSI: 25 +[WS] MISO: 24 +[WS] SCK: 26 +[WS] SS: 5 +[WS] ========================= +WebSockets Client @ IP address: 192.168.2.93 +Connecting to WebSockets Server @ IP address: 192.168.2.140 +[WS] [WS-Client][handleHeader] RX: HTTP/1.1 101 Switching Protocols +[WS] [WS-Client][handleHeader] RX: Server: arduino-WebSocketsServer +[WS] [WS-Client][handleHeader] RX: Upgrade: websocket +[WS] [WS-Client][handleHeader] RX: Connection: Upgrade +[WS] [WS-Client][handleHeader] RX: Sec-WebSocket-Version: 13 +[WS] [WS-Client][handleHeader] RX: Sec-WebSocket-Accept: PJIpSp/QBZPtgaA5LIeNbtWz710= +[WS] [WS-Client][handleHeader] RX: Sec-WebSocket-Protocol: arduino +[WS] [WS-Client][handleHeader] Header read fin. +[WS] [WS-Client][handleHeader] Client settings: +[WS] [WS-Client][handleHeader] - cURL: / +[WS] [WS-Client][handleHeader] - cKey: XAtxzzeVt0HiQZ3cu85Y3A== +[WS] [WS-Client][handleHeader] Server header: +[WS] [WS-Client][handleHeader] - cCode: 101 +[WS] [WS-Client][handleHeader] - cIsUpgrade: 1 +[WS] [WS-Client][handleHeader] - cIsWebsocket: 1 +[WS] [WS-Client][handleHeader] - cAccept: PJIpSp/QBZPtgaA5LIeNbtWz710= +[WS] [WS-Client][handleHeader] - cProtocol: arduino +[WS] [WS-Client][handleHeader] - cExtensions: +[WS] [WS-Client][handleHeader] - cVersion: 13 +[WS] [WS-Client][handleHeader] - cSessionId: +[WSc] Connected to url: / +[WSc] get text: Connected + +``` +--- + +#### 2. [Generic_Ethernet_Blinds](https://github.com/khoih-prog/SinricPro_Generic/tree/master/examples/Generic/Blinds/Generic_Ethernet_Blinds) on NRF52840_FEATHER with ENC28J60 using EthernetENC Library + +You can see the **NRF52840_FEATHER** board, with ENC28J60 using EthernetENC Library, connects to SinricPro service using [**SinricPro_Generic** library](https://github.com/khoih-prog/SinricPro_Generic). + +It also uses this [**WebSockets_Generic** library](https://github.com/khoih-prog/WebSockets_Generic) to communicate with [**SinricPro** service](https://sinric.pro/), to control Blinds via the `Sinric Pro` phone APP + + +``` +Starting Generic_Ethernet_Blinds on NRF52840_FEATHER with ENC28J60 using EthernetENC Library +[SRP] ========================= +[SRP] Default SPI pinout: +[SRP] MOSI: 25 +[SRP] MISO: 24 +[SRP] SCK: 26 +[SRP] SS: 5 +[SRP] ========================= +[SRP] Use default CS/SS pin : 10 +Index = 6 +Connected! +[Ethernet]: IP-Address is 192.168.2.97 +[SRP] Creating new device. No current DeviceId = 123456789012345678901234 +[SRP] add(): Adding DeviceId = 123456789012345678901234 +[SRP] begin(): App-Key = 12345678-1234-1234-1234-123456789012 +[SRP] begin(): App-Secret = 12345678-1234-1234-1234-123456789012-12345678-1234-1234-1234-123456789012 +[SRP] Websocket: Connecting to WebSocket Server: ws.sinric.pro +Websocket: headers: +appkey:12345678-1234-1234-1234-123456789012 +deviceids:123456789012345678901234 +restoredevicestates:false +platform:NRF52840_FEATHER +version:2.8.4 +Connected to SinricPro +[SRP] handleReceiveQueue(): Message(s) in receiveQueue = 1 +[SRP] handleReceiveQueue(): Valid Signature. Processing message... +[SRP] extractTimestamp(): Got Timestamp = 1602031564 +[SRP] handleReceiveQueue(): Message(s) in receiveQueue = 1 +[SRP] handleReceiveQueue(): Valid Signature. Processing message... +[SRP] extractTimestamp(): Got Timestamp = 1602031575 +[SRP] handleRequest(): handling request +{ + "header": { + "payloadVersion": 2, + "signatureVersion": 1 + }, + "payload": { + "action": "setPowerState", + "clientId": "sinricpro-web", + "createdAt": 1602031575, + "deviceAttributes": [], + "deviceId": "123456789012345678901234", + "replyToken": "4a2080b4-ca92-4fb7-aec1-3aa8d108a818", + "type": "request", + "value": { + "state": "Off" + } + }, + "signature": { + "HMAC": "PttsGuF4w4xfwzJHA6C5WDOmQmBgHXv9eTMSg8hYHXM=" + } +} +Device 123456789012345678901234 power turned off +[SRP] handleSendQueue(): Sending Number of Message(s) in sendQueue = 1 +{ + "header": { + "payloadVersion": 2, + "signatureVersion": 1 + }, + "payload": { + "action": "setPowerState", + "clientId": "sinricpro-web", + "createdAt": 1602031575, + "deviceId": "123456789012345678901234", + "message": "OK", + "replyToken": "4a2080b4-ca92-4fb7-aec1-3aa8d108a818", + "success": true, + "type": "response", + "value": { + "state": "Off" + } + }, + "signature": { + "HMAC": "42vn7js8X+KvuHHPZSrGeJt7dtwP8VVl9Y3cZsYtXOA=" + } +} +[SRP] handleSendQueue: Sending to WebSocket +[SRP] handleSendQueue(): Message sent. +[SRP] handleReceiveQueue(): Message(s) in receiveQueue = 1 +[SRP] handleReceiveQueue(): Valid Signature. Processing message... +[SRP] extractTimestamp(): Got Timestamp = 1602031577 +[SRP] handleRequest(): handling request +{ + "header": { + "payloadVersion": 2, + "signatureVersion": 1 + }, + "payload": { + "action": "setPowerState", + "clientId": "sinricpro-web", + "createdAt": 1602031577, + "deviceAttributes": [], + "deviceId": "123456789012345678901234", + "replyToken": "81a2433d-957d-481e-a9f7-2dea5c2e6c78", + "type": "request", + "value": { + "state": "On" + } + }, + "signature": { + "HMAC": "ir18LAhlUVCWHY5hA8QdGY8bzHE/s4XBeX8cwHTaPQI=" + } +} +Device 123456789012345678901234 power turned on +[SRP] handleSendQueue(): Sending Number of Message(s) in sendQueue = 1 +{ + "header": { + "payloadVersion": 2, + "signatureVersion": 1 + }, + "payload": { + "action": "setPowerState", + "clientId": "sinricpro-web", + "createdAt": 1602031577, + "deviceId": "123456789012345678901234", + "message": "OK", + "replyToken": "81a2433d-957d-481e-a9f7-2dea5c2e6c78", + "success": true, + "type": "response", + "value": { + "state": "On" + } + }, + "signature": { + "HMAC": "9Z1uVUjeaCf1T2Ol6Fv4wXkz8gaJvEYmmIRfRcDnOgA=" + } +} +[SRP] handleSendQueue: Sending to WebSocket +[SRP] handleSendQueue(): Message sent. +[SRP] handleReceiveQueue(): Message(s) in receiveQueue = 1 +[SRP] handleReceiveQueue(): Valid Signature. Processing message... +[SRP] extractTimestamp(): Got Timestamp = 1602031578 +[SRP] handleRequest(): handling request +{ + "header": { + "payloadVersion": 2, + "signatureVersion": 1 + }, + "payload": { + "action": "setRangeValue", + "clientId": "sinricpro-web", + "createdAt": 1602031578, + "deviceAttributes": [], + "deviceId": "123456789012345678901234", + "replyToken": "16d6fd59-dfd1-4017-ab51-ff8bb85fc806", + "type": "request", + "value": { + "rangeValue": 100 + } + }, + "signature": { + "HMAC": "KfAwQ6z5XGvoZaspBVBP+CXnryW0YsEILqyxesHDhJo=" + } +} +Device 123456789012345678901234 set position to 100 +[SRP] handleSendQueue(): Sending Number of Message(s) in sendQueue = 1 +{ + "header": { + "payloadVersion": 2, + "signatureVersion": 1 + }, + "payload": { + "action": "setRangeValue", + "clientId": "sinricpro-web", + "createdAt": 1602031578, + "deviceId": "123456789012345678901234", + "message": "OK", + "replyToken": "16d6fd59-dfd1-4017-ab51-ff8bb85fc806", + "success": true, + "type": "response", + "value": { + "rangeValue": 100 + } + }, + "signature": { + "HMAC": "CNYG9Or+ZH+R2S1Ouvd2bqX8lT/8Siu23T8LycZVtTk=" + } +} +[SRP] handleSendQueue: Sending to WebSocket +[SRP] handleSendQueue(): Message sent. +[SRP] handleReceiveQueue(): Message(s) in receiveQueue = 1 +[SRP] handleReceiveQueue(): Valid Signature. Processing message... +[SRP] extractTimestamp(): Got Timestamp = 1602031579 +[SRP] handleRequest(): handling request +{ + "header": { + "payloadVersion": 2, + "signatureVersion": 1 + }, + "payload": { + "action": "setRangeValue", + "clientId": "sinricpro-web", + "createdAt": 1602031579, + "deviceAttributes": [], + "deviceId": "123456789012345678901234", + "replyToken": "864b1a6b-d539-49e0-bad8-48fa27d80d7f", + "type": "request", + "value": { + "rangeValue": 0 + } + }, + "signature": { + "HMAC": "8CsQ57297F9lzrKBopsE8Xga2RdT9pgJpA8moGQFBTs=" + } +} +Device 123456789012345678901234 set position to 0 +[SRP] handleSendQueue(): Sending Number of Message(s) in sendQueue = 1 +{ + "header": { + "payloadVersion": 2, + "signatureVersion": 1 + }, + "payload": { + "action": "setRangeValue", + "clientId": "sinricpro-web", + "createdAt": 1602031579, + "deviceId": "123456789012345678901234", + "message": "OK", + "replyToken": "864b1a6b-d539-49e0-bad8-48fa27d80d7f", + "success": true, + "type": "response", + "value": { + "rangeValue": 0 + } + }, + "signature": { + "HMAC": "AF7bO1deIYIh3VLvVuLaRx6n1ACVYgk2Evl3NgiZ0pg=" + } +} +[SRP] handleSendQueue: Sending to WebSocket +[SRP] handleSendQueue(): Message sent. +``` + +--- + +#### 3. [WebSocketClientSocketIO_W5500](examples/W5500/WebSocketClientSocketIO_W5500) on NRF52840_FEATHER with W5500 using Ethernet2 Library + +``` +Start WebSocketClientSocketIO_W5500 on NRF52840_FEATHER with W5x00 using Ethernet2 Library +WebSockets_Generic v2.14.0 +[WS] Board : NRF52840_FEATHER , setCsPin: 10 +[WS] Default SPI pinout: +[WS] MOSI: 25 +[WS] MISO: 24 +[WS] SCK: 26 +[WS] SS: 5 +[WS] ========================= +WebSockets Client @ IP address: 192.168.2.108 +Connecting to WebSockets Server @ IP address: 192.168.2.30, port: 8080 +["event_name",{"now":6671}] +[WS] [WS-Client][handleHeader] RX: HTTP/1.1 200 OK +[WS] [WS-Client][handleHeader] RX: Content-Type: text/plain; charset=UTF-8 +[WS] [WS-Client][handleHeader] RX: Content-Length: 103 +[WS] [WS-Client][handleHeader] RX: Access-Control-Allow-Credentials: true +[WS] [WS-Client][handleHeader] RX: Access-Control-Allow-Origin: file:// +[WS] [WS-Client][handleHeader] RX: Set-Cookie: io=ivB-kiMefQhNrlkgAAAd; Path=/; HttpOnly; SameSite=Strict +[WS] [WS-Client][handleHeader] RX: Date: Thu, 08 Oct 2020 00:32:59 GMT +[WS] [WS-Client][handleHeader] RX: Connection: keep-alive +[WS] [WS-Client][handleHeader] RX: Keep-Alive: timeout=5 +[WS] [WS-Client][handleHeader] Header read fin. +[WS] [WS-Client][handleHeader] Client settings: +[WS] [WS-Client][handleHeader] - cURL: /socket.io/?EIO=3 +[WS] [WS-Client][handleHeader] - cKey: DT1hYS8BbVNsE++xI7B82A== +[WS] [WS-Client][handleHeader] Server header: +[WS] [WS-Client][handleHeader] - cCode: 200 +[WS] [WS-Client][handleHeader] - cIsUpgrade: 0 +[WS] [WS-Client][handleHeader] - cIsWebsocket: 1 +[WS] [WS-Client][handleHeader] - cAccept: +[WS] [WS-Client][handleHeader] - cProtocol: arduino +[WS] [WS-Client][handleHeader] - cExtensions: +[WS] [WS-Client][handleHeader] - cVersion: 0 +[WS] [WS-Client][handleHeader] - cSessionId: ivB-kiMefQhNrlkgAAAd +[IOc] Disconnected +[WS] [WS-Client][handleHeader] RX: HTTP/1.1 200 OK +[WS] [WS-Client][handleHeader] RX: Content-Type: text/plain; charset=UTF-8 +[WS] [WS-Client][handleHeader] RX: Content-Length: 103 +[WS] [WS-Client][handleHeader] RX: Access-Control-Allow-Credentials: true +[WS] [WS-Client][handleHeader] RX: Access-Control-Allow-Origin: file:// +[WS] [WS-Client][handleHeader] RX: Set-Cookie: io=Lq1IQW-WBtymSZzzAAAe; Path=/; HttpOnly; SameSite=Strict +[WS] [WS-Client][handleHeader] RX: Date: Thu, 08 Oct 2020 00:32:59 GMT +[WS] [WS-Client][handleHeader] RX: Connection: keep-alive +[WS] [WS-Client][handleHeader] RX: Keep-Alive: timeout=5 +[WS] [WS-Client][handleHeader] Header read fin. +[WS] [WS-Client][handleHeader] Client settings: +[WS] [WS-Client][handleHeader] - cURL: /socket.io/?EIO=3 +[WS] [WS-Client][handleHeader] - cKey: onWidNpa6PhedJSy60Az5A== +[WS] [WS-Client][handleHeader] Server header: +[WS] [WS-Client][handleHeader] - cCode: 200 +[WS] [WS-Client][handleHeader] - cIsUpgrade: 0 +[WS] [WS-Client][handleHeader] - cIsWebsocket: 0 +[WS] [WS-Client][handleHeader] - cAccept: +[WS] [WS-Client][handleHeader] - cProtocol: arduino +[WS] [WS-Client][handleHeader] - cExtensions: +[WS] [WS-Client][handleHeader] - cVersion: 0 +[WS] [WS-Client][handleHeader] - cSessionId: Lq1IQW-WBtymSZzzAAAe +[WS] [WS-Client][handleHeader] RX: HTTP/1.1 101 Switching Protocols +[WS] [WS-Client][handleHeader] RX: Upgrade: websocket +[WS] [WS-Client][handleHeader] RX: Connection: Upgrade +[WS] [WS-Client][handleHeader] RX: Sec-WebSocket-Accept: 92pjBGiagarYGjMy1FsUcKOzrSk= +[WS] [WS-Client][handleHeader] RX: Sec-WebSocket-Protocol: arduino +[WS] [WS-Client][handleHeader] Header read fin. +[WS] [WS-Client][handleHeader] Client settings: +[WS] [WS-Client][handleHeader] - cURL: /socket.io/?EIO=3 +[WS] [WS-Client][handleHeader] - cKey: i6rJQeEER2+zCTjRW4OjLg== +[WS] [WS-Client][handleHeader] Server header: +[WS] [WS-Client][handleHeader] - cCode: 101 +[WS] [WS-Client][handleHeader] - cIsUpgrade: 1 +[WS] [WS-Client][handleHeader] - cIsWebsocket: 1 +[WS] [WS-Client][handleHeader] - cAccept: 92pjBGiagarYGjMy1FsUcKOzrSk= +[WS] [WS-Client][handleHeader] - cProtocol: arduino +[WS] [WS-Client][handleHeader] - cExtensions: +[WS] [WS-Client][handleHeader] - cVersion: 0 +[WS] [WS-Client][handleHeader] - cSessionId: Lq1IQW-WBtymSZzzAAAe +[IOc] Connected to url: /socket.io/?EIO=3 +``` + +--- + +#### 4. [Generic_WebSocketClientSocketIO_EthernetENC](examples/Generic/EthernetENC/Generic_WebSocketClientSocketIO_EthernetENC) on NRF52840_FEATHER with ENC28J60 using EthernetENC Library + +``` +Start Generic_WebSocketClientSocketIO_EthernetENC on NRF52840_FEATHER with ENC28J60 using EthernetENC Library +WebSockets_Generic v2.14.0 +[WS] Board : NRF52840_FEATHER , setCsPin: 10 +[WS] Default SPI pinout: +[WS] MOSI: 25 +[WS] MISO: 24 +[WS] SCK: 26 +[WS] SS: 5 +[WS] ========================= +WebSockets Client @ IP address: 192.168.2.86 +Connecting to WebSockets Server @ IP address: 192.168.2.30, port: 8080 +["event_name",{"now":9577}] +[WS] [WS-Client][handleHeader] RX: HTTP/1.1 200 OK +[WS] [WS-Client][handleHeader] RX: Content-Type: text/plain; charset=UTF-8 +[WS] [WS-Client][handleHeader] RX: Content-Length: 103 +[WS] [WS-Client][handleHeader] RX: Access-Control-Allow-Credentials: true +[WS] [WS-Client][handleHeader] RX: Access-Control-Allow-Origin: file:// +[WS] [WS-Client][handleHeader] RX: Set-Cookie: io=W5HMvbfTz5Nbn2SgAAAV; Path=/; HttpOnly; SameSite=Strict +[WS] [WS-Client][handleHeader] RX: Date: Thu, 08 Oct 2020 00:23:11 GMT +[WS] [WS-Client][handleHeader] RX: Connection: keep-alive +[WS] [WS-Client][handleHeader] RX: Keep-Alive: timeout=5 +[WS] [WS-Client][handleHeader] Header read fin. +[WS] [WS-Client][handleHeader] Client settings: +[WS] [WS-Client][handleHeader] - cURL: /socket.io/?EIO=3 +[WS] [WS-Client][handleHeader] - cKey: tTIoy547t0bFK6IwotJ0Ww== +[WS] [WS-Client][handleHeader] Server header: +[WS] [WS-Client][handleHeader] - cCode: 200 +[WS] [WS-Client][handleHeader] - cIsUpgrade: 0 +[WS] [WS-Client][handleHeader] - cIsWebsocket: 1 +[WS] [WS-Client][handleHeader] - cAccept: +[WS] [WS-Client][handleHeader] - cProtocol: arduino +[WS] [WS-Client][handleHeader] - cExtensions: +[WS] [WS-Client][handleHeader] - cVersion: 0 +[WS] [WS-Client][handleHeader] - cSessionId: W5HMvbfTz5Nbn2SgAAAV +[IOc] Disconnected +[WS] [WS-Client][handleHeader] RX: HTTP/1.1 200 OK +[WS] [WS-Client][handleHeader] RX: Content-Type: text/plain; charset=UTF-8 +[WS] [WS-Client][handleHeader] RX: Content-Length: 103 +[WS] [WS-Client][handleHeader] RX: Access-Control-Allow-Credentials: true +[WS] [WS-Client][handleHeader] RX: Access-Control-Allow-Origin: file:// +[WS] [WS-Client][handleHeader] RX: Set-Cookie: io=r1Kx0T7wZNQ9BHk9AAAW; Path=/; HttpOnly; SameSite=Strict +[WS] [WS-Client][handleHeader] RX: Date: Thu, 08 Oct 2020 00:23:11 GMT +[WS] [WS-Client][handleHeader] RX: Connection: keep-alive +[WS] [WS-Client][handleHeader] RX: Keep-Alive: timeout=5 +[WS] [WS-Client][handleHeader] Header read fin. +[WS] [WS-Client][handleHeader] Client settings: +[WS] [WS-Client][handleHeader] - cURL: /socket.io/?EIO=3 +[WS] [WS-Client][handleHeader] - cKey: BgGmlEiRrKzeEDEHHE48qA== +[WS] [WS-Client][handleHeader] Server header: +[WS] [WS-Client][handleHeader] - cCode: 200 +[WS] [WS-Client][handleHeader] - cIsUpgrade: 0 +[WS] [WS-Client][handleHeader] - cIsWebsocket: 0 +[WS] [WS-Client][handleHeader] - cAccept: +[WS] [WS-Client][handleHeader] - cProtocol: arduino +[WS] [WS-Client][handleHeader] - cExtensions: +[WS] [WS-Client][handleHeader] - cVersion: 0 +[WS] [WS-Client][handleHeader] - cSessionId: r1Kx0T7wZNQ9BHk9AAAW +[WS] [WS-Client][handleHeader] RX: HTTP/1.1 101 Switching Protocols +[WS] [WS-Client][handleHeader] RX: Upgrade: websocket +[WS] [WS-Client][handleHeader] RX: Connection: Upgrade +[WS] [WS-Client][handleHeader] RX: Sec-WebSocket-Accept: P76KK/oGpRX1UE1cAtk5jp31+Aw= +[WS] [WS-Client][handleHeader] RX: Sec-WebSocket-Protocol: arduino +[WS] [WS-Client][handleHeader] Header read fin. +[WS] [WS-Client][handleHeader] Client settings: +[WS] [WS-Client][handleHeader] - cURL: /socket.io/?EIO=3 +[WS] [WS-Client][handleHeader] - cKey: 1uSPYGC/Asnl0DfyQcW5NQ== +[WS] [WS-Client][handleHeader] Server header: +[WS] [WS-Client][handleHeader] - cCode: 101 +[WS] [WS-Client][handleHeader] - cIsUpgrade: 1 +[WS] [WS-Client][handleHeader] - cIsWebsocket: 1 +[WS] [WS-Client][handleHeader] - cAccept: P76KK/oGpRX1UE1cAtk5jp31+Aw= +[WS] [WS-Client][handleHeader] - cProtocol: arduino +[WS] [WS-Client][handleHeader] - cExtensions: +[WS] [WS-Client][handleHeader] - cVersion: 0 +[WS] [WS-Client][handleHeader] - cSessionId: r1Kx0T7wZNQ9BHk9AAAW +[IOc] Connected to url: /socket.io/?EIO=3 +``` + +--- + +#### 5. [WIOTerminal_WebSocketClientSSL](examples/WIO_Terminal/WIOTerminal_WebSocketClientSSL) on SeeedStudio SAMD51 WIO_TERMINAL with Realtek RTL8720DN WiFi using Seeed_Arduino_rpcWiFi Library + +``` + +Start WIOTerminal_WebSocketClientSSL on WIO_TERMINAL +WebSockets_Generic v2.14.0 +WebSockets Client started @ IP address: 192.168.2.150 +WebSockets Server : wss://account.duckdns.org +Connected to WebSockets Server @ wss://account.duckdns.org +[WS] [WS-Client] Connect wss... +[WS] [WS-Client] Calling _client.tcp->connect, _host = wss://account.duckdns.org , port = 443 +[WS] [WS-Client] Calling _client.tcp->connect, _connectResult = 1 +[WS] [WS-Client] connectedCb +[WS] [WS-Client][connectedCb] Connected to Host: wss://account.duckdns.org , Port: 443 +[WS] [WS-Client] [sendHeader] Sending header... +[WS] [WS-Client] [sendHeader] Handshake: GET / HTTP/1.1 +Host: wss://account.duckdns.org:443 +Connection: Upgrade +Upgrade: websocket +Sec-WebSocket-Version: 13 +Sec-WebSocket-Key: SfXbpj+U4TexBeIDuBiYog== +Sec-WebSocket-Protocol: arduino +Origin: file:// +User-Agent: arduino-WebSocket-Client + + + +``` + +--- + +#### 6. [Generic_WebSocketClientSSL_WiFiNINA](examples/Generic/WiFiNINA/Generic_WebSocketClientSSL_WiFiNINA) on Arduino SAMD21 Nano-33-IoT with WiFiNINA using WiFiNINA_Generic Library + +``` +Start Generic_WebSocketClientSSL_WiFiNINA on SAMD_NANO_33_IOT +WebSockets_Generic v2.14.0 +Used/default SPI pinout: +MOSI:11 +MISO:12 +SCK:13 +SS:10 +Attempting to connect to SSID: HueNet1 +SSID: HueNet1 +WebSockets Client @ IP Address: 192.168.2.98 +signal strength (RSSI):-13 dBm +WebSockets Server : wss://account.duckdns.org +Connected to WebSockets Server @ wss://account.duckdns.org +[WS] [WS-Client] Connect wss... +[WS] [WS-Client] connectedCb +[WS] [WS-Client][connectedCb] Connected to Host: wss://account.duckdns.org , Port: 443 +[WS] [WS-Client] [sendHeader] Sending header... +[WS] [WS-Client] [sendHeader] Handshake: GET / HTTP/1.1 +Host: wss://account.duckdns.org:443 +Connection: Upgrade +Upgrade: websocket +Sec-WebSocket-Version: 13 +Sec-WebSocket-Key: XOexobdyHBCcAnl9W4F+9w== +Sec-WebSocket-Protocol: arduino +Origin: file:// +User-Agent: arduino-WebSocket-Client + +``` + +--- + +#### 7. [WebSocketClientSocketIO_NINA](examples/WiFiNINA/WebSocketClientSocketIO_NINA) on Arduino SAMD21 Nano-33-IoT with WiFiNINA using WiFiNINA_Generic Library + +#### 7.1 Client + +``` +Start WebSocketClientSocketIO_NINA on SAMD_NANO_33_IOT +WebSockets_Generic v2.14.0 +Used/default SPI pinout: +MOSI:11 +MISO:12 +SCK:13 +SS:10 +Attempting to connect to SSID: HueNet1 +SSID: HueNet1 +WebSockets Client IP Address: 192.168.2.114 +signal strength (RSSI):-18 dBm +Connecting to WebSockets Server @ IP address: 192.168.2.30, port: 8080 +[WS] WebSockets_Generic v2.14.0 +[WS] [wsIOc] found EIO=4 disable EIO ping on client +[WS] [WS-Client] Connect ws... +[WS] [WS-Client][connectedCb] Connected to Host:192.168.2.30, Port:8080 +[WS] [WS-Client] [sendHeader] Sending header... +[WS] sendHeader: client->cKey = 7nb1qwQBvz58aozmAyBmag== +[WS] [WS-Client] [sendHeader] Handshake:GET /socket.io/?EIO=4&transport=polling HTTP/1.1 +Host: 192.168.2.30:8080 +Connection: keep-alive +Origin: file:// +User-Agent: arduino-WebSocket-Client + + +[WS] [WS-Client] [sendHeader] Sending header... Done (us):2669 +[WS] [WS-Client][handleHeader] RX:HTTP/1.1 200 OK +[WS] [WS-Client][handleHeader] RX:Content-Type: text/plain; charset=UTF-8 +[WS] [WS-Client][handleHeader] RX:Content-Length: 97 +[WS] [WS-Client][handleHeader] RX:Date: Mon, 24 May 2021 02:19:53 GMT +[WS] [WS-Client][handleHeader] RX:Connection: keep-alive +[WS] [WS-Client][handleHeader] Header read fin. +[WS] [WS-Client][handleHeader] Client settings: +[WS] [WS-Client][handleHeader] - cURL:/socket.io/?EIO=4 +[WS] [WS-Client][handleHeader] - cKey:7nb1qwQBvz58aozmAyBmag== +[WS] [WS-Client][handleHeader] Server header: +[WS] [WS-Client][handleHeader] - cCode:200 +[WS] [WS-Client][handleHeader] - cIsUpgrade:0 +[WS] [WS-Client][handleHeader] - cIsWebsocket:1 +[WS] [WS-Client][handleHeader] - cAccept: +[WS] [WS-Client][handleHeader] - cProtocol:arduino +[WS] [WS-Client][handleHeader] - cExtensions: +[WS] [WS-Client][handleHeader] - cVersion:0 +[WS] [WS-Client][handleHeader] - cSessionId: +[WS] [WS-Client][handleHeader] Still missing cSessionId try Socket.IO +[WS] [WS-Client][handleHeader] socket.io json: 0{"sid":"WdrsvWrSeNmPDSlFAAAa","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":20000} +[WS] [WS-Client][handleHeader] - cSessionId: WdrsvWrSeNmPDSlFAAAa +[WS] [WS-Client][handleHeader] Header read fin. +[WS] [WS-Client][handleHeader] Client settings: +[WS] [WS-Client][handleHeader] - cURL:/socket.io/?EIO=4 +[WS] [WS-Client][handleHeader] - cKey:7nb1qwQBvz58aozmAyBmag== +[WS] [WS-Client][handleHeader] Server header: +[WS] [WS-Client][handleHeader] - cCode:200 +[WS] [WS-Client][handleHeader] - cIsUpgrade:0 +[WS] [WS-Client][handleHeader] - cIsWebsocket:1 +[WS] [WS-Client][handleHeader] - cAccept: +[WS] [WS-Client][handleHeader] - cProtocol:arduino +[WS] [WS-Client][handleHeader] - cExtensions: +[WS] [WS-Client][handleHeader] - cVersion:0 +[WS] [WS-Client][handleHeader] - cSessionId:WdrsvWrSeNmPDSlFAAAa +[WS] [WS-Client][handleHeader] found cSessionId +[WS] [WS-Client] [sendHeader] Sending header... +[WS] sendHeader: client->cKey = 6b1sIaeSY4sl6HQqSLZaKQ== +[WS] [WS-Client] [sendHeader] Handshake:GET /socket.io/?EIO=4&transport=websocket&sid=WdrsvWrSeNmPDSlFAAAa HTTP/1.1 +Host: 192.168.2.30:8080 +Connection: Upgrade +Upgrade: websocket +Sec-WebSocket-Version: 13 +Sec-WebSocket-Key: 6b1sIaeSY4sl6HQqSLZaKQ== +Sec-WebSocket-Protocol: arduino +Origin: file:// +User-Agent: arduino-WebSocket-Client + + +[WS] [WS-Client] [sendHeader] Sending header... Done (us):3458 +[WS] [WS-Client][handleHeader] RX:HTTP/1.1 101 Switching Protocols +[WS] [WS-Client][handleHeader] RX:Upgrade: websocket +[WS] [WS-Client][handleHeader] RX:Connection: Upgrade +[WS] [WS-Client][handleHeader] RX:Sec-WebSocket-Accept: KJjOfxcGJBEkOTLzz/+pFRXs0Bc= +[WS] [WS-Client][handleHeader] RX:Sec-WebSocket-Protocol: arduino +[WS] [WS-Client][handleHeader] Header read fin. +[WS] [WS-Client][handleHeader] Client settings: +[WS] [WS-Client][handleHeader] - cURL:/socket.io/?EIO=4 +[WS] [WS-Client][handleHeader] - cKey:6b1sIaeSY4sl6HQqSLZaKQ== +[WS] [WS-Client][handleHeader] Server header: +[WS] [WS-Client][handleHeader] - cCode:101 +[WS] [WS-Client][handleHeader] - cIsUpgrade:1 +[WS] [WS-Client][handleHeader] - cIsWebsocket:1 +[WS] [WS-Client][handleHeader] - cAccept:KJjOfxcGJBEkOTLzz/+pFRXs0Bc= +[WS] [WS-Client][handleHeader] - cProtocol:arduino +[WS] [WS-Client][handleHeader] - cExtensions: +[WS] [WS-Client][handleHeader] - cVersion:0 +[WS] [WS-Client][handleHeader] - cSessionId:WdrsvWrSeNmPDSlFAAAa +[WS] [WS-Client][handleHeader] Websocket connection init done. +[WS] [wsIOc] Connected to url:/socket.io/?EIO=4 +[IOc] Connected to url: /socket.io/?EIO=4 +[WS] [wsIOc] get pong +[IOc] Get PONG +[WS] [wsIOc] connected: len = 30 +[WS] [wsIOc] data: {"sid":"QPel_hhsFl5pJ9ZpAAAb"} +["event_name",{"now":30001}] +[WS] [wsIOc] get ping send pong:3 +[IOc] Get PING +[WS] [WS-Client] Sending HB ping +["event_name",{"now":30001}] +``` + +#### 7.2 Server + +Using the Socket.IO Server in [**Nodejs_SocketIO_TestServer**](examples/Nodejs_SocketIO_TestServer) + +``` +kh@kh-Inspiron-3593:~/Downloads/Nodejs/New_SIO$ nodejs app +Server launched on port 8080 +Connected +QPel_hhsFl5pJ9ZpAAAb +JWT token test: { host: '192.168.2.30:8080', + connection: 'keep-alive', + origin: 'file://', + 'user-agent': 'arduino-WebSocket-Client' } +Message from Client : { now: 30001 } + +``` + +--- + +#### 8. [Generic_WebSocketClientSocketIO_W5500](examples/Generic/W5500/Generic_WebSocketClientSocketIO_W5500) on NRF52840_FEATHER with W5x00 using EthernetLarge Library + + +#### 8.1 Client + +``` +Start Generic_WebSocketClientSocketIO_W5500 on NRF52840_FEATHER with W5x00 using EthernetLarge Library +WebSockets_Generic v2.14.0 +[WS] Board :NRF52840_FEATHER, setCsPin:10 +[WS] Default SPI pinout: +[WS] MOSI:25 +[WS] MISO:24 +[WS] SCK:26 +[WS] SS:5 +[WS] ========================= +_pinCS = 0 +W5100 init, using SS_PIN_DEFAULT = 10, new ss_pin = 10, W5100Class::ss_pin = 10 +W5100::init: W5500, SSIZE =8192 +WebSockets Client @ IP address: 192.168.2.94 +Connecting to WebSockets Server @ IP address: 192.168.2.30, port: 8080 +[WS] WebSockets_Generic v2.14.0 +[WS] [wsIOc] found EIO=4 disable EIO ping on client +[WS] [WS-Client][connectedCb] Connected to Host:192.168.2.30, Port:8080 +[WS] [WS-Client] [sendHeader] Sending header... +[WS] sendHeader: client->cKey = A5uXYZ6TvNkcNshB9bd4mw== +[WS] [WS-Client] [sendHeader] Handshake:GET /socket.io/?EIO=4&transport=polling HTTP/1.1 +Host: 192.168.2.30:8080 +Connection: keep-alive +Authorization: 1234567890 +User-Agent: arduino-WebSocket-Client + + +[WS] [WS-Client] [sendHeader] Sending header... Done (us):1953 +[WS] [WS-Client][handleHeader] RX:HTTP/1.1 200 OK +[WS] [WS-Client][handleHeader] RX:Content-Type: text/plain; charset=UTF-8 +[WS] [WS-Client][handleHeader] RX:Content-Length: 97 +[WS] [WS-Client][handleHeader] RX:Date: Mon, 24 May 2021 02:44:22 GMT +[WS] [WS-Client][handleHeader] RX:Connection: keep-alive +[WS] [WS-Client][handleHeader] Header read fin. +[WS] [WS-Client][handleHeader] Client settings: +[WS] [WS-Client][handleHeader] - cURL:/socket.io/?EIO=4 +[WS] [WS-Client][handleHeader] - cKey:A5uXYZ6TvNkcNshB9bd4mw== +[WS] [WS-Client][handleHeader] Server header: +[WS] [WS-Client][handleHeader] - cCode:200 +[WS] [WS-Client][handleHeader] - cIsUpgrade:0 +[WS] [WS-Client][handleHeader] - cIsWebsocket:1 +[WS] [WS-Client][handleHeader] - cAccept: +[WS] [WS-Client][handleHeader] - cProtocol:arduino +[WS] [WS-Client][handleHeader] - cExtensions: +[WS] [WS-Client][handleHeader] - cVersion:0 +[WS] [WS-Client][handleHeader] - cSessionId: +[WS] [WS-Client][handleHeader] Still missing cSessionId try Socket.IO +[WS] [WS-Client][handleHeader] socket.io json: 0{"sid":"NsqUuXlPnVoCSumYAAAc","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":20000} +[WS] [WS-Client][handleHeader] - cSessionId: NsqUuXlPnVoCSumYAAAc +[WS] [WS-Client][handleHeader] Header read fin. +[WS] [WS-Client][handleHeader] Client settings: +[WS] [WS-Client][handleHeader] - cURL:/socket.io/?EIO=4 +[WS] [WS-Client][handleHeader] - cKey:A5uXYZ6TvNkcNshB9bd4mw== +[WS] [WS-Client][handleHeader] Server header: +[WS] [WS-Client][handleHeader] - cCode:200 +[WS] [WS-Client][handleHeader] - cIsUpgrade:0 +[WS] [WS-Client][handleHeader] - cIsWebsocket:1 +[WS] [WS-Client][handleHeader] - cAccept: +[WS] [WS-Client][handleHeader] - cProtocol:arduino +[WS] [WS-Client][handleHeader] - cExtensions: +[WS] [WS-Client][handleHeader] - cVersion:0 +[WS] [WS-Client][handleHeader] - cSessionId:NsqUuXlPnVoCSumYAAAc +[WS] [WS-Client][handleHeader] found cSessionId +[WS] [WS-Client] [sendHeader] Sending header... +[WS] sendHeader: client->cKey = sQfvRYgeBW4Lg9NMIB977g== +[WS] [WS-Client] [sendHeader] Handshake:GET /socket.io/?EIO=4&transport=websocket&sid=NsqUuXlPnVoCSumYAAAc HTTP/1.1 +Host: 192.168.2.30:8080 +Connection: Upgrade +Upgrade: websocket +Sec-WebSocket-Version: 13 +Sec-WebSocket-Key: sQfvRYgeBW4Lg9NMIB977g== +Sec-WebSocket-Protocol: arduino +Authorization: 1234567890 +User-Agent: arduino-WebSocket-Client + + +[WS] [WS-Client] [sendHeader] Sending header... Done (us):3907 +[WS] [WS-Client][handleHeader] RX:HTTP/1.1 101 Switching Protocols +[WS] [WS-Client][handleHeader] RX:Upgrade: websocket +[WS] [WS-Client][handleHeader] RX:Connection: Upgrade +[WS] [WS-Client][handleHeader] RX:Sec-WebSocket-Accept: KSsqUKjgfa1vum+jM9GAEuTogmY= +[WS] [WS-Client][handleHeader] RX:Sec-WebSocket-Protocol: arduino +[WS] [WS-Client][handleHeader] Header read fin. +[WS] [WS-Client][handleHeader] Client settings: +[WS] [WS-Client][handleHeader] - cURL:/socket.io/?EIO=4 +[WS] [WS-Client][handleHeader] - cKey:sQfvRYgeBW4Lg9NMIB977g== +[WS] [WS-Client][handleHeader] Server header: +[WS] [WS-Client][handleHeader] - cCode:101 +[WS] [WS-Client][handleHeader] - cIsUpgrade:1 +[WS] [WS-Client][handleHeader] - cIsWebsocket:1 +[WS] [WS-Client][handleHeader] - cAccept:KSsqUKjgfa1vum+jM9GAEuTogmY= +[WS] [WS-Client][handleHeader] - cProtocol:arduino +[WS] [WS-Client][handleHeader] - cExtensions: +[WS] [WS-Client][handleHeader] - cVersion:0 +[WS] [WS-Client][handleHeader] - cSessionId:NsqUuXlPnVoCSumYAAAc +[WS] [WS-Client][handleHeader] Websocket connection init done. +[WS] [wsIOc] Connected to url:/socket.io/?EIO=4 +[IOc] Connected to url: /socket.io/?EIO=4 +[WS] [wsIOc] get pong +[IOc] Get PONG +[WS] [wsIOc] connected: len = 30 +[WS] [wsIOc] data: {"sid":"cSx3YyFrDOfxUW8hAAAd"} +Message from Client : { now: 30001 } + +``` + +--- + +#### 8.2 Server + +Using the Socket.IO Server in [**Nodejs_SocketIO_TestServer**](examples/Nodejs_SocketIO_TestServer) + +``` +kh@kh-Inspiron-3593:~/Downloads/Nodejs/New_SIO$ nodejs app +Server launched on port 8080 +Connected +cSx3YyFrDOfxUW8hAAAd +JWT token test: { host: '192.168.2.30:8080', + connection: 'keep-alive', + authorization: '1234567890', + 'user-agent': 'arduino-WebSocket-Client' } +Message from Client : { now: 30001 } + +``` + +--- + +#### 9. [WebSocketClientSocketIO_W5500](examples/W5500/WebSocketClientSocketIO_W5500) on RASPBERRY_PI_PICO with W5x00 using Ethernet2 Library + +The following are debug terminal output when running example [WebSocketClientSocketIO_W5500](examples/W5500/WebSocketClientSocketIO_W5500) on RASPBERRY_PI_PICO with W5x00 and Ethernet2 Library using [**Earle Philhower's arduino-pico core** v1.12.0](https://github.com/earlephilhower/arduino-pico) + + +#### 9.1 Client + +``` +Start WebSocketClientSocketIO_W5500 on RASPBERRY_PI_PICO with W5x00 using Ethernet2 Library +WebSockets_Generic v2.14.0 +[WS] Board :RASPBERRY_PI_PICO, setCsPin:17 +[WS] Default SPI pinout: +[WS] MOSI:19 +[WS] MISO:16 +[WS] SCK:18 +[WS] SS:17 +[WS] ========================= +WebSockets Client @ IP address: 192.168.2.119 +Connecting to WebSockets Server @ IP address: 192.168.2.30, port: 8080 +[WS] WebSockets_Generic v2.14.0 +[WS] [wsIOc] found EIO=4 disable EIO ping on client +[WS] [WS-Client][connectedCb] Connected to Host:192.168.2.30, Port:8080 +[WS] [WS-Client] [sendHeader] Sending header... +[WS] sendHeader: client->cKey = rqJZ543MlA+uTo5YdFR+qA== +[WS] [WS-Client] [sendHeader] Handshake:GET /socket.io/?EIO=4&transport=polling HTTP/1.1 +Host: 192.168.2.30:8080 +Connection: keep-alive +Authorization: 1234567890 +User-Agent: arduino-WebSocket-Client + + +[WS] [WS-Client] [sendHeader] Sending header... Done (us):2184 +[WS] [WS-Client][handleHeader] RX:HTTP/1.1 200 OK +[WS] [WS-Client][handleHeader] RX:Content-Type: text/plain; charset=UTF-8 +[WS] [WS-Client][handleHeader] RX:Content-Length: 97 +[WS] [WS-Client][handleHeader] RX:Date: Mon, 24 May 2021 04:29:00 GMT +[WS] [WS-Client][handleHeader] RX:Connection: keep-alive +[WS] [WS-Client][handleHeader] Header read fin. +[WS] [WS-Client][handleHeader] Client settings: +[WS] [WS-Client][handleHeader] - cURL:/socket.io/?EIO=4 +[WS] [WS-Client][handleHeader] - cKey:rqJZ543MlA+uTo5YdFR+qA== +[WS] [WS-Client][handleHeader] Server header: +[WS] [WS-Client][handleHeader] - cCode:200 +[WS] [WS-Client][handleHeader] - cIsUpgrade:0 +[WS] [WS-Client][handleHeader] - cIsWebsocket:1 +[WS] [WS-Client][handleHeader] - cAccept: +[WS] [WS-Client][handleHeader] - cProtocol:arduino +[WS] [WS-Client][handleHeader] - cExtensions: +[WS] [WS-Client][handleHeader] - cVersion:0 +[WS] [WS-Client][handleHeader] - cSessionId: +[WS] [WS-Client][handleHeader] Still missing cSessionId try Socket.IO +[WS] [WS-Client][handleHeader] socket.io json: 0{"sid":"TCiWG1KEq2MHPezpAAAg","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":20000} +[WS] [WS-Client][handleHeader] - cSessionId: TCiWG1KEq2MHPezpAAAg +[WS] [WS-Client][handleHeader] Header read fin. +[WS] [WS-Client][handleHeader] Client settings: +[WS] [WS-Client][handleHeader] - cURL:/socket.io/?EIO=4 +[WS] [WS-Client][handleHeader] - cKey:rqJZ543MlA+uTo5YdFR+qA== +[WS] [WS-Client][handleHeader] Server header: +[WS] [WS-Client][handleHeader] - cCode:200 +[WS] [WS-Client][handleHeader] - cIsUpgrade:0 +[WS] [WS-Client][handleHeader] - cIsWebsocket:1 +[WS] [WS-Client][handleHeader] - cAccept: +[WS] [WS-Client][handleHeader] - cProtocol:arduino +[WS] [WS-Client][handleHeader] - cExtensions: +[WS] [WS-Client][handleHeader] - cVersion:0 +[WS] [WS-Client][handleHeader] - cSessionId:TCiWG1KEq2MHPezpAAAg +[WS] [WS-Client][handleHeader] found cSessionId +[WS] [WS-Client] [sendHeader] Sending header... +[WS] sendHeader: client->cKey = ADdto91YKZwqbZ0X0v5ceg== +[WS] [WS-Client] [sendHeader] Handshake:GET /socket.io/?EIO=4&transport=websocket&sid=TCiWG1KEq2MHPezpAAAg HTTP/1.1 +Host: 192.168.2.30:8080 +Connection: Upgrade +Upgrade: websocket +Sec-WebSocket-Version: 13 +Sec-WebSocket-Key: ADdto91YKZwqbZ0X0v5ceg== +Sec-WebSocket-Protocol: arduino +Authorization: 1234567890 +User-Agent: arduino-WebSocket-Client + + +[WS] [WS-Client] [sendHeader] Sending header... Done (us):2851 +[WS] [WS-Client][handleHeader] RX:HTTP/1.1 101 Switching Protocols +[WS] [WS-Client][handleHeader] RX:Upgrade: websocket +[WS] [WS-Client][handleHeader] RX:Connection: Upgrade +[WS] [WS-Client][handleHeader] RX:Sec-WebSocket-Accept: gKekYE3itucoN6vDWPglIu3GU1U= +[WS] [WS-Client][handleHeader] RX:Sec-WebSocket-Protocol: arduino +[WS] [WS-Client][handleHeader] Header read fin. +[WS] [WS-Client][handleHeader] Client settings: +[WS] [WS-Client][handleHeader] - cURL:/socket.io/?EIO=4 +[WS] [WS-Client][handleHeader] - cKey:ADdto91YKZwqbZ0X0v5ceg== +[WS] [WS-Client][handleHeader] Server header: +[WS] [WS-Client][handleHeader] - cCode:101 +[WS] [WS-Client][handleHeader] - cIsUpgrade:1 +[WS] [WS-Client][handleHeader] - cIsWebsocket:1 +[WS] [WS-Client][handleHeader] - cAccept:gKekYE3itucoN6vDWPglIu3GU1U= +[WS] [WS-Client][handleHeader] - cProtocol:arduino +[WS] [WS-Client][handleHeader] - cExtensions: +[WS] [WS-Client][handleHeader] - cVersion:0 +[WS] [WS-Client][handleHeader] - cSessionId:TCiWG1KEq2MHPezpAAAg +[WS] [WS-Client][handleHeader] Websocket connection init done. +[WS] [wsIOc] Connected to url:/socket.io/?EIO=4 +[IOc] Connected to url: /socket.io/?EIO=4 +[WS] [wsIOc] get pong +[IOc] Get PONG +[WS] [wsIOc] connected: len = 30 +[WS] [wsIOc] data: {"sid":"kcgaqp1ovWXOgjCnAAAh"} +["event_name",{"now":30001}] +[WS] [wsIOc] get ping send pong:3 +[IOc] Get PING +[WS] [WS-Client] Sending HB ping +["event_name",{"now":60002}] +[WS] [wsIOc] get ping send pong:3 +[WS] [wsIOc] get ping send pong:3 +["event_name",{"now":90003}] +[WS] [wsIOc] get ping send pong:3 +[IOc] Get PING +[WS] [WS-Client] Sending HB ping +["event_name",{"now":120004}] +[WS] [wsIOc] get ping send pong:3 +["event_name",{"now":150005}] +[WS] [wsIOc] get ping send pong:3 + +``` + +--- + +#### 9.2 Server + +Using the Socket.IO Server in [**Nodejs_SocketIO_TestServer**](examples/Nodejs_SocketIO_TestServer) + +``` +kh@kh-Inspiron-3593:~/Downloads/Nodejs/New_SIO$ nodejs app +Server launched on port 8080 +Connected +kcgaqp1ovWXOgjCnAAAh +JWT token test: { host: '192.168.2.30:8080', + connection: 'keep-alive', + authorization: '1234567890', + 'user-agent': 'arduino-WebSocket-Client' } +Message from Client : { now: 30001 } +Message from Client : { now: 60002 } +Message from Client : { now: 90003 } +Message from Client : { now: 120004 } +Message from Client : { now: 150005 } + +``` + +--- + +#### 10. [WebSocketClientSocketIO_W5500](examples/W5500/WebSocketClientSocketIO_W5500) on MBED RASPBERRY_PI_PICO with W5x00 using Ethernet2 Library + +The following are debug terminal output when running example [WebSocketClientSocketIO_W5500](examples/W5500/WebSocketClientSocketIO_W5500) on RASPBERRY_PI_PICO with W5x00 and Ethernet2 Library using [**Arduino-mbed RP2040** core v2.7.2](https://github.com/arduino/ArduinoCore-mbed) + + +#### 10.1 Client + +``` +Start WebSocketClientSocketIO_W5500 on RaspberryPi Pico with W5x00 using Ethernet2 Library +WebSockets_Generic v2.14.0 +[WS] Board :RaspberryPi Pico, setCsPin:17 +[WS] Default SPI pinout: +[WS] MOSI:19 +[WS] MISO:16 +[WS] SCK:18 +[WS] SS:17 +[WS] ========================= +WebSockets Client @ IP address: 192.168.2.98 +Connecting to WebSockets Server @ IP address: 192.168.2.30, port: 8080 +[WS] WebSockets_Generic v2.14.0 +[WS] [wsIOc] found EIO=4 disable EIO ping on client +[WS] [WS-Client][connectedCb] Connected to Host:192.168.2.30, Port:8080 +[WS] [WS-Client] [sendHeader] Sending header... +[WS] sendHeader: client->cKey = fDyOMZVB7gvbnhOZclfWcA== +[WS] [WS-Client] [sendHeader] Handshake:GET /socket.io/?EIO=4&transport=polling HTTP/1.1 +Host: 192.168.2.30:8080 +Connection: keep-alive +Authorization: 1234567890 +User-Agent: arduino-WebSocket-Client + + +[WS] [WS-Client] [sendHeader] Sending header... Done (us):3217 +[WS] [WS-Client][handleHeader] RX:HTTP/1.1 200 OK +[WS] [WS-Client][handleHeader] RX:Content-Type: text/plain; charset=UTF-8 +[WS] [WS-Client][handleHeader] RX:Content-Length: 97 +[WS] [WS-Client][handleHeader] RX:Date: Mon, 24 May 2021 04:37:41 GMT +[WS] [WS-Client][handleHeader] RX:Connection: keep-alive +[WS] [WS-Client][handleHeader] Header read fin. +[WS] [WS-Client][handleHeader] Client settings: +[WS] [WS-Client][handleHeader] - cURL:/socket.io/?EIO=4 +[WS] [WS-Client][handleHeader] - cKey:fDyOMZVB7gvbnhOZclfWcA== +[WS] [WS-Client][handleHeader] Server header: +[WS] [WS-Client][handleHeader] - cCode:200 +[WS] [WS-Client][handleHeader] - cIsUpgrade:0 +[WS] [WS-Client][handleHeader] - cIsWebsocket:1 +[WS] [WS-Client][handleHeader] - cAccept: +[WS] [WS-Client][handleHeader] - cProtocol:arduino +[WS] [WS-Client][handleHeader] - cExtensions: +[WS] [WS-Client][handleHeader] - cVersion:0 +[WS] [WS-Client][handleHeader] - cSessionId: +[WS] [WS-Client][handleHeader] Still missing cSessionId try Socket.IO +[WS] [WS-Client][handleHeader] socket.io json: 0{"sid":"7zb9ikut5ezr2H6kAAAi","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":20000} +[WS] [WS-Client][handleHeader] - cSessionId: 7zb9ikut5ezr2H6kAAAi +[WS] [WS-Client][handleHeader] Header read fin. +[WS] [WS-Client][handleHeader] Client settings: +[WS] [WS-Client][handleHeader] - cURL:/socket.io/?EIO=4 +[WS] [WS-Client][handleHeader] - cKey:fDyOMZVB7gvbnhOZclfWcA== +[WS] [WS-Client][handleHeader] Server header: +[WS] [WS-Client][handleHeader] - cCode:200 +[WS] [WS-Client][handleHeader] - cIsUpgrade:0 +[WS] [WS-Client][handleHeader] - cIsWebsocket:1 +[WS] [WS-Client][handleHeader] - cAccept: +[WS] [WS-Client][handleHeader] - cProtocol:arduino +[WS] [WS-Client][handleHeader] - cExtensions: +[WS] [WS-Client][handleHeader] - cVersion:0 +[WS] [WS-Client][handleHeader] - cSessionId:7zb9ikut5ezr2H6kAAAi +[WS] [WS-Client][handleHeader] found cSessionId +[WS] [WS-Client] [sendHeader] Sending header... +[WS] sendHeader: client->cKey = m1MElaS+NSouCUhWjSLPug== +[WS] [WS-Client] [sendHeader] Handshake:GET /socket.io/?EIO=4&transport=websocket&sid=7zb9ikut5ezr2H6kAAAi HTTP/1.1 +Host: 192.168.2.30:8080 +Connection: Upgrade +Upgrade: websocket +Sec-WebSocket-Version: 13 +Sec-WebSocket-Key: m1MElaS+NSouCUhWjSLPug== +Sec-WebSocket-Protocol: arduino +Authorization: 1234567890 +User-Agent: arduino-WebSocket-Client + + +[WS] [WS-Client] [sendHeader] Sending header... Done (us):4878 +[WS] [WS-Client][handleHeader] RX:HTTP/1.1 101 Switching Protocols +[WS] [WS-Client][handleHeader] RX:Upgrade: websocket +[WS] [WS-Client][handleHeader] RX:Connection: Upgrade +[WS] [WS-Client][handleHeader] RX:Sec-WebSocket-Accept: r/1zdz7Sk+4eMliZJTebh6cH7uw= +[WS] [WS-Client][handleHeader] RX:Sec-WebSocket-Protocol: arduino +[WS] [WS-Client][handleHeader] Header read fin. +[WS] [WS-Client][handleHeader] Client settings: +[WS] [WS-Client][handleHeader] - cURL:/socket.io/?EIO=4 +[WS] [WS-Client][handleHeader] - cKey:m1MElaS+NSouCUhWjSLPug== +[WS] [WS-Client][handleHeader] Server header: +[WS] [WS-Client][handleHeader] - cCode:101 +[WS] [WS-Client][handleHeader] - cIsUpgrade:1 +[WS] [WS-Client][handleHeader] - cIsWebsocket:1 +[WS] [WS-Client][handleHeader] - cAccept:r/1zdz7Sk+4eMliZJTebh6cH7uw= +[WS] [WS-Client][handleHeader] - cProtocol:arduino +[WS] [WS-Client][handleHeader] - cExtensions: +[WS] [WS-Client][handleHeader] - cVersion:0 +[WS] [WS-Client][handleHeader] - cSessionId:7zb9ikut5ezr2H6kAAAi +[WS] [WS-Client][handleHeader] Websocket connection init done. +[WS] [wsIOc] Connected to url:/socket.io/?EIO=4 +[IOc] Connected to url: /socket.io/?EIO=4 +[WS] [wsIOc] get pong +[IOc] Get PONG +[WS] [wsIOc] connected: len = 30 +[WS] [wsIOc] data: {"sid":"7SXGNMJxjtzOWXClAAAj"} +["event_name",{"now":30001}] +[WS] [wsIOc] get ping send pong:3 +[IOc] Get PING +[WS] [WS-Client] Sending HB ping +["event_name",{"now":60002}] +[WS] [wsIOc] get ping send pong:3 +["event_name",{"now":90003}] +[WS] [wsIOc] get ping send pong:3 +[WS] [wsIOc] get ping send pong:3 +[IOc] Get PING +[WS] [WS-Client] Sending HB ping +["event_name",{"now":120004}] +``` + +--- + +#### 10.2 Server + +Using the Socket.IO Server in [**Nodejs_SocketIO_TestServer**](examples/Nodejs_SocketIO_TestServer) + +``` +kh@kh-Inspiron-3593:~/Downloads/Nodejs/New_SIO$ nodejs app +Server launched on port 8080 +Connected +7SXGNMJxjtzOWXClAAAj +JWT token test: { host: '192.168.2.30:8080', + connection: 'keep-alive', + authorization: '1234567890', + 'user-agent': 'arduino-WebSocket-Client' } +Message from Client : { now: 30001 } +Message from Client : { now: 60002 } +Message from Client : { now: 90003 } +Message from Client : { now: 120005 } +``` + +--- + +#### 11. [WT32_ETH01_WebSocketClientSocketIO](examples/WT32_ETH01/WT32_ETH01_WebSocketClientSocketIO) on WT32_ETH01 + +The following are debug terminal output when running example [WT32_ETH01_WebSocketClientSocketIO](examples/WT32_ETH01/WT32_ETH01_WebSocketClientSocketIO) on WT32_ETH01 + +#### 11.1 Client + +``` +Starting WT32_ETH01_WebSocketClient on ESP32_DEV with ETH_PHY_LAN8720 +WebServer_WT32_ETH01 v1.4.1 +WebSockets_Generic v2.14.0 +ETH MAC: A8:03:2A:A1:61:73, IPv4: 192.168.2.232, FULL_DUPLEX, 100Mbps +WebSockets Client started @ IP address: 192.168.2.232 +Connecting to WebSockets Server @ IP address: 192.168.2.30, port: 8080 +[WS] [WS-Client] Connect ws... +[IOc] Disconnected +[WS] [WS-Client] Connect ws... +[WS] [WS-Client][connectedCb] Connected to Host:192.168.2.30, Port:8080 +[WS] [wsIOc] Connected to url:/socket.io/?EIO=4 +[IOc] Connected to url: /socket.io/?EIO=4 +[WS] [wsIOc] get pong +[IOc] Get PONG +[WS] [wsIOc] connected: len = 30 +[WS] [wsIOc] data: {"sid":"cxEI-kMvZ1uKiyQ-AAAB"} +["event_name",{"now":30001}] +[WS] [wsIOc] get event: len = 53 +[WS] [wsIOc] get data: ["Send Message io.emit Broadcasted : ",{"now":30001}] +[IOc] Get event: ["Send Message io.emit Broadcasted : ",{"now":30001}] +[WS] [wsIOc] get event: len = 33 +[WS] [wsIOc] get data: ["Send Message : ",{"now":30001}] +[IOc] Get event: ["Send Message : ",{"now":30001}] +[WS] [wsIOc] get ping send pong:3 +[IOc] Get PING +[WS] [WS-Client] Sending HB ping +["event_name",{"now":60002}] +[WS] [wsIOc] get event: len = 53 +[WS] [wsIOc] get data: ["Send Message io.emit Broadcasted : ",{"now":60002}] +[IOc] Get event: ["Send Message io.emit Broadcasted : ",{"now":60002}] +[WS] [wsIOc] get event: len = 33 +[WS] [wsIOc] get data: ["Send Message : ",{"now":60002}] +[IOc] Get event: ["Send Message : ",{"now":60002}] +[WS] [wsIOc] get ping send pong:3 +["event_name",{"now":90003}] +[WS] [wsIOc] get event: len = 53 +[WS] [wsIOc] get data: ["Send Message io.emit Broadcasted : ",{"now":90003}] +[IOc] Get event: ["Send Message io.emit Broadcasted : ",{"now":90003}] +[WS] [wsIOc] get event: len = 33 +[WS] [wsIOc] get data: ["Send Message : ",{"now":90003}] +[IOc] Get event: ["Send Message : ",{"now":90003}] +[WS] [wsIOc] get ping send pong:3 +[IOc] Get PING +[WS] [WS-Client] Sending HB ping +["event_name",{"now":120004}] +[WS] [wsIOc] get event: len = 54 +[WS] [wsIOc] get data: ["Send Message io.emit Broadcasted : ",{"now":120004}] +[IOc] Get event: ["Send Message io.emit Broadcasted : ",{"now":120004}] +[WS] [wsIOc] get event: len = 34 +[WS] [wsIOc] get data: ["Send Message : ",{"now":120004}] +[IOc] Get event: ["Send Message : ",{"now":120004}] +[WS] [wsIOc] get ping send pong:3 +``` + +--- + +#### 11.2 Server + +Using the Socket.IO Server in [**Nodejs_SocketIO_TestServer**](examples/Nodejs_SocketIO_TestServer) + +``` +kh@kh-Inspiron-3593:~/Downloads/Nodejs/New_SIO$ nodejs app +Server launched on port 8080 +Connected +cxEI-kMvZ1uKiyQ-AAAB +JWT token test: { host: '192.168.2.30:8080', + connection: 'keep-alive', + authorization: '1234567890', + 'user-agent': 'arduino-WebSocket-Client' } +Message from Client : { now: 30001 } +Message from Client : { now: 60002 } +Message from Client : { now: 90003 } +Message from Client : { now: 120004 } +``` + +--- + +#### 12. [Teensy_WebSocketClientSocketIO_QNEthernet](examples/Teensy/QNEthernet/Teensy_WebSocketClientSocketIO_QNEthernet) on TEENSY 4.1 using QNEthernet + +The following are debug terminal output when running example [Teensy_WebSocketClientSocketIO_QNEthernet](examples/Teensy/QNEthernet/Teensy_WebSocketClientSocketIO_QNEthernet) on TEENSY 4.1 using [`QNEthernet`](https://github.com/ssilverman/QNEthernet) library + + +#### 12.1 Client + +``` +Starting Teensy_WebSocketClient_QNEthernet on TEENSY 4.1 using QNEthernet +WebSockets_Generic v2.14.0 +=========== USE_QN_ETHERNET =========== +Initialize Ethernet using static IP => Connected! IP address:192.168.2.222 +Connecting to WebSockets Server @ IP address: 192.168.2.30, port: 8080 +[IOc] Connected to url: /socket.io/?EIO=4 +["event_name",{"now":30001}] +[IOc] Get event: ["Send Message io.emit Broadcasted : ",{"now":30001}] +[IOc] Get event: ["Send Message : ",{"now":30001}] +["event_name",{"now":60002}] +[IOc] Get event: ["Send Message io.emit Broadcasted : ",{"now":60002}] +[IOc] Get event: ["Send Message : ",{"now":60002}] +["event_name",{"now":90003}] +[IOc] Get event: ["Send Message io.emit Broadcasted : ",{"now":90003}] +[IOc] Get event: ["Send Message : ",{"now":90003}] +``` + +--- + +#### 12.2 Server + +Using the Socket.IO Server in [**Nodejs_SocketIO_TestServer**](examples/Nodejs_SocketIO_TestServer) + +``` +kh@kh-Inspiron-3593:~/Downloads/Nodejs/New_SIO$ ./SIO_server.sh +Server launched on port 8080 +Connected +bK733pVgbd3DCsy5AAAB +JWT token test: { host: '192.168.2.30:8080', + connection: 'keep-alive', + authorization: '1234567890', + 'user-agent': 'arduino-WebSocket-Client' } +Message from Client : { now: 30001 } +Message from Client : { now: 60002 } +Message from Client : { now: 90003 } +``` + +--- + +#### 13. [Portenta_H7_WebSocketClientSocketIO](examples/Portenta_H7/Ethernet/Portenta_H7_WebSocketClientSocketIO) on PORTENTA_H7_M7 with Ethernet + +The following are debug terminal output when running example [Portenta_H7_WebSocketClientSocketIO](examples/Portenta_H7/Ethernet/Portenta_H7_WebSocketClientSocketIO) on **PORTENTA_H7_M7 with Ethernet** using Portenta_Ethernet Library + + +#### 13.1 Client + +``` +Start Portenta_H7_WebSocketClientSocketIO on PORTENTA_H7_M7 with Ethernet using Portenta_Ethernet Library +WebSockets_Generic v2.14.0 +WebSockets Client @ IP address: 192.168.2.132 +Connecting to WebSockets Server @ IP address: 192.168.2.30, port: 8080 +[WS] [WS-Client][connectedCb] Connected to Host:192.168.2.30, Port:8080 +[WS] [wsIOc] Connected to url:/socket.io/?EIO=4 +[IOc] Connected to url: /socket.io/?EIO=4 +[WS] [wsIOc] get pong +[IOc] Get PONG +[WS] [wsIOc] connected: len = 30 +[WS] [wsIOc] data: {"sid":"RqchvIdY1DWbvxTpAAAB"} +["event_name",{"now":30001}] +[WS] [wsIOc] get event: len = 53 +[WS] [wsIOc] get data: ["Send Message io.emit Broadcasted : ",{"now":30001}] +[IOc] Get event: ["Send Message io.emit Broadcasted : ",{"now":30001}] +[WS] [wsIOc] get event: len = 33 +[WS] [wsIOc] get data: ["Send Message : ",{"now":30001}] +[IOc] Get event: ["Send Message : ",{"now":30001}] +[WS] [wsIOc] get ping send pong:3 +[IOc] Get PING +[WS] [WS-Client] Sending HB ping +["event_name",{"now":60006}] +[WS] [wsIOc] get event: len = 53 +[WS] [wsIOc] get data: ["Send Message io.emit Broadcasted : ",{"now":60006}] +[IOc] Get event: ["Send Message io.emit Broadcasted : ",{"now":60006}] +[WS] [wsIOc] get event: len = 33 +[WS] [wsIOc] get data: ["Send Message : ",{"now":60006}] +[IOc] Get event: ["Send Message : ",{"now":60006}] +[WS] [wsIOc] get ping send pong:3 +``` + +--- + +#### 13.2 Server + +Using the Socket.IO Server in [**Nodejs_SocketIO_TestServer**](examples/Nodejs_SocketIO_TestServer) + +``` +kh@kh-Inspiron-3593:~/Downloads/Nodejs/New_SIO$ ./SIO_server.sh +Server launched on port 8080 +Connected +RqchvIdY1DWbvxTpAAAB +JWT token test: { host: '192.168.2.30:8080', + connection: 'keep-alive', + authorization: '1234567890', + 'user-agent': 'arduino-WebSocket-Client' } +Message from Client : { now: 30001 } +Message from Client : { now: 60006 } + +``` + +--- + +#### 14. [WebSocketClientSocketIO_WiFi](examples/Portenta_H7/WiFi/WebSocketClientSocketIO_WiFi) on Portenta_H7 using WiFi + +The following are debug terminal output when running example [WebSocketClientSocketIO_WiFi](examples/Portenta_H7/WiFi/WebSocketClientSocketIO_WiFi) on Portenta_H7 using `Murata` WiFi + + +#### 14.1 Client + +``` +Start WebSocketClientSocketIO_WiFi on PORTENTA_H7_M7 +WebSockets_Generic v2.14.0 +Connecting to SSID: HueNet1 +SSID: HueNet1 +WebSockets Client IP Address: 192.168.2.130 +signal strength (RSSI):-27 dBm +Connecting to WebSockets Server @ IP address: 192.168.2.30, port: 8080 +[IOc] Connected to url: /socket.io/?EIO=4 +["event_name",{"now":30001}] +[IOc] Get event: ["Send Message io.emit Broadcasted : ",{"now":30001}] +[IOc] Get event: ["Send Message : ",{"now":30001}] +["event_name",{"now":60002}] +[IOc] Get event: ["Send Message io.emit Broadcasted : ",{"now":60002}] +[IOc] Get event: ["Send Message : ",{"now":60002}] +["event_name",{"now":90003}] +[IOc] Get event: ["Send Message io.emit Broadcasted : ",{"now":90003}] +[IOc] Get event: ["Send Message : ",{"now":90003}] +["event_name",{"now":121501}] +[IOc] Get event: ["Send Message io.emit Broadcasted : ",{"now":121501}] +[IOc] Get event: ["Send Message : ",{"now":121501}] +["event_name",{"now":151503}] +[IOc] Get event: ["Send Message io.emit Broadcasted : ",{"now":151503}] +[IOc] Get event: ["Send Message : ",{"now":151503}] +``` + +--- + +#### 14.2 Server + +Using the Socket.IO Server in [**Nodejs_SocketIO_TestServer**](examples/Nodejs_SocketIO_TestServer) + +``` +kh@kh-Inspiron-3593:~/Downloads/Nodejs/New_SIO$ ./SIO_server.sh +Server launched on port 8080 +Connected +nr4syN7HdG1PlCYrAAAF +JWT token test: { host: '192.168.2.30:8080', + connection: 'keep-alive', + authorization: '1234567890', + 'user-agent': 'arduino-WebSocket-Client' } +Message from Client : { now: 30001 } +Message from Client : { now: 60002 } +Message from Client : { now: 90003 } +Message from Client : { now: 121501 } +Message from Client : { now: 151503 } +Message from Client : { now: 181506 } +``` + +--- + +#### 15. [Portenta_H7_WebSocketClient_Sticky_SocketIO](examples/Portenta_H7/Ethernet/Portenta_H7_WebSocketClient_Sticky_SocketIO) on Portenta_H7 using Ethernet + +The following are debug terminal output when running example [Portenta_H7_WebSocketClient_Sticky_SocketIO](examples/Portenta_H7/Ethernet/Portenta_H7_WebSocketClient_Sticky_SocketIO) on Portenta_H7 using Vision-shield Ethernet. + + +``` +Start Portenta_H7_WebSocketClient_Sticky_SocketIO on PORTENTA_H7_M7 with Ethernet using Portenta_Ethernet Library +WebSockets_Generic v2.14.0 +WebSockets Client @ IP address: 192.168.2.133 +Connecting to WebSockets Server @ IP address: 192.168.2.30, port: 8080 +[WS] WebSockets_Generic v2.14.0 +[WS] [wsIOc] found EIO=4 disable EIO ping on client +[WS] [WS-Client][connectedCb] Connected to Host:192.168.2.30, Port:8080 +[WS] [WS-Client] [sendHeader] Sending header... +[WS] sendHeader: client->cKey = Kp/b0RFGMw/WSNGn35/s3A== +[WS] [WS-Client] [sendHeader] Handshake:GET /socket.io/?EIO=4&transport=websocket HTTP/1.1 +Host: 192.168.2.30:8080 +Connection: keep-alive +Authorization: 1234567890 +User-Agent: arduino-WebSocket-Client + + +[WS] [WS-Client] [sendHeader] Sending header... Done (us):712 +[WS] [WS-Client][handleHeader] RX:HTTP/1.1 200 OK +[WS] [WS-Client][handleHeader] RX:Date: Sun, 12 Dec 2021 05:58:29 GMT +[WS] [WS-Client][handleHeader] RX:Connection: keep-alive +[WS] [WS-Client][handleHeader] RX:Keep-Alive: timeout=5 +[WS] [WS-Client][handleHeader] RX:Transfer-Encoding: chunked +[WS] [WS-Client][handleHeader] Header read fin. +[WS] [WS-Client][handleHeader] Client settings: +[WS] [WS-Client][handleHeader] - cURL:/socket.io/?EIO=4 +[WS] [WS-Client][handleHeader] - cKey:Kp/b0RFGMw/WSNGn35/s3A== +[WS] [WS-Client][handleHeader] Server header: +[WS] [WS-Client][handleHeader] - cCode:200 +[WS] [WS-Client][handleHeader] - cIsUpgrade:0 +[WS] [WS-Client][handleHeader] - cIsWebsocket:1 +[WS] [WS-Client][handleHeader] - cAccept: +[WS] [WS-Client][handleHeader] - cProtocol:arduino +[WS] [WS-Client][handleHeader] - cExtensions: +[WS] [WS-Client][handleHeader] - cVersion:0 +[WS] [WS-Client][handleHeader] - cSessionId: +[WS] [WS-Client][handleHeader] Still missing cSessionId try Socket.IO +[WS] [WS-Client][handleHeader] socket.io json: c +hello world + +0 +[WS] [WS-Client][handleHeader] RX:c +hello world + +0 +[WS] [WS-Client][handleHeader] Header error:c +hello world + +0 +[WS] [WS-Client][handleClientData] Header response timeout.. Disconnecting! +[IOc] Disconnected +[WS] [wsIOc] Disconnected! +[WS] [WS-Client][connectedCb] Connected to Host:192.168.2.30, Port:8080 +[WS] [WS-Client] [sendHeader] Sending header... +[WS] sendHeader: client->cKey = dm6SsOCMRZwhNjKmQeo2lw== +[WS] [WS-Client] [sendHeader] Handshake:GET /socket.io/?EIO=4&transport=websocket HTTP/1.1 +Host: 192.168.2.30:8080 +Connection: keep-alive +Authorization: 1234567890 +User-Agent: arduino-WebSocket-Client +``` + + + +--- + +#### 16. [ESP32_WebSocketClientSocketIO](examples/esp32/ESP32_WebSocketClientSocketIO) on ESP32S3_DEV + +The following are debug terminal output when running example [ESP32_WebSocketClientSocketIO](examples/esp32/ESP32_WebSocketClientSocketIO) on **ESP32S3_DEV** + + +``` +Start ESP32_WebSocketClientSocketIO on ESP32S3_DEV +WebSockets_Generic v2.14.0 +Connecting to HueNet1 +WebSockets Client started @ IP address: 192.168.2.83 +Connecting to WebSockets Server @ IP address: 192.168.2.30, port: 8080 +[WS] [WS-Client] beginSocketIO with IPAddress +[WS] [WS-Client] beginSocketIO with const char +[WS] WebSockets_Generic v2.12.0 +[WS] [wsIOc] found EIO=4 disable EIO ping on client +[WS] [WS-Client] Connect ws... +[WS] [WS-Client] Calling _client.tcp->connect, _host =192.168.2.30, port =8080 +[WS] [WS-Client] Calling _client.tcp->connect, _connectResult =1 +[WS] [WS-Client] connectedCb +[WS] [WS-Client][connectedCb] Connected to Host:192.168.2.30, Port:8080 +[WS] [WS-Client] [sendHeader] Sending header... +[WS] sendHeader: client->cKey = 8FGfIMaycpbZsGx1WcjYPg== +[WS] [WS-Client] [sendHeader] Handshake:GET /socket.io/?EIO=4&transport=polling HTTP/1.1 +Host: 192.168.2.30:8080 +Connection: keep-alive +Authorization: 1234567890 +User-Agent: arduino-WebSocket-Client + +[WS] [write] n:166, t:10047 +[WS] [write] Write, Length :166, Left :0 +[WS] [WS-Client] [sendHeader] Sending header... Done (us):32263 +[WS] [WS-Client][handleHeader] RX:HTTP/1.1 200 OK +[WS] [WS-Client][handleHeader] RX:Content-Type: text/plain; charset=UTF-8 +[WS] [WS-Client][handleHeader] RX:Content-Length: 97 +[WS] [WS-Client][handleHeader] RX:Date: Mon, 14 Feb 2022 23:52:21 GMT +[WS] [WS-Client][handleHeader] RX:Connection: keep-alive +[WS] [WS-Client][handleHeader] RX:Keep-Alive: timeout=5 +[WS] [WS-Client][handleHeader] Header read fin. +[WS] [WS-Client][handleHeader] Client settings: +[WS] [WS-Client][handleHeader] - cURL:/socket.io/?EIO=4 +[WS] [WS-Client][handleHeader] - cKey:8FGfIMaycpbZsGx1WcjYPg== +[WS] [WS-Client][handleHeader] Server header: +[WS] [WS-Client][handleHeader] - cCode:200 +[WS] [WS-Client][handleHeader] - cIsUpgrade:0 +[WS] [WS-Client][handleHeader] - cIsWebsocket:1 +[WS] [WS-Client][handleHeader] - cAccept: +[WS] [WS-Client][handleHeader] - cProtocol:arduino +[WS] [WS-Client][handleHeader] - cExtensions: +[WS] [WS-Client][handleHeader] - cVersion:0 +[WS] [WS-Client][handleHeader] - cSessionId: +[WS] [WS-Client][handleHeader] Still missing cSessionId try Socket.IO +[WS] [WS-Client][handleHeader] socket.io json: 0{"sid":"p6g2ESTze400qtXcAAAE","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":20000} +[WS] [WS-Client][handleHeader] - cSessionId: p6g2ESTze400qtXcAAAE +[WS] [WS-Client][handleHeader] Header read fin. +[WS] [WS-Client][handleHeader] Client settings: +[WS] [WS-Client][handleHeader] - cURL:/socket.io/?EIO=4 +[WS] [WS-Client][handleHeader] - cKey:8FGfIMaycpbZsGx1WcjYPg== +[WS] [WS-Client][handleHeader] Server header: +[WS] [WS-Client][handleHeader] - cCode:200 +[WS] [WS-Client][handleHeader] - cIsUpgrade:0 +[WS] [WS-Client][handleHeader] - cIsWebsocket:1 +[WS] [WS-Client][handleHeader] - cAccept: +[WS] [WS-Client][handleHeader] - cProtocol:arduino +[WS] [WS-Client][handleHeader] - cExtensions: +[WS] [WS-Client][handleHeader] - cVersion:0 +[WS] [WS-Client][handleHeader] - cSessionId:p6g2ESTze400qtXcAAAE +[WS] [WS-Client][handleHeader] found cSessionId +[WS] [WS-Client] [sendHeader] Sending header... +[WS] sendHeader: client->cKey = 2btvEqbCEn69Vmh40QfIaA== +[WS] [WS-Client] [sendHeader] Handshake:GET /socket.io/?EIO=4&transport=websocket&sid=p6g2ESTze400qtXcAAAE HTTP/1.1 +Host: 192.168.2.30:8080 +Connection: Upgrade +Upgrade: websocket +Sec-WebSocket-Version: 13 +Sec-WebSocket-Key: 2btvEqbCEn69Vmh40QfIaA== +Sec-WebSocket-Protocol: arduino +Authorization: 1234567890 +User-Agent: arduino-WebSocket-Client + +[WS] [write] n:315, t:10268 +[WS] [write] Write, Length :315, Left :0 +[WS] [WS-Client] [sendHeader] Sending header... Done (us):42597 +[WS] [WS-Client][handleHeader] RX:HTTP/1.1 101 Switching Protocols +[WS] [WS-Client][handleHeader] RX:Upgrade: websocket +[WS] [WS-Client][handleHeader] RX:Connection: Upgrade +[WS] [WS-Client][handleHeader] RX:Sec-WebSocket-Accept: MokU7OGA/lZbCC0KeEZT6+rp5l0= +[WS] [WS-Client][handleHeader] RX:Sec-WebSocket-Protocol: arduino +[WS] [WS-Client][handleHeader] Header read fin. +[WS] [WS-Client][handleHeader] Client settings: +[WS] [WS-Client][handleHeader] - cURL:/socket.io/?EIO=4 +[WS] [WS-Client][handleHeader] - cKey:2btvEqbCEn69Vmh40QfIaA== +[WS] [WS-Client][handleHeader] Server header: +[WS] [WS-Client][handleHeader] - cCode:101 +[WS] [WS-Client][handleHeader] - cIsUpgrade:1 +[WS] [WS-Client][handleHeader] - cIsWebsocket:1 +[WS] [WS-Client][handleHeader] - cAccept:MokU7OGA/lZbCC0KeEZT6+rp5l0= +[WS] [WS-Client][handleHeader] - cProtocol:arduino +[WS] [WS-Client][handleHeader] - cExtensions: +[WS] [WS-Client][handleHeader] - cVersion:0 +[WS] [WS-Client][handleHeader] - cSessionId:p6g2ESTze400qtXcAAAE +[WS] [WS-Client][handleHeader] Websocket connection init done. +[WS] [headerDone] Header Handling Done. Client:0 +[WS] [wsIOc] Connected to url:/socket.io/?EIO=4 +[WS] [sendFrame] ------- send message frame ------- +[WS] [sendFrame] Client:0 +[WS] fin:1 +[WS] opCode:1 +[WS] mask:1 +[WS] length:6 +[WS] headerToPayload:0 +[WS] [sendFrame] Client: 0, text:2probe +[WS] [sendFrame] pack to one TCP package... Client:0 +[WS] [write] n:12, t:10411 +[WS] [write] Write, Length :12, Left :0 +[WS] [sendFrame] ------- send message frame ------- +[WS] [sendFrame] Client:0 +[WS] fin:1 +[WS] opCode:1 +[WS] mask:1 +[WS] length:1 +[WS] headerToPayload:1 +[WS] [sendFrame] Client: 0, text:5 +[WS] [write] n:7, t:10433 +[WS] [write] Write, Length :7, Left :0 +[IOc] Connected to url: /socket.io/?EIO=4 +[WS] [write] n:6, t:10435 +[WS] [write] Write, Length :6, Left :0 +[WS] [write] n:2, t:10446 +[WS] [write] Write, Length :2, Left :0 +[WS] [write] n:1, t:10447 +[WS] [write] Write, Length :1, Left :0 +[WS] [handleWebsocketWaitFor] Client: 0, size:2 +[WS] cWsRXsize:0 +[WS] [readCb] n:2, t:10459 +[WS] [readCb] Receive Length =2, left =0 +[WS] [handleWebsocketWaitFor][readCb] Client: 0, size:2 +[WS] ok:1 +[WS] [handleWebsocket] ------- read massage frame ------- Client:0 +[WS] [handleWebsocket] Client: 0, fin:1 +[WS] rsv1:0 +[WS] rsv2:0 +[WS] rsv3:0 +[WS] opCode:1 +[WS] [handleWebsocket] Client: 0, mask:0 +[WS] payloadLen:6 +[WS] [readCb] n:6, t:10491 +[WS] [readCb] Receive Length =6, left =0 +[WS] [handleWebsocketPayloadCb] Client: 0, text:3probe +[WS] [wsIOc] get pong +[IOc] Get PONG +[WS] [handleWebsocketWaitFor] Client: 0, size:2 +[WS] cWsRXsize:0 +[WS] [readCb] n:2, t:10512 +[WS] [readCb] Receive Length =2, left =0 +[WS] [handleWebsocketWaitFor][readCb] Client: 0, size:2 +[WS] ok:1 +[WS] [handleWebsocket] ------- read massage frame ------- Client:0 +[WS] [handleWebsocket] Client: 0, fin:1 +[WS] rsv1:0 +[WS] rsv2:0 +[WS] rsv3:0 +[WS] opCode:1 +[WS] [handleWebsocket] Client: 0, mask:0 +[WS] payloadLen:32 +[WS] [readCb] n:32, t:10544 +[WS] [readCb] Receive Length =32, left =0 +[WS] [handleWebsocketPayloadCb] Client: 0, text:40{"sid":"356v34mdH9BycjJpAAAF"} +[WS] [wsIOc] connected: len = 30 +[WS] [wsIOc] data: {"sid":"356v34mdH9BycjJpAAAF"} +``` + +--- +--- + +### Debug + +Debug is enabled by default on Serial. To disable, add at the beginning of sketch + +```cpp +/* Comment this out to disable prints and save space */ +#define DEBUG_WEBSOCKETS_PORT Serial + +#define _WEBSOCKETS_LOGLEVEL_ 4 +``` + +### Troubleshooting + +If you get compilation errors, more often than not, you may need to install a newer version of the board's core, dependent libraries or this library version. + +Sometimes, the library will only work if you update the core to the newer or older version because some function compatibility. + +--- +--- + +### Issues + +Submit issues to: [WebSockets_Generic issues](https://github.com/khoih-prog/WebSockets_Generic/issues) + +--- +--- + +### TO DO + +1. Bug Searching and Killing +2. Support more types of boards using WiFi/Ethernet shields (Teensy, etc.) +3. Support more non-compatible Ethernet Libraries such as Ethernet_Shield_W5200, EtherCard, EtherSia + +--- + +### DONE + + 1. Add support to Arduino SAMD21 (ZERO, MKR, NANO_33_IOT, etc.) + 2. Add support to Adafruit SAMD21 (Itsy-Bitsy M0, Metro M0, Feather M0 Express, etc.). + 3. Add support to Adafruit SAMD51 (Itsy-Bitsy M4, Metro M4, Grand Central M4, Feather M4 Express, etc.). + 4. Add support to Adafruit nRF52 ( Feather nRF52832, nRF52840 Express, BlueFruit Sense, Itsy-Bitsy nRF52840 Express, Metro nRF52840 Express, NINA_B302_ublox, NINA_B112_ublox, etc. + 5. Add support to Seeeduino SAMD21/SAMD51 boards (SEEED_WIO_TERMINAL, SEEED_FEMTO_M0, SEEED_XIAO_M0, Wio_Lite_MG126, WIO_GPS_BOARD, SEEEDUINO_ZERO, SEEEDUINO_LORAWAN, SEEED_GROVE_UI_WIRELESS, etc.) + 6. Add support to STM32F/L/H/G/WB/MP1 (Nucleo-144, Nucleo-64, Nucleo-32, Discovery, STM32Fx, STM32H7, STM32Lx, STM32Gx, STM32WB, STM32MP1, etc.) having 64K+ Flash program memory. + 7. Add support to Ethernet W5x00, using either [`Ethernet`](https://www.arduino.cc/en/Reference/Ethernet), [`Ethernet2`](https://github.com/khoih-prog/Ethernet2), [`Ethernet3`](https://github.com/sstaub/Ethernet3) or [`EthernetLarge`](https://github.com/OPEnSLab-OSU/EthernetLarge) library + 8. Add support to WiFiNINA using WiFiNINA or [**WiFiNINA_Generic library**](https://github.com/khoih-prog/WiFiNINA_Generic). + 9. Add support to ENC28J60 using [`UIPEthernet`](https://github.com/UIPEthernet/UIPEthernet) +10. Add support to ENC28J60 using [`EthernetENC`](https://github.com/jandrassy/EthernetENC) +11. Add support to Teensy using W5x00, ENC28J60, WiFiNINA +12. Add support to Teensy 4.1 built-in Ethernet using [`NativeEthernet`](https://github.com/vjmuzik/NativeEthernet) library +13. Add support to STM32F/L/H/G/WB/MP1 using built-in LAN8742A and [`STM32Ethernet`](https://github.com/stm32duino/STM32Ethernet) +14. Add support to SeeedStudio WIO Terminal with **Realtek RTL8720DN WiFi** using [`Seeed_Arduino_rpcWiFi`](https://github.com/Seeed-Studio/Seeed_Arduino_rpcWiFi) and [`Seeed_Arduino_rpcUnified`](https://github.com/khoih-prog/Seeed_Arduino_rpcUnified) libraries +15. Add support to SAMD_MKR1000 and SAMD_MKRWIFI1010 using WiFi101 +16. Fix breaking problem with SocketIO. +17. Default to EIOv4 +18. Add support to RP2040-based boards, such as **RASPBERRY_PI_PICO, ADAFRUIT_FEATHER_RP2040 and GENERIC_RP2040**, using [**Earle Philhower's arduino-pico core** v1.3.1+](https://github.com/earlephilhower/arduino-pico). +19. Add support to RP2040-based boards, such as **RASPBERRY_PI_PICO, ADAFRUIT_FEATHER_RP2040 and GENERIC_RP2040**, using [**Arduino-mbed RP2040** core](https://github.com/arduino/ArduinoCore-mbed). +20. Add support to **WT32_ETH01 boards** using ESP32-based boards and LAN8720 Ethernet +21. Add support to Teensy 4.1 built-in Ethernet using [`QNEthernet`](https://github.com/ssilverman/QNEthernet) library +22. Add support to **Portenta_H7**, using either `Murata WiFi` or `Vision-shield Ethernet` +23. Auto detect ESP32 core to use for WT32_ETH01 +24. Fix bug in WT32_ETH01 examples to reduce connection time +25. Add option to use transport=websocket with sticky-session SIO server +26. Add SSL support to ESP32-based WT32_ETH01 boards +27. Add support to ESP32_S3, ESP32_C3 +28. Add `sIOtype_PING` and `sIOtype_PING` SocketIO events. +29. Don't use `deprecated sha.h` for ESP32 core v1.0.6+. +30. Optimize code by passing by `reference` instead of `value` + + +--- +--- + +### Contributions and Thanks + +1. Based on and modified from [Markus Sattler's **arduinoWebSockets** library](https://github.com/Links2004/arduinoWebSockets) +2. Thanks to [Anson He](https://github.com/ansonhe97) for the PR [**Fix compile error for Wio Terminal**](https://github.com/khoih-prog/WebSockets_Generic/pull/5) to fix SeeedStudio **SEEED_WIO_TERMINAL** compile errors and leading to new version v2.3.3. +3. Thanks to [Jose A.Molina](https://github.com/Josua2012) for the enhancement request [**WiFi101 and Arduino MKR1000.** #10](https://github.com/khoih-prog/WebSockets_Generic/issues/10), and help testing, leading to new version v2.5.0, and v2.6.0 +4. Thanks to [Ideen Kaffee Korner](https://github.com/iKK001) for + - the enhancement request [**Run websocket only mode for Socket.IO** #16](https://github.com/khoih-prog/WebSockets_Generic/issues/16), leading to new version v2.11.1 + - the issue [Ethernet with SSL #17](https://github.com/khoih-prog/WebSockets_Generic/issues/17), leading to new version v2.12.0 to support SSL for WT32_ETH01 using LAN8720 Ethernet + - the issue [Ping events propagated to main code socketIO events #18](https://github.com/khoih-prog/WebSockets_Generic/issues/18), leading to new version v2.13.0 to add `sIOtype_PING` and `sIOtype_PING` SocketIO events + + + + + + + + +
Links2004
⭐️⭐️ Markus Sattler

ansonhe97
Anson He

Josua2012
Jose A. Molina

iKK001
⭐️ Ideen Kaffee Korner

+ +--- + +### Contributing + +If you want to contribute to this project: + +- Report bugs and errors +- Ask for enhancements +- Create issues and pull requests +- Tell other people about this library + +--- + +### License and credits + +- Most of the credits go to original author [**Markus Sattler**](https://github.com/Links2004). + +- The library is licensed under [**GPLv3**](https://github.com/khoih-prog/WebSockets_Generic/blob/master/LICENSE) + +- [libb64](http://libb64.sourceforge.net/) written by Chris Venter. It is distributed under Public Domain see [LICENSE](https://github.com/Links2004/arduinoWebSockets/blob/master/src/libb64/LICENSE). + + + diff --git a/src/changelog.md b/src/changelog.md new file mode 100644 index 00000000..f2fe1db6 --- /dev/null +++ b/src/changelog.md @@ -0,0 +1,288 @@ +## WebSockets_Generic + +[![arduino-library-badge](https://www.ardu-badge.com/badge/WebSockets_Generic.svg?)](https://www.ardu-badge.com/WebSockets_Generic) +[![GitHub release](https://img.shields.io/github/release/khoih-prog/WebSockets_Generic.svg)](https://github.com/khoih-prog/WebSockets_Generic/releases) +[![GitHub](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/khoih-prog/WebSockets_Generic/blob/master/LICENSE) +[![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](#Contributing) +[![GitHub issues](https://img.shields.io/github/issues/khoih-prog/WebSockets_Generic.svg)](http://github.com/khoih-prog/WebSockets_Generic/issues) + +--- +--- + +## Table of Contents + +* [Changelog](#changelog) + * [Release v2.14.0](#release-v2140) + * [Release v2.13.0](#release-v2130) + * [Major Release v2.12.0](#major-release-v2120) + * [Release v2.11.1](#release-v2111) + * [Major Release v2.11.0](#major-release-v2110) + * [Release v2.10.1](#release-v2101) + * [Major Release v2.10.0](#major-release-v2100) + * [Major Release v2.9.0](#major-release-v290) + * [Major Release v2.8.0](#major-release-v280) + * [Major Release v2.7.0](#major-release-v270) + * [Major Release v2.6.0](#major-release-v260) + * [Release v2.5.1](#release-v251) + * [Major Release v2.5.0](#major-release-v250) + * [Release v2.4.1](#release-v241) + * [Major Release v2.4.0](#major-release-v240) + * [Release v2.3.4](#release-v234) + * [Release v2.3.3](#release-v233) + * [Release v2.3.2](#release-v232) + * [Release v2.3.1](#release-v231) + * [Release v2.2.3](#release-v223) + * [Release v2.2.2](#release-v222) + * [Release v2.2.1](#release-v221) + * [Release v2.1.3](#release-v213) +* [Important Notes](#important-notes) + * [Originally Supported Hardware](#originally-supported-hardware) + * [New support from v2.10.0](#new-support-from-v2100) + * [New support from v2.9.0](#new-support-from-v290) + * [New support from v2.8.0](#new-support-from-v280) + * [New support from v2.7.0](#new-support-from-v270) + * [New support from v2.5.0](#new-support-from-v250) + * [New support from v2.4.0](#new-support-from-v240) + * [New support from v2.3.4](#new-support-from-v234) + * [New support from v2.3.2](#new-support-from-v232) + * [New support from v2.3.1](#new-support-from-v231) + * [New support from v2.2.3](#new-support-from-v223) + * [New support from v2.2.2](#new-support-from-v222) + * [New support from v2.1.3](#new-support-from-v213) +--- +--- + +## Changelog + +### Release v2.14.0 + +1. Suppress unnecessary warnings. +2. Don't use `deprecated sha.h` for ESP32 core v1.0.6+. Check [warning sha.h is deprecated, use sha_parallel_engine.h #738](https://github.com/Links2004/arduinoWebSockets/issues/738) +3. Optimize code by passing by `reference` instead of `value` +4. Modify nearly all examples +5. Update `Packages' Patches` + +### Release v2.13.0 + +1. Add support to `ESP32_S3`. +2. Add `sIOtype_PING` and `sIOtype_PING` SocketIO events. Check [Ping events propagated to main code socketIO events #18](https://github.com/khoih-prog/WebSockets_Generic/issues/18) +3. Add [ESP32_WebSocketClientSocketIO](examples/ESP32_WebSocketClientSocketIO) example +4. Update `Packages' Patches` + +### Major Release v2.12.0 + +1. Add SSL support to ESP32-based WT32_ETH01 boards using LAN8720 Ethernet +2. Add WT32_ETH01-related [WT32_ETH01_SSL_SIO example](examples/WT32_ETH01/WT32_ETH01_SSL_SIO) +3. Update `Packages' Patches` + + +### Release v2.11.1 + +1. Add option to use `transport=websocket` with sticky-session SIO server. Check [Run websocket only mode for Socket.IO #16](https://github.com/khoih-prog/WebSockets_Generic/issues/16) +2. Add some Sticky_SIO-related examples + +### Major Release v2.11.0 + +1. Auto detect ESP32 core to use for WT32_ETH01 +2. Fix bug in WT32_ETH01 examples to reduce connection time +3. Delete Blynk-related examples +4. Replace deprecated `echo.websocket.org` in examples. + +### Release v2.10.1 + +1. Update `platform.ini` and `library.json` to use original `khoih-prog` instead of `khoih.prog` after PIO fix +2. Update `Packages' Patches` + +### Major Release v2.10.0 + +1. Add support to **Portenta_H7**, using either WiFi or Vision-shield Ethernet +2. Add examples with new features + +### Major Release v2.9.0 + +1. Add support to [QNEthernet Library](https://github.com/ssilverman/QNEthernet) for Teensy 4.1 built-in Ethernet +2. Update examples with new features + +### Major Release v2.8.0 + +1. Add support to WT32_ETH01 (ESP32 + LAN8720) boards +2. Add examples with new features + +### Major Release v2.7.0 + +1. Add support to RP2040-based boards, such as **RASPBERRY_PI_PICO, ADAFRUIT_FEATHER_RP2040 and GENERIC_RP2040**, using [**Earle Philhower's arduino-pico** v1.6.2+ core](https://github.com/earlephilhower/arduino-pico). +2. Add support to RP2040-based boards, such as **RASPBERRY_PI_PICO, ADAFRUIT_FEATHER_RP2040 and GENERIC_RP2040**, using [**Arduino-mbed RP2040** v2.1.0+ core](https://github.com/arduino/ArduinoCore-mbed). +3. Update Socket.IO Test Server to demonstrate the server message broadcast +4. Update examples with new features +5. Verify working with new ESP8266 core v3.0.0 +6. Suppress all warnings possible. + +### Major Release v2.6.0 + +1. Fix breaking problem with SocketIO. +2. Add setExtraHeaders function to SocketIO +3. Clean possible compiler's warnings + +### Release v2.5.1 + +1. Default to **EIO4 for Socket.IO**. +2. Permit changing reconnectInterval in Socket.IO. Default is 0.5s. Set in Socket.IO examples to 10s. +2. Better debug settings + +### Major Release v2.5.0 + +1. Add support to SAMD_MKR1000 and SAMD_MKRWIFI1010 using WiFi101. To be used with [**Forked WiFi101** library](https://github.com/khoih-prog/WiFi101) +2. Clean compiler's warnings +3. Add examples for WiFi101 + +### Release v2.4.1 + +1. Sync with v2.3.5 of original WebSockets library to adapt to ESP32 SSL changes +2. Update Packages' and Libraries' Patches +3. Add `Bug Report` and `Feature Request` templates + +### Major Release v2.4.0 + +1. Add support to Teensy 4.1 using NativeEthernet. +2. Add support to STM32F/L/H/G/WB/MP1 using built-in LAN8742A. +3. Sync with v2.3.4 of original WebSockets library +4. Add Teensy, Teensy 4.1 NativeEthernet and STM32 LAN8742A examples. +5. Fix bugs in and optimize examples. + +### Release v2.3.4 + +1. Add SSL support to boards using **WiFiNINA (Nano-33-IoT, etc.)** +2. Add SSL support to boards using **Realtek RTL8720DN WiFi and Seeed_Arduino_rpcWiFi (WIO_Terminal, etc.)** +3. Upgrade WS and WSS examples. + +### Release v2.3.3 + +1. Fix compile errors for boards (nRF52, SAMD, etc.) using libraries with lib64, such as [**EthernetWebServer**](https://github.com/khoih-prog/EthernetWebServer) +2. Fix SeeedStudio **SEEED_WIO_TERMINAL** compile errors. See [**Fix compile error for Wio Terminal**](https://github.com/khoih-prog/WebSockets_Generic/pull/5) +3. Add file to SeeedStudio SAMD Packages' Patches. +4. Fix compiler warnings for duplications in WS_LOG with [WiFiWebServer Library](https://github.com/khoih-prog/WiFiWebServer) + + +### Release v2.3.2 + +1. Add support to **Realtek RTL8720DN WiFi** using [**Seeed_Arduino_rpcWiFi**](https://github.com/Seeed-Studio/Seeed_Arduino_rpcWiFi) and [**Seeed_Arduino_rpcUnified**](https://github.com/khoih-prog/Seeed_Arduino_rpcUnified) libraries. This RTL8720DN supports Dual-Band 2.4GHz / 5GHz Wi-Fi (802.11 a/b/g/n) as well as BLE/BLE 5.0 and is currently used in SeeedStudio **SEEED_WIO_TERMINAL**. +2. Add examples for SeeedStudio **SEEED_WIO_TERMINAL** and update all examples +3. Add Version string definition + +### Release v2.3.1 + +1. Sync with v2.3.1 of original [**WebSockets library**](https://github.com/Links2004/arduinoWebSockets). +2. Add support to ENC28J60 using [**EthernetENC library**](https://github.com/jandrassy/EthernetENC). +3. Add and update examples + +#### Release v2.2.3 + +1. Add support to all **STM32F/L/H/G/WB/MP1 (Nucleo-144 NUCLEO_F767ZI, Nucleo-64 NUCLEO_L053R8, etc.)** +2. Add support to **Seeeduino SAMD21/SAMD51 boards (SEEED_WIO_TERMINAL, SEEED_FEMTO_M0, SEEED_XIAO_M0, Wio_Lite_MG126, WIO_GPS_BOARD, SEEEDUINO_ZERO, SEEEDUINO_LORAWAN, SEEED_GROVE_UI_WIRELESS, etc.)** +3. Add support to **W5x00's Ethernet2, Ethernet3, EthernetLarge Libraries.** +4. Add sample Packages_Patches for **STM32 stm32** (Nucleo-144 NUCLEO_F767ZI, Nucleo-64 NUCLEO_L053R8) +5. Add Packages' Patches and Ethernet Library Patches. + +#### Release v2.2.2 + +1. Add support to **Teensy** boards, such as **Teensy 4.1, 4.0. 3.6, 3.5, 3.2/3.1, 3.0, LC.**. +2. Add support to **STM32 (Nucleo-144, Nucleo-64, Nucleo-32, Discovery, STM32F1, STM32F3, STM32F4, STM32H7, STM32L0, etc.)**. +3. Add support to **SAM DUE** +4. Add WebSocketServer examples to those supported boards. + +#### Release v2.2.1 + +1. Bump up to sync with v2.2.1 of original WebSockets library + +#### Release v2.1.3 + +1. Add support to **nRF52** boards, such as **AdaFruit Feather nRF52832, nRF52840 Express, BlueFruit Sense, Itsy-Bitsy nRF52840 Express, Metro nRF52840 Express, NINA_B302_ublox, etc.**. +2. Add support to **SAMD51 (Itsy-Bitsy M4, Metro M4, Grand Central M4, Feather M4 Express, etc.)**. +3. Add support to **SAMD21 (ZERO, MKR, NANO_33_IOT, M0, M0 Pro, AdaFruit CIRCUITPLAYGROUND_EXPRESS, etc.)**. + + +--- +--- + +### Important Notes + +#### Originally Supported Hardware + + - ESP8266 [Arduino for ESP8266](https://github.com/esp8266/Arduino/) + - ESP32 [Arduino for ESP32](https://github.com/espressif/arduino-esp32) + - ESP31B + - Particle with STM32 ARM Cortex M3 + - ATmega328 with Ethernet Shield (ATmega branch) + - ATmega328 with ENC28J60 (ATmega branch) + - ATmega2560 with Ethernet Shield (ATmega branch) + - ATmega2560 with ENC28J60 (ATmega branch) + +--- + +#### New support from v2.10.0 + +1. **Portenta_H7**, using either WiFi or Vision-shield Ethernet + +#### New support from v2.9.0 + +1. Teensy 4.1 built-in Ethernet using [QNEthernet Library](https://github.com/ssilverman/QNEthernet) + +#### New support from v2.8.0 + +1. **WT32_ETH01 boards** using ESP32-based boards and LAN8720 Ethernet + +#### New support from v2.7.0 + +1. RP2040-based boards, such as **RASPBERRY_PI_PICO, ADAFRUIT_FEATHER_RP2040 and GENERIC_RP2040**, using [**Earle Philhower's arduino-pico core**](https://github.com/earlephilhower/arduino-pico). +2. RP2040-based boards, such as **RASPBERRY_PI_PICO, ADAFRUIT_FEATHER_RP2040 and GENERIC_RP2040**, using [**Arduino-mbed RP2040** core](https://github.com/arduino/ArduinoCore-mbed). + +#### New support from v2.5.0 + +1. **SAMD_MKR1000 and SAMD_MKRWIFI1010** using WiFi101 + +#### New support from v2.4.0 + +1. **STM32F/L/H/G/WB/MP1 (Nucleo-144 NUCLEO_F767ZI, Nucleo-64 NUCLEO_L053R8, etc.)** using Built-in LAN8742A Ethernet +2. **Teensy 4.1** using NativeEthernet +3. **Teensy** using W5x00, ENC28J60 Ethernet, WiFiNINA + +#### New support from v2.3.4 + +1. **SSL support** to WiFiNINA +2. **SSL support** to boards using **Realtek RTL8720DN WiFi and Seeed_Arduino_rpcWiFi (WIO_Terminal, etc.)** +3. **Teensy** using W5x00, ENC28J60 Ethernet, WiFiNINA + +#### New support from v2.3.2 + +1. **Realtek RTL8720DN WiFi** using [**Seeed_Arduino_rpcWiFi**](https://github.com/Seeed-Studio/Seeed_Arduino_rpcWiFi) and [**Seeed_Arduino_rpcUnified**](https://github.com/khoih-prog/Seeed_Arduino_rpcUnified) libraries. This RTL8720DN supports Dual-Band 2.4GHz / 5GHz Wi-Fi (802.11 a/b/g/n) as well as BLE/BLE 5.0 and is currently used in SeeedStudio **SEEED_WIO_TERMINAL**. + +#### New support from v2.3.1 + +1. **ENC28J60's EthernetENC Library.** + +#### New support from v2.2.3 + +1. **STM32F/L/H/G/WB/MP1 (Nucleo-144 NUCLEO_F767ZI, Nucleo-64 NUCLEO_L053R8, etc.)** +2. **Seeeduino SAMD21/SAMD51 boards (SEEED_WIO_TERMINAL, SEEED_FEMTO_M0, SEEED_XIAO_M0, Wio_Lite_MG126, WIO_GPS_BOARD, SEEEDUINO_ZERO, SEEEDUINO_LORAWAN, SEEED_GROVE_UI_WIRELESS, etc.)** +3. **W5x00's Ethernet2, Ethernet3, EthernetLarge Libraries.** + +#### New support from v2.2.2 + +1. **Teensy** boards, such as **Teensy 4.1, 4.0. 3.6, 3.5, 3.2/3.1, 3.0, LC.**. +2. **STM32 (Nucleo-144, Nucleo-64, Nucleo-32, Discovery, STM32F1, STM32F3, STM32F4, STM32H7, STM32L0, etc.)**. +3. **SAM DUE** +4. WebSocketServer for those supported boards. + +#### New support from v2.1.3 + +1. **nRF52** boards, such as **AdaFruit Feather nRF52832, nRF52840 Express, BlueFruit Sense, Itsy-Bitsy nRF52840 Express, Metro nRF52840 Express, NINA_B30_ublox, etc.** +2. **SAM51 (Itsy-Bitsy M4, Metro M4, Grand Central M4, Feather M4 Express, etc.) and SAM DUE**. +3. **SAMD21 (ZERO, MKR, NANO_33_IOT, M0, M0 Pro, AdaFruit CIRCUITPLAYGROUND_EXPRESS, etc.)** + +#### Note: + + Version 2.0.0 and up is not compatible with AVR/ATmega, check ATmega branch. + + Version 2.3.0 has API changes for the ESP8266 BearSSL (may break existing code) + + Arduino for AVR not supports std namespace of c++. diff --git a/src/keywords.txt b/src/keywords.txt new file mode 100644 index 00000000..168356cd --- /dev/null +++ b/src/keywords.txt @@ -0,0 +1,91 @@ +####################################### +# Data types (KEYWORD1) +####################################### +WSclientsStatus_t KEYWORD1 +WStype_t KEYWORD1 +WSopcode_t KEYWORD1 +WSMessageHeader_t KEYWORD1 +WSclient_t KEYWORD1 +WebSockets KEYWORD1 +WebSocketsClient KEYWORD1 +WebSocketsServerCore KEYWORD1 +WebSocketsServer KEYWORD1 +WebSocketServerEvent KEYWORD1 +WebSocketServerHttpHeaderValFunc KEYWORD1 +engineIOmessageType_t KEYWORD1 +SocketIOclient KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +############################## +# WebSocketsClient_Generic +############################## + +begin KEYWORD2 +beginSSL KEYWORD2 +beginSslWithCA KEYWORD2 +beginSocketIO KEYWORD2 +beginSocketIOSSL KEYWORD2 +beginSocketIOSSLWithCA KEYWORD2 +loop KEYWORD2 +onEvent KEYWORD2 +sendTXT KEYWORD2 +sendBIN KEYWORD2 +sendPing KEYWORD2 +disconnect KEYWORD2 +setAuthorization KEYWORD2 +setExtraHeaders KEYWORD2 +setReconnectInterval KEYWORD2 +enableHeartbeat KEYWORD2 +disableHeartbeat KEYWORD2 + +############################## +# WebSocketsServer_Generic +############################## + +close KEYWORD2 +begin KEYWORD2 +loop KEYWORD2 +onEvent KEYWORD2 +onValidateHttpHeader KEYWORD2 +sendTXT KEYWORD2 +broadcastTXT KEYWORD2 +sendBIN KEYWORD2 +broadcastBIN KEYWORD2 +sendPing KEYWORD2 +broadcastPing KEYWORD2 +disconnect KEYWORD2 +setAuthorization KEYWORD2 +connectedClients KEYWORD2 +clientIsConnected KEYWORD2 +enableHeartbeat KEYWORD2 +disableHeartbeat KEYWORD2 +remoteIP KEYWORD2 +loop KEYWORD2 +newClient KEYWORD2 + +############################## +# SocketIOclient_Generic +############################## + +begin KEYWORD2 +isConnected KEYWORD2 +onEvent KEYWORD2 +sendEVENT KEYWORD2 +send KEYWORD2 +loop KEYWORD2 +setReconnectInterval KEYWORD2 +setExtraHeaders KEYWORD2 + +####################################### +# Literals (LITERAL1) +####################################### + +WEBSOCKETS_GENERIC_VERSION LITERAL1 +WEBSOCKETS_GENERIC_VERSION_MAJOR LITERAL1 +WEBSOCKETS_GENERIC_VERSION_MINOR LITERAL1 +WEBSOCKETS_GENERIC_VERSION_PATCH LITERAL1 +WEBSOCKETS_GENERIC_VERSION_INT LITERAL1 + diff --git a/src/library.json b/src/library.json new file mode 100644 index 00000000..3e5071f7 --- /dev/null +++ b/src/library.json @@ -0,0 +1,157 @@ +{ + "name": "WebSockets_Generic", + "version": "2.14.0", + "description": "RFC6455-based WebSockets Server and Client for Arduino boards, such as nRF52, Portenta_H7, SAMD21, SAMD51, STM32F/L/H/G/WB/MP1, Teensy, SAM DUE, RP2040-based boards, besides ESP8266/ESP32 ESP32 (ESP32, ESP32_S2, ESP32_S3 and ESP32_C3) and WT32_ETH01. Ethernet shields W5100, W5200, W5500, ENC28J60, Teensy 4.1 NativeEthernet/QNEthernet or Portenta_H7 WiFi/Ethernet. Now supporting websocket only mode for Socket.IO", + "keywords": "wifi, WiFiNINA, websocket, websockets-server, websockets-client, Teensy, SAM DUE, SAMD, STM32, nRF52, QNEthernet, rp2040, Portenta-H7, ESP32, ESP8266, W5x00, Ethernet, Ethernet2, Ethernet3, EthernetLarge, EthernetENC, UIPEthernet, NativeEthernet, ENC28J60, rpi-pico, http, web, server, client, Mega", + "authors": [ + { + "name": "Markus Sattler", + "url": "https://github.com/Links2004" + }, + { + "name": "Khoi Hoang", + "url": "https://github.com/khoih-prog", + "email": "khoih.prog@gmail.com", + "maintainer": true + } + ], + "repository": + { + "type": "git", + "url": "https://github.com/khoih-prog/WebSockets_Generic" + }, + "homepage": "https://github.com/khoih-prog/WebSockets_Generic", + "export": { + "exclude": [ + "linux", + "extras", + "tests" + ] + }, + "dependencies": + [ + { + "owner": "khoih-prog", + "name": "WiFiNINA_Generic", + "version": ">=1.8.14-3", + "platforms": ["*"] + }, + { + "owner": "khoih-prog", + "name": "DoubleResetDetector_Generic", + "version": ">=1.8.0", + "platforms": ["*"] + }, + { + "owner": "khoih-prog", + "name": "FlashStorage_SAMD", + "version": ">=1.3.2", + "platforms": ["*"] + }, + { + "owner": "sebnil", + "name": "DueFlashStorage", + "version": ">=1.0.0", + "platforms": ["*"] + }, + { + "owner": "khoih-prog", + "name": "WiFiWebServer", + "version": ">=1.6.1", + "platforms": ["*"] + }, + { + "owner": "khoih-prog", + "name": "EthernetWebServer", + "version": ">=2.0.0", + "platforms": ["*"] + }, + { + "owner": "khoih-prog", + "name": "WebServer_WT32_ETH01", + "version": "^1.4.1", + "platforms": ["espressif32"] + }, + { + "owner": "khoih-prog", + "name": "EthernetWebServer_STM32", + "version": ">=1.3.3", + "platforms": ["ststm32"] + }, + { + "owner": "khoih-prog", + "name": "SinricPro_Generic", + "version": ">=2.8.4", + "platforms": ["*"] + }, + { + "owner": "stm32duino", + "name": "STM32duino LwIP", + "version": ">=2.1.2", + "platforms": ["ststm32"] + }, + { + "owner": "stm32duino", + "name": "STM32Ethernet", + "version": ">=1.2.0", + "platforms": ["ststm32"] + }, + { + "owner": "uipethernet", + "name": "UIPEthernet", + "version": ">=2.0.8", + "platforms": ["atmelavr", "atmelmegaavr", "atmelsam", "espressif8266", "intel_arc32", "nordicnrf51", "nxplpc", "ststm32", "teensy"] + }, + { + "owner": "jandrassy", + "name": "EthernetENC", + "version": ">=2.0.2", + "platforms": ["*"] + }, + { + "owner": "jandrassy", + "name": "WiFiEspAT", + "version": ">=1.3.2", + "platforms": ["*"] + }, + { + "owner": "adafruit", + "name": "Ethernet2", + "version": ">=1.0.4", + "platforms": ["*"] + }, + { + "owner": "sstaub", + "name": "Ethernet3", + "version": ">=1.5.5", + "platforms": ["*"] + }, + { + "owner": "arduino-libraries", + "name": "Ethernet", + "version": ">=2.0.0", + "platforms": ["*"] + }, + { + "owner": "openslab-osu", + "name": "EthernetLarge", + "version": ">=2.0.0", + "platforms": ["*"] + }, + { + "name": "WiFi101", + "version": "https://github.com/khoih-prog/WiFi101" + }, + { + "owner": "ssilverman", + "name": "QNEthernet", + "version": ">=0.13.0", + "platforms": ["teensy"] + } + ], + "license": "LGPL-3.0", + "frameworks": "*", + "platforms": "*", + "examples": "examples/*/*/*.ino", + "headers": ["WebSocketsClient_Generic.h", "WebSocketsServer_Generic.h", "SocketIOclient_Generic"] +} diff --git a/src/library.properties b/src/library.properties new file mode 100644 index 00000000..1c4e657e --- /dev/null +++ b/src/library.properties @@ -0,0 +1,11 @@ +name=WebSockets_Generic +version=2.14.0 +author=Markus Sattler, Khoi Hoang +maintainer=Khoi Hoang +sentence=RFC6455-based WebSockets Server and Client for Arduino boards, such as nRF52, Portenta_H7, SAMD21, SAMD51, STM32F/L/H/G/WB/MP1, Teensy, SAM DUE, RP2040-based boards, besides ESP8266/ESP32 (ESP32, ESP32_S2, ESP32_S3 and ESP32_C3) and WT32_ETH01. Ethernet shields W5100, W5200, W5500, ENC28J60, Teensy 4.1 NativeEthernet/QNEthernet or Portenta_H7 WiFi/Ethernet. Now supporting websocket only mode for Socket.IO +paragraph=Use v2.2.2+ for ESP, nRF52, SAMD21, SAMD51, STM32F/L/H/G/WB/MP1, Teensy, SAM DUE, RP2040-based boards, WT32_ETH01, Portenta_H7, etc. +category=Communication +url=https://github.com/khoih-prog/WebSockets_Generic +architectures=* +depends=WiFiNINA_Generic, WiFiWebServer, EthernetWebServer, WebServer_WT32_ETH01, EthernetWebServer_STM32, DoubleResetDetector_Generic, SinricPro_Generic, FlashStorage_SAMD +includes=WebSocketsClient_Generic.h, WebSocketsServer_Generic.h,SocketIOclient_Generic diff --git a/src/platformio/platformio.ini b/src/platformio/platformio.ini new file mode 100644 index 00000000..8bdb5953 --- /dev/null +++ b/src/platformio/platformio.ini @@ -0,0 +1,379 @@ +;PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[platformio] +; ============================================================ +; chose environment: +; ESP8266 +; ESP32 +; SAMD +; NRF52 +; STM32 +; ============================================================ +;default_envs = ESP8266 +;default_envs = ESP32 +default_envs = SAMD +;default_envs = NRF52 +;default_envs = STM32 +;default_envs = portenta_h7_m7 +;default_envs = portenta_h7_m4 + +[env] +; ============================================================ +; Serial configuration +; choose upload speed, serial-monitor speed +; ============================================================ +upload_speed = 921600 +;upload_port = COM11 +;monitor_speed = 9600 +;monitor_port = COM11 + +; Checks for the compatibility with frameworks and dev/platforms +lib_compat_mode = strict + +lib_deps = +; PlatformIO 4.x + WiFiNINA_Generic@~1.8.14-3 + WiFiWebServer@~1.6.1 + EthernetWebServer@~2.0.0 + WebServer_WT32_ETH01@~1.4.1 + EthernetWebServer_STM32@>=1.3.3 + Ethernet@~2.0.0 + EthernetLarge@~2.0.0 + Ethernet2@~1.0.4 + Ethernet3@~1.5.5 + EthernetENC@~2.0.2 + UIPEthernet@~2.0.8 + STM32duino LwIP@>=2.1.2 + STM32duino STM32Ethernet@>=1.2.0 + DoubleResetDetector_Generic@>=1.8.0 + SinricPro_Generic@>=2.8.4 + FlashStorage_SAMD@>=1.3.2 + FlashStorage_STM32@~1.2.0 + QNEthernet@~0.13.0 + https://github.com/khoih-prog/WiFi101 +; PlatformIO 5.x +; khoih-prog/WiFiNINA_Generic@~1.8.14-3 +; khoih-prog/WiFiWebServer@~1.6.1 +; khoih-prog/EthernetWebServer@~2.0.0 +; khoih-prog/WebServer_WT32_ETH01@~1.4.1 +; khoih-prog/EthernetWebServer_STM32@>=1.3.3 +; PaulStoffregen/Ethernet@~2.0.0 +; PaulStoffregen/EthernetLarge@~2.0.0 +; adafruit/Ethernet2@~1.0.4 +; sstaub/Ethernet3@~1.5.5 +; jandrassy/EthernetENC@~2.0.2 +; UIPEthernet/UIPEthernet@~2.0.8 +; stm32duino/STM32duino LwIP@>=2.1.2 +; stm32duino/STM32duino STM32Ethernet@>=1.2.0 +; khoih-prog/DoubleResetDetector_Generic@>=1.8.0 +; khoih-prog/SinricPro_Generic@>=2.8.4 +; khoih-prog/FlashStorage_SAMD@~1.3.2 +; khoih-prog/FlashStorage_STM32@~1.2.0 +; ssilverman/QNEthernet@~0.13.0 +; https://github.com/khoih-prog/WiFi101 + +build_flags = +; set your debug output (default=Serial) +; -D DEBUG_ESP_PORT=Serial +; comment the folowing line to enable WiFi debugging +; -D NDEBUG + +[env:ESP8266] +platform = espressif8266 +framework = arduino +; ============================================================ +; Board configuration +; choose your board by uncommenting one of the following lines +; ============================================================ +;board = gen4iod +;board = huzzah +;board = oak +;board = esp_wroom_02 +;board = espduino +;board = espectro +;board = espino +;board = espresso_lite_v1 +;board = espresso_lite_v2 +;board = esp12e +;board = esp01_1m +;board = esp01 +;board = esp07 +;board = esp8285 +;board = heltec_wifi_kit_8 +;board = inventone +;board = nodemcu +board = nodemcuv2 +;board = modwifi +;board = phoenix_v1 +;board = phoenix_v2 +;board = sparkfunBlynk +;board = thing +;board = thingdev +;board = esp210 +;board = espinotee +;board = d1 +;board = d1_mini +;board = d1_mini_lite +;board = d1_mini_pro +;board = wifi_slot +;board = wifiduino +;board = wifinfo +;board = wio_link +;board = wio_node +;board = xinabox_cw01 +;board = esp32doit-devkit-v1 + +[env:ESP32] +platform = espressif32 +framework = arduino, espidf +; ============================================================ +; Board configuration +; choose your board by uncommenting one of the following lines +; ============================================================ +;board = esp32cam +;board = alksesp32 +;board = featheresp32 +;board = espea32 +;board = bpi-bit +;board = d-duino-32 +board = esp32doit-devkit-v1 +;board = pocket_32 +;board = fm-devkit +;board = pico32 +;board = esp32-evb +;board = esp32-gateway +;board = esp32-pro +;board = esp32-poe +;board = oroca_edubot +;board = onehorse32dev +;board = lopy +;board = lopy4 +;board = wesp32 +;board = esp32thing +;board = sparkfun_lora_gateway_1-channel +;board = ttgo-lora32-v1 +;board = ttgo-t-beam +;board = turta_iot_node +;board = lolin_d32 +;board = lolin_d32_pro +;board = lolin32 +;board = wemosbat +;board = widora-air +;board = xinabox_cw02 +;board = iotbusio +;board = iotbusproteus +;board = nina_w10 + +[env:SAMD] +platform = atmelsam +framework = arduino +; ============================================================ +; Choose your board by uncommenting one of the following lines +; ============================================================ +; ============================================================ +; Board configuration Adafruit SAMD +; ============================================================ + +;board = adafruit_feather_m0 +;board = adafruit_feather_m0_express +;board = adafruit_metro_m0 +;board = adafruit_circuitplayground_m0 +;board = adafruit_gemma_m0 +;board = adafruit_trinket_m0 +;board = adafruit_itsybitsy_m0 +;board = adafruit_pirkey +;board = adafruit_hallowing +;board = adafruit_crickit_m0 +;board = adafruit_metro_m4 +;board = adafruit_grandcentral_m4 +board = adafruit_itsybitsy_m4 +;board = adafruit_feather_m4 +;board = adafruit_trellis_m4 +;board = adafruit_pyportal_m4 +;board = adafruit_pyportal_m4_titano +;board = adafruit_pybadge_m4 +;board = adafruit_metro_m4_airliftlite +;board = adafruit_pygamer_m4 +;board = adafruit_pygamer_advance_m4 +;board = adafruit_pybadge_airlift_m4 +;board = adafruit_monster_m4sk +;board = adafruit_hallowing_m4 + +; ============================================================ +; Board configuration Arduino SAMD and SAM +; ============================================================ + +;board = arduino_zero_edbg +;board = arduino_zero_native +;board = mkr1000 +;board = mkrzero +;board = mkrwifi1010 +;board = nano_33_iot +;board = mkrfox1200 +;board = mkrwan1300 +;board = mkrwan1310 +;board = mkrgsm1400 +;board = mkrnb1500 +;board = mkrvidor4000 +;board = adafruit_circuitplayground_m0 +;board = mzero_pro_bl_dbg +;board = mzero_pro_bl +;board = mzero_bl +;board = tian +;board = tian_cons +;board = arduino_due_x_dbg +;board = arduino_due_x + +; ============================================================ +; Board configuration Seeeduino SAMD +; ============================================================ + +;board = seeed_wio_terminal +;board = Seeed_femto_m0 +;board = seeed_XIAO_m0 +;board = Wio_Lite_MG126 +;board = WioGPS +;board = zero +;board = rolawan +;board = seeed_grove_ui_wireless + + +[env:NRF52] +platform = nordicnrf52 +framework = arduino +; ============================================================ +; Board configuration Adafruit nRF52 +; choose your board by uncommenting one of the following lines +; ============================================================ +;board = feather52832 +board = feather52840 +;board = feather52840sense +;board = itsybitsy52840 +;board = cplaynrf52840 +;board = cluenrf52840 +;board = metro52840 +;board = pca10056 +;board = particle_xenon +;board = mdbt50qrx +;board = ninab302 +;board = ninab112 + +[env:STM32] +platform = ststm32 +framework = arduino + +; ============================================================ +; Choose your board by uncommenting one of the following lines +; ============================================================ + +; ============================================================ +; Board configuration Nucleo-144 +; ============================================================ + +;board = nucleo_f207zg +;board = nucleo_f429zi +;board = nucleo_f746zg +;board = nucleo_f756zg +;board = nucleo_f767zi +;board = nucleo_h743zi +;board = nucleo_l496zg +;board = nucleo_l496zg-p +;board = nucleo_l4r5zi +;board = nucleo_l4r5zi-p + +; ============================================================ +; Board configuration Nucleo-64 +; ============================================================ + +;board = nucleo_f030r8 +;board = nucleo_f072rb + +;board = nucleo_f091rc +;board = nucleo_f103rb +;board = nucleo_f302r8 +;board = nucleo_f303re +;board = nucleo_f401re +;board = nucleo_f411re +;board = nucleo_f446re +;board = nucleo_g071rb +;board = nucleo_g431rb +;board = nucleo_g474re +;board = nucleo_l053r8 +;board = nucleo_l073rz +;board = nucleo_l152re +;board = nucleo_l433rc_p +;board = nucleo_l452re +;board = nucleo_l452re-p +;board = nucleo_l476rg +;board = pnucleo_wb55rg + +; ============================================================ +; Board configuration Nucleo-32 +; ============================================================ + +;board = nucleo_f031k6 +;board = nucleo_l031k6 +;board = nucleo_l412kb +;board = nucleo_l432lc +;board = nucleo_f303k8 +;board = nucleo_g431kb + +; ============================================================ +; Board configuration Discovery Boards +; ============================================================ + +;board = disco_f030r8 +;board = disco_f072rb +;board = disco_f030r8 +;board = disco_f100rb +;board = disco_f407vg +;board = disco_f413zh +;board = disco_f746ng +;board = disco_g0316 +;board = disco_l475vg_iot +;board = disco_f072cz-lrwan1 + +; ============================================================ +; Board configuration STM32MP1 Boards +; ============================================================ + +;board = stm32mp157a-dk1 +;board = stm32mp157c-dk2 + +; ============================================================ +; Board configuration Generic Boards +; ============================================================ + +;board = bluepill_f103c6 +;board = bluepill_f103c8 +;board = blackpill_f103c8 +;board = stm32f103cx +;board = stm32f103rx +;board = stm32f103tx +;board = stm32f103vx +;board = stm32f103zx +;board = stm32f103zet6 +;board = maplemini_f103cb +;board = blackpill_f303cc +;board = black_f407ve +;board = black_f407vg +;board = black_f407ze +;board = black_f407zg +;board = blue_f407ve_mini +;board = blackpill_f401cc +;board = blackpill_f411ce +;board = coreboard_f401rc +;board = feather_f405 + +; ============================================================ +; Board configuration Many more Boards to be filled +; ============================================================ + diff --git a/src/src/SocketIOclient_Generic-Impl.h b/src/src/SocketIOclient_Generic-Impl.h new file mode 100644 index 00000000..13f9a9f3 --- /dev/null +++ b/src/src/SocketIOclient_Generic-Impl.h @@ -0,0 +1,400 @@ +/**************************************************************************************************************************** + SocketIOclient_Generic-Impl.h - WebSockets Library for boards + + Based on and modified from WebSockets libarary https://github.com/Links2004/arduinoWebSockets + to support other boards such as SAMD21, SAMD51, Adafruit's nRF52 boards, etc. + + Built by Khoi Hoang https://github.com/khoih-prog/WebSockets_Generic + Licensed under MIT license + + @original file SocketIOclient.cpp + @Created on: May 12, 2018 + @Author: links + + Copyright (c) 2015 Markus Sattler. All rights reserved. + This file is part of the WebSockets for Arduino. + + 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 St, Fifth Floor, Boston, MA 02110-1301 USA + + Version: 2.14.0 + + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 2.1.3 K Hoang 15/05/2020 Initial porting to support SAMD21, SAMD51, nRF52 boards, such as AdaFruit Feather nRF52832, + nRF52840 Express, BlueFruit Sense, Itsy-Bitsy nRF52840 Express, Metro nRF52840 Express, etc. + 2.2.1 K Hoang 18/05/2020 Bump up to sync with v2.2.1 of original WebSockets library + 2.2.2 K Hoang 25/05/2020 Add support to Teensy, SAM DUE and STM32. Enable WebSocket Server for new supported boards. + 2.2.3 K Hoang 02/08/2020 Add support to W5x00's Ethernet2, Ethernet3, EthernetLarge Libraries. + Add support to STM32F/L/H/G/WB/MP1 and Seeeduino SAMD21/SAMD51 boards. + 2.3.1 K Hoang 07/10/2020 Sync with v2.3.1 of original WebSockets library. Add ENC28J60 EthernetENC library support + 2.3.2 K Hoang 12/11/2020 Add RTL8720DN Seeed_Arduino_rpcWiFi library support + 2.3.3 K Hoang 28/11/2020 Fix compile error for WIO_TERMINAL and boards using libraries with lib64. + 2.3.4 K Hoang 12/12/2020 Add SSL support to SAMD21 Nano-33-IoT using WiFiNINA. Upgrade WS and WSS examples. + 2.4.0 K Hoang 06/02/2021 Add support to Teensy 4.1 NativeEthernet and STM32 built-in LAN8742A. + Sync with v2.3.4 of original WebSockets library + 2.4.1 K Hoang 19/03/2021 Sync with v2.3.5 of original WebSockets library to adapt to ESP32 SSL changes + 2.5.0 K Hoang 22/05/2021 Add support to WiFi101 + 2.5.1 K Hoang 22/05/2021 Default to EIO4 for Socket.IO. Permit increase reconnectInterval in Socket.IO + 2.6.0 K Hoang 23/05/2021 Fix breaking problem with SocketIO. Add setExtraHeaders to SocketIO + 2.7.0 K Hoang 24/05/2021 Add support to RP2040-based boards using Arduino-pico and Arduino mbed_rp2040 core + 2.8.0 K Hoang 08/07/2021 Add support to WT32_ETH01 (ESP32 + LAN8720) boards + 2.9.0 K Hoang 05/09/2021 Add support to QNEthernet Library for Teensy 4.1 + 2.10.0 K Hoang 18/09/2021 Add support to Portenta_H7, using either WiFi or Vision-shield Ethernet + 2.10.1 K Hoang 12/10/2021 Update `platform.ini` and `library.json` + 2.11.0 K Hoang 30/11/2021 Auto detect ESP32 core version. Fix bug in examples + 2.11.1 K Hoang 12/12/2021 Add option to use transport=websocket with sticky-session SIO server + 2.12.0 K Hoang 28/01/2022 Supporting SSL for ESP32-based WT32_ETH01 boards + 2.13.0 K Hoang 14/02/2022 Add support to ESP32_S3. Add PING and PONG SocketIO events + 2.14.0 K Hoang 17/02/2022 Suppress unnecessary warnings. Optimize code by passing by reference instead of value + *****************************************************************************************************************************/ + +#pragma once + +#ifndef SOCKET_IO_CLIENT_GENERIC_IMPL_H_ +#define SOCKET_IO_CLIENT_GENERIC_IMPL_H_ + +#include "WebSocketsClient_Generic.h" + +SocketIOclient::SocketIOclient() +{ +} + +SocketIOclient::~SocketIOclient() +{ +} + +void SocketIOclient::begin(const char * host, const uint16_t& port, const char * url, const char * protocol) +{ + WebSocketsClient::beginSocketIO(host, port, url, protocol); + WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5); + initClient(); +} + +void SocketIOclient::begin(const String& host, const uint16_t& port, const String& url, const String& protocol) +{ + WebSocketsClient::beginSocketIO(host, port, url, protocol); + WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5); + initClient(); +} + +void SocketIOclient::begin(const IPAddress& host, const uint16_t& port, const String& url, const String& protocol) +{ + WebSocketsClient::beginSocketIO(host, port, url, protocol); + WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5); + initClient(); +} + +#if defined(HAS_SSL) +void SocketIOclient::beginSSL(const char * host, const uint16_t& port, const char * url, const char * protocol) +{ + WebSocketsClient::beginSocketIOSSL(host, port, url, protocol); + WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5); + initClient(); +} + +void SocketIOclient::beginSSL(const String& host, const uint16_t& port, const String& url, const String& protocol) +{ + WebSocketsClient::beginSocketIOSSL(host, port, url, protocol); + WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5); + initClient(); +} + +#if defined(SSL_BARESSL) +void SocketIOclient::beginSSLWithCA(const char * host, const uint16_t& port, const char * url, + const char * CA_cert, const char * protocol) +{ + WebSocketsClient::beginSocketIOSSLWithCA(host, port, url, CA_cert, protocol); + WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5); + initClient(); +} + +void SocketIOclient::beginSSLWithCA(const char * host, const uint16_t& port, const char * url, + BearSSL::X509List * CA_cert, const char * protocol) +{ + WebSocketsClient::beginSocketIOSSLWithCA(host, port, url, CA_cert, protocol); + WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5); + initClient(); +} + +void SocketIOclient::setSSLClientCertKey(const char * clientCert, const char * clientPrivateKey) +{ + WebSocketsClient::setSSLClientCertKey(clientCert, clientPrivateKey); +} + +void SocketIOclient::setSSLClientCertKey(BearSSL::X509List * clientCert, BearSSL::PrivateKey * clientPrivateKey) +{ + WebSocketsClient::setSSLClientCertKey(clientCert, clientPrivateKey); +} + +#endif +#endif + +void SocketIOclient::configureEIOping(bool disableHeartbeat) +{ + _disableHeartbeat = disableHeartbeat; +} + +void SocketIOclient::initClient() +{ + if(_client.cUrl.indexOf("EIO=4") != -1) + { + WSK_LOGINFO("[wsIOc] found EIO=4 disable EIO ping on client"); + configureEIOping(true); + } +} + +/** + set callback function + @param cbEvent SocketIOclientEvent +*/ +void SocketIOclient::onEvent(SocketIOclientEvent cbEvent) +{ + _cbEvent = cbEvent; +} + +bool SocketIOclient::isConnected() +{ + return WebSocketsClient::isConnected(); +} + +/** + send text data to client + @param num uint8_t client id + @param type socketIOmessageType_t + @param payload uint8_t + @param length size_t + @param headerToPayload bool (see sendFrame for more details) + @return true if ok +*/ +bool SocketIOclient::send(socketIOmessageType_t type, uint8_t * payload, size_t length, bool headerToPayload) +{ + bool ret = false; + + if (length == 0) + { + length = strlen((const char *)payload); + } + + if (clientIsConnected(&_client) && _client.status == WSC_CONNECTED) + { + if (!headerToPayload) + { + // webSocket Header + ret = WebSocketsClient::sendFrameHeader(&_client, WSop_text, length + 2, true); + + // Engine.IO / Socket.IO Header + if (ret) + { + uint8_t buf[3] = { eIOtype_MESSAGE, type, 0x00 }; + ret = WebSocketsClient::write(&_client, buf, 2); + } + + if (ret && payload && length > 0) + { + ret = WebSocketsClient::write(&_client, payload, length); + } + + return ret; + } + else + { + // TODO implement + } + } + + return false; +} + +bool SocketIOclient::send(socketIOmessageType_t type, const uint8_t * payload, size_t length) +{ + return send(type, (uint8_t *)payload, length); +} + +bool SocketIOclient::send(socketIOmessageType_t type, char * payload, size_t length, bool headerToPayload) +{ + return send(type, (uint8_t *)payload, length, headerToPayload); +} + +bool SocketIOclient::send(socketIOmessageType_t type, const char * payload, size_t length) +{ + return send(type, (uint8_t *)payload, length); +} + +bool SocketIOclient::send(socketIOmessageType_t type, const String& payload) +{ + return send(type, (uint8_t *)payload.c_str(), payload.length()); +} + +/** + send text data to client + @param num uint8_t client id + @param payload uint8_t + @param length size_t + @param headerToPayload bool (see sendFrame for more details) + @return true if ok +*/ +bool SocketIOclient::sendEVENT(uint8_t * payload, size_t length, bool headerToPayload) +{ + return send(sIOtype_EVENT, payload, length, headerToPayload); +} + +bool SocketIOclient::sendEVENT(const uint8_t * payload, size_t length) +{ + return sendEVENT((uint8_t *)payload, length); +} + +bool SocketIOclient::sendEVENT(char * payload, size_t length, bool headerToPayload) +{ + return sendEVENT((uint8_t *)payload, length, headerToPayload); +} + +bool SocketIOclient::sendEVENT(const char * payload, size_t length) +{ + return sendEVENT((uint8_t *)payload, length); +} + +bool SocketIOclient::sendEVENT(const String& payload) +{ + return sendEVENT((uint8_t *)payload.c_str(), payload.length()); +} + +void SocketIOclient::loop() +{ + WebSocketsClient::loop(); + unsigned long t = millis(); + + if(!_disableHeartbeat && (t - _lastHeartbeat) > EIO_HEARTBEAT_INTERVAL) + { + _lastHeartbeat = t; + WSK_LOGINFO("[wsIOc] send ping\n"); + WebSocketsClient::sendTXT(eIOtype_PING); + } +} + +void SocketIOclient::handleCbEvent(WStype_t type, uint8_t * payload, size_t length) +{ + switch (type) + { + case WStype_DISCONNECTED: + runIOCbEvent(sIOtype_DISCONNECT, NULL, 0); + + WSK_LOGINFO("[wsIOc] Disconnected!"); + + break; + case WStype_CONNECTED: + { + WSK_LOGWARN1("[wsIOc] Connected to url:", (char *) payload); + + // send message to server when Connected + // Engine.io upgrade confirmation message (required) + WebSocketsClient::sendTXT("2probe"); + WebSocketsClient::sendTXT(eIOtype_UPGRADE); + runIOCbEvent(sIOtype_CONNECT, payload, length); + } + + break; + case WStype_TEXT: + { + if (length < 1) + { + break; + } + + engineIOmessageType_t eType = (engineIOmessageType_t)payload[0]; + + switch (eType) + { + case eIOtype_PING: + payload[0] = eIOtype_PONG; + + WSK_LOGWARN1("[wsIOc] get ping send pong:", (char *) payload); + + WebSocketsClient::sendTXT(payload, length, false); + runIOCbEvent(sIOtype_PING, payload, length); + + break; + case eIOtype_PONG: + WSK_LOGWARN("[wsIOc] get pong"); + runIOCbEvent(sIOtype_PONG, payload, length); + + break; + case eIOtype_MESSAGE: + { + if (length < 2) + { + break; + } + + socketIOmessageType_t ioType = (socketIOmessageType_t)payload[1]; + uint8_t * data = &payload[2]; + size_t lData = length - 2; + + switch (ioType) + { + case sIOtype_EVENT: + WSK_LOGWARN1("[wsIOc] get event: len = ", lData); + WSK_LOGWARN1("[wsIOc] get data: ", (char *) data); + + break; + case sIOtype_CONNECT: + WSK_LOGWARN1("[wsIOc] connected: len = ", lData); + WSK_LOGWARN1("[wsIOc] data: ", (char *) data); + return; + + case sIOtype_DISCONNECT: + case sIOtype_ACK: + case sIOtype_ERROR: + case sIOtype_BINARY_EVENT: + case sIOtype_BINARY_ACK: + default: + WSK_LOGINFO1("[wsIOc] Socket.IO Message Type is not implemented:", ioType); + WSK_LOGWARN1("[wsIOc] get text:", (char *) payload); + + break; + } + + runIOCbEvent(ioType, data, lData); + } + + break; + + case eIOtype_OPEN: + case eIOtype_CLOSE: + case eIOtype_UPGRADE: + case eIOtype_NOOP: + default: + WSK_LOGINFO1("[wsIOc] Socket.IO Message Type is not implemented:", eType); + WSK_LOGWARN1("[wsIOc] get text:", (char *) payload); + + break; + } + } + + break; + case WStype_ERROR: + case WStype_BIN: + case WStype_FRAGMENT_TEXT_START: + case WStype_FRAGMENT_BIN_START: + case WStype_FRAGMENT: + case WStype_FRAGMENT_FIN: + case WStype_PING: + case WStype_PONG: + break; + } +} + +#endif // SOCKET_IO_CLIENT_GENERIC_IMPL_H_ + + diff --git a/src/src/SocketIOclient_Generic.h b/src/src/SocketIOclient_Generic.h new file mode 100644 index 00000000..7161460e --- /dev/null +++ b/src/src/SocketIOclient_Generic.h @@ -0,0 +1,201 @@ +/**************************************************************************************************************************** + SocketIOclient_Generic.h - WebSockets Library for boards + + Based on and modified from WebSockets libarary https://github.com/Links2004/arduinoWebSockets + to support other boards such as SAMD21, SAMD51, Adafruit's nRF52 boards, etc. + + Built by Khoi Hoang https://github.com/khoih-prog/WebSockets_Generic + Licensed under MIT license + + @original file SocketIOclient.h + @Created on: May 12, 2018 + @Author: links + + Copyright (c) 2015 Markus Sattler. All rights reserved. + This file is part of the WebSockets for Arduino. + + 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 St, Fifth Floor, Boston, MA 02110-1301 USA + + Version: 2.14.0 + + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 2.1.3 K Hoang 15/05/2020 Initial porting to support SAMD21, SAMD51, nRF52 boards, such as AdaFruit Feather nRF52832, + nRF52840 Express, BlueFruit Sense, Itsy-Bitsy nRF52840 Express, Metro nRF52840 Express, etc. + 2.2.1 K Hoang 18/05/2020 Bump up to sync with v2.2.1 of original WebSockets library + 2.2.2 K Hoang 25/05/2020 Add support to Teensy, SAM DUE and STM32. Enable WebSocket Server for new supported boards. + 2.2.3 K Hoang 02/08/2020 Add support to W5x00's Ethernet2, Ethernet3, EthernetLarge Libraries. + Add support to STM32F/L/H/G/WB/MP1 and Seeeduino SAMD21/SAMD51 boards. + 2.3.1 K Hoang 07/10/2020 Sync with v2.3.1 of original WebSockets library. Add ENC28J60 EthernetENC library support + 2.3.2 K Hoang 12/11/2020 Add RTL8720DN Seeed_Arduino_rpcWiFi library support + 2.3.3 K Hoang 28/11/2020 Fix compile error for WIO_TERMINAL and boards using libraries with lib64. + 2.3.4 K Hoang 12/12/2020 Add SSL support to SAMD21 Nano-33-IoT using WiFiNINA. Upgrade WS and WSS examples. + 2.4.0 K Hoang 06/02/2021 Add support to Teensy 4.1 NativeEthernet and STM32 built-in LAN8742A. + Sync with v2.3.4 of original WebSockets library + 2.4.1 K Hoang 19/03/2021 Sync with v2.3.5 of original WebSockets library to adapt to ESP32 SSL changes + 2.5.0 K Hoang 22/05/2021 Add support to WiFi101 + 2.5.1 K Hoang 22/05/2021 Default to EIO4 for Socket.IO. Permit increase reconnectInterval in Socket.IO + 2.6.0 K Hoang 23/05/2021 Fix breaking problem with SocketIO. Add setExtraHeaders to SocketIO + 2.7.0 K Hoang 24/05/2021 Add support to RP2040-based boards using Arduino-pico and Arduino mbed_rp2040 core + 2.8.0 K Hoang 08/07/2021 Add support to WT32_ETH01 (ESP32 + LAN8720) boards + 2.9.0 K Hoang 05/09/2021 Add support to QNEthernet Library for Teensy 4.1 + 2.10.0 K Hoang 18/09/2021 Add support to Portenta_H7, using either WiFi or Vision-shield Ethernet + 2.10.1 K Hoang 12/10/2021 Update `platform.ini` and `library.json` + 2.11.0 K Hoang 30/11/2021 Auto detect ESP32 core version. Fix bug in examples + 2.11.1 K Hoang 12/12/2021 Add option to use transport=websocket with sticky-session SIO server + 2.12.0 K Hoang 28/01/2022 Supporting SSL for ESP32-based WT32_ETH01 boards + 2.13.0 K Hoang 14/02/2022 Add support to ESP32_S3. Add PING and PONG SocketIO events + 2.14.0 K Hoang 17/02/2022 Suppress unnecessary warnings. Optimize code by passing by reference instead of value + *****************************************************************************************************************************/ + +#pragma once + +#ifndef SOCKET_IO_CLIENT_GENERIC_H_ +#define SOCKET_IO_CLIENT_GENERIC_H_ + +#if !defined(USING_STICKY_SESSION_SIO) + #define USING_STICKY_SESSION_SIO false +#endif + +#include "WebSockets_Generic.h" + +#define EIO_HEARTBEAT_INTERVAL 20000 + +#define EIO_MAX_HEADER_SIZE (WEBSOCKETS_MAX_HEADER_SIZE + 1) +#define SIO_MAX_HEADER_SIZE (EIO_MAX_HEADER_SIZE + 1) + +typedef enum +{ + eIOtype_OPEN = '0', ///< Sent from the server when a new transport is opened (recheck) + eIOtype_CLOSE = '1', ///< Request the close of this transport but does not shutdown the connection itself. + eIOtype_PING = '2', ///< Sent by the client. Server should answer with a pong packet containing the same data + eIOtype_PONG = '3', ///< Sent by the server to respond to ping packets. + eIOtype_MESSAGE = '4', ///< actual message, client and server should call their callbacks with the data + eIOtype_UPGRADE = '5', ///< Before engine.io switches a transport, it tests, if server and client can communicate over this transport. If this test succeed, the client sends an upgrade packets which requests the server to flush its cache on the old transport and switch to the new transport. + eIOtype_NOOP = '6', ///< A noop packet. Used primarily to force a poll cycle when an incoming websocket connection is received. +} engineIOmessageType_t; + +typedef enum +{ + sIOtype_CONNECT = '0', + sIOtype_DISCONNECT = '1', + sIOtype_EVENT = '2', + sIOtype_ACK = '3', + sIOtype_ERROR = '4', + sIOtype_BINARY_EVENT = '5', + sIOtype_BINARY_ACK = '6', + sIOtype_PING = '7', + sIOtype_PONG = '8', +} socketIOmessageType_t; + +class SocketIOclient : protected WebSocketsClient +{ + public: +#ifdef __AVR__ + typedef void (*SocketIOclientEvent)(socketIOmessageType_t type, uint8_t * payload, size_t length); +#else + typedef std::function SocketIOclientEvent; +#endif + + SocketIOclient(); + virtual ~SocketIOclient(); + + // KH, change to default EIO=4. v2.5.1 + void begin(const char * host, const uint16_t& port, const char * url = "/socket.io/?EIO=4", + const char * protocol = "arduino"); + + void begin(const String& host, const uint16_t& port, const String& url = "/socket.io/?EIO=4", + const String& protocol = "arduino"); + // KH + void begin(const IPAddress& host, const uint16_t& port, const String& url = "/socket.io/?EIO=4", + const String& protocol = "arduino"); + +#ifdef HAS_SSL + void beginSSL(const char * host, const uint16_t& port, const char * url = "/socket.io/?EIO=4", + const char * protocol = "arduino"); + + void beginSSL(const String& host, const uint16_t& port, const String& url = "/socket.io/?EIO=4", + const String& protocol = "arduino"); +#ifndef SSL_AXTLS + void beginSSLWithCA(const char * host, const uint16_t& port, const char * url = "/socket.io/?EIO=4", + const char * CA_cert = NULL, const char * protocol = "arduino"); + + void beginSSLWithCA(const char * host, const uint16_t& port, const char * url = "/socket.io/?EIO=4", + BearSSL::X509List * CA_cert = NULL, const char * protocol = "arduino"); + + void setSSLClientCertKey(const char * clientCert = NULL, const char * clientPrivateKey = NULL); + + void setSSLClientCertKey(BearSSL::X509List * clientCert = NULL, BearSSL::PrivateKey * clientPrivateKey = NULL); +#endif +#endif + + bool isConnected(); + + void onEvent(SocketIOclientEvent cbEvent); + + bool sendEVENT(uint8_t * payload, size_t length = 0, bool headerToPayload = false); + bool sendEVENT(const uint8_t * payload, size_t length = 0); + bool sendEVENT(char * payload, size_t length = 0, bool headerToPayload = false); + bool sendEVENT(const char * payload, size_t length = 0); + bool sendEVENT(const String& payload); + + bool send(socketIOmessageType_t type, uint8_t * payload, size_t length = 0, bool headerToPayload = false); + bool send(socketIOmessageType_t type, const uint8_t * payload, size_t length = 0); + bool send(socketIOmessageType_t type, char * payload, size_t length = 0, bool headerToPayload = false); + bool send(socketIOmessageType_t type, const char * payload, size_t length = 0); + bool send(socketIOmessageType_t type, const String& payload); + + void loop(); + + void configureEIOping(bool disableHeartbeat = false); + + // KH, add v2.5.1 + void setReconnectInterval(const unsigned long& time) + { + _reconnectInterval = time; + } + + void setExtraHeaders(const char * extraHeaders = nullptr) + { + WebSocketsClient::setExtraHeaders(extraHeaders); + } + + protected: + bool _disableHeartbeat = false; + uint64_t _lastHeartbeat = 0; + SocketIOclientEvent _cbEvent; + virtual void runIOCbEvent(socketIOmessageType_t type, uint8_t * payload, size_t length) + { + if (_cbEvent) + { + _cbEvent(type, payload, length); + } + } + + void initClient(); + + // Handling events from websocket layer + virtual void runCbEvent(WStype_t type, uint8_t * payload, size_t length) + { + handleCbEvent(type, payload, length); + } + + void handleCbEvent(WStype_t type, uint8_t * payload, size_t length); +}; + +#include "SocketIOclient_Generic-Impl.h" + +#endif // SOCKET_IO_CLIENT_GENERIC_H_ + diff --git a/src/src/WebSockets4WebServer_Generic.h b/src/src/WebSockets4WebServer_Generic.h new file mode 100644 index 00000000..7c505fee --- /dev/null +++ b/src/src/WebSockets4WebServer_Generic.h @@ -0,0 +1,127 @@ +/**************************************************************************************************************************** + WebSockets4WebServer_Generic.h - WebSockets Library for boards + + Based on and modified from WebSockets libarary https://github.com/Links2004/arduinoWebSockets + to support other boards such as SAMD21, SAMD51, Adafruit's nRF52 boards, etc. + + Built by Khoi Hoang https://github.com/khoih-prog/WebSockets_Generic + Licensed under MIT license + + @original file WebSocketsServer.cpp + @date 20.05.2015 + @author Markus Sattler + + Copyright (c) 2015 Markus Sattler. All rights reserved. + This file is part of the WebSockets for Arduino. + + 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 St, Fifth Floor, Boston, MA 02110-1301 USA + + Version: 2.14.0 + + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 2.1.3 K Hoang 15/05/2020 Initial porting to support SAMD21, SAMD51, nRF52 boards, such as AdaFruit Feather nRF52832, + nRF52840 Express, BlueFruit Sense, Itsy-Bitsy nRF52840 Express, Metro nRF52840 Express, etc. + 2.2.1 K Hoang 18/05/2020 Bump up to sync with v2.2.1 of original WebSockets library + 2.2.2 K Hoang 25/05/2020 Add support to Teensy, SAM DUE and STM32. Enable WebSocket Server for new supported boards. + 2.2.3 K Hoang 02/08/2020 Add support to W5x00's Ethernet2, Ethernet3, EthernetLarge Libraries. + Add support to STM32F/L/H/G/WB/MP1 and Seeeduino SAMD21/SAMD51 boards. + 2.3.1 K Hoang 07/10/2020 Sync with v2.3.1 of original WebSockets library. Add ENC28J60 EthernetENC library support + 2.3.2 K Hoang 12/11/2020 Add RTL8720DN Seeed_Arduino_rpcWiFi library support + 2.3.3 K Hoang 28/11/2020 Fix compile error for WIO_TERMINAL and boards using libraries with lib64. + 2.3.4 K Hoang 12/12/2020 Add SSL support to SAMD21 Nano-33-IoT using WiFiNINA. Upgrade WS and WSS examples. + 2.4.0 K Hoang 06/02/2021 Add support to Teensy 4.1 NativeEthernet and STM32 built-in LAN8742A. + Sync with v2.3.4 of original WebSockets library + 2.4.1 K Hoang 19/03/2021 Sync with v2.3.5 of original WebSockets library to adapt to ESP32 SSL changes + 2.5.0 K Hoang 22/05/2021 Add support to WiFi101 + 2.5.1 K Hoang 22/05/2021 Default to EIO4 for Socket.IO. Permit increase reconnectInterval in Socket.IO + 2.6.0 K Hoang 23/05/2021 Fix breaking problem with SocketIO. Add setExtraHeaders to SocketIO + 2.7.0 K Hoang 24/05/2021 Add support to RP2040-based boards using Arduino-pico and Arduino mbed_rp2040 core + 2.8.0 K Hoang 08/07/2021 Add support to WT32_ETH01 (ESP32 + LAN8720) boards + 2.9.0 K Hoang 05/09/2021 Add support to QNEthernet Library for Teensy 4.1 + 2.10.0 K Hoang 18/09/2021 Add support to Portenta_H7, using either WiFi or Vision-shield Ethernet + 2.10.1 K Hoang 12/10/2021 Update `platform.ini` and `library.json` + 2.11.0 K Hoang 30/11/2021 Auto detect ESP32 core version. Fix bug in examples + 2.11.1 K Hoang 12/12/2021 Add option to use transport=websocket with sticky-session SIO server + 2.12.0 K Hoang 28/01/2022 Supporting SSL for ESP32-based WT32_ETH01 boards + 2.13.0 K Hoang 14/02/2022 Add support to ESP32_S3. Add PING and PONG SocketIO events + 2.14.0 K Hoang 17/02/2022 Suppress unnecessary warnings. Optimize code by passing by reference instead of value + *****************************************************************************************************************************/ + +#pragma once + +#ifndef __WEBSOCKETS4WEBSERVER_GENERIC_H +#define __WEBSOCKETS4WEBSERVER_GENERIC_H + +#include +#include + +#if WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266 && WEBSERVER_HAS_HOOK + +class WebSockets4WebServer : public WebSocketsServerCore +{ + public: + WebSockets4WebServer(const String & origin = "", const String & protocol = "arduino") + : WebSocketsServerCore(origin, protocol) + { + begin(); + } + + ESP8266WebServer::HookFunction hookForWebserver(const String & wsRootDir, WebSocketServerEvent event) + { + onEvent(event); + + return [&, wsRootDir](const String & method, const String & url, WiFiClient * tcpClient, + ESP8266WebServer::ContentTypeFunction contentType) + { + (void)contentType; + + if (!(method == "GET" && url.indexOf(wsRootDir) == 0)) + { + return ESP8266WebServer::CLIENT_REQUEST_CAN_CONTINUE; + } + + // allocate a WiFiClient copy (like in WebSocketsServer::handleNewClients()) + WEBSOCKETS_NETWORK_CLASS * newTcpClient = new WEBSOCKETS_NETWORK_CLASS(*tcpClient); + + // Then initialize a new WSclient_t (like in WebSocketsServer::handleNewClient()) + WSclient_t * client = handleNewClient(newTcpClient); + + if (client) + { + // give "GET " + String headerLine; + headerLine.reserve(url.length() + 5); + headerLine = "GET "; + headerLine += url; + handleHeader(client, &headerLine); + } + + // tell webserver to not close but forget about this client + return ESP8266WebServer::CLIENT_IS_GIVEN; + }; + } +}; +#else // WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266 && WEBSERVER_HAS_HOOK + +#ifndef WEBSERVER_HAS_HOOK + #error Your current Framework / Arduino core version does not support Webserver Hook Functions +#else + #error Your Hardware Platform does not support Webserver Hook Functions +#endif + +#endif // WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266 && WEBSERVER_HAS_HOOK + +#endif // __WEBSOCKETS4WEBSERVER_GENERIC_H diff --git a/src/src/WebSocketsClient_Generic-Impl.h b/src/src/WebSocketsClient_Generic-Impl.h new file mode 100644 index 00000000..2b301699 --- /dev/null +++ b/src/src/WebSocketsClient_Generic-Impl.h @@ -0,0 +1,1406 @@ +/**************************************************************************************************************************** + WebSocketsClient_Generic-Impl.h - WebSockets Library for boards + + Based on and modified from WebSockets libarary https://github.com/Links2004/arduinoWebSockets + to support other boards such as SAMD21, SAMD51, Adafruit's nRF52 boards, etc. + + Built by Khoi Hoang https://github.com/khoih-prog/WebSockets_Generic + Licensed under MIT license + + @original file WebSocketsClient.cpp + @date 20.05.2015 + @author Markus Sattler + + Copyright (c) 2015 Markus Sattler. All rights reserved. + This file is part of the WebSockets for Arduino. + + 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 St, Fifth Floor, Boston, MA 02110-1301 USA + + Version: 2.14.0 + + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 2.1.3 K Hoang 15/05/2020 Initial porting to support SAMD21, SAMD51, nRF52 boards, such as AdaFruit Feather nRF52832, + nRF52840 Express, BlueFruit Sense, Itsy-Bitsy nRF52840 Express, Metro nRF52840 Express, etc. + 2.2.1 K Hoang 18/05/2020 Bump up to sync with v2.2.1 of original WebSockets library + 2.2.2 K Hoang 25/05/2020 Add support to Teensy, SAM DUE and STM32. Enable WebSocket Server for new supported boards. + 2.2.3 K Hoang 02/08/2020 Add support to W5x00's Ethernet2, Ethernet3, EthernetLarge Libraries. + Add support to STM32F/L/H/G/WB/MP1 and Seeeduino SAMD21/SAMD51 boards. + 2.3.1 K Hoang 07/10/2020 Sync with v2.3.1 of original WebSockets library. Add ENC28J60 EthernetENC library support + 2.3.2 K Hoang 12/11/2020 Add RTL8720DN Seeed_Arduino_rpcWiFi library support + 2.3.3 K Hoang 28/11/2020 Fix compile error for WIO_TERMINAL and boards using libraries with lib64. + 2.3.4 K Hoang 12/12/2020 Add SSL support to SAMD21 Nano-33-IoT using WiFiNINA. Upgrade WS and WSS examples. + 2.4.0 K Hoang 06/02/2021 Add support to Teensy 4.1 NativeEthernet and STM32 built-in LAN8742A. + Sync with v2.3.4 of original WebSockets library + 2.4.1 K Hoang 19/03/2021 Sync with v2.3.5 of original WebSockets library to adapt to ESP32 SSL changes + 2.5.0 K Hoang 22/05/2021 Add support to WiFi101 + 2.5.1 K Hoang 22/05/2021 Default to EIO4 for Socket.IO. Permit increase reconnectInterval in Socket.IO + 2.6.0 K Hoang 23/05/2021 Fix breaking problem with SocketIO. Add setExtraHeaders to SocketIO + 2.7.0 K Hoang 24/05/2021 Add support to RP2040-based boards using Arduino-pico and Arduino mbed_rp2040 core + 2.8.0 K Hoang 08/07/2021 Add support to WT32_ETH01 (ESP32 + LAN8720) boards + 2.9.0 K Hoang 05/09/2021 Add support to QNEthernet Library for Teensy 4.1 + 2.10.0 K Hoang 18/09/2021 Add support to Portenta_H7, using either WiFi or Vision-shield Ethernet + 2.10.1 K Hoang 12/10/2021 Update `platform.ini` and `library.json` + 2.11.0 K Hoang 30/11/2021 Auto detect ESP32 core version. Fix bug in examples + 2.11.1 K Hoang 12/12/2021 Add option to use transport=websocket with sticky-session SIO server + 2.12.0 K Hoang 28/01/2022 Supporting SSL for ESP32-based WT32_ETH01 boards + 2.13.0 K Hoang 14/02/2022 Add support to ESP32_S3. Add PING and PONG SocketIO events + 2.14.0 K Hoang 17/02/2022 Suppress unnecessary warnings. Optimize code by passing by reference instead of value + *****************************************************************************************************************************/ + +#pragma once + +#ifndef WEBSOCKETS_CLIENT_GENERIC_IMPL_H_ +#define WEBSOCKETS_CLIENT_GENERIC_IMPL_H_ + +WebSocketsClient::WebSocketsClient() +{ + _cbEvent = NULL; + _client.num = 0; + _client.cIsClient = true; + _client.extraHeaders = WEBSOCKETS_STRING("Origin: file://"); + _reconnectInterval = 500; + + _port = 0; + _host = ""; +} + +WebSocketsClient::~WebSocketsClient() +{ + disconnect(); +} + +/** + calles to init the Websockets server +*/ +void WebSocketsClient::begin(const char * host, const uint16_t& port, const char * url, const char * protocol) +{ + _host = host; + _port = port; + +#if defined(HAS_SSL) + + _fingerprint = SSL_FINGERPRINT_NULL; + + _CA_cert = NULL; + +#endif + + _client.num = 0; + _client.status = WSC_NOT_CONNECTED; + _client.tcp = NULL; + +#if defined(HAS_SSL) + _client.isSSL = false; + _client.ssl = NULL; +#endif + + _client.cUrl = url; + _client.cCode = 0; + _client.cIsUpgrade = false; + _client.cIsWebsocket = true; + _client.cKey = ""; + _client.cAccept = ""; + _client.cProtocol = protocol; + _client.cExtensions = ""; + _client.cVersion = 0; + _client.base64Authorization = ""; + _client.plainAuthorization = ""; + _client.isSocketIO = false; + + _client.lastPing = 0; + _client.pongReceived = false; + _client.pongTimeoutCount = 0; + +#ifdef ESP8266 + randomSeed(RANDOM_REG32); +#else + // todo find better seed + randomSeed(millis()); +#endif + +#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) + asyncConnect(); +#endif + + _lastConnectionFail = 0; + _lastHeaderSent = 0; + + WSK_LOGINFO(WEBSOCKETS_GENERIC_VERSION); +} + +void WebSocketsClient::begin(const String& host, const uint16_t& port, const String& url, const String& protocol) +{ + begin(host.c_str(), port, url.c_str(), protocol.c_str()); +} + +void WebSocketsClient::begin(const IPAddress& host, const uint16_t& port, const char * url, const char * protocol) +{ +#if defined(ESP8266) || defined(ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RTL8720DN) + return begin(host.toString().c_str(), port, url, protocol); +#else + return begin(WS_IPAddressToString(host).c_str(), port, url, protocol); +#endif +} + +//KH +void WebSocketsClient::begin(const IPAddress& host, const uint16_t& port, const String& url, const String& protocol) +{ + return begin(WS_IPAddressToString(host).c_str(), port, url.c_str(), protocol.c_str()); +} + +#if defined(HAS_SSL) + +#if defined(SSL_AXTLS) + +void WebSocketsClient::beginSSL(const char * host, const uint16_t& port, const char * url, const char * fingerprint, + const char * protocol) +{ + begin(host, port, url, protocol); + _client.isSSL = true; + _fingerprint = fingerprint; + _CA_cert = NULL; +} + +void WebSocketsClient::beginSSL(const String& host, const uint16_t& port, const String& url, const String& fingerprint, + const String& protocol) +{ + beginSSL(host.c_str(), port, url.c_str(), fingerprint.c_str(), protocol.c_str()); +} + +// KH +void WebSocketsClient::beginSSL(const IPAddress& host, const uint16_t& port, const String& url, const String& fingerprint, + const String& protocol) +{ + beginSSL(WS_IPAddressToString(host).c_str(), port, url.c_str(), fingerprint.c_str(), protocol.c_str()); +} + +void WebSocketsClient::beginSslWithCA(const char * host, const uint16_t& port, const char * url, const char * CA_cert, + const char * protocol) +{ + begin(host, port, url, protocol); + _client.isSSL = true; + + _fingerprint = SSL_FINGERPRINT_NULL; + + + _CA_cert = CA_cert; +} + +#else // SSL_AXTLS + +void WebSocketsClient::beginSSL(const char * host, const uint16_t& port, const char * url, const uint8_t * fingerprint, + const char * protocol) +{ + begin(host, port, url, protocol); + _client.isSSL = true; + _fingerprint = fingerprint; + _CA_cert = NULL; +} + +// KH +void WebSocketsClient::beginSSL(const IPAddress& host, const uint16_t& port, const String& url, const String& fingerprint, + const String& protocol) +{ + beginSSL(WS_IPAddressToString(host).c_str(), port, url.c_str(), (uint8_t *) fingerprint.c_str(), protocol.c_str()); +} + +void WebSocketsClient::beginSslWithCA(const char * host, const uint16_t& port, const char * url, BearSSL::X509List * CA_cert, + const char * protocol) +{ + begin(host, port, url, protocol); + _client.isSSL = true; + _fingerprint = SSL_FINGERPRINT_NULL; + _CA_cert = CA_cert; +} + + +void WebSocketsClient::beginSslWithCA(const char * host, const uint16_t& port, const char * url, const char * CA_cert, + const char * protocol) +{ + begin(host, port, url, protocol); + _client.isSSL = true; + _fingerprint = SSL_FINGERPRINT_NULL; + _CA_cert = new BearSSL::X509List(CA_cert); +} + +void WebSocketsClient::setSSLClientCertKey(BearSSL::X509List * clientCert, BearSSL::PrivateKey * clientPrivateKey) +{ + _client_cert = clientCert; + _client_key = clientPrivateKey; +} + +void WebSocketsClient::setSSLClientCertKey(const char * clientCert, const char * clientPrivateKey) +{ + setSSLClientCertKey(new BearSSL::X509List(clientCert), new BearSSL::PrivateKey(clientPrivateKey)); +} + + +#endif // SSL_AXTLS + +#endif // HAS_SSL + +void WebSocketsClient::beginSocketIO(const char * host, const uint16_t& port, const char * url, const char * protocol) +{ + WSK_LOGDEBUG("[WS-Client] beginSocketIO with const char"); + + begin(host, port, url, protocol); + _client.isSocketIO = true; +} + +void WebSocketsClient::beginSocketIO(const String& host, const uint16_t& port, const String& url, const String& protocol) +{ + WSK_LOGDEBUG("[WS-Client] beginSocketIO with String"); + + beginSocketIO(host.c_str(), port, url.c_str(), protocol.c_str()); +} + + +// KH +void WebSocketsClient::beginSocketIO(const IPAddress& host, const uint16_t& port, const String& url, const String& protocol) +{ + WSK_LOGDEBUG("[WS-Client] beginSocketIO with IPAddress"); + + beginSocketIO(WS_IPAddressToString(host).c_str(), port, url.c_str(), protocol.c_str()); +} + + +#if defined(HAS_SSL) +void WebSocketsClient::beginSocketIOSSL(const char * host, const uint16_t& port, const char * url, const char * protocol) +{ + begin(host, port, url, protocol); + _client.isSocketIO = true; + _client.isSSL = true; + + _fingerprint = SSL_FINGERPRINT_NULL; +} + +void WebSocketsClient::beginSocketIOSSL(const String& host, const uint16_t& port, const String& url, const String& protocol) +{ + beginSocketIOSSL(host.c_str(), port, url.c_str(), protocol.c_str()); +} + +// KH +void WebSocketsClient::beginSocketIOSSL(const IPAddress& host, const uint16_t& port, const String& url, const String& protocol) +{ + beginSocketIOSSL(WS_IPAddressToString(host).c_str(), port, url.c_str(), protocol.c_str()); +} + + +#if defined(SSL_BARESSL) +void WebSocketsClient::beginSocketIOSSLWithCA(const char * host, const uint16_t& port, const char * url, + BearSSL::X509List * CA_cert, const char * protocol) +{ + begin(host, port, url, protocol); + _client.isSocketIO = true; + _client.isSSL = true; + _fingerprint = SSL_FINGERPRINT_NULL; + _CA_cert = CA_cert; +} +#endif + +void WebSocketsClient::beginSocketIOSSLWithCA(const char * host, const uint16_t& port, const char * url, const char * CA_cert, + const char * protocol) +{ + begin(host, port, url, protocol); + _client.isSocketIO = true; + _client.isSSL = true; + _fingerprint = SSL_FINGERPRINT_NULL; +#if defined(SSL_BARESSL) + _CA_cert = new BearSSL::X509List(CA_cert); +#else + _CA_cert = CA_cert; +#endif +} + +#endif // HAS_SSL + +#if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) + #if(_WEBSOCKETS_LOGLEVEL_>3) + #warning WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC + #endif +/** + called in arduino loop +*/ +void WebSocketsClient::loop() +{ + if (_port == 0) + { + return; + } + + WEBSOCKETS_YIELD(); + + if (!clientIsConnected(&_client)) + { + // do not flood the server + if ((millis() - _lastConnectionFail) < _reconnectInterval) + { + return; + } + +#if defined(HAS_SSL) + #if(_WEBSOCKETS_LOGLEVEL_>2) + #warning HAS_SSL + #endif + + if (_client.isSSL) + { + WSK_LOGWARN("[WS-Client] Connect wss..."); + + if (_client.ssl) + { + delete _client.ssl; + _client.ssl = NULL; + _client.tcp = NULL; + } + + _client.ssl = new WEBSOCKETS_NETWORK_SSL_CLASS(); + _client.tcp = _client.ssl; + + if (_CA_cert) + { + WSK_LOGWARN("[WS-Client] Setting CA certificate"); + +#if defined(ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RTL8720DN) + #if(_WEBSOCKETS_LOGLEVEL_>3) + #warning ESP32 or NETWORK_RTL8720DN + #endif + + _client.ssl->setCACert(_CA_cert); + +#elif defined(ESP8266) && defined(SSL_AXTLS) + #if(_WEBSOCKETS_LOGLEVEL_>3) + #warning ESP8266 and SSL_AXTLS + #endif + + _client.ssl->setCACert((const uint8_t *)_CA_cert, strlen(_CA_cert) + 1); + +#elif defined(ESP8266) && ( defined(SSL_BARESSL) || defined(SSL_BEARSSL) ) + #if(_WEBSOCKETS_LOGLEVEL_>3) + #warning ESP8266 and SSL_BEARSSL + #endif + + _client.ssl->setTrustAnchors(_CA_cert); + +#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_RTL8720DN) //defined(SEEED_WIO_TERMINAL) + #if(_WEBSOCKETS_LOGLEVEL_>3) + #warning NETWORK_RTL8720DN + #endif + + _client.ssl->setCACert(_CA_cert); + +#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_WIFININA) + // Do something here for WiFiNINA + +#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_WIFI101) + // Do something here for WiFi101 + +#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_PORTENTA_H7_WIFI) + // Do something here for Portenta_H7 WiFi if SSL is supported + +#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_PORTENTA_H7_ETHERNET) + // Do something here for Portenta_H7 Ethernet if SSL is supported + +#else + #error setCACert not implemented +#endif + } + +//////////////////// +#if defined(ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RTL8720DN) + else if (!SSL_FINGERPRINT_IS_SET) + { + // ESP32 has setInsecure() now from v1.0.6 + _client.ssl->setInsecure(); + } +#elif defined(ESP8266) + else if (!SSL_FINGERPRINT_IS_SET) + { + _client.ssl->setInsecure(); + } +//////////////////// + +#elif ( defined(SSL_BARESSL) || defined(SSL_BEARSSL) ) + else if (SSL_FINGERPRINT_IS_SET) + { + _client.ssl->setFingerprint(_fingerprint); + } + else + { + #if defined(ESP8266) + // ESP32 has setInsecure() now from v1.0.6 + _client.ssl->setInsecure(); + #endif + } + + if(_client_cert && _client_key) + { + _client.ssl->setClientRSACert(_client_cert, _client_key); + WSK_LOGWARN("[WS-Client] setting client certificate and key"); + } +#endif // defined(ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RTL8720DN) + } + else + { + WSK_LOGWARN("[WS-Client] Connect ws..."); + + if (_client.tcp) + { + delete _client.tcp; + _client.tcp = NULL; + } + + _client.tcp = new WEBSOCKETS_NETWORK_CLASS(); + } + +#else // HAS_SSL + #if(_WEBSOCKETS_LOGLEVEL_>2) + #warning Not HAS_SSL + #endif + + _client.tcp = new WEBSOCKETS_NETWORK_CLASS(); +#endif // HAS_SSL + + if (!_client.tcp) + { + WSK_LOGERROR("[WS-Client] Creating Network class failed!"); + return; + } + + WEBSOCKETS_YIELD(); + +#if defined(ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RTL8720DN) + // KH test SSL + WSK_LOGINFO3("[WS-Client] Calling _client.tcp->connect, _host =", _host, ", port =", _port); + + int _connectResult = _client.tcp->connect(_host.c_str(), _port, WEBSOCKETS_TCP_TIMEOUT); + + WSK_LOGINFO1("[WS-Client] Calling _client.tcp->connect, _connectResult =", _connectResult); + + if (_connectResult) + +#else + if (_client.tcp->connect(_host.c_str(), _port)) +#endif + { + WSK_LOGDEBUG("[WS-Client] connectedCb"); + connectedCb(); + _lastConnectionFail = 0; + } + else + { + WSK_LOGDEBUG("[WS-Client] connectFailedCb"); + connectFailedCb(); + _lastConnectionFail = millis(); + } + } + else + { + //WSK_LOGDEBUG("[WS-Client] handleClientData"); + handleClientData(); + WEBSOCKETS_YIELD(); + + if (_client.status == WSC_CONNECTED) + { + handleHBPing(); + handleHBTimeout(&_client); + } + } +} +#endif // (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) + +/** + set callback function + @param cbEvent WebSocketServerEvent +*/ +void WebSocketsClient::onEvent(WebSocketClientEvent cbEvent) +{ + _cbEvent = cbEvent; +} + +/** + send text data to client + @param num uint8_t client id + @param payload uint8_t + @param length size_t + @param headerToPayload bool (see sendFrame for more details) + @return true if ok +*/ +bool WebSocketsClient::sendTXT(uint8_t * payload, size_t length, bool headerToPayload) +{ + if (length == 0) + { + length = strlen((const char *)payload); + } + + if (clientIsConnected(&_client)) + { + return sendFrame(&_client, WSop_text, payload, length, true, headerToPayload); + } + + return false; +} + +bool WebSocketsClient::sendTXT(const uint8_t * payload, size_t length) +{ + return sendTXT((uint8_t *)payload, length); +} + +bool WebSocketsClient::sendTXT(char * payload, size_t length, bool headerToPayload) +{ + return sendTXT((uint8_t *)payload, length, headerToPayload); +} + +bool WebSocketsClient::sendTXT(const char * payload, size_t length) +{ + return sendTXT((uint8_t *)payload, length); +} + +bool WebSocketsClient::sendTXT(const String& payload) +{ + return sendTXT((uint8_t *)payload.c_str(), payload.length()); +} + +bool WebSocketsClient::sendTXT(char payload) +{ + uint8_t buf[WEBSOCKETS_MAX_HEADER_SIZE + 2] = { 0x00 }; + buf[WEBSOCKETS_MAX_HEADER_SIZE] = payload; + return sendTXT(buf, 1, true); +} + +/** + send binary data to client + @param num uint8_t client id + @param payload uint8_t + @param length size_t + @param headerToPayload bool (see sendFrame for more details) + @return true if ok +*/ +bool WebSocketsClient::sendBIN(uint8_t * payload, size_t length, bool headerToPayload) +{ + if (clientIsConnected(&_client)) + { + return sendFrame(&_client, WSop_binary, payload, length, true, headerToPayload); + } + + return false; +} + +bool WebSocketsClient::sendBIN(const uint8_t * payload, size_t length) +{ + return sendBIN((uint8_t *)payload, length); +} + +/** + sends a WS ping to Server + @param payload uint8_t + @param length size_t + @return true if ping is send out +*/ +bool WebSocketsClient::sendPing(uint8_t * payload, size_t length) +{ + if (clientIsConnected(&_client)) + { + bool sent = sendFrame(&_client, WSop_ping, payload, length); + + if (sent) + _client.lastPing = millis(); + + return sent; + } + + return false; +} + +bool WebSocketsClient::sendPing(const String& payload) +{ + return sendPing((uint8_t *)payload.c_str(), payload.length()); +} + +/** + disconnect one client + @param num uint8_t client id +*/ +void WebSocketsClient::disconnect() +{ + if (clientIsConnected(&_client)) + { + WebSockets::clientDisconnect(&_client, 1000); + } +} + +/** + set the Authorization for the http request + @param user const char + @param password const char +*/ +void WebSocketsClient::setAuthorization(const char * user, const char * password) +{ + if (user && password) + { + String auth = user; + auth += ":"; + auth += password; + _client.base64Authorization = base64_encode((uint8_t *)auth.c_str(), auth.length()); + } +} + +/** + set the Authorization for the http request + @param auth const char * base64 +*/ +void WebSocketsClient::setAuthorization(const char * auth) +{ + if (auth) + { + //_client.base64Authorization = auth; + _client.plainAuthorization = auth; + } +} + +/** + set extra headers for the http request; + separate headers by "\r\n" + @param extraHeaders const char * extraHeaders +*/ +void WebSocketsClient::setExtraHeaders(const char * extraHeaders) +{ + _client.extraHeaders = extraHeaders; +} + +/** + set the reconnect Interval + how long to wait after a connection initiate failed + @param time in ms +*/ +void WebSocketsClient::setReconnectInterval(const unsigned long& time) +{ + _reconnectInterval = time; +} + +bool WebSocketsClient::isConnected() +{ + return (_client.status == WSC_CONNECTED); +} + +//################################################################################# +//################################################################################# +//################################################################################# + +/** + + @param client WSclient_t * ptr to the client struct + @param opcode WSopcode_t + @param payload uint8_t + @param length size_t +*/ +void WebSocketsClient::messageReceived(WSclient_t * client, WSopcode_t opcode, + uint8_t * payload, size_t length, bool fin) +{ + WStype_t type = WStype_ERROR; + + UNUSED(client); + + switch (opcode) + { + case WSop_text: + type = fin ? WStype_TEXT : WStype_FRAGMENT_TEXT_START; + break; + case WSop_binary: + type = fin ? WStype_BIN : WStype_FRAGMENT_BIN_START; + break; + case WSop_continuation: + type = fin ? WStype_FRAGMENT_FIN : WStype_FRAGMENT; + break; + case WSop_ping: + type = WStype_PING; + break; + case WSop_pong: + type = WStype_PONG; + break; + case WSop_close: + default: + break; + } + + runCbEvent(type, payload, length); +} + +/** + Disconnect an client + @param client WSclient_t * ptr to the client struct +*/ +void WebSocketsClient::clientDisconnect(WSclient_t * client) +{ + bool event = false; + +#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || \ + (WEBSOCKETS_NETWORK_TYPE == NETWORK_RTL8720DN) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_WIFININA) || \ + (WEBSOCKETS_NETWORK_TYPE == NETWORK_WIFI101) + if (client->isSSL && client->ssl) + { + if (client->ssl->connected()) + { + client->ssl->flush(); + client->ssl->stop(); + } + + event = true; + delete client->ssl; + client->ssl = NULL; + client->tcp = NULL; + } +#endif + + if (client->tcp) + { + if (client->tcp->connected()) + { +#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) + client->tcp->flush(); +#endif + client->tcp->stop(); + } + + event = true; +#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) + client->status = WSC_NOT_CONNECTED; +#else + delete client->tcp; +#endif + client->tcp = NULL; + } + + client->cCode = 0; + client->cKey = ""; + client->cAccept = ""; + client->cVersion = 0; + client->cIsUpgrade = false; + client->cIsWebsocket = false; + client->cSessionId = ""; + + client->status = WSC_NOT_CONNECTED; + + WSK_LOGDEBUG("[WS-Client] client disconnected."); + + if (event) + { + runCbEvent(WStype_DISCONNECTED, NULL, 0); + } +} + +/** + get client state + @param client WSclient_t * ptr to the client struct + @return true = conneted +*/ +bool WebSocketsClient::clientIsConnected(WSclient_t * client) +{ + if (!client->tcp) + { + return false; + } + + if (client->tcp->connected()) + { + if (client->status != WSC_NOT_CONNECTED) { + return true; + } + } + else + { + // client lost + if (client->status != WSC_NOT_CONNECTED) + { + WSK_LOGWARN("[WS-Client] connection lost."); + + // do cleanup + clientDisconnect(client); + } + } + + if (client->tcp) + { + // do cleanup + clientDisconnect(client); + } + + return false; +} +#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) +/** + Handle incomming data from Client +*/ +void WebSocketsClient::handleClientData() +{ + if ((_client.status == WSC_HEADER || _client.status == WSC_BODY) && _lastHeaderSent + WEBSOCKETS_TCP_TIMEOUT < millis()) + { + WSK_LOGINFO("[WS-Client][handleClientData] Header response timeout.. Disconnecting!"); + clientDisconnect(&_client); + WEBSOCKETS_YIELD(); + return; + } + + int len = _client.tcp->available(); + + if (len > 0) + { + switch (_client.status) + { + case WSC_HEADER: + { + String headerLine = _client.tcp->readStringUntil('\n'); + handleHeader(&_client, headerLine); + } + + break; + case WSC_BODY: + { + char buf[256] = { 0 }; + _client.tcp->readBytes(&buf[0], std::min((size_t)len, sizeof(buf))); + String bodyLine = buf; + handleHeader(&_client, bodyLine); + } + + break; + case WSC_CONNECTED: + WebSockets::handleWebsocket(&_client); + + break; + default: + WebSockets::clientDisconnect(&_client, 1002); + + break; + } + } + + WEBSOCKETS_YIELD(); +} +#endif + +/** + send the WebSocket header to Server + @param client WSclient_t * ptr to the client struct +*/ +void WebSocketsClient::sendHeader(WSclient_t * client) +{ + static const char * NEW_LINE = "\r\n"; + + WSK_LOGINFO("[WS-Client] [sendHeader] Sending header..."); + + uint8_t randomKey[16] = { 0 }; + + for (uint8_t i = 0; i < sizeof(randomKey); i++) + { + randomKey[i] = random(0xFF); + } + + client->cKey = base64_encode(&randomKey[0], 16); + + WSK_LOGINFO1("sendHeader: client->cKey = ", client->cKey); + + unsigned long start = micros(); + + String handshake; + bool ws_header = true; + String url = client->cUrl; + + if (client->isSocketIO) + { + if (client->cSessionId.length() == 0) + { +#if USING_STICKY_SESSION_SIO + #if(_WEBSOCKETS_LOGLEVEL_>2) + #warning Using USING_STICKY_SESSION_SIO with transport=websocket + #endif + + url += WEBSOCKETS_STRING("&transport=websocket"); +#else + url += WEBSOCKETS_STRING("&transport=polling"); +#endif + ws_header = false; + } + else + { + url += WEBSOCKETS_STRING("&transport=websocket&sid="); + url += client->cSessionId; + } + } + + handshake = WEBSOCKETS_STRING("GET "); + handshake += url + WEBSOCKETS_STRING( + " HTTP/1.1\r\n" + "Host: "); + handshake += _host + ":" + _port + NEW_LINE; + + if (ws_header) + { + handshake += WEBSOCKETS_STRING( + "Connection: Upgrade\r\n" + "Upgrade: websocket\r\n" + "Sec-WebSocket-Version: 13\r\n" + "Sec-WebSocket-Key: "); + handshake += client->cKey + NEW_LINE; + + if (client->cProtocol.length() > 0) + { + handshake += WEBSOCKETS_STRING("Sec-WebSocket-Protocol: "); + handshake += client->cProtocol + NEW_LINE; + } + + if (client->cExtensions.length() > 0) + { + handshake += WEBSOCKETS_STRING("Sec-WebSocket-Extensions: "); + handshake += client->cExtensions + NEW_LINE; + } + } + else + { + handshake += WEBSOCKETS_STRING("Connection: keep-alive\r\n"); + } + + // add extra headers; by default this includes "Origin: file://" + if(client->extraHeaders.length() > 0) + { + handshake += client->extraHeaders + NEW_LINE; + } + + handshake += WEBSOCKETS_STRING("User-Agent: arduino-WebSocket-Client\r\n"); + + if (client->base64Authorization.length() > 0) + { + handshake += WEBSOCKETS_STRING("Authorization: Basic "); + handshake += client->base64Authorization + NEW_LINE; + } + + if (client->plainAuthorization.length() > 0) + { + handshake += WEBSOCKETS_STRING("Authorization: "); + handshake += client->plainAuthorization + NEW_LINE; + } + + handshake += NEW_LINE; + + WSK_LOGINFO1("[WS-Client] [sendHeader] Handshake:", handshake); + + write(client, (uint8_t *)handshake.c_str(), handshake.length()); + +#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) + client->tcp->readStringUntil('\n', &(client->cHttpLine), std::bind(&WebSocketsClient::handleHeader, + this, client, &(client->cHttpLine))); +#endif + + WSK_LOGINFO1("[WS-Client] [sendHeader] Sending header... Done (us):", (micros() - start)); + + _lastHeaderSent = millis(); +} + +/** + handle the WebSocket header reading + @param client WSclient_t * ptr to the client struct +*/ + +///////////////////////////////////////////////////////////////////////////////////////////////////// + +void WebSocketsClient::handleHeader(WSclient_t * client, String& headerLine) +{ + headerLine.trim(); // remove \r + + // this code handels the http body for Socket.IO requests + if ( (headerLine.length() > 0) && (client->isSocketIO) && (client->status == WSC_BODY) && \ + (client->cSessionId.length() == 0) ) + { + WSK_LOGINFO1("[WS-Client][handleHeader] socket.io json: ", headerLine.c_str()); + + String sid_begin = WEBSOCKETS_STRING("\"sid\":\""); + + if (headerLine.indexOf(sid_begin) > -1) + { + int start = headerLine.indexOf(sid_begin) + sid_begin.length(); + int end = headerLine.indexOf('"', start); + client->cSessionId = headerLine.substring(start, end); + + WSK_LOGINFO1("[WS-Client][handleHeader] - cSessionId: ", client->cSessionId.c_str()); + + // Trigger websocket connection code path + headerLine = ""; + } + } + + // handle HTTP header + if (headerLine.length() > 0) + { + WSK_LOGINFO1("[WS-Client][handleHeader] RX:", headerLine.c_str()); + + if (headerLine.startsWith(WEBSOCKETS_STRING("HTTP/1."))) + { + // "HTTP/1.1 101 Switching Protocols" + client->cCode = headerLine.substring(9, headerLine.indexOf(' ', 9)).toInt(); + } + else if (headerLine.indexOf(':') >= 0) + { + String headerName = headerLine.substring(0, headerLine.indexOf(':')); + String headerValue = headerLine.substring(headerLine.indexOf(':') + 1); + + // remove space in the beginning (RFC2616) + if (headerValue[0] == ' ') + { + headerValue.remove(0, 1); + } + + if (headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Connection"))) + { + if (headerValue.equalsIgnoreCase(WEBSOCKETS_STRING("upgrade"))) + { + client->cIsUpgrade = true; + } + } + else if (headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Upgrade"))) + { + if (headerValue.equalsIgnoreCase(WEBSOCKETS_STRING("websocket"))) + { + client->cIsWebsocket = true; + } + } + else if (headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Sec-WebSocket-Accept"))) + { + client->cAccept = headerValue; + client->cAccept.trim(); // see rfc6455 + } + else if (headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Sec-WebSocket-Protocol"))) + { + client->cProtocol = headerValue; + } + else if (headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Sec-WebSocket-Extensions"))) + { + client->cExtensions = headerValue; + } + else if (headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Sec-WebSocket-Version"))) + { + client->cVersion = headerValue.toInt(); + } + else if (headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Set-Cookie"))) + { + if (headerValue.indexOf(';') > -1) + { + client->cSessionId = headerValue.substring(headerValue.indexOf('=') + 1, headerValue.indexOf(";")); + } + else + { + client->cSessionId = headerValue.substring(headerValue.indexOf('=') + 1); + } + } + } + else + { + WSK_LOGINFO1("[WS-Client][handleHeader] Header error:", headerLine.c_str()); + } + + headerLine = ""; + +#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) + client->tcp->readStringUntil('\n', &(client->cHttpLine), std::bind(&WebSocketsClient::handleHeader, + this, client, &(client->cHttpLine))); +#endif + } + else + { + WSK_LOGINFO("[WS-Client][handleHeader] Header read fin."); + WSK_LOGINFO("[WS-Client][handleHeader] Client settings:"); + WSK_LOGINFO1("[WS-Client][handleHeader] - cURL:", client->cUrl.c_str()); + WSK_LOGINFO1("[WS-Client][handleHeader] - cKey:", client->cKey.c_str()); + WSK_LOGINFO("[WS-Client][handleHeader] Server header:"); + WSK_LOGINFO1("[WS-Client][handleHeader] - cCode:", client->cCode); + WSK_LOGINFO1("[WS-Client][handleHeader] - cIsUpgrade:", client->cIsUpgrade); + WSK_LOGINFO1("[WS-Client][handleHeader] - cIsWebsocket:", client->cIsWebsocket); + WSK_LOGINFO1("[WS-Client][handleHeader] - cAccept:", client->cAccept.c_str()); + WSK_LOGINFO1("[WS-Client][handleHeader] - cProtocol:", client->cProtocol.c_str()); + WSK_LOGINFO1("[WS-Client][handleHeader] - cExtensions:", client->cExtensions.c_str()); + WSK_LOGINFO1("[WS-Client][handleHeader] - cVersion:", client->cVersion); + WSK_LOGINFO1("[WS-Client][handleHeader] - cSessionId:", client->cSessionId.c_str()); + + + if(client->isSocketIO && client->cSessionId.length() == 0 && clientIsConnected(client)) + { + WSK_LOGINFO("[WS-Client][handleHeader] Still missing cSessionId try Socket.IO"); + client->status = WSC_BODY; + return; + } + else + { + client->status = WSC_HEADER; + } + + bool ok = (client->cIsUpgrade && client->cIsWebsocket); + + if (ok) + { + if ( (client->cCode == 101) || ( (client->cCode == 200) && (client->isSocketIO) ) ) + { + // Do nothing + } + else + { + // including 403 (forbidden) + + ok = false; + + WSK_LOGINFO1("[WS-Client][handleHeader] serverCode is not 101 :", client->cCode); + + clientDisconnect(client); + _lastConnectionFail = millis(); + } + } + + if (ok) + { + if (client->cAccept.length() == 0) + { + ok = false; + } + else + { + // generate Sec-WebSocket-Accept key for check + String sKey = acceptKey(client->cKey); + + if (sKey != client->cAccept) + { + WSK_LOGINFO("[WS-Client][handleHeader] Sec-WebSocket-Accept is wrong"); + + ok = false; + } + } + } + + if (ok) + { + WSK_LOGINFO("[WS-Client][handleHeader] Websocket connection init done."); + + headerDone(client); + + runCbEvent(WStype_CONNECTED, (uint8_t *)client->cUrl.c_str(), client->cUrl.length()); + } +#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) + else if (client->isSocketIO) + { + if (client->cSessionId.length() > 0) + { + WSK_LOGINFO("[WS-Client][handleHeader] found cSessionId"); + + if(clientIsConnected(client) && _client.tcp->available()) + { + // read not needed data + DEBUG_WEBSOCKETS("[WS-Client][handleHeader] still data in buffer (%d), clean up.\n", _client.tcp->available()); + + while(_client.tcp->available() > 0) + { + _client.tcp->read(); + } + } + + sendHeader(client); + } + } +#endif + else + { + WSK_LOGDEBUG("[WS-Client][handleHeader] no Websocket connection close."); + + _lastConnectionFail = millis(); + + if (clientIsConnected(client)) + { + write(client, "This is a webSocket client!"); + } + + clientDisconnect(client); + } + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////// + +void WebSocketsClient::connectedCb() +{ + WSK_LOGWARN3("[WS-Client][connectedCb] Connected to Host:", _host, ", Port:", _port); + +#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) + _client.tcp->onDisconnect(std::bind([](WebSocketsClient * c, AsyncTCPbuffer * obj, WSclient_t * client) -> bool + { + WSK_LOGWARN1("[WS-Client][connectedCb] Disconnect client :", client->num); + + client->status = WSC_NOT_CONNECTED; + client->tcp = NULL; + + // reconnect + c->asyncConnect(); + + return true; + }, this, std::placeholders::_1, &_client)); +#endif + + _client.status = WSC_HEADER; + +#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) + // set Timeout for readBytesUntil and readStringUntil + _client.tcp->setTimeout(WEBSOCKETS_TCP_TIMEOUT); +#endif + +#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || \ + (WEBSOCKETS_NETWORK_TYPE == NETWORK_RTL8720DN) + _client.tcp->setNoDelay(true); +#endif + +#if defined(HAS_SSL) + +#if (defined(SSL_AXTLS) || defined(ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RTL8720DN)) && \ + ( (WEBSOCKETS_NETWORK_TYPE != NETWORK_WIFININA) && (WEBSOCKETS_NETWORK_TYPE != NETWORK_WIFI101) ) + + if(_client.isSSL && SSL_FINGERPRINT_IS_SET) + { + if (!_client.ssl->verify(_fingerprint.c_str(), _host.c_str())) + { + WSK_LOGERROR("[WS-Client][connectedCb] Certificate mismatch"); + + WebSockets::clientDisconnect(&_client, 1000); + return; + } + } +#else + if(_client.isSSL && SSL_FINGERPRINT_IS_SET) + { + } +#endif + else if (_client.isSSL && !_CA_cert) + { +#if (defined(SSL_BARESSL) || defined(SSL_BEARSSL) ) + // ESP32 has setInsecure() now + _client.ssl->setInsecure(); +#endif + } + +#endif // HAS_SSL + + // send Header to Server + sendHeader(&_client); +} + +void WebSocketsClient::connectFailedCb() +{ + WSK_LOGDEBUG3("[WS-Client][connectFailedCb] Failed connection to host:", _host, ", port:", _port); +} + +#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) + +void WebSocketsClient::asyncConnect() +{ + WSK_LOGINFO("[WS-Client] asyncConnect..."); + + AsyncClient * tcpclient = new AsyncClient(); + + if (!tcpclient) + { + WSK_LOGINFO("[WS-Client] Creating AsyncClient class failed!"); + + return; + } + + tcpclient->onDisconnect([](void * obj, AsyncClient * c) + { + c->free(); + delete c; + }); + + tcpclient->onConnect(std::bind([](WebSocketsClient * ws, AsyncClient * tcp) + { + ws->_client.tcp = new AsyncTCPbuffer(tcp); + + if (!ws->_client.tcp) + { + WSK_LOGINFO("[WS-Client] Creating Network class failed!"); + + ws->connectFailedCb(); + return; + } + + ws->connectedCb(); + }, this, std::placeholders::_2)); + + tcpclient->onError(std::bind([](WebSocketsClient * ws, AsyncClient * tcp) + { + ws->connectFailedCb(); + + // reconnect + ws->asyncConnect(); + }, this, std::placeholders::_2)); + + if (!tcpclient->connect(_host.c_str(), _port)) + { + connectFailedCb(); + delete tcpclient; + } +} + +#endif + +/** + send heartbeat ping to server in set intervals +*/ +void WebSocketsClient::handleHBPing() +{ + if (_client.pingInterval == 0) + return; + + uint32_t pi = millis() - _client.lastPing; + + if (pi > _client.pingInterval) + { + WSK_LOGWARN("[WS-Client] Sending HB ping"); + + if (sendPing()) + { + _client.lastPing = millis(); + _client.pongReceived = false; + } + else + { + WSK_LOGERROR("[WS-Client] sending HB ping failed"); + WebSockets::clientDisconnect(&_client, 1000); + } + } +} + +/** + enable ping/pong heartbeat process + @param pingInterval uint32_t how often ping will be sent + @param pongTimeout uint32_t millis after which pong should timout if not received + @param disconnectTimeoutCount uint8_t how many timeouts before disconnect, 0=> do not disconnect +*/ +void WebSocketsClient::enableHeartbeat(const uint32_t& pingInterval, const uint32_t& pongTimeout, + const uint8_t& disconnectTimeoutCount) +{ + WebSockets::enableHeartbeat(&_client, pingInterval, pongTimeout, disconnectTimeoutCount); +} + +/** + disable ping/pong heartbeat process +*/ +void WebSocketsClient::disableHeartbeat() +{ + _client.pingInterval = 0; +} + +#endif // WEBSOCKETS_CLIENT_GENERIC_IMPL_H_ diff --git a/src/src/WebSocketsClient_Generic.h b/src/src/WebSocketsClient_Generic.h new file mode 100644 index 00000000..a59fa3dc --- /dev/null +++ b/src/src/WebSocketsClient_Generic.h @@ -0,0 +1,268 @@ +/**************************************************************************************************************************** + WebSocketsClient_Generic.h - WebSockets Library for boards + + Based on and modified from WebSockets libarary https://github.com/Links2004/arduinoWebSockets + to support other boards such as SAMD21, SAMD51, Adafruit's nRF52 boards, etc. + + Built by Khoi Hoang https://github.com/khoih-prog/WebSockets_Generic + Licensed under MIT license + + @original file WebSocketsClient.h + @date 20.05.2015 + @author Markus Sattler + + Copyright (c) 2015 Markus Sattler. All rights reserved. + This file is part of the WebSockets for Arduino. + + 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 St, Fifth Floor, Boston, MA 02110-1301 USA + + Version: 2.14.0 + + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 2.1.3 K Hoang 15/05/2020 Initial porting to support SAMD21, SAMD51, nRF52 boards, such as AdaFruit Feather nRF52832, + nRF52840 Express, BlueFruit Sense, Itsy-Bitsy nRF52840 Express, Metro nRF52840 Express, etc. + 2.2.1 K Hoang 18/05/2020 Bump up to sync with v2.2.1 of original WebSockets library + 2.2.2 K Hoang 25/05/2020 Add support to Teensy, SAM DUE and STM32. Enable WebSocket Server for new supported boards. + 2.2.3 K Hoang 02/08/2020 Add support to W5x00's Ethernet2, Ethernet3, EthernetLarge Libraries. + Add support to STM32F/L/H/G/WB/MP1 and Seeeduino SAMD21/SAMD51 boards. + 2.3.1 K Hoang 07/10/2020 Sync with v2.3.1 of original WebSockets library. Add ENC28J60 EthernetENC library support + 2.3.2 K Hoang 12/11/2020 Add RTL8720DN Seeed_Arduino_rpcWiFi library support + 2.3.3 K Hoang 28/11/2020 Fix compile error for WIO_TERMINAL and boards using libraries with lib64. + 2.3.4 K Hoang 12/12/2020 Add SSL support to SAMD21 Nano-33-IoT using WiFiNINA. Upgrade WS and WSS examples. + 2.4.0 K Hoang 06/02/2021 Add support to Teensy 4.1 NativeEthernet and STM32 built-in LAN8742A. + Sync with v2.3.4 of original WebSockets library + 2.4.1 K Hoang 19/03/2021 Sync with v2.3.5 of original WebSockets library to adapt to ESP32 SSL changes + 2.5.0 K Hoang 22/05/2021 Add support to WiFi101 + 2.5.1 K Hoang 22/05/2021 Default to EIO4 for Socket.IO. Permit increase reconnectInterval in Socket.IO + 2.6.0 K Hoang 23/05/2021 Fix breaking problem with SocketIO. Add setExtraHeaders to SocketIO + 2.7.0 K Hoang 24/05/2021 Add support to RP2040-based boards using Arduino-pico and Arduino mbed_rp2040 core + 2.8.0 K Hoang 08/07/2021 Add support to WT32_ETH01 (ESP32 + LAN8720) boards + 2.9.0 K Hoang 05/09/2021 Add support to QNEthernet Library for Teensy 4.1 + 2.10.0 K Hoang 18/09/2021 Add support to Portenta_H7, using either WiFi or Vision-shield Ethernet + 2.10.1 K Hoang 12/10/2021 Update `platform.ini` and `library.json` + 2.11.0 K Hoang 30/11/2021 Auto detect ESP32 core version. Fix bug in examples + 2.11.1 K Hoang 12/12/2021 Add option to use transport=websocket with sticky-session SIO server + 2.12.0 K Hoang 28/01/2022 Supporting SSL for ESP32-based WT32_ETH01 boards + 2.13.0 K Hoang 14/02/2022 Add support to ESP32_S3. Add PING and PONG SocketIO events + 2.14.0 K Hoang 17/02/2022 Suppress unnecessary warnings. Optimize code by passing by reference instead of value + *****************************************************************************************************************************/ + +#pragma once + +#ifndef WEBSOCKETS_CLIENT_GENERIC_H_ +#define WEBSOCKETS_CLIENT_GENERIC_H_ + +#include "WebSockets_Generic.h" + +class WebSocketsClient : protected WebSockets +{ + public: +#ifdef __AVR__ + typedef void (*WebSocketClientEvent)(WStype_t type, uint8_t * payload, size_t length); +#else + typedef std::function WebSocketClientEvent; +#endif + + WebSocketsClient(); + virtual ~WebSocketsClient(); + + void begin(const char * host, const uint16_t& port, const char * url = "/", const char * protocol = "arduino"); + void begin(const String& host, const uint16_t& port, const String& url = "/", const String& protocol = "arduino"); + void begin(const IPAddress& host, const uint16_t& port, const char * url = "/", const char * protocol = "arduino"); + + // KH + void begin(const IPAddress& host, const uint16_t& port, const String& url = "/", const String& protocol = "arduino"); + +#if defined(HAS_SSL) +#ifdef SSL_AXTLS + + void beginSSL(const char * host, const uint16_t& port, const char * url = "/", const char * fingerprint = "", + const char * protocol = "arduino"); + + // KH + void beginSSL(const IPAddress& host, const uint16_t& port, const String& url = "/", const String& fingerprint = "", + const String& protocol = "arduino"); + ////// + + void beginSSL(const String& host, const uint16_t& port, const String& url = "/", const String& fingerprint = "", + const String& protocol = "arduino"); + +#else + + void beginSSL(const char * host, const uint16_t& port, const char * url = "/", const uint8_t * fingerprint = NULL, + const char * protocol = "arduino"); + + // KH + void beginSSL(const IPAddress& host, const uint16_t& port, const String& url = "/", const String& fingerprint = "", + const String& protocol = "arduino"); + ////// + + void beginSslWithCA(const char * host, const uint16_t& port, const char * url = "/", BearSSL::X509List * CA_cert = NULL, + const char * protocol = "arduino"); + + // New in v2.3.5 + void setSSLClientCertKey(BearSSL::X509List * clientCert = NULL, BearSSL::PrivateKey * clientPrivateKey = NULL); + + void setSSLClientCertKey(const char * clientCert = NULL, const char * clientPrivateKey = NULL); + ////// + +#endif // SSL_AXTLS + + void beginSslWithCA(const char * host, const uint16_t& port, const char * url = "/", const char * CA_cert = NULL, const char * protocol = "arduino"); + +#endif // HAS_SSL + + void beginSocketIO(const char * host, const uint16_t& port, const char * url = "/socket.io/?EIO=4", + const char * protocol = "arduino"); + + void beginSocketIO(const String& host, const uint16_t& port, const String& url = "/socket.io/?EIO=4", + const String& protocol = "arduino"); + + // KH + void beginSocketIO(const IPAddress& host, const uint16_t& port, const String& url = "/socket.io/?EIO=4", + const String& protocol = "arduino"); + ////// + +#if defined(HAS_SSL) + void beginSocketIOSSL(const char * host, const uint16_t& port, const char * url = "/socket.io/?EIO=4", + const char * protocol = "arduino"); + + void beginSocketIOSSL(const String& host, const uint16_t& port, const String& url = "/socket.io/?EIO=4", + const String& protocol = "arduino"); + + // KH + void beginSocketIOSSL(const IPAddress& host, const uint16_t& port, const String& url = "/socket.io/?EIO=4", + const String& protocol = "arduino"); + ////// + + void beginSocketIOSSLWithCA(const char * host, const uint16_t& port, const char * url = "/socket.io/?EIO=4", + const char * CA_cert = NULL, const char * protocol = "arduino"); + +#if defined(SSL_BARESSL) + void beginSocketIOSSLWithCA(const char * host, const uint16_t& port, const char * url = "/socket.io/?EIO=4", + BearSSL::X509List * CA_cert = NULL, const char * protocol = "arduino"); +#endif // SSL_BARESSL + +#endif // HAS_SSL + +#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) + void loop(); +#else + // Async interface not need a loop call + void loop() __attribute__((deprecated)) {} +#endif + + void onEvent(WebSocketClientEvent cbEvent); + + bool sendTXT(uint8_t * payload, size_t length = 0, bool headerToPayload = false); + bool sendTXT(const uint8_t * payload, size_t length = 0); + bool sendTXT(char * payload, size_t length = 0, bool headerToPayload = false); + bool sendTXT(const char * payload, size_t length = 0); + bool sendTXT(const String& payload); + bool sendTXT(char payload); + + bool sendBIN(uint8_t * payload, size_t length, bool headerToPayload = false); + bool sendBIN(const uint8_t * payload, size_t length); + + bool sendPing(uint8_t * payload = NULL, size_t length = 0); + bool sendPing(const String& payload); + + void disconnect(); + + void setAuthorization(const char * user, const char * password); + void setAuthorization(const char * auth); + + void setExtraHeaders(const char * extraHeaders = NULL); + + void setReconnectInterval(const unsigned long& time); + + void enableHeartbeat(const uint32_t& pingInterval, const uint32_t& pongTimeout, const uint8_t& disconnectTimeoutCount); + void disableHeartbeat(); + + bool isConnected(); + + protected: + String _host; + uint16_t _port; + +#if defined(HAS_SSL) + +#ifdef SSL_AXTLS + String _fingerprint; + const char * _CA_cert; + + #define SSL_FINGERPRINT_IS_SET (_fingerprint.length()) + #define SSL_FINGERPRINT_NULL "" +#else + const uint8_t * _fingerprint; + BearSSL::X509List * _CA_cert; + BearSSL::X509List * _client_cert; + BearSSL::PrivateKey * _client_key; + + #define SSL_FINGERPRINT_IS_SET (_fingerprint != NULL) + #define SSL_FINGERPRINT_NULL NULL +#endif + +#endif + + WSclient_t _client; + + WebSocketClientEvent _cbEvent; + + unsigned long _lastConnectionFail; + unsigned long _reconnectInterval; + unsigned long _lastHeaderSent; + + void messageReceived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length, bool fin); + + void clientDisconnect(WSclient_t * client); + bool clientIsConnected(WSclient_t * client); + +#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) + void handleClientData(); +#endif + + void sendHeader(WSclient_t * client); + + void handleHeader(WSclient_t * client, String& headerLine); + + void connectedCb(); + void connectFailedCb(); + + void handleHBPing(); // send ping in specified intervals + +#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) + void asyncConnect(); +#endif + + /** + called for sending a Event to the app + @param type WStype_t + @param payload uint8_t + @param length size_t + */ + virtual void runCbEvent(WStype_t type, uint8_t * payload, size_t length) + { + if (_cbEvent) + { + _cbEvent(type, payload, length); + } + } +}; + +#include "WebSocketsClient_Generic-Impl.h" + +#endif // WEBSOCKETS_CLIENT_GENERIC_H_ diff --git a/src/src/WebSocketsDebug_Generic.h b/src/src/WebSocketsDebug_Generic.h new file mode 100644 index 00000000..70acdc93 --- /dev/null +++ b/src/src/WebSocketsDebug_Generic.h @@ -0,0 +1,192 @@ +/**************************************************************************************************************************** + WebSocketsDebug_Generic.h - WebSockets Library for boards + + Based on and modified from WebSockets libarary https://github.com/Links2004/arduinoWS + to support other boards such as SAMD21, SAMD51, Adafruit's nRF52, Teensy, STM32F, SAM DUE boards, etc. + + Built by Khoi Hoang https://github.com/khoih-prog/WS_Generic + Licensed under MIT license + + Copyright (c) 2015 Markus Sattler. All rights reserved. + This file is part of the WS for Arduino. + + 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 St, Fifth Floor, Boston, MA 02110-1301 USA + + Version: 2.14.0 + + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 2.1.3 K Hoang 15/05/2020 Initial porting to support SAMD21, SAMD51, nRF52 boards, such as AdaFruit Feather nRF52832, + nRF52840 Express, BlueFruit Sense, Itsy-Bitsy nRF52840 Express, Metro nRF52840 Express, etc. + 2.2.1 K Hoang 18/05/2020 Bump up to sync with v2.2.1 of original WebSockets library + 2.2.2 K Hoang 25/05/2020 Add support to Teensy, SAM DUE and STM32. Enable WebSocket Server for new supported boards. + 2.2.3 K Hoang 02/08/2020 Add support to W5x00's Ethernet2, Ethernet3, EthernetLarge Libraries. + Add support to STM32F/L/H/G/WB/MP1 and Seeeduino SAMD21/SAMD51 boards. + 2.3.1 K Hoang 07/10/2020 Sync with v2.3.1 of original WebSockets library. Add ENC28J60 EthernetENC library support + 2.3.2 K Hoang 12/11/2020 Add RTL8720DN Seeed_Arduino_rpcWiFi library support + 2.3.3 K Hoang 28/11/2020 Fix compile error for WIO_TERMINAL and boards using libraries with lib64. + 2.3.4 K Hoang 12/12/2020 Add SSL support to SAMD21 Nano-33-IoT using WiFiNINA. Upgrade WS and WSS examples. + 2.4.0 K Hoang 06/02/2021 Add support to Teensy 4.1 NativeEthernet and STM32 built-in LAN8742A. + Sync with v2.3.4 of original WebSockets library + 2.4.1 K Hoang 19/03/2021 Sync with v2.3.5 of original WebSockets library to adapt to ESP32 SSL changes + 2.5.0 K Hoang 22/05/2021 Add support to WiFi101 + 2.5.1 K Hoang 22/05/2021 Default to EIO4 for Socket.IO. Permit increase reconnectInterval in Socket.IO + 2.6.0 K Hoang 23/05/2021 Fix breaking problem with SocketIO. Add setExtraHeaders to SocketIO + 2.7.0 K Hoang 24/05/2021 Add support to RP2040-based boards using Arduino-pico and Arduino mbed_rp2040 core + 2.8.0 K Hoang 08/07/2021 Add support to WT32_ETH01 (ESP32 + LAN8720) boards + 2.9.0 K Hoang 05/09/2021 Add support to QNEthernet Library for Teensy 4.1 + 2.10.0 K Hoang 18/09/2021 Add support to Portenta_H7, using either WiFi or Vision-shield Ethernet + 2.10.1 K Hoang 12/10/2021 Update `platform.ini` and `library.json` + 2.11.0 K Hoang 30/11/2021 Auto detect ESP32 core version. Fix bug in examples + 2.11.1 K Hoang 12/12/2021 Add option to use transport=websocket with sticky-session SIO server + 2.12.0 K Hoang 28/01/2022 Supporting SSL for ESP32-based WT32_ETH01 boards + 2.13.0 K Hoang 14/02/2022 Add support to ESP32_S3. Add PING and PONG SocketIO events + 2.14.0 K Hoang 17/02/2022 Suppress unnecessary warnings. Optimize code by passing by reference instead of value + *****************************************************************************************************************************/ + +#pragma once + +#ifndef WEBSOCKETS_DEBUG_GENERIC_H_ +#define WEBSOCKETS_DEBUG_GENERIC_H_ + +#include + +#ifdef DEBUG_WEBSOCKETS_PORT + #define DBG_PORT DEBUG_WEBSOCKETS_PORT +#else + #define DBG_PORT Serial +#endif + +// Change _WEBSOCKETS_LOGLEVEL_ to set tracing and logging verbosity +// 0: DISABLED: no logging +// 1: ERROR: errors +// 2: WARN: errors and warnings +// 3: INFO: errors, warnings and informational (default) +// 4: DEBUG: errors, warnings, informational and debug + +#ifndef _WEBSOCKETS_LOGLEVEL_ + #define _WEBSOCKETS_LOGLEVEL_ 0 +#endif + +///////////////////// + +//For compatibility to old version libraries relying on this lib +#ifndef LOGERROR + #define LOGERROR WSK_LOGERROR + #define LOGERROR0 WSK_LOGERROR0 + #define LOGERROR1 WSK_LOGERROR1 + #define LOGERROR2 WSK_LOGERROR2 + #define LOGERROR3 WSK_LOGERROR3 +#endif + +#ifndef LOGWARN + #define LOGWARN WSK_LOGWARN + #define LOGWARN0 WSK_LOGWARN0 + #define LOGWARN1 WSK_LOGWARN1 + #define LOGWARN2 WSK_LOGWARN2 + #define LOGWARN3 WSK_LOGWARN3 +#endif + +#ifndef LOGINFO + #define LOGINFO WSK_LOGINFO + #define LOGINFO0 WSK_LOGINFO0 + #define LOGINFO1 WSK_LOGINFO1 + #define LOGINFO2 WSK_LOGINFO2 + #define LOGINFO3 WSK_LOGINFO3 +#endif + +#ifndef LOGDEBUG + #define LOGDEBUG WSK_LOGDEBUG + #define LOGDEBUG0 WSK_LOGDEBUG0 + #define LOGDEBUG1 WSK_LOGDEBUG1 + #define LOGDEBUG2 WSK_LOGDEBUG2 + #define LOGDEBUG3 WSK_LOGDEBUG3 +#endif + +///////////////////// + +//For compatibility to old version examples if not fixed yet + +#ifndef WS_LOGERROR + #define WS_LOGERROR WSK_LOGERROR + #define WS_LOGERROR0 WSK_LOGERROR0 + #define WS_LOGERROR1 WSK_LOGERROR1 + #define WS_LOGERROR2 WSK_LOGERROR2 + #define WS_LOGERROR3 WSK_LOGERROR3 + + #define WS_LOGWARN WSK_LOGWARN + #define WS_LOGWARN0 WSK_LOGWARN0 + #define WS_LOGWARN1 WSK_LOGWARN1 + #define WS_LOGWARN2 WSK_LOGWARN2 + #define WS_LOGWARN3 WSK_LOGWARN3 + + #define WS_LOGINFO WSK_LOGINFO + #define WS_LOGINFO0 WSK_LOGINFO0 + #define WS_LOGINFO1 WSK_LOGINFO1 + #define WS_LOGINFO2 WSK_LOGINFO2 + #define WS_LOGINFO3 WSK_LOGINFO3 + + #define WS_LOGDEBUG WSK_LOGDEBUG + #define WS_LOGDEBUG0 WSK_LOGDEBUG0 + #define WS_LOGDEBUG1 WSK_LOGDEBUG1 + #define WS_LOGDEBUG2 WSK_LOGDEBUG2 + #define WS_LOGDEBUG3 WSK_LOGDEBUG3 +#endif + +///////////////////// + +const char WS_MARK[] = "[WS] "; + +#define WS_PRINT_MARK WS_PRINT(WS_MARK) + +#define WS_PRINT DBG_PORT.print +#define WS_PRINTLN DBG_PORT.println + +///////////////////// + +#define WSK_LOGERROR(x) if(_WEBSOCKETS_LOGLEVEL_>0) { WS_PRINT_MARK; WS_PRINTLN(x); } +#define WSK_LOGERROR0(x) if(_WEBSOCKETS_LOGLEVEL_>0) { WS_PRINT(x); } +#define WSK_LOGERROR1(x,y) if(_WEBSOCKETS_LOGLEVEL_>0) { WS_PRINT_MARK; WS_PRINT(x); WS_PRINTLN(y); } +#define WSK_LOGERROR2(x,y,z) if(_WEBSOCKETS_LOGLEVEL_>0) { WS_PRINT_MARK; WS_PRINT(x); WS_PRINT(y); WS_PRINTLN(z); } +#define WSK_LOGERROR3(x,y,z,w) if(_WEBSOCKETS_LOGLEVEL_>0) { WS_PRINT_MARK; WS_PRINT(x); WS_PRINT(y); WS_PRINT(z); WS_PRINTLN(w); } + +///////////////////// + +#define WSK_LOGWARN(x) if(_WEBSOCKETS_LOGLEVEL_>1) { WS_PRINT_MARK; WS_PRINTLN(x); } +#define WSK_LOGWARN0(x) if(_WEBSOCKETS_LOGLEVEL_>1) { WS_PRINT(x); } +#define WSK_LOGWARN1(x,y) if(_WEBSOCKETS_LOGLEVEL_>1) { WS_PRINT_MARK; WS_PRINT(x); WS_PRINTLN(y); } +#define WSK_LOGWARN2(x,y,z) if(_WEBSOCKETS_LOGLEVEL_>1) { WS_PRINT_MARK; WS_PRINT(x); WS_PRINT(y); WS_PRINTLN(z); } +#define WSK_LOGWARN3(x,y,z,w) if(_WEBSOCKETS_LOGLEVEL_>1) { WS_PRINT_MARK; WS_PRINT(x); WS_PRINT(y); WS_PRINT(z); WS_PRINTLN(w); } + +///////////////////// + +#define WSK_LOGINFO(x) if(_WEBSOCKETS_LOGLEVEL_>2) { WS_PRINT_MARK; WS_PRINTLN(x); } +#define WSK_LOGINFO0(x) if(_WEBSOCKETS_LOGLEVEL_>2) { WS_PRINT(x); } +#define WSK_LOGINFO1(x,y) if(_WEBSOCKETS_LOGLEVEL_>2) { WS_PRINT_MARK; WS_PRINT(x); WS_PRINTLN(y); } +#define WSK_LOGINFO2(x,y,z) if(_WEBSOCKETS_LOGLEVEL_>2) { WS_PRINT_MARK; WS_PRINT(x); WS_PRINT(y); WS_PRINTLN(z); } +#define WSK_LOGINFO3(x,y,z,w) if(_WEBSOCKETS_LOGLEVEL_>2) { WS_PRINT_MARK; WS_PRINT(x); WS_PRINT(y); WS_PRINT(z); WS_PRINTLN(w); } + +///////////////////// + +#define WSK_LOGDEBUG(x) if(_WEBSOCKETS_LOGLEVEL_>3) { WS_PRINT_MARK; WS_PRINTLN(x); } +#define WSK_LOGDEBUG0(x) if(_WEBSOCKETS_LOGLEVEL_>3) { WS_PRINT_MARK; WS_PRINT(x); } +#define WSK_LOGDEBUG1(x,y) if(_WEBSOCKETS_LOGLEVEL_>3) { WS_PRINT_MARK; WS_PRINT(x); WS_PRINTLN(y); } +#define WSK_LOGDEBUG2(x,y,z) if(_WEBSOCKETS_LOGLEVEL_>3) { WS_PRINT_MARK; WS_PRINT(x); WS_PRINT(y); WS_PRINTLN(z); } +#define WSK_LOGDEBUG3(x,y,z,w) if(_WEBSOCKETS_LOGLEVEL_>3) { WS_PRINT_MARK; WS_PRINT(x); WS_PRINT(y); WS_PRINT(z); WS_PRINTLN(w); } + +///////////////////// + +#endif // WEBSOCKETS_DEBUG_GENERIC_H_ + diff --git a/src/src/WebSocketsServer_Generic-Impl.h b/src/src/WebSocketsServer_Generic-Impl.h new file mode 100644 index 00000000..55725d2a --- /dev/null +++ b/src/src/WebSocketsServer_Generic-Impl.h @@ -0,0 +1,1289 @@ +/**************************************************************************************************************************** + WebSocketsServer_Generic-Impl.h - WebSockets Library for boards + + Based on and modified from WebSockets libarary https://github.com/Links2004/arduinoWebSockets + to support other boards such as SAMD21, SAMD51, Adafruit's nRF52 boards, etc. + + Built by Khoi Hoang https://github.com/khoih-prog/WebSockets_Generic + Licensed under MIT license + + @original file WebSocketsServer.cpp + @date 20.05.2015 + @author Markus Sattler + + Copyright (c) 2015 Markus Sattler. All rights reserved. + This file is part of the WebSockets for Arduino. + + 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 St, Fifth Floor, Boston, MA 02110-1301 USA + + Version: 2.14.0 + + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 2.1.3 K Hoang 15/05/2020 Initial porting to support SAMD21, SAMD51, nRF52 boards, such as AdaFruit Feather nRF52832, + nRF52840 Express, BlueFruit Sense, Itsy-Bitsy nRF52840 Express, Metro nRF52840 Express, etc. + 2.2.1 K Hoang 18/05/2020 Bump up to sync with v2.2.1 of original WebSockets library + 2.2.2 K Hoang 25/05/2020 Add support to Teensy, SAM DUE and STM32. Enable WebSocket Server for new supported boards. + 2.2.3 K Hoang 02/08/2020 Add support to W5x00's Ethernet2, Ethernet3, EthernetLarge Libraries. + Add support to STM32F/L/H/G/WB/MP1 and Seeeduino SAMD21/SAMD51 boards. + 2.3.1 K Hoang 07/10/2020 Sync with v2.3.1 of original WebSockets library. Add ENC28J60 EthernetENC library support + 2.3.2 K Hoang 12/11/2020 Add RTL8720DN Seeed_Arduino_rpcWiFi library support + 2.3.3 K Hoang 28/11/2020 Fix compile error for WIO_TERMINAL and boards using libraries with lib64. + 2.3.4 K Hoang 12/12/2020 Add SSL support to SAMD21 Nano-33-IoT using WiFiNINA. Upgrade WS and WSS examples. + 2.4.0 K Hoang 06/02/2021 Add support to Teensy 4.1 NativeEthernet and STM32 built-in LAN8742A. + Sync with v2.3.4 of original WebSockets library + 2.4.1 K Hoang 19/03/2021 Sync with v2.3.5 of original WebSockets library to adapt to ESP32 SSL changes + 2.5.0 K Hoang 22/05/2021 Add support to WiFi101 + 2.5.1 K Hoang 22/05/2021 Default to EIO4 for Socket.IO. Permit increase reconnectInterval in Socket.IO + 2.6.0 K Hoang 23/05/2021 Fix breaking problem with SocketIO. Add setExtraHeaders to SocketIO + 2.7.0 K Hoang 24/05/2021 Add support to RP2040-based boards using Arduino-pico and Arduino mbed_rp2040 core + 2.8.0 K Hoang 08/07/2021 Add support to WT32_ETH01 (ESP32 + LAN8720) boards + 2.9.0 K Hoang 05/09/2021 Add support to QNEthernet Library for Teensy 4.1 + 2.10.0 K Hoang 18/09/2021 Add support to Portenta_H7, using either WiFi or Vision-shield Ethernet + 2.10.1 K Hoang 12/10/2021 Update `platform.ini` and `library.json` + 2.11.0 K Hoang 30/11/2021 Auto detect ESP32 core version. Fix bug in examples + 2.11.1 K Hoang 12/12/2021 Add option to use transport=websocket with sticky-session SIO server + 2.12.0 K Hoang 28/01/2022 Supporting SSL for ESP32-based WT32_ETH01 boards + 2.13.0 K Hoang 14/02/2022 Add support to ESP32_S3. Add PING and PONG SocketIO events + 2.14.0 K Hoang 17/02/2022 Suppress unnecessary warnings. Optimize code by passing by reference instead of value + *****************************************************************************************************************************/ + +#pragma once + +#ifndef WEBSOCKETS_SERVER_GENERIC_IMPL_H_ +#define WEBSOCKETS_SERVER_GENERIC_IMPL_H_ + +WebSocketsServerCore::WebSocketsServerCore(const String & origin, const String & protocol) +{ + _origin = origin; + _protocol = protocol; + _runnning = false; + _pingInterval = 0; + _pongTimeout = 0; + _disconnectTimeoutCount = 0; + + _cbEvent = NULL; + + _httpHeaderValidationFunc = NULL; + _mandatoryHttpHeaders = NULL; + _mandatoryHttpHeaderCount = 0; +} + +WebSocketsServer::WebSocketsServer(const uint16_t& port, const String & origin, const String & protocol) + : WebSocketsServerCore(origin, protocol) +{ + _port = port; + + _server = new WEBSOCKETS_NETWORK_SERVER_CLASS(port); + +#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) + _server->onClient([](void * s, AsyncClient * c) + { + ((WebSocketsServerCore *)s)->newClient(new AsyncTCPbuffer(c)); + }, + this); +#endif +} + +WebSocketsServerCore::~WebSocketsServerCore() +{ + // disconnect all clients + close(); + + if(_mandatoryHttpHeaders) + delete[] _mandatoryHttpHeaders; + + _mandatoryHttpHeaderCount = 0; +} + +WebSocketsServer::~WebSocketsServer() +{ +} + +/** + called to initialize the Websocket server +*/ +void WebSocketsServerCore::begin() +{ + // adjust clients storage: + // _clients[i]'s constructor are already called, + // all its members are initialized to their default value, + // except the ones explicitly detailed in WSclient_t() constructor. + // Then we need to initialize some members to non-trivial values: + for (int i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) + { + _clients[i].init(i, _pingInterval, _pongTimeout, _disconnectTimeoutCount); + } + +#ifdef ESP8266 + randomSeed(RANDOM_REG32); +#elif defined(ESP32) + #define DR_REG_RNG_BASE 0x3ff75144 + randomSeed(READ_PERI_REG(DR_REG_RNG_BASE)); +#else + // TODO find better seed + randomSeed(millis()); +#endif + + _runnning = true; + + WSK_LOGDEBUG(WEBSOCKETS_GENERIC_VERSION); +} + +void WebSocketsServerCore::close() +{ + _runnning = false; + disconnect(); + + // restore _clients[] to their initial state + // before next call to ::begin() + for (int i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) + { + _clients[i] = WSclient_t(); + } +} + +/** + * set callback function + * @param cbEvent WebSocketServerEvent + */ +void WebSocketsServerCore::onEvent(WebSocketServerEvent cbEvent) +{ + _cbEvent = cbEvent; +} + +/* + Sets the custom http header validator function + @param httpHeaderValidationFunc WebSocketServerHttpHeaderValFunc ///< pointer to the custom http header validation function + @param mandatoryHttpHeaders[] const char* ///< the array of named http headers considered to be mandatory / must be present in order for websocket upgrade to succeed + @param mandatoryHttpHeaderCount size_t ///< the number of items in the mandatoryHttpHeaders array +*/ +void WebSocketsServerCore::onValidateHttpHeader(WebSocketServerHttpHeaderValFunc validationFunc, + const char * mandatoryHttpHeaders[], size_t mandatoryHttpHeaderCount) +{ + _httpHeaderValidationFunc = validationFunc; + + if (_mandatoryHttpHeaders) + delete[] _mandatoryHttpHeaders; + + _mandatoryHttpHeaderCount = mandatoryHttpHeaderCount; + _mandatoryHttpHeaders = new String[_mandatoryHttpHeaderCount]; + + for (size_t i = 0; i < _mandatoryHttpHeaderCount; i++) + { + _mandatoryHttpHeaders[i] = mandatoryHttpHeaders[i]; + } +} + +/* + send text data to client + @param num uint8_t client id + @param payload uint8_t + @param length size_t + @param headerToPayload bool (see sendFrame for more details) + @return true if ok +*/ +bool WebSocketsServerCore::sendTXT(const uint8_t& num, uint8_t * payload, size_t length, bool headerToPayload) +{ + if (num >= WEBSOCKETS_SERVER_CLIENT_MAX) + { + return false; + } + + if (length == 0) + { + length = strlen((const char *)payload); + } + + WSclient_t * client = &_clients[num]; + + if (clientIsConnected(client)) + { + return sendFrame(client, WSop_text, payload, length, true, headerToPayload); + } + + return false; +} + +bool WebSocketsServerCore::sendTXT(const uint8_t& num, const uint8_t * payload, size_t length) +{ + return sendTXT(num, (uint8_t *)payload, length); +} + +bool WebSocketsServerCore::sendTXT(const uint8_t& num, char * payload, size_t length, bool headerToPayload) +{ + return sendTXT(num, (uint8_t *)payload, length, headerToPayload); +} + +bool WebSocketsServerCore::sendTXT(const uint8_t& num, const char * payload, size_t length) +{ + return sendTXT(num, (uint8_t *)payload, length); +} + +bool WebSocketsServerCore::sendTXT(const uint8_t& num, const String& payload) +{ + return sendTXT(num, (uint8_t *)payload.c_str(), payload.length()); +} + +/** + send text data to client all + @param payload uint8_t + @param length size_t + @param headerToPayload bool (see sendFrame for more details) + @return true if ok +*/ +bool WebSocketsServerCore::broadcastTXT(uint8_t * payload, size_t length, bool headerToPayload) +{ + WSclient_t * client; + bool ret = true; + + if (length == 0) + { + length = strlen((const char *)payload); + } + + for (uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) + { + client = &_clients[i]; + + if (clientIsConnected(client)) + { + if (!sendFrame(client, WSop_text, payload, length, true, headerToPayload)) + { + ret = false; + } + } + + WEBSOCKETS_YIELD(); + } + + return ret; +} + +bool WebSocketsServerCore::broadcastTXT(const uint8_t * payload, size_t length) +{ + return broadcastTXT((uint8_t *)payload, length); +} + +bool WebSocketsServerCore::broadcastTXT(char * payload, size_t length, bool headerToPayload) +{ + return broadcastTXT((uint8_t *)payload, length, headerToPayload); +} + +bool WebSocketsServerCore::broadcastTXT(const char * payload, size_t length) +{ + return broadcastTXT((uint8_t *)payload, length); +} + +bool WebSocketsServerCore::broadcastTXT(const String& payload) +{ + return broadcastTXT((uint8_t *)payload.c_str(), payload.length()); +} + +/** + send binary data to client + @param num uint8_t client id + @param payload uint8_t + @param length size_t + @param headerToPayload bool (see sendFrame for more details) + @return true if ok +*/ +bool WebSocketsServerCore::sendBIN(const uint8_t& num, uint8_t * payload, size_t length, bool headerToPayload) +{ + if (num >= WEBSOCKETS_SERVER_CLIENT_MAX) + { + return false; + } + + WSclient_t * client = &_clients[num]; + + if (clientIsConnected(client)) + { + return sendFrame(client, WSop_binary, payload, length, true, headerToPayload); + } + + return false; +} + +bool WebSocketsServerCore::sendBIN(const uint8_t& num, const uint8_t * payload, size_t length) +{ + return sendBIN(num, (uint8_t *)payload, length); +} + +/** + send binary data to client all + @param payload uint8_t + @param length size_t + @param headerToPayload bool (see sendFrame for more details) + @return true if ok +*/ +bool WebSocketsServerCore::broadcastBIN(uint8_t * payload, size_t length, bool headerToPayload) +{ + WSclient_t * client; + bool ret = true; + + for (uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) + { + client = &_clients[i]; + + if (clientIsConnected(client)) + { + if (!sendFrame(client, WSop_binary, payload, length, true, headerToPayload)) + { + ret = false; + } + } + + WEBSOCKETS_YIELD(); + } + + return ret; +} + +bool WebSocketsServerCore::broadcastBIN(const uint8_t * payload, size_t length) +{ + return broadcastBIN((uint8_t *)payload, length); +} + +/** + sends a WS ping to Client + @param num uint8_t client id + @param payload uint8_t + @param length size_t + @return true if ping is send out +*/ +bool WebSocketsServerCore::sendPing(const uint8_t& num, uint8_t * payload, size_t length) +{ + if (num >= WEBSOCKETS_SERVER_CLIENT_MAX) + { + return false; + } + + WSclient_t * client = &_clients[num]; + + if (clientIsConnected(client)) + { + return sendFrame(client, WSop_ping, payload, length); + } + + return false; +} + +bool WebSocketsServerCore::sendPing(const uint8_t& num, const String& payload) +{ + return sendPing(num, (uint8_t *)payload.c_str(), payload.length()); +} + +/** + sends a WS ping to all Client + @param payload uint8_t + @param length size_t + @return true if ping is send out +*/ +bool WebSocketsServerCore::broadcastPing(uint8_t * payload, size_t length) +{ + WSclient_t * client; + bool ret = true; + + for (uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) + { + client = &_clients[i]; + if (clientIsConnected(client)) + { + if (!sendFrame(client, WSop_ping, payload, length)) + { + ret = false; + } + } + + WEBSOCKETS_YIELD(); + } + + return ret; +} + +bool WebSocketsServerCore::broadcastPing(const String& payload) +{ + return broadcastPing((uint8_t *)payload.c_str(), payload.length()); +} + +/** + disconnect all clients +*/ +void WebSocketsServerCore::disconnect() +{ + WSclient_t * client; + + for (uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) + { + client = &_clients[i]; + + if (clientIsConnected(client)) + { + WebSockets::clientDisconnect(client, 1000); + } + } +} + +/** + disconnect one client + @param num uint8_t client id +*/ +void WebSocketsServerCore::disconnect(const uint8_t& num) +{ + if (num >= WEBSOCKETS_SERVER_CLIENT_MAX) + { + return; + } + + WSclient_t * client = &_clients[num]; + + if (clientIsConnected(client)) + { + WebSockets::clientDisconnect(client, 1000); + } +} + +/* + set the Authorization for the http request + @param user const char + @param password const char +*/ +void WebSocketsServerCore::setAuthorization(const char * user, const char * password) +{ + if (user && password) + { + String auth = user; + auth += ":"; + auth += password; + _base64Authorization = base64_encode((uint8_t *)auth.c_str(), auth.length()); + } +} + +/** + set the Authorizatio for the http request + @param auth const char * base64 +*/ +void WebSocketsServerCore::setAuthorization(const char * auth) +{ + if (auth) + { + _base64Authorization = auth; + } +} + +/** + count the connected clients (optional ping them) + @param ping bool ping the connected clients +*/ +int WebSocketsServerCore::connectedClients(bool ping) +{ + WSclient_t * client; + int count = 0; + + for (uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) + { + client = &_clients[i]; + + if (client->status == WSC_CONNECTED) + { + if (ping != true || sendPing(i)) + { + count++; + } + } + } + + return count; +} + +/** + see if one client is connected + @param num uint8_t client id +*/ +bool WebSocketsServerCore::clientIsConnected(const uint8_t& num) +{ + if (num >= WEBSOCKETS_SERVER_CLIENT_MAX) + { + return false; + } + + WSclient_t * client = &_clients[num]; + + return clientIsConnected(client); +} + +#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) || \ + (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RTL8720DN) +/** + get an IP for a client + @param num uint8_t client id + @return IPAddress +*/ +IPAddress WebSocketsServerCore::remoteIP(const uint8_t& num) +{ + if (num < WEBSOCKETS_SERVER_CLIENT_MAX) + { + WSclient_t * client = &_clients[num]; + + if (clientIsConnected(client)) + { + return client->tcp->remoteIP(); + } + } + + return IPAddress(); +} +#endif + +//################################################################################# +//################################################################################# +//################################################################################# + +/** + handle new client connection + @param client +*/ +WSclient_t * WebSocketsServerCore::newClient(WEBSOCKETS_NETWORK_CLASS * TCPclient) +{ + WSclient_t * client; + + // search free list entry for client + for (uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) + { + client = &_clients[i]; + + // KH Debug + //displayClientData(client, false); + //displayClientData(client); + + // state is not connected or tcp connection is lost + if (!clientIsConnected(client)) + { + client->tcp = TCPclient; + +#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || \ + (WEBSOCKETS_NETWORK_TYPE == NETWORK_RTL8720DN) + client->isSSL = false; + client->tcp->setNoDelay(true); +#endif + +#if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) + // set Timeout for readBytesUntil and readStringUntil + client->tcp->setTimeout(WEBSOCKETS_TCP_TIMEOUT); +#endif + + client->status = WSC_HEADER; + + // KH Debug + //client->status = WSC_NOT_CONNECTED; + +#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) \ + || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RTL8720DN) + #ifndef NODEBUG_WEBSOCKETS + IPAddress ip = client->tcp->remoteIP(); + + // KH New debug + WSK_LOGDEBUG3("ESP New Client :", client->num, ", IP =", ip); + #endif +#else + // KH New debug + WSK_LOGDEBUG1("New Client :", client->num); +#endif + +#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) + + client->tcp->onDisconnect(std::bind([](WebSocketsServerCore * server, AsyncTCPbuffer * obj, + WSclient_t * client) -> bool + { + WSK_LOGDEBUG1("Disconnect Client :", client->num); + + AsyncTCPbuffer ** sl = &server->_clients[client->num].tcp; + + if (*sl == obj) + { + client->status = WSC_NOT_CONNECTED; + *sl = NULL; + } + + return true; + }, + this, std::placeholders::_1, client)); + + client->tcp->readStringUntil('\n', &(client->cHttpLine), std::bind(&WebSocketsServerCore::handleHeader, + this, client, &(client->cHttpLine))); + +#endif + + client->pingInterval = _pingInterval; + client->pongTimeout = _pongTimeout; + client->disconnectTimeoutCount = _disconnectTimeoutCount; + client->lastPing = millis(); + client->pongReceived = false; + + return client; + break; + } + } + + return nullptr; +} + +/** + + @param client WSclient_t * ptr to the client struct + @param opcode WSopcode_t + @param payload uint8_t + @param length size_t +*/ +void WebSocketsServerCore::messageReceived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length, bool fin) +{ + WStype_t type = WStype_ERROR; + + switch (opcode) + { + case WSop_text: + type = fin ? WStype_TEXT : WStype_FRAGMENT_TEXT_START; + break; + case WSop_binary: + type = fin ? WStype_BIN : WStype_FRAGMENT_BIN_START; + break; + case WSop_continuation: + type = fin ? WStype_FRAGMENT_FIN : WStype_FRAGMENT; + break; + case WSop_ping: + type = WStype_PING; + break; + case WSop_pong: + type = WStype_PONG; + break; + case WSop_close: + default: + break; + } + + runCbEvent(client->num, type, payload, length); +} + +/** + Discard a native client + @param client WSclient_t * ptr to the client struct contaning the native client "->tcp" +*/ +void WebSocketsServerCore::dropNativeClient(WSclient_t * client) +{ + if (client->tcp) + { + if (client->tcp->connected()) + { +#if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) && (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP32) + client->tcp->flush(); +#endif + client->tcp->stop(); + } + +#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) + client->status = WSC_NOT_CONNECTED; +#else + delete client->tcp; +#endif + client->tcp = NULL; + } +} + +/** + Disconnect an client + @param client WSclient_t * ptr to the client struct +*/ +void WebSocketsServerCore::clientDisconnect(WSclient_t * client) +{ +#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || \ + (WEBSOCKETS_NETWORK_TYPE == NETWORK_RTL8720DN) + if (client->isSSL && client->ssl) + { + if (client->ssl->connected()) + { + client->ssl->flush(); + client->ssl->stop(); + } + + delete client->ssl; + client->ssl = NULL; + client->tcp = NULL; + } +#endif + + dropNativeClient(client); + + client->cUrl = ""; + client->cKey = ""; + client->cProtocol = ""; + client->cVersion = 0; + client->cIsUpgrade = false; + client->cIsWebsocket = false; + + client->cWsRXsize = 0; + +#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) + client->cHttpLine = ""; +#endif + + client->status = WSC_NOT_CONNECTED; + + // KH New debug + WSK_LOGDEBUG1("Disconnected Client :", client->num); + //WSK_LOGINFO1("Disconnected Client :", client->num); + + runCbEvent(client->num, WStype_DISCONNECTED, NULL, 0); +} + +/** + get client state + @param client WSclient_t * ptr to the client struct + @return true = connected +*/ +bool WebSocketsServerCore::clientIsConnected(WSclient_t * client) +{ + if (!client->tcp) + { + return false; + } + + if (client->tcp->connected()) + { + if (client->status != WSC_NOT_CONNECTED) + { + return true; + } + } + else + { + // client lost + if (client->status != WSC_NOT_CONNECTED) + { + WSK_LOGDEBUG1("Clean up : Connection lost. Client :", client->num ); + // do cleanup + clientDisconnect(client); + } + } + + if (client->tcp) + { + // do cleanup + WSK_LOGDEBUG1("[WS-Server] client->tcp, client list cleanup 2. Client :", client->num); + clientDisconnect(client); + } + + return false; +} + +#if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) +/** + Handle incoming Connection Request +*/ +WSclient_t * WebSocketsServerCore::handleNewClient(WEBSOCKETS_NETWORK_CLASS * tcpClient) +{ + WSclient_t * client = newClient(tcpClient); + + if (!client) + { + // no free space to handle client +#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || \ + (WEBSOCKETS_NETWORK_TYPE == NETWORK_RTL8720DN) + #ifndef NODEBUG_WEBSOCKETS + IPAddress ip = tcpClient->remoteIP(); + + WSK_LOGERROR1("[WS-Server][handleNewClient] No free space for new client from", ip); + #endif +#else + WSK_LOGERROR("[WS-Server][handleNewClient] No free space new client"); +#endif + + dropNativeClient(client); + } + + WEBSOCKETS_YIELD(); + + return client; +} + +/** + Handle incoming Connection Request +*/ +void WebSocketsServer::handleNewClients() +{ +#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || \ + (WEBSOCKETS_NETWORK_TYPE == NETWORK_RTL8720DN) + while (_server->hasClient()) + { +#endif + + // store new connection + WEBSOCKETS_NETWORK_CLASS * tcpClient = new WEBSOCKETS_NETWORK_CLASS(_server->available()); + + if (!tcpClient) + { + WSK_LOGERROR("[WS-Server][handleNewClients] Creating Network class failed!"); + + return; + } + + handleNewClient(tcpClient); + +#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || \ + (WEBSOCKETS_NETWORK_TYPE == NETWORK_RTL8720DN) + } +#endif +} + +/** + Handel incomming data from Client +*/ +void WebSocketsServerCore::handleClientData() +{ + WSclient_t * client; + + //static uint8_t currentActiveClient = 0xFF; + + for (uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) + { + client = &_clients[i]; + + // KH New debug + //displayClientData(client); + + if (clientIsConnected(client)) + // KH Debug + //if ( clientIsConnected(client) && client->cHttpHeadersValid ) + { + int len = client->tcp->available(); + + if (len > 0) + { + // KH New + WSK_LOGINFO3("[handleClientData] Client:", client->num, ", tcp->available len:", len); + + switch (client->status) + { + case WSC_HEADER: + { + // KH New + WSK_LOGINFO1(client->num, "[handleClientData] =================== Start ======================="); + + String headerLine = client->tcp->readStringUntil('\n'); + + // KH New + WSK_LOGINFO3("[handleClientData] Status WSC_HEADER. Client:", client->num, ", headerLine:", headerLine); + // KH Debug + //if ( client->cHttpHeadersValid ) + { + handleHeader(client, headerLine); + } + + // KH New + currentActiveClient = client->num; + + // KH New + WSK_LOGINFO1(client->num, "[handleClientData] =================== End ======================="); + } + + break; + + case WSC_CONNECTED: + // KH New + WSK_LOGINFO1("[handleClientData] Status WSC_CONNECTED. handleWebsocket. Client:", client->num); + + WebSockets::handleWebsocket(client); + + break; + + default: + // KH New + WSK_LOGINFO3("[handleClientData] default: clientDisconnect. Client:", client->num, + "unknown client status", client->status); + WebSockets::clientDisconnect(client, 1002); + + // KH New + currentActiveClient = 0xFF; + + break; + } + } + + handleHBPing(client); + handleHBTimeout(client); + } + + WEBSOCKETS_YIELD(); + } +} +#endif // #if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) + +/* + returns an indicator whether the given named header exists in the configured _mandatoryHttpHeaders collection + @param headerName String ///< the name of the header being checked +*/ +bool WebSocketsServerCore::hasMandatoryHeader(const String& headerName) +{ + for (size_t i = 0; i < _mandatoryHttpHeaderCount; i++) + { + if (_mandatoryHttpHeaders[i].equalsIgnoreCase(headerName)) + return true; + } + + return false; +} + +/** + handles http header reading for WebSocket upgrade + @param client WSclient_t * ///< pointer to the client struct + @param headerLine String ///< the header being read / processed +*/ + +///////////////////////////////////////////////////////////////////////////////////////////////////// + +void WebSocketsServerCore::handleHeader(WSclient_t * client, String& headerLine) +{ + static const char * NEW_LINE = "\r\n"; + + //WSK_LOGINFO3("[handleHeader] Client:", client->num, ", RX before trim:", headerLine.c_str()); + + headerLine.trim(); // remove \r + + //WSK_LOGINFO3("[handleHeader] Client:", client->num, ", RX after trim:", headerLine.c_str()); + + if (headerLine.length() > 0) + { + WSK_LOGINFO3("[handleHeader] Client:", client->num, ", RX:", headerLine.c_str()); + + //KH New + WSK_LOGINFO1("[handleHeader] RX: HeaderLine Len =", headerLine.length()); + + // websocket requests always start with GET see rfc6455 + if (headerLine.startsWith("GET ")) + { + // cut URL out + client->cUrl = headerLine.substring(4, headerLine.indexOf(' ', 4)); + + //KH New + WSK_LOGINFO1("[handleHeader] RX: client->cUrl =", client->cUrl); + + //reset non-websocket http header validation state for this client + client->cHttpHeadersValid = true; + client->cMandatoryHeadersCount = 0; + + } + else if (headerLine.indexOf(':') >= 0) + { + String headerName = headerLine.substring(0, headerLine.indexOf(':')); + String headerValue = headerLine.substring(headerLine.indexOf(':') + 1); + + // remove space in the beginning (RFC2616) + if (headerValue[0] == ' ') + { + headerValue.remove(0, 1); + } + + if (headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Connection"))) + { + headerValue.toLowerCase(); + + if (headerValue.indexOf(WEBSOCKETS_STRING("upgrade")) >= 0) + { + client->cIsUpgrade = true; + } + } + else if (headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Upgrade"))) + { + if (headerValue.equalsIgnoreCase(WEBSOCKETS_STRING("websocket"))) + { + client->cIsWebsocket = true; + } + } + else if (headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Sec-WebSocket-Version"))) + { + client->cVersion = headerValue.toInt(); + } + else if (headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Sec-WebSocket-Key"))) + { + client->cKey = headerValue; + client->cKey.trim(); // see rfc6455 + } + else if (headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Sec-WebSocket-Protocol"))) + { + client->cProtocol = headerValue; + } + else if (headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Sec-WebSocket-Extensions"))) + { + client->cExtensions = headerValue; + } + else if (headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Authorization"))) + { + client->base64Authorization = headerValue; + } + else + { + client->cHttpHeadersValid &= execHttpHeaderValidation(headerName, headerValue); + + if (_mandatoryHttpHeaderCount > 0 && hasMandatoryHeader(headerName)) + { + client->cMandatoryHeadersCount++; + } + } + } + else + { + WSK_LOGINFO1("[handleHeader] Header error. RX:", headerLine.c_str()); + } + + headerLine = ""; + +#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) + client->tcp->readStringUntil('\n', &(client->cHttpLine), std::bind(&WebSocketsServerCore::handleHeader, + this, client, &(client->cHttpLine))); +#endif + } + else + { + WSK_LOGINFO1(client->num, "Header read fin."); + WSK_LOGINFO2(client->num, " - cURL:", client->cUrl.c_str()); + WSK_LOGINFO2(client->num, " - cIsUpgrade:", client->cIsUpgrade); + WSK_LOGINFO2(client->num, " - cIsWebsocket:", client->cIsWebsocket); + WSK_LOGINFO2(client->num, " - cKey:", client->cKey.c_str()); + WSK_LOGINFO2(client->num, " - cProtocol:", client->cProtocol.c_str()); + WSK_LOGINFO2(client->num, " - cExtensions:", client->cExtensions.c_str()); + WSK_LOGINFO2(client->num, " - cVersion:", client->cVersion); + WSK_LOGINFO2(client->num, " - base64Authorization:", client->base64Authorization.c_str()); + WSK_LOGINFO2(client->num, " - cHttpHeadersValid:", client->cHttpHeadersValid); + WSK_LOGINFO2(client->num, " - cMandatoryHeadersCount:", client->cMandatoryHeadersCount); + + bool ok = (client->cIsUpgrade && client->cIsWebsocket); + + if (ok) + { + if (client->cUrl.length() == 0) + { + ok = false; + } + + if (client->cKey.length() == 0) + { + ok = false; + } + + if (client->cVersion != 13) + { + ok = false; + } + + if (!client->cHttpHeadersValid) + { + ok = false; + } + + if (client->cMandatoryHeadersCount != _mandatoryHttpHeaderCount) + { + ok = false; + } + } + + if (_base64Authorization.length() > 0) + { + String auth = WEBSOCKETS_STRING("Basic "); + auth += _base64Authorization; + + if (auth != client->base64Authorization) + { + WSK_LOGDEBUG1("[handleHeader] HTTP Authorization failed! Client:", client->num); + + handleAuthorizationFailed(client); + return; + } + } + + if (ok) + { + WSK_LOGDEBUG1("[handleHeader] Websocket connection incoming. Client:", client->num); + + // generate Sec-WebSocket-Accept key + String sKey = acceptKey(client->cKey); + + WSK_LOGDEBUG2(client->num, "[handleHeader] - sKey:", sKey.c_str()); + + client->status = WSC_CONNECTED; + + String handshake = WEBSOCKETS_STRING( + "HTTP/1.1 101 Switching Protocols\r\n" + "Server: arduino-WebSocketsServer\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + "Sec-WebSocket-Version: 13\r\n" + "Sec-WebSocket-Accept: "); + + handshake += sKey + NEW_LINE; + + if (_origin.length() > 0) + { + handshake += WEBSOCKETS_STRING("Access-Control-Allow-Origin: "); + handshake += _origin + NEW_LINE; + } + + if (client->cProtocol.length() > 0) + { + handshake += WEBSOCKETS_STRING("Sec-WebSocket-Protocol: "); + handshake += _protocol + NEW_LINE; + } + + // header end + handshake += NEW_LINE; + + WSK_LOGDEBUG3("[handleHeader] Client:", client->num, ", handshake:", (char *)handshake.c_str()); + + write(client, (uint8_t *)handshake.c_str(), handshake.length()); + + headerDone(client); + + // send ping + WebSockets::sendFrame(client, WSop_ping); + + runCbEvent(client->num, WStype_CONNECTED, (uint8_t *)client->cUrl.c_str(), client->cUrl.length()); + + } + else + { + handleNonWebsocketConnection(client); + } + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + send heartbeat ping to server in set intervals +*/ +void WebSocketsServerCore::handleHBPing(WSclient_t * client) +{ + if (client->pingInterval == 0) + return; + + uint32_t pi = millis() - client->lastPing; + + if (pi > client->pingInterval) + { + WSK_LOGDEBUG1("[handleHeader] Sending HB ping to Client:", client->num); + + if (sendPing(client->num)) + { + client->lastPing = millis(); + client->pongReceived = false; + } + } +} + +/** + enable ping/pong heartbeat process + @param pingInterval uint32_t how often ping will be sent + @param pongTimeout uint32_t millis after which pong should timout if not received + @param disconnectTimeoutCount uint8_t how many timeouts before disconnect, 0=> do not disconnect +*/ +void WebSocketsServerCore::enableHeartbeat(const uint32_t& pingInterval, const uint32_t& pongTimeout, + const uint8_t& disconnectTimeoutCount) +{ + _pingInterval = pingInterval; + _pongTimeout = pongTimeout; + _disconnectTimeoutCount = disconnectTimeoutCount; + + WSclient_t * client; + + for (uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) + { + client = &_clients[i]; + WebSockets::enableHeartbeat(client, pingInterval, pongTimeout, disconnectTimeoutCount); + } +} + +/** + disable ping/pong heartbeat process +*/ +void WebSocketsServerCore::disableHeartbeat() +{ + _pingInterval = 0; + + WSclient_t * client; + + for (uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) + { + client = &_clients[i]; + client->pingInterval = 0; + } +} + + +//////////////////// +// WebSocketServer + +/** + called to initialize the Websocket server +*/ +void WebSocketsServer::begin() +{ + WebSocketsServerCore::begin(); + _server->begin(); + + WSK_LOGDEBUG("[WS-Server] Server Started."); +} + +void WebSocketsServer::close() +{ + WebSocketsServerCore::close(); + +#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) + _server->close(); +#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) || \ + (WEBSOCKETS_NETWORK_TYPE == NETWORK_RTL8720DN) + _server->end(); +#else + // TODO how to close server? +#endif +} + +#if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) +/** + called in arduino loop +*/ +void WebSocketsServerCore::loop() +{ + if (_runnning) + { + WEBSOCKETS_YIELD(); + handleClientData(); + } +} + +/** + called in arduino loop +*/ +void WebSocketsServer::loop() +{ + if (_runnning) + { + WEBSOCKETS_YIELD(); + handleNewClients(); + WebSocketsServerCore::loop(); + } +} +#endif + +#endif // WEBSOCKETS_SERVER_GENERIC_IMPL_H_ + diff --git a/src/src/WebSocketsServer_Generic.h b/src/src/WebSocketsServer_Generic.h new file mode 100644 index 00000000..3f4f9b8e --- /dev/null +++ b/src/src/WebSocketsServer_Generic.h @@ -0,0 +1,309 @@ +/**************************************************************************************************************************** + WebSocketsServer_Generic.h - WebSockets Library for boards + + Based on and modified from WebSockets libarary https://github.com/Links2004/arduinoWebSockets + to support other boards such as SAMD21, SAMD51, Adafruit's nRF52 boards, etc. + + Built by Khoi Hoang https://github.com/khoih-prog/WebSockets_Generic + Licensed under MIT license + + @original file WebSocketsServer.h + @date 20.05.2015 + @author Markus Sattler + + Copyright (c) 2015 Markus Sattler. All rights reserved. + This file is part of the WebSockets for Arduino. + + 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 St, Fifth Floor, Boston, MA 02110-1301 USA + + Version: 2.14.0 + + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 2.1.3 K Hoang 15/05/2020 Initial porting to support SAMD21, SAMD51, nRF52 boards, such as AdaFruit Feather nRF52832, + nRF52840 Express, BlueFruit Sense, Itsy-Bitsy nRF52840 Express, Metro nRF52840 Express, etc. + 2.2.1 K Hoang 18/05/2020 Bump up to sync with v2.2.1 of original WebSockets library + 2.2.2 K Hoang 25/05/2020 Add support to Teensy, SAM DUE and STM32. Enable WebSocket Server for new supported boards. + 2.2.3 K Hoang 02/08/2020 Add support to W5x00's Ethernet2, Ethernet3, EthernetLarge Libraries. + Add support to STM32F/L/H/G/WB/MP1 and Seeeduino SAMD21/SAMD51 boards. + 2.3.1 K Hoang 07/10/2020 Sync with v2.3.1 of original WebSockets library. Add ENC28J60 EthernetENC library support + 2.3.2 K Hoang 12/11/2020 Add RTL8720DN Seeed_Arduino_rpcWiFi library support + 2.3.3 K Hoang 28/11/2020 Fix compile error for WIO_TERMINAL and boards using libraries with lib64. + 2.3.4 K Hoang 12/12/2020 Add SSL support to SAMD21 Nano-33-IoT using WiFiNINA. Upgrade WS and WSS examples. + 2.4.0 K Hoang 06/02/2021 Add support to Teensy 4.1 NativeEthernet and STM32 built-in LAN8742A. + Sync with v2.3.4 of original WebSockets library + 2.4.1 K Hoang 19/03/2021 Sync with v2.3.5 of original WebSockets library to adapt to ESP32 SSL changes + 2.5.0 K Hoang 22/05/2021 Add support to WiFi101 + 2.5.1 K Hoang 22/05/2021 Default to EIO4 for Socket.IO. Permit increase reconnectInterval in Socket.IO + 2.6.0 K Hoang 23/05/2021 Fix breaking problem with SocketIO. Add setExtraHeaders to SocketIO + 2.7.0 K Hoang 24/05/2021 Add support to RP2040-based boards using Arduino-pico and Arduino mbed_rp2040 core + 2.8.0 K Hoang 08/07/2021 Add support to WT32_ETH01 (ESP32 + LAN8720) boards + 2.9.0 K Hoang 05/09/2021 Add support to QNEthernet Library for Teensy 4.1 + 2.10.0 K Hoang 18/09/2021 Add support to Portenta_H7, using either WiFi or Vision-shield Ethernet + 2.10.1 K Hoang 12/10/2021 Update `platform.ini` and `library.json` + 2.11.0 K Hoang 30/11/2021 Auto detect ESP32 core version. Fix bug in examples + 2.11.1 K Hoang 12/12/2021 Add option to use transport=websocket with sticky-session SIO server + 2.12.0 K Hoang 28/01/2022 Supporting SSL for ESP32-based WT32_ETH01 boards + 2.13.0 K Hoang 14/02/2022 Add support to ESP32_S3. Add PING and PONG SocketIO events + 2.14.0 K Hoang 17/02/2022 Suppress unnecessary warnings. Optimize code by passing by reference instead of value + *****************************************************************************************************************************/ + +#pragma once + +#ifndef WEBSOCKETS_SERVER_GENERIC_H_ +#define WEBSOCKETS_SERVER_GENERIC_H_ + +#include "WebSockets_Generic.h" + +#ifndef WEBSOCKETS_SERVER_CLIENT_MAX + #define WEBSOCKETS_SERVER_CLIENT_MAX (5) +#endif + +class WebSocketsServerCore : protected WebSockets +{ + public: + WebSocketsServerCore(const String & origin = "", const String & protocol = "arduino"); + virtual ~WebSocketsServerCore(); + + void begin(); + void close(); + +#ifdef __AVR__ + typedef void (*WebSocketServerEvent)(const uint8_t& num, const WStype_t& type, uint8_t * payload, const size_t& length); + typedef bool (*WebSocketServerHttpHeaderValFunc)(const String& headerName, const String& headerValue); +#else + typedef std::function WebSocketServerEvent; + typedef std::function WebSocketServerHttpHeaderValFunc; +#endif + + void onEvent(WebSocketServerEvent cbEvent); + void onValidateHttpHeader( + WebSocketServerHttpHeaderValFunc validationFunc, + const char * mandatoryHttpHeaders[], + size_t mandatoryHttpHeaderCount); + + bool sendTXT(const uint8_t& num, uint8_t * payload, size_t length = 0, bool headerToPayload = false); + bool sendTXT(const uint8_t& num, const uint8_t * payload, size_t length = 0); + bool sendTXT(const uint8_t& num, char * payload, size_t length = 0, bool headerToPayload = false); + bool sendTXT(const uint8_t& num, const char * payload, size_t length = 0); + bool sendTXT(const uint8_t& num, const String& payload); + + bool broadcastTXT(uint8_t * payload, size_t length = 0, bool headerToPayload = false); + bool broadcastTXT(const uint8_t * payload, size_t length = 0); + bool broadcastTXT(char * payload, size_t length = 0, bool headerToPayload = false); + bool broadcastTXT(const char * payload, size_t length = 0); + bool broadcastTXT(const String& payload); + + bool sendBIN(const uint8_t& num, uint8_t * payload, size_t length, bool headerToPayload = false); + bool sendBIN(const uint8_t& num, const uint8_t * payload, size_t length); + + bool broadcastBIN(uint8_t * payload, size_t length, bool headerToPayload = false); + bool broadcastBIN(const uint8_t * payload, size_t length); + + bool sendPing(const uint8_t& num, uint8_t * payload = NULL, size_t length = 0); + bool sendPing(const uint8_t& num, const String& payload); + + bool broadcastPing(uint8_t * payload = NULL, size_t length = 0); + bool broadcastPing(const String& payload); + + void disconnect(); + void disconnect(const uint8_t& num); + + void setAuthorization(const char * user, const char * password); + void setAuthorization(const char * auth); + + int connectedClients(bool ping = false); + + bool clientIsConnected(const uint8_t& num); + + void enableHeartbeat(const uint32_t& pingInterval, const uint32_t& pongTimeout, const uint8_t& disconnectTimeoutCount); + void disableHeartbeat(); + +#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)\ + || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RTL8720DN) + IPAddress remoteIP(const uint8_t& num); +#endif + +#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) + void loop(); // handle client data only +#endif + + WSclient_t * newClient(WEBSOCKETS_NETWORK_CLASS * TCPclient); + + protected: + + // KH Debug + uint8_t currentActiveClient = 0xFF; + ////// + + String _origin; + String _protocol; + String _base64Authorization; ///< Base64 encoded Auth request + String * _mandatoryHttpHeaders; + size_t _mandatoryHttpHeaderCount; + + WSclient_t _clients[WEBSOCKETS_SERVER_CLIENT_MAX]; + + WebSocketServerEvent _cbEvent; + WebSocketServerHttpHeaderValFunc _httpHeaderValidationFunc; + + bool _runnning; + + uint32_t _pingInterval; + uint32_t _pongTimeout; + uint8_t _disconnectTimeoutCount; + + void messageReceived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length, bool fin); + + void clientDisconnect(WSclient_t * client); + bool clientIsConnected(WSclient_t * client); + +#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) + void handleClientData(); +#endif + + void handleHeader(WSclient_t * client, String& headerLine); + + void handleHBPing(WSclient_t * client); // send ping in specified intervals + + /** + * called if a non Websocket connection is coming in. + * Note: can be override + * @param client WSclient_t * ptr to the client struct + */ + virtual void handleNonWebsocketConnection(WSclient_t * client) + { + WSK_LOGDEBUG1("[WS-Server handleHeader] no Websocket connection close. Client =", client->num); + + client->tcp->write( + "HTTP/1.1 400 Bad Request\r\n" + "Server: arduino-WebSocket-Server\r\n" + "Content-Type: text/plain\r\n" + "Content-Length: 32\r\n" + "Connection: close\r\n" + "Sec-WebSocket-Version: 13\r\n" + "\r\n" + "This is a Websocket server only!"); + + clientDisconnect(client); + } + + /** + * called if a non Authorization connection is coming in. + * Note: can be override + * @param client WSclient_t * ptr to the client struct + */ + virtual void handleAuthorizationFailed(WSclient_t * client) + { + client->tcp->write( + "HTTP/1.1 401 Unauthorized\r\n" + "Server: arduino-WebSocket-Server\r\n" + "Content-Type: text/plain\r\n" + "Content-Length: 45\r\n" + "Connection: close\r\n" + "Sec-WebSocket-Version: 13\r\n" + "WWW-Authenticate: Basic realm=\"WebSocket Server\"" + "\r\n" + "This Websocket server requires Authorization!"); + + clientDisconnect(client); + } + + /** + * called for sending a Event to the app + * @param num uint8_t + * @param type WStype_t + * @param payload uint8_t * + * @param length size_t + */ + //virtual void runCbEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) + virtual void runCbEvent(const uint8_t& num, const WStype_t& type, uint8_t * payload, const size_t& length) + { + if(_cbEvent) + { + _cbEvent(num, type, payload, length); + } + } + + /* + * Called at client socket connect handshake negotiation time for each http header that is not + * a websocket specific http header (not Connection, Upgrade, Sec-WebSocket-*) + * If the custom httpHeaderValidationFunc returns false for any headerName / headerValue passed, the + * socket negotiation is considered invalid and the upgrade to websockets request is denied / rejected + * This mechanism can be used to enable custom authentication schemes e.g. test the value + * of a session cookie to determine if a user is logged on / authenticated + */ + virtual bool execHttpHeaderValidation(const String& headerName, const String& headerValue) + { + if(_httpHeaderValidationFunc) + { + //return the value of the custom http header validation function + return _httpHeaderValidationFunc(headerName, headerValue); + } + + //no custom http header validation so just assume all is good + return true; + } + +#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) + WSclient_t * handleNewClient(WEBSOCKETS_NETWORK_CLASS * tcpClient); +#endif + + /** + * drop native tcp connection (client->tcp) + */ + void dropNativeClient(WSclient_t * client); + + private: + /* + * returns an indicator whether the given named header exists in the configured _mandatoryHttpHeaders collection + * @param headerName String ///< the name of the header being checked + */ + bool hasMandatoryHeader(const String& headerName); +}; + +class WebSocketsServer : public WebSocketsServerCore +{ + public: + WebSocketsServer(const uint16_t& port, const String & origin = "", const String & protocol = "arduino"); + virtual ~WebSocketsServer(); + + void begin(); + void close(); + +#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) + void loop(); // handle incoming client and client data +#else + // Async interface not need a loop call + void loop() __attribute__((deprecated)) {} +#endif + + protected: +#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) + void handleNewClients(); +#endif + + // KH Debug + uint8_t currentActiveClient = 0xFF; + ////// + + uint16_t _port; + WEBSOCKETS_NETWORK_SERVER_CLASS * _server; +}; + + +#include "WebSocketsServer_Generic-Impl.h" + +#endif // WEBSOCKETS_SERVER_GENERIC_H_ diff --git a/src/src/WebSockets_Generic-Impl.h b/src/src/WebSockets_Generic-Impl.h new file mode 100644 index 00000000..0d186972 --- /dev/null +++ b/src/src/WebSockets_Generic-Impl.h @@ -0,0 +1,1058 @@ +/**************************************************************************************************************************** + WebSockets_Generic-Impl.h - WebSockets Library for boards + + Based on and modified from WebSockets libarary https://github.com/Links2004/arduinoWebSockets + to support other boards such as SAMD21, SAMD51, Adafruit's nRF52 boards, etc. + + Built by Khoi Hoang https://github.com/khoih-prog/WebSockets_Generic + Licensed under MIT license + + @original file WebSockets.cpp + @date 20.05.2015 + @author Markus Sattler + + Copyright (c) 2015 Markus Sattler. All rights reserved. + This file is part of the WebSockets for Arduino. + + 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 St, Fifth Floor, Boston, MA 02110-1301 USA + + Version: 2.14.0 + + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 2.1.3 K Hoang 15/05/2020 Initial porting to support SAMD21, SAMD51, nRF52 boards, such as AdaFruit Feather nRF52832, + nRF52840 Express, BlueFruit Sense, Itsy-Bitsy nRF52840 Express, Metro nRF52840 Express, etc. + 2.2.1 K Hoang 18/05/2020 Bump up to sync with v2.2.1 of original WebSockets library + 2.2.2 K Hoang 25/05/2020 Add support to Teensy, SAM DUE and STM32. Enable WebSocket Server for new supported boards. + 2.2.3 K Hoang 02/08/2020 Add support to W5x00's Ethernet2, Ethernet3, EthernetLarge Libraries. + Add support to STM32F/L/H/G/WB/MP1 and Seeeduino SAMD21/SAMD51 boards. + 2.3.1 K Hoang 07/10/2020 Sync with v2.3.1 of original WebSockets library. Add ENC28J60 EthernetENC library support + 2.3.2 K Hoang 12/11/2020 Add RTL8720DN Seeed_Arduino_rpcWiFi library support + 2.3.3 K Hoang 28/11/2020 Fix compile error for WIO_TERMINAL and boards using libraries with lib64. + 2.3.4 K Hoang 12/12/2020 Add SSL support to SAMD21 Nano-33-IoT using WiFiNINA. Upgrade WS and WSS examples. + 2.4.0 K Hoang 06/02/2021 Add support to Teensy 4.1 NativeEthernet and STM32 built-in LAN8742A. + Sync with v2.3.4 of original WebSockets library + 2.4.1 K Hoang 19/03/2021 Sync with v2.3.5 of original WebSockets library to adapt to ESP32 SSL changes + 2.5.0 K Hoang 22/05/2021 Add support to WiFi101 + 2.5.1 K Hoang 22/05/2021 Default to EIO4 for Socket.IO. Permit increase reconnectInterval in Socket.IO + 2.6.0 K Hoang 23/05/2021 Fix breaking problem with SocketIO. Add setExtraHeaders to SocketIO + 2.7.0 K Hoang 24/05/2021 Add support to RP2040-based boards using Arduino-pico and Arduino mbed_rp2040 core + 2.8.0 K Hoang 08/07/2021 Add support to WT32_ETH01 (ESP32 + LAN8720) boards + 2.9.0 K Hoang 05/09/2021 Add support to QNEthernet Library for Teensy 4.1 + 2.10.0 K Hoang 18/09/2021 Add support to Portenta_H7, using either WiFi or Vision-shield Ethernet + 2.10.1 K Hoang 12/10/2021 Update `platform.ini` and `library.json` + 2.11.0 K Hoang 30/11/2021 Auto detect ESP32 core version. Fix bug in examples + 2.11.1 K Hoang 12/12/2021 Add option to use transport=websocket with sticky-session SIO server + 2.12.0 K Hoang 28/01/2022 Supporting SSL for ESP32-based WT32_ETH01 boards + 2.13.0 K Hoang 14/02/2022 Add support to ESP32_S3. Add PING and PONG SocketIO events + 2.14.0 K Hoang 17/02/2022 Suppress unnecessary warnings. Optimize code by passing by reference instead of value + *****************************************************************************************************************************/ + +#pragma once + +#ifndef WEBSOCKETS_GENERIC_IMPL_H_ +#define WEBSOCKETS_GENERIC_IMPL_H_ + +#ifdef ESP8266 + #include +#endif + +#if defined(ESP32) || defined(WIO_TERMINAL) + #ifndef CORE_HAS_LIBB64 + #define CORE_HAS_LIBB64 + #endif +#endif + +extern "C" +{ + // Kludge to fix compile error for boards using libraries with lib64. From v2.3.3. + // To find better way, such as reused #ifdef ABC_H or #define LIBRARY_USING_LIB64 or #define CORE_HAS_LIBB64 in those libraries + #if defined(CORE_HAS_LIBB64) || defined(base64_encode_expected_len) || defined(base64_decode_expected_len) + #if(_WEBSOCKETS_LOGLEVEL_>3) + #warning CORE_HAS_LIBB64 + #endif + + #include + #else + #if(_WEBSOCKETS_LOGLEVEL_>3) + #warning No CORE_HAS_LIBB64 + #endif + + #include "libb64/cencode_inc.h" + #endif +} + +#ifdef ESP8266 + #include +#elif defined(ESP32) + + #include + + #if ESP_IDF_VERSION_MAJOR >= 4 + #if ( ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(1, 0, 6) ) + #include "sha/sha_parallel_engine.h" + #else + #include + #endif + #else + #include + #endif + +#else + +extern "C" +{ + #include "libsha1/libsha1.h" +} + +#endif + +/** + + @param client WSclient_t * ptr to the client struct + @param code uint16_t see RFC + @param reason ptr to the disconnect reason message + @param reasonLen length of the disconnect reason message +*/ +void WebSockets::clientDisconnect(WSclient_t * client, uint16_t code, char * reason, size_t reasonLen) +{ + WSK_LOGDEBUG2(client->num, "[handleWebsocket] clientDisconnect code:", code); + + if (client->status == WSC_CONNECTED && code) + { + if (reason) + { + sendFrame(client, WSop_close, (uint8_t *) reason, reasonLen); + } + else + { + uint8_t buffer[2]; + buffer[0] = ((code >> 8) & 0xFF); + buffer[1] = (code & 0xFF); + sendFrame(client, WSop_close, &buffer[0], 2); + } + } + + clientDisconnect(client); +} + +/** + + @param buf uint8_t * ptr to the buffer for writing + @param opcode WSopcode_t + @param length size_t length of the payload + @param mask bool add dummy mask to the frame (needed for web browser) + @param maskkey uint8_t[4] key used for payload + @param fin bool can be used to send data in more then one frame (set fin on the last frame) +*/ +uint8_t WebSockets::createHeader(uint8_t * headerPtr, WSopcode_t opcode, size_t length, bool mask, + uint8_t maskKey[4], bool fin) +{ + uint8_t headerSize; + + // calculate header Size + if (length < 126) + { + headerSize = 2; + } + else if (length < 0xFFFF) + { + headerSize = 4; + } + else + { + headerSize = 10; + } + + if (mask) + { + headerSize += 4; + } + + // create header + + // byte 0 + *headerPtr = 0x00; + + if (fin) + { + *headerPtr |= bit(7); ///< set Fin + } + + *headerPtr |= opcode; ///< set opcode + headerPtr++; + + // byte 1 + *headerPtr = 0x00; + + if (mask) + { + *headerPtr |= bit(7); ///< set mask + } + + if (length < 126) + { + *headerPtr |= length; + headerPtr++; + } + else if (length < 0xFFFF) + { + *headerPtr |= 126; + headerPtr++; + *headerPtr = ((length >> 8) & 0xFF); + headerPtr++; + *headerPtr = (length & 0xFF); + headerPtr++; + } + else + { + // Normally we never get here (to less memory) + *headerPtr |= 127; + headerPtr++; + *headerPtr = 0x00; + headerPtr++; + *headerPtr = 0x00; + headerPtr++; + *headerPtr = 0x00; + headerPtr++; + *headerPtr = 0x00; + headerPtr++; + *headerPtr = ((length >> 24) & 0xFF); + headerPtr++; + *headerPtr = ((length >> 16) & 0xFF); + headerPtr++; + *headerPtr = ((length >> 8) & 0xFF); + headerPtr++; + *headerPtr = (length & 0xFF); + headerPtr++; + } + + if (mask) + { + *headerPtr = maskKey[0]; + headerPtr++; + *headerPtr = maskKey[1]; + headerPtr++; + *headerPtr = maskKey[2]; + headerPtr++; + *headerPtr = maskKey[3]; + headerPtr++; + } + + return headerSize; +} + +/** + + @param client WSclient_t * ptr to the client struct + @param opcode WSopcode_t + @param length size_t length of the payload + @param fin bool can be used to send data in more then one frame (set fin on the last frame) + @return true if ok +*/ +bool WebSockets::sendFrameHeader(WSclient_t * client, WSopcode_t opcode, size_t length, bool fin) +{ + uint8_t maskKey[4] = { 0x00, 0x00, 0x00, 0x00 }; + uint8_t buffer[WEBSOCKETS_MAX_HEADER_SIZE] = { 0 }; + + uint8_t headerSize = createHeader(&buffer[0], opcode, length, client->cIsClient, maskKey, fin); + + if (write(client, &buffer[0], headerSize) != headerSize) + { + return false; + } + + return true; +} + +/** + + @param client WSclient_t * ptr to the client struct + @param opcode WSopcode_t + @param payload uint8_t * ptr to the payload + @param length size_t length of the payload + @param fin bool can be used to send data in more then one frame (set fin on the last frame) + @param headerToPayload bool set true if the payload has reserved 14 Byte at the beginning to dynamically + add the Header (payload neet to be in RAM!) + @return true if ok +*/ +bool WebSockets::sendFrame(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length, + bool fin, bool headerToPayload) +{ + if (client->tcp && !client->tcp->connected()) + { + WSK_LOGDEBUG1("[sendFrame] Not Connected!? Client:", client->num); + + + return false; + } + + if (client->status != WSC_CONNECTED) + { + WSK_LOGDEBUG1("[sendFrame] not in WSC_CONNECTED state!? Client:", client->num); + + return false; + } + + WSK_LOGDEBUG("[sendFrame] ------- send message frame -------"); + + WSK_LOGDEBUG1("[sendFrame] Client:", client->num); + WSK_LOGDEBUG1("fin:", fin); + WSK_LOGDEBUG1("opCode:", opcode); + WSK_LOGDEBUG1("mask:", client->cIsClient); + WSK_LOGDEBUG1("length:", length); + WSK_LOGDEBUG1("headerToPayload:", headerToPayload); + + if (opcode == WSop_text) + { + WSK_LOGDEBUG3("[sendFrame] Client: ", client->num, ", text:", (char*) (payload + (headerToPayload ? 14 : 0))); + } + + uint8_t maskKey[4] = { 0x00, 0x00, 0x00, 0x00 }; + uint8_t buffer[WEBSOCKETS_MAX_HEADER_SIZE] = { 0 }; + + uint8_t headerSize; + uint8_t * headerPtr; + uint8_t * payloadPtr = payload; + bool useInternBuffer = false; + bool ret = true; + + // calculate header Size + if (length < 126) + { + headerSize = 2; + } + else if (length < 0xFFFF) + { + headerSize = 4; + } + else + { + headerSize = 10; + } + + if (client->cIsClient) + { + headerSize += 4; + } + +#ifdef WEBSOCKETS_USE_BIG_MEM + // only for ESP since AVR has less HEAP + // try to send data in one TCP package (only if some free Heap is there) + if (!headerToPayload && ((length > 0) && (length < 1400)) && (GET_FREE_HEAP > 6000)) + { + WSK_LOGDEBUG1("[sendFrame] pack to one TCP package... Client:", client->num); + + uint8_t * dataPtr = (uint8_t *)malloc(length + WEBSOCKETS_MAX_HEADER_SIZE); + + if (dataPtr) + { + memcpy((dataPtr + WEBSOCKETS_MAX_HEADER_SIZE), payload, length); + headerToPayload = true; + useInternBuffer = true; + payloadPtr = dataPtr; + } + } +#endif + + // set Header Pointer + if (headerToPayload) + { + // calculate offset in payload + headerPtr = (payloadPtr + (WEBSOCKETS_MAX_HEADER_SIZE - headerSize)); + } + else + { + headerPtr = &buffer[0]; + } + + if (client->cIsClient && useInternBuffer) + { + // if we use a Intern Buffer we can modify the data + // by this fact its possible the do the masking + for (uint8_t x = 0; x < sizeof(maskKey); x++) + { + maskKey[x] = random(0xFF); + } + } + + createHeader(headerPtr, opcode, length, client->cIsClient, maskKey, fin); + + if (client->cIsClient && useInternBuffer) + { + uint8_t * dataMaskPtr; + + if (headerToPayload) + { + dataMaskPtr = (payloadPtr + WEBSOCKETS_MAX_HEADER_SIZE); + } + else + { + dataMaskPtr = payloadPtr; + } + + for (size_t x = 0; x < length; x++) + { + dataMaskPtr[x] = (dataMaskPtr[x] ^ maskKey[x % 4]); + } + } + +#ifndef NODEBUG_WEBSOCKETS + unsigned long start = micros(); +#endif + + if (headerToPayload) + { + // header has be added to payload + // payload is forced to reserved 14 Byte but we may not need all based on the length and mask settings + // offset in payload is calculatetd 14 - headerSize + if (write(client, &payloadPtr[(WEBSOCKETS_MAX_HEADER_SIZE - headerSize)], (length + headerSize)) != (length + headerSize)) + { + ret = false; + } + } + else + { + // send header + if (write(client, &buffer[0], headerSize) != headerSize) + { + ret = false; + } + + if (payloadPtr && length > 0) + { + // send payload + if (write(client, &payloadPtr[0], length) != length) + { + ret = false; + } + } + } + +#ifndef NODEBUG_WEBSOCKETS + WSK_LOGDEBUG3("[handleWebsocketWaitFor] Sending Frame Done. Client: ", client->num, ", (us):", (micros() - start)); +#endif + +#ifdef WEBSOCKETS_USE_BIG_MEM + if (useInternBuffer && payloadPtr) + { + free(payloadPtr); + } +#endif + + return ret; +} + +/** + callen when HTTP header is done + @param client WSclient_t * ptr to the client struct +*/ +void WebSockets::headerDone(WSclient_t * client) +{ + client->status = WSC_CONNECTED; + client->cWsRXsize = 0; + + WSK_LOGDEBUG1("[headerDone] Header Handling Done. Client:", client->num); + +#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) + client->cHttpLine = ""; + handleWebsocket(client); +#endif +} + +/** + handle the WebSocket stream + @param client WSclient_t * ptr to the client struct +*/ +void WebSockets::handleWebsocket(WSclient_t * client) +{ + if (client->cWsRXsize == 0) + { + handleWebsocketCb(client); + } +} + +/** + wait for + @param client + @param size +*/ +bool WebSockets::handleWebsocketWaitFor(WSclient_t * client, size_t size) +{ + if (!client->tcp || !client->tcp->connected()) + { + return false; + } + + if (size > WEBSOCKETS_MAX_HEADER_SIZE) + { + WSK_LOGDEBUG3("[handleWebsocketWaitFor] Client: ", client->num, ", size too big:", size); + + return false; + } + + if (client->cWsRXsize >= size) + { + return true; + } + + WSK_LOGDEBUG3("[handleWebsocketWaitFor] Client: ", client->num, ", size:", size); + WSK_LOGDEBUG1("cWsRXsize:", client->cWsRXsize); + + + readCb(client, &client->cWsHeader[client->cWsRXsize], (size - client->cWsRXsize), + std::bind([](WebSockets * server, size_t size, WSclient_t * client, bool ok) + { + WSK_LOGDEBUG3("[handleWebsocketWaitFor][readCb] Client: ", client->num, ", size:", size); + WSK_LOGDEBUG1("ok:", ok); + + if (ok) + { + client->cWsRXsize = size; + server->handleWebsocketCb(client); + } + else + { + WSK_LOGDEBUG1("[readCb] failed. Client:", client->num); + + client->cWsRXsize = 0; + // timeout or error + server->clientDisconnect(client, 1002); + } + }, + this, size, std::placeholders::_1, std::placeholders::_2)); + return false; +} + +void WebSockets::handleWebsocketCb(WSclient_t * client) +{ + if (!client->tcp || !client->tcp->connected()) + { + return; + } + + uint8_t * buffer = client->cWsHeader; + + WSMessageHeader_t * header = &client->cWsHeaderDecode; + uint8_t * payload = NULL; + + uint8_t headerLen = 2; + + if (!handleWebsocketWaitFor(client, headerLen)) + { + return; + } + + // split first 2 bytes in the data + header->fin = ((*buffer >> 7) & 0x01); + header->rsv1 = ((*buffer >> 6) & 0x01); + header->rsv2 = ((*buffer >> 5) & 0x01); + header->rsv3 = ((*buffer >> 4) & 0x01); + header->opCode = (WSopcode_t)(*buffer & 0x0F); + buffer++; + + header->mask = ((*buffer >> 7) & 0x01); + header->payloadLen = (WSopcode_t)(*buffer & 0x7F); + buffer++; + + if (header->payloadLen == 126) + { + headerLen += 2; + + if (!handleWebsocketWaitFor(client, headerLen)) + { + return; + } + + header->payloadLen = buffer[0] << 8 | buffer[1]; + buffer += 2; + } + else if (header->payloadLen == 127) + { + headerLen += 8; + + // read 64bit integer as length + if (!handleWebsocketWaitFor(client, headerLen)) + { + return; + } + + if (buffer[0] != 0 || buffer[1] != 0 || buffer[2] != 0 || buffer[3] != 0) + { + // really too big! + header->payloadLen = 0xFFFFFFFF; + } + else + { + header->payloadLen = buffer[4] << 24 | buffer[5] << 16 | buffer[6] << 8 | buffer[7]; + } + + buffer += 8; + } + + WSK_LOGDEBUG1("[handleWebsocket] ------- read massage frame ------- Client:", client->num); + + WSK_LOGDEBUG3("[handleWebsocket] Client: ", client->num, ", fin:", header->fin); + WSK_LOGDEBUG1("rsv1:", header->rsv1); + WSK_LOGDEBUG1("rsv2:", header->rsv2); + WSK_LOGDEBUG1("rsv3:", header->rsv3); + WSK_LOGDEBUG1("opCode:", header->opCode); + + WSK_LOGDEBUG3("[handleWebsocket] Client: ", client->num, ", mask:", header->mask); + WSK_LOGDEBUG1("payloadLen:", header->payloadLen); + + + if (header->payloadLen > WEBSOCKETS_MAX_DATA_SIZE) + { + WSK_LOGDEBUG3("[handleWebsocket] Client: ", client->num, ", payload too big:", header->payloadLen); + + clientDisconnect(client, 1009); + return; + } + + if (header->mask) + { + headerLen += 4; + if (!handleWebsocketWaitFor(client, headerLen)) + { + return; + } + + header->maskKey = buffer; + buffer += 4; + } + + if (header->payloadLen > 0) + { + // if text data we need one more + payload = (uint8_t *) malloc(header->payloadLen + 1); + + if (!payload) + { + WSK_LOGDEBUG3("[handleWebsocket] Client: ", client->num, ", No memory to handle payload", header->payloadLen); + + clientDisconnect(client, 1011); + return; + } + + readCb(client, payload, header->payloadLen, std::bind(&WebSockets::handleWebsocketPayloadCb, + this, std::placeholders::_1, std::placeholders::_2, payload)); + } + else + { + handleWebsocketPayloadCb(client, true, NULL); + } +} + +void WebSockets::handleWebsocketPayloadCb(WSclient_t * client, bool ok, uint8_t * payload) +{ + WSMessageHeader_t * header = &client->cWsHeaderDecode; + + if (ok) + { + if (header->payloadLen > 0) + { + payload[header->payloadLen] = 0x00; + + if (header->mask) + { + //decode XOR + for (size_t i = 0; i < header->payloadLen; i++) + { + payload[i] = (payload[i] ^ header->maskKey[i % 4]); + } + } + } + + switch (header->opCode) + { + case WSop_text: + WSK_LOGDEBUG3("[handleWebsocketPayloadCb] Client: ", client->num, ", text:", (char *) payload); + messageReceived(client, header->opCode, payload, header->payloadLen, header->fin); + break; + + case WSop_binary: + case WSop_continuation: + messageReceived(client, header->opCode, payload, header->payloadLen, header->fin); + break; + + case WSop_ping: + // send pong back + WSK_LOGDEBUG3("[handleWebsocketPayloadCb] Client: ", client->num, + ", ping received", payload ? (const char *)payload : ""); + + sendFrame(client, WSop_pong, payload, header->payloadLen); + messageReceived(client, header->opCode, payload, header->payloadLen, header->fin); + break; + + case WSop_pong: + WSK_LOGDEBUG3("[handleWebsocketPayloadCb] Client: ", client->num, + ", get pong", payload ? (const char *)payload : ""); + + client->pongReceived = true; + messageReceived(client, header->opCode, payload, header->payloadLen, header->fin); + break; + + case WSop_close: + { + uint16_t reasonCode = 1000; + + if (header->payloadLen >= 2) + { + reasonCode = payload[0] << 8 | payload[1]; + } + + WSK_LOGDEBUG3("[handleWebsocketPayloadCb] Get ask for close. Client Num:", client->num, ", Code:", reasonCode); + + if (header->payloadLen > 2) + { + WSK_LOGDEBUG1("Payload =", (char *) (payload + 2)); + } + + clientDisconnect(client, 1000); + } + break; + + default: + WSK_LOGDEBUG3("[WS][handleWebsocket] Got unknown opcode: Client =", client->num, ", opcode =", header->opCode); + clientDisconnect(client, 1002); + break; + } + + if (payload) + { + free(payload); + } + + // reset input + client->cWsRXsize = 0; +#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) + //register callback for next message + handleWebsocketWaitFor(client, 2); +#endif + + } + else + { + WSK_LOGDEBUG1("[handleWebsocket] Missing data!. Client:", client->num); + + free(payload); + clientDisconnect(client, 1002); + } +} + +/** + generate the key for Sec-WebSocket-Accept + @param clientKey String + @return String Accept Key +*/ +String WebSockets::acceptKey(String & clientKey) +{ + uint8_t sha1HashBin[20] = { 0 }; + +#ifdef ESP8266 + sha1(clientKey + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11", &sha1HashBin[0]); +#elif defined(ESP32) + String data = clientKey + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; + esp_sha(SHA1, (unsigned char *)data.c_str(), data.length(), &sha1HashBin[0]); +#else + clientKey += "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; + SHA1_CTX ctx; + SHA1Init(&ctx); + SHA1Update(&ctx, (const unsigned char *)clientKey.c_str(), clientKey.length()); + SHA1Final(&sha1HashBin[0], &ctx); +#endif + + String key = base64_encode(sha1HashBin, 20); + key.trim(); + + return key; +} + + +/** + base64_encode + @param data uint8_t + @param length size_t + @return base64 encoded String +*/ +String WebSockets::base64_encode(uint8_t * data, size_t length) +{ + size_t size = ((length * 1.6f) + 1); + char * buffer = (char *) malloc(size); + + //WSK_LOGDEBUG3("[base64_encode] length:", length, ", size:", size); + + if (buffer) + { + base64_encodestate _state; + + base64_init_encodestate(&_state); + + int len = base64_encode_block((const char *)&data[0], length, &buffer[0], &_state); + + //WSK_LOGDEBUG1("[base64_encode] #1 len:", len); + + len = base64_encode_blockend((buffer + len), &_state); + //WSK_LOGDEBUG1("[base64_encode] #2 len:", len); + + String base64 = String(buffer); + + //WSK_LOGDEBUG3("[base64_encode] base64:", base64, ", buffer:", buffer); + + free(buffer); + return base64; + } + + return String("-FAIL-"); +} + +/** + read x byte from tcp or get timeout + @param client WSclient_t + @param out uint8_t * data buffer + @param n size_t byte count + @return true if ok +*/ +bool WebSockets::readCb(WSclient_t * client, uint8_t * out, size_t n, WSreadWaitCb cb) +{ +#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) + if (!client->tcp || !client->tcp->connected()) + { + return false; + } + + client->tcp->readBytes(out, n, std::bind([](WSclient_t * client, bool ok, WSreadWaitCb cb) + { + if (cb) + { + cb(client, ok); + } + }, client, std::placeholders::_1, cb)); + +#else + unsigned long t = millis(); + ssize_t len; + + WSK_LOGDEBUG3("[readCb] n:", n, ", t:", t); + + while (n > 0) + { + if (client->tcp == NULL) + { + WSK_LOGDEBUG("[readCb] Null tcp!"); + + if (cb) + { + cb(client, false); + } + + return false; + } + + if (!client->tcp->connected()) + { + WSK_LOGDEBUG("[readCb] Not connected!"); + + if (cb) + { + cb(client, false); + } + + return false; + } + + if ((millis() - t) > WEBSOCKETS_TCP_TIMEOUT) + { + WSK_LOGDEBUG1("[readCb] TIMEOUT (ms):", (millis() - t)); + + if (cb) + { + cb(client, false); + } + + return false; + } + + if (!client->tcp->available()) + { + WEBSOCKETS_YIELD_MORE(); + continue; + } + + len = client->tcp->read((uint8_t *)out, n); + + if (len > 0) + { + t = millis(); + out += len; + n -= len; + } + + WSK_LOGDEBUG3("[readCb] Receive Length =", len, ", left =", n); + + if (n > 0) + { + WEBSOCKETS_YIELD(); + } + } + + if (cb) + { + cb(client, true); + } + + WEBSOCKETS_YIELD(); +#endif + + return true; +} + +/** + write x byte to tcp or get timeout + @param client WSclient_t + @param out uint8_t * data buffer + @param n size_t byte count + @return bytes send +*/ +size_t WebSockets::write(WSclient_t * client, uint8_t * out, size_t n) +{ + if (out == NULL) + return 0; + + if (client == NULL) + return 0; + + unsigned long t = millis(); + size_t len = 0; + size_t total = 0; + + WSK_LOGDEBUG3("[write] n:", n, ", t:", t); + + while (n > 0) + { + if (client->tcp == NULL) + { + WSK_LOGDEBUG("[write] Null tcp!"); + break; + } + + if (!client->tcp->connected()) + { + WSK_LOGDEBUG("[write] Not connected!"); + break; + } + + if ((millis() - t) > WEBSOCKETS_TCP_TIMEOUT) + { + WSK_LOGDEBUG1("[write] TIMEOUT (ms):", (millis() - t)); + break; + } + + len = client->tcp->write((const uint8_t *)out, n); + + if (len) + { + t = millis(); + out += len; + n -= len; + total += len; + + WSK_LOGDEBUG3("[write] Write, Length :", len, ", Left :", n); + } + else + { + WSK_LOGDEBUG3("[write] Failed Write, Length :", len, ", Left :", n); + } + + if (n > 0) + { + WEBSOCKETS_YIELD(); + } + } + + WEBSOCKETS_YIELD(); + + return total; +} + +size_t WebSockets::write(WSclient_t * client, const char * out) +{ + if (client == NULL) + return 0; + + if (out == NULL) + return 0; + + return write(client, (uint8_t *)out, strlen(out)); +} + +/** + enable ping/pong heartbeat process + @param client WSclient_t + @param pingInterval uint32_t how often ping will be sent + @param pongTimeout uint32_t millis after which pong should timout if not received + @param disconnectTimeoutCount uint8_t how many timeouts before disconnect, 0=> do not disconnect +*/ +void WebSockets::enableHeartbeat(WSclient_t * client, const uint32_t& pingInterval, const uint32_t& pongTimeout, + const uint8_t& disconnectTimeoutCount) +{ + if (client == NULL) + return; + + client->pingInterval = pingInterval; + client->pongTimeout = pongTimeout; + client->disconnectTimeoutCount = disconnectTimeoutCount; + client->pongReceived = false; +} + +/** + handle ping/pong heartbeat timeout process + @param client WSclient_t +*/ +void WebSockets::handleHBTimeout(WSclient_t * client) +{ + if (client->pingInterval) + { + // if heartbeat is enabled + uint32_t pi = millis() - client->lastPing; + + if (client->pongReceived) + { + client->pongTimeoutCount = 0; + } + else + { + if (pi > client->pongTimeout) + { + // pong not received in time + client->pongTimeoutCount++; + client->lastPing = millis() - client->pingInterval - 500; // force ping on the next run + + WSK_LOGDEBUG3("[HBtimeout] pong TIMEOUT! lp=", client->lastPing, ", millis=", millis()); + WSK_LOGDEBUG3("[HBtimeout] pong TIMEOUT! pi=", pi, ", count=", client->pongTimeoutCount); + + if (client->disconnectTimeoutCount && client->pongTimeoutCount >= client->disconnectTimeoutCount) + { + WSK_LOGDEBUG1("[HBtimeout] DISCONNECTING, count=", client->pongTimeoutCount); + + clientDisconnect(client); + } + } + } + } +} + +#endif // WEBSOCKETS_GENERIC_IMPL_H_ diff --git a/src/src/WebSockets_Generic.h b/src/src/WebSockets_Generic.h new file mode 100644 index 00000000..100bec6b --- /dev/null +++ b/src/src/WebSockets_Generic.h @@ -0,0 +1,915 @@ +/**************************************************************************************************************************** + WebSockets_Generic.h - WebSockets Library for boards + + Based on and modified from WebSockets libarary https://github.com/Links2004/arduinoWebSockets + to support other boards such as SAMD21, SAMD51, Adafruit's nRF52 boards, etc. + + Built by Khoi Hoang https://github.com/khoih-prog/WebSockets_Generic + Licensed under MIT license + + @original file WebSockets.h + @date 20.05.2015 + @author Markus Sattler + + Copyright (c) 2015 Markus Sattler. All rights reserved. + This file is part of the WebSockets for Arduino. + + 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 St, Fifth Floor, Boston, MA 02110-1301 USA + + Version: 2.14.0 + + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 2.1.3 K Hoang 15/05/2020 Initial porting to support SAMD21, SAMD51, nRF52 boards, such as AdaFruit Feather nRF52832, + nRF52840 Express, BlueFruit Sense, Itsy-Bitsy nRF52840 Express, Metro nRF52840 Express, etc. + 2.2.1 K Hoang 18/05/2020 Bump up to sync with v2.2.1 of original WebSockets library + 2.2.2 K Hoang 25/05/2020 Add support to Teensy, SAM DUE and STM32. Enable WebSocket Server for new supported boards. + 2.2.3 K Hoang 02/08/2020 Add support to W5x00's Ethernet2, Ethernet3, EthernetLarge Libraries. + Add support to STM32F/L/H/G/WB/MP1 and Seeeduino SAMD21/SAMD51 boards. + 2.3.1 K Hoang 07/10/2020 Sync with v2.3.1 of original WebSockets library. Add ENC28J60 EthernetENC library support + 2.3.2 K Hoang 12/11/2020 Add RTL8720DN Seeed_Arduino_rpcWiFi library support + 2.3.3 K Hoang 28/11/2020 Fix compile error for WIO_TERMINAL and boards using libraries with lib64. + 2.3.4 K Hoang 12/12/2020 Add SSL support to SAMD21 Nano-33-IoT using WiFiNINA. Upgrade WS and WSS examples. + 2.4.0 K Hoang 06/02/2021 Add support to Teensy 4.1 NativeEthernet and STM32 built-in LAN8742A. + Sync with v2.3.4 of original WebSockets library + 2.4.1 K Hoang 19/03/2021 Sync with v2.3.5 of original WebSockets library to adapt to ESP32 SSL changes + 2.5.0 K Hoang 22/05/2021 Add support to WiFi101 + 2.5.1 K Hoang 22/05/2021 Default to EIO4 for Socket.IO. Permit increase reconnectInterval in Socket.IO + 2.6.0 K Hoang 23/05/2021 Fix breaking problem with SocketIO. Add setExtraHeaders to SocketIO + 2.7.0 K Hoang 24/05/2021 Add support to RP2040-based boards using Arduino-pico and Arduino mbed_rp2040 core + 2.8.0 K Hoang 08/07/2021 Add support to WT32_ETH01 (ESP32 + LAN8720) boards + 2.9.0 K Hoang 05/09/2021 Add support to QNEthernet Library for Teensy 4.1 + 2.10.0 K Hoang 18/09/2021 Add support to Portenta_H7, using either WiFi or Vision-shield Ethernet + 2.10.1 K Hoang 12/10/2021 Update `platform.ini` and `library.json` + 2.11.0 K Hoang 30/11/2021 Auto detect ESP32 core version. Fix bug in examples + 2.11.1 K Hoang 12/12/2021 Add option to use transport=websocket with sticky-session SIO server + 2.12.0 K Hoang 28/01/2022 Supporting SSL for ESP32-based WT32_ETH01 boards + 2.13.0 K Hoang 14/02/2022 Add support to ESP32_S3. Add PING and PONG SocketIO events + 2.14.0 K Hoang 17/02/2022 Suppress unnecessary warnings. Optimize code by passing by reference instead of value + *****************************************************************************************************************************/ + +#pragma once + +#ifndef WEBSOCKETS_GENERIC_H_ +#define WEBSOCKETS_GENERIC_H_ + +#define WEBSOCKETS_GENERIC_VERSION "WebSockets_Generic v2.14.0" + +#define WEBSOCKETS_GENERIC_VERSION_MAJOR 2 +#define WEBSOCKETS_GENERIC_VERSION_MINOR 14 +#define WEBSOCKETS_GENERIC_VERSION_PATCH 0 + +#define WEBSOCKETS_GENERIC_VERSION_INT 2014000 + +#include "WebSocketsDebug_Generic.h" + +#ifdef STM32_DEVICE + #include + #define bit(b) (1UL << (b)) // Taken directly from Arduino.h +#else + #include + #include +#endif + +#ifdef ARDUINO_ARCH_AVR + #error Version 2.x.x currently does not support Arduino with AVR since there is no support for std namespace of c++. + #error Use Version 1.x.x. (ATmega branch) +#else + #ifdef max + // KH + #if(_WEBSOCKETS_LOGLEVEL_>3) + #warning Undef min/max in WebSockets_Generic + #endif + #undef max + #endif + #ifdef min + #undef min + #endif + + #include +#endif + +#if defined(TEENSYDUINO) + namespace std + { + //To avoid Teensy linker issue wth STL library + unsigned __exidx_start; + unsigned __exidx_end; + + // This is defined so that calling a std::function can compile when + // size optimization is enabled. + __attribute__((weak)) + void __throw_bad_function_call() + { + Serial.println("Library Exception"); + while (true) yield(); + } + } +#endif + +#ifndef NODEBUG_WEBSOCKETS + #ifdef DEBUG_ESP_PORT + #define DEBUG_WEBSOCKETS(...) \ + { \ + DEBUG_ESP_PORT.printf(__VA_ARGS__); \ + DEBUG_ESP_PORT.flush(); \ + } + #else + //#define DEBUG_WEBSOCKETS(...) os_printf( __VA_ARGS__ ) + #endif +#endif + +#ifndef DEBUG_WEBSOCKETS + #define DEBUG_WEBSOCKETS(...) + #ifndef NODEBUG_WEBSOCKETS + #define NODEBUG_WEBSOCKETS + #endif +#endif + +////////////////////////////////////////////////////////////// + +#if defined(ESP8266) || defined(ESP32) + + #define WEBSOCKETS_MAX_DATA_SIZE (15 * 1024) + #define WEBSOCKETS_USE_BIG_MEM + #define GET_FREE_HEAP ESP.getFreeHeap() + // moves all Header strings to Flash (~300 Byte) + //#define WEBSOCKETS_SAVE_RAM + + #if defined(ESP8266) + #if(_WEBSOCKETS_LOGLEVEL_>3) + #warning Use ESP8266 in WebSockets_Generic + #endif + + #define WEBSOCKETS_YIELD() delay(0) + #define WEBSOCKETS_YIELD_MORE() delay(1) + #elif defined(ESP32) + + #if(_WEBSOCKETS_LOGLEVEL_>3) + #warning Use ESP32 in WebSockets_Generic + #endif + + #define WEBSOCKETS_YIELD() yield() + #define WEBSOCKETS_YIELD_MORE() delay(1) + #endif + +#elif ( defined(STM32F0) || defined(STM32F1) || defined(STM32F2) || defined(STM32F3) ||defined(STM32F4) || defined(STM32F7) || \ + defined(STM32L0) || defined(STM32L1) || defined(STM32L4) || defined(STM32H7) ||defined(STM32G0) || defined(STM32G4) || \ + defined(STM32WB) || defined(STM32MP1) ) + // KH + #if(_WEBSOCKETS_LOGLEVEL_>3) + #warning Use STM32F/L/H/G/WB/MP1 in WebSockets_Generic + #endif + + #define WEBSOCKETS_MAX_DATA_SIZE (15 * 1024) + + // moves all Header strings to Flash (~300 Byte) + //#define WEBSOCKETS_USE_BIG_MEM + #define WEBSOCKETS_SAVE_RAM + //#define GET_FREE_HEAP System.freeMemory() + #define WEBSOCKETS_YIELD() + #define WEBSOCKETS_YIELD_MORE() + +#elif defined(STM32_DEVICE) + + #if(_WEBSOCKETS_LOGLEVEL_>3) + #warning Use STM32_DEVICE in WebSockets_Generic + #endif + + #define WEBSOCKETS_MAX_DATA_SIZE (15 * 1024) + #define WEBSOCKETS_USE_BIG_MEM + #define GET_FREE_HEAP System.freeMemory() + #define WEBSOCKETS_YIELD() + #define WEBSOCKETS_YIELD_MORE() + +#elif ( defined(NRF52840_FEATHER) || defined(NRF52832_FEATHER) || defined(NRF52_SERIES) || defined(ARDUINO_NRF52_ADAFRUIT) || \ + defined(NRF52840_FEATHER_SENSE) || defined(NRF52840_ITSYBITSY) || defined(NRF52840_CIRCUITPLAY) || defined(NRF52840_CLUE) || \ + defined(NRF52840_METRO) || defined(NRF52840_PCA10056) || defined(PARTICLE_XENON) || defined(NINA_B302_ublox) || defined(NINA_B112_ublox) ) + // KH + #if(_WEBSOCKETS_LOGLEVEL_>3) + #warning Use nRF52 in WebSockets_Generic + #endif + + #define WEBSOCKETS_MAX_DATA_SIZE (15 * 1024) + + // Try to use GET_FREE_HEAP and large mem + // only for ESP since AVR has less HEAP + // try to send data in one TCP package (only if some free Heap is there) + //#define WEBSOCKETS_USE_BIG_MEM + + // moves all Header strings to Flash (~300 Byte) + #define WEBSOCKETS_SAVE_RAM + + #define WEBSOCKETS_YIELD() yield() + #define WEBSOCKETS_YIELD_MORE() delay(1) + +#elif ( defined(ARDUINO_SAMD_ZERO) || defined(ARDUINO_SAMD_MKR1000) || defined(ARDUINO_SAMD_MKRWIFI1010) \ + || defined(ARDUINO_SAMD_NANO_33_IOT) || defined(ARDUINO_SAMD_MKRFox1200) || defined(ARDUINO_SAMD_MKRWAN1300) || defined(ARDUINO_SAMD_MKRWAN1310) \ + || defined(ARDUINO_SAMD_MKRGSM1400) || defined(ARDUINO_SAMD_MKRNB1500) || defined(ARDUINO_SAMD_MKRVIDOR4000) || defined(__SAMD21G18A__) \ + || defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) || defined(__SAMD21E18A__) || defined(__SAMD51__) || defined(__SAMD51J20A__) || defined(__SAMD51J19A__) \ + || defined(__SAMD51G19A__) || defined(__SAMD51P19A__) || defined(__SAMD21G18A__) ) + + // KH + #if(_WEBSOCKETS_LOGLEVEL_>3) + #warning Use SAMD21/SAMD51 in WebSockets_Generic + #endif + + #define WEBSOCKETS_MAX_DATA_SIZE (15 * 1024) + + // Try to use GET_FREE_HEAP and large mem + // only for ESP since AVR has less HEAP + // try to send data in one TCP package (only if some free Heap is there) + #if defined(SEEED_WIO_TERMINAL) + //#define WEBSOCKETS_USE_BIG_MEM + //#define GET_FREE_HEAP 10000 + #endif + // moves all Header strings to Flash (~300 Byte) + #define WEBSOCKETS_SAVE_RAM + + #define WEBSOCKETS_YIELD() yield() + #define WEBSOCKETS_YIELD_MORE() delay(1) + +#elif ( defined(ARDUINO_SAM_DUE) || defined(__SAM3X8E__) ) + + // KH + #if(_WEBSOCKETS_LOGLEVEL_>3) + #warning Use SAM DUE in WebSockets_Generic + #endif + + #define WEBSOCKETS_MAX_DATA_SIZE (15 * 1024) + + // Try to use GET_FREE_HEAP and large mem + // only for ESP since AVR has less HEAP + // try to send data in one TCP package (only if some free Heap is there) + //#define WEBSOCKETS_USE_BIG_MEM + + // moves all Header strings to Flash (~300 Byte) + #define WEBSOCKETS_SAVE_RAM + + #define WEBSOCKETS_YIELD() yield() + #define WEBSOCKETS_YIELD_MORE() delay(1) + +#elif defined(TEENSYDUINO) + + // KH + #if(_WEBSOCKETS_LOGLEVEL_>3) + #warning Use Teensy in WebSockets_Generic + #endif + + #define WEBSOCKETS_MAX_DATA_SIZE (15 * 1024) + + // Try to use GET_FREE_HEAP and large mem + // only for ESP since AVR has less HEAP + // try to send data in one TCP package (only if some free Heap is there) + //#define WEBSOCKETS_USE_BIG_MEM + + // moves all Header strings to Flash (~300 Byte) + #define WEBSOCKETS_SAVE_RAM + + #define WEBSOCKETS_YIELD() yield() + #define WEBSOCKETS_YIELD_MORE() delay(1) + + +#elif ( defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_RASPBERRY_PI_PICO) || defined(ARDUINO_ADAFRUIT_FEATHER_RP2040) || defined(ARDUINO_GENERIC_RP2040) ) + + // KH + #if(_WEBSOCKETS_LOGLEVEL_>3) + #warning Use RP2040 in WebSockets_Generic + #endif + + #define WEBSOCKETS_MAX_DATA_SIZE (15 * 1024) + + // Try to use GET_FREE_HEAP and large mem + // try to send data in one TCP package (only if some free Heap is there) + // moves all Header strings to Flash (~300 Byte) + #define WEBSOCKETS_SAVE_RAM + + #define WEBSOCKETS_YIELD() yield() + #define WEBSOCKETS_YIELD_MORE() delay(1) + +#elif ( ( defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) ) && defined(ARDUINO_ARCH_MBED) ) + + // KH + #if(_WEBSOCKETS_LOGLEVEL_>3) + #warning Use Portenta_H7 in WebSockets_Generic + #endif + + #define WEBSOCKETS_MAX_DATA_SIZE (15 * 1024) + + // Try to use GET_FREE_HEAP and large mem + // try to send data in one TCP package (only if some free Heap is there) + // moves all Header strings to Flash (~300 Byte) + #define WEBSOCKETS_SAVE_RAM + + #define WEBSOCKETS_YIELD() yield() + #define WEBSOCKETS_YIELD_MORE() delay(1) + +#else + + #if(_WEBSOCKETS_LOGLEVEL_>3) + #warning Use atmega328p in WebSockets_Generic + #endif + + //atmega328p has only 2KB ram! + #define WEBSOCKETS_MAX_DATA_SIZE (1024) + // moves all Header strings to Flash + #define WEBSOCKETS_SAVE_RAM + + #define WEBSOCKETS_YIELD() + #define WEBSOCKETS_YIELD_MORE() + +#endif + +////////////////////////////////////////////////////////////// + +#define WEBSOCKETS_TCP_TIMEOUT (5000) + +#define NETWORK_ESP8266_ASYNC (0) +#define NETWORK_ESP8266 (1) +#define NETWORK_W5100 (2) +#define NETWORK_ENC28J60 (3) +#define NETWORK_ESP32 (4) +#define NETWORK_ESP32_ETH (5) +//KH +#define NETWORK_WIFININA (6) +#define NETWORK_ETHERNET_ENC (7) +#define NETWORK_RTL8720DN (8) +#define NETWORK_NATIVEETHERNET (9) +#define NETWORK_LAN8742A (10) +#define NETWORK_WIFI101 (11) +#define NETWORK_QN_ETHERNET (12) +#define NETWORK_PORTENTA_H7_WIFI (13) +#define NETWORK_PORTENTA_H7_ETHERNET (14) + +//////////////////////////////// + +// max size of the WS Message Header +#define WEBSOCKETS_MAX_HEADER_SIZE (14) + +////////////////////////////////////////////////////////////// + +#ifndef WEBSOCKETS_NETWORK_TYPE + // select Network type based + #if defined(ESP8266) || defined(ESP31B) + //KH + #if(_WEBSOCKETS_LOGLEVEL_>2) + #warning WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266 + #endif + + #define WEBSOCKETS_NETWORK_TYPE NETWORK_ESP8266 + //#define WEBSOCKETS_NETWORK_TYPE NETWORK_ESP8266_ASYNC + //#define WEBSOCKETS_NETWORK_TYPE NETWORK_W5100 + + #elif defined(ESP32) + //KH + #if(_WEBSOCKETS_LOGLEVEL_>2) + #warning WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32 + #endif + + #define WEBSOCKETS_NETWORK_TYPE NETWORK_ESP32 + //#define WEBSOCKETS_NETWORK_TYPE NETWORK_ESP32_ETH + + #elif ( defined(NRF52840_FEATHER) || defined(NRF52832_FEATHER) || defined(NRF52_SERIES) || defined(ARDUINO_NRF52_ADAFRUIT) || \ + defined(NRF52840_FEATHER_SENSE) || defined(NRF52840_ITSYBITSY) || defined(NRF52840_CIRCUITPLAY) || defined(NRF52840_CLUE) || \ + defined(NRF52840_METRO) || defined(NRF52840_PCA10056) || defined(PARTICLE_XENON) || defined(NINA_B302_ublox) || defined(NINA_B112_ublox) ) + //KH + #if(_WEBSOCKETS_LOGLEVEL_>2) + #warning WEBSOCKETS_NETWORK_TYPE == NETWORK_WIFININA + #endif + + #define WEBSOCKETS_NETWORK_TYPE NETWORK_WIFININA + + #elif ( defined(ARDUINO_SAMD_ZERO) || defined(ARDUINO_SAMD_MKR1000) || defined(ARDUINO_SAMD_MKRWIFI1010) \ + || defined(ARDUINO_SAMD_NANO_33_IOT) || defined(ARDUINO_SAMD_MKRFox1200) || defined(ARDUINO_SAMD_MKRWAN1300) || defined(ARDUINO_SAMD_MKRWAN1310) \ + || defined(ARDUINO_SAMD_MKRGSM1400) || defined(ARDUINO_SAMD_MKRNB1500) || defined(ARDUINO_SAMD_MKRVIDOR4000) || defined(__SAMD21G18A__) \ + || defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) || defined(__SAMD21E18A__) || defined(__SAMD51__) || defined(__SAMD51J20A__) || defined(__SAMD51J19A__) \ + || defined(__SAMD51G19A__) || defined(__SAMD51P19A__) || defined(__SAMD21G18A__) ) + + + #if defined(ARDUINO_SAMD_MKR1000) || defined(ARDUINO_SAMD_MKRWIFI1010) + //KH + #if(_WEBSOCKETS_LOGLEVEL_>2) + #warning WEBSOCKETS_NETWORK_TYPE == NETWORK_WIFI101 + #endif + + #define WEBSOCKETS_NETWORK_TYPE NETWORK_WIFI101 + #elif defined(SEEED_WIO_TERMINAL) + //KH, from v2.3.2 + #if(_WEBSOCKETS_LOGLEVEL_>2) + #warning WEBSOCKETS_NETWORK_TYPE == NETWORK_RTL8720DN + #endif + + #define WEBSOCKETS_NETWORK_TYPE NETWORK_RTL8720DN + #else + //KH + #if(_WEBSOCKETS_LOGLEVEL_>2) + #warning WEBSOCKETS_NETWORK_TYPE == NETWORK_WIFININA + #endif + + #define WEBSOCKETS_NETWORK_TYPE NETWORK_WIFININA + #endif + + #else + //KH + #if(_WEBSOCKETS_LOGLEVEL_>2) + #warning WEBSOCKETS_NETWORK_TYPE == NETWORK_W5100 + #endif + + #define WEBSOCKETS_NETWORK_TYPE NETWORK_W5100 + + #endif //#if defined(ESP8266) || defined(ESP31B) + +#endif //#ifndef WEBSOCKETS_NETWORK_TYPE + +////////////////////////////////////////////////////////////// + +// Includes and defined based on Network Type +#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) + + // Note: + // No SSL/WSS support for client in Async mode + // TLS lib need a sync interface! + + #if defined(ESP8266) + #include + #elif defined(ESP32) + #include + #include + + // From v2.3.1 + #define SSL_AXTLS + ////// + + #elif defined(ESP31B) + #include + #else + #error "network type ESP8266 ASYNC only possible on the ESP mcu!" + #endif + + #include + #include + #define WEBSOCKETS_NETWORK_CLASS AsyncTCPbuffer + #define WEBSOCKETS_NETWORK_SERVER_CLASS AsyncServer + +//////////////////////////////////////////////////////////////// +#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) + + #if !defined(ESP8266) && !defined(ESP31B) + #error "network type ESP8266 only possible on the ESP mcu!" + #endif + + #ifdef ESP8266 + #include + + // From v2.3.1 + #if defined(wificlientbearssl_h) && !defined(USING_AXTLS) && !defined(wificlientsecure_h) + #define SSL_BARESSL + #define SSL_BEARSSL + #else + #define SSL_AXTLS + #endif + ////// + + #else + #include + #endif + + #define WEBSOCKETS_NETWORK_CLASS WiFiClient + #define WEBSOCKETS_NETWORK_SSL_CLASS WiFiClientSecure + #define WEBSOCKETS_NETWORK_SERVER_CLASS WiFiServer + +//////////////////////////////////////////////////////////////// +#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_W5100) + + #ifdef STM32_DEVICE + #define WEBSOCKETS_NETWORK_CLASS TCPClient + #define WEBSOCKETS_NETWORK_SERVER_CLASS TCPServer + #else + #include + // KH, New v2.2.3 to support Ethernet2, Ethernet3, EthernetLarge Lib + #if USE_ETHERNET //(WEBSOCKETS_NETWORK_LIB == _ETHERNET_) + #include + + #if(_WEBSOCKETS_LOGLEVEL_>3) + #warning Using Ethernet W5x00 Library + #endif + #elif USE_ETHERNET_LARGE //(WEBSOCKETS_NETWORK_LIB == _ETHERNET_LARGE_) + #include + + #if(_WEBSOCKETS_LOGLEVEL_>3) + #warning Using EthernetLarge W5x00 Library + #endif + + #elif USE_ETHERNET2 //(WEBSOCKETS_NETWORK_LIB == _ETHERNET2_) + #include + + #if(_WEBSOCKETS_LOGLEVEL_>3) + #warning Using Ethernet2 W5x00 Library + #endif + #elif USE_ETHERNET3 //(WEBSOCKETS_NETWORK_LIB == _ETHERNET3_) + #include + + #if(_WEBSOCKETS_LOGLEVEL_>3) + #warning Using Ethernet3 W5x00 Library + #endif + #else + #include + + #if(_WEBSOCKETS_LOGLEVEL_>3) + #warning Using default Ethernet W5x00 Library + #endif + #endif + ////// + + #define WEBSOCKETS_NETWORK_CLASS EthernetClient + #define WEBSOCKETS_NETWORK_SERVER_CLASS EthernetServer + + // KH, test SSL + //#define WEBSOCKETS_NETWORK_SSL_CLASS EthernetSSLClient + + #endif + +//////////////////////////////////////////////////////////////// +#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_ENC28J60) + + #include + #define WEBSOCKETS_NETWORK_CLASS UIPClient + #define WEBSOCKETS_NETWORK_SERVER_CLASS UIPServer + +//////////////////////////////////////////////////////////////// +#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) + + #include + #include + + // From v2.3.1 + #define SSL_AXTLS + ////// + + #define WEBSOCKETS_NETWORK_CLASS WiFiClient + #define WEBSOCKETS_NETWORK_SSL_CLASS WiFiClientSecure + #define WEBSOCKETS_NETWORK_SERVER_CLASS WiFiServer + +//////////////////////////////////////////////////////////////// +#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32_ETH) + + #include + + #include + #include + + // From v2.3.1 + #define SSL_AXTLS + ////// + + #define WEBSOCKETS_NETWORK_CLASS WiFiClient + #define WEBSOCKETS_NETWORK_SSL_CLASS WiFiClientSecure + #define WEBSOCKETS_NETWORK_SERVER_CLASS WiFiServer + + +//////////////////////////////////////////////////////////////// +#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_WIFININA) + + //KH + #include + #include + + #define SSL_AXTLS + + #define WEBSOCKETS_NETWORK_CLASS WiFiClient + #define WEBSOCKETS_NETWORK_SSL_CLASS WiFiSSLClient + #define WEBSOCKETS_NETWORK_SERVER_CLASS WiFiServer + +//////////////////////////////////////////////////////////////// +#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_WIFI101) + + //KH + #include + #include + + #define SSL_AXTLS + + #define WEBSOCKETS_NETWORK_CLASS WiFiClient + #define WEBSOCKETS_NETWORK_SSL_CLASS WiFiSSLClient + #define WEBSOCKETS_NETWORK_SERVER_CLASS WiFiServer + +//////////////////////////////////////////////////////////////// +#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_ETHERNET_ENC) + + //KH + #include + + #if(_WEBSOCKETS_LOGLEVEL_>3) + #warning Using ENC28J60 EthernetENC Library + #endif + + #define WEBSOCKETS_NETWORK_CLASS EthernetClient + #define WEBSOCKETS_NETWORK_SERVER_CLASS EthernetServer + +//////////////////////////////////////////////////////////////// +#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_RTL8720DN) + + //KH, from v2.3.2 + #include + #include + + #if(_WEBSOCKETS_LOGLEVEL_>3) + #warning Using RTL8720DN Seeed_Arduino_rpcWiFi Library + #endif + + #define SSL_AXTLS + + #define WEBSOCKETS_NETWORK_CLASS WiFiClient + #define WEBSOCKETS_NETWORK_SSL_CLASS WiFiClientSecure + #define WEBSOCKETS_NETWORK_SERVER_CLASS WiFiServer + +//////////////////////////////////////////////////////////////// +#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_NATIVEETHERNET) + + //KH, from v2.4.0 + #include + + #if(_WEBSOCKETS_LOGLEVEL_>3) + #warning Using Teensy 4.1 NativeEthernet Library + #endif + + #define WEBSOCKETS_NETWORK_CLASS EthernetClient + #define WEBSOCKETS_NETWORK_SERVER_CLASS EthernetServer + +//////////////////////////////////////////////////////////////// +#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_QN_ETHERNET) + + //KH, from v2.9.0 + #include + using namespace qindesign::network; + + #if(_WEBSOCKETS_LOGLEVEL_>3) + #warning Using Teensy 4.1 QNEthernet Library + #endif + + #define WEBSOCKETS_NETWORK_CLASS EthernetClient + #define WEBSOCKETS_NETWORK_SERVER_CLASS EthernetServer + +//////////////////////////////////////////////////////////////// +#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_PORTENTA_H7_WIFI) + + //KH, from v2.10.0 + #include + //#include + + #if(_WEBSOCKETS_LOGLEVEL_>3) + #warning Using Portenta_H7 WiFi Library + #endif + + #define WEBSOCKETS_NETWORK_CLASS WiFiClient + //#define WEBSOCKETS_NETWORK_SSL_CLASS WiFiSSLClient + #define WEBSOCKETS_NETWORK_SERVER_CLASS WiFiServer + +//////////////////////////////////////////////////////////////// +#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_PORTENTA_H7_ETHERNET) + + //KH, from v2.10.0 + #include + + #if(_WEBSOCKETS_LOGLEVEL_>3) + #warning Using Portenta_H7 Ethernet Library + #endif + + #define WEBSOCKETS_NETWORK_CLASS EthernetClient + //#define WEBSOCKETS_NETWORK_SSL_CLASS EthernetSSLClient + #define WEBSOCKETS_NETWORK_SERVER_CLASS EthernetServer + + + +//////////////////////////////////////////////////////////////// +#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_LAN8742A) + + //KH, from v2.4.0 + #include + #include + + #if(_WEBSOCKETS_LOGLEVEL_>3) + #warning Using LAN8742A Ethernet & STM32Ethernet lib + #endif + + #define WEBSOCKETS_NETWORK_CLASS EthernetClient + #define WEBSOCKETS_NETWORK_SERVER_CLASS EthernetServer + +//////////////////////////////////////////////////////////////// + +#else + #error "no network type selected!" +#endif + +////////////////////////////////////////////////////////////// + +#ifdef WEBSOCKETS_NETWORK_SSL_CLASS + + #if(_WEBSOCKETS_LOGLEVEL_>3) + #warning This network type Supporting SSL for WebSockets + #endif + + #define HAS_SSL +#endif + +// moves all Header strings to Flash (~300 Byte) +#ifdef WEBSOCKETS_SAVE_RAM + #define WEBSOCKETS_STRING(var) F(var) +#else + #define WEBSOCKETS_STRING(var) var +#endif + +typedef enum +{ + WSC_NOT_CONNECTED, + WSC_HEADER, + WSC_BODY, + WSC_CONNECTED +} WSclientsStatus_t; + +typedef enum +{ + WStype_ERROR, + WStype_DISCONNECTED, + WStype_CONNECTED, + WStype_TEXT, + WStype_BIN, + WStype_FRAGMENT_TEXT_START, + WStype_FRAGMENT_BIN_START, + WStype_FRAGMENT, + WStype_FRAGMENT_FIN, + WStype_PING, + WStype_PONG, +} WStype_t; + +typedef enum +{ + WSop_continuation = 0x00, ///< %x0 denotes a continuation frame + WSop_text = 0x01, ///< %x1 denotes a text frame + WSop_binary = 0x02, ///< %x2 denotes a binary frame + ///< %x3-7 are reserved for further non-control frames + WSop_close = 0x08, ///< %x8 denotes a connection close + WSop_ping = 0x09, ///< %x9 denotes a ping + WSop_pong = 0x0A ///< %xA denotes a pong + ///< %xB-F are reserved for further control frames +} WSopcode_t; + +typedef struct +{ + bool fin; + bool rsv1; + bool rsv2; + bool rsv3; + + WSopcode_t opCode; + bool mask; + + size_t payloadLen; + + uint8_t * maskKey; +} WSMessageHeader_t; + +typedef struct +{ + void init(const uint8_t& num, const uint32_t& pingInterval, const uint32_t& pongTimeout, + const uint8_t& disconnectTimeoutCount) + { + this->num = num; + this->pingInterval = pingInterval; + this->pongTimeout = pongTimeout; + this->disconnectTimeoutCount = disconnectTimeoutCount; + } + + uint8_t num = 0; ///< connection number + + WSclientsStatus_t status = WSC_NOT_CONNECTED; + + WEBSOCKETS_NETWORK_CLASS * tcp = nullptr; + + bool isSocketIO = false; ///< client for socket.io server + +#if defined(HAS_SSL) + bool isSSL = false; ///< run in ssl mode + WEBSOCKETS_NETWORK_SSL_CLASS * ssl = nullptr; +#endif + + String cUrl; ///< http url + uint16_t cCode = 0; ///< http code + + bool cIsClient = false; ///< will be used for masking + bool cIsUpgrade = false; ///< Connection == Upgrade + bool cIsWebsocket = false; ///< Upgrade == websocket + + String cSessionId; ///< client Set-Cookie (session id) + String cKey; ///< client Sec-WebSocket-Key + String cAccept; ///< client Sec-WebSocket-Accept + String cProtocol; ///< client Sec-WebSocket-Protocol + String cExtensions; ///< client Sec-WebSocket-Extensions + uint16_t cVersion = 0; ///< client Sec-WebSocket-Version + + uint8_t cWsRXsize = 0; ///< State of the RX + uint8_t cWsHeader[WEBSOCKETS_MAX_HEADER_SIZE]; ///< RX WS Message buffer + WSMessageHeader_t cWsHeaderDecode; + + String base64Authorization; ///< Base64 encoded Auth request + String plainAuthorization; ///< Base64 encoded Auth request + + String extraHeaders; + + bool cHttpHeadersValid = false; ///< non-websocket http header validity indicator + size_t cMandatoryHeadersCount; ///< non-websocket mandatory http headers present count + + bool pongReceived = false; + uint32_t pingInterval = 0; // how often ping will be sent, 0 means "heartbeat is not active" + uint32_t lastPing = 0; // millis when last pong has been received + uint32_t pongTimeout = 0; // interval in millis after which pong is considered to timeout + uint8_t disconnectTimeoutCount = 0; // after how many subsequent pong timeouts discconnect will happen, 0 means "do not disconnect" + uint8_t pongTimeoutCount = 0; // current pong timeout count + +#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) + String cHttpLine; ///< HTTP header lines +#endif + +} WSclient_t; + +class WebSockets +{ + protected: +#ifdef __AVR__ + typedef void (*WSreadWaitCb)(WSclient_t * client, bool ok); +#else + typedef std::function WSreadWaitCb; +#endif + + virtual void clientDisconnect(WSclient_t * client) = 0; + virtual bool clientIsConnected(WSclient_t * client) = 0; + + void clientDisconnect(WSclient_t * client, uint16_t code, char * reason = NULL, size_t reasonLen = 0); + + virtual void messageReceived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, + size_t length, bool fin) = 0; + + uint8_t createHeader(uint8_t * buf, WSopcode_t opcode, size_t length, bool mask, + uint8_t maskKey[4], bool fin); + + bool sendFrameHeader(WSclient_t * client, WSopcode_t opcode, size_t length = 0, bool fin = true); + + bool sendFrame(WSclient_t * client, WSopcode_t opcode, uint8_t * payload = NULL, size_t length = 0, + bool fin = true, bool headerToPayload = false); + + void headerDone(WSclient_t * client); + + void handleWebsocket(WSclient_t * client); + + bool handleWebsocketWaitFor(WSclient_t * client, size_t size); + void handleWebsocketCb(WSclient_t * client); + void handleWebsocketPayloadCb(WSclient_t * client, bool ok, uint8_t * payload); + + String acceptKey(String & clientKey); + String base64_encode(uint8_t * data, size_t length); + + bool readCb(WSclient_t * client, uint8_t * out, size_t n, WSreadWaitCb cb); + virtual size_t write(WSclient_t * client, uint8_t * out, size_t n); + size_t write(WSclient_t * client, const char * out); + + void enableHeartbeat(WSclient_t * client, const uint32_t& pingInterval, const uint32_t& pongTimeout, + const uint8_t& disconnectTimeoutCount); + + void handleHBTimeout(WSclient_t * client); +}; + + +// KH +String WS_IPAddressToString(const IPAddress& _address) +{ + String str = String(_address[0]); + str += "."; + str += String(_address[1]); + str += "."; + str += String(_address[2]); + str += "."; + str += String(_address[3]); + + return str; +} + +#ifndef UNUSED + #define UNUSED(var) (void)(var) +#endif + +#include "WebSockets_Generic-Impl.h" + +#endif // WEBSOCKETS_GENERIC_H_ + diff --git a/src/src/libb64/AUTHORS b/src/src/libb64/AUTHORS new file mode 100644 index 00000000..af687375 --- /dev/null +++ b/src/src/libb64/AUTHORS @@ -0,0 +1,7 @@ +libb64: Base64 Encoding/Decoding Routines +====================================== + +Authors: +------- + +Chris Venter chris.venter@gmail.com http://rocketpod.blogspot.com diff --git a/src/src/libb64/LICENSE b/src/src/libb64/LICENSE new file mode 100644 index 00000000..a6b56069 --- /dev/null +++ b/src/src/libb64/LICENSE @@ -0,0 +1,29 @@ +Copyright-Only Dedication (based on United States law) +or Public Domain Certification + +The person or persons who have associated work with this document (the +"Dedicator" or "Certifier") hereby either (a) certifies that, to the best of +his knowledge, the work of authorship identified is in the public domain of the +country from which the work is published, or (b) hereby dedicates whatever +copyright the dedicators holds in the work of authorship identified below (the +"Work") to the public domain. A certifier, moreover, dedicates any copyright +interest he may have in the associated work, and for these purposes, is +described as a "dedicator" below. + +A certifier has taken reasonable steps to verify the copyright status of this +work. Certifier recognizes that his good faith efforts may not shield him from +liability if in fact the work certified is not in the public domain. + +Dedicator makes this dedication for the benefit of the public at large and to +the detriment of the Dedicator's heirs and successors. Dedicator intends this +dedication to be an overt act of relinquishment in perpetuity of all present +and future rights under copyright law, whether vested or contingent, in the +Work. Dedicator understands that such relinquishment of all rights includes +the relinquishment of all rights to enforce (by lawsuit or otherwise) those +copyrights in the Work. + +Dedicator recognizes that, once placed in the public domain, the Work may be +freely reproduced, distributed, transmitted, used, modified, built upon, or +otherwise exploited by anyone for any purpose, commercial or non-commercial, +and in any way, including by methods that have not yet been invented or +conceived. \ No newline at end of file diff --git a/src/src/libb64/cdecode-Impl.h b/src/src/libb64/cdecode-Impl.h new file mode 100644 index 00000000..2fd3ce6b --- /dev/null +++ b/src/src/libb64/cdecode-Impl.h @@ -0,0 +1,166 @@ +/* +cdecoder.c - c source to a base64 decoding algorithm implementation + +This is part of the libb64 project, and has been placed in the public domain. +For details, see http://sourceforge.net/projects/libb64 +*/ + +#pragma once + +#ifndef BASE64_CDECODE_IMPL_H +#define BASE64_CDECODE_IMPL_H + +#ifdef ESP8266 + #include +#endif + +#if defined(ESP32) || defined(WIO_TERMINAL) + #ifndef CORE_HAS_LIBB64 + #define CORE_HAS_LIBB64 + #endif +#endif + +#include +//#include "cdecode_inc.h" + +#ifndef CORE_HAS_LIBB64 + +extern "C" { + + static int base64_decode_value_signed(int8_t value_in) + { + static const char decoding[] = + { 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, + -1, -1, -1, -2, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 + }; + + static const int8_t decoding_size = sizeof(decoding); + value_in -= 43; + + if (value_in < 0 || value_in > decoding_size) + return -1; + + return (int) ( &decoding[(int)value_in] ); + } + + void base64_init_decodestate(base64_decodestate* state_in) + { + state_in->step = step_a; + state_in->plainchar = 0; + } + + static int base64_decode_block_signed(const int8_t* code_in, const int length_in, int8_t* plaintext_out, base64_decodestate* state_in) + { + const int8_t* codechar = code_in; + int8_t* plainchar = plaintext_out; + int8_t fragment; + + *plainchar = state_in->plainchar; + + switch (state_in->step) + { + while (1) + { + case step_a: + do + { + if (codechar == code_in + length_in) + { + state_in->step = step_a; + state_in->plainchar = *plainchar; + return plainchar - plaintext_out; + } + + fragment = (int8_t)base64_decode_value_signed(*codechar++); + } while (fragment < 0); + + *plainchar = (fragment & 0x03f) << 2; + // falls through + case step_b: + do + { + if (codechar == code_in + length_in) + { + state_in->step = step_b; + state_in->plainchar = *plainchar; + return plainchar - plaintext_out; + } + + fragment = (int8_t)base64_decode_value_signed(*codechar++); + } while (fragment < 0); + + *plainchar++ |= (fragment & 0x030) >> 4; + *plainchar = (fragment & 0x00f) << 4; + // falls through + case step_c: + do + { + if (codechar == code_in + length_in) + { + state_in->step = step_c; + state_in->plainchar = *plainchar; + return plainchar - plaintext_out; + } + + fragment = (int8_t)base64_decode_value_signed(*codechar++); + } while (fragment < 0); + + *plainchar++ |= (fragment & 0x03c) >> 2; + *plainchar = (fragment & 0x003) << 6; + // falls through + case step_d: + do + { + if (codechar == code_in + length_in) + { + state_in->step = step_d; + state_in->plainchar = *plainchar; + return plainchar - plaintext_out; + } + fragment = (int8_t)base6 + 4_decode_value_signed(*codechar++); + } while (fragment < 0); + + *plainchar++ |= (fragment & 0x03f); + } + } + /* control should not reach here */ + return plainchar - plaintext_out; + } + + static int base64_decode_chars_signed(const int8_t* code_in, const int length_in, int8_t* plaintext_out) + { + base64_decodestate _state; + base64_init_decodestate(&_state); + + int len = base64_decode_block_signed(code_in, length_in, plaintext_out, &_state); + + if (len > 0) + plaintext_out[len] = 0; + + return len; + } + + int base64_decode_value(char value_in) + { + return base64_decode_value_signed(*((int8_t *) &value_in)); + } + + int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in) + { + return base64_decode_block_signed((int8_t *) code_in, length_in, (int8_t *) plaintext_out, state_in); + } + + int base64_decode_chars(const char* code_in, const int length_in, char* plaintext_out) + { + return base64_decode_chars_signed((int8_t *) code_in, length_in, (int8_t *) plaintext_out); + } + +}; + +#endif //CORE_HAS_LIBB64 + +#endif //BASE64_CDECODE_IMPL_H diff --git a/src/src/libb64/cdecode_inc.h b/src/src/libb64/cdecode_inc.h new file mode 100644 index 00000000..f2c1a8de --- /dev/null +++ b/src/src/libb64/cdecode_inc.h @@ -0,0 +1,47 @@ +/* +cdecode.h - c header for a base64 decoding algorithm + +This is part of the libb64 project, and has been placed in the public domain. +For details, see http://sourceforge.net/projects/libb64 +*/ + +#pragma once + +#ifndef BASE64_CDECODE_H +#define BASE64_CDECODE_H + +#define base64_decode_expected_len(n) ((n * 3) / 4) + +#ifdef __cplusplus + extern "C" { +#endif + +typedef enum +{ + step_a, + step_b, + step_c, + step_d +} base64_decodestep; + +typedef struct +{ + base64_decodestep step; + char plainchar; +} base64_decodestate; + +void base64_init_decodestate(base64_decodestate* state_in); + +int base64_decode_value(char value_in); + +int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in); + +int base64_decode_chars(const char* code_in, const int length_in, char* plaintext_out); + +#ifdef __cplusplus + } // extern "C" +#endif + +#include "cdecode-Impl.h" + +#endif /* BASE64_CDECODE_H */ diff --git a/src/src/libb64/cencode-Impl.h b/src/src/libb64/cencode-Impl.h new file mode 100644 index 00000000..b72736b8 --- /dev/null +++ b/src/src/libb64/cencode-Impl.h @@ -0,0 +1,166 @@ +/* +cencoder.c - c source to a base64 encoding algorithm implementation + +This is part of the libb64 project, and has been placed in the public domain. +For details, see http://sourceforge.net/projects/libb64 +*/ + +#pragma once + +#ifndef BASE64_CENCODE_IMPL_H +#define BASE64_CENCODE_IMPL_H + +#ifdef ESP8266 +#include +#endif + +#if defined(ESP32) || defined(WIO_TERMINAL) + #ifndef CORE_HAS_LIBB64 + #define CORE_HAS_LIBB64 + #endif +#endif + +#ifndef CORE_HAS_LIBB64 + +extern "C" +{ + + void base64_init_encodestate(base64_encodestate* state_in) + { + state_in->step = step_A; + state_in->result = 0; + state_in->stepcount = 0; + state_in->stepsnewline = BASE64_CHARS_PER_LINE; + } + + + void base64_init_encodestate_nonewlines(base64_encodestate* state_in) + { + base64_init_encodestate(state_in); + state_in->stepsnewline = -1; + } + + char base64_encode_value(const char n) + { + char r; + + if (n < 26) + r = n + 'A'; + else if (n < 26 + 26) + r = n - 26 + 'a'; + else if (n < 26 + 26 + 10 ) + r = n - 26 - 26 + '0'; + else if (n == 62 ) + r = '+'; + else + r = '/'; + return r; + } + + int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in) + { + const char* plainchar = plaintext_in; + const char* const plaintextend = plaintext_in + length_in; + char* codechar = code_out; + char result; + char fragment; + + result = state_in->result; + + switch (state_in->step) + { + while (1) + { + case step_A: + if (plainchar == plaintextend) + { + state_in->result = result; + state_in->step = step_A; + return codechar - code_out; + } + + fragment = *plainchar++; + result = (fragment & 0x0fc) >> 2; + *codechar++ = base64_encode_value(result); + result = (fragment & 0x003) << 4; + // falls through + case step_B: + if (plainchar == plaintextend) + { + state_in->result = result; + state_in->step = step_B; + return codechar - code_out; + } + + fragment = *plainchar++; + result |= (fragment & 0x0f0) >> 4; + *codechar++ = base64_encode_value(result); + result = (fragment & 0x00f) << 2; + // falls through + case step_C: + if (plainchar == plaintextend) + { + state_in->result = result; + state_in->step = step_C; + return codechar - code_out; + } + + fragment = *plainchar++; + result |= (fragment & 0x0c0) >> 6; + *codechar++ = base64_encode_value(result); + result = (fragment & 0x03f) >> 0; + *codechar++ = base64_encode_value(result); + + ++(state_in->stepcount); + + if ((state_in->stepcount == BASE64_CHARS_PER_LINE / 4) && (state_in->stepsnewline > 0)) + { + *codechar++ = '\n'; + state_in->stepcount = 0; + } + } + } + + /* control should not reach here */ + return codechar - code_out; + } + + int base64_encode_blockend(char* code_out, base64_encodestate* state_in) + { + char* codechar = code_out; + + switch (state_in->step) + { + case step_B: + *codechar++ = base64_encode_value(state_in->result); + *codechar++ = '='; + *codechar++ = '='; + break; + case step_C: + *codechar++ = base64_encode_value(state_in->result); + *codechar++ = '='; + break; + case step_A: + break; + } + + *codechar = 0x00; + + return codechar - code_out; + } + + int base64_encode_chars(const char* plaintext_in, int length_in, char* code_out) + { + base64_encodestate _state; + base64_init_encodestate(&_state); + + int len = base64_encode_block(plaintext_in, length_in, code_out, &_state); + + return len + base64_encode_blockend((code_out + len), &_state); + } + +}; + +#endif //CORE_HAS_LIBB64 + +#endif //BASE64_CENCODE_IMPL_H diff --git a/src/src/libb64/cencode_inc.h b/src/src/libb64/cencode_inc.h new file mode 100644 index 00000000..c4c3a530 --- /dev/null +++ b/src/src/libb64/cencode_inc.h @@ -0,0 +1,56 @@ +/* +cencode.h - c header for a base64 encoding algorithm + +This is part of the libb64 project, and has been placed in the public domain. +For details, see http://sourceforge.net/projects/libb64 +*/ + +#pragma once + +#ifndef BASE64_CENCODE_H +#define BASE64_CENCODE_H + +#define BASE64_CHARS_PER_LINE 72 + +#define base64_encode_expected_len_nonewlines(n) ((((4 * (n)) / 3) + 3) & ~3) +#define base64_encode_expected_len(n) \ + (base64_encode_expected_len_nonewlines(n) + ((n / ((BASE64_CHARS_PER_LINE * 3) / 4)) + 1)) + + +#ifdef __cplusplus + extern "C" { +#endif + +typedef enum +{ + step_A, + step_B, + step_C +} base64_encodestep; + +typedef struct +{ + base64_encodestep step; + char result; + int stepcount; + int stepsnewline; +} base64_encodestate; + +void base64_init_encodestate(base64_encodestate* state_in); +void base64_init_encodestate_nonewlines(base64_encodestate* state_in); + +char base64_encode_value(char value_in); + +int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in); + +int base64_encode_blockend(char* code_out, base64_encodestate* state_in); + +int base64_encode_chars(const char* plaintext_in, int length_in, char* code_out); + +#ifdef __cplusplus + } // extern "C" +#endif + +#include "cencode-Impl.h" + +#endif /* BASE64_CENCODE_H */ diff --git a/src/src/libsha1/libsha1.c b/src/src/libsha1/libsha1.c new file mode 100644 index 00000000..aed7c177 --- /dev/null +++ b/src/src/libsha1/libsha1.c @@ -0,0 +1,224 @@ +/* from valgrind tests */ + +/* ================ sha1.c ================ */ +/* + SHA-1 in C + By Steve Reid + 100% Public Domain + + Test Vectors (from FIPS PUB 180-1) + "abc" + A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 + A million repetitions of "a" + 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F +*/ + +/* #define LITTLE_ENDIAN * This should be #define'd already, if true. */ +/* #define SHA1HANDSOFF * Copies data before messing with it. */ + +#if !defined(ESP8266) && !defined(ESP32) + +#define SHA1HANDSOFF + +#include +#include +#include + +#include "libsha1.h" + +#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) + +/* blk0() and blk() perform the initial expand. */ +/* I got the idea of expanding during the round function from SSLeay */ +#if BYTE_ORDER == LITTLE_ENDIAN + #define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ + |(rol(block->l[i],8)&0x00FF00FF)) +#elif BYTE_ORDER == BIG_ENDIAN + #define blk0(i) block->l[i] +#else + #error "Endianness not defined!" +#endif + +#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ + ^block->l[(i+2)&15]^block->l[i&15],1)) + +/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ +#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); +#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); +#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); + + +/* Hash a single 512-bit block. This is the core of the algorithm. */ + +void SHA1Transform(uint32_t state[5], const unsigned char buffer[64]) +{ + uint32_t a, b, c, d, e; + typedef union + { + unsigned char c[64]; + uint32_t l[16]; + } CHAR64LONG16; + +#ifdef SHA1HANDSOFF + CHAR64LONG16 block[1]; /* use array to appear as a pointer */ + memcpy(block, buffer, 64); +#else + /* The following had better never be used because it causes the + pointer-to-const buffer to be cast into a pointer to non-const. + And the result is written through. I threw a "const" in, hoping + this will cause a diagnostic. + */ + CHAR64LONG16* block = (const CHAR64LONG16*)buffer; +#endif + + /* Copy context->state[] to working vars */ + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a, b, c, d, e, 0); R0(e, a, b, c, d, 1); R0(d, e, a, b, c, 2); R0(c, d, e, a, b, 3); + R0(b, c, d, e, a, 4); R0(a, b, c, d, e, 5); R0(e, a, b, c, d, 6); R0(d, e, a, b, c, 7); + R0(c, d, e, a, b, 8); R0(b, c, d, e, a, 9); R0(a, b, c, d, e, 10); R0(e, a, b, c, d, 11); + R0(d, e, a, b, c, 12); R0(c, d, e, a, b, 13); R0(b, c, d, e, a, 14); R0(a, b, c, d, e, 15); + R1(e, a, b, c, d, 16); R1(d, e, a, b, c, 17); R1(c, d, e, a, b, 18); R1(b, c, d, e, a, 19); + R2(a, b, c, d, e, 20); R2(e, a, b, c, d, 21); R2(d, e, a, b, c, 22); R2(c, d, e, a, b, 23); + R2(b, c, d, e, a, 24); R2(a, b, c, d, e, 25); R2(e, a, b, c, d, 26); R2(d, e, a, b, c, 27); + R2(c, d, e, a, b, 28); R2(b, c, d, e, a, 29); R2(a, b, c, d, e, 30); R2(e, a, b, c, d, 31); + R2(d, e, a, b, c, 32); R2(c, d, e, a, b, 33); R2(b, c, d, e, a, 34); R2(a, b, c, d, e, 35); + R2(e, a, b, c, d, 36); R2(d, e, a, b, c, 37); R2(c, d, e, a, b, 38); R2(b, c, d, e, a, 39); + R3(a, b, c, d, e, 40); R3(e, a, b, c, d, 41); R3(d, e, a, b, c, 42); R3(c, d, e, a, b, 43); + R3(b, c, d, e, a, 44); R3(a, b, c, d, e, 45); R3(e, a, b, c, d, 46); R3(d, e, a, b, c, 47); + R3(c, d, e, a, b, 48); R3(b, c, d, e, a, 49); R3(a, b, c, d, e, 50); R3(e, a, b, c, d, 51); + R3(d, e, a, b, c, 52); R3(c, d, e, a, b, 53); R3(b, c, d, e, a, 54); R3(a, b, c, d, e, 55); + R3(e, a, b, c, d, 56); R3(d, e, a, b, c, 57); R3(c, d, e, a, b, 58); R3(b, c, d, e, a, 59); + R4(a, b, c, d, e, 60); R4(e, a, b, c, d, 61); R4(d, e, a, b, c, 62); R4(c, d, e, a, b, 63); + R4(b, c, d, e, a, 64); R4(a, b, c, d, e, 65); R4(e, a, b, c, d, 66); R4(d, e, a, b, c, 67); + R4(c, d, e, a, b, 68); R4(b, c, d, e, a, 69); R4(a, b, c, d, e, 70); R4(e, a, b, c, d, 71); + R4(d, e, a, b, c, 72); R4(c, d, e, a, b, 73); R4(b, c, d, e, a, 74); R4(a, b, c, d, e, 75); + R4(e, a, b, c, d, 76); R4(d, e, a, b, c, 77); R4(c, d, e, a, b, 78); R4(b, c, d, e, a, 79); + + /* Add the working vars back into context.state[] */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + /* Wipe variables */ + a = b = c = d = e = 0; + +#ifdef SHA1HANDSOFF + memset(block, '\0', sizeof(block)); +#endif +} + + +/* SHA1Init - Initialize new context */ + +void SHA1Init(SHA1_CTX* context) +{ + /* SHA1 initialization constants */ + context->state[0] = 0x67452301; + context->state[1] = 0xEFCDAB89; + context->state[2] = 0x98BADCFE; + context->state[3] = 0x10325476; + context->state[4] = 0xC3D2E1F0; + context->count[0] = context->count[1] = 0; +} + + +/* Run your data through this. */ + +void SHA1Update(SHA1_CTX* context, const unsigned char* data, uint32_t len) +{ + uint32_t i, j; + + j = context->count[0]; + + if ((context->count[0] += len << 3) < j) + context->count[1]++; + + context->count[1] += (len >> 29); + j = (j >> 3) & 63; + + if ((j + len) > 63) + { + memcpy(&context->buffer[j], data, (i = 64 - j)); + SHA1Transform(context->state, context->buffer); + + for ( ; i + 63 < len; i += 64) + { + SHA1Transform(context->state, &data[i]); + } + + j = 0; + } + else + i = 0; + + memcpy(&context->buffer[j], &data[i], len - i); +} + + +/* Add padding and return the message digest. */ + +void SHA1Final(unsigned char digest[20], SHA1_CTX* context) +{ + unsigned i; + unsigned char finalcount[8]; + unsigned char c; + +#if 0 /* untested "improvement" by DHR */ + /* Convert context->count to a sequence of bytes + in finalcount. Second element first, but + big-endian order within element. + But we do it all backwards. + */ + unsigned char *fcp = &finalcount[8]; + + for (i = 0; i < 2; i++) + { + uint32_t t = context->count[i]; + int j; + + for (j = 0; j < 4; t >>= 8, j++) + * --fcp = (unsigned char) t; + } +#else + for (i = 0; i < 8; i++) + { + /* Endian independent */ + finalcount[i] = (unsigned char) + ((context->count[(i >= 4 ? 0 : 1)] >> ((3 - (i & 3)) * 8) ) & 255); + } +#endif + + c = 0200; + SHA1Update(context, &c, 1); + while ((context->count[0] & 504) != 448) + { + c = 0000; + SHA1Update(context, &c, 1); + } + + SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ + + for (i = 0; i < 20; i++) + { + digest[i] = (unsigned char) + ((context->state[i >> 2] >> ((3 - (i & 3)) * 8) ) & 255); + } + + /* Wipe variables */ + memset(context, '\0', sizeof(*context)); + memset(&finalcount, '\0', sizeof(finalcount)); +} +/* ================ end of sha1.c ================ */ + + +#endif diff --git a/src/src/libsha1/libsha1.h b/src/src/libsha1/libsha1.h new file mode 100644 index 00000000..0d8d8d2e --- /dev/null +++ b/src/src/libsha1/libsha1.h @@ -0,0 +1,29 @@ +/* ================ sha1.h ================ */ +/* +SHA-1 in C +By Steve Reid +100% Public Domain +*/ + +#pragma once + +#ifndef LIBSHA1_H +#define LIBSHA1_H + +#if !defined(ESP8266) && !defined(ESP32) + +typedef struct +{ + uint32_t state[5]; + uint32_t count[2]; + unsigned char buffer[64]; +} SHA1_CTX; + +void SHA1Transform(uint32_t state[5], const unsigned char buffer[64]); +void SHA1Init(SHA1_CTX* context); +void SHA1Update(SHA1_CTX* context, const unsigned char* data, uint32_t len); +void SHA1Final(unsigned char digest[20], SHA1_CTX* context); + +#endif + +#endif // LIBSHA1_H