jnx_tcp_listener* jnx_socket_tcp_listener_create(jnx_char *port, jnx_unsigned_int family, jnx_int max_connections) { JNXCHECK(max_connections <= 200); struct addrinfo hints; struct addrinfo *result, *rp; jnx_int on = 1,s; jnx_tcp_listener *l = malloc(sizeof(jnx_tcp_listener)); l->socket = jnx_socket_tcp_create(family); l->hint_exit = 0; memset (&hints, 0, sizeof (struct addrinfo)); hints.ai_family = family; hints.ai_socktype = l->socket->stype; hints.ai_flags = AI_PASSIVE; s = getaddrinfo (NULL, port, &hints, &result); if (s != 0) { fprintf (stderr, "getaddrinfo: %s\n", gai_strerror (s)); JNXFAIL("getaddrinfo failure"); } s = ioctl(l->socket->socket,FIONBIO,(char*)&on); for (rp = result; rp != NULL; rp = rp->ai_next) { JNXCHECK(s == 0); s = bind (l->socket->socket, rp->ai_addr, rp->ai_addrlen); if (s == 0) { break; } jnx_socket_tcp_listener_destroy(&l); JNXFAIL("bind failure"); } JNXCHECK(l->socket->socket); s = listen(l->socket->socket,max_connections); JNXCHECK(s == 0); l->ufds[0].fd = l->socket->socket; l->ufds[0].events = POLLIN; l->poll_timeout = 500; l->nfds = 1; return l; }
void jnx_socket_ipc_listener_tick(jnx_ipc_listener* listener, jnx_ipc_listener_callback callback, void *args) { jnx_int rv = poll(listener->ufds,listener->nfds,listener->poll_timeout); if (rv == -1) { perror("jnx IPC socket poll"); // error occurred in poll() } else if (rv == 0) { /* Timeout reached */ } jnx_int i, current_size = listener->nfds; jnx_int close_conn = 0, compress_array = 0; for(i=0;i<current_size;++i) { if(listener->ufds[i].revents == 0) { continue; } if(listener->ufds[i].fd == listener->socket->socket) { int new_fd = -1; do{ new_fd = accept(listener->socket->socket,NULL,NULL); if(new_fd < 0) { if(errno != EWOULDBLOCK) { JNXFAIL("jnx IPC socket could not accept"); exit(0); } break; } listener->ufds[listener->nfds].fd = new_fd; listener->ufds[listener->nfds].events = POLLIN; listener->nfds++; }while(new_fd != -1); }else { jnx_size rc = 0; // JNXLOG(LDEBUG,"Descriptor is readable %d",listener->ufds[i].fd); close_conn = 0; compress_array = 0; char buffer[MAXBUFFER]; bzero(buffer,MAXBUFFER); rc = recv(listener->ufds[i].fd,buffer,MAXBUFFER,0); if(rc == -1) { if(errno != EWOULDBLOCK){ perror("jnx IPC socket recv() failed"); close_conn = 1; } } if(rc == 0) { // JNXLOG(0,"Connection closed on fd %d",listener->ufds[i].fd); close_conn = 1; } /* Send callback */ if(rc > 0) { jnx_uint8 *outbuffer = malloc((rc + 1) * sizeof(jnx_uint8)); memset(outbuffer,0,rc + 1); memcpy(outbuffer,buffer,rc); callback(outbuffer,rc,listener->ufds[i].fd,args); free(outbuffer); } if(close_conn) { close(listener->ufds[i].fd); listener->ufds[i].fd = -1; compress_array = 1; } if(compress_array) { compress_array = 0; jnx_int j; for(j=i;j<listener->nfds;++j) { if(j+1 < listener->nfds) { listener->ufds[j] = listener->ufds[j+1]; } } listener->nfds--; } } } }