doorbell

annotate 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
rev   line source
nuclear@2 1 #include <stdio.h>
nuclear@2 2 #include <stdlib.h>
nuclear@2 3 #include <string.h>
nuclear@2 4 #include <errno.h>
nuclear@2 5 #include <assert.h>
nuclear@2 6 #include <unistd.h>
nuclear@2 7 #include <fcntl.h>
nuclear@2 8 #include <sys/socket.h>
nuclear@2 9 #include <arpa/inet.h>
nuclear@2 10 #include "srv.h"
nuclear@2 11 #include "dynarr.h"
nuclear@2 12
nuclear@2 13 static int lis_sock = -1, max_socket = -1;
nuclear@2 14 static int *csock;
nuclear@2 15
nuclear@2 16 int srv_init(int port)
nuclear@2 17 {
nuclear@2 18 struct sockaddr_in addr;
nuclear@2 19
nuclear@2 20 if(lis_sock != -1) {
nuclear@2 21 fprintf(stderr, "%s: already running\n", __func__);
nuclear@2 22 return -1;
nuclear@2 23 }
nuclear@2 24
nuclear@2 25 if((lis_sock = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
nuclear@2 26 fprintf(stderr, "%s: failed to create listening socket\n", __func__);
nuclear@2 27 return -1;
nuclear@2 28 }
nuclear@2 29 if(!(csock = dynarr_alloc(1, sizeof *csock))) {
nuclear@2 30 fprintf(stderr, "%s: failed to allocate client socket array\n", __func__);
nuclear@2 31 return -1;
nuclear@2 32 }
nuclear@2 33 csock[0] = lis_sock;
nuclear@2 34 max_socket = lis_sock;
nuclear@2 35
nuclear@2 36 fcntl(lis_sock, F_SETFD, fcntl(lis_sock, F_GETFD) | O_NONBLOCK);
nuclear@2 37
nuclear@2 38 memset(&addr, 0, sizeof addr);
nuclear@2 39 addr.sin_family = AF_INET;
nuclear@2 40 addr.sin_port = htons(port);
nuclear@2 41 addr.sin_addr.s_addr = INADDR_ANY;
nuclear@2 42 if(bind(lis_sock, (struct sockaddr*)&addr, sizeof addr) == -1) {
nuclear@2 43 fprintf(stderr, "%s: failed to bind port %d\n", __func__, port);
nuclear@2 44 close(lis_sock);
nuclear@2 45 lis_sock = -1;
nuclear@2 46 return -1;
nuclear@2 47 }
nuclear@2 48
nuclear@2 49 return 0;
nuclear@2 50 }
nuclear@2 51
nuclear@2 52 void srv_shutdown(void)
nuclear@2 53 {
nuclear@2 54 int i, sz = dynarr_size(csock);
nuclear@2 55 for(i=0; i<sz; i++) {
nuclear@2 56 close(csock[i]);
nuclear@2 57 }
nuclear@2 58 dynarr_free(csock);
nuclear@2 59 csock = 0;
nuclear@2 60 lis_sock = -1;
nuclear@2 61 max_socket = -1;
nuclear@2 62 }
nuclear@2 63
nuclear@2 64 int srv_num_sockets(void)
nuclear@2 65 {
nuclear@2 66 return dynarr_size(csock);
nuclear@2 67 }
nuclear@2 68
nuclear@2 69 int *srv_sockets(void)
nuclear@2 70 {
nuclear@2 71 return csock;
nuclear@2 72 }
nuclear@2 73
nuclear@2 74 int srv_max_socket(void)
nuclear@2 75 {
nuclear@2 76 return max_socket;
nuclear@2 77 }
nuclear@2 78
nuclear@2 79 int srv_handle(int s)
nuclear@2 80 {
nuclear@2 81 static char buf[1024];
nuclear@2 82 int sz;
nuclear@2 83
nuclear@2 84 if(s == lis_sock) {
nuclear@2 85 /* incoming connection */
nuclear@2 86 struct sockaddr_in addr;
nuclear@2 87 int addr_size;
nuclear@2 88
nuclear@2 89 if((s = accept(lis_sock, (struct sockaddr*)&addr, (int*)&addr_size)) == -1) {
nuclear@2 90 fprintf(stderr, "%s: failed to accept incoming connection\n", __func__);
nuclear@2 91 return -1;
nuclear@2 92 }
nuclear@2 93 printf("%s: incoming connection from %s:%d\n", __func__,
nuclear@2 94 inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
nuclear@2 95 csock = dynarr_push(csock, &s);
nuclear@2 96 assert(csock);
nuclear@2 97 return 0;
nuclear@2 98 }
nuclear@2 99
nuclear@2 100 /* handle client */
nuclear@2 101 while((sz = read(s, buf, sizeof buf - 1)) > 0) {
nuclear@2 102 printf("%s: got data: %s\n", __func__, buf);
nuclear@2 103 }
nuclear@2 104 if(sz < 0 && errno != EAGAIN) {
nuclear@2 105 /* client closed connection probably */
nuclear@2 106 int i, num_clients = dynarr_size(csock);
nuclear@2 107 printf("%s: removing client\n", __func__);
nuclear@2 108 close(s);
nuclear@2 109 for(i=0; i<num_clients; i++) {
nuclear@2 110 if(csock[i] == s) {
nuclear@2 111 csock[i] = csock[num_clients - 1];
nuclear@2 112 csock = dynarr_pop(csock);
nuclear@2 113 break;
nuclear@2 114 }
nuclear@2 115 }
nuclear@2 116 assert(i < num_clients);
nuclear@2 117 }
nuclear@2 118 return 0;
nuclear@2 119 }
nuclear@2 120
nuclear@2 121 void srv_send_frame(unsigned char *frame, int xsz, int ysz)
nuclear@2 122 {
nuclear@2 123 }