Beispiel #1
0
static inline void handler_process_request(Handler *handler, int id, int fd,
        Connection *conn, bstring payload)
{
    int rc = 0;

    if(conn == NULL) {
        debug("Ident %d (fd %d) is no longer connected.", id, fd);
        Handler_notify_leave(handler, id);
    } else {
        if(blength(payload) == 0) {
            rc = Register_disconnect(fd);
            check(rc != -1, "Register disconnect failed for: %d", fd);
        } else {
            int raw = conn->type != CONN_TYPE_MSG || handler->raw;

            rc = deliver_payload(raw, fd, conn, payload);
            check(rc != -1, "Failed to deliver to connection %d on socket %d", id, fd);
        }
    }

    return;

error:
    Register_disconnect(fd);  // return ignored
    return;
}
Beispiel #2
0
static inline void handler_process_extended_request(int fd, Connection *conn, bstring payload)
{
    char *x;
    tns_value_t *data = NULL;
    darray_t *l = NULL;
    
    data = tns_parse(bdata(payload),blength(payload),&x);

    check((x-bdata(payload))==blength(payload), "Invalid extended response: extra data after tnetstring.");
    check(data->type==tns_tag_list, "Invalid extended response: not a list.");
    l = data->value.list;
    check(darray_end(l)==2, "Invalid extended response: odd number of elements in list.");
    tns_value_t *key=darray_get(l,0);
    check(key->type==tns_tag_string, "Invalid extended response: key is not a string");
    check(key->value.string != NULL,, "Invalid extended response: key is NULL");

    if(!bstrcmp(key->value.string, &XREQ_CTL)) {
        check (0 == handler_process_control_request(conn, data),
                "Control request processing returned non-zero: %s", bdata(key->value.string));
    } else {
        check (0 == dispatch_extended_request(conn, key->value.string, data),
                "Extended request dispatch returned non-zero: %s",bdata(key->value.string));
    }

    return;
error:
    tns_value_destroy(data);
    Register_disconnect(fd); // return ignored
    return;
}
Beispiel #3
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;
}
Beispiel #4
0
int Register_cleanout()
{
    int i = 0;
    int nkilled = 0;
    int nscanned = 0;
    time_t now = THE_CURRENT_TIME_IS;
    int min_ping = Setting_get_int("limits.min_ping", DEFAULT_MIN_PING);
    int min_write_rate = Setting_get_int("limits.min_write_rate", DEFAULT_MIN_READ_RATE);
    int min_read_rate = Setting_get_int("limits.min_read_rate", DEFAULT_MIN_WRITE_RATE);
    int kill_limit = Setting_get_int("limits.kill_limit", DEFAULT_KILL_LIMIT);

    for(i = 0, nscanned = 0; i < darray_max(REGISTRATIONS) && nscanned < NUM_REG_FD; i++) {
        Registration *reg = darray_get(REGISTRATIONS, i);

        if(Register_valid(reg)) {
            nscanned++; // avoid scanning the whole array if we've found them all

            int last_ping = ZERO_OR_DELTA(now, reg->last_ping);
            off_t read_rate = reg->bytes_read / (ZERO_OR_DELTA(now, reg->last_read) + 1);
            off_t write_rate = reg->bytes_written / (ZERO_OR_DELTA(now, reg->last_write) + 1);
            int should_kill = 0;

            debug("Checking fd=%d:conn_id=%d against last_ping: %d, read_rate: %d, write_rate: %d",
                    i, reg->id, last_ping, read_rate, write_rate);

            // these are weighted so they are not if-else statements
            if(min_ping != 0 && last_ping > min_ping) {
                debug("Connection fd=%d:conn_id=%d over limits.min_ping time: %d < %d",
                        i, reg->id, min_ping, last_ping);
                should_kill++;
            }
            
            if(min_read_rate != 0 && read_rate < min_read_rate) {
                debug("Connection fd=%d:conn_id=%d read rate lower than allowed: %d < %d",
                        i, reg->id, read_rate, min_read_rate);
                should_kill++;
            } 

            if(min_write_rate != 0 && write_rate < min_write_rate) {
                debug("Connection fd=%d:conn_id=%d write rate lower than allowed: %d < %d",
                        i, reg->id, write_rate, min_write_rate);
                should_kill++;
            }

            if(should_kill > kill_limit) {
                nkilled++;
                Register_disconnect(i);
            }
        }
    }

    if(nkilled) {
        log_warn("Killed %d connections according to min_ping: %d, min_write_rate: %d, min_read_rate: %d", nkilled, min_ping, min_write_rate, min_read_rate);
    }

    return nkilled;
}
Beispiel #5
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;
}
Beispiel #6
0
static inline void handler_process_request(Handler *handler, int id, int fd,
        Connection *conn, bstring payload)
{
    int rc = 0;
    check(conn != NULL, "You can't pass NULL conn to this anymore.");

    if(blength(payload) == 0) {
        rc = Connection_deliver_raw(conn,NULL);
        check(rc != -1, "Register disconnect failed for: %d", fd);
    } else {
        int raw = conn->type != CONN_TYPE_MSG || handler->raw;

        rc = deliver_payload(raw, fd, conn, payload);
        check(rc != -1, "Failed to deliver to connection %d on socket %d", id, fd);
    }

    return;

error:
    Register_disconnect(fd);  // return ignored
    return;
}
Beispiel #7
0
int Register_connect(int fd, Connection* data)
{
    check(fd < MAX_REGISTERED_FDS, "FD given to register is greater than max.");
    check(data != NULL, "data can't be NULL");

    Registration *reg = darray_get(REGISTRATIONS, fd);

    if(reg == NULL) {
        reg = darray_new(REGISTRATIONS);
        check(reg != NULL, "Failed to allocate a new registration.");

        // we only set this here since they stay in list forever rather than recycle
        darray_set(REGISTRATIONS, fd, reg);
        darray_attach(REGISTRATIONS, reg);
    }

    if(Register_valid(reg)) {
        // force them to exit
        int rc = Register_disconnect(fd);
        check(rc != -1, "Weird error trying to disconnect. Tell Zed.");
        tasksignal(reg->task, SIGINT);
    }

    reg->data = data;
    reg->last_ping = THE_CURRENT_TIME_IS;
    reg->fd = fd;
    reg->task = taskself();

    reg->id = UINT32_MAX; // start off with an invalid conn_id
    
    // keep track of the number of registered things we're tracking
    NUM_REG_FD++;

    return 0;
error:
    return -1;
}
Beispiel #8
0
void fake_conn_close(Connection *conn)
{
    assert(conn && conn->iob && "Invalid connection.");
    Register_disconnect(conn->iob->fd);
    Connection_destroy(conn);
}