void nbuf_allocq(ndesc_t *nd, char *s, int sl) { check_ndesc(nd); nbuf_t **q = &nd->q, **q_head = &nd->q_head; nbuf_t *nb; bool ovfl; static int id; assert(s && sl); nb = nbuf_malloc(); //assert(nd->mc); nb->mc = nd->mc; nb->buf = (char*) wrx_malloc("nbuf:buf", sl); memcpy(nb->buf, s, sl); nb->len = sl; nb->done = FALSE; nb->dequeued = FALSE; nb->ttl = nd->ttl; if (nd->dbug) nb->id = id++; ovfl = nbuf_enqueue(nd, nb); if (nd->dbug) printf("A%d ", nb->id); if (nd->dbug) nbuf_dumpq(nd); check_nbuf(nb); if (ovfl) { wrx_free("nbuf:buf", nb->buf); nbuf_free(nb); } }
static const char* edata(const char *uri, size_t *size, char **free_buf) { const char* data = NULL; #ifdef EDATA_EMBED // the normal background daemon loads files from in-memory embedded data data = edata_embed(uri, size); #endif // some large, seldom-changed files are always loaded from memory if (!data) data = edata_always(uri, size); #ifdef EDATA_DEVEL // to speed edit-copy-compile-debug development, load the files from the local filesystem static bool init; if (!init) { scall("chdir web", chdir("web")); init = true; } // try as a local file if (!data) { int fd = open(uri, O_RDONLY); if (fd >= 0) { struct stat st; fstat(fd, &st); *size = st.st_size; data = (char *) wrx_malloc("file", *size); *free_buf = (char *) data; ssize_t rsize = read(fd, (void *) data, *size); assert(rsize == *size); close(fd); } } #endif return data; }
static nbuf_t *nbuf_malloc() { nbuf_t *nb; #ifdef NBUF_STATIC_ALLOC lock_enter(&nbuf_lock); int i; for (i=0; i<NNBUF; i++) { nb = &nbuf[i]; if (nb->isFree) break; } if (i == NNBUF) panic("out of nbufs"); lock_leave(&nbuf_lock); #else nb = (nbuf_t*) wrx_malloc("nbuf", sizeof(nbuf_t)); #endif memset(nb, 0, sizeof(nbuf_t)); nb->magic = NB_MAGIC; nb->magic_b = NBUF_MAGIC_B; nb->magic_e = NBUF_MAGIC_E; check_nbuf(nb); return nb; }
static int request(struct mg_connection *mc) { size_t edata_size=0; const char *edata_data; char *free_buf = NULL; if (mc->is_websocket) { // This handler is called for each incoming websocket frame, one or more // times for connection lifetime. char *s = mc->content; int sl = mc->content_len; //printf("WEBSOCKET: len %d uri <%s>\n", sl, mc->uri); if (sl == 0) { //printf("----KA %d\n", mc->remote_port); return MG_TRUE; // keepalive? } conn_t *c = rx_server_websocket(mc); if (c == NULL) return MG_FALSE; if (c->stop_data) return MG_FALSE; s[sl]=0; //printf("WEBSOCKET: %d <%s> ", sl, s); nbuf_allocq(&c->w2a, s, sl); if (mc->content_len == 4 && !memcmp(mc->content, "exit", 4)) { //printf("----EXIT %d\n", mc->remote_port); return MG_FALSE; } else { return MG_TRUE; } } else { if (strcmp(mc->uri, "/") == 0) mc->uri = "index.html"; else if (mc->uri[0] == '/') mc->uri++; char *ouri = (char *) mc->uri; char *uri = ouri; bool free_uri = FALSE; if (strncmp(ouri, "wrx/", 4) == 0) { uri = (char *) &mc->uri[4]; } else { user_iface_t *ui = find_ui(mc->local_port); // should never not find match since we only listen to ports in ui table assert(ui); asprintf(&uri, "%s/%s", ui->name, ouri); free_uri = TRUE; } //printf("---- HTTP: uri %s (%s)\n", ouri, uri); // try as file from in-memory embedded data edata_data = edata(uri, &edata_size, &free_buf); // try as request from browser if (!edata_data) { free_buf = (char*) wrx_malloc("req", NREQ_BUF); edata_data = rx_server_request(mc, free_buf, &edata_size); // mc->uri is ouri without ui->name prefix if (!edata_data) { wrx_free("req", free_buf); free_buf = NULL; } } if (!edata_data) { printf("unknown URL: %s (%s) %s\n", ouri, uri, mc->query_string); return MG_FALSE; } // for index.html process %[substitution] if (strcmp(ouri, "index.html") == 0) { static bool index_init; static char *index_html, *index_buf; static size_t index_size; #ifdef EDATA_EMBED if (!index_init) { // only have to do once #else if (true) { // file might change anytime during development #endif if (!index_buf) index_buf = (char*) wrx_malloc("index_buf", edata_size*3/2); char *cp = (char*) edata_data, *np = index_buf, *pp; int i, cl, sl, nl=0, pl; for (cl=0; cl < edata_size;) { if (*cp == '%' && *(cp+1) == '[') { cp += 2; cl += 2; pp = cp; pl = 0; while (*cp != ']' && cl < edata_size) { cp++; cl++; pl++; } cp++; cl++; for (i=0; i < ARRAY_LEN(index_html_params); i++) { index_html_params_t *ip = &index_html_params[i]; if (strncmp(pp, ip->param, pl) == 0) { sl = strlen(ip->value); strcpy(np, ip->value); np += sl; break; } } if (i == ARRAY_LEN(index_html_params)) { // not found, put back original strcpy(np, "%["); np += 2; strncpy(np, pp, pl); np += pl; *np++ = ']'; } } else { *np++ = *cp++; cl++; } } index_html = index_buf; index_size = np - index_buf; index_init = true; } edata_data = index_html; edata_size = index_size; } //printf("DATA: %s %d ", mc->uri, (int) edata_size); mg_send_header(mc, "Content-Type", mg_get_mime_type(mc->uri, "text/plain")); mg_send_data(mc, edata_data, edata_size); if (free_uri) free(uri); if (free_buf) wrx_free("req", free_buf); http_bytes += edata_size; return MG_TRUE; } } static int ev_handler(struct mg_connection *mc, enum mg_event ev) { int r; //printf("ev_handler %d:%d len %d ", mc->local_port, mc->remote_port, (int) mc->content_len); if (ev == MG_REQUEST) { //printf("MG_REQUEST: URI:%s query:%s\n", mc->uri, mc->query_string); r = request(mc); //printf("\n"); return r; } else if (ev == MG_AUTH) { //printf("MG_AUTH\n"); return MG_TRUE; } else { //printf("MG_OTHER\n"); return MG_FALSE; } }