rstatus_t core_core(void *arg, uint32_t events) { rstatus_t status; struct conn *conn = arg; struct context *ctx = conn_to_ctx(conn); log_debug(LOG_VVERB, "event %04"PRIX32" on %s %d", events, conn_get_type_string(conn), conn->sd); conn->events = events; /* error takes precedence over read | write */ if (events & EVENT_ERR) { if (conn->err && conn->dyn_mode) { loga("conn err on dnode EVENT_ERR: %d", conn->err); } core_error(ctx, conn); return DN_ERROR; } /* read takes precedence over write */ if (events & EVENT_READ) { status = core_recv(ctx, conn); if (status != DN_OK || conn->done || conn->err) { if (conn->dyn_mode) { if (conn->err) { loga("conn err on dnode EVENT_READ: %d", conn->err); core_close(ctx, conn); return DN_ERROR; } return DN_OK; } core_close(ctx, conn); return DN_ERROR; } } if (events & EVENT_WRITE) { status = core_send(ctx, conn); if (status != DN_OK || conn->done || conn->err) { if (conn->dyn_mode) { if (conn->err) { loga("conn err on dnode EVENT_WRITE: %d", conn->err); core_close(ctx, conn); return DN_ERROR; } return DN_OK; } core_close(ctx, conn); return DN_ERROR; } } return DN_OK; }
void dnode_rsp_recv_done(struct context *ctx, struct conn *conn, struct msg *msg, struct msg *nmsg) { log_debug(LOG_VERB, "dnode_rsp_recv_done entering ..."); ASSERT(conn->type == CONN_DNODE_PEER_SERVER); ASSERT(msg != NULL && conn->rmsg == msg); ASSERT(!msg->request); ASSERT(msg->owner == conn); ASSERT(nmsg == NULL || !nmsg->request); if (log_loggable(LOG_VVERB)) { loga("Dumping content for msg: "); msg_dump(msg); if (nmsg != NULL) { loga("Dumping content for nmsg :"); msg_dump(nmsg); } } /* enqueue next message (response), if any */ conn->rmsg = nmsg; if (dnode_rsp_filter(ctx, conn, msg)) { return; } dnode_rsp_forward(ctx, conn, msg); }
void dnode_rsp_recv_done(struct context *ctx, struct conn *conn, struct msg *msg, struct msg *nmsg) { log_debug(LOG_VERB, "dnode_rsp_recv_done entering ..."); ASSERT(!conn->dnode_client && !conn->dnode_server); ASSERT(msg != NULL && conn->rmsg == msg); ASSERT(!msg->request); ASSERT(msg->owner == conn); ASSERT(nmsg == NULL || !nmsg->request); if (TRACING_LEVEL == LOG_VVERB) { loga("Dumping content for msg: "); msg_dump(msg); if (nmsg != NULL) { loga("Dumping content for nmsg :"); msg_dump(nmsg); } } /* enqueue next message (response), if any */ conn->rmsg = nmsg; if (dnode_rsp_filter(ctx, conn, msg)) { return; } dnode_rsp_forward(ctx, conn, msg); }
static void nc_print_run(struct instance *nci) { loga("nutcracker-%s started on pid %d", NC_VERSION_STRING, nci->pid); loga("run, rabbit run / dig that hole, forget the sun / " "and when at last the work is done / don't sit down / " "it's time to dig another one"); }
int main() { char *filename = (char *)"/var/mylog"; int ret = log_init(LOG_WARN, filename); printf("ret: %d\n", ret); loga("for test"); loga("for test %d", 1); loga("for test %s", "test"); return 0; }
/* Description: link data from a peer connection to a client-facing connection * peer_conn: a peer connection * msg : msg with data from the peer connection after parsing */ static void dnode_rsp_forward(struct context *ctx, struct conn *peer_conn, struct msg *msg) { rstatus_t status; struct msg *pmsg; struct conn *c_conn; log_debug(LOG_VERB, "dnode_rsp_forward entering ..."); ASSERT(!peer_conn->dnode_client && !peer_conn->dnode_server); /* response from a peer implies that peer is ok and heartbeating */ dnode_peer_ok(ctx, peer_conn); /* dequeue peer message (request) from peer conn */ pmsg = TAILQ_FIRST(&peer_conn->omsg_q); ASSERT(pmsg != NULL && pmsg->peer == NULL); ASSERT(pmsg->request && !pmsg->done); if (TRACING_LEVEL >= LOG_VVERB) { loga("Dumping content for msg: "); msg_dump(msg); loga("msg id %d", msg->id); loga("Dumping content for pmsg :"); msg_dump(pmsg); loga("pmsg id %d", pmsg->id); } peer_conn->dequeue_outq(ctx, peer_conn, pmsg); pmsg->done = 1; /* establish msg <-> pmsg (response <-> request) link */ pmsg->peer = msg; msg->peer = pmsg; msg->pre_coalesce(msg); c_conn = pmsg->owner; ASSERT(c_conn->client && !c_conn->proxy); if (TAILQ_FIRST(&c_conn->omsg_q) != NULL && dnode_req_done(c_conn, TAILQ_FIRST(&c_conn->omsg_q))) { status = event_add_out(ctx->evb, c_conn); if (status != DN_OK) { c_conn->err = errno; } } dnode_rsp_forward_stats(ctx, peer_conn->owner, msg); }
struct mbuf * mbuf_get(void) { struct mbuf *mbuf; uint8_t *buf; mbuf = _mbuf_get(); if (mbuf == NULL) { loga("mbuf is Null"); return NULL; } buf = (uint8_t *)mbuf - mbuf_offset; mbuf->start = buf; mbuf->end = buf + mbuf_offset - MBUF_ESIZE; mbuf->end_extra = buf + mbuf_offset; //ASSERT(mbuf->end - mbuf->start == (int)mbuf_offset); ASSERT(mbuf->start < mbuf->end); mbuf->pos = mbuf->start; mbuf->last = mbuf->start; mbuf->read_flip = 0; log_debug(LOG_VVERB, "get mbuf %p", mbuf); return mbuf; }
void log_level_set(int level) { struct logger *l = &logger; l->level = MAX(LOG_EMERG, MIN(level, LOG_DEBUG)); loga("set log level to %d", l->level); }
rstatus_t dmsg_write(struct mbuf *mbuf, uint64_t msg_id, uint8_t type, struct conn *conn, uint32_t payload_len) { mbuf_write_string(mbuf, &MAGIC_STR); mbuf_write_uint64(mbuf, msg_id); mbuf_write_char(mbuf, ' '); mbuf_write_uint8(mbuf, type); mbuf_write_char(mbuf, ' '); //encryption bit if (conn->dnode_secured) { mbuf_write_uint8(mbuf, 1); } else { mbuf_write_uint8(mbuf, 0); } mbuf_write_char(mbuf, ' '); mbuf_write_uint8(mbuf, version); //mbuf_write_string(mbuf, &CRLF_STR); mbuf_write_char(mbuf, ' '); mbuf_write_char(mbuf, '*'); //write aes key unsigned char *aes_key = conn->aes_key; if (conn->dnode_secured && conn->dnode_crypto_state == 0) { mbuf_write_uint32(mbuf, AES_ENCRYPTED_KEYLEN); } else { mbuf_write_uint32(mbuf, 1); } mbuf_write_char(mbuf, ' '); //mbuf_write_string(mbuf, data); if (conn->dnode_secured && conn->dnode_crypto_state == 0) { #ifdef DN_DEBUG_LOG loga("AES key to be encrypted : %s \n", base64_encode(aes_key, 32)); #endif dyn_rsa_encrypt(aes_key, aes_encrypted_buf); mbuf_write_bytes(mbuf, aes_encrypted_buf, AES_ENCRYPTED_KEYLEN); conn->dnode_crypto_state = 1; } else { mbuf_write_char(mbuf, 'd'); //TODOs: replace with another string } //mbuf_write_string(mbuf, &CRLF_STR); mbuf_write_char(mbuf, ' '); mbuf_write_char(mbuf, '*'); mbuf_write_uint32(mbuf, payload_len); mbuf_write_string(mbuf, &CRLF_STR); #ifdef DN_DEBUG_LOG log_hexdump(LOG_VERB, mbuf->pos, mbuf_length(mbuf), "dyn message producer: "); #endif return DN_OK; }
void log_level_set(log_t *log,int level) { struct log_t *l = log; l->level = MAX(LOG_EMERG, MIN(level, LOG_PVERB)); loga(l,"set log level to %d", l->level); }
void log_level_set(int level) { struct logger *l = &logger; l->level = MAX(LOG_ALWAYS, MIN(level, LOG_VERB)); loga("set log level to %d", l->level); }
void slab_print(void) { uint8_t id; struct slabclass *p; loga("slab size %zu, slab hdr size %zu, item hdr size %zu, item chunk size" "%zu, total memory %zu", slab_size, SLAB_HDR_SIZE, ITEM_HDR_SIZE, item_min, slab_mem); for (id = SLABCLASS_MIN_ID; id <= profile_last_id; id++) { p = &slabclass[id]; loga("class %3"PRId8": items %7"PRIu32" size %7zu data %7zu " "slack %7zu", id, p->nitem, p->size, p->size - ITEM_HDR_SIZE, slab_capacity() - p->nitem * p->size); } }
void log_level_down(log_t *log) { struct log_t *l = log; if (l->level > LOG_EMERG) { l->level--; loga(l,"down log level to %d", l->level); } }
void log_level_up(log_t *log) { struct log_t *l = log; if (l->level < LOG_PVERB) { l->level++; loga(l,"up log level to %d", l->level); } }
static void nc_print_run(struct env_master *env) { int status; struct utsname name; status = uname(&name); if (status < 0) { loga("nutcracker-%s master started on pid %d", NC_VERSION_STRING, env->pid); } else { loga("nutcracker-%s master built for %s %s %s started on pid %d", NC_VERSION_STRING, name.sysname, name.release, name.machine, env->pid); } loga("run, rabbit run / dig that hole, forget the sun / " "and when at last the work is done / don't sit down / " "it's time to dig another one"); }
static void dn_print_run(struct instance *nci) { int status; struct utsname name; status = uname(&name); if (status < 0) { loga("dynomite-%s started on pid %d", DN_VERSION_STRING, nci->pid); } else { loga("dynomite-%s built for %s %s %s started on pid %d", DN_VERSION_STRING, name.sysname, name.release, name.machine, nci->pid); } loga("run, rabbit run / dig that hole, forget the sun / " "and when at last the work is done / don't sit down / " "it's time to dig another one"); }
void log_level_up(void) { struct logger *l = &logger; if (l->level < LOG_PVERB) { l->level++; loga("up log level to %d", l->level); } }
void log_level_down(void) { struct logger *l = &logger; if (l->level > LOG_EMERG) { l->level--; loga("down log level to %d", l->level); } }
void slab_print(void) { uint8_t cid; /* slab class id */ struct slabclass *c; /* slab class */ loga("slab size %zu, slab hdr size %zu, item hdr size %zu, " "item chunk size %zu", settings.slab_size, SLAB_HDR_SIZE, ITEM_HDR_SIZE, settings.chunk_size); loga("index memory %zu, slab memory %zu, disk space %zu", 0, mspace, dspace); for (cid = SLABCLASS_MIN_ID; cid < nctable; cid++) { c = &ctable[cid]; loga("class %3"PRId8": items %7"PRIu32" size %7zu data %7zu " "slack %7zu", cid, c->nitem, c->size, c->size - ITEM_HDR_SIZE, c->slack); } }
void disktree_writer::write(std::ostream &out) { loga("Writing title index"); if (! stree_.m_root) { constexpr treesize fill{0}; for (int i = 0; i < 2; i++) zsr::serialize(out, fill); return; } recursive_treewrite(out, stree_.m_root, static_cast<zsr::offset>(out.tellp())); }
static void dmsg_parse_host_id(uint8_t *start, uint32_t len, struct string *dc, struct string *rack, struct dyn_token *token) { uint8_t *p, *q; uint8_t *dc_p, *rack_p, *token_p; uint32_t k, delimlen, dc_len, rack_len, token_len; char delim[] = "$$"; delimlen = 2; /* parse "dc$rack$token : don't support vnode for now */ //log_hexdump(LOG_VERB, start, len, "host_addr testing: "); p = start + len - 1; dc_p = NULL; rack_p = NULL; token_p = NULL; dc_len = rack_len = token_len = 0; for (k = 0; k < sizeof(delim)-1; k++) { q = dn_strrchr(p, start, delim[k]); switch (k) { case 0: //no support for vnode at this time token_p = q + 1; token_len = (uint32_t)(p - token_p + 1); parse_dyn_token(token_p, token_len, token); break; case 1: rack_p = q + 1; rack_len = (uint32_t)(p - rack_p + 1); string_copy(rack, rack_p, rack_len); break; default: NOT_REACHED(); } p = q - 1; } if (k != delimlen) { loga("Error: this should not happen"); return;// DN_ERROR; } dc_p = start; dc_len = len - (token_len + rack_len + 2); string_copy(dc, dc_p, dc_len); }
void nc_stacktrace(int skip_count) { void *stack[64]; char **symbols; int size, i, j; size = backtrace(stack, 64); symbols = backtrace_symbols(stack, size); if (symbols == NULL) { return; } skip_count++; /* skip the current frame also */ for (i = skip_count, j = 0; i < size; i++, j++) { loga("[%d] %s", j, symbols[i]); } free(symbols); }
/* 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; }
void signal_handler(int signo) { struct signal *sig; void (*action)(void); char *actionstr; bool done; for (sig = signals; sig->signo != 0; sig++) { if (sig->signo == signo) { break; } } ASSERT(sig->signo != 0); actionstr = ""; action = NULL; done = false; switch (signo) { case SIGUSR1: break; case SIGUSR2: break; case SIGTTIN: actionstr = ", up logging level"; action = log_level_up; break; case SIGTTOU: actionstr = ", down logging level"; action = log_level_down; break; case SIGHUP: actionstr = ", reopening log file"; action = log_reopen; break; case SIGINT: done = true; actionstr = ", exiting"; break; case SIGSEGV: dn_stacktrace(1); actionstr = ", core dumping"; raise(SIGSEGV); break; default: NOT_REACHED(); } loga("signal %d (%s) received%s", signo, sig->signame, actionstr); if (action != NULL) { action(); } if (done) { exit(1); } }
static void dn_print_done(void) { loga("done, rabbit done"); }
static struct ring_msg * dmsg_parse(struct dmsg *dmsg) { //rstatus_t status; uint8_t *p, *q, *start, *end, *pipe_p; uint8_t *host_id, *host_addr, *ts, *node_state; uint32_t k, delimlen, host_id_len, host_addr_len, ts_len, node_state_len; char delim[] = ",,,"; delimlen = 3; /* parse "host_id1,generation_ts1,host_state1,host_broadcast_address1|host_id2,generation_ts2,host_state2,host_broadcast_address2" */ /* host_id = dc-rack-token */ //p = dmsg->data + dmsg->mlen - 1; //p = dmsg->owner->pos + dmsg->owner->mlen - 1; p = dmsg->payload + dmsg->plen - 1; end = p; //start = dmsg->data; //start = dmsg->owner->pos; start = dmsg->payload; host_id = NULL; host_addr = NULL; ts = NULL; node_state = NULL; host_id_len = 0; host_addr_len = 0; ts_len = 0; node_state_len = 0; pipe_p = start; int count = 0; do { q = dn_strrchr(p, start, '|'); count++; p = q - 1; } while (q != NULL); struct ring_msg *ring_msg = create_ring_msg_with_size(count, true); if (ring_msg == NULL) { log_debug(LOG_ERR, "Error: unable to create a new ring msg!"); //we just drop this msg return NULL; } struct server_pool *sp = (struct server_pool *) dmsg->owner->owner->owner; ring_msg->sp = sp; ring_msg->cb = gossip_msg_peer_update; count = 0; //p = dmsg->data + dmsg->mlen - 1; p = dmsg->payload + dmsg->plen - 1; do { for (k = 0; k < sizeof(delim)-1; k++) { q = dn_strrchr(p, start, delim[k]); switch (k) { case 0: host_addr = q + 1; host_addr_len = (uint32_t)(p - host_addr + 1); break; case 1: node_state = q + 1; node_state_len = (uint32_t)(p - node_state + 1); break; case 2: ts = q + 1; ts_len = (uint32_t)(p - ts + 1); break; default: NOT_REACHED(); } p = q - 1; } if (k != delimlen) { loga("Error: this is insanely bad"); return NULL;// DN_ERROR; } pipe_p = dn_strrchr(p, start, '|'); if (pipe_p == NULL) { pipe_p = start; } else { pipe_p = pipe_p + 1; p = pipe_p - 2; } //host_id = dmsg->data; //host_id_len = dmsg->mlen - (host_addr_len + node_state_len + ts_len + 3); host_id = pipe_p; host_id_len = end - pipe_p - (host_addr_len + node_state_len + ts_len + 3) + 1; end = p; struct node *rnode = (struct node *) array_get(&ring_msg->nodes, count); dmsg_parse_host_id(host_id, host_id_len, &rnode->dc, &rnode->rack, &rnode->token); string_copy(&rnode->name, host_addr, host_addr_len); string_copy(&rnode->pname, host_addr, host_addr_len); //need to add port rnode->port = sp->d_port; rnode->is_local = false; rnode->is_seed = false; ts[ts_len] = '\0'; rnode->ts = atol(ts); node_state[node_state_len] = '\0'; rnode->state = (uint8_t) atoi(node_state); count++; } while (pipe_p != start); //TODOs: should move this outside dmsg_to_gossip(ring_msg); return ring_msg; }
void dyn_parse_rsp(struct msg *r) { if (log_loggable(LOG_VVERB)) { log_debug(LOG_VVERB, ":::::::::::::::::::::: In dyn_parse_rsp, start to process response :::::::::::::::::::::::: "); msg_dump(r); } bool done_parsing = false; struct mbuf *b = STAILQ_LAST(&r->mhdr, mbuf, next); if (dyn_parse_core(r)) { struct dmsg *dmsg = r->dmsg; struct conn *conn = r->owner; conn->same_dc = dmsg->same_dc; if (dmsg->type != DMSG_UNKNOWN && dmsg->type != DMSG_RES) { log_debug(LOG_DEBUG, "Resp parser: I got a dnode msg of type %d", dmsg->type); r->state = 0; r->result = MSG_PARSE_OK; r->dyn_state = DYN_DONE; return; } if (r->dyn_state == DYN_DONE && dmsg->bit_field == 1) { dmsg->owner->owner->dnode_secured = 1; r->owner->dnode_crypto_state = 1; r->dyn_state = DYN_POST_DONE; r->result = MSG_PARSE_REPAIR; if (dmsg->mlen > 1) { //Decrypt AES key dyn_rsa_decrypt(dmsg->data, aes_decrypted_buf); strncpy(r->owner->aes_key, aes_decrypted_buf, strlen(aes_decrypted_buf)); } if (dmsg->plen + b->pos <= b->last) { struct mbuf *decrypted_buf = mbuf_get(); if (decrypted_buf == NULL) { loga("Unable to obtain an mbuf for dnode msg's header!"); r->result = MSG_OOM_ERROR; return; } dyn_aes_decrypt(b->pos, dmsg->plen, decrypted_buf, r->owner->aes_key); b->pos = b->pos + dmsg->plen; r->pos = decrypted_buf->start; mbuf_copy(decrypted_buf, b->pos, mbuf_length(b)); mbuf_insert(&r->mhdr, decrypted_buf); mbuf_remove(&r->mhdr, b); mbuf_put(b); r->mlen = mbuf_length(decrypted_buf); return data_store_parse_rsp(r); } //Subtract already received bytes dmsg->plen -= b->last - b->pos; return; } else if (r->dyn_state == DYN_POST_DONE) { struct mbuf *last_buf = STAILQ_LAST(&r->mhdr, mbuf, next); if (last_buf->read_flip == 1) { data_store_parse_rsp(r); } else { r->result = MSG_PARSE_AGAIN; } return; } if (done_parsing) return; return data_store_parse_rsp(r); } //bad case if (log_loggable(LOG_DEBUG)) { log_debug(LOG_DEBUG, "Resp: bad message - cannot parse"); //fix me to do something msg_dump(r); } r->result = MSG_PARSE_AGAIN; }
void dyn_parse_req(struct msg *r) { if (log_loggable(LOG_VVERB)) { log_debug(LOG_VVERB, ":::::::::::::::::::::: In dyn_parse_req, start to process request :::::::::::::::::::::: "); msg_dump(r); } bool done_parsing = false; struct mbuf *b = STAILQ_LAST(&r->mhdr, mbuf, next); if (dyn_parse_core(r)) { struct dmsg *dmsg = r->dmsg; struct conn *conn = r->owner; conn->same_dc = dmsg->same_dc; if (dmsg->type != DMSG_UNKNOWN && dmsg->type != DMSG_REQ && dmsg->type != DMSG_REQ_FORWARD && dmsg->type != GOSSIP_SYN) { r->state = 0; r->result = MSG_PARSE_OK; r->dyn_state = DYN_DONE; return; } if (r->dyn_state == DYN_DONE && dmsg->bit_field == 1) { dmsg->owner->owner->dnode_secured = 1; r->owner->dnode_crypto_state = 1; r->dyn_state = DYN_POST_DONE; r->result = MSG_PARSE_REPAIR; if (dmsg->mlen > 1) { //Decrypt AES key dyn_rsa_decrypt(dmsg->data, aes_decrypted_buf); strncpy(r->owner->aes_key, aes_decrypted_buf, strlen(aes_decrypted_buf)); } if (dmsg->plen + b->pos <= b->last) { struct mbuf *decrypted_buf = mbuf_get(); if (decrypted_buf == NULL) { loga("Unable to obtain an mbuf for dnode msg's header!"); r->result = MSG_OOM_ERROR; return; } dyn_aes_decrypt(b->pos, dmsg->plen, decrypted_buf, r->owner->aes_key); b->pos = b->pos + dmsg->plen; r->pos = decrypted_buf->start; mbuf_copy(decrypted_buf, b->pos, mbuf_length(b)); mbuf_insert(&r->mhdr, decrypted_buf); mbuf_remove(&r->mhdr, b); mbuf_put(b); r->mlen = mbuf_length(decrypted_buf); data_store_parse_req(r); } //substract alraedy received bytes dmsg->plen -= b->last - b->pos; return; } else if (r->dyn_state == DYN_POST_DONE) { struct mbuf *last_buf = STAILQ_LAST(&r->mhdr, mbuf, next); if (last_buf->read_flip == 1) { data_store_parse_req(r); } else { r->result = MSG_PARSE_AGAIN; } return; } if (dmsg->type == GOSSIP_SYN) { //TODOs: need to address multi-buffer msg later dmsg->payload = b->pos; b->pos = b->pos + dmsg->plen; r->pos = b->pos; done_parsing = true; } if (done_parsing) return; return data_store_parse_req(r); } //bad case if (log_loggable(LOG_VVERB)) { log_debug(LOG_VVERB, "Bad or splitted message"); //fix me to do something msg_dump(r); } r->result = MSG_PARSE_AGAIN; }
static rstatus_t dn_get_options(int argc, char **argv, struct instance *nci) { int c, value; // char str[128]; opterr = 0; for (;;) { c = getopt_long(argc, argv, short_options, long_options, NULL); if (c == -1) { /* no more options */ break; } switch (c) { case 'h': show_version = 1; show_help = 1; break; case 'V': show_version = 1; break; case 't': test_conf = 1; nci->log_level = 11; break; case 'd': daemonize = 1; break; case 'D': describe_stats = 1; show_version = 1; break; case 'v': value = dn_atoi(optarg, strlen(optarg)); if (value < 0) { log_stderr("dynomite: option -v requires a number"); return DN_ERROR; } nci->log_level = value; break; case 'o': nci->log_filename = optarg; break; case 'c': nci->conf_filename = optarg; break; case 's': value = dn_atoi(optarg, strlen(optarg)); if (value < 0) { log_stderr("dynomite: option -s requires a number"); return DN_ERROR; } if (!dn_valid_port(value)) { log_stderr("dynomite: option -s value %d is not a valid " "port", value); return DN_ERROR; } nci->stats_port = (uint16_t)value; break; case 'i': value = dn_atoi(optarg, strlen(optarg)); if (value < 0) { log_stderr("dynomite: option -i requires a number"); return DN_ERROR; } nci->stats_interval = value; break; case 'a': nci->stats_addr = optarg; break; case 'p': nci->pid_filename = optarg; break; case 'm': value = dn_atoi(optarg, strlen(optarg)); if (value <= 0) { log_stderr("dynomite: option -m requires a non-zero number"); return DN_ERROR; } if (value < DN_MBUF_MIN_SIZE || value > DN_MBUF_MAX_SIZE) { log_stderr("dynomite: mbuf chunk size must be between %zu and" " %zu bytes", DN_MBUF_MIN_SIZE, DN_MBUF_MAX_SIZE); return DN_ERROR; } nci->mbuf_chunk_size = (size_t)value; break; case 'n': sampling_freq = dn_atoi(optarg,strlen(optarg)); loga("Sampling freq %d", sampling_freq); break; case '?': switch (optopt) { case 'o': case 'c': case 'p': log_stderr("dynomite: option -%c requires a file name", optopt); break; case 'm': case 'v': case 's': case 'i': log_stderr("dynomite: option -%c requires a number", optopt); break; case 'a': log_stderr("dynomite: option -%c requires a string", optopt); break; default: log_stderr("dynomite: invalid option -- '%c'", optopt); break; } return DN_ERROR; default: log_stderr("dynomite: invalid option -- '%c'", optopt); return DN_ERROR; } } return DN_OK; }
static bool dyn_parse_core(struct msg *r) { struct dmsg *dmsg; struct mbuf *b; uint8_t *p, *token; uint8_t ch = ' '; uint64_t num = 0; dyn_state = r->dyn_state; if (log_loggable(LOG_DEBUG)) { log_debug(LOG_DEBUG, "dyn_state: %d", r->dyn_state); } if (r->dyn_state == DYN_DONE || r->dyn_state == DYN_POST_DONE) return true; b = STAILQ_LAST(&r->mhdr, mbuf, next); dmsg = r->dmsg; if (dmsg == NULL) { r->dmsg = dmsg_get(); dmsg = r->dmsg; dmsg->owner = r; if (dmsg == NULL) {//should track this as a dropped message loga("unable to create a new dmsg"); goto error; //should count as OOM error } } token = NULL; for (p = r->pos; p < b->last; p++) { ch = *p; switch (dyn_state) { case DYN_START: if (log_loggable(LOG_DEBUG)) { log_debug(LOG_DEBUG, "DYN_START"); } if (ch != ' ' && ch != '$') { break; } if (ch == ' ') { if (token == NULL) token = p; break; } if (ch == '$') { if (p + 5 < b->last) { if ((*(p+1) == '2') && (*(p+2) == '0') && (*(p+3) == '1') && (*(p+4) == '4') && (*(p+5) == '$')) { dyn_state = DYN_MAGIC_STRING; p += 5; } else { //goto skip; token = NULL; //reset } } else { goto split; } } else { loga("Facing a weird char %c", p); //goto skip; token = NULL; //reset } break; case DYN_MAGIC_STRING: if (log_loggable(LOG_DEBUG)) { log_debug(LOG_DEBUG, "DYN_MAGIC_STRING"); } if (ch == ' ') { dyn_state = DYN_MSG_ID; num = 0; break; } else { //loga("char is '%c %c %c %c'", *(p-2), *(p-1), ch, *(p+1)); token = NULL; loga("Facing a weird char %c", p); //goto skip; dyn_state = DYN_START; } break; case DYN_MSG_ID: if (log_loggable(LOG_DEBUG)) { log_debug(LOG_DEBUG, "DYN_MSG_ID"); log_debug(LOG_DEBUG, "num = %d", num); } if (isdigit(ch)) { num = num*10 + (ch - '0'); } else if (ch == ' ' && isdigit(*(p-1))) { if (log_loggable(LOG_DEBUG)) { log_debug(LOG_DEBUG, "MSG ID : %d", num); } dmsg->id = num; dyn_state = DYN_TYPE_ID; num = 0; } else { //loga("char is '%c %c %c %c'", *(p-2), *(p-1), ch, *(p+1)); //goto skip; token = NULL; //reset dyn_state = DYN_START; if (ch == '$') p -= 1; } break; case DYN_TYPE_ID: if (log_loggable(LOG_DEBUG)) { log_debug(LOG_DEBUG, "DYN_TYPE_ID: num = %d", num); } if (isdigit(ch)) { num = num*10 + (ch - '0'); } else if (ch == ' ' && isdigit(*(p-1))) { if (log_loggable(LOG_DEBUG)) { log_debug(LOG_DEBUG, "Type Id: %d", num); } dmsg->type = num; dyn_state = DYN_BIT_FIELD; num = 0; } else { //loga("char is '%c %c %c %c'", *(p-2), *(p-1), ch, *(p+1)); token = NULL; dyn_state = DYN_START; if (ch == '$') p -= 1; } break; case DYN_BIT_FIELD: if (log_loggable(LOG_DEBUG)) { log_debug(LOG_DEBUG, "DYN_BIT_FIELD, num = %d", num); } if (isdigit(ch)) { num = num*10 + (ch - '0'); } else if (ch == ' ' && isdigit(*(p-1))) { if (log_loggable(LOG_DEBUG)) { log_debug(LOG_DEBUG, "DYN_BIT_FIELD : %d", num); } dmsg->bit_field = num & 0xF; dyn_state = DYN_VERSION; num = 0; } else { token = NULL; //loga("char is '%c %c %c %c'", *(p-2), *(p-1), ch, *(p+1)); dyn_state = DYN_START; if (ch == '$') p -= 1; } break; case DYN_VERSION: if (log_loggable(LOG_DEBUG)) { log_debug(LOG_DEBUG, "DYN_VERSION: num = %d", num); } if (isdigit(ch)) { num = num*10 + (ch - '0'); } else if (ch == ' ' && isdigit(*(p-1))) { if (log_loggable(LOG_DEBUG)) { log_debug(LOG_DEBUG, "VERSION : %d", num); } dmsg->version = num; dyn_state = DYN_SAME_DC; num = 0; } else { token = NULL; //loga("char is '%c %c %c %c'", *(p-2), *(p-1), ch, *(p+1)); dyn_state = DYN_START; if (ch == '$') p -= 1; } break; case DYN_SAME_DC: if (isdigit(ch)) { dmsg->same_dc = ch - '0'; if (log_loggable(LOG_DEBUG)) { log_debug(LOG_DEBUG, "DYN_SAME_DC %d", dmsg->same_dc); } } else if (ch == ' ' && isdigit(*(p-1))) { dyn_state = DYN_DATA_LEN; num = 0; } else { token = NULL; //loga("char is '%c %c %c %c'", *(p-2), *(p-1), ch, *(p+1)); dyn_state = DYN_START; if (ch == '$') p -= 1; } break; case DYN_DATA_LEN: if (log_loggable(LOG_DEBUG)) { log_debug(LOG_DEBUG, "DYN_DATA_LEN: num = %d", num); } if (ch == '*') { break; } else if (isdigit(ch)) { num = num*10 + (ch - '0'); } else if (ch == ' ' && isdigit(*(p-1))) { if (log_loggable(LOG_DEBUG)) { log_debug(LOG_DEBUG, "Data len: %d", num); } dmsg->mlen = num; dyn_state = DYN_DATA; num = 0; } else { token = NULL; //loga("char is '%c %c %c %c'", *(p-2), *(p-1), ch, *(p+1)); dyn_state = DYN_START; if (ch == '$') p -= 1; } break; case DYN_DATA: if (log_loggable(LOG_DEBUG)) { log_debug(LOG_DEBUG, "DYN_DATA"); } if (p + dmsg->mlen < b->last) { dmsg->data = p; p += dmsg->mlen - 1; dyn_state = DYN_SPACES_BEFORE_PAYLOAD_LEN; } else { //loga("char is '%c %c %c %c'", *(p-2), *(p-1), ch, *(p+1)); goto split; } break; case DYN_SPACES_BEFORE_PAYLOAD_LEN: if (log_loggable(LOG_DEBUG)) { log_debug(LOG_DEBUG, "DYN_SPACES_BEFORE_PAYLOAD_LEN"); } if (ch == ' ') { break; } else if (ch == '*') { dyn_state = DYN_PAYLOAD_LEN; num = 0; } break; case DYN_PAYLOAD_LEN: if (isdigit(ch)) { num = num*10 + (ch - '0'); } else if (ch == CR) { if (log_loggable(LOG_DEBUG)) { log_debug(LOG_DEBUG, "Payload len: %d", num); } dmsg->plen = num; num = 0; dyn_state = DYN_CRLF_BEFORE_DONE; } else { token = NULL; dyn_state = DYN_START; if (ch == '$') p -= 1; } break; case DYN_CRLF_BEFORE_DONE: if (log_loggable(LOG_DEBUG)) { log_debug(LOG_DEBUG, "DYN_CRLF_BEFORE_DONE"); } if (*p == LF) { dyn_state = DYN_DONE; } else { token = NULL; dyn_state = DYN_START; if (ch == '$') p -= 1; } break; case DYN_DONE: if (log_loggable(LOG_DEBUG)) { log_debug(LOG_DEBUG, "DYN_DONE"); } r->pos = p; dmsg->payload = p; r->dyn_state = DYN_DONE; b->pos = p; goto done; break; default: NOT_REACHED(); break; } } if (log_loggable(LOG_DEBUG)) { log_debug(LOG_DEBUG, "Not fully parsed yet!!!!!!"); } split: //this is an attempt recovery when we got a bad message //we try to look for the start the next good one and throw away the bad part if (r->dyn_state == DYN_START) { r->result = MSG_PARSE_AGAIN; if (b->last == b->end) { struct mbuf *nbuf = mbuf_get(); if (nbuf == NULL) { loga("Unable to obtain a new mbuf for replacement!"); mbuf_put(b); nbuf = mbuf_get(); mbuf_insert_head(&r->mhdr, nbuf); r->pos = nbuf->pos; return false; } //replacing the bad mbuf with a new and empty mbuf mbuf_insert(&r->mhdr, nbuf); mbuf_remove(&r->mhdr, b); mbuf_put(b); r->pos = nbuf->pos; return false; } else { //split it and throw away the bad portion struct mbuf *nbuf; nbuf = mbuf_split(&r->mhdr, r->pos, NULL, NULL); if (nbuf == NULL) { return DN_ENOMEM; } mbuf_insert(&r->mhdr, nbuf); mbuf_remove(&r->mhdr, b); r->pos = nbuf->pos; return false; } } if (mbuf_length(b) == 0 || b->last == b->end) { if (log_loggable(LOG_DEBUG)) { log_debug(LOG_DEBUG, "Would this case ever happen?"); } r->result = MSG_PARSE_AGAIN; return false; } if (r->pos == b->last) { if (log_loggable(LOG_DEBUG)) { log_debug(LOG_DEBUG, "Forward to reading the new block of data"); } r->dyn_state = DYN_START; r->result = MSG_PARSE_AGAIN; token = NULL; return false; } if (log_loggable(LOG_VVERB)) { log_debug(LOG_VVERB, "in split"); } r->dyn_state = DYN_START; r->pos = token; r->result = MSG_PARSE_REPAIR; if (log_loggable(LOG_VVERB)) { log_hexdump(LOG_VVERB, b->pos, mbuf_length(b), "split and inspecting req %"PRIu64" " "res %d type %d state %d", r->id, r->result, r->type, r->dyn_state); log_hexdump(LOG_VVERB, b->start, b->last - b->start, "split and inspecting full req %"PRIu64" " "res %d type %d state %d", r->id, r->result, r->type, r->dyn_state); } return false; done: r->pos = p; dmsg->source_address = r->owner->addr; if (log_loggable(LOG_VVERB)) { log_debug(LOG_VVERB, "at done with p at %d", p); log_hexdump(LOG_VVERB, r->pos, b->last - r->pos, "done and inspecting req %"PRIu64" " "res %d type %d state %d", r->id, r->result, r->type, r->dyn_state); log_hexdump(LOG_VVERB, b->start, b->last - b->start, "inspecting req %"PRIu64" " "res %d type %d state %d", r->id, r->result, r->type, r->dyn_state); } return true; error: log_debug(LOG_ERR, "at error for state %d and c %c", dyn_state, *p); r->result = MSG_PARSE_ERROR; r->pos = p; errno = EINVAL; if (log_loggable(LOG_ERR)) { log_hexdump(LOG_ERR, b->pos, mbuf_length(b), "parsed bad req %"PRIu64" " "res %d type %d state %d", r->id, r->result, r->type, dyn_state); log_hexdump(LOG_ERR, p, b->last - p, "inspecting req %"PRIu64" " "res %d type %d state %d", r->id, r->result, r->type, dyn_state); } r->dyn_state = dyn_state; return false; }