Example #1
0
/*
 *   create from stack arguments
 */
vm_obj_id_t CVmObjAnonFn::create_from_stack(VMG_ const uchar **pc_ptr,
                                            uint argc)
{
    vm_obj_id_t id;
    vm_val_t funcptr;
    CVmObjAnonFn *new_obj;
    uint idx;
    
    /* at least one argument is required (the function pointer) */
    if (argc < 1)
        err_throw(VMERR_WRONG_NUM_OF_ARGS);

    /* retrieve our function pointer argument */
    G_stk->pop(&funcptr);
    if (funcptr.typ == VM_FUNCPTR)
    {
        /* it's a regular function pointer - accept it */
    }
    else if (funcptr.typ == VM_OBJ
             && vm_objp(vmg_ funcptr.val.obj)->get_invoker(vmg_ 0))
    {
        /* it's a pointer to an invokable object - accept it */
    }
    else
    {
        /* it's not a valid function pointer */
        err_throw(VMERR_FUNCPTR_VAL_REQD);
    }

    /* create the new object */
    id = vm_new_id(vmg_ FALSE, TRUE, FALSE);

    /* create the new object, giving it one slot per constructor argument */
    new_obj = new (vmg_ id) CVmObjAnonFn(vmg_ argc);

    /* set the first element to our function pointer */
    new_obj->set_element(0, &funcptr);

    /* set the remaining elements to the context objects */
    for (idx = 1 ; idx < argc ; ++idx)
    {
        vm_val_t val;
        
        /* pop this value */
        G_stk->pop(&val);

        /* set the element */
        new_obj->set_element(idx, &val);
    }

    /* return the new object ID */
    return id;
}
Example #2
0
/*
 *   create 
 */
vm_obj_id_t CVmObjFrameDesc::create(
    VMG_ vm_obj_id_t fref, int frame_idx, uint ret_ofs)
{
    /* allocate an object ID */
    vm_obj_id_t id = vm_new_id(vmg_ FALSE, TRUE, FALSE);

    /* instantiate the new object */
    new (vmg_ id) CVmObjFrameDesc(vmg_ fref, frame_idx, ret_ofs);

    /* return the new object's ID */
    return id;
}
Example #3
0
/*
 *   create 
 */
vm_obj_id_t CVmObjFrameRef::create(
    VMG_ vm_val_t *fp, const uchar *entry)
{
    /* allocate an object ID */
    vm_obj_id_t id = vm_new_id(vmg_ FALSE, TRUE, FALSE);

    /* instantiate the new object */
    new (vmg_ id) CVmObjFrameRef(vmg_ fp, entry);

    /* return the new object's ID */
    return id;
}
Example #4
0
/*
 *   create with a given dependency index 
 */
vm_obj_id_t CVmObjClass::create_dyn(VMG_ uint meta_idx)
{
    vm_obj_id_t id = vm_new_id(vmg_ FALSE, TRUE, FALSE);
    new (vmg_ id) CVmObjClass(vmg_ FALSE, meta_idx, id);
    return id;
}
Example #5
0
/* 
 *   create with no initial contents 
 */
vm_obj_id_t CVmObjClass::create(VMG_ int in_root_set)
{
    vm_obj_id_t id = vm_new_id(vmg_ in_root_set, TRUE, FALSE);
    new (vmg_ id) CVmObjClass();
    return id;
}
Example #6
0
/*
 *   create dynamically using stack arguments 
 */
vm_obj_id_t CVmObjHTTPServer::create_from_stack(
    VMG_ const uchar **pc_ptr, uint argc)
{
    vm_obj_id_t id;
    const char *errmsg;

    /* 
     *   parse arguments - new HTTPServer(addr?, port?) 
     */
    if (argc > 3)
        err_throw(VMERR_WRONG_NUM_OF_ARGS);

    /* check for the address - use "localhost" by default */
    char addr[256] = "localhost";
    if (argc >= 1)
    {
        /* get the address - this must be a string or nil */
        if (G_stk->get(0)->typ == VM_NIL)
            G_stk->discard();
        else
            CVmBif::pop_str_val_buf(vmg_ addr, sizeof(addr));
    }

    /* check for a port - use 0 by default */
    int port = 0;
    if (argc >= 2)
    {
        /* get the port number - this must be an integer or nil */
        if (G_stk->get(0)->typ == VM_NIL)
            G_stk->discard();
        else
            port = CVmBif::pop_int_val(vmg0_);
    }

    /* check for an upload size limit */
    int32_t ulim;
    if (argc >= 3)
    {
        if (G_stk->get(0)->typ == VM_NIL)
            G_stk->discard();
        else
            ulim = CVmBif::pop_long_val(vmg0_);
    }

    /* get the network safety level, to determine if this is allowed */
    int client_level, server_level;
    G_host_ifc->get_net_safety(&client_level, &server_level);

    /* check the network server safety level */
    switch (server_level)
    {
    case VM_NET_SAFETY_MINIMUM:
        /* all access allowed - proceed */
        break;

    case VM_NET_SAFETY_LOCALHOST:
        /* 
         *   localhost only - if the host isn't 'localhost' or '127.0.0.1',
         *   don't allow it 
         */
        if (stricmp(addr, "localhost") != 0
            && stricmp(addr, "127.0.0.1") != 0)
            goto access_error;

        /* allow it */
        break;

    case VM_NET_SAFETY_MAXIMUM:
    access_error:
        /* no access allowed */
        errmsg = "prohibited network access";
        G_interpreter->push_string(vmg_ errmsg);
        G_interpreter->throw_new_class(vmg_ G_predef->net_safety_exception,
                                       1, errmsg);
        AFTER_ERR_THROW(break;)
    }

    /* 
     *   allocate the object ID - this type of construction never creates a
     *   root object 
     */
    id = vm_new_id(vmg_ FALSE, FALSE, FALSE);

    /* http servers are inherently transient */
    G_obj_table->set_obj_transient(id);

    /* create the object */
    CVmObjHTTPServer *l = new (vmg_ id) CVmObjHTTPServer(vmg_ TRUE);

    /* get the extension */
    vm_httpsrv_ext *ext = l->get_ext();

    /* create the listener thread object */
    TadsHttpListenerThread *ht = new TadsHttpListenerThread(
        id, G_net_queue, ulim);

    /* launch the listener */
    ext->l = TadsListener::launch(addr, (ushort)port, ht);

    /* we're done with the thread object (the listener took it over) */
    ht->release_ref();

    /* if the launch failed, throw an error */
    if (ext->l == 0)
    {
        /* throw a network error */
        const char *errmsg = "Unable to start HTTP server";
        G_interpreter->push_string(vmg_ errmsg);
        G_interpreter->throw_new_class(vmg_ G_predef->net_exception, 1, errmsg);
    }

    /* remember my requested binding address */
    ext->addr = lib_copy_str(addr);

    /* return the new ID */
    return id;
}