nuclear@2: #include nuclear@2: #include nuclear@2: #include nuclear@5: #include nuclear@5: #include nuclear@2: #include nuclear@2: #include nuclear@2: #include nuclear@2: #include nuclear@2: #include nuclear@2: #include nuclear@2: #include "srv.h" nuclear@2: #include "dynarr.h" nuclear@2: nuclear@4: /* TODO convert this whole thing to multicast */ nuclear@4: nuclear@6: static int bsock = -1; nuclear@6: static struct sockaddr_in baddr; nuclear@2: static int lis_sock = -1, max_socket = -1; nuclear@2: static int *csock; nuclear@2: nuclear@2: int srv_init(int port) nuclear@2: { nuclear@6: int val; nuclear@2: struct sockaddr_in addr; nuclear@2: nuclear@2: if(lis_sock != -1) { nuclear@2: fprintf(stderr, "%s: already running\n", __func__); nuclear@2: return -1; nuclear@2: } nuclear@2: nuclear@2: if((lis_sock = socket(PF_INET, SOCK_STREAM, 0)) == -1) { nuclear@2: fprintf(stderr, "%s: failed to create listening socket\n", __func__); nuclear@2: return -1; nuclear@2: } nuclear@2: if(!(csock = dynarr_alloc(1, sizeof *csock))) { nuclear@2: fprintf(stderr, "%s: failed to allocate client socket array\n", __func__); nuclear@2: return -1; nuclear@2: } nuclear@2: csock[0] = lis_sock; nuclear@2: max_socket = lis_sock; nuclear@2: nuclear@5: fcntl(lis_sock, F_SETFL, fcntl(lis_sock, F_GETFL) | O_NONBLOCK); nuclear@2: nuclear@2: memset(&addr, 0, sizeof addr); nuclear@2: addr.sin_family = AF_INET; nuclear@2: addr.sin_port = htons(port); nuclear@2: addr.sin_addr.s_addr = INADDR_ANY; nuclear@2: if(bind(lis_sock, (struct sockaddr*)&addr, sizeof addr) == -1) { nuclear@2: fprintf(stderr, "%s: failed to bind port %d\n", __func__, port); nuclear@2: close(lis_sock); nuclear@2: lis_sock = -1; nuclear@2: return -1; nuclear@2: } nuclear@4: listen(lis_sock, 8); nuclear@2: nuclear@6: /* then create the video broadcast socket */ nuclear@6: if((bsock = socket(PF_INET, SOCK_DGRAM, 0)) == -1) { nuclear@6: fprintf(stderr, "%s: failed to create video broadcast socket\n", __func__); nuclear@6: return -1; nuclear@6: } nuclear@6: val = 1; nuclear@6: setsockopt(bsock, SOL_SOCKET, SO_BROADCAST, &val, sizeof val); nuclear@6: nuclear@6: memset(&baddr, 0, sizeof baddr); nuclear@6: baddr.sin_family = AF_INET; nuclear@6: baddr.sin_port = htons(port + 1); nuclear@6: baddr.sin_addr.s_addr = 0xffffffff; nuclear@6: nuclear@2: return 0; nuclear@2: } nuclear@2: nuclear@2: void srv_shutdown(void) nuclear@2: { nuclear@2: int i, sz = dynarr_size(csock); nuclear@2: for(i=0; i max_socket) { nuclear@6: max_socket = s; nuclear@6: } nuclear@6: fcntl(s, F_SETFL, fcntl(s, F_GETFL) | O_NONBLOCK); nuclear@6: return 0; nuclear@6: } nuclear@6: nuclear@6: static int handle_client(int s) nuclear@2: { nuclear@2: static char buf[1024]; nuclear@2: int sz; nuclear@2: nuclear@2: /* handle client */ nuclear@2: while((sz = read(s, buf, sizeof buf - 1)) > 0) { nuclear@2: printf("%s: got data: %s\n", __func__, buf); nuclear@2: } nuclear@4: if(sz <= 0 && errno != EAGAIN) { nuclear@2: /* client closed connection probably */ nuclear@2: int i, num_clients = dynarr_size(csock); nuclear@2: printf("%s: removing client\n", __func__); nuclear@2: close(s); nuclear@4: max_socket = lis_sock; nuclear@2: for(i=0; i max_socket) { nuclear@4: max_socket = csock[i]; nuclear@2: } nuclear@2: } nuclear@4: nuclear@4: csock = dynarr_pop(csock); nuclear@4: --num_clients; nuclear@2: } nuclear@2: return 0; nuclear@2: } nuclear@2: nuclear@6: int srv_handle(int s) nuclear@6: { nuclear@6: if(s == lis_sock) { nuclear@6: return handle_new_client(); nuclear@6: } nuclear@6: nuclear@6: return handle_client(s); nuclear@6: } nuclear@6: nuclear@4: struct video_block { nuclear@5: unsigned int magic; nuclear@4: int frame; nuclear@4: int x, y; nuclear@4: int width, height; nuclear@5: int frame_width, frame_height; nuclear@4: char pixels[1]; nuclear@4: }; nuclear@4: #define VBLOCK_HEADER_SIZE (offsetof(struct video_block, pixels)) nuclear@4: nuclear@2: void srv_send_frame(unsigned char *frame, int xsz, int ysz) nuclear@2: { nuclear@5: static int frame_num; nuclear@4: static unsigned char *buffer; nuclear@5: int i, j, size, num_clients; nuclear@4: struct video_block *vblock; nuclear@5: uint16_t *dest; nuclear@5: nuclear@5: printf("sending frame\n"); nuclear@4: nuclear@4: /* for now just send a big block */ nuclear@5: size = xsz * ysz * 2 + VBLOCK_HEADER_SIZE; nuclear@5: if(!buffer && !(buffer = malloc(size))) { nuclear@4: fprintf(stderr, "failed to allocate frame send buffer\n"); nuclear@4: return; nuclear@4: } nuclear@5: vblock = (struct video_block*)buffer; nuclear@5: nuclear@5: vblock->magic = 0x12341234; nuclear@5: vblock->frame = frame_num++; nuclear@5: vblock->x = vblock->y = 0; nuclear@5: vblock->width = vblock->frame_width = xsz; nuclear@5: vblock->height = vblock->frame_height = ysz; nuclear@5: nuclear@5: dest = (uint16_t*)vblock->pixels; nuclear@5: nuclear@5: for(i=0; i> 3) & 0x1f); nuclear@5: frame += 4; nuclear@5: } nuclear@5: } nuclear@5: nuclear@5: num_clients = dynarr_size(csock); nuclear@5: for(i=1; i