blob: 38e28745fe03f3650ba9f2d082a7bb5f69eb8498 [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>
Parker Schuhb59bf5e2016-12-28 21:09:36 -08005#include <netinet/in.h>
Stephan Pleinescc500b92024-05-30 10:58:40 -07006#include <stdint.h>
7#include <strings.h>
Parker Schuhb59bf5e2016-12-28 21:09:36 -08008#include <sys/socket.h>
Parker Schuhb59bf5e2016-12-28 21:09:36 -08009#include <unistd.h>
10
Tyler Chatowbf0609c2021-07-31 16:13:27 -070011#include <cerrno>
Tyler Chatowbf0609c2021-07-31 16:13:27 -070012
John Park33858a32018-09-28 23:05:48 -070013#include "aos/logging/logging.h"
Parker Schuhb59bf5e2016-12-28 21:09:36 -080014
Stephan Pleinesf63bde82024-01-13 15:59:33 -080015namespace aos::events {
Parker Schuhb59bf5e2016-12-28 21:09:36 -080016
17namespace {
18
19int MakeSocketNonBlocking(int sfd) {
20 int flags;
21
Austin Schuhf257f3c2019-10-27 21:00:43 -070022 AOS_PCHECK(flags = fcntl(sfd, F_GETFL, 0));
Parker Schuhb59bf5e2016-12-28 21:09:36 -080023
24 flags |= O_NONBLOCK;
Austin Schuhf257f3c2019-10-27 21:00:43 -070025 AOS_PCHECK(fcntl(sfd, F_SETFL, flags));
Parker Schuhb59bf5e2016-12-28 21:09:36 -080026
27 return 0;
28}
29} // namespace
30
31// This is all copied from somewhere.
32int TCPServerBase::SocketBindListenOnPort(int portno) {
33 int parentfd; /* parent socket */
34 struct sockaddr_in serveraddr; /* server's addr */
35 int optval; /* flag value for setsockopt */
36
37 /*
38 * socket: create the parent socket
39 */
Austin Schuhf257f3c2019-10-27 21:00:43 -070040 AOS_PCHECK(parentfd = socket(AF_INET, SOCK_STREAM, 0));
Parker Schuhb59bf5e2016-12-28 21:09:36 -080041
42 /* setsockopt: Handy debugging trick that lets
43 * us rerun the server immediately after we kill it;
44 * otherwise we have to wait about 20 secs.
45 * Eliminates "ERROR on binding: Address already in use" error.
46 */
47 optval = 1;
Austin Schuhf257f3c2019-10-27 21:00:43 -070048 AOS_PCHECK(setsockopt(parentfd, SOL_SOCKET, SO_REUSEADDR,
49 (const void *)&optval, sizeof(int)));
Parker Schuhb59bf5e2016-12-28 21:09:36 -080050
51 /*
52 * build the server's Internet address
53 */
54 bzero((char *)&serveraddr, sizeof(serveraddr));
55
56 /* this is an Internet address */
57 serveraddr.sin_family = AF_INET;
58
59 /* Listen on 0.0.0.0 */
60 serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
61
62 /* this is the port we will listen on */
63 serveraddr.sin_port = htons((uint16_t)portno);
64
65 /*
66 * bind: associate the parent socket with a port
67 */
Austin Schuhf257f3c2019-10-27 21:00:43 -070068 AOS_PCHECK(
69 bind(parentfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)));
Parker Schuhb59bf5e2016-12-28 21:09:36 -080070
Austin Schuhf257f3c2019-10-27 21:00:43 -070071 AOS_PCHECK(listen(parentfd, SOMAXCONN));
Parker Schuhb59bf5e2016-12-28 21:09:36 -080072
Austin Schuhf257f3c2019-10-27 21:00:43 -070073 AOS_LOG(INFO, "connected to port: %d on fd: %d\n", portno, parentfd);
Parker Schuhb59bf5e2016-12-28 21:09:36 -080074 return parentfd;
75}
76
77TCPServerBase::~TCPServerBase() { close(fd()); }
78
79void TCPServerBase::ReadEvent() {
80 /* We have a notification on the listening socket, which
81 means one or more incoming connections. */
82 struct sockaddr in_addr;
83 socklen_t in_len;
84 int infd;
85
86 in_len = sizeof in_addr;
87 infd = accept(fd(), &in_addr, &in_len);
88 if (infd == -1) {
89 if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
90 /* We have processed all incoming
91 connections. */
92 return;
93 } else {
Austin Schuhf257f3c2019-10-27 21:00:43 -070094 AOS_PLOG(WARNING, "accept");
Parker Schuhb59bf5e2016-12-28 21:09:36 -080095 return;
96 }
97 }
98
99 /* Make the incoming socket non-blocking and add it to the
100 list of fds to monitor. */
Austin Schuhf257f3c2019-10-27 21:00:43 -0700101 AOS_PCHECK(MakeSocketNonBlocking(infd));
Parker Schuhb59bf5e2016-12-28 21:09:36 -0800102
103 loop()->Add(Construct(infd));
104}
105
Stephan Pleinesf63bde82024-01-13 15:59:33 -0800106} // namespace aos::events