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