/* * Sending a mbuf of gossip data over the wire to a peer */ void dnode_peer_gossip_forward(struct context *ctx, struct conn *conn, bool redis, struct mbuf *data_buf) { rstatus_t status; struct msg *msg = msg_get(conn, 1, redis); if (msg == NULL) { log_debug(LOG_DEBUG, "Unable to obtain a msg"); return; } struct mbuf *header_buf = mbuf_get(); if (header_buf == NULL) { log_debug(LOG_DEBUG, "Unable to obtain a data_buf"); msg_put(msg); return; } uint64_t msg_id = peer_msg_id++; if (conn->dnode_secured) { log_debug(LOG_VERB, "Assemble a secured msg to send"); log_debug(LOG_VERB, "AES encryption key: %s\n", base64_encode(conn->aes_key, AES_KEYLEN)); struct mbuf *encrypted_buf = mbuf_get(); if (encrypted_buf == NULL) { loga("Unable to obtain an data_buf for encryption!"); return; //TODOs: need to clean up } status = dyn_aes_encrypt(data_buf->pos, mbuf_length(data_buf), encrypted_buf, conn->aes_key); log_debug(LOG_VERB, "#encrypted bytes : %d", status); //write dnode header dmsg_write(header_buf, msg_id, GOSSIP_SYN, conn, mbuf_length(encrypted_buf)); mbuf_insert_head(&msg->mhdr, header_buf); if (TRACING_LEVEL == LOG_VVERB) { log_hexdump(LOG_VVERB, data_buf->pos, mbuf_length(data_buf), "dyn message original payload: "); log_hexdump(LOG_VVERB, encrypted_buf->pos, mbuf_length(encrypted_buf), "dyn message encrypted payload: "); } mbuf_insert(&msg->mhdr, encrypted_buf); //free data_buf as no one will need it again mbuf_put(data_buf); } else { log_debug(LOG_VERB, "Assemble a non-secured msg to send"); dmsg_write_mbuf(header_buf, msg_id, GOSSIP_SYN, conn, mbuf_length(data_buf)); mbuf_insert_head(&msg->mhdr, header_buf); mbuf_insert(&msg->mhdr, data_buf); } if (TRACING_LEVEL == LOG_VVERB) { log_hexdump(LOG_VVERB, header_buf->pos, mbuf_length(header_buf), "dyn gossip message header: "); msg_dump(msg); } /* enqueue the message (request) into peer inq */ if (TAILQ_EMPTY(&conn->imsg_q)) { status = event_add_out(ctx->evb, conn); if (status != DN_OK) { dnode_req_forward_error(ctx, conn, msg); conn->err = errno; return; } } //need to handle a reply //conn->enqueue_outq(ctx, conn, msg); msg->noreply = 1; conn->enqueue_inq(ctx, conn, msg); }
/* dnode sends a response back to a peer */ struct msg * dnode_rsp_send_next(struct context *ctx, struct conn *conn) { if (TRACING_LEVEL == LOG_VVERB) { log_debug(LOG_VVERB, "dnode_rsp_send_next entering"); } ASSERT(conn->dnode_client && !conn->dnode_server); struct msg *msg = rsp_send_next(ctx, conn); if (msg != NULL && conn->dyn_mode) { struct msg *pmsg = TAILQ_FIRST(&conn->omsg_q); //peer request's msg //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 } //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 (TRACING_LEVEL == LOG_VVERB) { log_debug(LOG_VVERB, "Encrypting response ..."); loga("AES encryption key: %s\n", base64_encode(conn->aes_key, AES_KEYLEN)); } struct mbuf *data_buf = STAILQ_LAST(&msg->mhdr, mbuf, next); //if (ENCRYPTION) { struct mbuf *encrypted_buf = mbuf_get(); if (encrypted_buf == NULL) { loga("Unable to obtain an mbuf for encryption!"); return NULL; //TODOs: need to clean up } rstatus_t status = dyn_aes_encrypt(data_buf->pos, mbuf_length(data_buf), encrypted_buf, conn->aes_key); if (TRACING_LEVEL == LOG_VVERB) { log_debug(LOG_VERB, "#encrypted bytes : %d", status); } dmsg_write(header_buf, msg_id, DMSG_RES, conn, mbuf_length(encrypted_buf)); if (TRACING_LEVEL == LOG_VVERB) { log_hexdump(LOG_VVERB, data_buf->pos, mbuf_length(data_buf), "resp dyn message - original payload: "); log_hexdump(LOG_VVERB, encrypted_buf->pos, mbuf_length(encrypted_buf), "dyn message encrypted payload: "); } mbuf_copy(header_buf, encrypted_buf->start, mbuf_length(encrypted_buf)); mbuf_insert(&msg->mhdr, header_buf); //remove the original dbuf out of the queue and insert encrypted mbuf to replace mbuf_remove(&msg->mhdr, data_buf); //mbuf_insert(&msg->mhdr, encrypted_buf); mbuf_put(data_buf); mbuf_put(encrypted_buf); //} else { // log_debug(LOG_VERB, "no encryption on the response's payload"); // dmsg_write(header_buf, msg_id, DMSG_RES, conn, mbuf_length(data_buf)); //} } else { dmsg_write(header_buf, msg_id, DMSG_RES, conn, 0);//Dont care about 0 or the real length as we don't use that value in unencryption mode mbuf_insert_head(&msg->mhdr, header_buf); } if (TRACING_LEVEL == LOG_VVERB) { log_hexdump(LOG_VVERB, header_buf->pos, mbuf_length(header_buf), "resp dyn message - header: "); msg_dump(msg); } } return msg; }
/* 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) { if (TRACING_LEVEL == LOG_VVERB) { log_debug(LOG_VVERB, "dnode_peer_req_forward entering"); } rstatus_t status; /* enqueue message (request) into client outq, if response is expected */ if (!msg->noreply) { c_conn->enqueue_outq(ctx, c_conn, msg); } ASSERT(!p_conn->dnode_client && !p_conn->dnode_server); ASSERT(c_conn->client); /* enqueue the message (request) into peer inq */ if (TAILQ_EMPTY(&p_conn->imsg_q)) { 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; } } uint64_t msg_id = peer_msg_id++; struct mbuf *header_buf = mbuf_get(); if (header_buf == NULL) { loga("Unable to obtain an mbuf for dnode msg's header!"); return; } if (p_conn->dnode_secured) { //Encrypting and adding header for a request struct mbuf *data_buf = STAILQ_LAST(&msg->mhdr, mbuf, next); //TODOs: need to deal with multi-block later log_debug(LOG_VERB, "AES encryption key: %s\n", base64_encode(p_conn->aes_key, AES_KEYLEN)); struct mbuf *encrypted_buf = mbuf_get(); if (encrypted_buf == NULL) { loga("Unable to obtain an mbuf for encryption!"); return; //TODOs: need to clean up } status = dyn_aes_encrypt(data_buf->pos, mbuf_length(data_buf), encrypted_buf, p_conn->aes_key); log_debug(LOG_VERB, "#encrypted bytes : %d", status); //write dnode header dmsg_write(header_buf, msg_id, DMSG_REQ, p_conn, mbuf_length(encrypted_buf)); mbuf_insert_head(&msg->mhdr, header_buf); log_hexdump(LOG_VERB, data_buf->pos, mbuf_length(data_buf), "dyn message original payload: "); log_hexdump(LOG_VERB, encrypted_buf->pos, mbuf_length(encrypted_buf), "dyn message encrypted payload: "); //remove the original dbuf out of the queue and insert encrypted mbuf to replace mbuf_remove(&msg->mhdr, data_buf); mbuf_insert(&msg->mhdr, encrypted_buf); //free it as no one will need it again mbuf_put(data_buf); } else { //write dnode header dmsg_write(header_buf, msg_id, DMSG_REQ, p_conn, 0); mbuf_insert_head(&msg->mhdr, header_buf); } if (TRACING_LEVEL == LOG_VVERB) { log_hexdump(LOG_VVERB, header_buf->pos, mbuf_length(header_buf), "dyn message header: "); msg_dump(msg); } p_conn->enqueue_inq(ctx, p_conn, msg); dnode_peer_req_forward_stats(ctx, p_conn->owner, msg); if (TRACING_LEVEL == LOG_VERB) { log_debug(LOG_VERB, "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); } }