2 * Copyright © 2019 Advanced Driver Information Technology GmbH
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial
14 * portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 /*******************************************************************************
30 ** PROJECT : waltham-receiver **
32 ** PURPOSE : This file handles connection with remote-client **
34 *******************************************************************************/
37 #include "wth-receiver-comm.h"
39 #define MAX_EPOLL_WATCHES 2
43 /** Print out the application help
45 static void usage(void)
47 printf("Usage: waltham receiver [options]\n");
49 printf(" -p --port number TCP port number\n");
50 printf(" -h --help Usage\n");
51 printf(" -v --verbose Set verbose flag (Default:%d)\n", get_verbosity());
54 static struct option long_options[] = {
55 {"port", required_argument, 0, 'p'},
56 {"verbose", no_argument, 0, 'v'},
57 {"help", no_argument, 0, 'h'},
64 * Parses the application arguments
65 * The arguments are parsed and saved in static structure for future use.
67 * @param argc The amount of arguments
68 * @param argv The table of arguments
70 * @return 0 on success, -1 otherwise
72 static int parse_args(int argc, char *argv[])
77 while ((c = getopt_long(argc,
86 tcp_port = atoi(optarg);
92 printf("No verbose logs for release mode");
99 wth_error("Try %s -h for more information.\n", argv[0]);
106 wth_error("TCP port not set \n");
107 wth_error("Try %s -h for more information.\n", argv[0]);
115 watch_ctl(struct watch *w, int op, uint32_t events)
117 wth_verbose("%s >>> \n",__func__);
118 struct epoll_event ee;
122 wth_verbose(" <<< %s \n",__func__);
123 return epoll_ctl(w->receiver->epoll_fd, op, w->fd, &ee);
127 * listen_socket_handle_data
129 * Handles all incoming events on socket
131 * @param names struct watch *w ,uint32_t events
132 * @param value pointer to watch connection it holds receiver information, Incoming events information
136 listen_socket_handle_data(struct watch *w, uint32_t events)
138 wth_verbose("%s >>> \n",__func__);
139 struct receiver *srv = container_of(w, struct receiver, listen_watch);
141 if (events & EPOLLERR) {
142 wth_error("Listening socket errored out.\n");
143 srv->running = false;
148 if (events & EPOLLHUP) {
149 wth_error("Listening socket hung up.\n");
150 srv->running = false;
155 if (events & EPOLLIN)
157 wth_verbose("EPOLLIN evnet received. \n");
158 receiver_accept_client(srv);
160 wth_verbose(" <<< %s \n",__func__);
166 * This is the main loop, which will flush all pending clients requests and
167 * listen to input events from socket
169 * @param names void *data
170 * @param value pointer to receiver struct -
171 * struct holds the client connection information
175 receiver_mainloop(struct receiver *srv)
177 wth_verbose("%s >>> \n",__func__);
179 struct epoll_event ee[MAX_EPOLL_WATCHES];
186 while (srv->running) {
187 /* Run any idle tasks at this point. */
189 receiver_flush_clients(srv);
191 /* Wait for events or signals */
192 count = epoll_wait(srv->epoll_fd,
193 ee, ARRAY_LENGTH(ee), -1);
194 if (count < 0 && errno != EINTR) {
195 perror("Error with epoll_wait");
199 /* Handle all fds, both the listening socket
200 * (see listen_socket_handle_data()) and clients
201 * (see connection_handle_data()).
203 for (i = 0; i < count; i++) {
205 w->cb(w, ee[i].events);
208 wth_verbose(" <<< %s \n",__func__);
212 receiver_listen(uint16_t tcp_port)
214 wth_verbose("%s >>> \n",__func__);
217 struct sockaddr_in addr;
219 fd = socket(AF_INET, SOCK_STREAM, 0);
221 memset(&addr, 0, sizeof(addr));
222 addr.sin_family = AF_INET;
223 addr.sin_port = htons(tcp_port);
224 addr.sin_addr.s_addr = htonl(INADDR_ANY);
226 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof reuse);
228 if (bind(fd, (struct sockaddr *)&addr, sizeof addr) < 0) {
229 wth_error("Failed to bind to port %d", tcp_port);
234 if (listen(fd, 1024) < 0) {
235 wth_error("Failed to listen to port %d", tcp_port);
240 wth_verbose(" <<< %s \n",__func__);
244 static bool *signal_int_handler_run_flag;
247 signal_int_handler(int signum)
249 wth_verbose("%s >>> \n",__func__);
250 if (!*signal_int_handler_run_flag)
253 *signal_int_handler_run_flag = false;
254 wth_verbose(" <<< %s \n",__func__);
258 set_sigint_handler(bool *running)
260 wth_verbose("%s >>> \n",__func__);
261 struct sigaction sigint;
263 signal_int_handler_run_flag = running;
264 sigint.sa_handler = signal_int_handler;
265 sigemptyset(&sigint.sa_mask);
266 sigint.sa_flags = SA_RESETHAND;
267 sigaction(SIGINT, &sigint, NULL);
268 wth_verbose(" <<< %s \n",__func__);
274 * waltham receiver main function, it accepts tcp port number as argument.
275 * Establishes connection on the port and listen to port for incoming connection
276 * request from waltham clients
278 * @param names argv - argument list and argc -argument count
279 * @param value tcp port number as argument
280 * @return 0 on success, -1 on error
283 main(int argc, char *argv[])
285 struct receiver srv = { 0 };
288 wth_verbose("%s >>> \n",__func__);
290 /* Get command line arguments */
291 if (parse_args(argc, argv) != 0)
296 set_sigint_handler(&srv.running);
298 wl_list_init(&srv.client_list);
300 srv.epoll_fd = epoll_create1(EPOLL_CLOEXEC);
301 if (srv.epoll_fd == -1) {
302 perror("Error on epoll_create1");
306 srv.listen_fd = receiver_listen(tcp_port);
307 if (srv.listen_fd < 0) {
308 perror("Error setting up listening socket");
312 srv.listen_watch.receiver = &srv;
313 srv.listen_watch.cb = listen_socket_handle_data;
314 srv.listen_watch.fd = srv.listen_fd;
315 if (watch_ctl(&srv.listen_watch, EPOLL_CTL_ADD, EPOLLIN) < 0) {
316 perror("Error setting up listen polling");
320 wth_verbose("Waltham receiver listening on TCP port %u...\n",tcp_port);
323 receiver_mainloop(&srv);
325 /* destroy all things */
326 wl_list_last_until_empty(c, &srv.client_list, link)
329 close(srv.listen_fd);
332 wth_verbose(" <<< %s \n",__func__);