arduino-emulator
Loading...
Searching...
No Matches
EthernetServerWindows.h
1#pragma once
2
3#include "DesktopSocket.h"
4#include "Ethernet.h"
5#include "api/Server.h"
6#include "SignalHandler.h"
7
8namespace arduino {
9
10class EthernetServer : public Server {
11 private:
12 uint16_t _port;
13 SocketHandle server_fd = INVALID_SOCKET_HANDLE;
14 struct sockaddr_in server_addr;
15 int _status = wl_status_t::WL_DISCONNECTED;
16 bool is_blocking = false;
17 bool _noDelay = false;
18
19 static std::vector<EthernetServer*>& active_servers() {
20 static std::vector<EthernetServer*> servers;
21 return servers;
22 }
23 static void cleanupAll(int) {
24 for (auto* server : active_servers()) {
25 if (server && server->server_fd != INVALID_SOCKET_HANDLE) {
26 shutdown(server->server_fd, SHUT_RDWR);
27 closeSocket(server->server_fd);
28 server->server_fd = INVALID_SOCKET_HANDLE;
29 }
30 }
31 }
32
33 public:
34 EthernetServer(int port = 80) : _port(port) {
35 static bool signal_registered = false;
36 if (!signal_registered) {
37 SignalHandler::registerHandler(SIGINT, cleanupAll);
38 SignalHandler::registerHandler(SIGTERM, cleanupAll);
39 signal_registered = true;
40 }
41 }
42 ~EthernetServer() {
43 stop();
44 auto& servers = active_servers();
45 auto it = std::find(servers.begin(), servers.end(), this);
46 if (it != servers.end()) servers.erase(it);
47 }
48
49 void begin() { begin(_port); }
50 void begin(int port) { begin_(port); }
51 void stop() {
52 if (server_fd != INVALID_SOCKET_HANDLE) {
53 struct linger linger_opt = {1, 0};
54 setsockopt(server_fd, SOL_SOCKET, SO_LINGER,
55 reinterpret_cast<const char*>(&linger_opt), sizeof(linger_opt));
56 shutdown(server_fd, SHUT_RDWR);
57 closeSocket(server_fd);
58 }
59 server_fd = INVALID_SOCKET_HANDLE;
60 _status = wl_status_t::WL_DISCONNECTED;
61 }
62 WiFiClient accept() { return available_(); }
63 WiFiClient available(uint8_t* = nullptr) { return available_(); }
64 size_t write(uint8_t ch) override { return write(&ch, 1); }
65 size_t write(const uint8_t* buf, size_t size) override {
66 int rc = ::send(server_fd, reinterpret_cast<const char*>(buf), static_cast<int>(size), 0);
67 return rc < 0 ? 0 : rc;
68 }
69 int status() { return _status; }
70 void setNoDelay(bool nodelay) { _noDelay = nodelay; }
71 bool getNoDelay() { return _noDelay; }
72 bool hasClient() {
73 if (server_fd == INVALID_SOCKET_HANDLE) return false;
74 WSAPOLLFD pfd{};
75 pfd.fd = server_fd;
76 pfd.events = POLLRDNORM;
77 return WSAPoll(&pfd, 1, 0) > 0 && (pfd.revents & POLLRDNORM);
78 }
79 using Print::write;
80
81 protected:
82 bool begin_(int port = 0) {
83 if (port > 0) _port = port;
84 _status = wl_status_t::WL_DISCONNECTED;
85 ensureSocketRuntime();
86 if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET_HANDLE) {
87 _status = wl_status_t::WL_CONNECT_FAILED;
88 return false;
89 }
90 int option = 1;
91 setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR,
92 reinterpret_cast<const char*>(&option), sizeof(option));
93 server_addr.sin_family = AF_INET;
94 server_addr.sin_addr.s_addr = INADDR_ANY;
95 server_addr.sin_port = htons(_port);
96 while (::bind(server_fd, reinterpret_cast<struct sockaddr*>(&server_addr),
97 sizeof(server_addr)) < 0) {
98 Logger.error("bind failed");
99 delay(1000);
100 }
101 if (::listen(server_fd, 10) < 0) {
102 _status = wl_status_t::WL_CONNECT_FAILED;
103 Logger.error("listen failed");
104 return false;
105 }
106 _noDelay = false;
107 active_servers().push_back(this);
108 _status = wl_status_t::WL_CONNECTED;
109 return true;
110 }
111 void setBlocking(bool flag) { is_blocking = flag; }
112
113 EthernetClient available_() {
114 struct sockaddr_in client_addr;
115 SocketLength client_addr_len = sizeof(client_addr);
116 SocketHandle client_fd;
117 if (_status == wl_status_t::WL_CONNECT_FAILED) begin(_port);
118 WSAPOLLFD pfd{};
119 pfd.fd = server_fd;
120 pfd.events = POLLRDNORM;
121 int poll_rc = WSAPoll(&pfd, 1, 200);
122 if (!is_blocking && (poll_rc <= 0 || !(pfd.revents & POLLRDNORM)))
123 return EthernetClient(nullptr);
124 if ((client_fd = ::accept(server_fd, reinterpret_cast<struct sockaddr*>(&client_addr),
125 &client_addr_len)) == INVALID_SOCKET_HANDLE) {
126 Logger.error("accept failed");
127 return EthernetClient(nullptr);
128 }
129 setSocketNonBlocking(client_fd);
130 return EthernetClient(std::make_shared<SocketImpl>(client_fd, &client_addr));
131 }
132};
133
134} // namespace arduino
We provide the WiFi class to simulate the Arduino WIFI. In in Linux we can expect that networking is ...
Definition CanMsg.cpp:31
EthernetClient WiFiClient
Alias for EthernetClient to provide WiFiClient compatibility.
Definition WiFiClient.h:28