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