blob: cf4dd7fe02ac2cfdf2a7598b0a49cfa5b9efb818 [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
19namespace aos {
20namespace events {
21
22namespace {
23
24int MakeSocketNonBlocking(int sfd) {
25 int flags;
26
Austin Schuhf257f3c2019-10-27 21:00:43 -070027 AOS_PCHECK(flags = fcntl(sfd, F_GETFL, 0));
Parker Schuhb59bf5e2016-12-28 21:09:36 -080028
29 flags |= O_NONBLOCK;
Austin Schuhf257f3c2019-10-27 21:00:43 -070030 AOS_PCHECK(fcntl(sfd, F_SETFL, flags));
Parker Schuhb59bf5e2016-12-28 21:09:36 -080031
32 return 0;
33}
34} // namespace
35
36// This is all copied from somewhere.
37int TCPServerBase::SocketBindListenOnPort(int portno) {
38 int parentfd; /* parent socket */
39 struct sockaddr_in serveraddr; /* server's addr */
40 int optval; /* flag value for setsockopt */
41
42 /*
43 * socket: create the parent socket
44 */
Austin Schuhf257f3c2019-10-27 21:00:43 -070045 AOS_PCHECK(parentfd = socket(AF_INET, SOCK_STREAM, 0));
Parker Schuhb59bf5e2016-12-28 21:09:36 -080046
47 /* setsockopt: Handy debugging trick that lets
48 * us rerun the server immediately after we kill it;
49 * otherwise we have to wait about 20 secs.
50 * Eliminates "ERROR on binding: Address already in use" error.
51 */
52 optval = 1;
Austin Schuhf257f3c2019-10-27 21:00:43 -070053 AOS_PCHECK(setsockopt(parentfd, SOL_SOCKET, SO_REUSEADDR,
54 (const void *)&optval, sizeof(int)));
Parker Schuhb59bf5e2016-12-28 21:09:36 -080055
56 /*
57 * build the server's Internet address
58 */
59 bzero((char *)&serveraddr, sizeof(serveraddr));
60
61 /* this is an Internet address */
62 serveraddr.sin_family = AF_INET;
63
64 /* Listen on 0.0.0.0 */
65 serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
66
67 /* this is the port we will listen on */
68 serveraddr.sin_port = htons((uint16_t)portno);
69
70 /*
71 * bind: associate the parent socket with a port
72 */
Austin Schuhf257f3c2019-10-27 21:00:43 -070073 AOS_PCHECK(
74 bind(parentfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)));
Parker Schuhb59bf5e2016-12-28 21:09:36 -080075
Austin Schuhf257f3c2019-10-27 21:00:43 -070076 AOS_PCHECK(listen(parentfd, SOMAXCONN));
Parker Schuhb59bf5e2016-12-28 21:09:36 -080077
Austin Schuhf257f3c2019-10-27 21:00:43 -070078 AOS_LOG(INFO, "connected to port: %d on fd: %d\n", portno, parentfd);
Parker Schuhb59bf5e2016-12-28 21:09:36 -080079 return parentfd;
80}
81
82TCPServerBase::~TCPServerBase() { close(fd()); }
83
84void TCPServerBase::ReadEvent() {
85 /* We have a notification on the listening socket, which
86 means one or more incoming connections. */
87 struct sockaddr in_addr;
88 socklen_t in_len;
89 int infd;
90
91 in_len = sizeof in_addr;
92 infd = accept(fd(), &in_addr, &in_len);
93 if (infd == -1) {
94 if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
95 /* We have processed all incoming
96 connections. */
97 return;
98 } else {
Austin Schuhf257f3c2019-10-27 21:00:43 -070099 AOS_PLOG(WARNING, "accept");
Parker Schuhb59bf5e2016-12-28 21:09:36 -0800100 return;
101 }
102 }
103
104 /* Make the incoming socket non-blocking and add it to the
105 list of fds to monitor. */
Austin Schuhf257f3c2019-10-27 21:00:43 -0700106 AOS_PCHECK(MakeSocketNonBlocking(infd));
Parker Schuhb59bf5e2016-12-28 21:09:36 -0800107
108 loop()->Add(Construct(infd));
109}
110
111} // namespace events
112} // namespace aos