libqb  0.16.0
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
tcpserver.c
/*
* Copyright (c) 2011 Red Hat, Inc.
*
* All rights reserved.
*
* Author: Angus Salkeld <asalkeld@redhat.com>
*
* libqb is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 2.1 of the License, or
* (at your option) any later version.
*
* libqb is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with libqb. If not, see <http://www.gnu.org/licenses/>.
*/
#include "os_base.h"
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif /* HAVE_NETINET_IN_H */
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif /* HAVE_ARPA_INET_H */
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif /* HAVE_NETDB_H */
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif /* HAVE_SYS_SOCKET_H */
#ifdef HAVE_SYS_POLL_H
#include <sys/poll.h>
#endif /* HAVE_SYS_POLL_H */
#include <qb/qbdefs.h>
#include <qb/qbloop.h>
static int32_t
sock_read_fn(int32_t fd, int32_t revents, void *data)
{
char recv_data[1024];
char send_data[1024];
int bytes_recieved;
if (revents & POLLHUP) {
printf("Socket %d peer closed\n", fd);
close(fd);
return QB_FALSE;
}
bytes_recieved = recv(fd, recv_data, 1024, 0);
if (bytes_recieved < 0) {
perror("recv");
return QB_TRUE;
}
recv_data[bytes_recieved] = '\0';
if (strcmp(recv_data, "q") == 0 || strcmp(recv_data, "Q") == 0) {
printf("Quiting connection from socket %d\n", fd);
close(fd);
return QB_FALSE;
} else {
printf("Recieved: %s\n", recv_data);
snprintf(send_data, 1024, "ACK %d bytes", bytes_recieved);
if (send(fd, send_data, strlen(send_data), 0) < 0) {
close(fd);
return QB_FALSE;
}
}
return QB_TRUE;
}
static int32_t
sock_accept_fn(int32_t fd, int32_t revents, void *data)
{
struct sockaddr_in client_addr;
qb_loop_t *ml = (qb_loop_t *) data;
socklen_t sin_size = sizeof(struct sockaddr_in);
int connected = accept(fd, (struct sockaddr *)&client_addr, &sin_size);
if (connected < 0) {
perror("accept");
return QB_TRUE;
}
printf("I got a connection from (%s , %d)\n",
inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
qb_loop_poll_add(ml, QB_LOOP_MED, connected, POLLIN, ml, sock_read_fn);
return QB_TRUE;
}
static int32_t
please_exit_fn(int32_t rsignal, void *data)
{
qb_loop_t *ml = (qb_loop_t *) data;
printf("Shutting down at you request...\n");
return QB_FALSE;
}
int
main(int argc, char *argv[])
{
int sock;
int true_opt = 1;
struct sockaddr_in server_addr;
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("Socket");
exit(1);
}
if (setsockopt(sock,
SOL_SOCKET,
SO_REUSEADDR, &true_opt, sizeof(int)) == -1) {
perror("Setsockopt");
exit(1);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(5000);
server_addr.sin_addr.s_addr = INADDR_ANY;
bzero(&(server_addr.sin_zero), 8);
printf("TCPServer binding to port 5000\n");
if (bind(sock,
(struct sockaddr *)&server_addr,
sizeof(struct sockaddr)) == -1) {
perror("Unable to bind");
exit(1);
}
printf("TCPServer Waiting for client on port 5000\n");
if (listen(sock, 5) == -1) {
perror("Listen");
exit(1);
}
qb_loop_poll_add(ml, QB_LOOP_MED, sock, POLLIN, ml, sock_accept_fn);
qb_loop_signal_add(ml, QB_LOOP_HIGH, SIGINT, ml, please_exit_fn, NULL);
close(sock);
return 0;
}