Пример #1
0
/*
 * 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;
}
Пример #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)
{

    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);
    }

}