blob: 49a5a8cba2fb61fbc2d3ed77af862f9e93dfb926 [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>
5#include <vector>
6
Austin Schuh60e77942022-05-16 17:48:24 -07007#include "aos/vision/events/epoll_events.h"
8#include "aos/vision/events/intrusive_free_list.h"
9
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -080010namespace aos::events {
Parker Schuhb59bf5e2016-12-28 21:09:36 -080011
12// 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;
17class SocketConnection;
18class TCPServerBase : public EpollEvent {
19 public:
20 TCPServerBase(int fd) : EpollEvent(fd) {}
21 ~TCPServerBase();
22
23 protected:
24 // Listens on port portno. File descriptor to
25 // accept on is returned.
26 static int SocketBindListenOnPort(int portno);
27
28 private:
29 virtual SocketConnection *Construct(int child_fd) = 0;
30 void ReadEvent() override;
31 friend class SocketConnection;
32 template <class T>
33 friend class TCPServer;
34 intrusive_free_list<SocketConnection> free_list;
35};
36
37// Base class for client connections. Clients are responsible for
38// deleting themselves once the connection is broken. This will remove
39// the entry from the free list.
40class SocketConnection : public EpollEvent,
41 public intrusive_free_list<SocketConnection>::element {
42 public:
43 SocketConnection(TCPServerBase *server, int fd)
44 : EpollEvent(fd), element(&server->free_list, this) {}
45};
46
47// T should be a subclass of SocketConnection.
48template <class T>
49class TCPServer : public TCPServerBase {
50 public:
51 TCPServer(int port) : TCPServerBase(SocketBindListenOnPort(port)) {}
52 SocketConnection *Construct(int child_fd) override {
53 return new T(this, child_fd);
54 }
55
56 static std::unique_ptr<TCPServer<T>> Make(int port) {
57 return std::unique_ptr<TCPServer<T>>(new TCPServer<T>(port));
58 }
59
60 // Call blk on each entry of the free-list. This is used to send a message
61 // to all clients.
62 template <typename EachBlock>
63 void Broadcast(const EachBlock &blk) {
64 auto a = free_list.begin();
65 while (a) {
66 auto client = static_cast<T *>(a);
67 blk(client);
68 a = a->next();
69 }
70 }
71};
72
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -080073} // namespace aos::events
Parker Schuhb59bf5e2016-12-28 21:09:36 -080074
75#endif // _AOS_VISION_EVENTS_TCP_SERVER_H_