Пример #1
0
static int _openTcpClient( UThread* ut, struct sockaddr* addr,
                           socklen_t addrlen )
{
    SOCKET fd;
#ifdef __APPLE__
    int yes = 1;
#endif

    fd = socket( AF_INET, SOCK_STREAM, 0 );
    if( INVALID(fd) )
    {
        ur_error( ut, UR_ERR_ACCESS, "socket %s", SOCKET_ERR );
        return -1;
    }

#ifdef __APPLE__
    if( setsockopt( fd, SOL_SOCKET, SO_NOSIGPIPE, &yes, sizeof(int) ) != 0 )
    {
        closesocket( fd );
        ur_error( ut, UR_ERR_ACCESS, "setsockopt %s", SOCKET_ERR );
        return -1;
    }
#endif

    if( connect( fd, addr, addrlen ) < 0 )
    {
        closesocket( fd );
        ur_error( ut, UR_ERR_ACCESS, "connect %s", SOCKET_ERR );
        return -1;
    }

    return fd;
}
Пример #2
0
static int printInfoLog( UThread* ut, GLuint obj, int prog )
{
    GLint infologLength;
    GLint charsWritten;
    char* infoLog;

    if( prog )
        glGetProgramiv( obj, GL_INFO_LOG_LENGTH, &infologLength );
    else
        glGetShaderiv( obj, GL_INFO_LOG_LENGTH, &infologLength );

    if( infologLength > 0 )
    {
        infoLog = (char*) malloc( infologLength );

        if( prog )
            glGetProgramInfoLog( obj, infologLength, &charsWritten, infoLog );
        else
            glGetShaderInfoLog( obj, infologLength, &charsWritten, infoLog );

        //fprintf( stderr, "%s\n", infoLog );
        ur_error( ut, UR_ERR_SCRIPT, infoLog );

        free( infoLog );
    }
    else
    {
        ur_error( ut, UR_ERR_SCRIPT, prog ? "glLinkProgram failed"
                                          : "glCompileShader failed" );
    }
    return UR_THROW;
}
Пример #3
0
/*
   \param ext  If non-zero, then bind socket to ext->addr.
*/
static int _openUdpSocket( UThread* ut, SocketExt* ext, int nowait )
{
    SOCKET fd;

    fd = socket( AF_INET, SOCK_DGRAM, 0 );
    if( INVALID(fd) )
    {
        ur_error( ut, UR_ERR_ACCESS, "socket %s", SOCKET_ERR );
        return -1;
    }

    if( nowait )
    {
#ifdef _WIN32
        u_long flags = 1;
        ioctlsocket( fd, FIONBIO, &flags );
#else
        fcntl( fd, F_SETFL, fcntl( fd, F_GETFL, 0 ) | O_NONBLOCK );
#endif
    }

    if( ext )
    {
        if( bind( fd, &ext->addr, ext->addrlen ) < 0 )
        {
            closesocket( fd );
            ur_error( ut, UR_ERR_ACCESS, "bind %s", SOCKET_ERR );
            return -1;
        }
    }

    return fd;
}
Пример #4
0
static const UBuffer* _execBuf( UThread* ut, const UCell* cell, int fd )
{
    static const char* name[3] = { "input", "output", "error" };
    const UBuffer* buf;

    if( fd == 0 )
        buf = ur_bufferSer(cell);
    else if( ! (buf = ur_bufferSerM(cell)) )
        return 0;

    if( buf->type == UT_BINARY )
    {
        return buf;
    }
    else if( buf->type == UT_STRING )
    {
        if( ! ur_strIsUcs2(buf) )
            return buf;
        ur_error( ut, UR_ERR_TYPE, "execute does not handle UCS2 strings" );
    }
    else
    {
        ur_error( ut, UR_ERR_TYPE, "execute expected binary!/string! for %s",
                  name[fd] );
    }
    return 0;
}
Пример #5
0
static int thread_open( UThread* ut, const UPortDevice* pdev,
                        const UCell* from, int opt, UCell* res )
{
    UBuffer* port;
    ThreadExt* ext;
    (void) from;
    (void) opt;

    ext = (ThreadExt*) memAlloc( sizeof(ThreadExt) );
    if( ! ext )
        return ur_error( ut, UR_ERR_INTERNAL, "Could not alloc thread port" );

    if( ! _initThreadQueue( &ext->A ) )
    {
fail:
        memFree( ext );
        return ur_error( ut, UR_ERR_INTERNAL, "Could not create thread queue" );
    }

    if( ! _initThreadQueue( &ext->B ) )
    {
        mutexFree( ext->A.mutex );
        goto fail;
    }

    ext->A.END_OPEN = 0;
    ext->B.END_OPEN = 1;

    port = boron_makePort( ut, pdev, ext, res );
    port->SIDE = SIDE_A;
    return UR_OK;
}
Пример #6
0
/*
  "tcp://host:port"
  "tcp://:port"
  "udp://host:port"
  "udp://:port"
*/
static int socket_open( UThread* ut, const UPortDevice* pdev,
                        const UCell* from, int opt, UCell* res )
{
    NodeServ ns;
    SocketExt* ext;
    int socket;
    int nowait = opt & UR_PORT_NOWAIT;
    //int port = 0;
    //int hostPort = 0;
    //UCell* initAddr = 0;


    if( ! ur_is(from, UT_STRING) )
        return ur_error( ut, UR_ERR_TYPE, "socket open expected string" );

    ext = (SocketExt*) memAlloc( sizeof(SocketExt) );
    ext->addrlen = 0;
#ifdef _WIN32
    ext->event = WSA_INVALID_EVENT;
#endif

    //if( ur_is(from, UT_STRING) )
    {
        stringToNodeServ( ut, from, &ns );
        if( ! makeSockAddr( ut, ext, &ns ) )
            goto fail;
    }
#if 0
    else if( ur_is(from, UT_BLOCK) )
Пример #7
0
static int thread_seek( UThread* ut, UBuffer* port, UCell* pos, int where )
{
    (void) port;
    (void) pos;
    (void) where;
    return ur_error( ut, UR_ERR_SCRIPT, "Cannot seek on thread port" );
}
Пример #8
0
static int makeSockAddr( UThread* ut, SocketExt* ext, const NodeServ* ns )
{
    struct addrinfo hints;
    struct addrinfo* res;
    int err;

    memset( &hints, 0, sizeof(hints) );
    hints.ai_family   = AF_INET;  // AF_UNSPEC
    hints.ai_socktype = ns->socktype;
    if( ! ns->node )
        hints.ai_flags = AI_PASSIVE;

    err = getaddrinfo( ns->node, ns->service, &hints, &res );
    if( err )
    {
        return ur_error( ut, UR_ERR_SCRIPT, "getaddrinfo (%s)",
                         gai_strerror( err ) );
    }

    memcpy( &ext->addr, res->ai_addr, res->ai_addrlen );
    ext->addrlen = res->ai_addrlen;

    freeaddrinfo( res );
    return UR_OK;
}
Пример #9
0
static int _execSpawn( UThread* ut, char* cmd, UCell* res )
{
    STARTUPINFO si;
    PROCESS_INFORMATION pi;

    ZeroMemory( &si, sizeof(si) );
    si.cb = sizeof(si);

    ZeroMemory( &pi, sizeof(pi) );

    // Start the child process. 
    if( ! CreateProcess( NULL,   // No module name (use command line). 
        TEXT(cmd),        // Command line. 
        NULL,             // Process handle not inheritable. 
        NULL,             // Thread handle not inheritable. 
        FALSE,            // Set handle inheritance to FALSE. 
        0,                // No creation flags. 
        NULL,             // Use parent's environment block. 
        NULL,             // Use parent's starting directory. 
        &si,              // Pointer to STARTUPINFO structure.
        &pi )             // Pointer to PROCESS_INFORMATION structure.
    )
    {
        return ur_error( ut, UR_ERR_INTERNAL,
                         "CreateProcess failed (%d).\n", GetLastError() );
    }

    // Close process and thread handles. 
    CloseHandle( pi.hProcess );
    CloseHandle( pi.hThread );

    ur_setId(res, UT_INT);
    ur_int(res) = pi.dwProcessId;
    return UR_OK;
}
Пример #10
0
/*
    line-edit word!/string! <max-chars>
*/
static GWidget* ledit_make( UThread* ut, UBlockIter* bi,
                            const GWidgetClass* wclass )
{
    LineEdit* ep;
    const UCell* arg[2];
    int maxChars = 32;

    if( ! gui_parseArgs( ut, bi, wclass, ledit_args, arg ) )
        return 0;

    if( ur_isShared( arg[0]->series.buf ) )
    {
        ur_error( ut, UR_ERR_SCRIPT, "line-edit cannot modify shared string" );
        return 0;
    }

    if( arg[1] )
        maxChars = ur_int(arg[1]);

    ep = (LineEdit*) gui_allocWidget( sizeof(LineEdit), wclass );
    ep->wid.flags |= CHANGED;

    //ep->state = LEDIT_STATE_DISPLAY;
    ep->strN     = arg[0]->series.buf;
    ep->maxChars = maxChars;
    ep->vboN     = ledit_vbo( ut, maxChars );

    return (GWidget*) ep;
}
Пример #11
0
static int ssl_write( UThread* ut, UBuffer* port, const UCell* data )
{
    const void* buf;
    SSLExt* ext = ur_ptr(SSLExt, port);
    int len;
    int n;

    len = boron_sliceMem( ut, data, &buf );

    if( port->FD > -1 && len )
    {
retry:
        n = mbedtls_ssl_write( &ext->sc, buf, len );
        if( n < 0 )
        {
            if( n == MBEDTLS_ERR_SSL_WANT_READ ||
                    n == MBEDTLS_ERR_SSL_WANT_WRITE )
            {
                ssl_wait();
                goto retry;
            }

            // An error occured; the ssl context must not be used again.
            ssl_free( ext );
            port->FD = -1;

            return ur_error( ut, UR_ERR_ACCESS, "ssl_write %d", n );
        }
        else if( n != len )
        {
            if( n > 0 && n < len )
            {
                buf = ((const char*) buf) + n;
                len -= n;
                goto retry;
            }
            return ur_error( ut, UR_ERR_ACCESS,
                             "ssl_write only sent %d of %d bytes", n, len );
        }
    }
    return UR_OK;
}
Пример #12
0
static int thread_read( UThread* ut, UBuffer* port, UCell* dest, int part )
{
    UBuffer tbuf;
    ThreadExt* ext = (ThreadExt*) port->ptr.v;
    ThreadQueue* queue;
    (void) part;

    tbuf.type = 0;

    queue = (port->SIDE == SIDE_A) ? &ext->B : &ext->A;

    if( ! queue->readIt )
        readEvent( queue );     // Waits until data is available.

    mutexLock( queue->mutex );
    while( queue->readIt >= queue->buf.used )
    {
        if( condWaitF( queue->cond, queue->mutex ) )
        {
            mutexUnlock( queue->mutex );
            goto waitError;
        }
    }
    queue->readIt = thread_dequeue( &queue->buf, queue->readIt, dest, &tbuf );
    mutexUnlock( queue->mutex );

    if( tbuf.type )
    {
        UIndex bufN;

        dest->series.buf = UR_INVALID_BUF;
        ur_genBuffers( ut, 1, &bufN );
        dest->series.buf = bufN;

        memCpy( ur_buffer( bufN ), &tbuf, sizeof(UBuffer) );
    }
    else
    {
        int type = ur_type(dest);
        if( ur_isWordType(type) )
        {
            if( ur_binding(dest) == UR_BIND_THREAD )
                ur_unbind(dest);
        }
    }

    return UR_OK;

waitError:

    return ur_error( ut, UR_ERR_INTERNAL, "thread_read condWait failed" );
}
Пример #13
0
static SocketExt* _socketPort( UThread* ut, UCell* cell, const char* funcName )
{
    SocketExt* ext;
    UBuffer* pbuf = ur_buffer( cell->series.buf );
    if( (pbuf->form == UR_PORT_EXT) && pbuf->ptr.v )
    {
        ext = ur_ptr(SocketExt, pbuf);
        if( ext->dev == &port_socket )
            return ext;
    }
    ur_error( ut, UR_ERR_SCRIPT, "%s expected socket port", funcName );
    return 0;
}
Пример #14
0
/*
  Return UR_OK/UR_THROW.
*/
int ur_makeDir( UThread* ut, const char* path )
{
    if( ! CreateDirectory( path, NULL ) )
    {
        DWORD err;
        err = GetLastError();
        if( (err != ERROR_FILE_EXISTS) || (_isDir(path) != 1) )
        {
            ur_error( ut, UR_ERR_ACCESS, "CreateDirectory error (%d)", err );
            return UR_THROW;
        }
    }
    return UR_OK;
}
Пример #15
0
static int thread_write( UThread* ut, UBuffer* port, const UCell* data )
{
    UBuffer* buf;
    ThreadExt* ext = (ThreadExt*) port->ptr.v;
    ThreadQueue* queue;
    int type = ur_type(data);

    if( ur_isSeriesType(type) && ! ur_isShared( data->series.buf ) )
    {
        buf = ur_bufferSerM( data );
        if( ! buf )
            return UR_THROW;

        if( ur_isBlockType(type) )
        {
            UCell* it  = buf->ptr.cell;
            UCell* end = it + buf->used;
            while( it != end )
            {
                type = ur_type(it);
                if( ur_isWordType(type) )
                {
                    if( ur_binding(it) == UR_BIND_THREAD )
                        ur_unbind(it);
                }
                else if( ur_isSeriesType(type) )
                {
                    return ur_error( ut, UR_ERR_INTERNAL,
                        "Cannot write block containing series to thread port" );
                }
                ++it;
            }
        }
    }
    else
        buf = 0;

    queue = (port->SIDE == SIDE_A) ? &ext->A : &ext->B;

    mutexLock( queue->mutex );
    if( queue->END_OPEN )
    {
        thread_queue( &queue->buf, data, buf );
        condSignal( queue->cond );
        writeEvent( queue );
    }
    mutexUnlock( queue->mutex );

    return UR_OK;
}
Пример #16
0
static int _openTcpServer( UThread* ut, struct sockaddr* addr,
                           socklen_t addrlen, int backlog )
{
    SOCKET fd;
    int yes = 1;

    fd = socket( AF_INET, SOCK_STREAM, 0 );
    if( INVALID(fd) )
    {
        ur_error( ut, UR_ERR_ACCESS, "socket %s", SOCKET_ERR );
        return -1;
    }

    if( setsockopt( fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int) ) != 0 )
    {
        closesocket( fd );
        ur_error( ut, UR_ERR_ACCESS, "setsockopt %s", SOCKET_ERR );
        return -1;
    }

    if( bind( fd, addr, addrlen ) != 0 )
    {
        closesocket( fd );
        ur_error( ut, UR_ERR_ACCESS, "bind %s", SOCKET_ERR );
        return -1;
    }

    if( listen( fd, backlog ) != 0 )
    {
        closesocket( fd );
        ur_error( ut, UR_ERR_ACCESS, "listen %s", SOCKET_ERR );
        return -1;
    }

    return fd;
}
Пример #17
0
static int ssl_read( UThread* ut, UBuffer* port, UCell* dest, int len )
{
    SSLExt* ext = ur_ptr(SSLExt, port);
    UBuffer* buf = ur_buffer( dest->series.buf );
    int n;

    if( port->FD > -1 && len )
    {
retry:
        n = mbedtls_ssl_read( &ext->sc, buf->ptr.b + buf->used, len );
        //printf( "KR ssl_read %d\n", n );
        if( n > 0 )
        {
            buf->used += n;
        }
        else if( n < 0 )
        {
            if( n == MBEDTLS_ERR_SSL_WANT_READ ||
                    n == MBEDTLS_ERR_SSL_WANT_WRITE )
            {
                ssl_wait();
                goto retry;
            }

            // An error occured; the ssl context must not be used again.
            ssl_free( ext );
            port->FD = -1;

            return ur_error( ut, UR_ERR_ACCESS, "ssl_read %d", n );
        }
        else
        {
            ur_setId(dest, UT_NONE);
        }
    }
    return UR_OK;
}
Пример #18
0
static GWidget* itemview_make( UThread* ut, UBlockIter* bi,
                               const GWidgetClass* wclass )
{
    GItemView* ep;
    UIndex itemBlkN;
    const UCell* arg[3];
    //int ok;

    if( ! gui_parseArgs( ut, bi, wclass, itemview_args, arg ) )
        return 0;

    ep = (GItemView*) gui_allocWidget( sizeof(GItemView), wclass );

    assert( sizeof(GLint) == sizeof(GLsizei) );
    ur_arrInit( ep->fc + 0, sizeof(GLint), 0 );
    ur_arrInit( ep->fc + 1, sizeof(GLint), 0 );

    glGenBuffers( 2, ep->vbo );
    ep->vboSize[0] = ep->vboSize[1] = 0;

    ep->use_color  = -1;
    ep->selCol     = -1;
    ep->selRow     = -1;
    ep->itemCount  = 0;
    ep->itemWidth  = 0;
    ep->itemHeight = 0;
    ep->scrollY    = 0;
    ep->modVbo     = 0;
    ep->updateMethod = IV_UPDATE_2;
    ep->layoutBlkN   = UR_INVALID_BUF;
    ep->selectBgBlkN = UR_INVALID_BUF;
    ep->bindCtxN     = UR_INVALID_BUF;
    ep->actionBlkN   = UR_INVALID_BUF;

    itemBlkN = arg[0]->series.buf;
    if( ur_isShared( itemBlkN ) )
        ep->dataBlkN = UR_INVALID_BUF;
    else
        ep->dataBlkN = itemBlkN;

    // Optional action block.
    if( arg[2] )
        ep->actionBlkN = arg[2]->series.buf;

    //--------------------------------------------
    // Parse layout block   [size coord!  item block!  selected block!]

    {
    UBlockIterM bi;
    UBuffer* ctx;

    if( ur_blkSliceM( ut, &bi, arg[1] ) != UR_OK )
        goto fail;
    if( (bi.end - bi.it) < 3 )
        goto bad_layout;

    ctx = gui_styleContext( ut );
    if( ctx )
        ur_bind( ut, bi.buf, ctx, UR_BIND_THREAD );

    if( ur_is(bi.it, UT_COORD) )
    {
        // Fixed layout.
        static char itemStr[] = "item";
        UBuffer* blk;

        if( ! ur_is(bi.it + 1, UT_BLOCK) || ! ur_is(bi.it + 2, UT_BLOCK) )
            goto bad_layout;

        ep->itemWidth  = bi.it->coord.n[0];
        ep->itemHeight = bi.it->coord.n[1];
        //printf( "KR item dim %d,%d\n", ep->itemWidth, ep->itemHeight );
        ++bi.it;

        ep->layoutBlkN = bi.it->series.buf;

        ep->bindCtxN = ur_makeContext( ut, 1 );     // gc!
        ctx = ur_buffer( ep->bindCtxN );
        ur_ctxAppendWord( ctx, ur_intern( ut, itemStr, 4 ) );

        if( ! (blk = ur_bufferSerM( bi.it )) )
            goto fail;
        ur_bind( ut, blk, ctx, UR_BIND_THREAD );
        ++bi.it;

        ep->selectBgBlkN = bi.it->series.buf;
    }
#ifdef ITEMVIEW_BOX_LAYOUT
    else
    {
        // Automatic layout.
        glEnv.guiParsingItemView = 1;
        ok = gui_makeWidgets( ut, arg[1], &ep->wid, 0 );
        glEnv.guiParsingItemView = 0;
        if( ! ok )
            goto fail;
        //ep->wid.child->flags |= GW_HIDDEN;
    }
#endif
    }

    return (GWidget*) ep;

bad_layout:

    ur_error( ut, UR_ERR_SCRIPT, "Invalid item-view layout" );

fail:

    itemview_free( (GWidget*) ep );
    return 0;
}
Пример #19
0
/*
  Updates DrawContext attr & drawCount.

  Return UR_OK/UR_THROW.
*/
int itemview_parse( DrawContext* dc, UThread* ut, UBlockIter* bi, GWidget* wp )
{
    const UCell* arg[3];
    UAtom atom;
    int opcode;
    float x, y;

    while( bi->it != bi->end )
    {
        if( ur_is(bi->it, UT_WORD) )
        {
            atom = ur_atom( bi->it );
            opcode = ur_atomsSearch( glEnv.drawOpTable, DOP_COUNT, atom );
            switch( opcode )
            {
                case DOP_IMAGE:
                {
                    QuadDim qd;
                    int16_t rect[4];
                    const int16_t* coord;
                    FETCH_ARGS( iv_args_image );
                    //printf( "KR IV image\n" );
                    coord = arg[0]->coord.n;
                    rect[0] = coord[0] + dc->penX;
                    rect[1] = coord[1] + dc->penY;
                    rect[2] = coord[2];
                    rect[3] = coord[3];
                    quad_init( &qd, rect, arg[1]->coord.n, arg[2]->coord.n );
                    quad_emitVT( &qd, dc->attr, dc->attr + 3, AttrCount );
                    vbo_setVec3( dc->attr + 5, AttrCount, 6, dc->color );
                    dc->attr      += 6 * AttrCount;
                    dc->drawCount += 6;
                }
                    break;

                case DOP_COLOR:
                    FETCH_ARGS( iv_args_color );
                    dc->color[0] = (GLfloat) ur_int( arg[0] );
                    break;

                case DOP_FONT:
                    FETCH_ARGS( iv_args_font );
                    dc->fontN = ur_fontTF( arg[0] );
                    break;

                case DOP_TEXT:
                    FETCH_ARGS( iv_args_text );

                    x = dc->penX + (float) arg[0]->coord.n[0];
                    y = dc->penY + (float) arg[0]->coord.n[1];

                {
                    DrawTextState dts;
                    UBinaryIter si;
                    int glyphCount;

                    //printf( "KR IV text\n" );
                    dp_toString( ut, arg[1], &si );
                    vbo_drawTextInit( &dts,
                                      (TexFont*) ur_buffer( dc->fontN )->ptr.v,
                                      x, y );
                    dts.emitTris = 1;
                    glyphCount = vbo_drawText( &dts, dc->attr + 3, dc->attr,
                                               AttrCount, si.it, si.end );
                    glyphCount *= 6;
                    vbo_setVec3( dc->attr + 5, AttrCount, glyphCount,
                                 dc->color );
                    /*
                    while( si.it != si.end )
                        putchar( *si.it++ );
                    putchar( '\n' );
                    */
                    dc->attr      += glyphCount * AttrCount;
                    dc->drawCount += glyphCount;
                }
                    break;

                default:
                    goto invalid_op;
            }
        }
        else
        {
            goto invalid_op;
        }
    }
    return UR_OK;

invalid_op:

    return ur_error( ut, UR_ERR_SCRIPT, "Invalid item-view instruction" );
}
Пример #20
0
/*
  Returns zero if matching rule not found or exception occured.
*/
static const UCell* _parseBin( UThread* ut, BinaryParser* pe,
                               const UCell* rit, const UCell* rend,
                               UIndex* spos )
{
    const UCell* set = 0;
    const UCell* tval;
    uint32_t bitCount;
    uint32_t field;
    UBuffer* ibin  = ur_buffer( pe->inputBufN );
    uint8_t* in    = ibin->ptr.b + *spos;
    uint8_t* inEnd = ibin->ptr.b + pe->inputEnd;


match:

    while( rit != rend )
    {
        switch( ur_type(rit) )
        {
            case UT_INT:
                bitCount = ur_int(rit);
                if( bitCount < 1 || bitCount > 32 )
                {
                    ur_error( PARSE_ERR, "bit-field size must be 1 to 32" );
                    goto parse_err;
                }
                if( bitCount > 24 )
                {
                    uint32_t high;
                    in = pullBits( pe, bitCount - 16, in, inEnd, &high );
                    if( ! in )
                        goto failed;
                    in = pullBits( pe, 16, in, inEnd, &field );
                    if( ! in )
                        goto failed;
                    field |= high << 16;
                }
                else
                {
                    in = pullBits( pe, bitCount, in, inEnd, &field );
                    if( ! in )
                        goto failed;
                }
                goto set_field;

            case UT_WORD:
                switch( ur_atom(rit) )
                {
                case UR_ATOM_U8:
                    if( in == inEnd )
                        goto failed;
                    field = *in++;
                    goto set_field;

                case UR_ATOM_U16:
                    if( (inEnd - in) < 2 )
                        goto failed;
                    if( pe->bigEndian )
                        field = (in[0] << 8) | in[1];
                    else
                        field = (in[1] << 8) | in[0];
                    in += 2;
                    goto set_field;

                case UR_ATOM_U32:
                    if( (inEnd - in) < 4 )
                        goto failed;
                    if( pe->bigEndian )
                        field = (in[0] << 24) | (in[1] << 16) |
                                (in[2] <<  8) |  in[3];
                    else
                        field = (in[3] << 24) | (in[2] << 16) |
                                (in[1] <<  8) |  in[0];
                    in += 4;
                    goto set_field;

                case UR_ATOM_SKIP:
                    ++rit;
                    ++in;
                    break;
#if 0
                case UR_ATOM_MARK:
                    break;

                case UR_ATOM_PLACE:
                    ++rit;
                    if( (rit != rend) && ur_is(rit, UT_WORD) )
                    {
                        tval = ur_wordCell( ut, rit++ );
                        CHECK_WORD(tval);
                        if( ur_is(tval, UT_BINARY) )
                        {
                            pos = tval->series.it;
                            break;
                        }
                    }
                    ur_error( PARSE_ERR, "place expected series word" );
                    goto parse_err;
#endif
                case UR_ATOM_COPY:      // copy  dest   size
                                        //       word!  int!/word!
                    ++rit;
                    if( (rit != rend) && ur_is(rit, UT_WORD) )
                    {
                        UCell* res = ur_wordCellM( ut, rit );
                        CHECK_WORD(res);
                        if( ++rit != rend )
                        {
                            tval = rit++;
                            if( ur_is(tval, UT_WORD) )
                            {
                                tval = ur_wordCell( ut, tval );
                                CHECK_WORD(tval);
                            }
                            if( ur_is(tval, UT_INT) )
                            {
                                UBuffer* cb;
                                int size = ur_int(tval);
                                cb = ur_makeBinaryCell( ut, size, res );
                                cb->used = size;
                                memCpy( cb->ptr.b, in, size );
                                in += size;
                                break;
                            }
                        }
                        ur_error( PARSE_ERR, "copy expected int! count" );
                        goto parse_err;
                    }
                    ur_error( PARSE_ERR, "copy expected word! destination" );
                    goto parse_err;

                case UR_ATOM_BIG_ENDIAN:
                    ++rit;
                    pe->bigEndian = 1;
                    break;

                case UR_ATOM_LITTLE_ENDIAN:
                    ++rit;
                    pe->bigEndian = 0;
                    break;

                default:
                    tval = ur_wordCell( ut, rit );
                    CHECK_WORD(tval);

                    if( ur_is(tval, UT_CHAR) )
                        goto match_char;
                    else if( ur_is(tval, UT_STRING) )
                        goto match_string;
                    else if( ur_is(tval, UT_BLOCK) )
                        goto match_block;
                    /*
                    else if( ur_is(tval, UT_BITSET) )
                        goto match_bitset;
                    */
                    else
                    {
                        ur_error( PARSE_ERR,
                                "parse expected char!/string!/block!" );
                        goto parse_err;
                    }
                    break;
                }
                break;

            case UT_SETWORD:
                set = rit++;
                while( (rit != rend) && ur_is(rit, UT_SETWORD) )
                    ++rit;
                break;
#if 0
            case UT_GETWORD:
                break;

            case UT_INT:
                repMin = ur_int(rit);

                ++rit;
                if( rit == rend )
                    return 0;

                if( ur_is(rit, UT_INT) )
                {
                    repMax = ur_int(rit);
                    ++rit;
                }
                else
                {
                    repMax = repMin;
                }
                goto repeat;
#endif
            case UT_CHAR:
match_char:
                if( *in != ur_int(rit) )
                    goto failed;
                ++in;
                ++rit;
                break;

            case UT_BLOCK:
                tval = rit;
match_block:
            {
                UBlockIter bi;
                UIndex pos = in - ibin->ptr.b;
                UIndex rblkN = tval->series.buf;
                ur_blkSlice( ut, &bi, tval );
                tval = _parseBin( ut, pe, bi.it, bi.end, &pos );
                ibin = ur_buffer( pe->inputBufN );
                if( ! tval )
                {
                    if( pe->exception == PARSE_EX_ERROR )
                    {
                        ur_appendTrace( ut, rblkN, 0 );
                        return 0;
                    }
                    if( pe->exception == PARSE_EX_BREAK )
                        pe->exception = PARSE_EX_NONE;
                    else
                        goto failed;
                }
                in    = ibin->ptr.b + pos;
                inEnd = ibin->ptr.b + pe->inputEnd;
                ++rit;
            }
                break;

            case UT_PAREN:
            {
                UIndex pos = in - ibin->ptr.b;

                if( UR_OK != pe->eval( ut, rit ) )
                    goto parse_err;

                /* Re-acquire pointer & check if input modified. */
                ibin = ur_buffer( pe->inputBufN );
                if( pe->sliced )
                {
                    // We have no way to track changes to the end of a slice,
                    // so just make sure we remain in valid memery.
                    if( ibin->used < pe->inputEnd )
                        pe->inputEnd = ibin->used;
                }
                else
                {
                    // Not sliced, track input end.
                    if( ibin->used != pe->inputEnd )
                        pe->inputEnd = ibin->used;
                }
                in    = ibin->ptr.b + pos;
                inEnd = ibin->ptr.b + pe->inputEnd;
                ++rit;
            }
                break;

            case UT_STRING:
                tval = rit;
match_string:
            {
                UBinaryIter bi;
                int size;

                ur_binSlice( ut, &bi, tval );
                if( ur_strIsUcs2(bi.buf) )
                    goto bad_enc;
                size = bi.end - bi.it;
                if( size > (inEnd - in) )
                    goto failed;
                if( match_pattern_8(in, inEnd, bi.it, bi.end) == bi.end )
                {
                    in += size;
                    ++rit;
                }
                else
                    goto failed;
            }
                break;
#if 0
            case UT_BITSET:
                tval = rit;
match_bitset:
            if( pos >= pe->inputEnd )
                goto failed;
            {
                const UBuffer* bin = ur_bufferSer( tval );
                int c = istr->ptr.c[ pos ];
                if( bitIsSet( bin->ptr.b, c ) )
                {
                    ++rit;
                    ++pos;
                }
                else
                    goto failed;
            }
                break;
#endif
            default:
                ur_error( PARSE_ERR, "invalid parse value" );
                             //orDatatypeName( ur_type(rit) ) );
                goto parse_err;
        }
    }

//complete:

    *spos = in - ibin->ptr.b;
    return rit;

set_field:

    if( set )
    {
        UCell* val;
        while( set != rit )
        {
            val = ur_wordCellM( ut, set++ );
            CHECK_WORD(val);
            ur_setId(val, UT_INT);
            ur_int(val) = field;
        }
        set = 0;
    }
    ++rit;
    goto match;

failed:

    *spos = in - ibin->ptr.b;
    return 0;

bad_enc:

    ur_error( ut, UR_ERR_INTERNAL,
              "parse binary does not handle UCS2 strings" );
    //goto parse_err;

parse_err:

    pe->exception = PARSE_EX_ERROR;
    return 0;
}
Пример #21
0
/*
  "tcps://host:port"
  "tcps://:port"
  "udps://host:port"
  "udps://:port"
*/
static int ssl_open( UThread* ut, const UPortDevice* pdev,
                     const UCell* from, int opt, UCell* res )
{
    NodeServ ns;
    SSLExt* ext;
    int ok;
    //int nowait = opt & UR_PORT_NOWAIT;
    mbedtls_net_context* nc;
    mbedtls_ssl_context* sc;
    mbedtls_ssl_config* conf;
    const char* pers = "ssl_client1";
    (void) opt;


    if( ! ur_is(from, UT_STRING) )
        return ur_error( ut, UR_ERR_TYPE, "socket open expected string" );

    ext = (SSLExt*) memAlloc( sizeof(SSLExt) );
    ext->se.addrlen = 0;
#ifdef _WIN32
    ext->se.event = WSA_INVALID_EVENT;
#endif

    //if( ur_is(from, UT_STRING) )
    {
        stringToNodeServ( ut, from, &ns );
        if( ! makeSockAddr( ut, &ext->se, &ns ) )
            goto fail;
    }

    if( ! ns.service )
    {
        ur_error( ut, UR_ERR_SCRIPT,
                  "Socket port requires hostname and/or port" );
        goto fail;
    }

    if( ! boron_requestAccess( ut, "Open socket %s", ns.service ) )
        goto fail;

    ssl_init( ext );
    nc   = &ext->nc;
    sc   = &ext->sc;
    conf = &ext->conf;

    ok = mbedtls_ctr_drbg_seed( &ext->ctr_drbg, mbedtls_entropy_func,
                                &ext->entropy,
                                (const unsigned char*) pers, strlen(pers) );
    if( ok != 0 )
    {
        ssl_error( ut, "mbedtls_ctr_drbg_seed", ok );
        goto failSSL;
    }

    ok = mbedtls_net_connect( nc, ns.node, ns.service,
                              (ns.socktype == SOCK_DGRAM)
                              ? MBEDTLS_NET_PROTO_UDP
                              : MBEDTLS_NET_PROTO_TCP );
    if( ok != 0 )
    {
        ssl_error( ut, "mbedtls_net_connect", ok );
        goto failSSL;
    }

    ok = mbedtls_ssl_config_defaults( conf, MBEDTLS_SSL_IS_CLIENT,
                                      (ns.socktype == SOCK_DGRAM) ? MBEDTLS_SSL_TRANSPORT_DATAGRAM
                                      : MBEDTLS_SSL_TRANSPORT_STREAM,
                                      MBEDTLS_SSL_PRESET_DEFAULT );
    if( ok != 0 )
    {
        ssl_error( ut, "mbedtls_ssl_config_defaults", ok );
        goto failSSL;
    }

    mbedtls_ssl_conf_authmode( conf, MBEDTLS_SSL_VERIFY_NONE );
    //mbedtls_ssl_conf_ca_chain( conf, cacert, NULL );
    mbedtls_ssl_conf_rng( conf, mbedtls_ctr_drbg_random, &ext->ctr_drbg );
    mbedtls_ssl_conf_dbg( conf, ssl_debug, stdout );

    ok = mbedtls_ssl_setup( sc, conf );
    if( ok != 0 )
    {
        ssl_error( ut, "mbedtls_ssl_setup", ok );
        goto failSSL;
    }

    ok = mbedtls_ssl_set_hostname( sc, "Boron TLS Server 1" );
    if( ok != 0 )
    {
        ssl_error( ut, "mbedtls_ssl_set_hostname", ok );
        goto failSSL;
    }

    mbedtls_ssl_set_bio( sc, nc, mbedtls_net_send, mbedtls_net_recv, NULL );

    while( (ok = mbedtls_ssl_handshake( sc )) != 0 )
    {
        if( ok != MBEDTLS_ERR_SSL_WANT_READ &&
                ok != MBEDTLS_ERR_SSL_WANT_WRITE )
        {
            ssl_error( ut, "mbedtls_ssl_handshake", ok );
            goto failSSL;
        }
    }

    {
        UBuffer* pbuf;

        pbuf = boron_makePort( ut, pdev, ext, res );
        pbuf->TCP = (ns.socktype == SOCK_STREAM) ? 1 : 0;
        pbuf->FD  = nc->fd;
        //printf( "KR socket_open %d %d\n", pbuf->FD, pbuf->TCP );
    }
    return UR_OK;

failSSL:

    ssl_free( ext );

fail:

    memFree( ext );
    return UR_THROW;
}
Пример #22
0
static int ssl_error( UThread* ut, const char* func, int err )
{
    return ur_error( ut, UR_ERR_INTERNAL, "%s: -0x%d", func, -err );
}
Пример #23
0
/*
  Recursively evaluate math expression.

  \param cell   Cell to evaluate.
  \param res    Result.

  \return UR_OK or UR_THROW.
*/
int calc_eval( UThread* ut, UCell* cell, double* res )
{
    switch( ur_type(cell) )
    {
    case UT_WORD:
    {
        const UCell* val = ur_wordCell( ut, cell );
        if( ! val )
            return UR_THROW;
        if( ur_is(val, UT_DECIMAL) )
            *res = ur_decimal(val);
        else if( ur_is(val, UT_INT) || ur_is(val, UT_CHAR) )
            *res = (double) ur_int(val);
        else
        {
            return ur_error( ut, UR_ERR_SCRIPT, "Invalid word '%s",
                             ur_wordCStr( cell ) );
        }
    }
    break;

    case UT_DECIMAL:
        *res = ur_decimal(cell);
        break;

    case UT_INT:
    case UT_CHAR:
        *res = (double) ur_int(cell);
        break;

    case UT_BLOCK:
    case UT_PAREN:
    {
        UBlockIterM bi;
        double num = 0.0;
        double right;

#define RIGHT_VAL \
if( ++bi.it == bi.end ) \
    return ur_error( ut, UR_ERR_SCRIPT, "Expected operator r-value" ); \
if( ! calc_eval( ut, bi.it, &right ) ) \
    return UR_THROW;

        if( ! ur_blkSliceM( ut, &bi, cell ) )
            return UR_THROW;
        ur_foreach( bi )
        {
            if( ur_is(bi.it, UT_WORD) )
            {
                switch( ur_atom(bi.it) )
                {
                case UR_ATOM_PLUS:
                    RIGHT_VAL
                    num += right;
                    break;

                case UR_ATOM_MINUS:
                    RIGHT_VAL
                    num -= right;
                    break;

                case UR_ATOM_ASTERISK:
                    RIGHT_VAL
                    num *= right;
                    break;

                case UR_ATOM_SLASH:
                    RIGHT_VAL
                    num /= right;
                    break;

                default:
                    if( ! calc_eval( ut, bi.it, &num ) )
                        return UR_THROW;
                }
            }
            else if( ur_is(bi.it, UT_SETWORD) )
            {
                cell = ur_wordCellM( ut, bi.it );
                if( ! cell )
                    return UR_THROW;
                ur_setId( cell, UT_DECIMAL );
                ur_decimal(cell) = num;
            }
            else
            {
                if( ! calc_eval( ut, bi.it, &num ) )
                    return UR_THROW;
            }
        }
        *res = num;
    }
    break;

    default:
        *res = 0.0;
        break;
    }
    return UR_OK;
}
Пример #24
0
static int _execIO( UThread* ut, char* cmd, UCell* res,
                    const UBuffer* in, UBuffer* out, UBuffer* err )
{
    HANDLE childStdInR;
    HANDLE childStdInW;
    HANDLE childStdOutR;
    HANDLE childStdOutW;
    HANDLE childStdErrR;
    HANDLE childStdErrW;
    SECURITY_ATTRIBUTES sec;
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    DWORD flags = 0;


    sec.nLength              = sizeof(SECURITY_ATTRIBUTES); 
    sec.lpSecurityDescriptor = NULL;
    sec.bInheritHandle       = TRUE; 

    childStdOutR = childStdErrR = INVALID_HANDLE_VALUE;

    if( in )
    {
        if( ! CreatePipe( &childStdInR, &childStdInW, &sec, 0 ) ) 
        {
fail0:
            return ur_error( ut, UR_ERR_INTERNAL, "CreatePipe failed\n" );
        }
        // Child does not inherit our end of pipe.
        SetHandleInformation( childStdInW, HANDLE_FLAG_INHERIT, 0 );
    }

    if( out )
    {
        if( ! CreatePipe( &childStdOutR, &childStdOutW, &sec, 0 ) ) 
        {
fail1:
            if( in )
                _closePipe( childStdInR, childStdInW );
            goto fail0;
        }
        // Child does not inherit our end of pipe.
        SetHandleInformation( childStdOutR, HANDLE_FLAG_INHERIT, 0 );
        flags = DETACHED_PROCESS;
    }

    if( err )
    {
        if( ! CreatePipe( &childStdErrR, &childStdErrW, &sec, 0 ) ) 
        {
            if( out )
                _closePipe( childStdOutR, childStdOutW );
            goto fail1;
        }
        // Child does not inherit our end of pipe.
        SetHandleInformation( childStdErrR, HANDLE_FLAG_INHERIT, 0 );
        flags = DETACHED_PROCESS;
    }

    ZeroMemory( &si, sizeof(si) );
    si.cb = sizeof(si);
    if( in || out || err )
    {
        si.hStdInput  = in  ? childStdInR  : NULL;
        si.hStdOutput = out ? childStdOutW : GetStdHandle( STD_OUTPUT_HANDLE );
        si.hStdError  = err ? childStdErrW : GetStdHandle( STD_ERROR_HANDLE );
        si.dwFlags    = STARTF_USESTDHANDLES;
    }

    ZeroMemory( &pi, sizeof(pi) );

    // Start the child process. 
    if( ! CreateProcess( NULL,   // No module name (use command line). 
        TEXT(cmd),        // Command line. 
        NULL,             // Process handle not inheritable. 
        NULL,             // Thread handle not inheritable. 
        TRUE,             // Handle inheritance. 
        flags,            // Creation flags.
        NULL,             // Use parent's environment block. 
        NULL,             // Use parent's starting directory. 
        &si,              // Pointer to STARTUPINFO structure.
        &pi )             // Pointer to PROCESS_INFORMATION structure.
    )
    {
        if( in )
            _closePipe( childStdInR, childStdInW );
        if( out )
            _closePipe( childStdOutR, childStdOutW );
        if( err )
            _closePipe( childStdErrR, childStdErrW );
        return ur_error( ut, UR_ERR_INTERNAL,
                         "CreateProcess failed (%d).\n", GetLastError() );
    }

    if( in )
    {
        DWORD nw;
        CloseHandle( childStdInR );
        WriteFile( childStdInW, in->ptr.v,
                   (in->type == UT_STRING) ? in->used * in->elemSize : in->used,
                   &nw, NULL );
        CloseHandle( childStdInW );
    }

    if( out || err )
    {
        if( out )
            CloseHandle( childStdOutW );
        if( err )
            CloseHandle( childStdErrW );
        _readPipes( childStdOutR, out, childStdErrR, err );
        if( out )
            CloseHandle( childStdOutR );
        if( err )
            CloseHandle( childStdErrR );
    }

    {
    DWORD code;

    // Wait until child process exits.
    WaitForSingleObject( pi.hProcess, INFINITE );

    if( GetExitCodeProcess( pi.hProcess, &code ) )
    {
        ur_setId(res, UT_INT);
        ur_int(res) = code;
    }
    else
    {
        ur_setId(res, UT_NONE);
    }
    }

    // Close process and thread handles. 
    CloseHandle( pi.hProcess );
    CloseHandle( pi.hThread );
    return UR_OK;
}