Ejemplo n.º 1
0
Archivo: work.c Proyecto: membase/moxi
/** Use work_send() to place work on another thread's work queue.
 *  The receiving thread will invoke the given function with
 *  the given callback data.
 *
 *  Returns true on success.
 */
bool work_send(work_queue *m,
               void (*func)(void *data0, void *data1),
               void *data0, void *data1) {
    cb_assert(m != NULL);
    cb_assert(m->recv_fd >= 0);
    cb_assert(m->send_fd >= 0);
    cb_assert(m->event_base != NULL);
    cb_assert(func != NULL);

    bool rv = false;

    /* TODO: Add a free-list of work_items. */

    work_item *w = calloc(1, sizeof(work_item));
    if (w != NULL) {
        w->func  = func;
        w->data0 = data0;
        w->data1 = data1;
        w->next  = NULL;

        cb_mutex_enter(&m->work_lock);

        if (m->work_tail != NULL)
            m->work_tail->next = w;
        m->work_tail = w;
        if (m->work_head == NULL)
            m->work_head = w;

        if (send(m->send_fd, "", 1, 0) == 1) {
            m->num_items++;
            m->tot_sends++;

#ifdef WORK_DEBUG
            moxi_log_write("work_send %x %x %x %d %d %d %llu %llu\n",
                    (int) cb_thread_self(),
                    (int) m,
                    (int) m->event_base,
                    m->send_fd, m->recv_fd,
                    m->work_head != NULL,
                    m->num_items,
                    m->tot_sends);
#endif

            rv = true;
        }

        cb_mutex_exit(&m->work_lock);
    }

    return rv;
}
Ejemplo n.º 2
0
static void setup_dispatcher(struct event_base *main_base,
                             void (*dispatcher_callback)(evutil_socket_t, short, void *))
{
    memset(&dispatcher_thread, 0, sizeof(dispatcher_thread));
    dispatcher_thread.type = DISPATCHER;
    dispatcher_thread.base = main_base;
	dispatcher_thread.thread_id = cb_thread_self();
    if (!create_notification_pipe(&dispatcher_thread)) {
        exit(1);
    }
    /* Listen for notifications from other threads */
    event_set(&dispatcher_thread.notify_event, dispatcher_thread.notify[0],
              EV_READ | EV_PERSIST, dispatcher_callback, &dispatcher_callback);
    event_base_set(dispatcher_thread.base, &dispatcher_thread.notify_event);

    if (event_add(&dispatcher_thread.notify_event, 0) == -1) {
        settings.extensions.logger->log(EXTENSION_LOG_WARNING, NULL,
                                        "Can't monitor libevent notify pipe\n");
        exit(1);
    }
}
Ejemplo n.º 3
0
static void cproxy_sasl_plain_auth(conn *c, char *req_bytes) {
    protocol_binary_request_header *req;
    char *key;
    int keylen;
    int bodylen;
    char *clientin;
    unsigned int clientinlen;

    proxy_td *ptd = c->extra;
    cb_assert(ptd != NULL);
    cb_assert(ptd->proxy != NULL);
    cb_assert(ptd->proxy->main != NULL);

    /* Authenticate an upstream connection. */

    req = (protocol_binary_request_header *) req_bytes;

    key = ((char *) req) + sizeof(*req) + req->request.extlen;
    keylen = ntohs(req->request.keylen);
    bodylen = ntohl(req->request.bodylen);

    /* The key is the sasl mech. */

    if (keylen != 5 ||
        memcmp(key, "PLAIN", 5) != 0) { /* 5 == strlen("PLAIN"). */
        write_bin_error(c, PROTOCOL_BINARY_RESPONSE_AUTH_ERROR, 0);
        return;
    }

    clientin = key + keylen;
    clientinlen = bodylen - keylen - req->request.extlen;

    /* The clientin string looks like "[authzid]\0username\0password". */

    while (clientinlen > 0 && clientin[0] != '\0') {
        /* Skip authzid. */

        clientin++;
        clientinlen--;
    }

    if (clientinlen > 2 && clientinlen < 128 && clientin[0] == '\0') {
        const char *username = clientin + 1;
        char        password[256];

        int uslen = strlen(username);
        int pwlen = clientinlen - 2 - uslen;

        if (pwlen < (int) sizeof(password)) {
            proxy *p;
            memcpy(password, clientin + 2 + uslen, pwlen);
            password[pwlen] = '\0';

            p = cproxy_find_proxy_by_auth(ptd->proxy->main,
                                                 username, password);
            if (p != NULL) {
                proxy_td *ptd_target = cproxy_find_thread_data(p, cb_thread_self());
                if (ptd_target != NULL) {
                    c->extra = ptd_target;

                    write_bin_response(c, "Authenticated", 0, 0,
                                       strlen("Authenticated"));

                    if (settings.verbose > 2) {
                        moxi_log_write("<%d sasl authenticated for %s\n",
                                       c->sfd, username);
                    }

                    return;
                } else {
                    if (settings.verbose > 2) {
                        moxi_log_write("<%d sasl auth failed on ptd for %s\n",
                                       c->sfd, username);
                    }
                }
            } else {
                if (settings.verbose > 2) {
                    moxi_log_write("<%d sasl auth failed for %s (%d)\n",
                                   c->sfd, username, pwlen);
                }
            }
        } else {
            if (settings.verbose > 2) {
                moxi_log_write("<%d sasl auth failed for %s with empty password\n",
                               c->sfd, username);
            }
        }
    } else {
        if (settings.verbose > 2) {
            moxi_log_write("<%d sasl auth failed with malformed PLAIN data\n",
                           c->sfd);
        }
    }

    /* TODO: If authentication failed, we should consider */
    /* reassigning the connection to the NULL_BUCKET. */

    write_bin_error(c, PROTOCOL_BINARY_RESPONSE_AUTH_ERROR, 0);
}
Ejemplo n.º 4
0
/*
 * Returns true if this is the thread that listens for new TCP connections.
 */
int is_listen_thread() {
    return dispatcher_thread.thread_id == cb_thread_self();
}