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