static void client_handler(struct mg_connection *conn, int ev, void *p) { struct mbuf *io = &conn->recv_mbuf; (void) p; if (ev == MG_EV_CONNECT) { if (conn->flags & MG_F_CLOSE_IMMEDIATELY) { printf("%s\n", "Error connecting to server!"); exit(EXIT_FAILURE); } printf("%s\n", "Connected to server. Type a message and press enter."); } else if (ev == MG_EV_RECV) { if (conn->flags & MG_F_USER_1) { // Received data from the stdin, forward it to the server struct mg_connection *c = (struct mg_connection *) conn->user_data; mg_send(c, io->buf, io->len); mbuf_remove(io, io->len); } else { // Received data from server connection, print it fwrite(io->buf, io->len, 1, stdout); mbuf_remove(io, io->len); } } else if (ev == MG_EV_CLOSE) { // Connection has closed, most probably cause server has stopped exit(EXIT_SUCCESS); } }
void conn_handler(struct mg_connection *nc, int ev, void *arg) { struct conn_ctx *ctx = (struct conn_ctx *) nc->user_data; struct mbuf *io = &nc->recv_mbuf; switch (ev) { case NS_POLL: break; case NS_CONNECT: { printf("connected\n"); ctx->state = CONNECTED; do_send(nc); break; } case NS_RECV: ctx->num_received += io->len; mbuf_remove(io, io->len); break; case NS_SEND: { do_send(nc); ctx->num_sent += *((int *) arg); break; } case NS_CLOSE: { printf("disconnected\n"); ctx->state = DISCONNECTED; break; } } }
void mg_lwip_ssl_send(struct mg_connection *nc) { if (nc->sock == INVALID_SOCKET) { DBG(("%p invalid socket", nc)); return; } struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; /* It's ok if the buffer is empty. Return value of 0 may also be valid. */ int len = cs->last_ssl_write_size; if (len == 0) { len = MIN(MG_LWIP_SSL_IO_SIZE, nc->send_mbuf.len); } int ret = SSL_write(nc->ssl, nc->send_mbuf.buf, len); int err = SSL_get_error(nc->ssl, ret); DBG(("%p SSL_write %u = %d, %d", nc, len, ret, err)); if (ret > 0) { mbuf_remove(&nc->send_mbuf, ret); mbuf_trim(&nc->send_mbuf); cs->last_ssl_write_size = 0; } else if (ret < 0) { /* This is tricky. We must remember the exact data we were sending to retry * exactly the same send next time. */ cs->last_ssl_write_size = len; } if (err == SSL_ERROR_NONE) { nc->flags &= ~MG_F_WANT_WRITE; } else if (err == SSL_ERROR_WANT_WRITE) { nc->flags |= MG_F_WANT_WRITE; } else { LOG(LL_ERROR, ("SSL write error: %d", err)); mg_lwip_post_signal(MG_SIG_CLOSE_CONN, nc); } }
static void mg_lwip_tcp_write(struct mg_connection *nc) { struct tcp_pcb *tpcb = (struct tcp_pcb *) nc->sock; size_t len; if (nc->sock == INVALID_SOCKET) { DBG(("%p tcp_write invalid socket %d", nc, nc->err)); return; } len = MIN(tpcb->mss, MIN(nc->send_mbuf.len, tpcb->snd_buf)); if (len == 0) { DBG(("%p no buf avail %u %u %u %p %p", nc, tpcb->acked, tpcb->snd_buf, tpcb->snd_queuelen, tpcb->unsent, tpcb->unacked)); tcp_output(tpcb); return; } nc->err = tcp_write(tpcb, nc->send_mbuf.buf, len, TCP_WRITE_FLAG_COPY); tcp_output(tpcb); DBG(("%p tcp_write %u = %d", nc, len, nc->err)); if (nc->err != ERR_OK) { if (nc->err != ERR_MEM) { system_os_post(MG_TASK_PRIORITY, MG_SIG_CLOSE_CONN, (uint32_t) nc); } /* * We ignore ERR_MEM because memory will be freed up when the data is sent * and we'll retry. */ } else { mbuf_remove(&nc->send_mbuf, len); mbuf_trim(&nc->send_mbuf); } }
static int console_send_file(struct v7 *v7, struct cache *cache) { int ret = 0; char *logs = NULL; size_t size = 0; if (cache->file_names.len != 0) { logs = cs_read_file(cache->file_names.buf, &size); if (logs == NULL) { LOG(LL_ERROR, ("Failed to read from %s", cache->file_names.buf)); ret = -1; goto clean; } console_make_clubby_call(v7, logs); remove(cache->file_names.buf); mbuf_remove(&cache->file_names, FILENAME_LEN); } clean: if (logs != NULL) { free(logs); } return ret; }
void cc3200_console_cloud_putc(char c) { if (s_cctx.in_console || !s_cctx.initialized) return; s_cctx.in_console = 1; /* If console is overfull, drop old message(s). */ int max_buf = get_cfg()->console.mem_cache_size; while (s_cctx.buf.len >= max_buf) { int l = cc3200_console_next_msg_len(); if (l == 0) { l = s_cctx.buf.len; s_cctx.msg_in_progress = 0; } mbuf_remove(&s_cctx.buf, l); } /* Construct valid JSON from the get-go. */ if (!s_cctx.msg_in_progress) { /* Skip empty lines */ if (c == '\n') goto out; mbuf_append(&s_cctx.buf, "{\"msg\":\"", 8); s_cctx.msg_in_progress = 1; } if (c == '"' || c == '\\') { mbuf_append(&s_cctx.buf, "\\", 1); } if (c >= 0x20) mbuf_append(&s_cctx.buf, &c, 1); if (c == '\n') { mbuf_append(&s_cctx.buf, "\"}\n", 3); s_cctx.msg_in_progress = 0; } out: s_cctx.in_console = 0; }
void sj_conf_emit_f_cb(struct mbuf *data, void *param) { FILE **fp = (FILE **) param; if (*fp != NULL && fwrite(data->buf, 1, data->len, *fp) != data->len) { LOG(LL_ERROR, ("Error writing file\n")); fclose(*fp); *fp = NULL; } mbuf_remove(data, data->len); }
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); } if (dyn_parse_core(r)) { struct dmsg *dmsg = r->dmsg; struct mbuf *b = STAILQ_LAST(&r->mhdr, mbuf, next); 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; } //check whether we need to decrypt the payload if (dmsg->bit_field == 1) { //dmsg->owner->owner->dnode_secured = 1; struct mbuf *decrypted_buf = mbuf_get(); if (decrypted_buf == NULL) { log_debug(LOG_INFO, "Unable to obtain an mbuf for dnode msg's header!"); r->result = MSG_OOM_ERROR; return; } //Dont need to decrypt AES key - pull it out from the conn dyn_aes_decrypt(dmsg->payload, 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); } if (r->redis) { return redis_parse_rsp(r); } return memcache_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 mbuf_deinit(void) { while (!STAILQ_EMPTY(&free_mbufq)) { struct mbuf *mbuf = STAILQ_FIRST(&free_mbufq); mbuf_remove(&free_mbufq, mbuf); mbuf_free(mbuf); nfree_mbufq--; } ASSERT(nfree_mbufq == 0); }
void mgos_uart_hal_dispatch_tx_top(struct mgos_uart_state *us) { struct cc32xx_uart_state *ds = (struct cc32xx_uart_state *) us->dev_data; struct mbuf *txb = &us->tx_buf; size_t len = 0; while (len < txb->len && MAP_UARTSpaceAvail(ds->base)) { HWREG(ds->base + UART_O_DR) = *(txb->buf + len); len++; } mbuf_remove(txb, len); us->stats.tx_bytes += len; MAP_UARTIntClear(ds->base, UART_TX_INTS); }
static void ev_handler(struct mg_connection *nc, int ev, void *p) { struct mbuf *io = &nc->recv_mbuf; (void) p; switch (ev) { case MG_EV_RECV: mg_send(nc, io->buf, io->len); // Echo message back mbuf_remove(io, io->len); // Discard message from recv buffer break; default: break; } }
void mbuf_deinit(void) { while (!STAILQ_EMPTY(&free_mbufq)) { struct mbuf *mbuf = STAILQ_FIRST(&free_mbufq); mbuf_remove(&free_mbufq, mbuf); mbuf_free(mbuf); nfree_mbufq--; #if 1 //shenzheng 2015-3-23 common #ifdef NC_DEBUG_LOG ntotal_mbuf--; #endif #endif //shenzheng 2015-3-23 common } #if 1 //shenzheng 2015-5-13 proxy administer while (!STAILQ_EMPTY(&free_mbufq_proxy_adm)) { struct mbuf *mbuf = STAILQ_FIRST(&free_mbufq_proxy_adm); mbuf_remove(&free_mbufq_proxy_adm, mbuf); mbuf_free(mbuf); nfree_mbufq_proxy_adm--; #ifdef NC_DEBUG_LOG ntotal_mbuf_proxy_adm--; #endif } #endif //shenzheng 2015-5-13 proxy administer ASSERT(nfree_mbufq == 0); #if 1 //shenzheng 2015-3-23 common #ifdef NC_DEBUG_LOG ASSERT(ntotal_mbuf == 0); #endif #endif //shenzheng 2015-3-23 common }
rstatus_t conn_close(struct conn *conn) { rstatus_t status; struct mbuf *mbuf, *nbuf; /* current and next mbuf */ if (conn->fd < 0) { conn_put(conn); return NC_OK; } if (!STAILQ_EMPTY(&conn->recv_queue)) { log_warn("close conn %d discard data in send_queue", conn->fd); for (mbuf = STAILQ_FIRST(&conn->recv_queue); mbuf != NULL; mbuf = nbuf) { nbuf = STAILQ_NEXT(mbuf, next); mbuf_remove(&conn->recv_queue, mbuf); mbuf_put(mbuf); } } if (!STAILQ_EMPTY(&conn->send_queue)) { log_warn("close conn %d discard data in send_queue", conn->fd); for (mbuf = STAILQ_FIRST(&conn->send_queue); mbuf != NULL; mbuf = nbuf) { nbuf = STAILQ_NEXT(mbuf, next); mbuf_remove(&conn->send_queue, mbuf); mbuf_put(mbuf); } } status = close(conn->fd); if (status < 0) { log_error("close c %d failed, ignored: %s", conn->fd, strerror(errno)); } conn->fd = -1; conn_put(conn); return NC_OK; }
static void mg_lwip_send_more(struct mg_connection *nc) { struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; if (nc->sock == INVALID_SOCKET || cs->pcb.tcp == NULL) { DBG(("%p invalid socket", nc)); return; } int num_written = mg_lwip_tcp_write(nc, nc->send_mbuf.buf, nc->send_mbuf.len); DBG(("%p mg_lwip_tcp_write %u = %d", nc, nc->send_mbuf.len, num_written)); if (num_written == 0) return; if (num_written < 0) { mg_lwip_post_signal(MG_SIG_CLOSE_CONN, nc); } mbuf_remove(&nc->send_mbuf, num_written); mbuf_trim(&nc->send_mbuf); }
static void forward_body(struct peer *src, struct peer *dst) { struct mbuf *src_io = &src->nc->recv_mbuf; if (src->body_sent < src->body_len) { size_t to_send = src->body_len - src->body_sent; if (src_io->len < to_send) { to_send = src_io->len; } ns_send(dst->nc, src_io->buf, to_send); src->body_sent += to_send; mbuf_remove(src_io, to_send); } #ifdef DEBUG write_log("forward_body %p (ka=%d) -> %p sent %d of %d\n", src->nc, src->flags.keep_alive, dst->nc, src->body_sent, src->body_len); #endif }
static void ns_write_to_socket(struct ns_connection *conn) { struct mbuf *io = &conn->send_mbuf; int n = 0; assert(io->len > 0); #ifdef NS_ENABLE_SSL if (conn->ssl != NULL) { if (conn->flags & NSF_SSL_HANDSHAKE_DONE) { n = SSL_write(conn->ssl, io->buf, io->len); if (n <= 0) { int ssl_err = ns_ssl_err(conn, n); if (ssl_err == SSL_ERROR_WANT_READ || ssl_err == SSL_ERROR_WANT_WRITE) { return; /* Call us again */ } else { conn->flags |= NSF_CLOSE_IMMEDIATELY; } } else { /* Successful SSL operation, clear off SSL wait flags */ conn->flags &= ~(NSF_WANT_READ | NSF_WANT_WRITE); } } else { ns_ssl_begin(conn); return; } } else #endif { n = (int) NS_SEND_FUNC(conn->sock, io->buf, io->len, 0); } DBG(("%p %d bytes -> %d", conn, n, conn->sock)); if (ns_is_error(n)) { conn->flags |= NSF_CLOSE_IMMEDIATELY; } else if (n > 0) { #ifndef NS_DISABLE_FILESYSTEM /* LCOV_EXCL_START */ if (conn->mgr->hexdump_file != NULL) { ns_hexdump_connection(conn, conn->mgr->hexdump_file, n, NS_SEND); } /* LCOV_EXCL_STOP */ #endif mbuf_remove(io, n); } ns_call(conn, NS_SEND, &n); }
static void context_remove_data(struct update_context *ctx, size_t len) { LOG(LL_DEBUG, ("Removing %d bytes", len)); if (ctx->unprocessed.len != 0) { /* Consumed data from unprocessed*/ mbuf_remove(&ctx->unprocessed, len); ctx->data = ctx->unprocessed.buf; ctx->data_len = ctx->unprocessed.len; LOG(LL_DEBUG, ("Removed %d bytes from cached data", len)); } else { /* Consumed received data */ ctx->data = ctx->data + len; ctx->data_len -= len; } LOG(LL_DEBUG, ("Data size: %u bytes", ctx->data_len)); }
static void mg_lwip_send_more(struct mg_connection *nc) { struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; if (nc->sock == INVALID_SOCKET || cs->pcb.tcp == NULL) { DBG(("%p invalid socket", nc)); return; } struct tcp_pcb *tpcb = cs->pcb.tcp; int num_written = mg_lwip_tcp_write(tpcb, nc->send_mbuf.buf, nc->send_mbuf.len); DBG(("%p mg_lwip_tcp_write %u = %d", nc, nc->send_mbuf.len, num_written)); if (num_written == 0) return; if (num_written < 0) { system_os_post(MG_TASK_PRIORITY, MG_SIG_CLOSE_CONN, (uint32_t) nc); } mbuf_remove(&nc->send_mbuf, num_written); mbuf_trim(&nc->send_mbuf); }
static void prompt_handler(struct ns_connection *nc, int ev, void *ev_data) { size_t i; struct mbuf *io = &nc->recv_mbuf; switch (ev) { case NS_RECV: for (i = 0; i < io->len; i++) { sj_prompt_process_char(io->buf[i]); if (io->buf[i] == '\n') { sj_prompt_process_char('\r'); } } mbuf_remove(io, io->len); break; case NS_CLOSE: sj_please_quit = 1; break; } }
void mgos_uart_hal_dispatch_tx_top(struct mgos_uart_state *us) { int uart_no = us->uart_no; struct mbuf *txb = &us->tx_buf; uint32_t txn = 0; /* TX */ if (txb->len > 0) { while (txb->len > 0) { size_t tx_av = 128 - esp_uart_tx_fifo_len(uart_no); size_t len = MIN(txb->len, tx_av); if (len == 0) break; for (size_t i = 0; i < len; i++) { esp_uart_tx_byte(uart_no, *(txb->buf + i)); } txn += len; mbuf_remove(txb, len); } us->stats.tx_bytes += txn; } }
void cc3200_console_cloud_push() { if (s_cctx.buf.len == 0 || !s_cctx.initialized) return; int l = cc3200_console_next_msg_len(); if (l == 0) return; // Only send full messages. struct clubby *c = sj_clubby_get_global(); if (c == NULL || !sj_clubby_is_connected(c)) { /* If connection drops, do not wait for reply as it may never arrive. */ s_cctx.request_in_flight = 0; return; } if (s_cctx.request_in_flight || !sj_clubby_can_send(c)) return; s_cctx.request_in_flight = 1; s_cctx.in_console = 1; sj_clubby_call(c, NULL, "/v1/Log.Log", mg_mk_str_n(s_cctx.buf.buf, l - 1), 0, clubby_cb, NULL); mbuf_remove(&s_cctx.buf, l); if (s_cctx.buf.len == 0) mbuf_trim(&s_cctx.buf); s_cctx.in_console = 0; }
static void server_handler(struct mg_connection *nc, int ev, void *p) { (void) p; if (ev == MG_EV_RECV) { // Push received message to all ncections struct mbuf *io = &nc->recv_mbuf; struct mg_connection *c; for (c = mg_next(nc->mgr, NULL); c != NULL; c = mg_next(nc->mgr, c)) { if (!(c->flags |= MG_F_USER_2)) continue; // Skip non-client connections mg_send(c, io->buf, io->len); } mbuf_remove(io, io->len); } else if (ev == MG_EV_ACCEPT) { char addr[32]; mg_sock_addr_to_str(p, addr, sizeof(addr), MG_SOCK_STRINGIFY_IP | MG_SOCK_STRINGIFY_PORT); printf("New client connected from %s\n", addr); } }
static void mg_lwip_ssl_send(struct mg_connection *nc) { if (nc->sock == INVALID_SOCKET) { DBG(("%p invalid socket", nc)); return; } /* It's ok if the buffer is empty. Return value of 0 may also be valid. */ int ret = SSL_write(nc->ssl, nc->send_mbuf.buf, nc->send_mbuf.len); int err = SSL_get_error(nc->ssl, ret); DBG(("%p SSL_write %u = %d, %d", nc, nc->send_mbuf.len, ret, err)); if (ret > 0) { mbuf_remove(&nc->send_mbuf, ret); mbuf_trim(&nc->send_mbuf); } if (err == SSL_ERROR_NONE) { nc->flags &= ~MG_F_WANT_WRITE; } else if (err == SSL_ERROR_WANT_WRITE) { nc->flags |= MG_F_WANT_WRITE; } else { LOG(LL_ERROR, ("SSL write error: %d", err)); system_os_post(MG_TASK_PRIORITY, MG_SIG_CLOSE_CONN, (uint32_t) nc); } }
static rstatus_t conn_send_queue(struct conn *conn) { struct mbuf *mbuf, *nbuf; /* current and next mbuf */ size_t mlen; /* current mbuf data length */ ssize_t n; for (mbuf = STAILQ_FIRST(&conn->send_queue); mbuf != NULL; mbuf = nbuf) { nbuf = STAILQ_NEXT(mbuf, next); if (mbuf_empty(mbuf)) { continue; } mlen = mbuf_length(mbuf); n = conn_send_buf(conn, mbuf->pos, mlen); if (n < 0) { if (n == NC_EAGAIN) { return NC_OK; } return NC_ERROR; } mbuf->pos += n; if (n < mlen) { ASSERT(mbuf->pos < mbuf->end); return NC_OK; } ASSERT(mbuf->pos == mbuf->last); mbuf_remove(&conn->send_queue, mbuf); mbuf_put(mbuf); } conn->send_ready = 0; return NC_OK; }
/* 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; }
/* * copy one response from src to dst * return bytes copied * */ static rstatus_t memcache_copy_bulk(struct msg *dst, struct msg *src) { struct mbuf *mbuf, *nbuf; uint8_t *p; uint32_t len = 0; uint32_t bytes = 0; uint32_t i = 0; for (mbuf = STAILQ_FIRST(&src->mhdr); mbuf && mbuf_empty(mbuf); mbuf = STAILQ_FIRST(&src->mhdr)) { mbuf_remove(&src->mhdr, mbuf); mbuf_put(mbuf); } mbuf = STAILQ_FIRST(&src->mhdr); if (mbuf == NULL) { return NC_OK; /* key not exists */ } p = mbuf->pos; /* get : VALUE key 0 len\r\nval\r\n */ /* gets: VALUE key 0 len cas\r\nval\r\n */ ASSERT(*p == 'V'); for (i = 0; i < 3; i++) { /* eat 'VALUE key 0 ' */ for (; *p != ' ';) { p++; } p++; } len = 0; for (; p < mbuf->last && isdigit(*p); p++) { len = len * 10 + (uint32_t)(*p - '0'); } for (; p < mbuf->last && ('\r' != *p); p++) { /* eat cas for gets */ ; } len += CRLF_LEN * 2; len += (p - mbuf->pos); bytes = len; /* copy len bytes to dst */ for (; mbuf;) { if (mbuf_length(mbuf) <= len) { /* steal this mbuf from src to dst */ nbuf = STAILQ_NEXT(mbuf, next); mbuf_remove(&src->mhdr, mbuf); mbuf_insert(&dst->mhdr, mbuf); len -= mbuf_length(mbuf); mbuf = nbuf; } else { /* split it */ nbuf = mbuf_get(); if (nbuf == NULL) { return NC_ENOMEM; } mbuf_copy(nbuf, mbuf->pos, len); mbuf_insert(&dst->mhdr, nbuf); mbuf->pos += len; break; } } dst->mlen += bytes; src->mlen -= bytes; log_debug(LOG_VVERB, "memcache_copy_bulk copy bytes: %d", bytes); return NC_OK; }
static void forward(struct conn_data *conn, struct http_message *hm, struct peer *src_peer, struct peer *dst_peer) { struct ns_connection *src = src_peer->nc; struct ns_connection *dst = dst_peer->nc; struct mbuf *io = &src->recv_mbuf; int i; int is_request = (src_peer == &conn->client); src_peer->body_len = hm->body.len; struct http_backend *be = conn->be_conn->be; if (is_request) { /* Write rewritten request line. */ size_t trim_len = strlen(be->uri_prefix); ns_printf(dst, "%.*s%s%.*s\r\n", (int) (hm->uri.p - io->buf), io->buf, be->uri_prefix_replacement, (int) (hm->proto.p + hm->proto.len - (hm->uri.p + trim_len)), hm->uri.p + trim_len); } else { /* Reply line goes without modification */ ns_printf(dst, "%.*s %d %.*s\r\n", (int) hm->proto.len, hm->proto.p, (int) hm->resp_code, (int) hm->resp_status_msg.len, hm->resp_status_msg.p); } /* Headers. */ for (i = 0; i < NS_MAX_HTTP_HEADERS && hm->header_names[i].len > 0; i++) { struct ns_str hn = hm->header_names[i]; struct ns_str hv = hm->header_values[i]; #ifdef NS_ENABLE_SSL /* * If we terminate SSL and backend redirects to local HTTP port, * strip protocol to let client use HTTPS. * TODO(lsm): web page content may also contain local HTTP references, * they need to be rewritten too. */ if (ns_vcasecmp(&hn, "Location") == 0 && s_ssl_cert != NULL) { size_t hlen = strlen(be->host_port); const char *hp = be->host_port, *p = memchr(hp, ':', hlen); if (p == NULL) { p = hp + hlen; } if (ns_ncasecmp(hv.p, "http://", 7) == 0 && ns_ncasecmp(hv.p + 7, hp, (p - hp)) == 0) { ns_printf(dst, "Location: %.*s\r\n", (int) (hv.len - (7 + (p - hp))), hv.p + 7 + (p - hp)); continue; } } #endif /* We always rewrite the connection header depending on the settings. */ if (ns_vcasecmp(&hn, "Connection") == 0) continue; ns_printf(dst, "%.*s: %.*s\r\n", (int) hn.len, hn.p, (int) hv.len, hv.p); } /* Emit the connection header. */ const char *connection_mode = "close"; if (dst_peer == &conn->backend) { if (s_backend_keepalive) connection_mode = "keep-alive"; } else { if (conn->client.flags.keep_alive) connection_mode = "keep-alive"; } ns_printf(dst, "Connection: %s\r\n", connection_mode); ns_printf(dst, "%s", "\r\n"); mbuf_remove(io, hm->body.p - hm->message.p); /* We've forwarded headers */ dst_peer->flags.headers_sent = 1; forward_body(src_peer, dst_peer); }
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; }
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; }
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; }