block_reader::pointer block_reader::get(std::istream & base, const setup::version & version) { USE_ENUM_NAMES(block_compression) uint32_t expected_checksum = load_number<uint32_t>(base); crypto::crc32 actual_checksum; actual_checksum.init(); uint32_t stored_size; block_compression compression; if(version >= INNO_VERSION(4, 0, 9)) { stored_size = actual_checksum.load_number<uint32_t>(base); uint8_t compressed = actual_checksum.load_number<uint8_t>(base); compression = compressed ? (version >= INNO_VERSION(4, 1, 6) ? LZMA1 : Zlib) : Stored; } else { uint32_t compressed_size = actual_checksum.load_number<uint32_t>(base); uint32_t uncompressed_size = actual_checksum.load_number<uint32_t>(base); if(compressed_size == uint32_t(-1)) { stored_size = uncompressed_size, compression = Stored; } else { stored_size = compressed_size, compression = Zlib; } // Add the size of a CRC32 checksum for each 4KiB subblock. stored_size += uint32_t(ceildiv<uint64_t>(stored_size, 4096) * 4); } if(actual_checksum.finalize() != expected_checksum) { throw block_error("block CRC32 mismatch"); } debug("[block] size: " << stored_size << " compression: " << compression); boost::shared_ptr<io::filtering_istream> fis = boost::make_shared<io::filtering_istream>(); switch(compression) { case Stored: break; case Zlib: fis->push(io::zlib_decompressor(), 8192); break; #if INNOEXTRACT_HAVE_LZMA case LZMA1: fis->push(inno_lzma1_decompressor(), 8192); break; #else case LZMA1: throw block_error("LZMA decompression not supported by this " + std::string(innoextract_name) + " build"); #endif } fis->push(inno_block_filter(), 4096); fis->push(io::restrict(base, 0, stored_size)); return fis; }
/** 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); }
/** 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); }
/** 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); }
HL_PRIM int hl_socket_send_char( hl_socket *s, int c ) { char cc; cc = (char)(unsigned char)c; if( !s ) return -2; if( send(s->sock,&cc,1,MSG_NOSIGNAL) == SOCKET_ERROR ) return block_error(); return 1; }
HL_PRIM int hl_socket_send( hl_socket *s, vbyte *buf, int pos, int len ) { int r; if( !s ) return -2; r = send(s->sock, (char*)buf + pos, len, MSG_NOSIGNAL); if( r == SOCKET_ERROR ) return block_error(); return len; }
HL_PRIM int hl_socket_recv( hl_socket *s, vbyte *buf, int pos, int len ) { int ret; if( !s ) return -2; hl_blocking(true); ret = recv(s->sock, (char*)buf + pos, len, MSG_NOSIGNAL); hl_blocking(false); if( ret == SOCKET_ERROR ) return block_error(); return ret; }
HL_PRIM int hl_socket_send_to( hl_socket *s, char *data, int len, int host, int port ) { struct sockaddr_in addr; if( !s ) return -2; memset(&addr,0,sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons((unsigned short)port); *(int*)&addr.sin_addr.s_addr = host; len = sendto(s->sock, data, len, MSG_NOSIGNAL, (struct sockaddr*)&addr, sizeof(addr)); if( len == SOCKET_ERROR ) return block_error(); return len; }
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; }
static value socket_accept( value o ) { SOCKET sock = val_sock(o); struct sockaddr_in addr; SockLen addrlen = sizeof(addr); SOCKET s; gc_enter_blocking(); s = accept(sock,(struct sockaddr*)&addr,&addrlen); if( s == INVALID_SOCKET ) return block_error(); gc_exit_blocking(); return alloc_abstract(k_socket,(void *)(socket_int)s); }
HL_PRIM int hl_socket_recv_char( hl_socket *s ) { char cc; int ret; if( !s ) return -2; hl_blocking(true); ret = recv(s->sock,&cc,1,MSG_NOSIGNAL); hl_blocking(false); if( ret == SOCKET_ERROR ) return block_error(); if( ret == 0 ) return -2; return (unsigned char)cc; }
/** 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); }
/** socket_connect : 'socket -> host:'int32 -> port:int -> void <doc>Connect the socket the given [host] and [port]</doc> **/ static value socket_connect( value o, value host, value port ) { struct sockaddr_in addr; val_check_kind(o,k_socket); val_check(host,int32); val_check(port,int); 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( connect(val_sock(o),(struct sockaddr*)&addr,sizeof(addr)) != 0 ) return block_error(); return val_true; }
/** 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; }
/** 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); }
HL_PRIM bool hl_socket_connect( hl_socket *s, int host, int port ) { struct sockaddr_in addr; memset(&addr,0,sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons((unsigned short)port); *(int*)&addr.sin_addr.s_addr = host; if( !s ) return false; hl_blocking(true); if( connect(s->sock,(struct sockaddr*)&addr,sizeof(addr)) != 0 ) { int err = block_error(); hl_blocking(false); if( err == -1 ) return true; // in progress return false; } hl_blocking(false); return true; }
/** 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); }
HL_PRIM int hl_socket_recv_from( hl_socket *s, char *data, int len, int *host, int *port ) { struct sockaddr_in saddr; socklen_t slen = sizeof(saddr); if( !s ) return -2; hl_blocking(true); len = recvfrom(s->sock, data, len, MSG_NOSIGNAL, (struct sockaddr*)&saddr, &slen); hl_blocking(false); if( len == SOCKET_ERROR ) { #ifdef HL_WIN if( WSAGetLastError() == WSAECONNRESET ) len = 0; else #endif return block_error(); } *host = *(int*)&saddr.sin_addr; *port = ntohs(saddr.sin_port); return len; }
/** socket_send : 'socket -> buf:string -> pos:int -> len:int -> int <doc>Send up to [len] bytes from [buf] starting at [pos] over a connected socket. Return the number of bytes sent.</doc> **/ static value socket_send( value o, value data, value pos, value len ) { int p,l,dlen; 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(send_again); dlen = send(val_sock(o), val_string(data) + p , l, MSG_NOSIGNAL); if( dlen == SOCKET_ERROR ) { HANDLE_EINTR(send_again); return block_error(); } return alloc_int(dlen); }
/** 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; }
/** 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); }
/** socket_connect : 'socket -> host:'string -> port:int -> void <doc>Connect the socket the given [host] and [port]</doc> **/ static value socket_connect( value o, value host, value port ) { val_check(host,string); val_check(port,int); struct sockaddr* addr; struct sockaddr_in addr4; struct sockaddr_in6 addr6; unsigned char ip[16]; int len = 0; if (inet_pton(AF_INET, val_string(host), ip) == 1) { memset(&addr4,0,sizeof(addr4)); addr4.sin_family = AF_INET; addr4.sin_port = htons(val_int(port)); *(int*)&addr4.sin_addr.s_addr = *(int*)ip; addr = (struct sockaddr*)&addr4; len = sizeof (struct sockaddr_in); } else if (inet_pton(AF_INET6, val_string(host), ip) == 1) { memset(&addr6,0,sizeof(addr6)); addr6.sin6_family = AF_INET6; addr6.sin6_port = htons(val_int(port)); memcpy(addr6.sin6_addr.s6_addr, ip, 16); addr = (struct sockaddr*)&addr6; len = sizeof (struct sockaddr_in6); } gc_enter_blocking(); if( connect(val_sock(o),addr,len) != 0 ) { // This will throw a "Blocking" exception if the "error" was because // it's a non-blocking socket with connection in progress, otherwise // it will do nothing. (void) block_error(); // If the previous line did not throw an exception, then it was a real // connect failure. val_throw(alloc_string("std@socket_connect")); } gc_exit_blocking(); return alloc_bool(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); }
static value ssl_recv( value ssl, value data, value pos, value len ) { int p,l,dlen; void * buf; 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 ); buf = (void *) (val_string(data) + p); POSIX_LABEL(recv_again); dlen = mbedtls_ssl_read( val_ssl(ssl), buf, l ); if( dlen == SOCKET_ERROR ) { HANDLE_EINTR(recv_again); return block_error(); } if( dlen < 0 ) neko_error(); return alloc_int( dlen ); }
/** socket_send : 'socket -> buf:string -> pos:int -> len:int -> int <doc>Send up to [len] bytes from [buf] starting at [pos] over a connected socket. Return the number of bytes sent.</doc> **/ static value socket_send( value o, value data, value pos, value len ) { int p,l,dlen; SOCKET sock = val_sock(o); val_check(pos,int); val_check(len,int); buffer buf = val_to_buffer(data); if (!buf) hx_failure("not bytebuffer"); p = val_int(pos); l = val_int(len); dlen = buffer_size(buf); if( p < 0 || l < 0 || p > dlen || p + l > dlen ) return alloc_null(); gc_enter_blocking(); dlen = send(sock, buffer_data(buf) + p , l, MSG_NOSIGNAL); if( dlen == SOCKET_ERROR ) return block_error(); gc_exit_blocking(); return alloc_int(dlen); }
static value ssl_read( value ssl ) { int len, bufsize = 256; buffer b; unsigned char buf[256]; mbedtls_ssl_context *ctx; val_check_kind(ssl,k_ssl); ctx = val_ssl(ssl); b = alloc_buffer(NULL); while( true ) { POSIX_LABEL(read_again); len = mbedtls_ssl_read( ctx, buf, bufsize ); if( len == SOCKET_ERROR ) { HANDLE_EINTR(read_again); return block_error(); } if( len == 0 ) break; buffer_append_sub(b,(const char *)buf,len); } return buffer_to_string(b); }
static value ssl_write( value ssl, value data ) { int len, slen; const unsigned char *s; mbedtls_ssl_context *ctx; val_check_kind(ssl,k_ssl); val_check(data,string); s = (const unsigned char *)val_string( data ); len = val_strlen( data ); ctx = val_ssl(ssl); while( len > 0 ) { POSIX_LABEL( write_again ); slen = mbedtls_ssl_write( ctx, s, len ); if( slen == SOCKET_ERROR ) { HANDLE_EINTR( write_again ); return block_error(); } s += slen; len -= slen; } return val_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; SOCKET sock = val_sock(o); val_check(data,buffer); buffer buf = val_to_buffer(data); cdata = buffer_data(buf); datalen = buffer_size(buf); gc_enter_blocking(); while( datalen > 0 ) { POSIX_LABEL(write_again); slen = send(sock,cdata,datalen,MSG_NOSIGNAL); if( slen == SOCKET_ERROR ) { HANDLE_EINTR(write_again); return block_error(); } cdata += slen; datalen -= slen; } gc_exit_blocking(); return alloc_bool(true); }
/** socket_connect : 'socket -> host:'int32 -> port:int -> void <doc>Connect the socket the given [host] and [port]</doc> **/ static value socket_connect( value o, value host, value port ) { struct sockaddr_in addr; val_check(host,int); val_check(port,int); 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); gc_enter_blocking(); if( connect(val_sock(o),(struct sockaddr*)&addr,sizeof(addr)) != 0 ) { // This will throw a "Blocking" exception if the "error" was because // it's a non-blocking socket with connection in progress, otherwise // it will do nothing. (void) block_error(); // If the previous line did not throw an exception, then it was a real // connect failure. val_throw(alloc_string("std@socket_connect")); } gc_exit_blocking(); return alloc_bool(true); }