doorbell

annotate doorbelld/src/srv.c @ 4:08ea0abdbb8a

argument parsing
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 14 Mar 2016 04:20:59 +0200
parents d3f2a2b19504
children f21ae31ef0e7
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@4 13 /* TODO convert this whole thing to multicast */
nuclear@4 14
nuclear@2 15 static int lis_sock = -1, max_socket = -1;
nuclear@2 16 static int *csock;
nuclear@2 17
nuclear@2 18 int srv_init(int port)
nuclear@2 19 {
nuclear@2 20 struct sockaddr_in addr;
nuclear@2 21
nuclear@2 22 if(lis_sock != -1) {
nuclear@2 23 fprintf(stderr, "%s: already running\n", __func__);
nuclear@2 24 return -1;
nuclear@2 25 }
nuclear@2 26
nuclear@2 27 if((lis_sock = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
nuclear@2 28 fprintf(stderr, "%s: failed to create listening socket\n", __func__);
nuclear@2 29 return -1;
nuclear@2 30 }
nuclear@2 31 if(!(csock = dynarr_alloc(1, sizeof *csock))) {
nuclear@2 32 fprintf(stderr, "%s: failed to allocate client socket array\n", __func__);
nuclear@2 33 return -1;
nuclear@2 34 }
nuclear@2 35 csock[0] = lis_sock;
nuclear@2 36 max_socket = lis_sock;
nuclear@2 37
nuclear@2 38 fcntl(lis_sock, F_SETFD, fcntl(lis_sock, F_GETFD) | O_NONBLOCK);
nuclear@2 39
nuclear@2 40 memset(&addr, 0, sizeof addr);
nuclear@2 41 addr.sin_family = AF_INET;
nuclear@2 42 addr.sin_port = htons(port);
nuclear@2 43 addr.sin_addr.s_addr = INADDR_ANY;
nuclear@2 44 if(bind(lis_sock, (struct sockaddr*)&addr, sizeof addr) == -1) {
nuclear@2 45 fprintf(stderr, "%s: failed to bind port %d\n", __func__, port);
nuclear@2 46 close(lis_sock);
nuclear@2 47 lis_sock = -1;
nuclear@2 48 return -1;
nuclear@2 49 }
nuclear@4 50 listen(lis_sock, 8);
nuclear@2 51
nuclear@2 52 return 0;
nuclear@2 53 }
nuclear@2 54
nuclear@2 55 void srv_shutdown(void)
nuclear@2 56 {
nuclear@2 57 int i, sz = dynarr_size(csock);
nuclear@2 58 for(i=0; i<sz; i++) {
nuclear@2 59 close(csock[i]);
nuclear@2 60 }
nuclear@2 61 dynarr_free(csock);
nuclear@2 62 csock = 0;
nuclear@2 63 lis_sock = -1;
nuclear@2 64 max_socket = -1;
nuclear@2 65 }
nuclear@2 66
nuclear@2 67 int srv_num_sockets(void)
nuclear@2 68 {
nuclear@2 69 return dynarr_size(csock);
nuclear@2 70 }
nuclear@2 71
nuclear@2 72 int *srv_sockets(void)
nuclear@2 73 {
nuclear@2 74 return csock;
nuclear@2 75 }
nuclear@2 76
nuclear@2 77 int srv_max_socket(void)
nuclear@2 78 {
nuclear@2 79 return max_socket;
nuclear@2 80 }
nuclear@2 81
nuclear@2 82 int srv_handle(int s)
nuclear@2 83 {
nuclear@2 84 static char buf[1024];
nuclear@2 85 int sz;
nuclear@2 86
nuclear@2 87 if(s == lis_sock) {
nuclear@2 88 /* incoming connection */
nuclear@2 89 struct sockaddr_in addr;
nuclear@4 90 socklen_t addr_size = sizeof addr;
nuclear@4 91 if((s = accept(lis_sock, (struct sockaddr*)&addr, &addr_size)) == -1) {
nuclear@4 92 fprintf(stderr, "%s: failed to accept incoming connection: %s\n", __func__, strerror(errno));
nuclear@2 93 return -1;
nuclear@2 94 }
nuclear@2 95 printf("%s: incoming connection from %s:%d\n", __func__,
nuclear@2 96 inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
nuclear@2 97 csock = dynarr_push(csock, &s);
nuclear@2 98 assert(csock);
nuclear@4 99 if(s > max_socket) {
nuclear@4 100 max_socket = s;
nuclear@4 101 }
nuclear@4 102 fcntl(s, F_SETFD, fcntl(s, F_GETFD) | O_NONBLOCK);
nuclear@2 103 return 0;
nuclear@2 104 }
nuclear@2 105
nuclear@2 106 /* handle client */
nuclear@2 107 while((sz = read(s, buf, sizeof buf - 1)) > 0) {
nuclear@2 108 printf("%s: got data: %s\n", __func__, buf);
nuclear@2 109 }
nuclear@4 110 if(sz <= 0 && errno != EAGAIN) {
nuclear@2 111 /* client closed connection probably */
nuclear@2 112 int i, num_clients = dynarr_size(csock);
nuclear@2 113 printf("%s: removing client\n", __func__);
nuclear@2 114 close(s);
nuclear@4 115 max_socket = lis_sock;
nuclear@2 116 for(i=0; i<num_clients; i++) {
nuclear@2 117 if(csock[i] == s) {
nuclear@2 118 csock[i] = csock[num_clients - 1];
nuclear@4 119 }
nuclear@4 120 if(csock[i] > max_socket) {
nuclear@4 121 max_socket = csock[i];
nuclear@2 122 }
nuclear@2 123 }
nuclear@4 124
nuclear@4 125 csock = dynarr_pop(csock);
nuclear@4 126 --num_clients;
nuclear@2 127 }
nuclear@2 128 return 0;
nuclear@2 129 }
nuclear@2 130
nuclear@4 131 struct video_block {
nuclear@4 132 int frame;
nuclear@4 133 int x, y;
nuclear@4 134 int width, height;
nuclear@4 135 char pixels[1];
nuclear@4 136 };
nuclear@4 137 #define VBLOCK_HEADER_SIZE (offsetof(struct video_block, pixels))
nuclear@4 138
nuclear@2 139 void srv_send_frame(unsigned char *frame, int xsz, int ysz)
nuclear@2 140 {
nuclear@4 141 static unsigned char *buffer;
nuclear@4 142 struct video_block *vblock;
nuclear@4 143
nuclear@4 144 /* for now just send a big block */
nuclear@4 145 if(!buffer && !(buffer = malloc(xsz * ysz * 2) + VBLOCK_HEADER_SIZE)) {
nuclear@4 146 fprintf(stderr, "failed to allocate frame send buffer\n");
nuclear@4 147 return;
nuclear@4 148 }
nuclear@4 149 vblock = buffer;
nuclear@2 150 }