doorbell
diff doorbelld/src/srv.c @ 2:d3f2a2b19504
doorbell server under construction
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sun, 13 Mar 2016 07:56:03 +0200 |
parents | |
children | 08ea0abdbb8a |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/doorbelld/src/srv.c Sun Mar 13 07:56:03 2016 +0200 1.3 @@ -0,0 +1,123 @@ 1.4 +#include <stdio.h> 1.5 +#include <stdlib.h> 1.6 +#include <string.h> 1.7 +#include <errno.h> 1.8 +#include <assert.h> 1.9 +#include <unistd.h> 1.10 +#include <fcntl.h> 1.11 +#include <sys/socket.h> 1.12 +#include <arpa/inet.h> 1.13 +#include "srv.h" 1.14 +#include "dynarr.h" 1.15 + 1.16 +static int lis_sock = -1, max_socket = -1; 1.17 +static int *csock; 1.18 + 1.19 +int srv_init(int port) 1.20 +{ 1.21 + struct sockaddr_in addr; 1.22 + 1.23 + if(lis_sock != -1) { 1.24 + fprintf(stderr, "%s: already running\n", __func__); 1.25 + return -1; 1.26 + } 1.27 + 1.28 + if((lis_sock = socket(PF_INET, SOCK_STREAM, 0)) == -1) { 1.29 + fprintf(stderr, "%s: failed to create listening socket\n", __func__); 1.30 + return -1; 1.31 + } 1.32 + if(!(csock = dynarr_alloc(1, sizeof *csock))) { 1.33 + fprintf(stderr, "%s: failed to allocate client socket array\n", __func__); 1.34 + return -1; 1.35 + } 1.36 + csock[0] = lis_sock; 1.37 + max_socket = lis_sock; 1.38 + 1.39 + fcntl(lis_sock, F_SETFD, fcntl(lis_sock, F_GETFD) | O_NONBLOCK); 1.40 + 1.41 + memset(&addr, 0, sizeof addr); 1.42 + addr.sin_family = AF_INET; 1.43 + addr.sin_port = htons(port); 1.44 + addr.sin_addr.s_addr = INADDR_ANY; 1.45 + if(bind(lis_sock, (struct sockaddr*)&addr, sizeof addr) == -1) { 1.46 + fprintf(stderr, "%s: failed to bind port %d\n", __func__, port); 1.47 + close(lis_sock); 1.48 + lis_sock = -1; 1.49 + return -1; 1.50 + } 1.51 + 1.52 + return 0; 1.53 +} 1.54 + 1.55 +void srv_shutdown(void) 1.56 +{ 1.57 + int i, sz = dynarr_size(csock); 1.58 + for(i=0; i<sz; i++) { 1.59 + close(csock[i]); 1.60 + } 1.61 + dynarr_free(csock); 1.62 + csock = 0; 1.63 + lis_sock = -1; 1.64 + max_socket = -1; 1.65 +} 1.66 + 1.67 +int srv_num_sockets(void) 1.68 +{ 1.69 + return dynarr_size(csock); 1.70 +} 1.71 + 1.72 +int *srv_sockets(void) 1.73 +{ 1.74 + return csock; 1.75 +} 1.76 + 1.77 +int srv_max_socket(void) 1.78 +{ 1.79 + return max_socket; 1.80 +} 1.81 + 1.82 +int srv_handle(int s) 1.83 +{ 1.84 + static char buf[1024]; 1.85 + int sz; 1.86 + 1.87 + if(s == lis_sock) { 1.88 + /* incoming connection */ 1.89 + struct sockaddr_in addr; 1.90 + int addr_size; 1.91 + 1.92 + if((s = accept(lis_sock, (struct sockaddr*)&addr, (int*)&addr_size)) == -1) { 1.93 + fprintf(stderr, "%s: failed to accept incoming connection\n", __func__); 1.94 + return -1; 1.95 + } 1.96 + printf("%s: incoming connection from %s:%d\n", __func__, 1.97 + inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); 1.98 + csock = dynarr_push(csock, &s); 1.99 + assert(csock); 1.100 + return 0; 1.101 + } 1.102 + 1.103 + /* handle client */ 1.104 + while((sz = read(s, buf, sizeof buf - 1)) > 0) { 1.105 + printf("%s: got data: %s\n", __func__, buf); 1.106 + } 1.107 + if(sz < 0 && errno != EAGAIN) { 1.108 + /* client closed connection probably */ 1.109 + int i, num_clients = dynarr_size(csock); 1.110 + printf("%s: removing client\n", __func__); 1.111 + close(s); 1.112 + for(i=0; i<num_clients; i++) { 1.113 + if(csock[i] == s) { 1.114 + csock[i] = csock[num_clients - 1]; 1.115 + csock = dynarr_pop(csock); 1.116 + break; 1.117 + } 1.118 + } 1.119 + assert(i < num_clients); 1.120 + } 1.121 + return 0; 1.122 +} 1.123 + 1.124 +void srv_send_frame(unsigned char *frame, int xsz, int ysz) 1.125 +{ 1.126 +}