Repository navigation
Expand file tree
/
Copy pathlwip_echosrv.ino
More file actions
193 lines (159 loc) · 4.7 KB
/
Copy pathlwip_echosrv.ino
File metadata and controls
193 lines (159 loc) · 4.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
// lwip test framework
#include "lwipopts.h"
#include "lwip_t41.h"
#include "lwip/inet.h"
#include "lwip/dhcp.h"
#include "lwip/udp.h"
#include "lwip/tcp.h"
#define DO_VLANS
#define swap2 __builtin_bswap16
#define swap4 __builtin_bswap32
#ifdef DO_VLANS
struct netif vlan3_netif;
#endif
ip4_addr multicast_addr;
#ifdef LWIP_DEBUG
void debug_print(const char *msg) {
Serial.print(msg);
}
#endif
static void netif_status_callback(struct netif *netif)
{
static char str1[IP4ADDR_STRLEN_MAX], str2[IP4ADDR_STRLEN_MAX], str3[IP4ADDR_STRLEN_MAX];
Serial.printf("netif %c%c status changed: ip %s, mask %s, gw %s\n", netif->name[0], netif->name[1], ip4addr_ntoa_r(netif_ip_addr4(netif), str1, IP4ADDR_STRLEN_MAX), ip4addr_ntoa_r(netif_ip_netmask4(netif), str2, IP4ADDR_STRLEN_MAX), ip4addr_ntoa_r(netif_ip_gw4(netif), str3, IP4ADDR_STRLEN_MAX));
}
static void link_status_callback(struct netif *netif)
{
Serial.printf("enet netif %c%c link status: %s\n", netif->name[0], netif->name[1], netif_is_link_up(netif) ? "up" : "down");
#ifdef DO_VLANS
if (netif == netif_default) {
if (netif_is_link_up(netif_default)) {
netif_set_link_up(&vlan3_netif);
} else {
netif_set_link_down(&vlan3_netif);
}
}
#endif
}
// UDP callbacks
// fancy would be pbuf recv_q per UDP pcb, if q full, drop and free pbuf
// udp echo recv callback
void udp_callback(void * arg, struct udp_pcb * upcb, struct pbuf * p, const ip_addr_t * addr, u16_t port)
{
struct udp_pcb *pcb;
struct pbuf *pb;
if (p == NULL) return;
pb = pbuf_alloc(PBUF_TRANSPORT, p->tot_len, PBUF_RAM);
pbuf_take(pb, p->payload, p->tot_len);
upcb->tos = 0xB8; // DOB THIS IS WHERE TOS IS SET?
udp_sendto(upcb, p, addr, port);
pcb = udp_new();
udp_sendto(pcb, pb, &multicast_addr, 77);
pbuf_free(p);
pbuf_free(pb);
udp_remove(pcb);
}
void udp_echosrv() {
struct udp_pcb *pcb;
Serial.println("udp echosrv on port 7");
pcb = udp_new();
udp_bind(pcb, IP_ADDR_ANY, 7); // local port
udp_recv(pcb, udp_callback, NULL); // do once?
// fall into loop ether_poll
}
// ----- TCP ------
void echo_close(struct tcp_pcb * tpcb) {
Serial.println("echo TCP close");
tcp_recv(tpcb, NULL);
tcp_err(tpcb, NULL);
tcp_close(tpcb);
}
void tcperr_callback(void * arg, err_t err)
{
// set with tcp_err()
Serial.print("TCP err "); Serial.println(err);
*(int *)arg = err;
}
static struct tcp_pcb * pcbl; // listen pcb
void listen_err_callback(void * arg, err_t err)
{
// set with tcp_err()
Serial.print("TCP listen err "); Serial.println(err);
*(int *)arg = err;
}
err_t recv_callback(void * arg, struct tcp_pcb * tpcb, struct pbuf * p, err_t err)
{
if (p == NULL) {
// other end closed
echo_close(tpcb);
return 0;
}
// echo it back, not expecting our write to exceed sendqlth
tcp_write(tpcb, p->payload, p->tot_len, TCP_WRITE_FLAG_COPY); // PUSH
tcp_output(tpcb); // ?needed
tcp_recved(tpcb, p->tot_len); // data processed
pbuf_free(p);
return 0;
}
err_t accept_callback(void * arg, struct tcp_pcb * newpcb, err_t err) {
if (err || !newpcb) {
Serial.print("accept err "); Serial.println(err);
delay(100);
return 1;
}
Serial.println("accepted");
tcp_recv(newpcb, recv_callback);
tcp_err(newpcb, tcperr_callback);
// tcp_accepted(pcbl); // ref says the listen pcb
return 0;
}
void tcp_echosrv() {
struct tcp_pcb * pcb;
pcb = tcp_new();
tcp_bind(pcb, IP_ADDR_ANY, 7); // server port
pcbl = tcp_listen(pcb); // pcb deallocated
tcp_err(pcbl, listen_err_callback);
Serial.println("server listening on 7");
tcp_accept(pcbl, accept_callback);
// fall through to main ether_poll loop ....
}
void setup()
{
Serial.begin(115200);
while (!Serial) delay(100);
#ifdef LWIP_DEBUG
set_debug_print(debug_print);
#endif
IP4_ADDR(&multicast_addr,239,0,0,1);
enet_init(NULL, NULL, NULL);
#ifdef DO_VLANS
netif_add_vlan(&vlan3_netif, IP_ADDR_ANY, IP_ADDR_ANY, IP_ADDR_ANY, 3, 0, t41_extra_netif_init, 0);
netif_set_up(&vlan3_netif);
#endif
netif_set_status_callback(netif_default, netif_status_callback);
netif_set_link_callback(netif_default, link_status_callback);
netif_set_vlan_id(netif_default, 1);
netif_set_up(netif_default);
dhcp_start(netif_default);
#ifdef DO_VLANS
netif_set_status_callback(&vlan3_netif, netif_status_callback);
netif_set_link_callback(&vlan3_netif, link_status_callback);
dhcp_start(&vlan3_netif);
while (!netif_is_link_up(&vlan3_netif)) loop(); // await on link up
#endif
while (!netif_is_link_up(netif_default)) loop(); // await on link up
udp_echosrv();
tcp_echosrv();
}
void loop()
{
static uint32_t last_ms;
uint32_t ms;
enet_proc_input();
ms = millis();
if (ms - last_ms > 100)
{
last_ms = ms;
enet_poll();
}
}