/** deque_create : void -> 'deque <doc>create a message queue for multithread access</doc> **/ static value deque_create() { vdeque *q = (vdeque*)alloc(sizeof(vdeque)); value v = alloc_abstract(k_deque,q); val_gc(v,free_deque); _deque_init(q); return v; }
static value key_from_pem(value data, value pub, value pass){ mbedtls_pk_context *pk; int r, len; value v; unsigned char *buf; val_check(data, string); val_check(pub, bool); if (!val_is_null(pass)) val_check(pass, string); len = val_strlen(data)+1; buf = (unsigned char *)alloc(len); memcpy(buf, val_string(data), len-1); buf[len-1] = '\0'; pk = (mbedtls_pk_context *)alloc(sizeof(mbedtls_pk_context)); mbedtls_pk_init(pk); if( val_bool(pub) ) r = mbedtls_pk_parse_public_key( pk, buf, len ); else if( val_is_null(pass) ) r = mbedtls_pk_parse_key( pk, buf, len, NULL, 0 ); else r = mbedtls_pk_parse_key( pk, buf, len, (const unsigned char*)val_string(pass), val_strlen(pass) ); if( r != 0 ){ mbedtls_pk_free(pk); return ssl_error(r); } v = alloc_abstract(k_pkey,pk); val_gc(v,free_pkey); return v; }
/** socket_poll_alloc : int -> 'poll <doc>Allocate memory to perform polling on a given number of sockets</doc> **/ static value socket_poll_alloc( value nsocks ) { polldata *p; int i; val_check(nsocks,int); p = (polldata*)alloc(sizeof(polldata)); p->max = val_int(nsocks); if( p->max < 0 || p->max > 1000000 ) neko_error(); # ifdef NEKO_WINDOWS { p->fdr = (fd_set*)alloc_private(FDSIZE(p->max)); p->fdw = (fd_set*)alloc_private(FDSIZE(p->max)); p->outr = (fd_set*)alloc_private(FDSIZE(p->max)); p->outw = (fd_set*)alloc_private(FDSIZE(p->max)); p->fdr->fd_count = 0; p->fdw->fd_count = 0; } # else p->fds = (struct pollfd*)alloc_private(sizeof(struct pollfd) * p->max); p->rcount = 0; p->wcount = 0; # endif p->ridx = alloc_array(p->max+1); p->widx = alloc_array(p->max+1); for(i=0;i<=p->max;i++) { val_array_ptr(p->ridx)[i] = alloc_int(-1); val_array_ptr(p->widx)[i] = alloc_int(-1); } return alloc_abstract(k_poll, p); }
value hx_zmq_construct (value io_threads) { if (!val_is_int(io_threads)) return alloc_null(); int _io_threads = val_int(io_threads); if (_io_threads <= 0) { val_throw(alloc_int(EINVAL)); return alloc_null(); } void *c = zmq_init (_io_threads); int err = zmq_errno(); if (c == NULL) { val_throw (alloc_int(err)); return alloc_null(); } // See: http://nekovm.org/doc/ffi#abstracts_and_kinds value v = alloc_abstract(k_zmq_context_handle,c); val_gc(v,finalize_context); // finalize_context is called when the abstract value is garbage collected return v; }
/** module_read_path : string list -> name:string -> loader:object -> 'module <doc> Read a module using the specified search path. </doc> **/ static value module_read_path( value path, value name, value loader ) { FILE *f; value fname; char *mname, *ext; neko_module *m; val_check(name,string); val_check(loader,object); mname = val_string(name); ext = strrchr(mname,'.'); if( ext && ext[1] == 'n' && ext[2] == 0 ) fname = neko_select_file(path,mname,""); else fname = neko_select_file(path,mname,".n"); f = fopen(val_string(fname),"rb"); if( f == NULL ) { buffer b = alloc_buffer("Module not found : "); buffer_append(b,mname); bfailure(b); } m = neko_read_module(neko_file_reader,f,loader); fclose(f); if( m == NULL ) { buffer b = alloc_buffer("Invalid module : "); val_buffer(b,name); bfailure(b); } m->name = alloc_string(val_string(name)); return alloc_abstract(neko_kind_module,m); }
value lime_cffi_set_finalizer (value callback) { value abstract = alloc_abstract (k_finalizer, callback); val_gc (abstract, lime_cffi_finalizer); return abstract; }
/** connect : { host => string, port => int, user => string, pass => string, socket => string? } -> 'connection <doc>Connect to a database using the connection informations</doc> **/ static value connect_mysql( value params ) { value host, port, user, pass, socket; val_check(params,object); host = val_field(params,val_id("host")); port = val_field(params,val_id("port")); user = val_field(params,val_id("user")); pass = val_field(params,val_id("pass")); socket = val_field(params,val_id("socket")); val_check(host,string); val_check(port,int); val_check(user,string); val_check(pass,string); if( !val_is_string(socket) && !val_is_null(socket) ) neko_error(); { connection *c = (connection*)alloc(sizeof(connection)); value v; c->m = mysql_init(NULL); c->conv_string = NULL; c->conv_date = NULL; c->conv_bytes = NULL; if( mysql_real_connect(c->m,val_string(host),val_string(user),val_string(pass),NULL,val_int(port),val_is_null(socket)?NULL:val_string(socket),0) == NULL ) { buffer b = alloc_buffer("Failed to connect to mysql server : "); buffer_append(b,mysql_error(c->m)); mysql_close(c->m); bfailure(b); } v = alloc_abstract(k_connection,c); val_gc(v,free_connection); return v; } }
static value socket_poll_alloc( value nsocks ) { polldata *p; int i; val_check(nsocks,int); p = (polldata*)malloc(sizeof(polldata)); p->max = val_int(nsocks); if( p->max < 0 || p->max > 1000000 ) return alloc_null(); # ifdef NEKO_WINDOWS { p->fdr = (fd_set*)malloc(FDSIZE(p->max)); p->fdw = (fd_set*)malloc(FDSIZE(p->max)); p->outr = (fd_set*)malloc(FDSIZE(p->max)); p->outw = (fd_set*)malloc(FDSIZE(p->max)); p->fdr->fd_count = 0; p->fdw->fd_count = 0; } # else p->fds = (struct pollfd*)malloc(sizeof(struct pollfd) * p->max); p->rcount = 0; p->wcount = 0; # endif p->ridx = alloc_array(p->max+1); p->widx = alloc_array(p->max+1); val_gc_add_root(&p->ridx); val_gc_add_root(&p->widx); for(i=0;i<=p->max;i++) { val_array_set_i(p->ridx,i, alloc_int(-1)); val_array_set_i(p->widx,i, alloc_int(-1)); } value v = alloc_abstract(k_poll, p); val_gc(v,free_sock); return v; }
/** Connect out from a server socket. Returns an ENetPeer *, which has not yet connected, or throws if connection fails. **/ static value udpr_connect_out(value h, value ip, value port, value channels, value timeout) { ENetAddress address; ENetEvent event; ENetHost *host; ENetPeer *peer; int to; val_check_kind(h,k_udprhost); // checked in address population //val_check(ip,int); //val_check(port,int); val_check(channels,int); val_check(timeout,int); to = val_int(timeout); if(to < 0) to = 5000; host = (ENetHost *)val_data(h); if(populate_address(&address, ip, port) != val_true) val_throw(alloc_string("address")); //neko_error(); // Initiate the connection with channels 0..channels-1 peer = enet_host_connect (host, &address, (size_t)val_int(channels)); if (peer == NULL) //val_throw( alloc_string("Host not found") ); neko_error(); value v = alloc_abstract(k_udprpeer,peer); return v; }
/** * Create a temporary file which will be destroyed automatically when it is closed * @return value file handle **/ static value fileext_tmpfile_open() { fio* f = new fio(); if( !f->open_tmpfile() ) fileext_error("Unable to create temporary file", f, true); value v = alloc_abstract(k_file_ext,f); val_gc(v, fileext_free_file); return v; }
static value udpr_get_peer_pointer(value h, value idx) { val_check_kind(h,k_udprhost); val_check(idx,int); ENetPeerHandle hndPeer = (ENetPeerHandle)val_int(idx); ENetPeer *peer = enet_host_handle_to_peer((ENetHost *)val_data(h), (ENetPeerHandle)val_int(idx)); if(peer == NULL) neko_error(); value v = alloc_abstract(k_udprpeer,peer); return v; }
static value ssl_get_peer_certificate( value ssl ){ value v; const mbedtls_x509_crt *crt; val_check_kind(ssl,k_ssl); crt = mbedtls_ssl_get_peer_cert(val_ssl(ssl)); if( crt == NULL ) return val_null; v = alloc_abstract( k_cert, (void *)crt ); return v; }
/** request : 'db -> sql:string -> 'result <doc>Executes the SQL request and returns its result</doc> **/ static value request( value v, value sql ) { database *db; result *r; const char *tl; int i,j; val_check_kind(v,k_db); val_check(sql,string); db = val_db(v); r = (result*)alloc(sizeof(result)); r->db = db; if( sqlite3_prepare(db->db,val_string(sql),val_strlen(sql),&r->r,&tl) != SQLITE_OK ) { buffer b = alloc_buffer("Sqlite error in "); val_buffer(b,sql); buffer_append(b," : "); buffer_append(b,sqlite3_errmsg(db->db)); val_throw(buffer_to_string(b)); } if( *tl ) { sqlite3_finalize(r->r); val_throw(alloc_string("Cannot execute several SQL requests at the same time")); } r->ncols = sqlite3_column_count(r->r); r->names = (field*)alloc_private(sizeof(field)*r->ncols); r->bools = (int*)alloc_private(sizeof(int)*r->ncols); r->first = 1; r->done = 0; for(i=0;i<r->ncols;i++) { field id = val_id(sqlite3_column_name(r->r,i)); const char *dtype = sqlite3_column_decltype(r->r,i); for(j=0;j<i;j++) if( r->names[j] == id ) { if( strcmp(sqlite3_column_name(r->r,i),sqlite3_column_name(r->r,j)) == 0 ) { buffer b = alloc_buffer("Error, same field is two times in the request "); val_buffer(b,sql); sqlite3_finalize(r->r); val_throw(buffer_to_string(b)); } else { buffer b = alloc_buffer("Error, same field ids for : "); buffer_append(b,sqlite3_column_name(r->r,i)); buffer_append(b," and "); buffer_append(b,sqlite3_column_name(r->r,j)); buffer_append_char(b,'.'); sqlite3_finalize(r->r); val_throw(buffer_to_string(b)); } } r->names[i] = id; r->bools[i] = dtype?(strcmp(dtype,"BOOL") == 0):0; } // changes in an update/delete if( db->last != NULL ) finalize_result(val_result(db->last),0); db->last = alloc_abstract(k_result,r); return db->last; }
static value os_winlog_new( value title, value f ) { window *w; val_check(title,string); val_check_function(f,0); w = (window*)alloc(sizeof(window)); w->click = f; w->p = sys_winlog_new(val_string(title),wnd_callback,w); if( w->p == NULL ) neko_error(); return alloc_abstract(k_winlog,w); }
value hxfcgi_create_request() { try { hxfcgi::Request *req = new hxfcgi::Request(); value ret = alloc_abstract(hxRequest,req); return ret; } catch (string error) { hx_failure(error.c_str()); } return val_null; }
/* @description Returns a new pixel wand. */ value nMagick_pixel_new() { value v; PixelWand *pix; pix = NewPixelWand(); v = alloc_abstract( k_pixel, pix ); val_gc( v, nMagick_pixel_close ); return v; }
/** regexp_new_options : reg:string -> options:string -> 'regexp <doc>Build a new regexpr with the following options : <ul> <li>i : case insensitive matching</li> <li>s : . match anything including newlines</li> <li>m : treat the input as a multiline string</li> <li>u : run in utf8 mode</li> <li>g : turn off greedy behavior</li> </ul> </doc> **/ static value regexp_new_options( value s, value opt ) { val_check(s,string); val_check(opt,string); { value v; const char *error; int err_offset; pcre *p; pcredata *pdata; const char *o = val_string(opt); int options = 0; while( *o ) { switch( *o++ ) { case 'i': options |= PCRE_CASELESS; break; case 's': options |= PCRE_DOTALL; break; case 'm': options |= PCRE_MULTILINE; break; case 'u': options |= PCRE_UTF8; break; case 'g': options |= PCRE_UNGREEDY; break; default: return alloc_null(); break; } } p = pcre_compile(val_string(s),options,&error,&err_offset,NULL); if( p == NULL ) { buffer b = alloc_buffer("Regexp compilation error : "); buffer_append(b,error); buffer_append(b," in "); val_buffer(b,s); bfailure(b); } v = alloc_abstract(k_regexp,malloc(sizeof(pcredata))); pdata = PCRE(v); pdata->r = p; pdata->str = alloc_null(); val_gc_add_root(&pdata->str); pdata->nmatchs = 0; pcre_fullinfo(p,NULL,PCRE_INFO_CAPTURECOUNT,&pdata->nmatchs); pdata->nmatchs++; pdata->matchs = (int*)malloc(sizeof(int) * 3 * pdata->nmatchs); val_gc(v,free_regexp); return v; } }
static value cert_get_next( value cert ){ mbedtls_x509_crt *crt; value v; val_check_kind(cert,k_cert); crt = (mbedtls_x509_crt *)val_cert(cert); crt = crt->next; if( crt == NULL ) return val_null; v = alloc_abstract(k_cert, crt); return v; }
/* @description Returns a new pixel wand. */ value nMagick_draw_new() { value v; DrawingWand *draw; draw = NewDrawingWand(); v = alloc_abstract( k_draw, draw ); val_gc( v, nMagick_draw_close ); return v; }
/** file_open : f:string -> r:string -> 'file <doc> Call the C function [fopen] with the file path and access rights. Return the opened file or throw an exception if the file couldn't be open. </doc> **/ static value file_open( value name, value r ) { fio *f; val_check(name,string); val_check(r,string); f = (fio*)alloc(sizeof(fio)); f->name = alloc_string(val_string(name)); f->io = fopen(val_string(name),val_string(r)); if( f->io == NULL ) file_error("file_open",f); return alloc_abstract(k_file,f); }
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); }
/** * Open a file * @param name File name including path * @param mode File mode (r, rw, w etc) * @return value file handle **/ static value fileext_open(value name, value mode) { val_check(name, string); val_check(mode, string); fio* f = new fio(); if(!f->open(name, mode)) fileext_error("Unable to open file", f, true); value v = alloc_abstract(k_file_ext,f); val_gc(v, fileext_free_file); return v; }
static value ssl_new( value config ) { int ret; mbedtls_ssl_context *ssl; val_check_kind(config,k_ssl_conf); ssl = (mbedtls_ssl_context *)alloc(sizeof(mbedtls_ssl_context)); mbedtls_ssl_init(ssl); if( (ret = mbedtls_ssl_setup(ssl, val_conf(config))) != 0 ){ mbedtls_ssl_free(ssl); return ssl_error(ret); } return alloc_abstract( k_ssl, ssl ); }
/** tls_create : void -> 'tls <doc> Creates thread local storage. This is placeholder that can store a value that will be different depending on the local thread. You must set the tls value to [null] before exiting the thread or the memory will never be collected. </doc> **/ static value tls_create() { value v; vtls *t = (vtls*)malloc(sizeof(vtls)); # ifdef NEKO_WINDOWS t->tls = TlsAlloc(); TlsSetValue(t->tls,NULL); # else pthread_key_create(&t->key,NULL); # endif v = alloc_abstract(k_tls,t); val_gc(v,free_tls); return v; }
/* @description Returns an identical copy of the DrawingWand. */ value nMagick_draw_clone( value draw ) { value v; DrawingWand *drw; val_check_kind( draw, k_draw ); drw = DRAW( draw ); v = alloc_abstract( k_draw, CloneDrawingWand( drw ) ); val_gc( v, nMagick_draw_close ); return v; }
/** 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); }
/** module_read_string : string -> loader:object -> 'module <doc> Read a module using the specified string datas. </doc> **/ static value module_read_string( value str, value loader ) { neko_module *m; string_pos p; val_check(str,string); val_check(loader,object); p.p = val_string(str); p.len = val_strlen(str); m = neko_read_module(neko_string_reader,&p,loader); if( m == NULL ) neko_error(); m->name = alloc_string(""); return alloc_abstract(neko_kind_module,m); }
/** Returns the ENetPeer that generated an event, with the Event allocated pointer in Peer->data. The returned ENetPeer must not be destroyed, since it's a copy of an existing peer pointer. Timeout is float number of seconds (0.001 == 1 ms) **/ static value udpr_poll(value h, value timeout) { //ENetPeerHandle hndPeer = enet_host_peer_to_handle(host, event->peer); ENetEvent *event; int res; if( !val_is_abstract(h) || !val_is_kind(h,k_udprhost) ) neko_error(); val_check(timeout,number); enet_uint32 tout = (enet_uint32)(val_number(timeout)*1000); event = (ENetEvent *) enet_malloc (sizeof (ENetEvent)); // Wait up to timeout milliseconds for an event. res = enet_host_service ((ENetHost *)val_data(h), event, tout); if(res <= 0) { if(res == 0) return val_null; neko_error(); } switch (event->type) { case ENET_EVENT_TYPE_NONE: //if(event->peer != NULL) //free_peer_event(event->peer); enet_free(event); return val_null; break; default: // auto frees any existing unhandled event, add this event. #ifdef ENET_DEBUG_FULL if(event->type == ENET_EVENT_TYPE_RECEIVE) fprintf(stderr, "udpr_poll: event type %s %0.*s\n", event_to_string(event->type), event->packet->dataLength, event->packet->data); else fprintf(stderr, "udpr_poll: event type %s\n", event_to_string(event->type)); #endif break; } value v = alloc_abstract(k_udprevent,event); val_gc(v, destroy_enetevent); return v; #ifdef ENET_DEBUG //fprintf(stderr, "udpr_poll: returning peer %x\n", event->peer); #endif //value v = alloc_abstract(k_udprpeer, event->peer); //return v; }
/** Returns an ENetPeer *, or throw if connection fails. **/ static value udpr_connect(value h, value ip, value port, value channels, value timeout) { ENetAddress address; ENetEvent event; ENetHost *host; ENetPeer *peer; int to; if( !val_is_abstract(h) || !val_is_kind(h,k_udprhost) ) neko_error(); // checked in address population //val_check(ip,int); //val_check(port,int); val_check(channels,int); val_check(timeout,int); to = val_int(timeout); if(to < 0) to = 5000; host = (ENetHost *)val_data(h); if(populate_address(&address, ip, port) != val_true) neko_error(); // Initiate the connection with channels 0..channels-1 peer = enet_host_connect (host, &address, (size_t)val_int(channels)); if (peer == NULL) neko_error(); #ifdef ENET_DEBUG fprintf(stderr, "udpr_connect: waiting %d\n", to); #endif /* Wait up to 5 seconds for the connection attempt to succeed. */ if (enet_host_service (host, & event, to) > 0 && event.type == ENET_EVENT_TYPE_CONNECT) { // success #ifdef ENET_DEBUG fprintf(stderr, "udpr_connect: returning peer %x\n", peer); #endif value v = alloc_abstract(k_udprpeer,peer); //val_gc(v, destroy_enetpeer); return v; } // timeout has occurred or disconnect received. #ifdef ENET_DEBUG fprintf(stderr, "udpr_connect: *** enet_peer_reset\n"); #endif enet_peer_reset (peer); neko_error(); }
static value cert_load_path(value path){ int r; mbedtls_x509_crt *x; value v; val_check(path,string); x = (mbedtls_x509_crt *)alloc(sizeof(mbedtls_x509_crt)); mbedtls_x509_crt_init( x ); if( (r = mbedtls_x509_crt_parse_path(x, val_string(path))) != 0 ){ return ssl_error(r); } v = alloc_abstract(k_cert, x); val_gc(v,free_cert); return v; }