Example #1
0
int Upload_notify(Connection *conn, Handler *handler, const char *stage, bstring tmp_name)
{
    bstring key = bformat("x-mongrel2-upload-%s", stage);
    Request_set(conn->req, key, bstrcpy(tmp_name), 1);

    return Connection_send_to_handler(conn, handler, "", 0, NULL);
}
Example #2
0
int connection_http_to_handler(Connection *conn)
{
    int content_len = Request_content_length(conn->req);
    int rc = 0;
    char *body = NULL;

    Handler *handler = Request_get_action(conn->req, handler);
    error_unless(handler, conn, 404, "No action for request: %s", bdata(Request_path(conn->req)));

    // we don't need the header anymore, so commit the buffer and deal with the body
    IOBuf_read_commit(conn->iob, Request_header_length(conn->req));

    if(content_len == 0) {
        body = "";
        rc = Connection_send_to_handler(conn, handler, body, content_len);
        check_debug(rc == 0, "Failed to deliver to the handler.");
    } else if(content_len > MAX_CONTENT_LENGTH) {
        rc = Upload_file(conn, handler, content_len);
        check(rc == 0, "Failed to upload file.");
    } else {
        if(content_len > conn->iob->len) {
            // temporarily grow the buffer
            IOBuf_resize(conn->iob, content_len);
        }

        debug("READ ALL CALLED with content_len: %d, and MAX_CONTENT_LENGTH: %d", content_len, MAX_CONTENT_LENGTH);

        body = IOBuf_read_all(conn->iob, content_len, CLIENT_READ_RETRIES);
        check(body != NULL, "Client closed the connection during upload.");

        rc = Connection_send_to_handler(conn, handler, body, content_len);
        check_debug(rc == 0, "Failed to deliver to the handler.");
    }

    Log_request(conn, 200, content_len);

    return REQ_SENT;

error:
    return CLOSE;
}
Example #3
0
int Connection_read_wspacket(Connection *conn)
{
    bstring payload=NULL;

    uint8_t *dataU=NULL;
    char *data = IOBuf_start(conn->iob);
    int avail = IOBuf_avail(conn->iob);
    int64_t packet_length=-1;
    int smaller_packet_length;
    int header_length;
    char key[4];
    int i;
    int data_length;
    int tries = 0;
    int rc=0;
    int fin;
    int inprogFlags=0;
    int isControl;
    int flags;

again:
    dataU=NULL;
    data = IOBuf_start(conn->iob);
    avail = IOBuf_avail(conn->iob);
    packet_length=-1;
    smaller_packet_length=0;
    header_length=0;
    i=0;
    data_length=0;
    tries = 0;
    rc=0;
    fin=0;

    for(tries = 0; packet_length == -1 && tries < 8*CLIENT_READ_RETRIES; tries++) {
        if(avail > 0) {
            packet_length = Websocket_packet_length((uint8_t *)data, avail);
        }

        if(packet_length == -1) {
            data = IOBuf_read_some(conn->iob, &avail);
            check_debug(!IOBuf_closed(conn->iob), "Client closed during read.");
        }
    }
    check(packet_length > 0,"Error receiving websocket packet header.")

    check_debug(packet_length <= INT_MAX,"Websocket packet longer than MAXINT.");
    /* TODO properly terminate WS connection */

    smaller_packet_length = (int)packet_length;
    
    /* TODO check for maximum length */

    header_length=Websocket_header_length((uint8_t *) data, avail);
    data_length=smaller_packet_length-header_length;
    dataU = (uint8_t *)IOBuf_read_all(conn->iob,header_length,8*CLIENT_READ_RETRIES);
    memcpy(key,dataU+header_length-4,4);

    flags=dataU[0];
    if (payload==NULL) {
        inprogFlags=flags;
    }
    

    fin=(WS_fin(dataU));
    isControl=(WS_is_control(dataU));

{
    const char *error=WS_validate_packet(dataU,payload!=NULL);
    check(error==NULL,"%s",error);
}

    dataU = (uint8_t *)IOBuf_read_all(conn->iob,data_length, 8*CLIENT_READ_RETRIES);
    check(dataU != NULL, "Client closed the connection during websocket packet.");

    for(i=0;i<data_length;++i) {
        dataU[i]^=key[i%4];
    }

    if(isControl) /* Control frames get sent right-away */
    {
            Request_set(conn->req,bfromcstr("FLAGS"),bformat("0x%X",flags|0x80),1);
            rc = Connection_send_to_handler(conn, conn->handler, (void *)dataU,data_length);
            check_debug(rc == 0, "Failed to deliver to the handler.");
    }
    else {
        if(fin) {
            Request_set(conn->req,bfromcstr("FLAGS"),bformat("0x%X",inprogFlags|0x80),1);
        }
        if (payload == NULL) {
            if (fin) {
                rc = Connection_send_to_handler(conn, conn->handler, (void *)dataU,data_length);
                check_debug(rc == 0, "Failed to deliver to the handler.");
            }
            else {
                payload = blk2bstr(dataU,data_length);
                check(payload != NULL,"Allocation failed");
            }
        } else {
            check(BSTR_OK == bcatblk(payload,dataU,data_length), "Concatenation failed");
            if (fin) {
                rc = Connection_send_to_handler(conn, conn->handler, bdata(payload),blength(payload));
                check_debug(rc == 0, "Failed to deliver to the handler.");
                bdestroy(payload);
                payload=NULL;
            }
        }
    }
    if (payload != NULL) {
        goto again;
    }


    return packet_length;

error:
    bdestroy(payload);
    return -1;

}
Example #4
0
int connection_http_to_handler(Connection *conn)
{
    int content_len = Request_content_length(conn->req);
    int rc = 0;
    char *body = NULL;

    Handler *handler = Request_get_action(conn->req, handler);
    error_unless(handler, conn, 404, "No action for request: %s", bdata(Request_path(conn->req)));

    bstring expects = Request_get(conn->req, &HTTP_EXPECT);

    if (expects != NULL) {
        if (biseqcstr(expects, "100-continue")) {
            Response_send_status(conn, &HTTP_100);
        } else {
            Response_send_status(conn, &HTTP_417);
            log_info("Client requested unsupported expectation: %s.", bdata(expects));
            goto error;
        }
    }

    // we don't need the header anymore, so commit the buffer and deal with the body
    check(IOBuf_read_commit(conn->iob, Request_header_length(conn->req)) != -1, "Finaly commit failed streaming the connection to http handlers.");

    if(is_websocket(conn)) {
        bstring wsKey = Request_get(conn->req, &WS_SEC_WS_KEY);
        bstring response= websocket_challenge(wsKey);
        conn->handler = handler;

        //Response_send_status(conn,response);
        bdestroy(conn->req->request_method);
        conn->req->request_method=bfromcstr("WEBSOCKET_HANDSHAKE");
        Connection_send_to_handler(conn, handler, bdata(response), blength(response));
        bdestroy(response);

        bdestroy(conn->req->request_method);
        conn->req->request_method=bfromcstr("WEBSOCKET");
        return REQ_SENT;
    }

    if(content_len == 0) {
        body = "";
        rc = Connection_send_to_handler(conn, handler, body, content_len);
        check_debug(rc == 0, "Failed to deliver to the handler.");
    } else if(content_len > MAX_CONTENT_LENGTH) {
        rc = Upload_file(conn, handler, content_len);
        check(rc == 0, "Failed to upload file.");
    } else {
        debug("READ ALL CALLED with content_len: %d, and MAX_CONTENT_LENGTH: %d", content_len, MAX_CONTENT_LENGTH);

        body = IOBuf_read_all(conn->iob, content_len, CLIENT_READ_RETRIES);
        check(body != NULL, "Client closed the connection during upload.");

        rc = Connection_send_to_handler(conn, handler, body, content_len);
        check_debug(rc == 0, "Failed to deliver to the handler.");
    }

    Log_request(conn, 200, content_len);

    return REQ_SENT;

error:
    return CLOSE;
}
Example #5
0
int Upload_stream(Connection *conn, Handler *handler, int content_len)
{
    char *data = NULL;
    int avail = 0;
    int offset = 0;
    int first_chunk = 1;
    int rc;
    hash_t *altheaders = NULL;
    bstring offsetstr;

    debug("max content length: %d, content_len: %d", MAX_CONTENT_LENGTH, content_len);

    IOBuf_resize(conn->iob, MAX_CONTENT_LENGTH); // give us a good buffer size

    while(content_len > 0) {
        if(first_chunk) {
            // read whatever's there
            data = IOBuf_read_some(conn->iob, &avail);
        } else if(conn->sendCredits > 0) {
            // read up to credits
            data = IOBuf_read(conn->iob, conn->sendCredits < content_len ? conn->sendCredits : content_len, &avail);
            conn->sendCredits -= avail;
        } else {
            // sleep until we have credits
            tasksleep(&conn->uploadRendez);
            continue;
        }

        check(!IOBuf_closed(conn->iob), "Closed while reading from IOBuf.");
        content_len -= avail;

        offsetstr = bformat("%d", offset);

        if(first_chunk) {
            Request_set(conn->req, &UPLOAD_STREAM, offsetstr, 1);
            if(content_len == 0) {
                Request_set(conn->req, &UPLOAD_STREAM_DONE, bfromcstr("1"), 1);
            }
        } else {
            altheaders = hash_create(2, (hash_comp_t)bstrcmp, bstr_hash_fun);
            add_to_hash(altheaders, &UPLOAD_STREAM, offsetstr);
            if(content_len == 0) {
                add_to_hash(altheaders, &UPLOAD_STREAM_DONE, bfromcstr("1"));
            }
        }

        rc = Connection_send_to_handler(conn, handler, data, avail, altheaders);
        check_debug(rc == 0, "Failed to deliver to the handler.");

        if(altheaders != NULL) {
            hash_free_nodes(altheaders);
            hash_destroy(altheaders);
            altheaders = NULL;
        }

        check(IOBuf_read_commit(conn->iob, avail) != -1, "Commit failed while streaming.");

        first_chunk = 0;
        offset += avail;
    }

    check(content_len == 0, "Failed to write everything to the large upload tmpfile.");

    return 0;

error:
    return -1;
}