Skip to content

Commit da6b336

Browse files
authored
Merge pull request #10978 from vmedcy/lwip-rawsocket
LwIP: add ICMPv4 Socket support
2 parents 73b4f71 + 2d410e3 commit da6b336

File tree

14 files changed

+448
-292
lines changed

14 files changed

+448
-292
lines changed

UNITTESTS/features/netsocket/DTLSSocket/unittest.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ set(unittest-sources
77
../features/netsocket/SocketAddress.cpp
88
../features/netsocket/NetworkStack.cpp
99
../features/netsocket/InternetSocket.cpp
10+
../features/netsocket/InternetDatagramSocket.cpp
1011
../features/netsocket/UDPSocket.cpp
1112
../features/netsocket/DTLSSocket.cpp
1213
../features/netsocket/DTLSSocketWrapper.cpp

UNITTESTS/features/netsocket/DTLSSocketWrapper/unittest.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ set(unittest-sources
77
../features/netsocket/SocketAddress.cpp
88
../features/netsocket/NetworkStack.cpp
99
../features/netsocket/InternetSocket.cpp
10+
../features/netsocket/InternetDatagramSocket.cpp
1011
../features/netsocket/UDPSocket.cpp
1112
../features/netsocket/DTLSSocketWrapper.cpp
1213
../features/netsocket/TLSSocketWrapper.cpp

UNITTESTS/features/netsocket/UDPSocket/unittest.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ set(unittest-sources
77
../features/netsocket/SocketAddress.cpp
88
../features/netsocket/NetworkStack.cpp
99
../features/netsocket/InternetSocket.cpp
10+
../features/netsocket/InternetDatagramSocket.cpp
1011
../features/netsocket/UDPSocket.cpp
1112
../features/frameworks/nanostack-libservice/source/libip4string/ip4tos.c
1213
../features/frameworks/nanostack-libservice/source/libip6string/ip6tos.c

features/lwipstack/LWIPStack.cpp

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -230,14 +230,28 @@ nsapi_error_t LWIP::socket_open(nsapi_socket_t *handle, nsapi_protocol_t proto)
230230
return NSAPI_ERROR_NO_SOCKET;
231231
}
232232

233-
enum netconn_type lwip_proto = proto == NSAPI_TCP ? NETCONN_TCP : NETCONN_UDP;
233+
enum netconn_type netconntype;
234+
if (proto == NSAPI_TCP) {
235+
netconntype = NETCONN_TCP;
236+
} else if (proto == NSAPI_UDP) {
237+
netconntype = NETCONN_UDP;
238+
} else if (proto == NSAPI_ICMP) {
239+
netconntype = NETCONN_RAW;
240+
} else {
241+
return NSAPI_ERROR_UNSUPPORTED;
242+
}
234243

235244
#if LWIP_IPV6
236245
// Enable IPv6 (or dual-stack)
237-
lwip_proto = (enum netconn_type)(lwip_proto | NETCONN_TYPE_IPV6);
246+
netconntype = (enum netconn_type)(netconntype | NETCONN_TYPE_IPV6);
238247
#endif
239248

240-
s->conn = netconn_new_with_callback(lwip_proto, &LWIP::socket_callback);
249+
if (proto == NSAPI_ICMP) {
250+
s->conn = netconn_new_with_proto_and_callback(NETCONN_RAW,
251+
(u8_t)IP_PROTO_ICMP, &LWIP::socket_callback);
252+
} else {
253+
s->conn = netconn_new_with_callback(netconntype, &LWIP::socket_callback);
254+
}
241255

242256
if (!s->conn) {
243257
arena_dealloc(s);

features/lwipstack/lwipopts.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,7 @@
8181

8282
#define SYS_LIGHTWEIGHT_PROT 1
8383

84-
#ifndef LWIP_RAW
85-
#define LWIP_RAW 0
86-
#endif
84+
#define LWIP_RAW MBED_CONF_LWIP_RAW_SOCKET_ENABLED
8785

8886
#define MEMP_NUM_TCPIP_MSG_INPKT MBED_CONF_LWIP_MEMP_NUM_TCPIP_MSG_INPKT
8987
#define TCPIP_MBOX_SIZE MBED_CONF_LWIP_TCPIP_MBOX_SIZE

features/lwipstack/mbed_lib.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,10 @@
156156
"num-netbuf": {
157157
"help": "Number of netbufs, each netbuf requires 64 bytes of RAM, see LWIP's opt.h for more information. Current default is 8.",
158158
"value": 8
159+
},
160+
"raw-socket-enabled": {
161+
"help": "Enable lwip raw sockets, required for Mbed OS ICMPSocket",
162+
"value": false
159163
}
160164
},
161165
"target_overrides": {

features/netsocket/ICMPSocket.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/* Socket
2+
* Copyright (c) 2015 ARM Limited
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "ICMPSocket.h"
18+
#include "Timer.h"
19+
#include "mbed_assert.h"
20+
21+
ICMPSocket::ICMPSocket()
22+
{
23+
_socket_stats.stats_update_proto(this, NSAPI_ICMP);
24+
}
25+
26+
nsapi_protocol_t ICMPSocket::get_proto()
27+
{
28+
return NSAPI_ICMP;
29+
}

features/netsocket/ICMPSocket.h

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/** \addtogroup netsocket */
2+
/** @{*/
3+
/* ICMPSocket
4+
* Copyright (c) 2015 ARM Limited
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
#ifndef ICMPSOCKET_H
20+
#define ICMPSOCKET_H
21+
22+
#include "netsocket/InternetSocket.h"
23+
#include "netsocket/InternetDatagramSocket.h"
24+
#include "netsocket/NetworkStack.h"
25+
#include "netsocket/NetworkInterface.h"
26+
#include "rtos/EventFlags.h"
27+
28+
29+
/** ICMP socket implementation.
30+
*/
31+
class ICMPSocket : public InternetDatagramSocket {
32+
public:
33+
/** Create an uninitialized socket.
34+
*
35+
* @note Must call open to initialize the socket on a network stack.
36+
*/
37+
ICMPSocket();
38+
39+
#if !defined(DOXYGEN_ONLY)
40+
41+
protected:
42+
virtual nsapi_protocol_t get_proto();
43+
44+
#endif //!defined(DOXYGEN_ONLY)
45+
};
46+
47+
48+
#endif
49+
50+
/** @}*/
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
/* Socket
2+
* Copyright (c) 2015 ARM Limited
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "InternetDatagramSocket.h"
18+
#include "Timer.h"
19+
#include "mbed_assert.h"
20+
21+
nsapi_error_t InternetDatagramSocket::connect(const SocketAddress &address)
22+
{
23+
_remote_peer = address;
24+
_socket_stats.stats_update_peer(this, _remote_peer);
25+
_socket_stats.stats_update_socket_state(this, SOCK_CONNECTED);
26+
return NSAPI_ERROR_OK;
27+
}
28+
29+
nsapi_size_or_error_t InternetDatagramSocket::sendto(const char *host, uint16_t port, const void *data, nsapi_size_t size)
30+
{
31+
SocketAddress address;
32+
nsapi_size_or_error_t err;
33+
34+
if (!strcmp(_interface_name, "")) {
35+
err = _stack->gethostbyname(host, &address);
36+
} else {
37+
err = _stack->gethostbyname(host, &address, NSAPI_UNSPEC, _interface_name);
38+
}
39+
40+
if (err) {
41+
return NSAPI_ERROR_DNS_FAILURE;
42+
}
43+
44+
address.set_port(port);
45+
46+
// sendto is thread safe
47+
return sendto(address, data, size);
48+
}
49+
50+
nsapi_size_or_error_t InternetDatagramSocket::sendto(const SocketAddress &address, const void *data, nsapi_size_t size)
51+
{
52+
_lock.lock();
53+
nsapi_size_or_error_t ret;
54+
55+
_writers++;
56+
if (_socket) {
57+
_socket_stats.stats_update_socket_state(this, SOCK_OPEN);
58+
_socket_stats.stats_update_peer(this, address);
59+
}
60+
while (true) {
61+
if (!_socket) {
62+
ret = NSAPI_ERROR_NO_SOCKET;
63+
break;
64+
}
65+
66+
core_util_atomic_flag_clear(&_pending);
67+
nsapi_size_or_error_t sent = _stack->socket_sendto(_socket, address, data, size);
68+
if ((0 == _timeout) || (NSAPI_ERROR_WOULD_BLOCK != sent)) {
69+
_socket_stats.stats_update_sent_bytes(this, sent);
70+
ret = sent;
71+
break;
72+
} else {
73+
uint32_t flag;
74+
75+
// Release lock before blocking so other threads
76+
// accessing this object aren't blocked
77+
_lock.unlock();
78+
flag = _event_flag.wait_any(WRITE_FLAG, _timeout);
79+
_lock.lock();
80+
81+
if (flag & osFlagsError) {
82+
// Timeout break
83+
ret = NSAPI_ERROR_WOULD_BLOCK;
84+
break;
85+
}
86+
}
87+
}
88+
89+
_writers--;
90+
if (!_socket || !_writers) {
91+
_event_flag.set(FINISHED_FLAG);
92+
}
93+
_lock.unlock();
94+
return ret;
95+
}
96+
97+
nsapi_size_or_error_t InternetDatagramSocket::send(const void *data, nsapi_size_t size)
98+
{
99+
if (!_remote_peer) {
100+
return NSAPI_ERROR_NO_ADDRESS;
101+
}
102+
return sendto(_remote_peer, data, size);
103+
}
104+
105+
nsapi_size_or_error_t InternetDatagramSocket::recvfrom(SocketAddress *address, void *buffer, nsapi_size_t size)
106+
{
107+
_lock.lock();
108+
nsapi_size_or_error_t ret;
109+
SocketAddress ignored;
110+
111+
if (!address) {
112+
address = &ignored;
113+
}
114+
115+
_readers++;
116+
117+
if (_socket) {
118+
_socket_stats.stats_update_socket_state(this, SOCK_OPEN);
119+
}
120+
while (true) {
121+
if (!_socket) {
122+
ret = NSAPI_ERROR_NO_SOCKET;
123+
break;
124+
}
125+
126+
core_util_atomic_flag_clear(&_pending);
127+
nsapi_size_or_error_t recv = _stack->socket_recvfrom(_socket, address, buffer, size);
128+
129+
// Filter incomming packets using connected peer address
130+
if (recv >= 0 && _remote_peer && _remote_peer != *address) {
131+
continue;
132+
}
133+
134+
_socket_stats.stats_update_peer(this, _remote_peer);
135+
// Non-blocking sockets always return. Blocking only returns when success or errors other than WOULD_BLOCK
136+
if ((0 == _timeout) || (NSAPI_ERROR_WOULD_BLOCK != recv)) {
137+
ret = recv;
138+
_socket_stats.stats_update_recv_bytes(this, recv);
139+
break;
140+
} else {
141+
uint32_t flag;
142+
143+
// Release lock before blocking so other threads
144+
// accessing this object aren't blocked
145+
_lock.unlock();
146+
flag = _event_flag.wait_any(READ_FLAG, _timeout);
147+
_lock.lock();
148+
149+
if (flag & osFlagsError) {
150+
// Timeout break
151+
ret = NSAPI_ERROR_WOULD_BLOCK;
152+
break;
153+
}
154+
}
155+
}
156+
157+
_readers--;
158+
if (!_socket || !_readers) {
159+
_event_flag.set(FINISHED_FLAG);
160+
}
161+
162+
_lock.unlock();
163+
return ret;
164+
}
165+
166+
nsapi_size_or_error_t InternetDatagramSocket::recv(void *buffer, nsapi_size_t size)
167+
{
168+
return recvfrom(NULL, buffer, size);
169+
}
170+
171+
Socket *InternetDatagramSocket::accept(nsapi_error_t *error)
172+
{
173+
if (error) {
174+
*error = NSAPI_ERROR_UNSUPPORTED;
175+
}
176+
return NULL;
177+
}
178+
179+
nsapi_error_t InternetDatagramSocket::listen(int)
180+
{
181+
return NSAPI_ERROR_UNSUPPORTED;
182+
}

0 commit comments

Comments
 (0)