RF24Ethernet - TCP/IP over RF24Network v2.2.1
TMRh20 - Pushing the practical limits of RF24 modules
Loading...
Searching...
No Matches
RF24Server.cpp
Go to the documentation of this file.
1/*
2 RF24Server.cpp - Arduino implementation of a uIP wrapper class.
3 Copyright (c) 2014 tmrh20@gmail.com, github.com/TMRh20
4 Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de>
5 All rights reserved.
6
7 This program is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20#include "RF24Ethernet.h"
21#include "RF24Server.h"
22
23extern "C" {
24//#include "uip-conf.h"
25}
26
27/*************************************************************/
28#if USE_LWIP < 1
29RF24Server::RF24Server(uint16_t port) : _port(htons(port))
30{
31}
32#elif USE_LWIP == 1
33uint16_t RF24Server::_port;
34struct tcp_pcb* RF24Server::sPcb;
35EthernetClient::ConnectState* RF24Server::serverState;
36
38{
39 _port = port;
40 // Allocate data for a second server/client
41 RF24Client::incomingData[1] = (char*)malloc(INCOMING_DATA_SIZE);
42}
43
44#elif USE_LWIP == 2
45
46 #include <zephyr/kernel.h>
47 #include <zephyr/net/socket.h>
48 #include <zephyr/logging/log.h>
49 #include <zephyr/posix/fcntl.h>
50 #include <errno.h>
51
52LOG_MODULE_REGISTER(tcp_nonblock_listener, LOG_LEVEL_INF);
53 #define BACKLOG 1
54
55uint16_t RF24Server::_port;
56bool RF24Server::serverListening;
59RF24Client RF24Server::serverClient;
60uint32_t RF24Server::timeoutTimer;
61RF24Server::RF24Server(uint16_t port)
62{
63 _port = port;
64}
65
66#endif
67/*************************************************************/
68
70{
71
72 Ethernet.tick();
73#if USE_LWIP < 1
74 for (uip_userdata_t* data = &RF24Client::all_data[0]; data < &RF24Client::all_data[UIP_CONNS]; data++)
75 {
76 if (data->packets_in != 0 && (((data->state & UIP_CLIENT_CONNECTED) && uip_conns[data->state & UIP_CLIENT_SOCKETS].lport == _port) || ((data->state & UIP_CLIENT_REMOTECLOSED) && ((uip_userdata_closed_t*)data)->lport == _port)))
77 {
78 return RF24Client(data);
79 }
80 }
81#elif USE_LWIP == 1
82 uint32_t data = 1;
83 return RF24Client(data);
84#elif USE_LWIP == 2
85
86 uint32_t data = 1;
87
88 if (millis() - timeoutTimer > RF24Client::serverConnectionTimeout) {
89 connectionActive = false;
90 if (RF24Client::_socket >= 0) {
91 zsock_close(RF24Client::_socket);
92 RF24Client::_socket = -1;
93 }
94 timeoutTimer = millis();
95 return RF24Client(data);
96 }
97
98 if (!Ethernet.isInitialized || !serverListening || connectionActive || RF24Client::g_rf24client_instance->_socket > 0) {
99 if (RF24Client(data)) {
100 timeoutTimer = millis();
101 }
102 return RF24Client(data);
103 }
104
105 struct sockaddr_in client_addr;
106 socklen_t client_addr_len = sizeof(client_addr);
107
108 // Check once without blocking
109 int client_sock = zsock_accept(serverSocket, (struct sockaddr*)&client_addr, &client_addr_len);
110
111 if (client_sock < 0) {
112 // Check if the "error" is just the expected non-blocking silence
113 if (errno == EAGAIN || errno == EWOULDBLOCK) {
114 // Absolutely normal. No one is connecting right now.
115 if (RF24Client(data)) {
116 timeoutTimer = millis();
117 }
118 return RF24Client(data);
119 }
120
121 // This is a REAL error (e.g., socket closed, invalid descriptor, stack crash)
122 printk("CRITICAL Accept error: %d\n", errno);
123 if (RF24Client(data)) {
124 timeoutTimer = millis();
125 }
126 return RF24Client(data);
127 }
128
129 // Success! A client has successfully connected.
130 printk("Connection accepted (FD: %d)\n", client_sock);
131 connectionActive = true;
132
133 serverClient._socket = client_sock;
134 RF24Client::g_rf24client_instance = &serverClient;
135 timeoutTimer = millis();
136 return serverClient;
137
138#endif
139 return RF24Client();
140}
141
142/*************************************************************/
143
145{
146#if USE_LWIP < 1
147 uip_listen(_port);
148#elif USE_LWIP == 1
149
150 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
151 if (Ethernet.useCoreLocking) {
152 ETHERNET_APPLY_LOCK();
153 }
154 #endif
155
156 bool closed = false;
157
158 if (sPcb == nullptr) {
159 sPcb = tcp_new();
160 }
161
162 if (sPcb != nullptr) {
163 tcp_err(sPcb, RF24Client::error_callback);
164 }
165
166 err_t err = tcp_bind(sPcb, IP_ADDR_ANY, RF24Server::_port);
167
168 if (err != ERR_OK) {
169 //Debug print
170 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println("Server: Unable to bind to port"););
171 }
172
173 if (serverState == nullptr) {
174 serverState = new RF24Client::ConnectState;
175 }
176
177 RF24Client::gState[1]->stateActiveID = 1;
178
179 if (serverState != nullptr) {
180 serverState->connected = false;
181 serverState->result = 0;
182 serverState->waiting_for_ack = false;
183 }
184 sPcb = tcp_listen_with_backlog(sPcb, 1);
185
186 if (sPcb != nullptr) {
187 tcp_arg(sPcb, serverState);
188 tcp_accept(sPcb, RF24Client::accept);
189 }
190 else {
191 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println("Server: Failed to initialize"););
192 }
193
194 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
195 if (Ethernet.useCoreLocking) {
196 ETHERNET_REMOVE_LOCK();
197 }
198 #endif
199
200#elif USE_LWIP == 2
201
202 struct sockaddr_in bind_addr;
203
204 serverSocket = zsock_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
205 if (serverSocket < 0) {
206 printk("Socket creation failed: %d", errno);
207 return;
208 }
209
210 // Bind to port
211 memset(&bind_addr, 0, sizeof(bind_addr));
212 bind_addr.sin_family = AF_INET;
213 bind_addr.sin_port = htons(_port);
214 bind_addr.sin_addr.s_addr = INADDR_ANY;
215
216 if (zsock_bind(serverSocket, (struct sockaddr*)&bind_addr, sizeof(bind_addr)) < 0) {
217 printk("Bind failed: %d", errno);
218 zsock_close(serverSocket);
219 return;
220 }
221
222 // Start listening FIRST while the socket is still in default blocking state
223 if (zsock_listen(serverSocket, BACKLOG) < 0) {
224 printk("Listen failed: %d", errno);
225 zsock_close(serverSocket);
226 return;
227 }
228
229 // CRITICAL MOVE: Set to non-blocking mode ONLY AFTER listening is active
230 int flags = zsock_fcntl(serverSocket, F_GETFL, 0);
231 if (flags < 0 || zsock_fcntl(serverSocket, F_SETFL, flags | O_NONBLOCK) < 0) {
232 printk("Failed to set non-blocking flag: %d", errno);
233 zsock_close(serverSocket);
234 return;
235 }
236
237 serverListening = true;
238 printk("Server initialized successfully!");
239
240#endif
241 RF24Ethernet.tick();
242}
243
244/*************************************************************/
245#if defined(ESP32)
246void RF24Server::begin(uint16_t port)
247{
248 _port = port;
249 begin();
250}
251#endif
252
253/*************************************************************/
254
255size_t RF24Server::write(uint8_t c)
256{
257 return write(&c, 1);
258}
259
260/*************************************************************/
261
262size_t RF24Server::write(const uint8_t* buf, size_t size)
263{
264 size_t ret = 0;
265#if USE_LWIP < 1
266 for (uip_userdata_t* data = &RF24Client::all_data[0]; data < &RF24Client::all_data[UIP_CONNS]; data++)
267 {
268 if ((data->state & UIP_CLIENT_CONNECTED) && uip_conns[data->state & UIP_CLIENT_SOCKETS].lport == _port)
269 ret += RF24Client::_write(data, buf, size);
270 }
271#else
272 uint8_t data;
273 RF24Client::_write(&data, buf, size);
274#endif
275 return ret;
276}
277
278/*************************************************************/
279
280void RF24Server::setTimeout(uint32_t timeout)
281{
282#if USE_LWIP < 1
283 #if UIP_CONNECTION_TIMEOUT > 0
284 for (uint8_t i = 0; i < UIP_CONNS; i++) {
285 uip_userdata_t* data = &RF24Client::all_data[i];
286 if (data) {
287 data->connectTimeout = timeout;
288 }
289 }
290 #endif
291#else
292 RF24Client::serverConnectionTimeout = timeout;
293#endif
294}
#define INCOMING_DATA_SIZE
Definition RF24Client.h:85
RF24EthernetClass RF24Ethernet
static void error_callback(void *arg, err_t err)
static ConnectState * gState[2]
Definition RF24Client.h:226
size_t write(uint8_t)
static int serverSocket
Definition RF24Server.h:54
static bool connectionActive
Definition RF24Server.h:53
RF24Client available()
void setTimeout(uint32_t timeout)
#define Ethernet
#define IF_RF24ETHERNET_DEBUG_CLIENT(x)