// Renders the response void renderResponse(struct ns_connection *nc, const SharedMemory* sharedData, struct http_message *hm) { std::string responseJson = sharedMemoryRenderer.render(sharedData, getQueryString(hm)); std::string response; bool gzipResponse = shouldGzipResponse(hm, responseJson.size()); if (gzipResponse) { response = Utils::gzipString(responseJson); }else{ response = responseJson; } // build HTTP OK response with JSON response body ns_printf(nc, "HTTP/1.1 200 OK\r\n" "Content-Type: application/json\r\n" "Cache-Control: no-cache\r\n" "Access-Control-Allow-Origin: *\r\n"); if (gzipResponse) { ns_printf(nc, "Content-Encoding: gzip\r\n"); } ns_printf(nc, "Content-Length: %d\r\n\r\n", (int)response.size()); ns_send(nc, response.data(), response.size()); }
static void client_handler(struct ns_connection *conn, enum ns_event ev, void *p) { struct iobuf *io = &conn->recv_iobuf; (void) p; if (ev == NS_CONNECT) { if (conn->flags & NSF_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 == NS_RECV) { if (conn->flags & NSF_USER_1) { // Received data from the stdin, forward it to the server struct ns_connection *c = (struct ns_connection *) conn->user_data; ns_send(c, io->buf, io->len); iobuf_remove(io, io->len); } else { // Received data from server connection, print it fwrite(io->buf, io->len, 1, stdout); iobuf_remove(io, io->len); } } else if (ev == NS_CLOSE) { // Connection has closed, most probably cause server has stopped exit(EXIT_SUCCESS); } }
/* ** Name: void ns_reset(dpeth_t *dep) ** Function: Resets device. */ static void ns_reset(dpeth_t * dep) { int ix; /* Stop chip */ outb_reg0(dep, DP_CR, CR_STP | CR_NO_DMA); outb_reg0(dep, DP_RBCR0, 0); outb_reg0(dep, DP_RBCR1, 0); for (ix = 0; ix < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RST) == 0); ix += 1) /* Do nothing */ ; outb_reg0(dep, DP_TCR, TCR_1EXTERNAL | TCR_OFST); outb_reg0(dep, DP_CR, CR_STA | CR_NO_DMA); outb_reg0(dep, DP_TCR, TCR_NORMAL | TCR_OFST); /* Acknowledge the ISR_RDC (remote dma) interrupt. */ for (ix = 0; ix < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RDC) == 0); ix += 1) /* Do nothing */ ; outb_reg0(dep, DP_ISR, inb_reg0(dep, DP_ISR) & NOT(ISR_RDC)); /* Reset the transmit ring. If we were transmitting a packet, we * pretend that the packet is processed. Higher layers will * retransmit if the packet wasn't actually sent. */ dep->de_sendq_head = dep->de_sendq_tail = 0; for (ix = 0; ix < dep->de_sendq_nr; ix++) dep->de_sendq[ix].sq_filled = FALSE; ns_send(dep, TRUE, dep->de_send_s); return; }
static void choose_backend(struct ns_connection *nc) { struct http_message hm; struct iobuf *io = &nc->recv_iobuf; int req_len = ns_parse_http(io->buf, io->len, &hm); if (req_len < 0 || (req_len == 0 && io->len >= NS_MAX_HTTP_REQUEST_SIZE)) { /* Invalid, or too large request */ nc->flags |= NSF_CLOSE_IMMEDIATELY; } else if (req_len == 0) { /* Do nothing, request is not yet fully buffered */ } else { /* * Got HTTP request, look which backend to use. Round-robin over the * backends with the same uri_prefix and vhost. */ struct ns_str vhost = *ns_get_http_header(&hm, "host"); const char *vhost_end = vhost.p; while(vhost_end < vhost.p + vhost.len && *vhost_end != ':') { vhost_end++; } vhost.len = vhost_end - vhost.p; int i, chosen = -1; for (i = 0; i < s_num_http_backends; i++) { if (has_prefix(&hm.uri, s_http_backends[i].uri_prefix) && matches_vhost(&vhost, s_http_backends[i].vhost) && (chosen == -1 || s_http_backends[i].usage_counter < s_http_backends[chosen].usage_counter)) { chosen = i; } } if (chosen == -1) { /* No backend with given uri_prefix found, bail out */ ns_printf(nc, "%s%s\r\n", s_error_404, s_content_len_0); } else if (s_http_backends[chosen].redirect != 0) { ns_printf(nc, "HTTP/1.1 302 Found\r\nLocation: %s\r\n\r\n", s_http_backends[chosen].host_port); nc->flags |= NSF_SEND_AND_CLOSE; } else if ((nc->proto_data = ns_connect(nc->mgr, s_http_backends[chosen].host_port, ev_handler)) == NULL) { /* Connection to backend failed */ ns_printf(nc, "%s%s\r\n", s_error_500, s_content_len_0); } else { /* * Forward request to the backend. Note that we can insert extra headers * to pass information to the backend. * Store backend index as user_data for the backend connection. */ ((struct ns_connection *) nc->proto_data)->proto_data = nc; ((struct ns_connection *) nc->proto_data)->user_data = (void *) (long) chosen; s_http_backends[chosen].usage_counter++; ns_send(nc->proto_data, io->buf, io->len); iobuf_remove(io, io->len); } } }
static void js_send(struct v7 *v7, struct v7_val *this_obj, struct v7_val *result, struct v7_val **args, int num_args) { struct ns_connection *nc = get_nc(this_obj); int i; (void) v7; (void) result; for (i = 0; i < num_args; i++) { if (args[i]->type != V7_STR) continue; ns_send(nc, args[i]->v.str.buf, args[i]->v.str.len); } }
static void js_write(struct v7 *v7, struct v7_val *obj, struct v7_val *result, struct v7_val *args, int num_args) { int i; struct ns_connection *nc = get_nc(obj); (void) v7; result->type = V7_NUM; result->v.num = 0; for (i = 0; i < num_args; i++) { if (args[i].type != V7_STR) continue; ns_send(nc, args[i].v.str.buf, args[i].v.str.len); } }
static void ev_handler(struct ns_connection *nc, int ev, void *p) { struct iobuf *io = &nc->recv_iobuf; (void) p; switch (ev) { case NS_RECV: ns_send(nc, io->buf, io->len); // Echo message back iobuf_remove(io, io->len); // Discard message from recv buffer break; default: break; } }
static void server_handler(struct ns_connection *nc, enum ns_event ev, void *p) { (void) p; if (ev == NS_RECV) { // Push received message to all ncections struct iobuf *io = &nc->recv_iobuf; struct ns_connection *c; for (c = ns_next(nc->mgr, NULL); c != NULL; c = ns_next(nc->mgr, c)) { ns_send(c, io->buf, io->len); } iobuf_remove(io, io->len); } }
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 ev_handler(struct ns_connection *nc, int ev, void *ev_data) { struct iobuf *io = &nc->recv_iobuf; struct ns_connection *peer = (struct ns_connection *) nc->proto_data; switch (ev) { case NS_CONNECT: if (* (int *) ev_data != 0) { /* TODO(lsm): mark backend as defunct, try it later on */ fprintf(stderr, "connect(%s) failed\n", s_http_backends[(int) nc->user_data].host_port); ns_printf(nc->proto_data, "%s%s\r\n", s_error_500, s_content_len_0); } break; case NS_RECV: /* * For incoming client connection, nc->proto_data points to the respective * backend connection. For backend connection, nc->proto_data points * to the respective incoming client connection. */ if (peer == NULL) { choose_backend(nc); } else { /* Forward data to peer */ ns_send(peer, io->buf, io->len); iobuf_remove(io, io->len); } break; case NS_CLOSE: /* We're closing, detach our peer */ if (peer != NULL) { peer->proto_data = NULL; peer->flags |= NSF_SEND_AND_CLOSE; } break; } }
/* ** Name: void ns_interrupt(dpeth_t * dep) ** Function: Handles interrupt. */ static void ns_interrupt(dpeth_t * dep) { int isr, tsr; int queue; while ((isr = inb_reg0(dep, DP_ISR)) != 0) { outb_reg0(dep, DP_ISR, isr); if (isr & (ISR_PTX | ISR_TXE)) { tsr = inb_reg0(dep, DP_TSR); if (tsr & TSR_PTX) { dep->de_stat.ets_packetT++; } if (tsr & TSR_COL) dep->de_stat.ets_collision++; if (tsr & (TSR_ABT | TSR_FU)) { dep->de_stat.ets_fifoUnder++; } if ((isr & ISR_TXE) || (tsr & (TSR_CRS | TSR_CDH | TSR_OWC))) { printf("%s: got send Error (0x%02X)\n", dep->de_name, tsr); dep->de_stat.ets_sendErr++; } queue = dep->de_sendq_tail; if (!(dep->de_sendq[queue].sq_filled)) { /* Hardware bug? */ printf("%s: transmit interrupt, but not sending\n", dep->de_name); continue; } dep->de_sendq[queue].sq_filled = FALSE; if (++queue == dep->de_sendq_nr) queue = 0; dep->de_sendq_tail = queue; if (dep->de_sendq[queue].sq_filled) { ns_start_xmit(dep, dep->de_sendq[queue].sq_size, dep->de_sendq[queue].sq_sendpage); } if (dep->de_flags & DEF_SENDING) { ns_send(dep, TRUE, dep->de_send_s); } } if (isr & ISR_PRX) { ns_recv(dep, TRUE, 0); } if (isr & ISR_RXE) { printf("%s: got recv Error (0x%04X)\n", dep->de_name, inb_reg0(dep, DP_RSR)); dep->de_stat.ets_recvErr++; } if (isr & ISR_CNT) { dep->de_stat.ets_CRCerr += inb_reg0(dep, DP_CNTR0); dep->de_stat.ets_recvErr += inb_reg0(dep, DP_CNTR1); dep->de_stat.ets_fifoOver += inb_reg0(dep, DP_CNTR2); } if (isr & ISR_OVW) { printf("%s: got overwrite warning\n", dep->de_name); } if (isr & ISR_RDC) { /* Nothing to do */ } if (isr & ISR_RST) { /* This means we got an interrupt but the ethernet * chip is shutdown. We set the flag DEF_STOPPED, and * continue processing arrived packets. When the * receive buffer is empty, we reset the dp8390. */ printf("%s: network interface stopped\n", dep->de_name); dep->de_flags |= DEF_STOPPED; break; } } if ((dep->de_flags & (DEF_READING | DEF_STOPPED)) == (DEF_READING | DEF_STOPPED)) { /* The chip is stopped, and all arrived packets delivered */ ns_reset(dep); dep->de_flags &= NOT(DEF_STOPPED); } return; }