예제 #1
0
파일: wurfld.c 프로젝트: passani/wurfld
static void send_response(wurfld_connection_context *ctx) {
    char *useragent = ctx->useragent;
    DEBUG1("Worker %p is looking up useragent : %s", pthread_self(), useragent);

    // this might be unnecessary if libwurfl is thread-safe
    // XXX - needs to be checked
    wurfld_get_capabilities(useragent, ctx->output);

    if (use_http) {
        char response_header[1024];
        sprintf(response_header, "%s 200 OK\r\n"
                "Content-Type: application/json\r\n"
                "Content-length: %d\r\n"
                "Server: wurfld\r\n"
                "Connection: Close\r\n\r\n",
                ctx->is_http10 ? "HTTP/1.0" : "HTTP/1.1", fbuf_used(ctx->output));

        int err = write_socket(ctx->fd, response_header, strlen(response_header));
        if (err != 0) {
            ERROR("(%p) Can't write the response header : %s", pthread_self(), strerror(errno));
        }
    }

    if (write_socket(ctx->fd, fbuf_data(ctx->output), fbuf_used(ctx->output)) != 0) {
        ERROR("(%p) Can't write the response data : %s", pthread_self(), strerror(errno));
    }
}
예제 #2
0
size_t
shardcache_client_offset(shardcache_client_t *c, void *key, size_t klen, uint32_t offset, void *data, uint32_t dlen)
{
    int fd = -1;
    char *addr = select_node(c, key, klen, &fd);
    if (fd < 0) {
        c->errno = SHARDCACHE_CLIENT_ERROR_NETWORK;
        snprintf(c->errstr, sizeof(c->errstr), "Can't connect to '%s'", addr);
        return 0;
    }

    fbuf_t value = FBUF_STATIC_INITIALIZER;
    int rc = offset_from_peer(addr, (char *)c->auth, SHC_HDR_SIGNATURE_SIP, key, klen, offset, dlen, &value, fd);
    if (rc == 0) {
        uint32_t to_copy = dlen > fbuf_used(&value) ? fbuf_used(&value) : dlen;
        if (data)
            memcpy(data, fbuf_data(&value), to_copy);

        c->errno = SHARDCACHE_CLIENT_OK;
        c->errstr[0] = 0;

        connections_pool_add(c->connections, addr, fd);
        fbuf_destroy(&value);
        return to_copy;
    } else {
        close(fd);
        c->errno = SHARDCACHE_CLIENT_ERROR_NODE;
        snprintf(c->errstr, sizeof(c->errstr), "Can't fetch data from node '%s'", addr);
    }
    fbuf_destroy(&value);
    return 0;
}
예제 #3
0
size_t
shardcache_client_get(shardcache_client_t *c, void *key, size_t klen, void **data)
{
    int fd = -1;
    char *addr = select_node(c, key, klen, &fd);

    if (fd < 0) {
        c->errno = SHARDCACHE_CLIENT_ERROR_NETWORK;
        snprintf(c->errstr, sizeof(c->errstr), "Can't connect to '%s'", addr);
        return 0;
    }

    fbuf_t value = FBUF_STATIC_INITIALIZER;
    int rc = fetch_from_peer(addr, (char *)c->auth, SHC_HDR_SIGNATURE_SIP, key, klen, &value, fd);
    if (rc == 0) {
        size_t size = fbuf_used(&value);
        if (data)
            *data = fbuf_data(&value);
        else
            fbuf_destroy(&value);

        c->errno = SHARDCACHE_CLIENT_OK;
        c->errstr[0] = 0;

        connections_pool_add(c->connections, addr, fd);
        return size;
    } else {
        close(fd);
        c->errno = SHARDCACHE_CLIENT_ERROR_NODE;
        snprintf(c->errstr, sizeof(c->errstr), "Can't fetch data from node '%s'", addr);
        return 0;
    }
    return 0;
}
예제 #4
0
int
shardcache_client_migration_begin(shardcache_client_t *c, shardcache_node_t **nodes, int num_nodes)
{
    fbuf_t mgb_message = FBUF_STATIC_INITIALIZER;

    int i;
    for (i = 0; i < num_nodes; i++) {
        if (i > 0)
            fbuf_add(&mgb_message, ",");
        fbuf_printf(&mgb_message, "%s:%s", shardcache_node_get_string(nodes[i]));
    }

    for (i = 0; i < c->num_shards; i++) {
        char *addr = shardcache_node_get_address(c->shards[i]);
        int fd = connections_pool_get(c->connections, addr);
        if (fd < 0) {
            c->errno = SHARDCACHE_CLIENT_ERROR_NETWORK;
            snprintf(c->errstr, sizeof(c->errstr), "Can't connect to '%s'", addr);
            fbuf_destroy(&mgb_message);
            return -1;
        }

        int rc = migrate_peer(addr,
                              (char *)c->auth,
                              SHC_HDR_SIGNATURE_SIP,
                              fbuf_data(&mgb_message),
                              fbuf_used(&mgb_message), fd);
        if (rc != 0) {
            close(fd);
            c->errno = SHARDCACHE_CLIENT_ERROR_NODE;
            snprintf(c->errstr, sizeof(c->errstr), "Node '%s' (%s) didn't aknowledge the migration\n",
                    shardcache_node_get_label(c->shards[i]), addr);
            fbuf_destroy(&mgb_message);
            // XXX - should we abort migration on peers that have been notified (if any)?
            return -1;
        }
        connections_pool_add(c->connections, addr, fd);
    }
    fbuf_destroy(&mgb_message);

    c->errno = SHARDCACHE_CLIENT_OK;
    c->errstr[0] = 0;

    return 0;
}
예제 #5
0
파일: wurfld.c 프로젝트: passani/wurfld
static char *unescape_uri_request(char *uri) {
    fbuf_t buf = FBUF_STATIC_INITIALIZER;
    char *p = uri;
    while (*p != 0) {
        char *n = p;
        while (*n != '%' && *n != 0)
            n++;
        fbuf_add_binary(&buf, p, n-p);
        p = n;
        if (*n != 0) {
            // p and n now both point to %
            p+=3;
            n++;
            int c;
            if (sscanf(n, "%02x", &c) == 1)
                fbuf_add_binary(&buf, (char *)&c, 1);
            else
                WARN("Can't unescape uri byte");
        }
    }
    char *data = fbuf_data(&buf);
    return data;
}
예제 #6
0
파일: wurfld.c 프로젝트: passani/wurfld
void *worker(void *priv) {
    wurfld_connection_context *ctx = (wurfld_connection_context *)priv;

    DEBUG1("Worker %p started on fd %d", pthread_self(), ctx->fd);

    // we don't need to receive anything anymore on this fd
    int err = shutdown(ctx->fd, SHUT_RD);
    if (err != 0)
        NOTICE("Can't shutdown the receive part of fd %d : %s", ctx->fd, strerror(errno));

    int opts = fcntl(ctx->fd, F_GETFL);
    if (opts >= 0) {
        err = fcntl(ctx->fd, F_SETFL, opts & (~O_NONBLOCK));
        if (err != 0)
            NOTICE("Can't set blocking mode on fd %d : %s", ctx->fd, strerror(errno));
    } else {
        ERROR("Can't get flags on fd %d : %s", ctx->fd, strerror(errno));
    }

    char *useragent = NULL;
    fbuf_trim(ctx->input);

    // parse the request 
    char *request_data = fbuf_data(ctx->input);
    struct sockaddr_in peer;
    socklen_t socklen = sizeof(struct sockaddr);
    getpeername(ctx->fd, (struct sockaddr *)&peer, &socklen);
    if (use_http && strncmp(request_data, "GET /lookup/", 12) == 0) {
        char *reqline_start = fbuf_data(ctx->input) + 12;
        char *reqline_end = reqline_start;

        while (*reqline_end != '\r' && *reqline_end != '\n')
            reqline_end++;
        reqline_end++;

        char reqline[reqline_end-reqline_start];
        snprintf(reqline, reqline_end-reqline_start, "%s", reqline_start);

        char *httpv = strstr(reqline, " HTTP/1");
        if (httpv) {
            *httpv = 0;
            httpv++;
            ctx->is_http10 = (strncmp(httpv, "HTTP/1.0", 8) == 0);
        }
        useragent = unescape_uri_request(reqline);
    } else if (!use_http) {
        useragent = strdup(fbuf_data(ctx->input));
    }

    if (useragent) {
        NOTICE("(%p) Lookup request from %s: %s", pthread_self(), inet_ntoa(peer.sin_addr), useragent);
        ctx->useragent = useragent;
        send_response(ctx);
    } else if (use_http) {
        NOTICE("(%p) Unsupported Request from %s: %s", pthread_self(), inet_ntoa(peer.sin_addr), request_data);
        char response[2048];

        snprintf(response, sizeof(response),
                 "%s 400 NOT SUPPORTED\r\n"
                 "Content-Type: text/plain\r\n"
                 "Content-Length: 17\r\n\r\n"
                 "400 NOT SUPPORTED",
                 ctx->is_http10 ? "HTTP/1.0" : "HTTP/1.1");

        if (write_socket(ctx->fd, response, strlen(response)) != 0) {
            ERROR("Worker %p failed writing reponse: %s", pthread_self(), strerror(errno));
        }
    }
    DEBUG1("Worker %p finished on fd %d", pthread_self(), ctx->fd);
    shutdown(ctx->fd, SHUT_RDWR);
    close(ctx->fd);
    fbuf_free(ctx->input);
    fbuf_free(ctx->output);
    free(ctx->useragent); 
    free(ctx);
    return NULL;
}
예제 #7
0
파일: expression.c 프로젝트: xant/libexpr
char *expression_dump(expression_t *expr) {
    fbuf_t buf = FBUF_STATIC_INITIALIZER;
    expression_dump_internal(expr, &buf);
    return fbuf_data(&buf);
}