/** socket_set_timeout : 'socket -> timout:number? -> void <doc>Set the socket send and recv timeout in seconds to the given value (or null for blocking)</doc> **/ static value socket_set_timeout( value o, value t ) { #ifdef NEKO_WINDOWS int time; val_check_kind(o,k_socket); if( val_is_null(t) ) time = 0; else { val_check(t,number); time = (int)(val_number(t) * 1000); } #else struct timeval time; val_check_kind(o,k_socket); if( val_is_null(t) ) { time.tv_usec = 0; time.tv_sec = 0; } else { val_check(t,number); init_timeval(val_number(t),&time); } #endif if( setsockopt(val_sock(o),SOL_SOCKET,SO_SNDTIMEO,(char*)&time,sizeof(time)) != 0 ) neko_error(); if( setsockopt(val_sock(o),SOL_SOCKET,SO_RCVTIMEO,(char*)&time,sizeof(time)) != 0 ) neko_error(); return val_true; }
/** socket_set_timeout : 'socket -> timout:number? -> void <doc>Set the socket send and recv timeout in seconds to the given value (or null for blocking)</doc> **/ static value socket_set_timeout( value o, value t ) { SOCKET sock = val_sock(o); #ifdef NEKO_WINDOWS int time; if( val_is_null(t) ) time = 0; else { val_check(t,number); time = (int)(val_number(t) * 1000); } #else struct timeval time; if( val_is_null(t) ) { time.tv_usec = 0; time.tv_sec = 0; } else { val_check(t,number); init_timeval(val_number(t),&time); } #endif gc_enter_blocking(); if( setsockopt(sock,SOL_SOCKET,SO_SNDTIMEO,(char*)&time,sizeof(time)) != 0 ) { gc_exit_blocking(); return alloc_null(); } if( setsockopt(sock,SOL_SOCKET,SO_RCVTIMEO,(char*)&time,sizeof(time)) != 0 ) { gc_exit_blocking(); return alloc_null(); } gc_exit_blocking(); return alloc_bool(true); }
/** socket_select : read : 'socket array -> write : 'socket array -> others : 'socket array -> timeout:number? -> 'socket array array <doc>Perform the [select] operation. Timeout is in seconds or [null] if infinite</doc> **/ static value socket_select( value rs, value ws, value es, value timeout ) { struct timeval tval; struct timeval *tt; SOCKET n = 0; fd_set rx, wx, ex; fd_set *ra, *wa, *ea; value r; POSIX_LABEL(select_again); ra = make_socket_array(rs,val_array_size(rs),&rx,&n); wa = make_socket_array(ws,val_array_size(ws),&wx,&n); ea = make_socket_array(es,val_array_size(es),&ex,&n); if( ra == &INVALID || wa == &INVALID || ea == &INVALID ) neko_error(); if( val_is_null(timeout) ) tt = NULL; else { val_check(timeout,number); tt = &tval; init_timeval(val_number(timeout),tt); } if( select((int)(n+1),ra,wa,ea,tt) == SOCKET_ERROR ) { HANDLE_EINTR(select_again); neko_error(); } r = alloc_array(3); val_array_ptr(r)[0] = make_array_result(rs,ra); val_array_ptr(r)[1] = make_array_result(ws,wa); val_array_ptr(r)[2] = make_array_result(es,ea); return r; }
HL_PRIM bool hl_socket_select( varray *ra, varray *wa, varray *ea, char *tmp, int tmp_size, double timeout ) { struct timeval tval, *tt; fd_set *rs, *ws, *es; unsigned int max = 0; rs = make_socket_set(ra,&tmp,&tmp_size,&max); ws = make_socket_set(wa,&tmp,&tmp_size,&max); es = make_socket_set(ea,&tmp,&tmp_size,&max); if( rs == NULL || ws == NULL || es == NULL ) return false; if( timeout < 0 ) tt = NULL; else { tt = &tval; init_timeval(timeout,tt); } hl_blocking(true); if( select((int)(max+1),ra?rs:NULL,wa?ws:NULL,ea?es:NULL,tt) == SOCKET_ERROR ) { hl_blocking(false); return false; } hl_blocking(false); make_array_result(rs,ra); make_array_result(ws,wa); make_array_result(es,ea); return true; }
/** socket_poll_events : 'poll -> timeout:float -> void <doc> Update the read/write flags arrays that were created with [socket_poll_prepare]. </doc> **/ static value socket_poll_events( value pdata, value timeout ) { polldata *p; # ifdef NEKO_WINDOWS unsigned int i; int k = 0; struct timeval t; val_check_kind(pdata,k_poll); p = val_poll(pdata); memcpy(p->outr,p->fdr,FDSIZE(p->fdr->fd_count)); memcpy(p->outw,p->fdw,FDSIZE(p->fdw->fd_count)); val_check(timeout,number); init_timeval(val_number(timeout),&t); gc_enter_blocking(); if( p->fdr->fd_count + p->fdw->fd_count != 0 && select(0,p->outr,p->outw,NULL,&t) == SOCKET_ERROR ) { gc_exit_blocking(); return alloc_null(); } gc_exit_blocking(); k = 0; for(i=0;i<p->fdr->fd_count;i++) if( FD_ISSET(p->fdr->fd_array[i],p->outr) ) val_array_set_i(p->ridx,k++,alloc_int(i)); val_array_set_i(p->ridx,k,alloc_int(-1)); k = 0; for(i=0;i<p->fdw->fd_count;i++) if( FD_ISSET(p->fdw->fd_array[i],p->outw) ) val_array_set_i(p->widx,k++, alloc_int(i)); val_array_set_i(p->widx,k,alloc_int(-1)); #else int i,k; int tot; val_check_kind(pdata,k_poll); val_check(timeout,number); p = val_poll(pdata); tot = p->rcount + p->wcount; gc_enter_blocking(); POSIX_LABEL(poll_events_again); if( poll(p->fds,tot,(int)(val_number(timeout) * 1000)) < 0 ) { HANDLE_EINTR(poll_events_again); gc_exit_blocking(); return alloc_null(); } gc_exit_blocking(); k = 0; for(i=0;i<p->rcount;i++) if( p->fds[i].revents & (POLLIN|POLLHUP) ) val_array_set_i(p->ridx,k++,alloc_int(i)); val_array_set_i(p->ridx,k, alloc_int(-1)); k = 0; for(;i<tot;i++) if( p->fds[i].revents & (POLLOUT|POLLHUP) ) val_array_set_i(p->widx,k++, alloc_int(i - p->rcount)); val_array_set_i(p->widx,k, alloc_int(-1)); #endif return val_null; }
HL_PRIM bool hl_socket_set_timeout( hl_socket *s, double t ) { #ifdef HL_WIN int time = (int)(t * 1000); #else struct timeval time; init_timeval(t,&time); #endif if( !s ) return false; if( setsockopt(s->sock,SOL_SOCKET,SO_SNDTIMEO,(char*)&time,sizeof(time)) != 0 ) return false; if( setsockopt(s->sock,SOL_SOCKET,SO_RCVTIMEO,(char*)&time,sizeof(time)) != 0 ) return false; return true; }
/** socket_select : read : 'socket array -> write : 'socket array -> others : 'socket array -> timeout:number? -> 'socket array array <doc>Perform the [select] operation. Timeout is in seconds or [null] if infinite</doc> **/ static value socket_select( value rs, value ws, value es, value timeout ) { struct timeval tval; struct timeval *tt; SOCKET n = 0; fd_set rx, wx, ex; fd_set *ra, *wa, *ea; value r; POSIX_LABEL(select_again); ra = make_socket_array(rs,&rx,&n); wa = make_socket_array(ws,&wx,&n); ea = make_socket_array(es,&ex,&n); if( ra == &INVALID || wa == &INVALID || ea == &INVALID ) { val_throw( alloc_string("No valid sockets") ); return alloc_null(); } if( val_is_null(timeout) ) tt = NULL; else { val_check(timeout,number); tt = &tval; init_timeval(val_number(timeout),tt); } gc_enter_blocking(); if( select((int)(n+1),ra,wa,ea,tt) == SOCKET_ERROR ) { HANDLE_EINTR(select_again); gc_exit_blocking(); char buf[100]; sprintf(buf,"Select error %d", errno ); val_throw( alloc_string(buf) ); } gc_exit_blocking(); r = alloc_array(3); val_array_set_i(r,0,make_array_result(rs,ra)); val_array_set_i(r,1,make_array_result(ws,wa)); val_array_set_i(r,2,make_array_result(es,ea)); return r; }
/** socket_epoll_wait : 'epoll -> int -> float -> int array <doc>Wait and return a list of socket fds with events.</doc> **/ static value socket_epoll_wait(value e, value timeout) { epolldata *ep; #ifndef HAS_EPOLL struct timeval t; SOCKET n = 0; bool indefinite; fd_set rx, wx; fd_set *ra, *wa; int i; int pos = 0; val_check_kind(e,k_epoll); ep = val_epoll(e); POSIX_LABEL(select_again); ra = ep->rcount == 0 ? NULL : make_socket_array(ep->read, ep->rcount, &rx, &n); wa = ep->wcount == 0 ? NULL : make_socket_array(ep->write, ep->wcount, &wx, &n); indefinite = val_is_null(timeout); if (!indefinite) { val_check(timeout,number); init_timeval(val_number(timeout),&t); } if( select((int)(n+1),ra,wa,NULL,indefinite ? NULL : &t) == SOCKET_ERROR ) { HANDLE_EINTR(select_again); val_throw(alloc_int(errno)); } if (ra != NULL) { for (i=0; i < ep->rcount && pos < ep->maxevents; i++) { value s = val_array_ptr(ep->read)[i]; if (FD_ISSET(val_sock(s),ra)) val_array_ptr(ep->result)[pos++] = alloc_int(val_sock(s)); } } if (wa != NULL) { for (i=0; i < ep->wcount && pos < ep->maxevents; i++) { value s = val_array_ptr(ep->write)[i]; if (FD_ISSET(val_sock(s),wa)) val_array_ptr(ep->result)[pos++] = alloc_int(val_sock(s)); } } val_set_size(ep->result,pos); return ep->result; #else int t; val_check_kind(e,k_epoll); ep = val_epoll(e); if (val_is_null(timeout)) t = -1; else { val_check(timeout,number); t = (int)(val_number(timeout)) * 1000; } int ret = epoll_wait(ep->epollfd, ep->events, ep->maxevents, t); if (ret == -1) val_throw(alloc_int(errno)); val_set_size(ep->result, ret); int i; for (i = 0; i < ret; i++) { val_array_ptr(ep->result)[i] = alloc_int(ep->events[i].data.fd); } return ep->result; #endif }