/** socket_close : 'socket -> void <doc>Close a socket. Any subsequent operation on this socket will fail</doc> **/ static value socket_close( value o ) { POSIX_LABEL(close_again); if( closesocket(val_sock(o)) ) { HANDLE_EINTR(close_again); } return alloc_bool(true); }
/** file_contents : f:string -> string <doc>Read the content of the file [f] and return it.</doc> **/ static value file_contents( value name ) { buffer s; int len; int p; val_check(name,string); fio f(val_filename(name)); const char *fname = val_string(name); gc_enter_blocking(); f.io = fopen(fname,"rb"); if( f.io == NULL ) file_error("file_contents",&f); fseek(f.io,0,SEEK_END); len = ftell(f.io); fseek(f.io,0,SEEK_SET); gc_exit_blocking(); s = alloc_buffer_len(len); p = 0; gc_enter_blocking(); while( len > 0 ) { int d; POSIX_LABEL(file_contents); d = (int)fread((char*)buffer_data(s)+p,1,len,f.io); if( d <= 0 ) { HANDLE_FINTR(f.io,file_contents); fclose(f.io); file_error("file_contents",&f); } p += d; len -= d; } fclose(f.io); gc_exit_blocking(); return buffer_val(s); }
/** file_write : 'file -> s:string -> p:int -> l:int -> int <doc> Write up to [l] chars of string [s] starting at position [p]. Returns the number of chars written which is >= 0. </doc> **/ int _hx_std_file_write( Dynamic handle, Array<unsigned char> s, int p, int n ) { fio *f = getFio(handle); int buflen = s->length; int len = n; if( p < 0 || len < 0 || p > buflen || p + len > buflen ) return 0; hx::EnterGCFreeZone(); while( len > 0 ) { POSIX_LABEL(file_write_again); int d = (int)fwrite(&s[p],1,len,f->io); if( d <= 0 ) { HANDLE_FINTR(f->io,file_write_again); file_error("file_write",f->name); } p += d; len -= d; } hx::ExitGCFreeZone(); return n; }
/** file_contents : f:string -> string <doc>Read the content of the file [f] and return it.</doc> **/ static value file_contents( value name ) { value s; fio f; int len; int p; val_check(name,string); f.name = name; f.io = fopen(val_string(name),"rb"); if( f.io == NULL ) file_error("file_contents",&f); fseek(f.io,0,SEEK_END); len = ftell(f.io); fseek(f.io,0,SEEK_SET); s = alloc_empty_string(len); p = 0; while( len > 0 ) { int d; POSIX_LABEL(file_contents); d = (int)fread((char*)val_string(s)+p,1,len,f.io); if( d <= 0 ) { HANDLE_FINTR(f.io,file_contents); fclose(f.io); file_error("file_contents",&f); } p += d; len -= d; } fclose(f.io); return s; }
/** socket_send_to : 'socket -> buf:string -> pos:int -> length:int -> addr:{host:'int32,port:int} -> int <doc> Send data from an unconnected UDP socket to the given address. </doc> **/ static value socket_send_to( value o, value dataBuf, value pos, value len, value vaddr ) { int p,l; value host, port; struct sockaddr_in addr; val_check_kind(o,k_socket); buffer buf = val_to_buffer(dataBuf); const char *cdata = buffer_data(buf); int dlen = buffer_size(buf); val_check(pos,int); val_check(len,int); val_check(vaddr,object); host = val_field(vaddr, f_host); port = val_field(vaddr, f_port); val_check(host,int); val_check(port,int); p = val_int(pos); l = val_int(len); memset(&addr,0,sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(val_int(port)); *(int*)&addr.sin_addr.s_addr = val_int(host); if( p < 0 || l < 0 || p > dlen || p + l > dlen ) neko_error(); SOCKET sock = val_sock(o); gc_enter_blocking(); POSIX_LABEL(send_again); dlen = sendto(sock, cdata + p , l, MSG_NOSIGNAL, (struct sockaddr*)&addr, sizeof(addr)); if( dlen == SOCKET_ERROR ) { HANDLE_EINTR(send_again); return block_error(); } gc_exit_blocking(); return alloc_int(dlen); }
static value socket_recv_from( value o, value dataBuf, value pos, value len, value addr ) { int p,l,ret; int retry = 0; struct sockaddr_in saddr; SockLen slen = sizeof(saddr); val_check_kind(o,k_socket); val_check(dataBuf,buffer); buffer buf = val_to_buffer(dataBuf); char *data = buffer_data(buf); int dlen = buffer_size(buf); val_check(pos,int); val_check(len,int); val_check(addr,object); p = val_int(pos); l = val_int(len); if( p < 0 || l < 0 || p > dlen || p + l > dlen ) neko_error(); SOCKET sock = val_sock(o); gc_enter_blocking(); POSIX_LABEL(recv_from_again); if( retry++ > NRETRYS ) { ret = recv(sock,data+p,l,MSG_NOSIGNAL); } else ret = recvfrom(sock, data + p , l, MSG_NOSIGNAL, (struct sockaddr*)&saddr, &slen); if( ret == SOCKET_ERROR ) { HANDLE_EINTR(recv_from_again); return block_error(); } gc_exit_blocking(); alloc_field(addr,f_host,alloc_int32(*(int*)&saddr.sin_addr)); alloc_field(addr,f_port,alloc_int(ntohs(saddr.sin_port))); return alloc_int(ret); }
/** file_read : 'file -> s:string -> p:int -> l:int -> int <doc> Read up to [l] chars into the string [s] starting at position [p]. Returns the number of chars readed which is > 0 (or 0 if l == 0). </doc> **/ int _hx_std_file_read( Dynamic handle, Array<unsigned char> buf, int p, int n ) { fio *f = getFio(handle); int buf_len = buf->length; int len = n; if( p < 0 || len < 0 || p > buf_len || p + len > buf_len ) return 0; hx::EnterGCFreeZone(); // Attempt to increase the chances of pinning on the stack... unsigned char *bufPtr = &buf[0]; while( len > 0 ) { POSIX_LABEL(file_read_again); int d = (int)fread(bufPtr + p,1,len,f->io); if( d <= 0 ) { int size = n - len; HANDLE_FINTR(f->io,file_read_again); if( size == 0 ) file_error("file_read",f->name); hx::ExitGCFreeZone(); return size; } p += d; len -= d; } hx::ExitGCFreeZone(); return n; }
/** socket_send_to : 'socket -> buf:string -> pos:int -> length:int -> addr:{host:'int32,port:int} -> int <doc> Send data from an unconnected UDP socket to the given address. </doc> **/ static value socket_send_to( value o, value data, value pos, value len, value vaddr ) { int p,l,dlen; value host, port; struct sockaddr_in addr; val_check_kind(o,k_socket); val_check(data,string); val_check(pos,int); val_check(len,int); val_check(vaddr,object); host = val_field(vaddr, f_host); port = val_field(vaddr, f_port); val_check(host,int32); val_check(port,int); p = val_int(pos); l = val_int(len); dlen = val_strlen(data); memset(&addr,0,sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(val_int(port)); *(int*)&addr.sin_addr.s_addr = val_int32(host); if( p < 0 || l < 0 || p > dlen || p + l > dlen ) neko_error(); POSIX_LABEL(send_again); dlen = sendto(val_sock(o), val_string(data) + p , l, MSG_NOSIGNAL, (struct sockaddr*)&addr, sizeof(addr)); if( dlen == SOCKET_ERROR ) { HANDLE_EINTR(send_again); return block_error(); } return alloc_int(dlen); }
/** file_contents : f:string -> string <doc>Read the content of the file [f] and return it.</doc> **/ String _hx_std_file_contents_string( String name ) { std::vector<char> buffer; hx::EnterGCFreeZone(); FILE *file = fopen(name.__s, "rb"); if(!file) file_error("file_contents",name); fseek(file,0,SEEK_END); int len = ftell(file); if (len<0) file_error("file_ftell",name); fseek(file,0,SEEK_SET); buffer.resize(len); int p = 0; while( len > 0 ) { POSIX_LABEL(file_contents); int d = (int)fread(&buffer[p],1,len,file); if( d <= 0 ) { HANDLE_FINTR(file,file_contents); fclose(file); file_error("file_contents",name); } p += d; len -= d; } fclose(file); hx::ExitGCFreeZone(); return String(&buffer[0], buffer.size()).dup(); }
/** 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; }
/** socket_recv : 'socket -> buf:string -> pos:int -> len:int -> int <doc>Read up to [len] bytes from [buf] starting at [pos] from a connected socket. Return the number of bytes readed.</doc> **/ static value socket_recv( value o, value data, value pos, value len ) { int p,l,dlen,ret; int retry = 0; val_check_kind(o,k_socket); val_check(data,string); val_check(pos,int); val_check(len,int); p = val_int(pos); l = val_int(len); dlen = val_strlen(data); if( p < 0 || l < 0 || p > dlen || p + l > dlen ) neko_error(); POSIX_LABEL(recv_again); if( retry++ > NRETRYS ) { sock_tmp t; t.sock = val_sock(o); t.buf = val_string(data) + p; t.size = l; neko_thread_blocking(tmp_recv,&t); ret = t.ret; } else ret = recv(val_sock(o), val_string(data) + p , l, MSG_NOSIGNAL); if( ret == SOCKET_ERROR ) { HANDLE_EINTR(recv_again); return block_error(); } return alloc_int(ret); }
/** file_read : 'file -> s:string -> p:int -> l:int -> int <doc> Read up to [l] chars into the string [s] starting at position [p]. Returns the number of chars readed which is > 0 (or 0 if l == 0). </doc> **/ static value file_read( value o, value s, value pp, value n ) { fio *f; int p; int len; int buf_len; val_check_kind(o,k_file); val_check(s,buffer); buffer buf = val_to_buffer(s); buf_len = buffer_size(buf); val_check(pp,int); val_check(n,int); f = val_file(o); p = val_int(pp); len = val_int(n); if( p < 0 || len < 0 || p > buf_len || p + len > buf_len ) return alloc_null(); gc_enter_blocking(); while( len > 0 ) { int d; POSIX_LABEL(file_read_again); d = (int)fread(buffer_data(buf)+p,1,len,f->io); if( d <= 0 ) { int size = val_int(n) - len; HANDLE_FINTR(f->io,file_read_again); if( size == 0 ) file_error("file_read",f); return alloc_int(size); } p += d; len -= d; } gc_exit_blocking(); return n; }
/** file_write : 'file -> s:string -> p:int -> l:int -> int <doc> Write up to [l] chars of string [s] starting at position [p]. Returns the number of chars written which is >= 0. </doc> **/ static value file_write( value o, value s, value pp, value n ) { int p, len; fio *f; val_check_kind(o,k_file); val_check(s,string); val_check(pp,int); val_check(n,int); f = val_file(o); p = val_int(pp); len = val_int(n); if( p < 0 || len < 0 || p > val_strlen(s) || p + len > val_strlen(s) ) neko_error(); while( len > 0 ) { int d; POSIX_LABEL(file_write_again); d = (int)fwrite(val_string(s)+p,1,len,f->io); if( d <= 0 ) { HANDLE_FINTR(f->io,file_write_again); file_error("file_write",f); } p += d; len -= d; } return n; }
/** file_read : 'file -> s:string -> p:int -> l:int -> int <doc> Read up to [l] chars into the string [s] starting at position [p]. Returns the number of chars readed which is > 0 (or 0 if l == 0). </doc> **/ static value file_read( value o, value s, value pp, value n ) { fio *f; int p; int len; val_check_kind(o,k_file); val_check(s,string); val_check(pp,int); val_check(n,int); f = val_file(o); p = val_int(pp); len = val_int(n); if( p < 0 || len < 0 || p > val_strlen(s) || p + len > val_strlen(s) ) neko_error(); while( len > 0 ) { int d; POSIX_LABEL(file_read_again); d = (int)fread((char*)val_string(s)+p,1,len,f->io); if( d <= 0 ) { int size = val_int(n) - len; HANDLE_FINTR(f->io,file_read_again); if( size == 0 ) file_error("file_read",f); return alloc_int(size); } p += d; len -= d; } return n; }
static int do_close( int fd ) { POSIX_LABEL(close_again); if( close(fd) != 0 ) { HANDLE_EINTR(close_again); return 1; } return 0; }
/** socket_close : 'socket -> void <doc>Close a socket. Any subsequent operation on this socket will fail</doc> **/ static value socket_close( value o ) { val_check_kind(o,k_socket); POSIX_LABEL(close_again); if( closesocket(val_sock(o)) ) { HANDLE_EINTR(close_again); } val_kind(o) = NULL; return val_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; }
/** file_read_char : 'file -> int <doc>Read a char from the file. Exception on error</doc> **/ static value file_read_char( value o ) { unsigned char cc; fio *f; val_check_kind(o,k_file); f = val_file(o); POSIX_LABEL(read_char_again); if( fread(&cc,1,1,f->io) != 1 ) { HANDLE_FINTR(f->io,read_char_again); file_error("file_read_char",f); } return alloc_int(cc); }
static value ssl_handshake( value ssl ) { int r; val_check_kind(ssl,k_ssl); POSIX_LABEL(handshake_again); r = mbedtls_ssl_handshake( val_ssl(ssl) ); if( r == SOCKET_ERROR ) { HANDLE_EINTR(handshake_again); return block_error(); }else if( r != 0 ) return ssl_error(r); return val_true; }
/** socket_accept : 'socket -> 'socket <doc>Accept an incoming connection request</doc> **/ static value socket_accept( value o ) { struct sockaddr_in addr; unsigned int addrlen = sizeof(addr); SOCKET s; val_check_kind(o,k_socket); POSIX_LABEL(accept_again); s = accept(val_sock(o),(struct sockaddr*)&addr,&addrlen); if( s == INVALID_SOCKET ) { HANDLE_EINTR(accept_again); return block_error(); } return alloc_abstract(k_socket,(value)(int_val)s); }
/** file_read_char : 'file -> int <doc>Read a char from the file. Exception on error</doc> **/ int _hx_std_file_read_char( Dynamic handle ) { fio *f = getFio(handle); unsigned char cc = 0; hx::EnterGCFreeZone(); POSIX_LABEL(read_char_again); if( fread(&cc,1,1,f->io) != 1 ) { HANDLE_FINTR(f->io,read_char_again); file_error("file_read_char",f->name); } hx::ExitGCFreeZone(); return cc; }
/** socket_send_char : 'socket -> int -> void <doc>Send a character over a connected socket. Must be in the range 0..255</doc> **/ static value socket_send_char( value o, value v ) { int c; unsigned char cc; val_check_kind(o,k_socket); val_check(v,int); c = val_int(v); if( c < 0 || c > 255 ) neko_error(); cc = (unsigned char)c; POSIX_LABEL(send_char_again); if( send(val_sock(o),&cc,1,MSG_NOSIGNAL) == SOCKET_ERROR ) { HANDLE_EINTR(send_char_again); return block_error(); } return val_true; }
/** file_write_char : 'file -> c:int -> void <doc>Write the char [c]. Error if [c] outside of the range 0..255</doc> **/ void _hx_std_file_write_char( Dynamic handle, int c ) { fio *f = getFio(handle); if( c < 0 || c > 255 ) return; char cc = (char)c; hx::EnterGCFreeZone(); POSIX_LABEL(write_char_again); if( fwrite(&cc,1,1,f->io) != 1 ) { HANDLE_FINTR(f->io,write_char_again); file_error("file_write_char",f->name); } hx::ExitGCFreeZone(); }
/** file_write_char : 'file -> c:int -> void <doc>Write the char [c]. Error if [c] outside of the range 0..255</doc> **/ static value file_write_char( value o, value c ) { unsigned char cc; fio *f; val_check(c,int); val_check_kind(o,k_file); if( val_int(c) < 0 || val_int(c) > 255 ) neko_error(); cc = (char)val_int(c); f = val_file(o); POSIX_LABEL(write_char_again); if( fwrite(&cc,1,1,f->io) != 1 ) { HANDLE_FINTR(f->io,write_char_again); file_error("file_write_char",f); } return val_null; }
/** socket_recv_char : 'socket -> int <doc>Read a single char from a connected socket.</doc> **/ static value socket_recv_char( value o ) { int ret; unsigned char cc; SOCKET sock = val_sock(o); gc_enter_blocking(); POSIX_LABEL(recv_char_again); ret = recv(sock,(char *)&cc,1,MSG_NOSIGNAL); if( ret == SOCKET_ERROR ) { HANDLE_EINTR(recv_char_again); return block_error(); } gc_exit_blocking(); if( ret == 0 ) val_throw(alloc_string("Connection closed")); return alloc_int(cc); }
/** socket_send_char : 'socket -> int -> void <doc>Send a character over a connected socket. Must be in the range 0..255</doc> **/ static value socket_send_char( value o, value v ) { int c; unsigned char cc; SOCKET sock = val_sock(o); val_check(v,int); c = val_int(v); if( c < 0 || c > 255 ) return alloc_null(); cc = (unsigned char)c; gc_enter_blocking(); POSIX_LABEL(send_char_again); if( send(sock,(const char *)&cc,1,MSG_NOSIGNAL) == SOCKET_ERROR ) { HANDLE_EINTR(send_char_again); return block_error(); } gc_exit_blocking(); return alloc_bool(true); }
/** file_write_char : 'file -> c:int -> void <doc>Write the char [c]. Error if [c] outside of the range 0..255</doc> **/ static value file_write_char( value o, value c ) { unsigned char cc; fio *f; val_check(c,int); val_check_kind(o,k_file); if( val_int(c) < 0 || val_int(c) > 255 ) return alloc_null(); cc = (char)val_int(c); f = val_file(o); gc_enter_blocking(); POSIX_LABEL(write_char_again); if( fwrite(&cc,1,1,f->io) != 1 ) { HANDLE_FINTR(f->io,write_char_again); file_error("file_write_char",f); } gc_exit_blocking(); return alloc_bool(true); }
/** socket_write : 'socket -> string -> void <doc>Send the whole content of a string over a connected socket.</doc> **/ static value socket_write( value o, value data ) { const char *cdata; int datalen, slen; val_check_kind(o,k_socket); val_check(data,string); cdata = val_string(data); datalen = val_strlen(data); while( datalen > 0 ) { POSIX_LABEL(write_again); slen = send(val_sock(o),cdata,datalen,MSG_NOSIGNAL); if( slen == SOCKET_ERROR ) { HANDLE_EINTR(write_again); return block_error(); } cdata += slen; datalen -= slen; } return val_true; }
static value ssl_send( value ssl, value data, value pos, value len ) { int p,l,dlen; val_check_kind(ssl,k_ssl); val_check(data,string); val_check(pos,int); val_check(len,int); p = val_int(pos); l = val_int(len); dlen = val_strlen(data); if( p < 0 || l < 0 || p > dlen || p + l > dlen ) neko_error(); POSIX_LABEL(send_again); dlen = mbedtls_ssl_write( val_ssl(ssl), (const unsigned char *)val_string(data) + p, l ); if( dlen == SOCKET_ERROR ) { HANDLE_EINTR(send_again); return block_error(); } return alloc_int(dlen); }
/** socket_read : 'socket -> string <doc>Read the whole content of a the data available from a socket until the connection close. If the socket hasn't been close by the other side, the function might block. </doc> **/ static value socket_read( value o ) { buffer b; char buf[256]; int len; val_check_kind(o,k_socket); b = alloc_buffer(NULL); while( true ) { POSIX_LABEL(read_again); len = recv(val_sock(o),buf,256,MSG_NOSIGNAL); if( len == SOCKET_ERROR ) { HANDLE_EINTR(read_again); return block_error(); } if( len == 0 ) break; buffer_append_sub(b,buf,len); } return buffer_to_string(b); }