├── .gitignore ├── CHANGELOG.md ├── DOXYGEN_FRONTPAGE.md ├── LICENSE ├── README.md ├── apache-2.0.txt ├── coverage.json ├── mbed-net-sockets ├── Socket.h ├── SocketAddr.h ├── TCPAsynch.h ├── TCPListener.h ├── TCPStream.h ├── UDPSocket.h └── v0 │ ├── Socket.h │ ├── SocketAddr.h │ ├── TCPAsynch.h │ ├── TCPListener.h │ ├── TCPStream.h │ └── UDPSocket.h ├── module.json ├── sockets ├── Socket.h ├── SocketAddr.h ├── TCPAsynch.h ├── TCPListener.h ├── TCPStream.h ├── UDPSocket.h └── v0 │ ├── Socket.h │ ├── SocketAddr.h │ ├── TCPAsynch.h │ ├── TCPListener.h │ ├── TCPStream.h │ └── UDPSocket.h ├── source └── v0 │ ├── Socket.cpp │ ├── SocketAddr.cpp │ ├── TCPAsynch.cpp │ ├── TCPListener.cpp │ ├── TCPStream.cpp │ └── UDPSocket.cpp └── test ├── echo-tcp-client └── main.cpp ├── echo-udp-client └── main.cpp └── host_tests ├── tcpecho_client_auto.py └── udpecho_client_auto.py /.gitignore: -------------------------------------------------------------------------------- 1 | build/* 2 | yotta_modules/* 3 | yotta_targets/* 4 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | All notable changes to this project will be documented in this file. 3 | This project adheres to [Semantic Versioning](http://semver.org/). 4 | 5 | ## [Unreleased] 6 | ### Added 7 | - A Doxygen frontpage for Sockets 8 | 9 | ## [v1.1.4] - 2016-03-16 10 | ### Added 11 | * Configuration file to support test coverage generation 12 | 13 | ## [v1.1.3] - 2016-03-02 14 | ### Improved 15 | - Updated sockets tests to work with new mbed-greentea infrastructure 16 | 17 | ## [v1.1.2] - 2016-03-01 18 | ### Updated 19 | - Updated mbed-drivers dependency to 1.0.0 20 | 21 | ## [v1.1.1] 22 | ### Improved 23 | - Documentation now defines expected error codes 24 | - Error codes returned match documentation 25 | - Additional checks for failing conditions 26 | 27 | ### Added 28 | - A new TCPStream constructor for use with ```accept()``` 29 | - The previous TCPStream constructor used with ```accept()``` is now deprecated 30 | 31 | ## [v1.1.0] 32 | ### Improved 33 | - SocketAddr now formats both IPv4 and IPv6 addresses 34 | - SocketAddr now interprets text addresses into internal representation with the setAddr API 35 | - Added an API to enable/disable Nagle's algorithm on TCP Streams 36 | 37 | [Unreleased]: https://github.com/ARMmbed/sockets/compare/v1.1.4...HEAD 38 | [v1.1.4]: https://github.com/ARMmbed/sockets/compare/v1.1.3...v1.1.4 39 | [v1.1.3]: https://github.com/ARMmbed/sockets/compare/v1.1.2...v1.1.3 40 | [v1.1.2]: https://github.com/ARMmbed/sockets/compare/v1.1.1...v1.1.2 41 | [v1.1.1]: https://github.com/ARMmbed/sockets/compare/v1.1.0...v1.1.1 42 | [v1.1.0]: https://github.com/ARMmbed/sockets/compare/v1.0.2...v1.1.0 43 | -------------------------------------------------------------------------------- /DOXYGEN_FRONTPAGE.md: -------------------------------------------------------------------------------- 1 | # mbed C++ Socket API 2 | The mbed C++ Socket API provides an interface to sockets which will be familiar to users of BSD sockets, but there are several differences compared to the typical BSD socket implementations. In typical desktop BSD socket applications, the program will block a thread, while waiting for each socket call to complete. This is conceptually simple, but not well-suited to event-based embedded systems. In the C++ Socket API, each socket has a set of callbacks which trigger when events complete, much like the BSD Sockets work in asynchronous mode; instead of having a single SIGIO handler however, the C++ Socket API provides an event handler for each type of event. 3 | 4 | ## Usage Notes 5 | This version is an alpha and there are some known problems. 6 | ### Event handler context 7 | Event handling currently occurs in the interrupt context. In an upcoming release, there will be provision for event handling in the main loop. 8 | ### Error handling 9 | Errors are forwarded to the event registered with setOnError(). If this event is not set, errors are ignored. All applications should register an onError event handler. 10 | 11 | ## Getting Started 12 | The best place to start is the mbed-example-network module. There are simple examples there. However, for a simple overview, there are several examples below. 13 | 14 | ### UDP Examples 15 | Creating a UDP Socket 16 | ```C++ 17 | UDPSocket s(SOCKET_STACK_LWIP_IPV4); 18 | ``` 19 | Set an error handler 20 | ```C++ 21 | s.setOnError(onError); 22 | ``` 23 | Opening a UDP Socket 24 | ```C++ 25 | s.open(SOCKET_AF_INET4); 26 | ``` 27 | Send some data 28 | ```C++ 29 | s.send_to(data, dlen, addr, port); 30 | ``` 31 | Recieve some data 32 | ```C++ 33 | s.setOnReadable(onRecv); 34 | ``` 35 | 36 | ### TCP Examples 37 | Creating a TCP Socket 38 | ```C++ 39 | TCPStream s(SOCKET_STACK_LWIP_IPV4); 40 | ``` 41 | Opening a TCP Socket 42 | ```C++ 43 | s.open(SOCKET_AF_INET4); 44 | ``` 45 | Connect to a host 46 | ```C++ 47 | s.connect(addr, port, onConnect); 48 | ``` 49 | Set the disconnect handler 50 | ```C++ 51 | s.setOnDisconnect(onDisconnect); 52 | ``` 53 | Send some data 54 | ```C++ 55 | s.send(data, dlen); 56 | ``` 57 | Recieve some data 58 | ```C++ 59 | s.setOnReadable(onRecv); 60 | ``` 61 | Close the socket 62 | ```C++ 63 | s.close(); 64 | ``` 65 | 66 | ### DNS Example 67 | This is a complete example of resolving an address with DNS 68 | ```C++ 69 | #include "sockets/v0/UDPSocket.h" 70 | #include "sal-stack-lwip/lwipv4_init.h" 71 | #include "sal-iface-eth/EthernetInterface.h" 72 | using namespace mbed::Sockets::v0; 73 | class Resolver { 74 | private: 75 | UDPSocket _sock; 76 | public: 77 | Resolver() : _sock(SOCKET_STACK_LWIP_IPV4) { 78 | _sock.open(SOCKET_AF_INET4); 79 | } 80 | void onDNS(Socket *s, struct socket_addr addr, const char *domain) { 81 | (void) s; 82 | SocketAddr sa; 83 | char buf[16]; 84 | sa.setAddr(&addr); 85 | sa.fmtIPv4(buf,sizeof(buf)); 86 | printf("Resolved %s to %s\r\n", domain, buf); 87 | } 88 | socket_error_t resolve(const char * address) { 89 | printf("Resolving %s...\r\n", address); 90 | return _sock.resolve(address,UDPSocket::DNSHandler_t(this, &Resolver::onDNS)); 91 | } 92 | }; 93 | 94 | EthernetInterface eth; 95 | Resolver *r; 96 | void app_start(int argc, char *argv[]) { 97 | (void) argc; 98 | (void) argv; 99 | static Serial pc(USBTX, USBRX); 100 | pc.baud(115200); 101 | printf("Connecting to network...\r\n"); 102 | eth.init(); 103 | eth.connect(); 104 | printf("Connected\r\n"); 105 | lwipv4_socket_init(); 106 | r = new Resolver(); 107 | r->resolve("mbed.org"); 108 | } 109 | 110 | ``` 111 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Unless specifically indicated otherwise in a file, files are licensed 2 | under the Apache 2.0 license, as can be found in: apache-2.0.txt 3 | 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # mbed C++ Socket API 2 | The mbed C++ Socket API provides an interface to sockets which will be familiar to users of BSD sockets, but there are several differences compared to the typical BSD socket implementations. In typical desktop BSD socket applications, the program will block a thread, while waiting for each socket call to complete. This is conceptually simple, but not well-suited to event-based embedded systems. In the C++ Socket API, each socket has a set of callbacks which trigger when events complete, much like the BSD Sockets work in asynchronous mode; instead of having a single SIGIO handler however, the C++ Socket API provides an event handler for each type of event. 3 | 4 | ## Usage Notes 5 | This version is an alpha and there are some known problems. 6 | ### Event handler context 7 | Event handling currently occurs in the interrupt context. In an upcoming release, there will be provision for event handling in the main loop. 8 | ### Error handling 9 | Errors are forwarded to the event registered with setOnError(). If this event is not set, errors are ignored. All applications should register an onError event handler. 10 | 11 | ## Getting Started 12 | The best place to start is the mbed-example-network module. There are simple examples there. However, for a simple overview, there are several examples below. 13 | 14 | ### UDP Examples 15 | Creating a UDP Socket 16 | ```C++ 17 | UDPSocket s(SOCKET_STACK_LWIP_IPV4); 18 | ``` 19 | Set an error handler 20 | ```C++ 21 | s.setOnError(onError); 22 | ``` 23 | Opening a UDP Socket 24 | ```C++ 25 | s.open(SOCKET_AF_INET4); 26 | ``` 27 | Send some data 28 | ```C++ 29 | s.send_to(data, dlen, addr, port); 30 | ``` 31 | Recieve some data 32 | ```C++ 33 | s.setOnReadable(onRecv); 34 | ``` 35 | 36 | ### TCP Examples 37 | Creating a TCP Socket 38 | ```C++ 39 | TCPStream s(SOCKET_STACK_LWIP_IPV4); 40 | ``` 41 | Opening a TCP Socket 42 | ```C++ 43 | s.open(SOCKET_AF_INET4); 44 | ``` 45 | Connect to a host 46 | ```C++ 47 | s.connect(addr, port, onConnect); 48 | ``` 49 | Set the disconnect handler 50 | ```C++ 51 | s.setOnDisconnect(onDisconnect); 52 | ``` 53 | Send some data 54 | ```C++ 55 | s.send(data, dlen); 56 | ``` 57 | Receive some data 58 | ```C++ 59 | s.setOnReadable(onRecv); 60 | ``` 61 | Close the socket 62 | ```C++ 63 | s.close(); 64 | ``` 65 | 66 | ### DNS Example 67 | This is a complete example of resolving an address with DNS 68 | ```C++ 69 | #include "sockets/v0/UDPSocket.h" 70 | #include "sal-stack-lwip/lwipv4_init.h" 71 | #include "sal-iface-eth/EthernetInterface.h" 72 | using namespace mbed::Sockets::v0; 73 | class Resolver { 74 | private: 75 | UDPSocket _sock; 76 | public: 77 | Resolver() : _sock(SOCKET_STACK_LWIP_IPV4) { 78 | _sock.open(SOCKET_AF_INET4); 79 | } 80 | void onDNS(Socket *s, struct socket_addr addr, const char *domain) { 81 | (void) s; 82 | SocketAddr sa; 83 | char buf[16]; 84 | sa.setAddr(&addr); 85 | sa.fmtIPv4(buf,sizeof(buf)); 86 | printf("Resolved %s to %s\r\n", domain, buf); 87 | } 88 | socket_error_t resolve(const char * address) { 89 | printf("Resolving %s...\r\n", address); 90 | return _sock.resolve(address,UDPSocket::DNSHandler_t(this, &Resolver::onDNS)); 91 | } 92 | }; 93 | 94 | EthernetInterface eth; 95 | Resolver *r; 96 | void app_start(int argc, char *argv[]) { 97 | (void) argc; 98 | (void) argv; 99 | static Serial pc(USBTX, USBRX); 100 | pc.baud(115200); 101 | printf("Connecting to network...\r\n"); 102 | eth.init(); 103 | eth.connect(); 104 | printf("Connected\r\n"); 105 | lwipv4_socket_init(); 106 | r = new Resolver(); 107 | r->resolve("mbed.org"); 108 | } 109 | 110 | ``` 111 | -------------------------------------------------------------------------------- /apache-2.0.txt: -------------------------------------------------------------------------------- 1 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 2 | 3 | 1. Definitions. 4 | 5 | "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. 6 | 7 | "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. 8 | 9 | "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. 10 | 11 | "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. 12 | 13 | "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. 14 | 15 | "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. 16 | 17 | "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). 18 | 19 | "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. 20 | 21 | "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." 22 | 23 | "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 24 | 25 | 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 26 | 27 | 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 28 | 29 | 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: 30 | 31 | (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and 32 | 33 | (b) You must cause any modified files to carry prominent notices stating that You changed the files; and 34 | 35 | (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and 36 | 37 | (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. 38 | 39 | You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 40 | 41 | 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 42 | 43 | 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 44 | 45 | 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 46 | 47 | 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 48 | 49 | 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. 50 | 51 | END OF TERMS AND CONDITIONS 52 | 53 | APPENDIX: How to apply the Apache License to your work. 54 | 55 | To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. 56 | 57 | Copyright [yyyy] [name of copyright owner] 58 | 59 | Licensed under the Apache License, Version 2.0 (the "License"); 60 | you may not use this file except in compliance with the License. 61 | You may obtain a copy of the License at 62 | 63 | http://www.apache.org/licenses/LICENSE-2.0 64 | 65 | Unless required by applicable law or agreed to in writing, software 66 | distributed under the License is distributed on an "AS IS" BASIS, 67 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 68 | See the License for the specific language governing permissions and 69 | limitations under the License. 70 | -------------------------------------------------------------------------------- /coverage.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "debug":{ 4 | "options" : { 5 | "coverage" : { 6 | "modules" : { 7 | "sockets" : true 8 | } 9 | } 10 | } 11 | }, 12 | "mbed-os": { 13 | "stdio": { 14 | "default-baud": 115200 15 | } 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /mbed-net-sockets/Socket.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, ARM Limited, All Rights Reserved 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | * not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | #ifndef __MBED_NET_SOCKETS_SOCKET_H__ 18 | #define __MBED_NET_SOCKETS_SOCKET_H__ 19 | #warning mbed-net-sockets/Socket.h is deprecated. Please use sockets/Socket.h instead. 20 | #include "../sockets/Socket.h" 21 | #endif // __MBED_NET_SOCKETS_SOCKET_H__ 22 | 23 | -------------------------------------------------------------------------------- /mbed-net-sockets/SocketAddr.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, ARM Limited, All Rights Reserved 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | * not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | #ifndef __MBED_NET_SOCKETS_SOCKETADDR_H__ 18 | #define __MBED_NET_SOCKETS_SOCKETADDR_H__ 19 | #warning mbed-net-sockets/SocketAddr.h is deprecated. Please use sockets/SocketAddr.h instead. 20 | #include "../sockets/SocketAddr.h" 21 | #endif // __MBED_NET_SOCKETS_SOCKETADDR_H__ 22 | 23 | -------------------------------------------------------------------------------- /mbed-net-sockets/TCPAsynch.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, ARM Limited, All Rights Reserved 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | * not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | #ifndef __MBED_NET_SOCKETS_TCPASYNCH_H__ 18 | #define __MBED_NET_SOCKETS_TCPASYNCH_H__ 19 | #warning mbed-net-sockets/TCPAsynch.h is deprecated. Please use sockets/TCPAsynch.h instead. 20 | #include "../sockets/TCPAsynch.h" 21 | #endif // __MBED_NET_SOCKETS_TCPASYNCH_H__ 22 | 23 | -------------------------------------------------------------------------------- /mbed-net-sockets/TCPListener.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, ARM Limited, All Rights Reserved 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | * not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | #ifndef __MBED_NET_SOCKETS_TCPLISTENER_H__ 18 | #define __MBED_NET_SOCKETS_TCPLISTENER_H__ 19 | #warning mbed-net-sockets/TCPListener.h is deprecated. Please use sockets/TCPListener.h instead. 20 | #include "../sockets/TCPListener.h" 21 | #endif // __MBED_NET_SOCKETS_TCPLISTENER_H__ 22 | 23 | -------------------------------------------------------------------------------- /mbed-net-sockets/TCPStream.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, ARM Limited, All Rights Reserved 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | * not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | #ifndef __MBED_NET_SOCKETS_TCPSTREAM_H__ 18 | #define __MBED_NET_SOCKETS_TCPSTREAM_H__ 19 | #warning mbed-net-sockets/TCPStream.h is deprecated. Please use sockets/TCPStream.h instead. 20 | #include "../sockets/TCPStream.h" 21 | #endif // __MBED_NET_SOCKETS_TCPSTREAM_H__ 22 | 23 | -------------------------------------------------------------------------------- /mbed-net-sockets/UDPSocket.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, ARM Limited, All Rights Reserved 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | * not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | #ifndef __MBED_NET_SOCKETS_UDPSOCKET_H__ 18 | #define __MBED_NET_SOCKETS_UDPSOCKET_H__ 19 | #warning mbed-net-sockets/UDPSocket.h is deprecated. Please use sockets/UDPSocket.h instead. 20 | #include "../sockets/UDPSocket.h" 21 | #endif // __MBED_NET_SOCKETS_UDPSOCKET_H__ 22 | 23 | -------------------------------------------------------------------------------- /mbed-net-sockets/v0/Socket.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, ARM Limited, All Rights Reserved 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | * not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | #ifndef __MBED_NET_SOCKETS_V0_SOCKET_H__ 18 | #define __MBED_NET_SOCKETS_V0_SOCKET_H__ 19 | #warning mbed-net-sockets/v0/Socket.h is deprecated. Please use sockets/v0/Socket.h instead. 20 | #include "../sockets/v0/Socket.h" 21 | #endif // __MBED_NET_SOCKETS_V0_SOCKET_H__ 22 | 23 | -------------------------------------------------------------------------------- /mbed-net-sockets/v0/SocketAddr.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, ARM Limited, All Rights Reserved 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | * not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | #ifndef __MBED_NET_SOCKETS_V0_SOCKETADDR_H__ 18 | #define __MBED_NET_SOCKETS_V0_SOCKETADDR_H__ 19 | #warning mbed-net-sockets/v0/SocketAddr.h is deprecated. Please use sockets/v0/SocketAddr.h instead. 20 | #include "../sockets/v0/SocketAddr.h" 21 | #endif // __MBED_NET_SOCKETS_V0_SOCKETADDR_H__ 22 | 23 | -------------------------------------------------------------------------------- /mbed-net-sockets/v0/TCPAsynch.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, ARM Limited, All Rights Reserved 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | * not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | #ifndef __MBED_NET_SOCKETS_V0_TCPASYNCH_H__ 18 | #define __MBED_NET_SOCKETS_V0_TCPASYNCH_H__ 19 | #warning mbed-net-sockets/v0/TCPAsynch.h is deprecated. Please use sockets/v0/TCPAsynch.h instead. 20 | #include "../sockets/v0/TCPAsynch.h" 21 | #endif // __MBED_NET_SOCKETS_V0_TCPASYNCH_H__ 22 | 23 | -------------------------------------------------------------------------------- /mbed-net-sockets/v0/TCPListener.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, ARM Limited, All Rights Reserved 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | * not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | #ifndef __MBED_NET_SOCKETS_V0_TCPLISTENER_H__ 18 | #define __MBED_NET_SOCKETS_V0_TCPLISTENER_H__ 19 | #warning mbed-net-sockets/v0/TCPListener.h is deprecated. Please use sockets/v0/TCPListener.h instead. 20 | #include "../sockets/v0/TCPListener.h" 21 | #endif // __MBED_NET_SOCKETS_V0_TCPLISTENER_H__ 22 | 23 | -------------------------------------------------------------------------------- /mbed-net-sockets/v0/TCPStream.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, ARM Limited, All Rights Reserved 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | * not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | #ifndef __MBED_NET_SOCKETS_V0_TCPSTREAM_H__ 18 | #define __MBED_NET_SOCKETS_V0_TCPSTREAM_H__ 19 | #warning mbed-net-sockets/v0/TCPStream.h is deprecated. Please use sockets/v0/TCPStream.h instead. 20 | #include "../sockets/v0/TCPStream.h" 21 | #endif // __MBED_NET_SOCKETS_V0_TCPSTREAM_H__ 22 | 23 | -------------------------------------------------------------------------------- /mbed-net-sockets/v0/UDPSocket.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, ARM Limited, All Rights Reserved 3 | * SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | * not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | #ifndef __MBED_NET_SOCKETS_V0_UDPSOCKET_H__ 18 | #define __MBED_NET_SOCKETS_V0_UDPSOCKET_H__ 19 | #warning mbed-net-sockets/v0/UDPSocket.h is deprecated. Please use sockets/v0/UDPSocket.h instead. 20 | #include "../sockets/v0/UDPSocket.h" 21 | #endif // __MBED_NET_SOCKETS_V0_UDPSOCKET_H__ 22 | 23 | -------------------------------------------------------------------------------- /module.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sockets", 3 | "version": "1.3.0", 4 | "description": "C++ Asynchronous Sockets Layer", 5 | "keywords": [ 6 | "mbed", 7 | "network", 8 | "sockets", 9 | "mbed-official" 10 | ], 11 | "author": "brendan.moran@arm.com", 12 | "licenses": [ 13 | { 14 | "url": "https://spdx.org/licenses/Apache-2.0", 15 | "type": "Apache-2.0" 16 | } 17 | ], 18 | "dependencies": { 19 | "sal": "^1.1.3", 20 | "core-util": "^1.0.0", 21 | "minar": "^1.0.0" 22 | }, 23 | "testDependencies": { 24 | "mbed-drivers": "^1.0.0", 25 | "unity": "^2.0.1", 26 | "greentea-client": ">=0.1.4,<2.0.0" 27 | }, 28 | "scripts": { 29 | "testReporter": [ 30 | "mbedgt", 31 | "--digest", 32 | "stdin", 33 | "-v", 34 | "-V" 35 | ] 36 | }, 37 | "targetDependencies": {} 38 | } 39 | -------------------------------------------------------------------------------- /sockets/Socket.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PackageLicenseDeclared: Apache-2.0 3 | * Copyright (c) 2015 ARM Limited 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | #ifndef __SOCKETS_SOCKET_H__ 18 | #define __SOCKETS_SOCKET_H__ 19 | 20 | /* Include all versions of the API */ 21 | #include "v0/Socket.h" 22 | 23 | /* Set the current namespace */ 24 | namespace mbed { 25 | namespace Sockets { 26 | namespace current { 27 | using namespace mbed::Sockets::v0; 28 | } 29 | } 30 | } 31 | 32 | #endif // __SOCKETS_SOCKET_H__ 33 | -------------------------------------------------------------------------------- /sockets/SocketAddr.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PackageLicenseDeclared: Apache-2.0 3 | * Copyright (c) 2015 ARM Limited 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | #ifndef __SOCKETS_SOCKETADDR_H__ 18 | #define __SOCKETS_SOCKETADDR_H__ 19 | 20 | /* Include all versions of the API */ 21 | #include "v0/SocketAddr.h" 22 | 23 | /* Set the current namespace */ 24 | namespace mbed { 25 | namespace Sockets { 26 | namespace current { 27 | using namespace mbed::Sockets::v0; 28 | } 29 | } 30 | } 31 | 32 | #endif // __SOCKETS_SOCKETADDR_H__ 33 | -------------------------------------------------------------------------------- /sockets/TCPAsynch.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PackageLicenseDeclared: Apache-2.0 3 | * Copyright (c) 2015 ARM Limited 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | #ifndef __MBED_NET_SOCKETS_TCP_ASYNCH__H__ 18 | #define __MBED_NET_SOCKETS_TCP_ASYNCH__H__ 19 | 20 | /* Include all versions of the API */ 21 | #include "v0/TCPAsynch.h" 22 | 23 | /* Set the current namespace */ 24 | namespace mbed { 25 | namespace Sockets { 26 | namespace current { 27 | using namespace mbed::Sockets::v0; 28 | } 29 | } 30 | } 31 | 32 | #endif // __MBED_NET_SOCKETS_TCP_ASYNCH__H__ 33 | -------------------------------------------------------------------------------- /sockets/TCPListener.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PackageLicenseDeclared: Apache-2.0 3 | * Copyright (c) 2015 ARM Limited 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | #ifndef __SOCKETS_TCPLISTENER_H__ 18 | #define __SOCKETS_TCPLISTENER_H__ 19 | 20 | /* Include all versions of the API */ 21 | #include "v0/TCPListener.h" 22 | 23 | /* Set the current namespace */ 24 | namespace mbed { 25 | namespace Sockets { 26 | namespace current { 27 | using namespace mbed::Sockets::v0; 28 | } 29 | } 30 | } 31 | 32 | #endif // __SOCKETS_TCPLISTENER_H__ 33 | -------------------------------------------------------------------------------- /sockets/TCPStream.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PackageLicenseDeclared: Apache-2.0 3 | * Copyright (c) 2015 ARM Limited 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | #ifndef __SOCKETS_TCPSTREAM_H__ 18 | #define __SOCKETS_TCPSTREAM_H__ 19 | 20 | /* Include all versions of the API */ 21 | #include "v0/TCPStream.h" 22 | 23 | /* Set the current namespace */ 24 | namespace mbed { 25 | namespace Sockets { 26 | namespace current { 27 | using namespace mbed::Sockets::v0; 28 | } 29 | } 30 | } 31 | 32 | #endif // __SOCKETS_TCPSTREAM_H__ 33 | -------------------------------------------------------------------------------- /sockets/UDPSocket.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PackageLicenseDeclared: Apache-2.0 3 | * Copyright (c) 2015 ARM Limited 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | #ifndef __SOCKETS_UDPSOCKET_H__ 18 | #define __SOCKETS_UDPSOCKET_H__ 19 | 20 | /* Include all versions of the API */ 21 | #include "v0/UDPSocket.h" 22 | 23 | /* Set the current namespace */ 24 | namespace mbed { 25 | namespace Sockets { 26 | namespace current { 27 | using namespace mbed::Sockets::v0; 28 | } 29 | } 30 | } 31 | 32 | #endif // __SOCKETS_UDPSOCKET_H__ 33 | -------------------------------------------------------------------------------- /sockets/v0/Socket.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PackageLicenseDeclared: Apache-2.0 3 | * Copyright (c) 2015 ARM Limited 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | #ifndef __SOCKETS_V0_SOCKET_H__ 18 | #define __SOCKETS_V0_SOCKET_H__ 19 | 20 | 21 | #include 22 | #include 23 | #include "mbed-drivers/mbed.h" 24 | #include "core-util/FunctionPointer.h" 25 | #include "mbed-drivers/CThunk.h" 26 | #include "sal/socket_types.h" 27 | #include "SocketAddr.h" 28 | 29 | namespace mbed { 30 | namespace Sockets { 31 | namespace v0 { 32 | 33 | /** 34 | * \brief Socket implements most of the interfaces required for sockets. 35 | * Socket is a pure virtual class; it should never be instantiated directly, but it provides 36 | * common functionality for derived classes. 37 | */ 38 | class Socket { 39 | public: 40 | typedef mbed::util::FunctionPointer3 DNSHandler_t; 41 | typedef mbed::util::FunctionPointer2 ErrorHandler_t; 42 | typedef mbed::util::FunctionPointer1 ReadableHandler_t; 43 | typedef mbed::util::FunctionPointer2 SentHandler_t; 44 | protected: 45 | /** 46 | * Socket constructor 47 | * Initializes the Socket object. Initializes the underlying struct socket. Does not instantiate 48 | * an underlying network stack socket. 49 | * Since it is somewhat awkward to provide the network stack, a future change will provide 50 | * a way to pass the network interface to the socket constructor, which will extract the stack from 51 | * the interface. 52 | * @param[in] stack The network stack to use for this socket. 53 | */ 54 | Socket(const socket_stack_t stack); 55 | 56 | /** 57 | * Socket destructor 58 | * Frees the underlying socket implementation. 59 | */ 60 | virtual ~Socket(); 61 | public: 62 | /** 63 | * Start the process of resolving a domain name. 64 | * If the input is a text IP address, an event is queued immediately; otherwise, onDNS is 65 | * queued as soon as DNS is resolved. 66 | * @param[in] address The domain name to resolve 67 | * @param[in] onDNS The handler to call when the name is resolved 68 | * @retval SOCKET_ERROR_NONE on success 69 | * @retval SOCKET_ERROR_NULL_PTR if address is NULL 70 | * @return Error code on failure 71 | */ 72 | virtual socket_error_t resolve(const char* address, const DNSHandler_t &onDNS); 73 | 74 | /** 75 | * Open the socket. 76 | * Instantiates and initializes the underlying socket. Receive is started immediately after 77 | * the socket is opened. 78 | * @param[in] af Address family (SOCKET_AF_INET4 or SOCKET_AF_INET6), currently only IPv4 is supported 79 | * @param[in] pf Protocol family (SOCKET_DGRAM or SOCKET_STREAM) 80 | * @retval SOCKET_ERROR_NONE on success 81 | * @retval SOCKET_ERROR_BAD_STACK if there is no valid underlying network stack 82 | * @retval SOCKET_ERROR_BAD_FAMILY if an invalid Address or Protocol family is supplied 83 | * @return Error code on failure 84 | */ 85 | virtual socket_error_t open(const socket_address_family_t af, const socket_proto_family_t pf); 86 | 87 | /** 88 | * Binds the socket's local address and IP. 89 | * 0.0.0.0 is accepted as a local address if only the port is meant to be bound. 90 | * The behaviour of bind("0.0.0.0",...) is undefined where two or more stacks are in use. 91 | * Specifying a port value of 0, will instruct the stack to allocate an available port 92 | * automatically. 93 | * 94 | * @param[in] address The string representation of the address to bind 95 | * @param[in] port The local port to bind 96 | * @retval SOCKET_ERROR_NONE on success 97 | * @retval SOCKET_ERROR_NULL_PTR if the socket has not been opened or the address is NULL 98 | * @return Error code on failure 99 | */ 100 | virtual socket_error_t bind(const char *address, const uint16_t port); 101 | 102 | /** 103 | * bind(const SocketAddr *, const uint16_t) is the same as bind(const char *, const uint16_t), 104 | * except that the address passed in is a SocketAddr. 105 | * @param[in] address The address to bind 106 | * @param[in] port The local port to bind 107 | * @retval SOCKET_ERROR_NONE on success 108 | * @retval SOCKET_ERROR_NULL_PTR if the supplied address is NULL 109 | * @return Error code on failure 110 | */ 111 | virtual socket_error_t bind(const SocketAddr *address, const uint16_t port); 112 | 113 | /** 114 | * Set the error handler. 115 | * Errors are ignored if onError is not set. 116 | * @param[in] onError 117 | */ 118 | virtual void setOnError(const ErrorHandler_t &onError); 119 | 120 | /** 121 | * Set the received data handler 122 | * Received data is queued until it is read using recv or recv_from. 123 | * @param[in] onReadable the handler to use for receive events 124 | */ 125 | virtual void setOnReadable(const ReadableHandler_t &onReadable); 126 | 127 | /** 128 | * Receive a message 129 | * @param[out] buf The buffer to fill 130 | * @param[in,out] len A pointer to the size of the receive buffer. Sets the maximum number of bytes 131 | * to read but is updated with the actual number of bytes copied on success. len is not changed on 132 | * failure 133 | * @retval SOCKET_ERROR_NONE on success 134 | * @retval SOCKET_ERROR_NULL_PTR if the socket has not been opened, buf is NULL or len is NULL 135 | * @return Error code on failure 136 | */ 137 | virtual socket_error_t recv(void * buf, size_t *len); 138 | 139 | /** 140 | * Receive a message with the sender address and port 141 | * This API is not valid for SOCK_STREAM 142 | * @param[out] buf The buffer to fill 143 | * @param[in,out] len A pointer to the size of the receive buffer. Sets the maximum number of bytes 144 | * to read but is updated with the actual number of bytes copied on success. len is not changed on 145 | * failure 146 | * @param[out] remote_addr Pointer to an address structure to fill with the sender address 147 | * @param[out] remote_port Pointer to a uint16_t to fill with the sender port 148 | * @retval SOCKET_ERROR_NONE on success 149 | * @retval SOCKET_ERROR_NULL_PTR if the socket has not been opened or any of the pointer arguments 150 | * are NULL 151 | * @return Error code on failure 152 | */ 153 | virtual socket_error_t recv_from(void * buf, size_t *len, SocketAddr *remote_addr, uint16_t *remote_port); 154 | 155 | /** 156 | * Set the onSent handler. 157 | * The exact moment this handler is called varies from implementation to implementation. 158 | * On LwIP, onSent is called when the remote host ACK's data in TCP sockets, or when the message enters 159 | * the network stack in UDP sockets. 160 | * @param[in] onSent The handler to call when a send completes 161 | */ 162 | virtual void setOnSent(const SentHandler_t &onSent); 163 | 164 | /** 165 | * Send a message 166 | * Sends a message over an open connection. This call is valid for UDP sockets, provided that connect() 167 | * has been called. 168 | * @param[in] buf The payload to send 169 | * @param[in] len The size of the payload 170 | * @retval SOCKET_ERROR_NONE on success 171 | * @retval SOCKET_ERROR_NULL_PTR if the socket has not been opened or buf is NULL 172 | * @return Error code on failure 173 | */ 174 | virtual socket_error_t send(const void * buf, const size_t len); 175 | 176 | /** 177 | * Send a message to a specific address and port 178 | * This API is not valid for SOCK_STREAM 179 | * @param[in] buf The payload to send 180 | * @param[in] len The size of the payload 181 | * @param[in] address The address to send to 182 | * @param[in] port The remote port to send to 183 | * @retval SOCKET_ERROR_NONE on success 184 | * @retval SOCKET_ERROR_NULL_PTR if the socket has not been opened, buf is NULL or the 185 | * remote_addr is NULL 186 | * @return Error code on failure 187 | */ 188 | virtual socket_error_t send_to(const void * buf, const size_t len, const SocketAddr *remote_addr, uint16_t remote_port); 189 | 190 | /** 191 | * Shuts down a socket. 192 | * Sending and receiving are no longer possible after close() is called. 193 | * The socket is not deallocated on close. A socket must not be reopened, it should be 194 | * destroyed (either with delete, or by going out of scope) after calling close. 195 | * Calling open on a closed socket can result in a memory leak. 196 | * @retval SOCKET_ERROR_NONE on success 197 | * @retval SOCKET_ERROR_NULL_PTR if the socket has not been opened 198 | * @return Error code on failure 199 | */ 200 | virtual socket_error_t close(); 201 | 202 | /** 203 | * Error checking utility 204 | * Generates an event on error, does nothing on SOCKET_ERROR_NONE 205 | * @param[in] err the error code to check 206 | * @return false if err is SOCKET_ERROR_NONE, true otherwise 207 | */ 208 | virtual bool error_check(socket_error_t err); 209 | 210 | /** 211 | * Checks the socket status to determine whether it is still connected. 212 | * @return true if the socket is connected, false if it is not 213 | */ 214 | virtual bool isConnected() const; 215 | 216 | /** 217 | * Get the local address of the socket if bound. 218 | * Populates the SocketAddr object with the local address 219 | * 220 | * @param[out] addr a pointer to a SocketAddr object 221 | * @retval SOCKET_ERROR_NONE on success 222 | * @retval SOCKET_ERROR_NULL_PTR if the socket has not been opened or the addr is NULL 223 | * @retval SOCKET_ERROR_NOT_BOUND if the socket has not been bound 224 | * @return Error code on failure 225 | */ 226 | virtual socket_error_t getLocalAddr(SocketAddr *addr) const; 227 | 228 | /** 229 | * Get the local port of the socket if bound. 230 | * Populates the uint16_t object with the local port 231 | * 232 | * @param[out] port a pointer to a uint16_t 233 | * @retval SOCKET_ERROR_NONE on success 234 | * @retval SOCKET_ERROR_NULL_PTR if the socket has not been opened or the port is NULL 235 | * @retval SOCKET_ERROR_NOT_BOUND if the socket has not been bound 236 | * @return Error code on failure 237 | */ 238 | virtual socket_error_t getLocalPort(uint16_t *port) const; 239 | 240 | /** 241 | * Get the remote address of the socket if connected. 242 | * Populates the SocketAddr object with the remote address 243 | * 244 | * @param[out] addr a pointer to a SocketAddr object 245 | * @retval SOCKET_ERROR_NONE on success 246 | * @retval SOCKET_ERROR_NULL_PTR if the socket has not been opened or the addr is NULL 247 | * @retval SOCKET_ERROR_NO_CONNECTION if the socket has not been connected 248 | * @return Error code on failure 249 | */ 250 | virtual socket_error_t getRemoteAddr(SocketAddr *addr) const; 251 | 252 | /** 253 | * Get the remote port of the socket if connected. 254 | * Populates the uint16_t object with the remote port 255 | * 256 | * @param[out] port a pointer to a uint16_t 257 | * @retval SOCKET_ERROR_NONE on success 258 | * @retval SOCKET_ERROR_NULL_PTR if the socket has not been opened or the port is NULL 259 | * @retval SOCKET_ERROR_NO_CONNECTION if the socket has not been connected 260 | * @return Error code on failure 261 | */ 262 | virtual socket_error_t getRemotePort(uint16_t *port) const; 263 | 264 | #if 0 // not implemented yet 265 | static long ntohl(long); 266 | static short ntohs(short); 267 | static long long ntohll(long long); 268 | #endif 269 | 270 | protected: 271 | /** \internal 272 | * The internal event handler 273 | * @param[in] ev The event to handle 274 | */ 275 | virtual void _eventHandler(struct socket_event *ev); 276 | 277 | protected: 278 | /** Function pointer to the user-supplied DNS response handling function 279 | * \internal 280 | * This function pointer is called every time a DNS response is received. 281 | * If the function pointer is false when cast to a boolean, DNS events are discarded. 282 | */ 283 | DNSHandler_t _onDNS; 284 | /** Function pointer to the user-supplied error handling function 285 | * \internal 286 | * This function pointer is called when an error condition is encountered in a part 287 | * of the code which does not have a direct call path back to user-supplied code 288 | * If NULL, error handling is discarded. 289 | */ 290 | ErrorHandler_t _onError; 291 | /** Function pointer to the user-supplied data available handling function 292 | 293 | * This function pointer is called when data is available on the socket. It is called once for 294 | * each event generated by the socket layer, so partial reads can leave data available on the 295 | * socket and greedy reads can cause extra events with no data to read. 296 | * Suggested handling is to use greedy reads and terminate early in events with no */ 297 | ReadableHandler_t _onReadable; ///< Function pointer to the user-supplied socket readable function 298 | SentHandler_t _onSent; 299 | 300 | CThunk _irq; 301 | public: 302 | struct socket _socket; 303 | private: 304 | socket_event_t *_event; 305 | /** 306 | * Internal event handler. 307 | * @param[in] arg 308 | */ 309 | void _nvEventHandler(void * arg); 310 | }; 311 | } // namespace v0 312 | } // namespace Sockets 313 | } // namespace mbed 314 | #endif // __SOCKETS_V0_SOCKET_H__ 315 | -------------------------------------------------------------------------------- /sockets/v0/SocketAddr.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PackageLicenseDeclared: Apache-2.0 3 | * Copyright (c) 2015 ARM Limited 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | #ifndef __SOCKETS_V0_SOCKETADDR_H__ 18 | #define __SOCKETS_V0_SOCKETADDR_H__ 19 | 20 | #include "sal/socket_types.h" 21 | 22 | namespace mbed { 23 | namespace Sockets { 24 | namespace v0 { 25 | 26 | /** 27 | * SocketAddr is a container class for storing IP addresses. 28 | * 29 | * SocketAddr provides a common interface for setting and getting IP addresses 30 | * 31 | * When an IPv4 address is set, SocketAddr stores it in IPv4-mapped IPv6. It is assumed that any address in the 32 | * ::ffff:0000:0000 address range should be treated as an IPv4 address. 33 | */ 34 | class SocketAddr { 35 | public: 36 | /** 37 | * Get a pointer to the internal struct socket_addr storage 38 | * 39 | * @return The address of the internal struct 40 | */ 41 | struct socket_addr * getAddr() {return &_addr;} 42 | /** 43 | * Get a const pointer to the internal struct socket_addr storage 44 | * 45 | * @return The address of the internal struct 46 | */ 47 | const struct socket_addr * getAddr() const {return &_addr;} 48 | /** 49 | * Copy the contents of an existing struct socket_addr into the internal storage 50 | * 51 | * @param[in] addr the original address to copy 52 | */ 53 | void setAddr(const struct socket_addr *addr); 54 | /** 55 | * Copy the contents of an existing SocketAddr into the internal storage 56 | * 57 | * @param[in] addr the original address to copy 58 | */ 59 | void setAddr(const SocketAddr *addr); 60 | 61 | /** 62 | * Parse a string representation of the address into the SocketAddr 63 | * 64 | * This function uses inet_pton and has the restrictions expected with that API. 65 | * 66 | * @param[in] addr the original address to copy 67 | * @retval SOCKET_ERROR_NONE Format completed 68 | * @retval SOCKET_ERROR_BAD_ADDRESS Unrecognized address format 69 | * @retval SOCKET_ERROR_BAD_ARGUMENT An unexpected argument was provided 70 | * @retval SOCKET_ERROR_UNKNOWN An unexpected error occurred 71 | */ 72 | socket_error_t setAddr(socket_address_family_t af, const char *addr); 73 | /** 74 | * Return the size of the internal storage. 75 | * 76 | * @return the space consumed by a SocketAddr 77 | */ 78 | size_t getAddrSize() const {return sizeof(_addr.ipv6be);} 79 | /** 80 | * Check if the internal address is an IPv4 address 81 | * This checks if the address falls in the `::ffff:0000:0000` range. 82 | * 83 | * @retval true the IP address is IPv4 84 | * @retval false otherwise 85 | */ 86 | bool is_v4() const; 87 | 88 | /** 89 | * Format the IP address in IPv4 dotted-quad Format 90 | * 91 | * @param[out] buf the buffer to fill 92 | * @param[in] size the size of the buffer to fill. Must be at least 16 chars long (incl. terminator). 93 | * 94 | * @retval -1 error formatting 95 | * @retval 0 format successful 96 | */ 97 | int fmtIPv4(char *buf, size_t size) const; 98 | /// Convenience function for using statically allocated buffers. 99 | template< size_t N > 100 | int fmtIPv4(char (&buf)[N]) { 101 | return fmtIPv4(buf, N); 102 | } 103 | 104 | /** 105 | * Format the IP address in IPv6 colon separated format 106 | * 107 | * If the IP address is IPv6, colon-separated format is used. 108 | * If the IP address is IPv4, then the address is formatted as a 96-bit prefix in colon-separated format, followed 109 | * by a 32-bit dotted-quad. 110 | * 111 | * 112 | * @param[out] buf the buffer to fill 113 | * @param[in] size the size of the buffer to fill. 114 | * Must be at least 23 chars long (incl. terminator) for an IPv4 address in IPv6 format. 115 | * Must be at least 46 chars long for a complete IPv6 address. Smaller buffers may be used 116 | * for abbreviated addresses, such as ::1 117 | * 118 | * @retval 0 formatting was successful 119 | * @retval -1 formatting failed 120 | */ 121 | int fmtIPv6(char *buf, size_t size) const; 122 | /// Convenience function for using statically allocated buffers. 123 | template< size_t N > 124 | int fmtIPv6(char (&buf)[N]) { 125 | return fmtIPv6(buf, N); 126 | } 127 | protected: 128 | struct socket_addr _addr; 129 | }; 130 | } // namespace v0 131 | } // namespace Sockets 132 | } // namespace mbed 133 | #endif // __SOCKETS_V0_SOCKETADDR_H__ 134 | -------------------------------------------------------------------------------- /sockets/v0/TCPAsynch.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PackageLicenseDeclared: Apache-2.0 3 | * Copyright (c) 2015 ARM Limited 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | #ifndef __MBED_NET_SOCKETS_V0_TCP_ASYNCH__ 18 | #define __MBED_NET_SOCKETS_V0_TCP_ASYNCH__ 19 | 20 | #include "Socket.h" 21 | #include "sal/socket_api.h" 22 | 23 | #include "minar/minar.h" 24 | 25 | namespace mbed { 26 | namespace Sockets { 27 | namespace v0 { 28 | class TCPAsynch: public Socket { 29 | protected: 30 | TCPAsynch(const socket_stack_t stack); 31 | ~TCPAsynch(); 32 | 33 | public: 34 | 35 | /** 36 | * Open the socket. 37 | * Instantiates and initializes the underlying socket. Receive is started immediately after 38 | * the socket is opened. 39 | * @param[in] af Address family (SOCKET_AF_INET4 or SOCKET_AF_INET6), currently only IPv4 is supported 40 | * @retval SOCKET_ERROR_NONE on success 41 | * @retval SOCKET_ERROR_BAD_STACK if there is no valid underlying network stack 42 | * @retval SOCKET_ERROR_BAD_FAMILY if an invalid Address is supplied 43 | * @return Error code on failure 44 | */ 45 | virtual socket_error_t open(const socket_address_family_t af); 46 | 47 | protected: 48 | static minar::callback_handle_t _tick_handle; 49 | // uintptr_t is used to guarantee that there will always be a large enough 50 | // counter to avoid overflows. Memory allocation will always fail before 51 | // counter overflow if the counter is the same size as the pointer type and 52 | // sizeof(TCPAsynch) > 0 53 | static uintptr_t _TCPSockets; 54 | private: 55 | socket_error_t open(const socket_address_family_t af, const socket_proto_family_t pf); 56 | }; 57 | } // namespace v0 58 | } // namespace Sockets 59 | } // namespace mbed 60 | #endif // __MBED_NET_SOCKETS_V0_TCP_ASYNCH__ 61 | -------------------------------------------------------------------------------- /sockets/v0/TCPListener.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PackageLicenseDeclared: Apache-2.0 3 | * Copyright (c) 2015 ARM Limited 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | #ifndef __SOCKETS_V0_TCPLISTENER_H__ 18 | #define __SOCKETS_V0_TCPLISTENER_H__ 19 | 20 | #include 21 | #include 22 | #include "core-util/FunctionPointer.h" 23 | #include "TCPAsynch.h" 24 | #include "TCPStream.h" 25 | 26 | namespace mbed { 27 | namespace Sockets { 28 | namespace v0 { 29 | /** \brief TCPListener: a TCP server socket 30 | * The TCPListener listens for incoming connections. Prior to listening, the 31 | * TCPListener must be bound to a port and, optionally, an address. 32 | */ 33 | class TCPListener: public TCPAsynch { 34 | public: 35 | typedef mbed::util::FunctionPointer2 IncomingHandler_t; 36 | /** 37 | * The TCP Listener constructor. 38 | * @param[in] stack the network stack to use 39 | */ 40 | TCPListener(const socket_stack_t stack); 41 | 42 | /** 43 | * The TCP Listener destructor 44 | * This performs teardown of the listener 45 | */ 46 | ~TCPListener(); 47 | 48 | /** 49 | * Begin listening for incoming connections. 50 | * The supplied listenHandler will be called whenever an incoming connection arrives 51 | * To reject a connection, the event handler needs to set the reject flag in the event. 52 | * @param[in] listenHandler The event handler to call when an incoming connection arrives 53 | * @param[in] backlog The number of connection requests to keep in the backlog 54 | * @retval SOCKET_ERROR_NONE on success 55 | * @return Error code on failure 56 | */ 57 | socket_error_t start_listening(IncomingHandler_t listenHandler, uint32_t backlog = 0); 58 | /** 59 | * Stop listening for incoming connections 60 | * After this call, the server will reject incoming connections until start_listening is called again 61 | * @retval SOCKET_ERROR_NONE on success 62 | * @return Error code on failure 63 | */ 64 | socket_error_t stop_listening(); 65 | 66 | /** 67 | * accept is a utility function for constructing a new TCPStream from an incoming connection 68 | * The event passed to the listenHandler contains a pointer to a low level implementation of an 69 | * already connected socket. This function 70 | * @param new_impl 71 | * @return 72 | */ 73 | virtual TCPStream * accept(void *new_impl); 74 | virtual void reject(void *new_impl); 75 | 76 | protected: 77 | /** 78 | * Internal event handler 79 | * @param[in] ev the event to handle 80 | */ 81 | void _eventHandler(struct socket_event *ev); 82 | 83 | IncomingHandler_t _onIncoming; 84 | }; 85 | } // namespace v0 86 | } // namespace Sockets 87 | } // namespace mbed 88 | #endif // __SOCKETS_V0_TCPLISTENER_H__ 89 | -------------------------------------------------------------------------------- /sockets/v0/TCPStream.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PackageLicenseDeclared: Apache-2.0 3 | * Copyright (c) 2015 ARM Limited 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | #ifndef __SOCKETS_V0_TCPSTREAM_H__ 18 | #define __SOCKETS_V0_TCPSTREAM_H__ 19 | #include 20 | #include 21 | #include "TCPAsynch.h" 22 | 23 | namespace mbed { 24 | namespace Sockets { 25 | namespace v0 { 26 | 27 | class TCPStream: public TCPAsynch { 28 | public: 29 | typedef mbed::util::FunctionPointer1 ConnectHandler_t; 30 | typedef mbed::util::FunctionPointer1 DisconnectHandler_t; 31 | /** 32 | * TCP socket constructor. 33 | * Does not allocate an underlying TCP Socket instance. 34 | * @param[in] stack The network stack to use for this socket. 35 | */ 36 | TCPStream(const socket_stack_t stack); 37 | /** 38 | * TCP socket constructor. 39 | * Does not allocate an underlying TCP Socket instance. This version is for use with 40 | * TCPListener::accept(). The struct socket instance passed into this constructor should 41 | * be a fully initialized socket, with an initialized impl field. TCPStream will copy 42 | * the stack, API, protocol family, and impl pointer from sock. 43 | * @param[in] sock The TCP socket instance to use for this TCP socket. 44 | */ 45 | __deprecated TCPStream(const struct socket * sock); 46 | 47 | /** 48 | * TCP socket constructor. 49 | * Does not allocate an underlying TCP Socket instance. This version is for use with 50 | * TCPListener::accept(). The struct socket instance passed into this constructor should 51 | * be a fully initialized socket, with an initialized impl field. TCPStream will copy 52 | * the stack, API, protocol family, and impl pointer from sock. 53 | * 54 | * @param[in,out] listener The TCP socket instance that accepted the new socket. 55 | * @param[in] sock The TCP socket instance to use for this TCP socket. 56 | * @param[out] err The result of the call to accept. 57 | */ 58 | TCPStream(struct socket* listener, const struct socket *sock, socket_error_t &err); 59 | 60 | /** 61 | * TCP socket destructor 62 | */ 63 | ~TCPStream(); 64 | /** 65 | * Connect to a remote host. 66 | * Initates the TCP Connection process. onConnect is called when the connection 67 | * is acknowledged. 68 | * @param[in] address The remote host to connect to 69 | * @param[in] port The remote port to connect to 70 | * @param[in] onConnect 71 | * @retval SOCKET_ERROR_NONE on success 72 | * @return Error code on failure 73 | */ 74 | virtual socket_error_t connect(const SocketAddr &address, const uint16_t port, 75 | const ConnectHandler_t &onConnect); 76 | /** 77 | * Set a disconnect handler 78 | * This handler only needs to be configured once onConnect has been called 79 | * @param[in] h the handler to call when a connection is disconnected 80 | */ 81 | virtual void setOnDisconnect(const DisconnectHandler_t &h) { _onDisconnect = h; } 82 | 83 | /** 84 | * Enable Nagle's algorithm 85 | * Nagle's algorithm groups small packets together for more efficient transmission 86 | * on TCP sockets. Sometimes, this is undesirable, since it can introduce latency between 87 | * putting data in the send queue and it actually sending. 88 | * 89 | * @param[in] enable when true, enable the nagle algorithm, when false, disable it. 90 | */ 91 | virtual void setNagle(bool enable); 92 | 93 | protected: 94 | /** 95 | * Internal event handler 96 | * @param[in] ev the event to handle 97 | */ 98 | void _eventHandler(struct socket_event *ev); 99 | 100 | protected: 101 | ConnectHandler_t _onConnect; 102 | DisconnectHandler_t _onDisconnect; 103 | }; 104 | } // namespace v0 105 | } // namespace Sockets 106 | } // namespace mbed 107 | #endif // __SOCKETS_V0_TCPSTREAM_H__ 108 | -------------------------------------------------------------------------------- /sockets/v0/UDPSocket.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PackageLicenseDeclared: Apache-2.0 3 | * Copyright (c) 2015 ARM Limited 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | #ifndef __SOCKETS_V0_UDPSOCKET_H__ 18 | #define __SOCKETS_V0_UDPSOCKET_H__ 19 | 20 | #include 21 | #include 22 | #include "Socket.h" 23 | 24 | namespace mbed { 25 | namespace Sockets { 26 | namespace v0 { 27 | 28 | /* UDP socket class */ 29 | class UDPSocket: public Socket { 30 | public: 31 | /** 32 | * UDP socket constructor. 33 | * Does not allocate an underlying UDP Socket instance. 34 | * @param[in] stack The network stack to use for this socket. 35 | */ 36 | UDPSocket(socket_stack_t stack); 37 | /** 38 | * UDP Socket destructor 39 | */ 40 | ~UDPSocket(); 41 | /** 42 | * Open a UDP socket 43 | * Instantiates and initializes the underlying socket. Receive is started immediately after 44 | * the socket is opened. 45 | * @param[in] af Address family (SOCKET_AF_INET4 or SOCKET_AF_INET6), currently only IPv4 is supported 46 | * @retval SOCKET_ERROR_NONE on success 47 | * @retval SOCKET_ERROR_BAD_FAMILY if an invalid Address is supplied 48 | * @return Error code on failure 49 | */ 50 | socket_error_t inline open(const socket_address_family_t af) 51 | { 52 | return Socket::open(af,SOCKET_DGRAM); 53 | } 54 | /** 55 | * Connect to a remote host. 56 | * This is an internal configuration API only. No network traffic is generated. 57 | * @param[in] address The remote host to connect to 58 | * @param[in] port The remote port to connect to 59 | * @retval SOCKET_ERROR_NONE on success 60 | * @retval SOCKET_ERROR_NULL_PTR if address is NULL 61 | * @return Error code on failure 62 | */ 63 | socket_error_t connect(const SocketAddr *address, const uint16_t port); 64 | private: 65 | socket_error_t open(const socket_address_family_t af, const socket_proto_family_t pf); 66 | 67 | }; 68 | } // namespace v0 69 | } // namespace Sockets 70 | } // namespace mbed 71 | #endif // __SOCKETS_V0_UDPSOCKET_H__ 72 | -------------------------------------------------------------------------------- /source/v0/Socket.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * PackageLicenseDeclared: Apache-2.0 3 | * Copyright (c) 2015 ARM Limited 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | #include "sockets/v0/Socket.h" 18 | #include "minar/minar.h" 19 | #include "sal/socket_api.h" 20 | #include "cmsis.h" 21 | 22 | using namespace mbed::Sockets::v0; 23 | 24 | Socket::Socket(const socket_stack_t stack) : 25 | _onDNS(NULL), _onError(NULL), _onReadable(NULL), _onSent(NULL), 26 | _irq(this), _event(NULL) 27 | { 28 | _irq.callback(&Socket::_nvEventHandler); 29 | _socket.handler = (socket_api_handler_t)_irq.entry(); 30 | _socket.impl = NULL; 31 | _socket.stack = stack; 32 | _socket.api = socket_get_api(stack); 33 | } 34 | 35 | Socket::~Socket() 36 | { 37 | if(_socket.api != NULL && _socket.api->destroy != NULL) { 38 | socket_error_t err = _socket.api->destroy(&_socket); 39 | error_check(err); 40 | } 41 | } 42 | 43 | socket_error_t Socket::open(const socket_address_family_t af, const socket_proto_family_t pf) 44 | { 45 | if (_socket.api == NULL) { 46 | return SOCKET_ERROR_BAD_STACK; 47 | } 48 | return _socket.api->create(&_socket, af, pf, (socket_api_handler_t)_irq.entry()); 49 | } 50 | 51 | 52 | bool Socket::error_check(socket_error_t err) 53 | { 54 | if (err == SOCKET_ERROR_NONE) { 55 | return false; 56 | } 57 | minar::Scheduler::postCallback(_onError.bind(this, err)); 58 | // If there is an error, schedule an error event. 59 | return true; 60 | } 61 | 62 | void Socket::_eventHandler(struct socket_event *ev) 63 | { 64 | switch(ev->event) { 65 | case SOCKET_EVENT_RX_ERROR: 66 | case SOCKET_EVENT_TX_ERROR: 67 | case SOCKET_EVENT_ERROR: 68 | if (_onError) 69 | minar::Scheduler::postCallback(_onError.bind(this, ev->i.e)); 70 | break; 71 | case SOCKET_EVENT_RX_DONE: 72 | if(_onReadable) 73 | minar::Scheduler::postCallback(_onReadable.bind(this)); 74 | break; 75 | case SOCKET_EVENT_TX_DONE: 76 | if (_onSent) 77 | minar::Scheduler::postCallback(_onSent.bind(this, ev->i.t.sentbytes)); 78 | break; 79 | case SOCKET_EVENT_DNS: 80 | if (_onDNS) 81 | minar::Scheduler::postCallback(_onDNS.bind(this, ev->i.d.addr, ev->i.d.domain)); 82 | break; 83 | case SOCKET_EVENT_CONNECT: 84 | case SOCKET_EVENT_DISCONNECT: 85 | case SOCKET_EVENT_ACCEPT: 86 | case SOCKET_EVENT_NONE: 87 | default: 88 | break; 89 | } 90 | } 91 | 92 | void Socket::setOnError(const ErrorHandler_t &onError) 93 | { 94 | __disable_irq(); 95 | _onError = onError; 96 | __enable_irq(); 97 | } 98 | void Socket::setOnReadable(const ReadableHandler_t &onReadable) 99 | { 100 | __disable_irq(); 101 | _onReadable = onReadable; 102 | __enable_irq(); 103 | } 104 | void Socket::setOnSent(const SentHandler_t &onSent) 105 | { 106 | __disable_irq(); 107 | _onSent = onSent; 108 | __enable_irq(); 109 | } 110 | 111 | void Socket::_nvEventHandler(void * arg) 112 | { 113 | (void) arg; 114 | // Extract the event 115 | _event = _socket.event; // TODO: (CThunk upgrade/Alpha3) 116 | // Call the event handler 117 | _eventHandler(_event); 118 | _event = NULL; // TODO: (CThunk upgrade/Alpha3) 119 | } 120 | 121 | socket_error_t Socket::resolve(const char* address, const DNSHandler_t &onDNS) 122 | { 123 | if (_socket.impl == NULL) { 124 | return SOCKET_ERROR_NULL_PTR; 125 | } 126 | if (_socket.handler == NULL) { 127 | return SOCKET_ERROR_CLOSED; 128 | } 129 | _onDNS = onDNS; 130 | socket_error_t err = _socket.api->resolve(&_socket, address); 131 | return err; 132 | } 133 | 134 | socket_error_t Socket::bind(const char * addr, const uint16_t port) 135 | { 136 | SocketAddr tmp; 137 | if (_socket.impl == NULL) { 138 | return SOCKET_ERROR_NULL_PTR; 139 | } 140 | socket_error_t err = _socket.api->str2addr(&_socket, tmp.getAddr(), addr); 141 | if (err != SOCKET_ERROR_NONE) { 142 | return err; 143 | } 144 | return bind(&tmp, port); 145 | } 146 | socket_error_t Socket::bind(const SocketAddr * addr, const uint16_t port) 147 | { 148 | socket_error_t err; 149 | if (addr == NULL) { 150 | return SOCKET_ERROR_NULL_PTR; 151 | } 152 | 153 | if (_socket.impl == NULL) 154 | { 155 | err = open(SOCKET_AF_INET4,(socket_proto_family_t) _socket.family); 156 | if (err != SOCKET_ERROR_NONE) { 157 | return err; 158 | } 159 | } 160 | err = _socket.api->bind(&_socket, addr->getAddr(), port); 161 | return err; 162 | } 163 | 164 | socket_error_t Socket::close() 165 | { 166 | if (_socket.impl == NULL) { 167 | return SOCKET_ERROR_NULL_PTR; 168 | } 169 | return _socket.api->close(&_socket); 170 | } 171 | 172 | socket_error_t Socket::recv(void * buf, size_t *len) 173 | { 174 | if (_socket.impl == NULL) { 175 | return SOCKET_ERROR_NULL_PTR; 176 | } 177 | return _socket.api->recv(&_socket, buf, len); 178 | } 179 | socket_error_t Socket::recv_from(void * buf, size_t *len, SocketAddr *remote_addr, uint16_t *remote_port) 180 | { 181 | struct socket_addr addr; 182 | if (_socket.impl == NULL || remote_addr == NULL) { 183 | return SOCKET_ERROR_NULL_PTR; 184 | } 185 | socket_error_t err = _socket.api->recv_from(&_socket, buf, len, &addr, remote_port); 186 | remote_addr->setAddr(&addr); 187 | return err; 188 | } 189 | 190 | socket_error_t Socket::send(const void * buf, const size_t len) 191 | { 192 | if (_socket.impl == NULL) { 193 | return SOCKET_ERROR_NULL_PTR; 194 | } 195 | return _socket.api->send(&_socket, buf, len); 196 | } 197 | 198 | socket_error_t Socket::send_to(const void * buf, const size_t len, const SocketAddr *remote_addr, uint16_t remote_port) 199 | { 200 | if (_socket.impl == NULL || remote_addr == NULL) { 201 | return SOCKET_ERROR_NULL_PTR; 202 | } 203 | return _socket.api->send_to(&_socket, buf, len, remote_addr->getAddr(), remote_port); 204 | } 205 | 206 | bool Socket::isConnected() const { 207 | if (_socket.impl == NULL) { 208 | return false; 209 | } 210 | return _socket.api->is_connected(&_socket); 211 | } 212 | 213 | socket_error_t Socket::getLocalAddr(SocketAddr *addr) const 214 | { 215 | if (_socket.impl == NULL || addr == NULL) { 216 | return SOCKET_ERROR_NULL_PTR; 217 | } 218 | return _socket.api->get_local_addr(&_socket, addr->getAddr()); 219 | } 220 | socket_error_t Socket::getLocalPort(uint16_t *port) const 221 | { 222 | if (_socket.impl == NULL) { 223 | return SOCKET_ERROR_NULL_PTR; 224 | } 225 | return _socket.api->get_local_port(&_socket, port); 226 | } 227 | socket_error_t Socket::getRemoteAddr(SocketAddr *addr) const 228 | { 229 | if (_socket.impl == NULL || addr == NULL) { 230 | return SOCKET_ERROR_NULL_PTR; 231 | } 232 | return _socket.api->get_remote_addr(&_socket, addr->getAddr()); 233 | } 234 | socket_error_t Socket::getRemotePort(uint16_t *port) const 235 | { 236 | if (_socket.impl == NULL) { 237 | return SOCKET_ERROR_NULL_PTR; 238 | } 239 | return _socket.api->get_remote_port(&_socket, port); 240 | } 241 | -------------------------------------------------------------------------------- /source/v0/SocketAddr.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * PackageLicenseDeclared: Apache-2.0 3 | * Copyright (c) 2015 ARM Limited 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | #include 18 | #include 19 | 20 | #include "sockets/v0/SocketAddr.h" 21 | #include "sal/socket_api.h" 22 | 23 | using namespace mbed::Sockets::v0; 24 | 25 | void SocketAddr::setAddr(const struct socket_addr *addr) { 26 | socket_addr_copy(&_addr, addr); 27 | } 28 | void SocketAddr::setAddr(const SocketAddr *addr) { 29 | setAddr(addr->getAddr()); 30 | } 31 | socket_error_t SocketAddr::setAddr(socket_address_family_t af, const char *addr) { 32 | int rc = inet_pton(af, addr, &_addr); 33 | // Convert from inet_pton return codes to -1/0 34 | switch (rc) { 35 | case 1: 36 | return SOCKET_ERROR_NONE; 37 | case 0: 38 | return SOCKET_ERROR_BAD_ADDRESS; 39 | case -1: 40 | return SOCKET_ERROR_BAD_ARGUMENT; 41 | default: 42 | return SOCKET_ERROR_UNKNOWN; 43 | } 44 | } 45 | 46 | bool SocketAddr::is_v4() const { 47 | return socket_addr_is_ipv4(&_addr); 48 | } 49 | 50 | // Returns 0 on success 51 | int SocketAddr::fmtIPv4(char *buf, size_t size) const 52 | { 53 | if (!is_v4()){ 54 | return -1; 55 | } 56 | if (buf == NULL) { 57 | return -1; 58 | } 59 | char * ptr = inet_ntop(SOCKET_AF_INET4, &(_addr.ipv6be[3]), buf, size); 60 | return (ptr == NULL)?-1:0; 61 | } 62 | int SocketAddr::fmtIPv6(char *buf, size_t size) const 63 | { 64 | if (buf == NULL) { 65 | return -1; 66 | } 67 | char * ptr = inet_ntop(SOCKET_AF_INET6, &_addr, buf, size); 68 | return (ptr == NULL)?-1:0; 69 | } 70 | -------------------------------------------------------------------------------- /source/v0/TCPAsynch.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * PackageLicenseDeclared: Apache-2.0 3 | * Copyright (c) 2015 ARM Limited 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "minar/minar.h" 19 | #include "sockets/v0/TCPAsynch.h" 20 | #include "sal/socket_api.h" 21 | 22 | using namespace mbed::Sockets::v0; 23 | 24 | uintptr_t TCPAsynch::_TCPSockets = 0; 25 | minar::callback_handle_t TCPAsynch::_tick_handle(nullptr); 26 | 27 | TCPAsynch::TCPAsynch(const socket_stack_t stack) : 28 | Socket(stack) 29 | { 30 | _socket.family = SOCKET_STREAM; 31 | if (_TCPSockets == 0) { 32 | if (_socket.api != NULL){ 33 | 34 | uint32_t timeout = _socket.api->periodic_interval(&_socket); 35 | void (*f)() = _socket.api->periodic_task(&_socket); 36 | _tick_handle = minar::Scheduler::postCallback(f).period(minar::milliseconds(timeout)).tolerance(timeout/2).getHandle(); 37 | } 38 | } 39 | _TCPSockets++; 40 | } 41 | socket_error_t TCPAsynch::open(const socket_address_family_t af) 42 | { 43 | socket_error_t err = Socket::open(af, SOCKET_STREAM); 44 | return err; 45 | } 46 | 47 | socket_error_t TCPAsynch::open(const socket_address_family_t af, const socket_proto_family_t pf) 48 | { 49 | (void)af; 50 | (void)pf; 51 | return SOCKET_ERROR_UNIMPLEMENTED; 52 | } 53 | 54 | TCPAsynch::~TCPAsynch() 55 | { 56 | _TCPSockets--; 57 | if (_TCPSockets == 0 && _tick_handle != nullptr) { 58 | minar::Scheduler::cancelCallback(_tick_handle); 59 | _tick_handle = nullptr; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /source/v0/TCPListener.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * PackageLicenseDeclared: Apache-2.0 3 | * Copyright (c) 2015 ARM Limited 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "sockets/v0/TCPListener.h" 19 | #include "sockets/v0/TCPStream.h" 20 | #include "sal/socket_api.h" 21 | #include "minar/minar.h" 22 | 23 | using namespace mbed::Sockets::v0; 24 | 25 | 26 | TCPListener::TCPListener(const socket_stack_t stack) : 27 | TCPAsynch(stack), _onIncoming(NULL) 28 | { 29 | } 30 | TCPListener::~TCPListener() 31 | { 32 | stop_listening(); 33 | } 34 | 35 | socket_error_t TCPListener::start_listening(IncomingHandler_t listenHandler, uint32_t backlog) 36 | { 37 | if (_socket.api == NULL) { 38 | return SOCKET_ERROR_BAD_STACK; 39 | } 40 | 41 | _onIncoming = listenHandler; 42 | 43 | socket_error_t err = _socket.api->start_listen(&_socket, backlog); 44 | return err; 45 | } 46 | socket_error_t TCPListener::stop_listening() 47 | { 48 | if (_socket.api == NULL) { 49 | return SOCKET_ERROR_BAD_STACK; 50 | } 51 | socket_error_t err = _socket.api->stop_listen(&_socket); 52 | return err; 53 | } 54 | TCPStream * TCPListener::accept(void *new_impl) 55 | { 56 | struct socket new_socket = _socket; 57 | new_socket.impl = new_impl; 58 | new_socket.stack = _socket.stack; 59 | new_socket.family = _socket.family; 60 | socket_error_t err; 61 | TCPStream * stream = new TCPStream(&_socket, &new_socket, err); 62 | if(err != SOCKET_ERROR_NONE) { 63 | delete stream; 64 | return NULL; 65 | } 66 | return stream; 67 | } 68 | void TCPListener::reject(void * impl) 69 | { 70 | //TODO: Add support for reject 71 | struct socket s; 72 | s.impl = impl; 73 | s.stack = _socket.stack; 74 | s.api = _socket.api; 75 | s.family = _socket.family; 76 | s.api->close(&s); 77 | } 78 | 79 | void TCPListener::_eventHandler(struct socket_event *ev) 80 | { 81 | switch(ev->event) { 82 | case SOCKET_EVENT_RX_ERROR: 83 | case SOCKET_EVENT_TX_ERROR: 84 | case SOCKET_EVENT_ERROR: 85 | if (_onError) 86 | minar::Scheduler::postCallback(_onError.bind(this, ev->i.e)); 87 | break; 88 | case SOCKET_EVENT_RX_DONE: 89 | case SOCKET_EVENT_TX_DONE: 90 | case SOCKET_EVENT_CONNECT: 91 | case SOCKET_EVENT_DISCONNECT: 92 | if(_onError) 93 | minar::Scheduler::postCallback(_onError.bind(this, SOCKET_ERROR_UNIMPLEMENTED)); 94 | break; 95 | case SOCKET_EVENT_DNS: 96 | if (_onDNS) 97 | minar::Scheduler::postCallback(_onDNS.bind(this, ev->i.d.addr, ev->i.d.domain)); 98 | break; 99 | case SOCKET_EVENT_ACCEPT: 100 | if (_onIncoming) 101 | minar::Scheduler::postCallback(_onIncoming.bind(this, ev->i.a.newimpl)); 102 | //TODO: write reject API 103 | break; 104 | case SOCKET_EVENT_NONE: 105 | default: 106 | break; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /source/v0/TCPStream.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * PackageLicenseDeclared: Apache-2.0 3 | * Copyright (c) 2015 ARM Limited 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | #include "sockets/v0/TCPStream.h" 18 | #include "sockets/v0/SocketAddr.h" 19 | #include "sal/socket_api.h" 20 | #include "minar/minar.h" 21 | 22 | using namespace mbed::Sockets::v0; 23 | 24 | TCPStream::TCPStream(const socket_stack_t stack) : 25 | /* Store the default handler */ 26 | TCPAsynch(stack), 27 | /* Zero the handlers */ 28 | _onConnect(NULL), _onDisconnect(NULL) 29 | { 30 | /* NOTE: _socket is initialized by TCPAsynch. */ 31 | } 32 | TCPStream::TCPStream(const struct socket *sock) : 33 | /* Store the default handler */ 34 | TCPAsynch(sock->stack), 35 | /* Zero the handlers */ 36 | _onConnect(NULL), _onDisconnect(NULL) 37 | { 38 | _socket.family = sock->family; 39 | _socket.impl = sock->impl; 40 | socket_error_t err = _socket.api->accept(&_socket, reinterpret_cast(_irq.entry())); 41 | error_check(err); 42 | } 43 | TCPStream::TCPStream(struct socket* listener, const struct socket *sock, socket_error_t &err) : 44 | /* Store the default handler */ 45 | TCPAsynch(sock->stack), 46 | /* Zero the handlers */ 47 | _onConnect(NULL), _onDisconnect(NULL) 48 | { 49 | _socket.family = sock->family; 50 | _socket.impl = sock->impl; 51 | 52 | err = socket_accept(listener, &_socket, 53 | reinterpret_cast(_irq.entry())); 54 | } 55 | 56 | TCPStream::~TCPStream() 57 | { 58 | } 59 | socket_error_t TCPStream::connect(const SocketAddr &address, const uint16_t port, const ConnectHandler_t &onConnect) 60 | { 61 | if (_socket.api == NULL){ 62 | return SOCKET_ERROR_BAD_STACK; 63 | } 64 | _onConnect = onConnect; 65 | socket_error_t err = _socket.api->connect(&_socket, address.getAddr(), port); 66 | return err; 67 | } 68 | 69 | void TCPStream::_eventHandler(struct socket_event *ev) 70 | { 71 | switch (ev->event) { 72 | case SOCKET_EVENT_CONNECT: 73 | if (_onConnect) 74 | minar::Scheduler::postCallback(_onConnect.bind(this)); 75 | break; 76 | case SOCKET_EVENT_DISCONNECT: 77 | if (_onDisconnect) 78 | minar::Scheduler::postCallback(_onDisconnect.bind(this)); 79 | break; 80 | default: 81 | // Call the aSocket event handler if the event is a generic one 82 | Socket::_eventHandler(ev); 83 | break; 84 | } 85 | } 86 | 87 | void TCPStream::setNagle(bool enable) 88 | { 89 | void * enable_ptr; 90 | if(enable) { 91 | enable_ptr = (void*)1; 92 | } else { 93 | enable_ptr = NULL; 94 | } 95 | _socket.api->set_option(&_socket, SOCKET_PROTO_LEVEL_TCP, SOCKET_OPT_NAGLE, enable_ptr, 0); 96 | } 97 | -------------------------------------------------------------------------------- /source/v0/UDPSocket.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * PackageLicenseDeclared: Apache-2.0 3 | * Copyright (c) 2015 ARM Limited 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | #include "sockets/v0/UDPSocket.h" 18 | #include "sal/socket_api.h" 19 | 20 | using namespace mbed::Sockets::v0; 21 | UDPSocket::UDPSocket(socket_stack_t stack): 22 | /* Store the default handler */ 23 | Socket(stack) 24 | { 25 | _socket.family = SOCKET_DGRAM; 26 | } 27 | 28 | UDPSocket::~UDPSocket() 29 | { 30 | } 31 | 32 | socket_error_t UDPSocket::connect(const SocketAddr *address, const uint16_t port) 33 | { 34 | if (_socket.api == NULL) { 35 | return SOCKET_ERROR_BAD_STACK; 36 | } 37 | socket_error_t err = _socket.api->connect(&_socket, address->getAddr(), port); 38 | return err; 39 | } 40 | 41 | socket_error_t UDPSocket::open(const socket_address_family_t af, const socket_proto_family_t pf) 42 | { 43 | (void)af; 44 | (void)pf; 45 | return SOCKET_ERROR_UNIMPLEMENTED; 46 | } 47 | -------------------------------------------------------------------------------- /test/echo-tcp-client/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * PackageLicenseDeclared: Apache-2.0 3 | * Copyright (c) 2015 ARM Limited 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | #include "mbed-drivers/mbed.h" 18 | #include "sockets/TCPStream.h" 19 | #include "sal-stack-lwip/lwipv4_init.h" 20 | #include "sal-iface-eth/EthernetInterface.h" 21 | #include "minar/minar.h" 22 | #include "core-util/FunctionPointer.h" 23 | #include "greentea-client/test_env.h" 24 | #include "utest/utest.h" 25 | #include "unity/unity.h" 26 | 27 | using namespace utest::v1; 28 | using namespace mbed::Sockets::v0; 29 | 30 | EthernetInterface eth; 31 | 32 | class TCPEchoClient; 33 | typedef mbed::util::FunctionPointer2 fpterminate_t; 34 | void terminate(bool status, TCPEchoClient* client); 35 | 36 | char out_buffer[] = "Hello World\n"; 37 | char buffer[256]; 38 | char out_success[] = "{{success}}\n{{end}}\n"; 39 | TCPEchoClient *client; 40 | int port; 41 | 42 | class TCPEchoClient { 43 | public: 44 | TCPEchoClient(socket_stack_t stack) : 45 | _stream(stack), _done(false), _disconnected(true) 46 | { 47 | _stream.setOnError(TCPStream::ErrorHandler_t(this, &TCPEchoClient::onError)); 48 | } 49 | ~TCPEchoClient(){ 50 | if (_stream.isConnected()) 51 | _stream.close(); 52 | } 53 | void onError(Socket *s, socket_error_t err) { 54 | (void) s; 55 | TEST_ASSERT_NOT_EQUAL_MESSAGE(SOCKET_ERROR_NONE, err, socket_strerror(err)); 56 | printf("MBED: Socket Error: %s (%d)\r\n", socket_strerror(err), err); 57 | _done = true; 58 | minar::Scheduler::postCallback(fpterminate_t(terminate).bind(false,this)); 59 | } 60 | void start_test(char * host_addr, uint16_t port) 61 | { 62 | printf("Trying to resolve address %s" NL, host_addr); 63 | _port = port; 64 | _done = false; 65 | _disconnected = true; 66 | socket_error_t err = _stream.open(SOCKET_AF_INET4); 67 | TEST_ASSERT_EQUAL_MESSAGE(SOCKET_ERROR_NONE, err, "MBED: Failed to open socket!"); 68 | 69 | err = _stream.resolve(host_addr,TCPStream::DNSHandler_t(this, &TCPEchoClient::onDNS)); 70 | TEST_ASSERT_EQUAL_MESSAGE(SOCKET_ERROR_NONE, err, "MBED: Failed to resolve host address!"); 71 | } 72 | void onDNS(Socket *s, struct socket_addr sa, const char* domain) 73 | { 74 | (void) s; 75 | _resolvedAddr.setAddr(&sa); 76 | /* TODO: add support for getting AF from addr */ 77 | /* Open the socket */ 78 | _resolvedAddr.fmtIPv6(buffer, sizeof(buffer)); 79 | printf("MBED: Resolved %s to %s\r\n", domain, buffer); 80 | /* Register the read handler */ 81 | _stream.setOnReadable(TCPStream::ReadableHandler_t(this, &TCPEchoClient::onRx)); 82 | _stream.setOnSent(TCPStream::SentHandler_t(this, &TCPEchoClient::onSent)); 83 | _stream.setOnDisconnect(TCPStream::DisconnectHandler_t(this, &TCPEchoClient::onDisconnect)); 84 | /* Send the query packet to the remote host */ 85 | socket_error_t err = _stream.connect(_resolvedAddr, _port, TCPStream::ConnectHandler_t(this,&TCPEchoClient::onConnect)); 86 | TEST_ASSERT_EQUAL_MESSAGE(SOCKET_ERROR_NONE, err, "MBED: Failed to connect host server!"); 87 | } 88 | void onConnect(TCPStream *s) 89 | { 90 | (void) s; 91 | _disconnected = false; 92 | _unacked = sizeof(out_buffer) - 1; 93 | printf ("MBED: Sending (%d bytes) to host: %s" NL, _unacked, out_buffer); 94 | socket_error_t err = _stream.send(out_buffer, sizeof(out_buffer) - 1); 95 | TEST_ASSERT_EQUAL_MESSAGE(SOCKET_ERROR_NONE, err, "MBED: TCPClient failed to send data!"); 96 | } 97 | void onRx(Socket* s) 98 | { 99 | (void) s; 100 | size_t n = sizeof(buffer)-1; 101 | socket_error_t err = _stream.recv(buffer, &n); 102 | TEST_ASSERT_EQUAL_MESSAGE(SOCKET_ERROR_NONE, err, "MBED: TCPClient failed to recv data!"); 103 | 104 | buffer[n] = 0; 105 | printf ("MBED: Rx (%d bytes) from host: %s" NL, n, buffer); 106 | if (!_done && n > 0) 107 | { 108 | TEST_ASSERT_EQUAL_STRING_LEN_MESSAGE(out_buffer, buffer, n, "MBED: TCPClient round trip data validation failed!"); 109 | 110 | _unacked += sizeof(out_success) - 1; 111 | printf ("MBED: Sending (%d bytes) to host: %s" NL, _unacked, out_success); 112 | err = _stream.send(out_success, sizeof(out_success) - 1); 113 | _done = true; 114 | TEST_ASSERT_EQUAL_MESSAGE(SOCKET_ERROR_NONE, err, "MBED: TCPClient failed to send data!"); 115 | } 116 | if (!_done) { 117 | // Failed to validate rceived data. Terminating... 118 | minar::Scheduler::postCallback(fpterminate_t(terminate).bind(false,this)); 119 | } 120 | } 121 | void onSent(Socket *s, uint16_t nbytes) 122 | { 123 | (void) s; 124 | _unacked -= nbytes; 125 | printf ("MBED: Sent %d bytes" NL, nbytes); 126 | if (_done && (_unacked == 0)) { 127 | minar::Scheduler::postCallback(fpterminate_t(terminate).bind(true,this)); 128 | } 129 | } 130 | void onDisconnect(TCPStream *s) 131 | { 132 | (void) s; 133 | _disconnected = true; 134 | } 135 | protected: 136 | TCPStream _stream; 137 | SocketAddr _resolvedAddr; 138 | uint16_t _port; 139 | volatile bool _done; 140 | volatile bool _disconnected; 141 | volatile size_t _unacked; 142 | }; 143 | 144 | void terminate(bool status, TCPEchoClient* ) 145 | { 146 | if (client) { 147 | printf("MBED: Test finished!"); 148 | delete client; 149 | client = NULL; 150 | eth.disconnect(); 151 | TEST_ASSERT_TRUE_MESSAGE(status, "MBED: test failed!"); 152 | Harness::validate_callback(); 153 | } 154 | } 155 | 156 | control_t test_echo_tcp_client() 157 | { 158 | socket_error_t err = lwipv4_socket_init(); 159 | TEST_ASSERT_EQUAL(SOCKET_ERROR_NONE, err); 160 | 161 | TEST_ASSERT_EQUAL(0, eth.init()); //Use DHCP 162 | eth.connect(); 163 | 164 | printf("TCPClient IP Address is %s" NL, eth.getIPAddress()); 165 | greentea_send_kv("target_ip", eth.getIPAddress()); 166 | 167 | memset(buffer, 0, sizeof(buffer)); 168 | port = 0; 169 | 170 | printf("TCPClient waiting for server IP and port..." NL); 171 | char recv_key[] = "host_port"; 172 | char port_value[] = "65325"; 173 | 174 | greentea_send_kv("host_ip", " "); 175 | TEST_ASSERT_NOT_EQUAL_MESSAGE(0, greentea_parse_kv(recv_key, buffer, sizeof(recv_key), sizeof(buffer)), "MBED: Failed to recv/parse key value from host test!"); 176 | 177 | greentea_send_kv("host_port", " "); 178 | TEST_ASSERT_NOT_EQUAL_MESSAGE(0, greentea_parse_kv(recv_key, port_value, sizeof(recv_key), sizeof(port_value)), "MBED: Failed to recv/parse key value from host test!"); 179 | 180 | sscanf(port_value, "%d", &port); 181 | 182 | 183 | client = new TCPEchoClient(SOCKET_STACK_LWIP_IPV4); 184 | 185 | { 186 | mbed::util::FunctionPointer2 fp(client, &TCPEchoClient::start_test); 187 | minar::Scheduler::postCallback(fp.bind(buffer, port)); 188 | } 189 | 190 | return CaseTimeout(15000); 191 | } 192 | 193 | // Cases -------------------------------------------------------------------------------------------------------------- 194 | Case cases[] = { 195 | Case("Test Echo TCP Client", test_echo_tcp_client), 196 | }; 197 | 198 | status_t greentea_setup(const size_t number_of_cases) 199 | { 200 | // Handshake with greentea 201 | // Host test timeout should be more than target utest timeout to let target cleanup the test and send test summary. 202 | GREENTEA_SETUP(20, "tcpecho_client_auto"); 203 | return greentea_test_setup_handler(number_of_cases); 204 | } 205 | 206 | Specification specification(greentea_setup, cases); 207 | 208 | void app_start(int, char*[]) 209 | { 210 | Harness::run(specification); 211 | } 212 | 213 | -------------------------------------------------------------------------------- /test/echo-udp-client/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * PackageLicenseDeclared: Apache-2.0 3 | * Copyright (c) 2015 ARM Limited 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | #include "mbed-drivers/mbed.h" 18 | #include "sal/socket_api.h" 19 | #include 20 | #include "sockets/UDPSocket.h" 21 | #include "sal-iface-eth/EthernetInterface.h" 22 | #include "sal-stack-lwip/lwipv4_init.h" 23 | #include "minar/minar.h" 24 | #include "core-util/FunctionPointer.h" 25 | #include "greentea-client/test_env.h" 26 | #include "utest/utest.h" 27 | #include "unity/unity.h" 28 | 29 | #define CHECK(RC, STEP) if (RC < 0) error(STEP": %d\r\n", RC) 30 | 31 | using namespace utest::v1; 32 | using namespace mbed::Sockets::v0; 33 | 34 | 35 | namespace { 36 | const int BUFFER_SIZE = 64; 37 | const int MAX_ECHO_LOOPS = 100; 38 | const char ASCII_MAX = '~' - ' '; 39 | } 40 | 41 | char char_rand() { 42 | return (rand() % ASCII_MAX) + ' '; 43 | } 44 | 45 | #ifndef min 46 | #define min(A,B) \ 47 | ((A)<(B)?(A):(B)) 48 | #endif 49 | 50 | class UDPEchoClient; 51 | typedef mbed::util::FunctionPointer2 fpterminate_t; 52 | void terminate(bool status, UDPEchoClient* client); 53 | 54 | char buffer[BUFFER_SIZE] = {0}; 55 | int port = 0; 56 | UDPEchoClient *client; 57 | EthernetInterface eth; 58 | 59 | class UDPEchoClient { 60 | public: 61 | UDPEchoClient(socket_stack_t stack) : 62 | _usock(stack) 63 | { 64 | _usock.setOnError(UDPSocket::ErrorHandler_t(this, &UDPEchoClient::onError)); 65 | } 66 | ~UDPEchoClient(){ 67 | if (_usock.isConnected()) 68 | _usock.close(); 69 | } 70 | void start_test(char * host_addr, uint16_t port) 71 | { 72 | loop_ctr = 0; 73 | _port = port; 74 | 75 | socket_error_t err = _usock.open(SOCKET_AF_INET4); 76 | TEST_ASSERT_EQUAL_MESSAGE(SOCKET_ERROR_NONE, err, "MBED: UDPClient unable to open socket" NL); 77 | printf("MBED: Trying to resolve address %s" NL, host_addr); 78 | err = _usock.resolve(host_addr,UDPSocket::DNSHandler_t(this, &UDPEchoClient::onDNS)); 79 | TEST_ASSERT_EQUAL_MESSAGE(SOCKET_ERROR_NONE, err, "MBED: UDPClient failed to resolve host server address" NL); 80 | } 81 | void onError(Socket *s, socket_error_t err) { 82 | (void) s; 83 | TEST_ASSERT_NOT_EQUAL(SOCKET_ERROR_NONE, err); 84 | printf("MBED: Socket Error: %s (%d)\r\n", socket_strerror(err), err); 85 | minar::Scheduler::postCallback(fpterminate_t(terminate).bind(false,this)); 86 | } 87 | void onDNS(Socket *s, struct socket_addr sa, const char * domain) 88 | { 89 | (void) s; 90 | /* Extract the Socket event to read the resolved address */ 91 | _resolvedAddr.setAddr(&sa); 92 | _resolvedAddr.fmtIPv6(out_buffer, sizeof(out_buffer)); 93 | printf("MBED: Resolved %s to %s\r\n", domain, out_buffer); 94 | 95 | /* TODO: add support for getting AF from addr */ 96 | socket_error_t err = _usock.open(SOCKET_AF_INET4); 97 | TEST_ASSERT_EQUAL_MESSAGE(SOCKET_ERROR_NONE, err, "MBED: UDPClient failed to open socket!" NL); 98 | 99 | /* Register the read handler */ 100 | _usock.setOnReadable(UDPSocket::ReadableHandler_t(this, &UDPEchoClient::onRx)); 101 | /* Send the query packet to the remote host */ 102 | send_test(); 103 | } 104 | void onRx(Socket *s) 105 | { 106 | (void) s; 107 | unsigned int n = sizeof(buffer); 108 | socket_error_t err = _usock.recv(buffer, &n); 109 | TEST_ASSERT_EQUAL_MESSAGE(SOCKET_ERROR_NONE, err, "MBED: UDPClient failed to recv data!" NL); 110 | 111 | int rc = memcmp(buffer, out_buffer, min(BUFFER_SIZE,n)); 112 | TEST_ASSERT_EQUAL_MESSAGE(0, rc, "MBED: UDPClient round trip data validation error!" NL); 113 | 114 | loop_ctr++; 115 | if (loop_ctr < MAX_ECHO_LOOPS) { 116 | send_test(); 117 | 118 | } 119 | if (loop_ctr >= MAX_ECHO_LOOPS) { 120 | _usock.send_to(buffer, strlen(buffer), &_resolvedAddr, _port); 121 | minar::Scheduler::postCallback(fpterminate_t(terminate).bind(true,this)); 122 | } 123 | } 124 | 125 | protected: 126 | void send_test() { 127 | std::generate(out_buffer, out_buffer + BUFFER_SIZE, char_rand); 128 | socket_error_t err = _usock.send_to(out_buffer, sizeof(BUFFER_SIZE), &_resolvedAddr, _port); 129 | TEST_ASSERT_EQUAL_MESSAGE(SOCKET_ERROR_NONE, err, "MBED: UDPClient failed to send data!" NL); 130 | } 131 | protected: 132 | UDPSocket _usock; 133 | SocketAddr _resolvedAddr; 134 | uint16_t _port; 135 | char out_buffer[BUFFER_SIZE]; 136 | char buffer[BUFFER_SIZE]; 137 | uint32_t loop_ctr; 138 | volatile bool done; 139 | }; 140 | 141 | void terminate(bool status, UDPEchoClient* ) 142 | { 143 | if (client) { 144 | printf("MBED: Test finished!"); 145 | delete client; 146 | client = NULL; 147 | eth.disconnect(); 148 | TEST_ASSERT_TRUE_MESSAGE(status, "MBED: test failed!"); 149 | Harness::validate_callback(); 150 | } 151 | } 152 | 153 | 154 | 155 | control_t test_echo_udp_client() 156 | { 157 | socket_error_t err = lwipv4_socket_init(); 158 | TEST_ASSERT_EQUAL_MESSAGE(SOCKET_ERROR_NONE, err, "Failed to init LWIPv4 socket!"); 159 | 160 | printf("MBED: Initializing ethernet connection." NL); 161 | //Use DHCP 162 | TEST_ASSERT_EQUAL_MESSAGE(0, eth.init(), "Failed to init LWIPv4 socket!"); 163 | eth.connect(); 164 | 165 | printf("MBED: IP Address is %s" NL, eth.getIPAddress()); 166 | greentea_send_kv("target_ip", eth.getIPAddress()); 167 | 168 | memset(buffer, 0, sizeof(buffer)); 169 | port = 0; 170 | 171 | printf("UDPClient waiting for server IP and port..." NL); 172 | char recv_key[] = "host_port"; 173 | char port_value[] = "65325"; 174 | 175 | greentea_send_kv("host_ip", " "); 176 | TEST_ASSERT_NOT_EQUAL_MESSAGE(0, greentea_parse_kv(recv_key, buffer, sizeof(recv_key), sizeof(buffer)), "MBED: Failed to recv/parse key value from host!"); 177 | 178 | greentea_send_kv("host_port", " "); 179 | TEST_ASSERT_NOT_EQUAL_MESSAGE(0, greentea_parse_kv(recv_key, port_value, sizeof(recv_key), sizeof(port_value)), "MBED: Failed to recv/parse key value from host!"); 180 | 181 | sscanf(port_value, "%d", &port); 182 | 183 | 184 | client = new UDPEchoClient(SOCKET_STACK_LWIP_IPV4); 185 | 186 | { 187 | mbed::util::FunctionPointer2 fp(client, &UDPEchoClient::start_test); 188 | minar::Scheduler::postCallback(fp.bind(buffer, port)); 189 | } 190 | return CaseTimeout(25000); 191 | } 192 | 193 | 194 | // Cases -------------------------------------------------------------------------------------------------------------- 195 | Case cases[] = { 196 | Case("Test Echo UDP Client", test_echo_udp_client), 197 | }; 198 | 199 | status_t greentea_setup(const size_t number_of_cases) 200 | { 201 | // Handshake with greentea 202 | // Host test timeout should be more than target utest timeout to let target cleanup the test and send test summary. 203 | GREENTEA_SETUP(30, "udpecho_client_auto"); 204 | return greentea_test_setup_handler(number_of_cases); 205 | } 206 | 207 | void greentea_teardown(const size_t passed, const size_t failed, const failure_t failure) 208 | { 209 | greentea_test_teardown_handler(passed, failed, failure); 210 | GREENTEA_TESTSUITE_RESULT(failed == 0); 211 | } 212 | 213 | Specification specification(greentea_setup, cases, greentea_teardown); 214 | 215 | void app_start(int, char*[]) 216 | { 217 | Harness::run(specification); 218 | } 219 | 220 | -------------------------------------------------------------------------------- /test/host_tests/tcpecho_client_auto.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 ARM Limited, All rights reserved 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import sys 16 | import select 17 | import socket 18 | import logging 19 | from threading import Thread 20 | from sys import stdout 21 | from SocketServer import BaseRequestHandler, TCPServer 22 | from mbed_host_tests import BaseHostTest, event_callback 23 | 24 | 25 | class TCPEchoClientHandler(BaseRequestHandler): 26 | def handle(self): 27 | """ 28 | Handles a connection. Test starts by client(i.e. mbed) connecting to server. 29 | This connection handler receives data and echoes back to the client util 30 | {{end}} is received. Then it sits on recv() for client to terminate the 31 | connection. 32 | 33 | Note: reason for not echoing data back after receiving {{end}} is that send 34 | fails raising a SocketError as client closes connection. 35 | """ 36 | print ("HOST: TCPEchoClient_Handler: Connection received...") 37 | while self.server.isrunning(): 38 | try: 39 | data = self.recv() 40 | if not data: break 41 | print ('HOST: TCPEchoClient_Handler: \n%s\n' % data) 42 | 43 | # If client finishes, sit on recv and terminate 44 | # after client closes connection. 45 | if '{{end}}' in data: continue 46 | 47 | # echo data back to the client 48 | self.send(data) 49 | except Exception as e: 50 | print ('HOST: TCPEchoClient_Handler: %s' % str(e)) 51 | break 52 | print 'Connection finshed' 53 | 54 | def recv(self): 55 | """ 56 | Try to receive until server is shutdown 57 | """ 58 | while self.server.isrunning(): 59 | rl, wl, xl = select.select([self.request], [], [], 1) 60 | if len(rl): 61 | return self.request.recv(1024) 62 | 63 | def send(self, data): 64 | """ 65 | Try to send until server is shutdown 66 | """ 67 | while self.server.isrunning(): 68 | rl, wl, xl = select.select([], [self.request], [], 1) 69 | if len(wl): 70 | self.request.sendall(data) 71 | break 72 | 73 | 74 | class TCPServerWrapper(TCPServer): 75 | """ 76 | Wrapper over TCP server to implement server initiated shutdown. 77 | Adds a flag:= running that a request handler can check and come out of 78 | recv loop when shutdown is called. 79 | """ 80 | 81 | def __init__(self, addr, request_handler): 82 | # hmm, TCPServer is not sub-classed from object! 83 | if issubclass(TCPServer, object): 84 | super(TCPServerWrapper, self).__init__(addr, request_handler) 85 | else: 86 | TCPServer.__init__(self, addr, request_handler) 87 | self.running = False 88 | 89 | def serve_forever(self): 90 | self.running = True 91 | if issubclass(TCPServer, object): 92 | super(TCPServerWrapper, self).serve_forever() 93 | else: 94 | TCPServer.serve_forever(self) 95 | 96 | def shutdown(self): 97 | self.running = False 98 | if issubclass(TCPServer, object): 99 | super(TCPServerWrapper, self).shutdown() 100 | else: 101 | TCPServer.shutdown(self) 102 | 103 | def isrunning(self): 104 | return self.running 105 | 106 | 107 | class TCPEchoClientTest(BaseHostTest): 108 | 109 | def __init__(self): 110 | """ 111 | Initialise test parameters. 112 | 113 | :return: 114 | """ 115 | super(BaseHostTest, self).__init__() 116 | self.SERVER_IP = None # Will be determined after knowing the target IP 117 | self.SERVER_PORT = 0 # Let TCPServer choose an arbitrary port 118 | self.server = None 119 | self.server_thread = None 120 | self.target_ip = None 121 | 122 | @staticmethod 123 | def find_interface_to_target_addr(target_ip): 124 | """ 125 | Finds IP address of the interface through which it is connected to the target. 126 | 127 | :return: 128 | """ 129 | s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 130 | s.connect((target_ip, 0)) # Target IP, Any port 131 | ip = s.getsockname()[0] 132 | s.close() 133 | return ip 134 | 135 | def setup_tcp_server(self): 136 | """ 137 | sets up a TCP server for target to connect and send test data. 138 | 139 | :return: 140 | """ 141 | # !NOTE: There should mechanism to assert in the host test 142 | if self.SERVER_IP is None: 143 | self.log("setup_tcp_server() called before determining server IP!") 144 | self.notify_complete(False) 145 | 146 | # Returning none will suppress host test from printing success code 147 | self.server = TCPServerWrapper((self.SERVER_IP, self.SERVER_PORT), TCPEchoClientHandler) 148 | ip, port = self.server.server_address 149 | self.SERVER_PORT = port 150 | self.server.allow_reuse_address = True 151 | self.log("HOST: Listening for TCP connections: " + self.SERVER_IP + ":" + str(self.SERVER_PORT)) 152 | self.server_thread = Thread(target=TCPEchoClientTest.server_thread_func, args=(self,)) 153 | self.server_thread.start() 154 | 155 | @staticmethod 156 | def server_thread_func(this): 157 | """ 158 | Thread function to run TCP server forever. 159 | 160 | :param this: 161 | :return: 162 | """ 163 | this.server.serve_forever() 164 | 165 | @event_callback("target_ip") 166 | def _callback_target_ip(self, key, value, timestamp): 167 | """ 168 | Callback to handle reception of target's IP address. 169 | 170 | :param key: 171 | :param value: 172 | :param timestamp: 173 | :return: 174 | """ 175 | self.target_ip = value 176 | self.SERVER_IP = self.find_interface_to_target_addr(self.target_ip) 177 | self.setup_tcp_server() 178 | 179 | @event_callback("host_ip") 180 | def _callback_host_ip(self, key, value, timestamp): 181 | """ 182 | Callback for request for host IP Addr 183 | 184 | """ 185 | self.send_kv("host_ip", self.SERVER_IP) 186 | 187 | @event_callback("host_port") 188 | def _callback_host_port(self, key, value, timestamp): 189 | """ 190 | Callback for request for host port 191 | """ 192 | self.send_kv("host_port", self.SERVER_PORT) 193 | 194 | def teardown(self): 195 | if self.server: 196 | self.server.shutdown() 197 | self.server_thread.join() 198 | -------------------------------------------------------------------------------- /test/host_tests/udpecho_client_auto.py: -------------------------------------------------------------------------------- 1 | """ 2 | mbed SDK 3 | Copyright (c) 2011-2013 ARM Limited 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | """ 17 | 18 | import sys 19 | import socket 20 | from sys import stdout 21 | from threading import Thread 22 | from SocketServer import BaseRequestHandler, UDPServer 23 | from mbed_host_tests import BaseHostTest, event_callback 24 | 25 | 26 | class UDPEchoClientHandler(BaseRequestHandler): 27 | def handle(self): 28 | """ UDP packet handler. Echoes data back to sender's address. 29 | """ 30 | data, sock = self.request 31 | print data 32 | sock.sendto(data, self.client_address) 33 | 34 | 35 | class UDPEchoClientTest(BaseHostTest): 36 | 37 | def __init__(self): 38 | """ 39 | Initialise test parameters. 40 | 41 | :return: 42 | """ 43 | super(BaseHostTest, self).__init__() 44 | self.SERVER_IP = None # Will be determined after knowing the target IP 45 | self.SERVER_PORT = 0 # Let TCPServer choose an arbitrary port 46 | self.server = None 47 | self.server_thread = None 48 | self.target_ip = None 49 | 50 | @staticmethod 51 | def find_interface_to_target_addr(target_ip): 52 | """ 53 | Finds IP address of the interface through which it is connected to the target. 54 | 55 | :return: 56 | """ 57 | s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 58 | s.connect((target_ip, 0)) # Target IP, Any port 59 | ip = s.getsockname()[0] 60 | s.close() 61 | return ip 62 | 63 | def setup_udp_server(self): 64 | """ 65 | sets up a UDP server for target to connect and send test data. 66 | 67 | :return: 68 | """ 69 | # !NOTE: There should mechanism to assert in the host test 70 | if self.SERVER_IP is None: 71 | self.log("setup_udp_server() called before determining server IP!") 72 | self.notify_complete(False) 73 | 74 | # Returning none will suppress host test from printing success code 75 | self.server = UDPServer((self.SERVER_IP, self.SERVER_PORT), UDPEchoClientHandler) 76 | ip, port = self.server.server_address 77 | self.SERVER_PORT = port 78 | self.server.allow_reuse_address = True 79 | self.log("HOST: Listening for UDP packets: " + self.SERVER_IP + ":" + str(self.SERVER_PORT)) 80 | self.server_thread = Thread(target=UDPEchoClientTest.server_thread_func, args=(self,)) 81 | self.server_thread.start() 82 | 83 | @staticmethod 84 | def server_thread_func(this): 85 | """ 86 | Thread function to run TCP server forever. 87 | 88 | :param this: 89 | :return: 90 | """ 91 | this.server.serve_forever() 92 | 93 | @event_callback("target_ip") 94 | def _callback_target_ip(self, key, value, timestamp): 95 | """ 96 | Callback to handle reception of target's IP address. 97 | 98 | :param key: 99 | :param value: 100 | :param timestamp: 101 | :return: 102 | """ 103 | self.target_ip = value 104 | self.SERVER_IP = self.find_interface_to_target_addr(self.target_ip) 105 | self.setup_udp_server() 106 | 107 | @event_callback("host_ip") 108 | def _callback_host_ip(self, key, value, timestamp): 109 | """ 110 | Callback for request for host IP Addr 111 | 112 | """ 113 | self.send_kv("host_ip", self.SERVER_IP) 114 | 115 | @event_callback("host_port") 116 | def _callback_host_port(self, key, value, timestamp): 117 | """ 118 | Callback for request for host port 119 | """ 120 | self.send_kv("host_port", self.SERVER_PORT) 121 | 122 | def teardown(self): 123 | if self.server: 124 | self.server.shutdown() 125 | self.server_thread.join() 126 | --------------------------------------------------------------------------------