Esempio n. 1
0
/*  
    function sendBlock(content, options): Number
 */
static EjsNumber *ws_sendBlock(Ejs *ejs, EjsWebSocket *ws, int argc, EjsObj **argv)
{
    EjsByteArray    *ba;
    EjsAny          *content, *vp;
    ssize           nbytes;
    cchar           *str;
    int             last, mode, type, flags;

    assert(argc == 2);

    if (ws->conn->state < HTTP_STATE_PARSED && !waitForHttpState(ws, HTTP_STATE_PARSED, -1, 1)) {
        return ESV(null);
    }
    content = argv[0];
    last = ejsGetPropertyByName(ejs, argv[1], EN("last")) != ESV(false);
    if ((vp = ejsGetPropertyByName(ejs, argv[1], EN("mode"))) != 0) {
        mode = (int) ejsGetNumber(ejs, vp);
        if (mode != HTTP_BUFFER && mode != HTTP_BLOCK && mode != HTTP_NON_BLOCK) {
            ejsThrowArgError(ejs, "Bad message mode");
            return 0;
        }
    } else {
        mode = HTTP_BUFFER;
    }
    if ((vp = ejsGetPropertyByName(ejs, argv[1], EN("type"))) != 0) {
        type = (int) ejsGetNumber(ejs, vp);
        if (type != WS_MSG_CONT && type != WS_MSG_TEXT && type != WS_MSG_BINARY) {
            ejsThrowArgError(ejs, "Bad message type");
            return 0;
        }
    } else {
        type = WS_MSG_TEXT;
    }
    flags = mode;
    if (!last) {
        flags |= HTTP_MORE;
    }
    if (ejsIs(ejs, content, ByteArray)) {
        ba = (EjsByteArray*) content;
        nbytes = ejsGetByteArrayAvailableData(ba);
        nbytes = httpSendBlock(ws->conn, type, (cchar*) &ba->value[ba->readPosition], nbytes, flags);
    } else {
        str = ejsToMulti(ejs, content);
        nbytes = httpSendBlock(ws->conn, type, str, slen(str), flags);
    }
    if (nbytes < 0) {
        ejsThrowIOError(ejs, "Cannot send block");
        return 0;
    }
    return ejsCreateNumber(ejs, (MprNumber) nbytes);
}
Esempio n. 2
0
/*  
    function send(...content): Number
 */
static EjsNumber *ws_send(Ejs *ejs, EjsWebSocket *ws, int argc, EjsObj **argv)
{
    EjsArray        *args;
    EjsByteArray    *ba;
    EjsAny          *arg;
    ssize           nbytes;
    int             i;

    args = (EjsArray*) argv[0];
    if (ws->conn->state < HTTP_STATE_PARSED && !waitForHttpState(ws, HTTP_STATE_PARSED, -1, 1)) {
        return ESV(null);
    }
    nbytes = 0;
    for (i = 0; i < args->length; i++) {
        if ((arg = ejsGetProperty(ejs, args, i)) != 0) {
            if (ejsIs(ejs, arg, ByteArray)) {
                ba = (EjsByteArray*) arg;
                nbytes = ejsGetByteArrayAvailableData(ba);
                nbytes = httpSendBlock(ws->conn, WS_MSG_BINARY, (cchar*) &ba->value[ba->readPosition], nbytes, HTTP_BLOCK);
            } else {
                nbytes = httpSend(ws->conn, ejsToMulti(ejs, arg));
            }
            if (nbytes < 0) {
                return ESV(null);
            }
        }
    }
    return ejsCreateNumber(ejs, (MprNumber) nbytes);
}
Esempio n. 3
0
/*
    Send message to a connection
 */
static void chat(Msg *msg)
{
    HttpConn    *conn;
    HttpPacket  *packet;

    conn = msg->conn;
    packet = msg->packet;
    httpSendBlock(conn, packet->type, httpGetPacketStart(packet), httpGetPacketLength(packet), 0);
}
Esempio n. 4
0
/*
    Event callback. Invoked for incoming web socket messages and other events of interest.
    We're interested in the WRITABLE event.
 */
static void output_callback(HttpConn *conn, int event, int arg)
{
    Output      *output;
    ssize       len, wrote;
    int         flags, type;
    char        buf[MPR_BUFSIZE];

    /*
        Get a writable event when the socket can absorb more data
     */
    if (event == HTTP_EVENT_WRITABLE) {
        output = getData();
        do {
            if ((len = mprReadFile(output->file, buf, sizeof(buf))) > 0) {

                /*
                    Set the HTTP_MORE flag on every write except the last. This means each write is sent as
                    a separate frame. The first frame has the type of WS_MSG_TEXT, all others must be 
                    continuation frames.
                 */
                flags = HTTP_NON_BLOCK;
                if ((output->written + len) < output->info.size) {
                    flags |= HTTP_MORE;
                }
                type = output->written == 0 ? WS_MSG_TEXT : WS_MSG_CONT;
                /*
                    Send the next chunk as a WebSockets frame using a non-blocking write. 
                    This may return having written only a portion of the requested data.
                 */
                if ((wrote = httpSendBlock(conn, type, buf, len, flags)) < 0) {
                    httpError(conn, HTTP_CODE_INTERNAL_SERVER_ERROR, "Cannot send message of %d bytes", len);
                    return;
                }
                output->written += wrote;
                if (wrote < len) {
                    /* Reposition if the send returned having written less than requested */
                    mprSeekFile(output->file, SEEK_CUR, wrote - len);
                    break;
                }
            } else {
                httpSendClose(conn, WS_STATUS_OK, "OK");
                break;
            }
        } while (len > 0);

    } else if (event == HTTP_EVENT_APP_CLOSE) {
        mprLog(0, "output.c: close event. Status status %d, orderly closed %d, reason %s", arg,
        httpWebSocketOrderlyClosed(conn), httpGetWebSocketCloseReason(conn));

    } else if (event == HTTP_EVENT_ERROR) {
        mprLog(0, "output.c: error event");
    }
}
Esempio n. 5
0
/*
    Event callback. Invoked for incoming web socket messages and other events of interest.
 */
static void echo_callback(HttpConn *conn, int event, int arg)
{
    HttpPacket      *packet;

    if (event == HTTP_EVENT_READABLE) {
        /*
            Grab the packet off the read queue.
         */
        packet = httpGetPacket(conn->readq);
        if (packet->type == WS_MSG_TEXT || packet->type == WS_MSG_BINARY) {
            /*
                Echo back the contents
             */
            httpSendBlock(conn, packet->type, httpGetPacketStart(packet), httpGetPacketLength(packet), 0);
        }
    } else if (event == HTTP_EVENT_APP_CLOSE) {
        mprLog("info echo", 0, "close event. Status status %d, orderly closed %d, reason %s", arg,
        httpWebSocketOrderlyClosed(conn), httpGetWebSocketCloseReason(conn));

    } else if (event == HTTP_EVENT_ERROR) {
        mprLog("info echo", 0, "error event");
    }
}