Exemplo n.º 1
0
static int handler_process_control_request(Connection *conn, tns_value_t *data)
{
    tns_value_t *args = darray_get(data->value.list, 1);
    check(args->type==tns_tag_dict, "Invalid control response: not a dict.");

    hnode_t *n = hash_lookup(args->value.dict, &KEEP_ALIVE);
    if(n != NULL) {
        Register_ping(IOBuf_fd(conn->iob));
    }

    n = hash_lookup(args->value.dict, &CREDITS);
    if(n != NULL) {
        tns_value_t *credits = (tns_value_t *)hnode_get(n);
        conn->sendCredits += credits->value.number;
        taskwakeup(&conn->uploadRendez);
    }

    n = hash_lookup(args->value.dict, &CANCEL);
    if(n != NULL && !conn->closing) {
        Register_disconnect(IOBuf_fd(conn->iob));
        taskwakeup(&conn->uploadRendez);
    }

    tns_value_destroy(data);
    return 0;

error:
    return -1;
}
Exemplo n.º 2
0
int connection_msg_to_handler(Connection *conn)
{
    Handler *handler = Request_get_action(conn->req, handler);
    int rc = 0;
    int header_len = Request_header_length(conn->req);
    // body_len will include \0
    int body_len = Request_content_length(conn->req);

    check(handler, "JSON request doesn't match any handler: %s", 
            bdata(Request_path(conn->req)));

    if(pattern_match(IOBuf_start(conn->iob), header_len + body_len, bdata(&PING_PATTERN))) {
        Register_ping(IOBuf_fd(conn->iob));
    } else {
        check(body_len >= 0, "Parsing error, body length ended up being: %d", body_len);

        bstring payload = Request_to_payload(conn->req, handler->send_ident,
                IOBuf_fd(conn->iob), IOBuf_start(conn->iob) + header_len,
                body_len - 1);  // drop \0 on payloads


        rc = Handler_deliver(handler->send_socket, bdata(payload), blength(payload));
        bdestroy(payload);
    
        check(rc == 0, "Failed to deliver to handler: %s", bdata(Request_path(conn->req)));
    }

    // consumes \0 from body_len
    IOBuf_read_commit(conn->iob, header_len + body_len);

    return REQ_SENT;

error:
    return CLOSE;
}
Exemplo n.º 3
0
static inline int close_or_error(Connection *conn, int next)
{

    IOBuf_destroy(conn->proxy_iob);
    conn->proxy_iob = NULL;

    check_debug(Register_disconnect(IOBuf_fd(conn->iob)) != -1,
            "Register disconnect didn't work for %d", IOBuf_fd(conn->iob));

error:
    // fallthrough on purpose
    return next;
}
Exemplo n.º 4
0
Connection *Connection_create(Server *srv, int fd, int rport, 
                              const char *remote, SSL_CTX *ssl_ctx)
{
    Connection *conn = h_calloc(sizeof(Connection), 1);
    check_mem(conn);

    conn->server = srv;

    conn->rport = rport;
    memcpy(conn->remote, remote, IPADDR_SIZE);
    conn->remote[IPADDR_SIZE] = '\0';
    conn->type = 0;

    conn->req = Request_create();
    check_mem(conn->req);

    if(ssl_ctx != NULL) {
        conn->iob = IOBuf_create(BUFFER_SIZE, fd, IOBUF_SSL);
        check(conn->iob != NULL, "Failed to create the SSL IOBuf.");
        conn->iob->ssl = ssl_server_new(ssl_ctx, IOBuf_fd(conn->iob));
        check(conn->iob->ssl != NULL, "Failed to create new ssl for connection");
    } else {
        conn->iob = IOBuf_create(BUFFER_SIZE, fd, IOBUF_SOCKET);
    }

    return conn;

error:
    Connection_destroy(conn);
    return NULL;
}
Exemplo n.º 5
0
static ssize_t plain_stream_file(IOBuf *iob, int fd, off_t len)
{
    off_t sent = 0;
    off_t total = 0;
    off_t offset = 0;
    off_t block_size = MAX_SEND_BUFFER;
    int conn_fd = IOBuf_fd(iob);

    for(total = 0; fdwait(conn_fd, 'w') == 0 && total < len; total += sent) {

        block_size = (len - total) > block_size ? block_size : (len - total);
        sent = IOBuf_sendfile(conn_fd, fd, &offset, block_size);

        check(Register_write(iob->fd, sent) != -1, "Socket seems to be closed.");

        check_debug(sent > 0, "Client closed probably during sendfile on socket: %d from "
                    "file %d", conn_fd, fd);
    }
    
    check(total <= len,
            "Wrote way too much, wrote %d but size was %zd",
            (int)total, len);

    check(total == len,
            "Sent other than expected, sent: %d, but expected: %zd", 
            (int)total, len);

    return total;

error:
    return -1;
}
Exemplo n.º 6
0
void Connection_task(void *v)
{
    Connection *conn = (Connection *)v;
    int i = 0;
    int next = OPEN;

    State_init(&conn->state, &CONN_ACTIONS);

    while(1) {
        if(Filter_activated()) {
            next = Filter_run(next, conn);
            check(next >= CLOSE && next < EVENT_END,
                    "!!! Invalid next event[%d]: %d from filter!", i, next);
        }

        if(next == CLOSE) break;

        next = State_exec(&conn->state, next, (void *)conn);

        check(next >= CLOSE && next < EVENT_END,
                "!!! Invalid next event[%d]: %d, Tell ZED!", i, next);

        if(conn->iob && !conn->iob->closed) {
            Register_ping(IOBuf_fd(conn->iob));
        }

        i++;
    }

error: // fallthrough
    State_exec(&conn->state, CLOSE, (void *)conn);
    Connection_destroy(conn);
    taskexit(0);
}
Exemplo n.º 7
0
int connection_msg_to_handler(Connection *conn)
{
    Handler *handler = Request_get_action(conn->req, handler);
    int rc = 0;
    int header_len = Request_header_length(conn->req);
    // body_len will include \0
    int body_len = Request_content_length(conn->req);

    check(handler, "JSON request doesn't match any handler: %s", 
            bdata(Request_path(conn->req)));

    if(pattern_match(IOBuf_start(conn->iob), header_len + body_len, bdata(&PING_PATTERN))) {
        Register_ping(IOBuf_fd(conn->iob));
    } else {
        check(body_len >= 0, "Parsing error, body length ended up being: %d", body_len);
        bstring payload = NULL;

        if(handler->protocol == HANDLER_PROTO_TNET) {
            payload = Request_to_tnetstring(conn->req, handler->send_ident,
                    IOBuf_fd(conn->iob), IOBuf_start(conn->iob) + header_len,
                    body_len - 1);  // drop \0 on payloads
        } else if(handler->protocol == HANDLER_PROTO_JSON) {
            payload = Request_to_payload(conn->req, handler->send_ident,
                    IOBuf_fd(conn->iob), IOBuf_start(conn->iob) + header_len,
                    body_len - 1);  // drop \0 on payloads
        } else {
            sentinel("Invalid protocol type: %d", handler->protocol);
        }

        debug("SENT: %s", bdata(payload));
        check(payload != NULL, "Failed to generate payload.");
        check(handler->send_socket != NULL, "Handler socket is NULL, tell Zed.");

        rc = Handler_deliver(handler->send_socket, bdata(payload), blength(payload));
        free(payload);
    
        check(rc == 0, "Failed to deliver to handler: %s", bdata(Request_path(conn->req)));
    }

    // consumes \0 from body_len
    check(IOBuf_read_commit(conn->iob, header_len + body_len) != -1, "Final commit failed.");

    return REQ_SENT;

error:
    return CLOSE;
}
Exemplo n.º 8
0
char *test_IOBuf_send_operations() 
{
    Connection *conn = fake_conn("/dev/null", O_WRONLY);
    mu_assert(conn != NULL, "Failed to allocate buf.");
    IOBuf *buf = conn->iob;
    mu_assert(Register_fd_exists(IOBuf_fd(buf)) != NULL, "Damn fd isn't registered.");

    int rc = IOBuf_send(buf, "012345789", 10);
    mu_assert(!IOBuf_closed(buf), "Should not be closed.");
    mu_assert(rc == 10, "Should have sent 10 bytes.");

    fdclose(IOBuf_fd(buf));
    rc = IOBuf_send(buf, "012345789", 10);
    mu_assert(IOBuf_closed(buf), "Should be closed.");
    mu_assert(rc == -1, "Should send nothing.");

    fake_conn_close(conn);

    return NULL;
}
Exemplo n.º 9
0
void Connection_deliver_task(void *v)
{
    Connection *conn=v;
    bstring msg=NULL;
    while(1) {
        msg = Connection_deliver_dequeue(conn);
        check_debug(msg,"Received NULL msg on FD %d, exiting deliver task",IOBuf_fd(conn->iob));
        check(-1 != Connection_deliver_raw_internal(conn,msg),"Error delivering to MSG listener on FD %d, closing them.", IOBuf_fd(conn->iob));
        bdestroy(msg);
        msg=NULL;
    }
error:
    conn->deliverTaskStatus=DT_DYING;
    while(conn->deliverPost > conn->deliverAck) {
        bdestroy(Connection_deliver_dequeue(conn));
    }

    bdestroy(msg);
    if (IOBuf_fd(conn->iob) >= 0)
        shutdown(IOBuf_fd(conn->iob), SHUT_RDWR);
    debug("Deliver Task Shut Down\n");
    conn->deliverTaskStatus=DT_DEAD;
    taskexit(0);
}
Exemplo n.º 10
0
int Connection_send_to_handler(Connection *conn, Handler *handler, char *body, int content_len)
{
    int rc = 0;
    bstring payload = NULL;

    if(conn->iob->use_ssl)
	Connection_fingerprint_from_cert(conn);

    error_unless(handler->running, conn, 404,
            "Handler shutdown while trying to deliver: %s", bdata(Request_path(conn->req)));

    if(handler->protocol == HANDLER_PROTO_TNET) {
        payload = Request_to_tnetstring(conn->req, handler->send_ident, 
                IOBuf_fd(conn->iob), body, content_len);
    } else if(handler->protocol == HANDLER_PROTO_JSON) {
        payload = Request_to_payload(conn->req, handler->send_ident, 
                IOBuf_fd(conn->iob), body, content_len);
    } else {
        sentinel("Invalid protocol type: %d", handler->protocol);
    }

    check(payload, "Failed to create payload for request.");
    debug("HTTP TO HANDLER: %.*s", blength(payload) - content_len, bdata(payload));

    rc = Handler_deliver(handler->send_socket, bdata(payload), blength(payload));
    free(payload); payload = NULL;

    error_unless(rc != -1, conn, 502, "Failed to deliver to handler: %s", 
            bdata(Request_path(conn->req)));

    return 0;

error:
    if(payload) free(payload);
    return -1;
}
Exemplo n.º 11
0
int Connection_accept(Connection *conn)
{
    check(Register_connect(IOBuf_fd(conn->iob), (void*)conn) != -1,
            "Failed to register connection.");

    check(taskcreate(Connection_task, conn, CONNECTION_STACK) != -1,
            "Failed to create connection task.");
    
    check(taskcreate(Connection_deliver_task, conn, CONNECTION_STACK) != -1,
            "Failed to create connection task.");
    conn->deliverTaskStatus=DT_RUNNING;
    return 0;
error:
    IOBuf_register_disconnect(conn->iob);
    return -1;
}
Exemplo n.º 12
0
int Connection_deliver(Connection *conn, bstring buf)
{
    int rc = 0;

    bstring b64_buf = bBase64Encode(buf);
    check(b64_buf != NULL, "Failed to base64 encode data.");
    check(conn->iob != NULL, "There's no IOBuffer to send to, Tell Zed.");
    /* The deliver task will free the buffer */
    rc = Connection_deliver_enqueue(conn,b64_buf);
    check_debug(rc == 0, "Failed to write message to conn %d", IOBuf_fd(conn->iob));

    return 0;

error:
    bdestroy(b64_buf);
    return -1;
}
Exemplo n.º 13
0
static ssize_t ssl_stream_file(IOBuf *iob, int fd, off_t len)
{
    ssize_t sent = 0;
    off_t total = 0;
    ssize_t amt = 0;
    ssize_t tosend = 0;
    int conn_fd = IOBuf_fd(iob);
    char buff[1024];

    for(total = 0; fdwait(conn_fd, 'w') == 0 && total < len; total += tosend) {
        tosend = pread(fd, buff, sizeof(buff), total);
        check_debug(tosend > 0, "Came up short in reading file %d\n", fd);

        // We do this in case the file somehow lengthened on us.  In general,
        // it shouldn't happen.
        if(tosend + total > len)
            tosend = len - total;

        sent = 0;
        while(sent < tosend) {
            amt = ssl_send(iob, buff, tosend);
            check_debug(amt > 0, "ssl_send failed in ssl_stream_file with "
                        "return code %zd", amt);
            sent += amt;
        }

        check(Register_write(iob->fd, sent) != -1, "Failed to record write, must have died.");
    }
    
    check(total <= len,
            "Wrote way too much, wrote %d but size was %zd",
            (int)total, len);

    check(total == len,
            "Sent other than expected, sent: %d, but expected: %zd", 
            (int)total, len);

    return total;

error:
    return -1;
}
Exemplo n.º 14
0
int Connection_send_to_handler(Connection *conn, Handler *handler, char *body, int content_len)
{
    int rc = 0;
    bstring result = NULL;

    result = Request_to_payload(conn->req, handler->send_ident, 
            IOBuf_fd(conn->iob), body, content_len);
    check(result, "Failed to create payload for request.");

    debug("HTTP TO HANDLER: %.*s", blength(result) - content_len, bdata(result));

    rc = Handler_deliver(handler->send_socket, bdata(result), blength(result));
    error_unless(rc != -1, conn, 502, "Failed to deliver to handler: %s", 
            bdata(Request_path(conn->req)));

    bdestroy(result);
    return 0;

error:
    bdestroy(result);
    return -1;
}
Exemplo n.º 15
0
static inline int ident_and_register(Connection *conn, int reg_too)
{
    int next = CLOSE;

    if(Request_is_xml(conn->req)) {
        if(biseq(Request_path(conn->req), &POLICY_XML_REQUEST)) {
            debug("XML POLICY CONNECTION");
            conn->type = CONN_TYPE_SOCKET;
            taskname("XML");
            next = SOCKET_REQ;
        } else {
            debug("XML MESSAGE");
            conn->type = CONN_TYPE_MSG;
            taskname("MSG");
            next = MSG_REQ;
        }
    } else if(Request_is_json(conn->req)) {
        debug("JSON SOCKET MESSAGE");
        conn->type = CONN_TYPE_MSG;
        taskname("MSG");
        next = MSG_REQ;
    } else if(Request_is_http(conn->req)) {
        debug("HTTP MESSAGE");
        conn->type = CONN_TYPE_HTTP;
        taskname("HTTP");
        next = HTTP_REQ;
    } else {
        error_response(conn, 500, "Invalid code branch, tell Zed.");
    }

    if(reg_too) Register_connect(IOBuf_fd(conn->iob), (void*)conn);
    return next;

error:
    return CLOSE;

}
Exemplo n.º 16
0
int Connection_deliver(Connection *conn, bstring buf)
{
    int rc = 0;

    bstring b64_buf = bBase64Encode(buf);
    rc = IOBuf_send(conn->iob, bdata(b64_buf), blength(b64_buf)+1);
    check_debug(rc == blength(b64_buf)+1, "Failed to write entire message to conn %d", IOBuf_fd(conn->iob));

    bdestroy(b64_buf);
    return 0;

error:
    bdestroy(b64_buf);
    return -1;
}