blob: fa2a369a5924240248867951d2ec3e2d1460d065 [file] [log] [blame]
Parker Schuhb59bf5e2016-12-28 21:09:36 -08001#include "aos/vision/events/tcp_server.h"
2
3#include <arpa/inet.h>
Parker Schuhb59bf5e2016-12-28 21:09:36 -08004#include <fcntl.h>
5#include <netdb.h>
6#include <netinet/in.h>
Parker Schuhb59bf5e2016-12-28 21:09:36 -08007#include <sys/epoll.h>
8#include <sys/socket.h>
9#include <sys/types.h>
10#include <unistd.h>
11
Tyler Chatowbf0609c2021-07-31 16:13:27 -070012#include <cerrno>
13#include <cstdio>
14#include <cstdlib>
15#include <cstring>
16
John Park33858a32018-09-28 23:05:48 -070017#include "aos/logging/logging.h"
Parker Schuhb59bf5e2016-12-28 21:09:36 -080018
Stephan Pleinesf63bde82024-01-13 15:59:33 -080019namespace aos::events {
Parker Schuhb59bf5e2016-12-28 21:09:36 -080020
21namespace {
22
23int MakeSocketNonBlocking(int sfd) {
24 int flags;
25
Austin Schuhf257f3c2019-10-27 21:00:43 -070026 AOS_PCHECK(flags = fcntl(sfd, F_GETFL, 0));
Parker Schuhb59bf5e2016-12-28 21:09:36 -080027
28 flags |= O_NONBLOCK;
Austin Schuhf257f3c2019-10-27 21:00:43 -070029 AOS_PCHECK(fcntl(sfd, F_SETFL, flags));
Parker Schuhb59bf5e2016-12-28 21:09:36 -080030
31 return 0;
32}
33} // namespace
34
35// This is all copied from somewhere.
36int TCPServerBase::SocketBindListenOnPort(int portno) {
37 int parentfd; /* parent socket */
38 struct sockaddr_in serveraddr; /* server's addr */
39 int optval; /* flag value for setsockopt */
40
41 /*
42 * socket: create the parent socket
43 */
Austin Schuhf257f3c2019-10-27 21:00:43 -070044 AOS_PCHECK(parentfd = socket(AF_INET, SOCK_STREAM, 0));
Parker Schuhb59bf5e2016-12-28 21:09:36 -080045
46 /* setsockopt: Handy debugging trick that lets
47 * us rerun the server immediately after we kill it;
48 * otherwise we have to wait about 20 secs.
49 * Eliminates "ERROR on binding: Address already in use" error.
50 */
51 optval = 1;
Austin Schuhf257f3c2019-10-27 21:00:43 -070052 AOS_PCHECK(setsockopt(parentfd, SOL_SOCKET, SO_REUSEADDR,
53 (const void *)&optval, sizeof(int)));
Parker Schuhb59bf5e2016-12-28 21:09:36 -080054
55 /*
56 * build the server's Internet address
57 */
58 bzero((char *)&serveraddr, sizeof(serveraddr));
59
60 /* this is an Internet address */
61 serveraddr.sin_family = AF_INET;
62
63 /* Listen on 0.0.0.0 */
64 serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
65
66 /* this is the port we will listen on */
67 serveraddr.sin_port = htons((uint16_t)portno);
68
69 /*
70 * bind: associate the parent socket with a port
71 */
Austin Schuhf257f3c2019-10-27 21:00:43 -070072 AOS_PCHECK(
73 bind(parentfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)));
Parker Schuhb59bf5e2016-12-28 21:09:36 -080074
Austin Schuhf257f3c2019-10-27 21:00:43 -070075 AOS_PCHECK(listen(parentfd, SOMAXCONN));
Parker Schuhb59bf5e2016-12-28 21:09:36 -080076
Austin Schuhf257f3c2019-10-27 21:00:43 -070077 AOS_LOG(INFO, "connected to port: %d on fd: %d\n", portno, parentfd);
Parker Schuhb59bf5e2016-12-28 21:09:36 -080078 return parentfd;
79}
80
81TCPServerBase::~TCPServerBase() { close(fd()); }
82
83void TCPServerBase::ReadEvent() {
84 /* We have a notification on the listening socket, which
85 means one or more incoming connections. */
86 struct sockaddr in_addr;
87 socklen_t in_len;
88 int infd;
89
90 in_len = sizeof in_addr;
91 infd = accept(fd(), &in_addr, &in_len);
92 if (infd == -1) {
93 if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
94 /* We have processed all incoming
95 connections. */
96 return;
97 } else {
Austin Schuhf257f3c2019-10-27 21:00:43 -070098 AOS_PLOG(WARNING, "accept");
Parker Schuhb59bf5e2016-12-28 21:09:36 -080099 return;
100 }
101 }
102
103 /* Make the incoming socket non-blocking and add it to the
104 list of fds to monitor. */
Austin Schuhf257f3c2019-10-27 21:00:43 -0700105 AOS_PCHECK(MakeSocketNonBlocking(infd));
Parker Schuhb59bf5e2016-12-28 21:09:36 -0800106
107 loop()->Add(Construct(infd));
108}
109
Stephan Pleinesf63bde82024-01-13 15:59:33 -0800110} // namespace aos::events