1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2018 Intel Corporation
11 #include <sys/socket.h>
13 #include <sys/epoll.h>
14 #include <netinet/in.h>
15 #include <arpa/inet.h>
20 #define MSG_CMD_TOO_LONG "Command too long."
29 size_t msg_in_len_max;
30 size_t msg_out_len_max;
34 conn_msg_handle_t msg_handle;
38 conn_init(struct conn_params *p)
40 struct sockaddr_in server_address;
42 int fd_server, fd_client_group, status;
44 memset(&server_address, 0, sizeof(server_address));
46 /* Check input arguments */
48 (p->welcome == NULL) ||
49 (p->prompt == NULL) ||
52 (p->msg_in_len_max == 0) ||
53 (p->msg_out_len_max == 0) ||
54 (p->msg_handle == NULL))
57 status = inet_aton(p->addr, &server_address.sin_addr);
61 /* Memory allocation */
62 conn = calloc(1, sizeof(struct conn));
66 conn->welcome = calloc(1, CONN_WELCOME_LEN_MAX + 1);
67 conn->prompt = calloc(1, CONN_PROMPT_LEN_MAX + 1);
68 conn->buf = calloc(1, p->buf_size);
69 conn->msg_in = calloc(1, p->msg_in_len_max + 1);
70 conn->msg_out = calloc(1, p->msg_out_len_max + 1);
72 if ((conn->welcome == NULL) ||
73 (conn->prompt == NULL) ||
74 (conn->buf == NULL) ||
75 (conn->msg_in == NULL) ||
76 (conn->msg_out == NULL)) {
82 server_address.sin_family = AF_INET;
83 server_address.sin_port = htons(p->port);
85 fd_server = socket(AF_INET,
86 SOCK_STREAM | SOCK_NONBLOCK,
88 if (fd_server == -1) {
93 status = bind(fd_server,
94 (struct sockaddr *) &server_address,
95 sizeof(server_address));
102 status = listen(fd_server, 16);
110 fd_client_group = epoll_create(1);
111 if (fd_client_group == -1) {
118 strncpy(conn->welcome, p->welcome, CONN_WELCOME_LEN_MAX);
119 strncpy(conn->prompt, p->prompt, CONN_PROMPT_LEN_MAX);
120 conn->buf_size = p->buf_size;
121 conn->msg_in_len_max = p->msg_in_len_max;
122 conn->msg_out_len_max = p->msg_out_len_max;
123 conn->msg_in_len = 0;
124 conn->fd_server = fd_server;
125 conn->fd_client_group = fd_client_group;
126 conn->msg_handle = p->msg_handle;
132 conn_free(struct conn *conn)
137 if (conn->fd_client_group)
138 close(conn->fd_client_group);
141 close(conn->fd_server);
151 conn_poll_for_conn(struct conn *conn)
153 struct sockaddr_in client_address;
154 struct epoll_event event;
155 socklen_t client_address_length;
156 int fd_client, status;
158 /* Check input arguments */
163 client_address_length = sizeof(client_address);
164 fd_client = accept4(conn->fd_server,
165 (struct sockaddr *) &client_address,
166 &client_address_length,
168 if (fd_client == -1) {
169 if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
176 event.events = EPOLLIN | EPOLLRDHUP | EPOLLHUP;
177 event.data.fd = fd_client;
179 status = epoll_ctl(conn->fd_client_group,
189 status = write(fd_client,
191 strlen(conn->welcome));
197 status = write(fd_client,
199 strlen(conn->prompt));
209 data_event_handle(struct conn *conn,
212 ssize_t len, i, status;
214 /* Read input message */
216 len = read(fd_client,
220 if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
228 /* Handle input messages */
229 for (i = 0; i < len; i++) {
230 if (conn->buf[i] == '\n') {
233 conn->msg_in[conn->msg_in_len] = 0;
234 conn->msg_out[0] = 0;
236 conn->msg_handle(conn->msg_in,
238 conn->msg_out_len_max);
240 n = strlen(conn->msg_out);
242 status = write(fd_client,
249 conn->msg_in_len = 0;
250 } else if (conn->msg_in_len < conn->msg_in_len_max) {
251 conn->msg_in[conn->msg_in_len] = conn->buf[i];
254 status = write(fd_client,
256 strlen(MSG_CMD_TOO_LONG));
260 conn->msg_in_len = 0;
265 status = write(fd_client,
267 strlen(conn->prompt));
275 control_event_handle(struct conn *conn,
280 status = epoll_ctl(conn->fd_client_group,
287 status = close(fd_client);
295 conn_poll_for_msg(struct conn *conn)
297 struct epoll_event event;
298 int fd_client, status, status_data = 0, status_control = 0;
300 /* Check input arguments */
305 status = epoll_wait(conn->fd_client_group,
314 fd_client = event.data.fd;
317 if (event.events & EPOLLIN)
318 status_data = data_event_handle(conn, fd_client);
321 if (event.events & (EPOLLRDHUP | EPOLLERR | EPOLLHUP))
322 status_control = control_event_handle(conn, fd_client);
324 if (status_data || status_control)