My Project
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros
socket_monitor.c
Go to the documentation of this file.
1 /*
2 START OF LICENSE STUB
3  DeDOS: Declarative Dispersion-Oriented Software
4  Copyright (C) 2017 University of Pennsylvania, Georgetown University
5 
6  This program is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program. If not, see <http://www.gnu.org/licenses/>.
18 END OF LICENSE STUB
19 */
25 #include "epollops.h"
26 #include "communication.h"
27 #include "logging.h"
29 #include "runtime_communication.h"
30 
31 #include <sys/epoll.h>
32 
34 #define MAX_RUNTIME_FD 1024
35 
37 
39 int runtime_socket = -1;
41 int epoll_fd = -1;
42 
44 static int init_socket_monitor(int port) {
45  if (runtime_socket > 0) {
46  log_error("Runtime socket already initialized to %d. Cannot reinitialize",
48  return -1;
49  }
51  if (runtime_socket < 0) {
52  log_error("Error initializing runtime socket on port %d", port);
53  return -1;
54  }
55  log_info("Initialized runtime socket on port %d", port);
56 
58 
59  if (epoll_fd < 0) {
60  log_error("Error initializing runtime epoll. Closing runtime socket.");
61  close(runtime_socket);
62  return -1;
63  }
64 
65  return 0;
66 }
67 
69 static int handle_connection(int fd, void *data) {
70  if (runtime_fds[fd]) {
71  int rtn = handle_runtime_communication(fd);
72  if (rtn != 0) {
73  return rtn;
74  }
75  return 0;
76  } else {
77  // It's a controller file descriptor. Can add check if necessary,
78  // but this epoll should only handle runtimes or controller
79  int rtn = handle_controller_communication(fd);
80  if (rtn != 0) {
81  return rtn;
82  }
83  return 0;
84  }
85  return 0;
86 }
87 
89 static int accept_connection(int fd, void *data) {
90  if (fd > MAX_RUNTIME_FD) {
91  log_error("Cannot accept runtime connection on file descriptor greater than %d",
93  // note: returning 0, not -1, because -1 will make epoll loop exit
94  return 0;
95  }
96  runtime_fds[fd] = true;
97  return 0;
98 }
99 
102  if (runtime_socket == -1 || epoll_fd == -1) {
103  log_error("Runtime socket or epoll not initialized. Cannot start monitor loop");
104  return -1;
105  }
106 
107  int rtn = epoll_loop(runtime_socket, epoll_fd, -1, -1, 0,
109  if (rtn < 0) {
110  log_error("Epoll loop exited with error");
111  }
112  log_info("Epoll loop exited");
113  return rtn;
114 }
115 
116 int monitor_controller_socket(int new_fd) {
117  if ( epoll_fd == -1 ) {
118  log_error("Epoll not initialized. Cannot monitor new socket");
119  return -1;
120  }
121 
122  int rtn = add_to_epoll(epoll_fd, new_fd, EPOLLIN, false);
123  if (rtn < 0) {
124  log_perror("Error adding socket %d to epoll", new_fd);
125  return -1;
126  }
127  return 0;
128 }
129 
130 int monitor_runtime_socket(int new_fd) {
131  if ( epoll_fd == -1 ) {
132  log_error("Epoll not initialized. Cannot monitor new socket");
133  return -1;
134  }
135 
136  int rtn = add_to_epoll(epoll_fd, new_fd, EPOLLIN, false);
137  runtime_fds[new_fd] = true;
138  if (rtn < 0) {
139  log_perror("Error adding socket %d to epoll", new_fd);
140  return -1;
141  }
142  return 0;
143 }
144 
145 int run_socket_monitor(int local_port, struct sockaddr_in *ctrl_addr) {
146  int rtn = init_socket_monitor(local_port);
147  if (rtn < 0) {
148  log_critical("Error initializing socket monitor");
149  return -1;
150  }
151 
152  int sock;
153  do {
154  log_info("Attempting to connect to controller");
155  sock = init_controller_socket(ctrl_addr);
156  if (sock < 0)
157  sleep(1);
158  } while (sock <= 0);
159 
160  log_info("Connected to global controller on socket %d. Entering socket monitor loop.", sock);
161 
162  return socket_monitor_epoll_loop();
163 }
Interface for general-purpose socket communication.
#define log_info(fmt,...)
Definition: logging.h:88
Socket-handling between runtimes.
Wrapper functions for epoll to manage event-based communication.
int monitor_runtime_socket(int new_fd)
Adds a runtime to be monitored by the socket monitor.
int epoll_fd
The epoll file descriptor monitoring sockets.
#define log_critical(fmt,...)
Definition: logging.h:124
#define log_perror(fmt,...)
Definition: logging.h:102
Logging of status messages to the terminal.
int init_controller_socket(struct sockaddr_in *addr)
Initilizes a connection with the global controller located at the provided address.
int handle_runtime_communication(int fd)
Reads a message off of the provided file descriptor as if it is coming from a runtime peer...
int add_to_epoll(int epoll_fd, int new_fd, uint32_t events, bool oneshot)
Adds a file descriptor to an epoll instance.
Definition: epollops.c:59
int init_epoll(int socket_fd)
Initializes a new instance of an epoll file descriptor and adds a socket to it, listening for input o...
Definition: epollops.c:182
#define log_error(fmt,...)
Definition: logging.h:101
int monitor_controller_socket(int new_fd)
Adds the global controller to be monitored by the socket monitor.
int runtime_socket
The socket on which incoming connections are monitored.
int epoll_loop(int socket_fd, int epoll_fd, int batch_size, int timeout, bool oneshot, int(*connection_handler)(int, void *), int(*accept_handler)(int, void *), void *data)
The event-based loop for epoll_wait.
Definition: epollops.c:132
static bool runtime_fds[1024]
Whether the file descriptor has been associated with a runtime.
static int accept_connection(int fd, void *data)
Accepts a new connection.
int init_runtime_socket(int listen_port)
Initializes the socket listening for incoming connections.
static int init_socket_monitor(int port)
Initializes the socket monitor on the given port.
static int handle_connection(int fd, void *data)
Checks if the file descriptor is a runtime or controller, and handles it appropraitely.
int run_socket_monitor(int local_port, struct sockaddr_in *ctrl_addr)
Starts (blocking) the socket monitor, listening on the provided port.
int handle_controller_communication(int fd)
Reads and processes a controller message off of the provided file descriptor.
#define MAX_RUNTIME_FD
The maximum file descriptor that can be associated with a runtime.
static int socket_monitor_epoll_loop()
The main loop for the socket monitor.
Communication with global controller from runtime.