2 // Copyright (c) 2010-2017 Intel Corporation
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
8 // http://www.apache.org/licenses/LICENSE-2.0
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
18 #include <netinet/in.h>
19 #include <sys/socket.h>
23 #include <rte_cycles.h>
24 #include "input_conn.h"
28 #include "cmd_parser.h"
31 static struct input tcp_server;
32 int tcp_server_started;
33 static struct input uds_server;
34 int uds_server_started;
44 struct client_conn clients[32];
46 static int start_listen_tcp(void)
48 struct sockaddr_in server;
52 memset(&server, 0, sizeof(server));
53 sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
58 server.sin_family = AF_INET;
59 server.sin_port = ntohs(8474);
60 server.sin_addr.s_addr = ntohl(INADDR_ANY);
62 ret = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(int));
67 if (bind(sock, (struct sockaddr *) &server, sizeof(server)) == -1)
70 if (listen(sock, 1) == -1)
76 static int start_listen_uds(void)
79 struct sockaddr_un server = {
80 .sun_path = "/tmp/prox.sock",
84 sock = socket(AF_UNIX, SOCK_STREAM, 0);
88 /* Unlink can fail, i.e. when /tmp/prox.sock does not
89 exists. This is not fatal. */
90 unlink(server.sun_path);
92 if (bind(sock, (struct sockaddr *) &server, sizeof(server)) == -1)
95 if (listen(sock, 1) == -1)
101 static void write_client(struct input *input, const char *buf, size_t len)
105 while ((ret = write(input->fd, buf, len)) != (int)len) {
111 static void handle_client(struct input* client_input)
116 struct client_conn *c = NULL;
118 /* Get the client structure that uses this input */
119 for (i = 0; i < sizeof(clients)/sizeof(clients[0]); ++i) {
120 if (&clients[i].input == client_input) {
126 /* handle_client function called non-tcp client */
130 ret = read(c->input.fd, cur, sizeof(cur));
134 unreg_input(&c->input);
138 prox_cfg.heartbeat_tsc = rte_rdtsc() + prox_cfg.heartbeat_timeout * rte_get_tsc_hz();
140 /* Scan in data until \n (\r skipped if followed by \n) */
141 for (int i = 0; i < ret; ++i) {
142 if (cur[i] == '\r' && i + 1 < ret && cur[i + 1] == '\n')
145 if (cur[i] == '\n') {
146 c->buf[c->n_buf] = 0;
148 cmd_parser_parse(c->buf, client_input);
151 else if (c->n_buf + 1 < (int)sizeof(c->buf))
152 c->buf[c->n_buf++] = cur[i];
158 void stop_handling_client(void)
161 for (i = 0; i < sizeof(clients)/sizeof(clients[0]); ++i) {
162 if (clients[i].enabled) {
163 close(clients[i].input.fd);
164 clients[i].enabled = 0;
165 unreg_input(&clients[i].input);
170 static void handle_new_client(struct input* server)
174 int new_client = accept(server->fd, NULL, NULL);
176 for (i = 0; i < sizeof(clients)/sizeof(clients[0]); ++i) {
177 if (clients[i].enabled == 0) {
182 if (i == sizeof(clients)/sizeof(clients[0])) {
187 clients[i].enabled = 1;
188 clients[i].n_buf = 0;
189 clients[i].input.fd = new_client;
190 clients[i].input.reply = server->reply;
191 clients[i].input.proc_input = handle_client;
193 reg_input(&clients[i].input);
196 int reg_input_tcp(void)
200 if (tcp_server_started)
202 if ((fd = start_listen_tcp()) < 0)
206 tcp_server.proc_input = handle_new_client;
207 tcp_server.reply = write_client;
208 if (reg_input(&tcp_server) != 0) {
212 tcp_server_started = 1;
216 int reg_input_uds(void)
220 if (uds_server_started)
223 if ((fd = start_listen_uds()) < 0)
227 uds_server.proc_input = handle_new_client;
228 uds_server.reply = write_client;
229 if (reg_input(&uds_server) != 0) {
233 uds_server_started = 1;
237 void unreg_input_tcp(void)
239 if (!tcp_server_started)
241 tcp_server_started = 0;
242 close(tcp_server.fd);
243 unreg_input(&tcp_server);
246 void unreg_input_uds(void)
248 if (!uds_server_started)
250 uds_server_started = 0;
251 close(tcp_server.fd);
252 unreg_input(&tcp_server);