1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2018 Intel Corporation
12 #include <sys/socket.h>
14 #include <sys/epoll.h>
15 #include <netinet/in.h>
16 #include <arpa/inet.h>
21 #define MSG_CMD_TOO_LONG "Command too long."
30 size_t msg_in_len_max;
31 size_t msg_out_len_max;
35 softnic_conn_msg_handle_t msg_handle;
40 softnic_conn_init(struct softnic_conn_params *p)
42 struct sockaddr_in server_address;
43 struct softnic_conn *conn;
44 int fd_server, fd_client_group, status;
46 memset(&server_address, 0, sizeof(server_address));
48 /* Check input arguments */
54 p->msg_in_len_max == 0 ||
55 p->msg_out_len_max == 0 ||
56 p->msg_handle == NULL)
59 status = inet_aton(p->addr, &server_address.sin_addr);
63 /* Memory allocation */
64 conn = calloc(1, sizeof(struct softnic_conn));
68 conn->welcome = calloc(1, CONN_WELCOME_LEN_MAX + 1);
69 conn->prompt = calloc(1, CONN_PROMPT_LEN_MAX + 1);
70 conn->buf = calloc(1, p->buf_size);
71 conn->msg_in = calloc(1, p->msg_in_len_max + 1);
72 conn->msg_out = calloc(1, p->msg_out_len_max + 1);
74 if (conn->welcome == NULL ||
75 conn->prompt == NULL ||
77 conn->msg_in == NULL ||
78 conn->msg_out == NULL) {
79 softnic_conn_free(conn);
84 server_address.sin_family = AF_INET;
85 server_address.sin_port = htons(p->port);
87 fd_server = socket(AF_INET,
88 SOCK_STREAM | SOCK_NONBLOCK,
90 if (fd_server == -1) {
91 softnic_conn_free(conn);
95 status = bind(fd_server,
96 (struct sockaddr *)&server_address,
97 sizeof(server_address));
99 softnic_conn_free(conn);
104 status = listen(fd_server, 16);
106 softnic_conn_free(conn);
112 fd_client_group = epoll_create(1);
113 if (fd_client_group == -1) {
114 softnic_conn_free(conn);
120 strncpy(conn->welcome, p->welcome, CONN_WELCOME_LEN_MAX);
121 strncpy(conn->prompt, p->prompt, CONN_PROMPT_LEN_MAX);
122 conn->buf_size = p->buf_size;
123 conn->msg_in_len_max = p->msg_in_len_max;
124 conn->msg_out_len_max = p->msg_out_len_max;
125 conn->msg_in_len = 0;
126 conn->fd_server = fd_server;
127 conn->fd_client_group = fd_client_group;
128 conn->msg_handle = p->msg_handle;
129 conn->msg_handle_arg = p->msg_handle_arg;
135 softnic_conn_free(struct softnic_conn *conn)
140 if (conn->fd_client_group)
141 close(conn->fd_client_group);
144 close(conn->fd_server);
154 softnic_conn_poll_for_conn(struct softnic_conn *conn)
156 struct sockaddr_in client_address;
157 struct epoll_event event;
158 socklen_t client_address_length;
159 int fd_client, status;
161 /* Check input arguments */
166 client_address_length = sizeof(client_address);
167 fd_client = accept4(conn->fd_server,
168 (struct sockaddr *)&client_address,
169 &client_address_length,
171 if (fd_client == -1) {
172 if (errno == EAGAIN || errno == EWOULDBLOCK)
179 event.events = EPOLLIN | EPOLLRDHUP | EPOLLHUP;
180 event.data.fd = fd_client;
182 status = epoll_ctl(conn->fd_client_group,
192 status = write(fd_client,
194 strlen(conn->welcome));
200 status = write(fd_client,
202 strlen(conn->prompt));
212 data_event_handle(struct softnic_conn *conn,
215 ssize_t len, i, status;
217 /* Read input message */
219 len = read(fd_client,
223 if (errno == EAGAIN || errno == EWOULDBLOCK)
231 /* Handle input messages */
232 for (i = 0; i < len; i++) {
233 if (conn->buf[i] == '\n') {
236 conn->msg_in[conn->msg_in_len] = 0;
237 conn->msg_out[0] = 0;
239 conn->msg_handle(conn->msg_in,
241 conn->msg_out_len_max,
242 conn->msg_handle_arg);
244 n = strlen(conn->msg_out);
246 status = write(fd_client,
253 conn->msg_in_len = 0;
254 } else if (conn->msg_in_len < conn->msg_in_len_max) {
255 conn->msg_in[conn->msg_in_len] = conn->buf[i];
258 status = write(fd_client,
260 strlen(MSG_CMD_TOO_LONG));
264 conn->msg_in_len = 0;
269 status = write(fd_client,
271 strlen(conn->prompt));
279 control_event_handle(struct softnic_conn *conn,
284 status = epoll_ctl(conn->fd_client_group,
291 status = close(fd_client);
299 softnic_conn_poll_for_msg(struct softnic_conn *conn)
301 struct epoll_event event;
302 int fd_client, status, status_data = 0, status_control = 0;
304 /* Check input arguments */
309 status = epoll_wait(conn->fd_client_group,
318 fd_client = event.data.fd;
321 if (event.events & EPOLLIN)
322 status_data = data_event_handle(conn, fd_client);
325 if (event.events & (EPOLLRDHUP | EPOLLERR | EPOLLHUP))
326 status_control = control_event_handle(conn, fd_client);
328 if (status_data || status_control)