55
66#include " Ethernet.h"
77#include " Server.h"
8+ #include " SignalHandler.h"
89
910namespace arduino {
1011
1112/* *
1213 * A minimal ethernet server
1314 */
15+
1416class EthernetServer : public Server {
1517 private:
1618 uint16_t _port;
1719 int server_fd = 0 ;
1820 struct sockaddr_in server_addr;
1921 int _status = wl_status_t ::WL_DISCONNECTED;
2022 bool is_blocking = false ;
23+ static std::vector<EthernetServer*>& active_servers () {
24+ static std::vector<EthernetServer*> servers;
25+ return servers;
26+ }
27+ static void cleanupAll (int sig) {
28+ for (auto * server : active_servers ()) {
29+ if (server && server->server_fd > 0 ) {
30+ shutdown (server->server_fd , SHUT_RDWR);
31+ close (server->server_fd );
32+ server->server_fd = 0 ;
33+ }
34+ }
35+ }
2136
2237 public:
23- EthernetServer (int port = 80 ) { _port = port; }
24- ~EthernetServer () { stop (); }
38+ EthernetServer (int port = 80 ) {
39+ _port = port;
40+ // Register signal handler only once
41+ static bool signal_registered = false ;
42+ if (!signal_registered) {
43+ SignalHandler::registerHandler (SIGINT, cleanupAll);
44+ SignalHandler::registerHandler (SIGTERM, cleanupAll);
45+ signal_registered = true ;
46+ }
47+ }
48+
49+ ~EthernetServer () {
50+ stop ();
51+ // Remove from active servers list
52+ auto & servers = active_servers ();
53+ auto it = std::find (servers.begin (), servers.end (), this );
54+ if (it != servers.end ()) {
55+ servers.erase (it);
56+ }
57+ }
2558 void begin () { begin (0 ); }
2659 void begin (int port) { begin_ (port); }
2760 void stop () {
28- if (server_fd > 0 ) close (server_fd);
61+ if (server_fd > 0 ) {
62+ // Set SO_LINGER to force immediate close
63+ struct linger linger_opt = {1 , 0 };
64+ setsockopt (server_fd, SOL_SOCKET, SO_LINGER, &linger_opt,
65+ sizeof (linger_opt));
66+
67+ shutdown (server_fd, SHUT_RDWR);
68+ close (server_fd);
69+ }
2970 server_fd = 0 ;
71+ _status = wl_status_t ::WL_DISCONNECTED;
3072 }
3173 WiFiClient accept () { return available_ (); }
3274 WiFiClient available (uint8_t * status = NULL ) { return available_ (); }
@@ -59,6 +101,10 @@ class EthernetServer : public Server {
59101 setsockopt (server_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&iSetOption,
60102 sizeof (iSetOption));
61103
104+ // Set SO_REUSEPORT for better port reuse
105+ setsockopt (server_fd, SOL_SOCKET, SO_REUSEPORT, (char *)&iSetOption,
106+ sizeof (iSetOption));
107+
62108 // config socket
63109 server_addr.sin_family = AF_INET;
64110 server_addr.sin_addr .s_addr = INADDR_ANY;
@@ -82,6 +128,9 @@ class EthernetServer : public Server {
82128 return false ;
83129 }
84130
131+ // Add to active servers list for signal handling
132+ active_servers ().push_back (this );
133+ _status = wl_status_t ::WL_CONNECTED;
85134 return true ;
86135 }
87136
0 commit comments