1 /*
2 * Copyright (c) 2011 Red Hat, Inc.
3 *
4 * All rights reserved.
5 *
6 * Author: Angus Salkeld <asalkeld@redhat.com>
7 *
8 * libqb is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation, either version 2.1 of the License, or
11 * (at your option) any later version.
12 *
13 * libqb is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with libqb. If not, see <http://www.gnu.org/licenses/>.
20 */
21 #include "os_base.h"
22
23 #ifdef HAVE_NETINET_IN_H
24 #include <netinet/in.h>
25 #endif /* HAVE_NETINET_IN_H */
26 #ifdef HAVE_ARPA_INET_H
27 #include <arpa/inet.h>
28 #endif /* HAVE_ARPA_INET_H */
29 #ifdef HAVE_NETDB_H
30 #include <netdb.h>
31 #endif /* HAVE_NETDB_H */
32 #ifdef HAVE_SYS_SOCKET_H
33 #include <sys/socket.h>
34 #endif /* HAVE_SYS_SOCKET_H */
35 #ifdef HAVE_SYS_POLL_H
36 #include <sys/poll.h>
37 #endif /* HAVE_SYS_POLL_H */
38
39 #include <qb/qbdefs.h>
40 #include <qb/qbloop.h>
41
42 static int32_t
sock_read_fn(int32_t fd,int32_t revents,void * data)43 sock_read_fn(int32_t fd, int32_t revents, void *data)
44 {
45 char recv_data[1024];
46 char send_data[1024];
47 int bytes_recieved;
48
49 if (revents & POLLHUP) {
50 printf("Socket %d peer closed\n", fd);
51 close(fd);
52 return QB_FALSE;
53 }
54
55 bytes_recieved = recv(fd, recv_data, 1024, 0);
56 if (bytes_recieved < 0) {
57 perror("recv");
58 return QB_TRUE;
59 }
60 recv_data[bytes_recieved] = '\0';
61
62 if (strcmp(recv_data, "q") == 0 || strcmp(recv_data, "Q") == 0) {
63 printf("Quiting connection from socket %d\n", fd);
64 close(fd);
65 return QB_FALSE;
66 } else {
67 printf("Recieved: %s\n", recv_data);
68 snprintf(send_data, 1024, "ACK %d bytes", bytes_recieved);
69 if (send(fd, send_data, strlen(send_data), 0) < 0) {
70 close(fd);
71 return QB_FALSE;
72 }
73 }
74 return QB_TRUE;
75 }
76
77 static int32_t
sock_accept_fn(int32_t fd,int32_t revents,void * data)78 sock_accept_fn(int32_t fd, int32_t revents, void *data)
79 {
80 struct sockaddr_in client_addr;
81 qb_loop_t *ml = (qb_loop_t *) data;
82 socklen_t sin_size = sizeof(struct sockaddr_in);
83 int connected = accept(fd, (struct sockaddr *)&client_addr, &sin_size);
84
85 if (connected < 0) {
86 perror("accept");
87 return QB_TRUE;
88 }
89 printf("I got a connection from (%s , %d)\n",
90 inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
91
92 qb_loop_poll_add(ml, QB_LOOP_MED, connected, POLLIN, ml, sock_read_fn);
93
94 return QB_TRUE;
95 }
96
97 static int32_t
please_exit_fn(int32_t rsignal,void * data)98 please_exit_fn(int32_t rsignal, void *data)
99 {
100 qb_loop_t *ml = (qb_loop_t *) data;
101
102 printf("Shutting down at you request...\n");
103 qb_loop_stop(ml);
104 return QB_FALSE;
105 }
106
107 int
main(int argc,char * argv[])108 main(int argc, char *argv[])
109 {
110 int sock;
111 int true_opt = 1;
112 struct sockaddr_in server_addr;
113 qb_loop_t *ml = qb_loop_create();
114
115 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
116 perror("Socket");
117 exit(1);
118 }
119
120 if (setsockopt(sock,
121 SOL_SOCKET,
122 SO_REUSEADDR, &true_opt, sizeof(int)) == -1) {
123 perror("Setsockopt");
124 exit(1);
125 }
126
127 server_addr.sin_family = AF_INET;
128 server_addr.sin_port = htons(5000);
129 server_addr.sin_addr.s_addr = INADDR_ANY;
130 bzero(&(server_addr.sin_zero), 8);
131
132 printf("TCPServer binding to port 5000\n");
133 if (bind(sock,
134 (struct sockaddr *)&server_addr,
135 sizeof(struct sockaddr)) == -1) {
136 perror("Unable to bind");
137 exit(1);
138 }
139
140 printf("TCPServer Waiting for client on port 5000\n");
141
142 if (listen(sock, 5) == -1) {
143 perror("Listen");
144 exit(1);
145 }
146
147 qb_loop_poll_add(ml, QB_LOOP_MED, sock, POLLIN, ml, sock_accept_fn);
148
149 qb_loop_signal_add(ml, QB_LOOP_HIGH, SIGINT, ml, please_exit_fn, NULL);
150 qb_loop_run(ml);
151
152 close(sock);
153 return 0;
154 }
155