Ejemplo n.º 1
0
/* dnode sends a response back to a peer  */
static struct msg *
dnode_rsp_send_next(struct context *ctx, struct conn *conn)
{
    rstatus_t status;

    // SMB: There is some non trivial thing happening here. And I think it is very
    // important to read this before anything is changed in here. There is also a
    // bug that exists which I will mention briefly:
    // A message is a structure that has a list of mbufs which hold the actual data.
    // Each mbuf has start, pos, last as pointers (amongst others) which indicate start of the
    // buffer, current read position and end of the buffer respectively.
    //
    // Every time a message is sent to a peer within dynomite, a DNODE header is
    // prepended which is created using dmsg_write. A message remembers this case
    // in dnode_header_prepended, so that if the messsage is sent in parts, the
    // header is not prepended again for the subsequent parts.
    //
    // Like I said earlier there is a pos pointer in mbuf. If a message is sent
    // partially (or it is parsed partially too I think) the pos reflects that
    // case such that things can be resumed where it left off.
    //
    // dmsg_write has a parameter which reflects the payload length following the
    // dnode header calculated by msg_length. msg_length is a summation of all
    // mbuf sizes (last - start). Which I think is wrong.
    //
    // +------------+           +---------------+
    // |    DC1N1   +---------> |     DC2N1     |
    // +------------+           +-------+-------+
    //                                  |
    //                                  |
    //                                  |
    //                                  |
    //                          +-------v-------+
    //                          |    DC2N2      |
    //                          +---------------+
    //
    // Consider the case where
    // a node DC1N1 in region DC1 sends a request to DC2N1 which forwards it to
    // to local token owner DC2N2. Now DC2N1 receives a response from DC2N2 which
    // has to be relayed back to DC1N1. This response from DC2N2 already has a
    // dnode header but for the link between DC2N1 and DC2N2. DC2N1 should strip
    // this header and prepend its own header for sending it back to DC1N1. This
    // gets handled in encryption case since we overwrite all mbufs in the response
    // However if the encryption is off, the message length sent to dmsg_write
    // consists of the header from DC2N2 also which is wrong. So this relaying
    // of responses will not work for the case where encryption is disabled.
    //
    // So msg_length should really be from mbuf->pos and not mbuf->start. This
    // is a problem only with remote region replication since that is the only
    // case where we CAN have 2 hops to send the request/response. This is also
    // not a problem if encryption is ON.
    ASSERT(conn->type == CONN_DNODE_PEER_CLIENT);

    struct msg *rsp = rsp_send_next(ctx, conn);

    if (rsp != NULL && conn->dyn_mode) {
        struct msg *pmsg = rsp->peer;

        //need to deal with multi-block later
        uint64_t msg_id = pmsg->dmsg->id;
        if (rsp->dnode_header_prepended) {
            return rsp;
        }

        struct mbuf *header_buf = mbuf_get();
        if (header_buf == NULL) {
            loga("Unable to obtain an mbuf for header!");
            return NULL; //need to address error here properly
        }
        dmsg_type_t msg_type = DMSG_RES;
        //TODOs: need to set the outcoming conn to be secured too if the incoming conn is secured
        if (pmsg->owner->dnode_secured || conn->dnode_secured) {
            if (log_loggable(LOG_VVERB)) {
                log_debug(LOG_VVERB, "Encrypting response ...");
                loga("AES encryption key: %s\n", base64_encode(conn->aes_key, AES_KEYLEN));
            }

            if (ENCRYPTION) {
              status = dyn_aes_encrypt_msg(rsp, conn->aes_key);
              if (status == DN_ERROR) {
                    loga("OOM to obtain an mbuf for encryption!");
                    mbuf_put(header_buf);
                    req_put(rsp);
                    return NULL;
              }

              if (log_loggable(LOG_VVERB)) {
                   log_debug(LOG_VERB, "#encrypted bytes : %d", status);
              }

              dmsg_write(header_buf, msg_id, msg_type, conn, msg_length(rsp));
            } else {
                if (log_loggable(LOG_VVERB)) {
                   log_debug(LOG_VERB, "no encryption on the rsp payload");
                }
                dmsg_write(header_buf, msg_id, msg_type, conn, msg_length(rsp));
            }

        } else {
            //write dnode header
            log_debug(LOG_VERB, "sending dnode response with msg_id %u", msg_id);
            dmsg_write(header_buf, msg_id, msg_type, conn, msg_length(rsp));
        }

        rsp->dnode_header_prepended = 1;
        mbuf_insert_head(&rsp->mhdr, header_buf);

        if (log_loggable(LOG_VVERB)) {
            log_hexdump(LOG_VVERB, header_buf->pos, mbuf_length(header_buf), "resp dyn message - header: ");
            msg_dump(rsp);
        }

    }

    return rsp;
}
Ejemplo n.º 2
0
/* dnode sends a response back to a peer  */
struct msg *
dnode_rsp_send_next(struct context *ctx, struct conn *conn)
{
    rstatus_t status;


    ASSERT(conn->dnode_client && !conn->dnode_server);
    struct msg *rsp = rsp_send_next(ctx, conn);

    if (rsp != NULL && conn->dyn_mode) {
        struct msg *pmsg = rsp->peer;

        //need to deal with multi-block later
        uint64_t msg_id = pmsg->dmsg->id;

        struct mbuf *header_buf = mbuf_get();
        if (header_buf == NULL) {
            loga("Unable to obtain an mbuf for header!");
            return NULL; //need to address error here properly
        }
        dmsg_type_t msg_type = DMSG_RES;
        //TODOs: need to set the outcoming conn to be secured too if the incoming conn is secured
        if (pmsg->owner->dnode_secured || conn->dnode_secured) {
            if (log_loggable(LOG_VVERB)) {
                log_debug(LOG_VVERB, "Encrypting response ...");
                loga("AES encryption key: %s\n", base64_encode(conn->aes_key, AES_KEYLEN));
            }

            if (ENCRYPTION) {
                status = dyn_aes_encrypt_msg(rsp, conn->aes_key);
                if (status == DN_ERROR) {
                    loga("OOM to obtain an mbuf for encryption!");
                    mbuf_put(header_buf);
                    req_put(rsp);
                    return NULL;
                }

                if (log_loggable(LOG_VVERB)) {
                    log_debug(LOG_VERB, "#encrypted bytes : %d", status);
                }

                dmsg_write(header_buf, msg_id, msg_type, conn, msg_length(rsp));
            } else {
                if (log_loggable(LOG_VVERB)) {
                    log_debug(LOG_VERB, "no encryption on the rsp payload");
                }
                dmsg_write(header_buf, msg_id, msg_type, conn, msg_length(rsp));
            }

        } else {
            //write dnode header
            log_info("sending dnode response with msg_id %u", msg_id);
            dmsg_write(header_buf, msg_id, msg_type, conn, msg_length(rsp));
        }

        mbuf_insert_head(&rsp->mhdr, header_buf);

        if (log_loggable(LOG_VVERB)) {
            log_hexdump(LOG_VVERB, header_buf->pos, mbuf_length(header_buf), "resp dyn message - header: ");
            msg_dump(rsp);
        }

    }

    return rsp;
}
Ejemplo n.º 3
0
/* Forward a client request over to a peer */
void dnode_peer_req_forward(struct context *ctx, struct conn *c_conn,
                            struct conn *p_conn, struct msg *msg,
                            struct rack *rack, uint8_t *key, uint32_t keylen)
{

    struct server *server = p_conn->owner;
    log_debug(LOG_DEBUG, "forwarding request from client conn '%s' to peer conn '%s' on rack '%.*s' dc '%.*s' ",
              dn_unresolve_peer_desc(c_conn->sd), dn_unresolve_peer_desc(p_conn->sd),
              rack->name->len, rack->name->data,
              server->dc.len, server->dc.data);

    struct string *dc = rack->dc;
    rstatus_t status;
    /* enqueue message (request) into client outq, if response is expected */
    if (!msg->noreply && !msg->swallow) {
        conn_enqueue_outq(ctx, c_conn, msg);
    }

    ASSERT(p_conn->type == CONN_DNODE_PEER_SERVER);
    ASSERT((c_conn->type == CONN_CLIENT) ||
           (c_conn->type == CONN_DNODE_PEER_CLIENT));

    /* enqueue the message (request) into peer inq */
    status = event_add_out(ctx->evb, p_conn);
    if (status != DN_OK) {
        dnode_req_forward_error(ctx, p_conn, msg);
        p_conn->err = errno;
        return;
    }

    struct mbuf *header_buf = mbuf_get();
    if (header_buf == NULL) {
        loga("Unable to obtain an mbuf for dnode msg's header!");
        req_put(msg);
        return;
    }

    struct server_pool *pool = c_conn->owner;
    dmsg_type_t msg_type = (string_compare(&pool->dc, dc) != 0)? DMSG_REQ_FORWARD : DMSG_REQ;

    if (p_conn->dnode_secured) {
        //Encrypting and adding header for a request
        if (log_loggable(LOG_VVERB)) {
           log_debug(LOG_VERB, "AES encryption key: %s\n", base64_encode(p_conn->aes_key, AES_KEYLEN));
        }

        //write dnode header
        if (ENCRYPTION) {
            status = dyn_aes_encrypt_msg(msg, p_conn->aes_key);
            if (status == DN_ERROR) {
                loga("OOM to obtain an mbuf for encryption!");
                mbuf_put(header_buf);
                req_put(msg);
                return;
            }

            if (log_loggable(LOG_VVERB)) {
               log_debug(LOG_VERB, "#encrypted bytes : %d", status);
            }

            dmsg_write(header_buf, msg->id, msg_type, p_conn, msg_length(msg));
        } else {
            if (log_loggable(LOG_VVERB)) {
               log_debug(LOG_VERB, "no encryption on the msg payload");
            }
            dmsg_write(header_buf, msg->id, msg_type, p_conn, msg_length(msg));
        }

    } else {
        //write dnode header
        dmsg_write(header_buf, msg->id, msg_type, p_conn, msg_length(msg));
    }

    mbuf_insert_head(&msg->mhdr, header_buf);

    if (log_loggable(LOG_VVERB)) {
        log_hexdump(LOG_VVERB, header_buf->pos, mbuf_length(header_buf), "dyn message header: ");
        msg_dump(msg);
    }

    conn_enqueue_inq(ctx, p_conn, msg);

    dnode_peer_req_forward_stats(ctx, p_conn->owner, msg);

    if (log_loggable(LOG_VVERB)) {
       log_debug(LOG_VVERB, "remote forward from c %d to s %d req %"PRIu64" len %"PRIu32
                   " type %d with key '%.*s'", c_conn->sd, p_conn->sd, msg->id,
                   msg->mlen, msg->type, keylen, key);
    }

}