blob: b9010778117608037f540cb54e19004374b7a1fc [file] [log] [blame]
Parker Schuhb59bf5e2016-12-28 21:09:36 -08001#ifndef _AOS_VISION_EVENTS_TCP_SERVER_H_
2#define _AOS_VISION_EVENTS_TCP_SERVER_H_
3
Parker Schuhb59bf5e2016-12-28 21:09:36 -08004#include <memory>
Parker Schuhb59bf5e2016-12-28 21:09:36 -08005
Austin Schuh60e77942022-05-16 17:48:24 -07006#include "aos/vision/events/epoll_events.h"
7#include "aos/vision/events/intrusive_free_list.h"
8
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -08009namespace aos::events {
Parker Schuhb59bf5e2016-12-28 21:09:36 -080010
Stephan Pleinescc500b92024-05-30 10:58:40 -070011// IWYU pragma: begin_keep
Parker Schuhb59bf5e2016-12-28 21:09:36 -080012// Non-templatized base class of TCP server.
13// TCPServer implements Construct which specializes the client connection
14// based on the specific use-case.
15template <class T>
16class TCPServer;
Stephan Pleinescc500b92024-05-30 10:58:40 -070017// IWYU pragma: end_keep
Parker Schuhb59bf5e2016-12-28 21:09:36 -080018class SocketConnection;
Stephan Pleinescc500b92024-05-30 10:58:40 -070019
Parker Schuhb59bf5e2016-12-28 21:09:36 -080020class TCPServerBase : public EpollEvent {
21 public:
22 TCPServerBase(int fd) : EpollEvent(fd) {}
23 ~TCPServerBase();
24
25 protected:
26 // Listens on port portno. File descriptor to
27 // accept on is returned.
28 static int SocketBindListenOnPort(int portno);
29
30 private:
31 virtual SocketConnection *Construct(int child_fd) = 0;
32 void ReadEvent() override;
33 friend class SocketConnection;
34 template <class T>
35 friend class TCPServer;
36 intrusive_free_list<SocketConnection> free_list;
37};
38
39// Base class for client connections. Clients are responsible for
40// deleting themselves once the connection is broken. This will remove
41// the entry from the free list.
42class SocketConnection : public EpollEvent,
43 public intrusive_free_list<SocketConnection>::element {
44 public:
45 SocketConnection(TCPServerBase *server, int fd)
46 : EpollEvent(fd), element(&server->free_list, this) {}
47};
48
49// T should be a subclass of SocketConnection.
50template <class T>
51class TCPServer : public TCPServerBase {
52 public:
53 TCPServer(int port) : TCPServerBase(SocketBindListenOnPort(port)) {}
54 SocketConnection *Construct(int child_fd) override {
55 return new T(this, child_fd);
56 }
57
58 static std::unique_ptr<TCPServer<T>> Make(int port) {
59 return std::unique_ptr<TCPServer<T>>(new TCPServer<T>(port));
60 }
61
62 // Call blk on each entry of the free-list. This is used to send a message
63 // to all clients.
64 template <typename EachBlock>
65 void Broadcast(const EachBlock &blk) {
66 auto a = free_list.begin();
67 while (a) {
68 auto client = static_cast<T *>(a);
69 blk(client);
70 a = a->next();
71 }
72 }
73};
74
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -080075} // namespace aos::events
Parker Schuhb59bf5e2016-12-28 21:09:36 -080076
77#endif // _AOS_VISION_EVENTS_TCP_SERVER_H_