void mg_if_recved(struct mg_connection *nc, size_t len) { if (nc->flags & MG_F_UDP) return; struct tcp_pcb *tpcb = (struct tcp_pcb *) nc->sock; DBG(("%p %u", nc, len)); tcp_recved(tpcb, len); mbuf_trim(&nc->recv_mbuf); }
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); } }
struct mg_str mg_url_encode_opt(const struct mg_str src, const struct mg_str safe, unsigned int flags) { const char *hex = (flags & MG_URL_ENCODE_F_UPPERCASE_HEX ? "0123456789ABCDEF" : "0123456789abcdef"); size_t i = 0; struct mbuf mb; mbuf_init(&mb, src.len); for (i = 0; i < src.len; i++) { const unsigned char c = *((const unsigned char *) src.p + i); if (isalnum(c) || mg_strchr(safe, c) != NULL) { mbuf_append(&mb, &c, 1); } else if (c == ' ' && (flags & MG_URL_ENCODE_F_SPACE_AS_PLUS)) { mbuf_append(&mb, "+", 1); } else { mbuf_append(&mb, "%", 1); mbuf_append(&mb, &hex[c >> 4], 1); mbuf_append(&mb, &hex[c & 15], 1); } } mbuf_append(&mb, "", 1); mbuf_trim(&mb); return mg_mk_str_n(mb.buf, mb.len - 1); }
void tcp_conn::recv() { struct mbuf *mb; struct le *le; bool hlp_estab = false; int err = 0; DEBUG_INFO("TCP Receive %u bytes\n", ctc->iBufRx.Length()); /* If no memory packet will be dropped */ mb = mbuf_alloc(ctc->iBufRx.Length()); if (mb) { (void)mbuf_write_mem(mb, (uint8_t *)ctc->iBufRx.Ptr(), ctc->iBufRx.Length()); mb->pos = 0; } ctc->StartReceiving(); if (!mb) goto out; le = list_head(&helpers); while (le) { struct tcp_helper *th; bool hdld; th = (struct tcp_helper *)le->data; le = le->next; if (!hlp_estab) hdld = th->recvh(&err, mb, &hlp_estab, arg); else hdld = th->estabh(&err, active, arg); if (hdld || err) { if (err) conn_close(err); goto out; } } mbuf_trim(mb); if (!hlp_estab) { if (recvh) recvh(mb, arg); } else { if (estabh) estabh(arg); } out: mem_deref(mb); }
void mg_if_recved(struct mg_connection *nc, size_t len) { if (nc->flags & MG_F_UDP) return; struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; DBG(("%p %p %u", nc, cs->pcb.tcp, len)); /* Currently SSL acknowledges data immediately. * TODO(rojer): Find a way to propagate mg_if_recved. */ if (nc->ssl == NULL) { tcp_recved(cs->pcb.tcp, len); } mbuf_trim(&nc->recv_mbuf); }
void Server::event_handler(struct mg_connection *conn, int ev, void *p) { struct http_message *hm = (struct http_message *) p; if (ev == MG_EV_SSI_CALL) { mbuf_resize(&conn->send_mbuf, conn->send_mbuf.size * 2); std::string resp(conn->send_mbuf.buf, conn->send_mbuf.len); boost::replace_all(resp, "href=\"/", std::string("href=\"") + CONFIG_STRING(m_config, "service.base_location")); boost::replace_all(resp, "src=\"/", std::string("src=\"") + CONFIG_STRING(m_config, "service.base_location")); boost::replace_all(resp, "action=\"/", std::string("action=\"") + CONFIG_STRING(m_config, "service.base_location")); strcpy(conn->send_mbuf.buf, resp.c_str()); mbuf_trim(&conn->send_mbuf); return; } if (ev != MG_EV_HTTP_REQUEST) { return; } hm->uri.p += CONFIG_STRING(m_config, "service.base_location").size() - 1; hm->uri.len -= CONFIG_STRING(m_config, "service.base_location").size() - 1; if (!is_authorized(conn, hm)) { redirect_to(conn, hm, "/login"); } else if (mg_vcmp(&hm->uri, "/authorize") == 0) { authorize(conn, hm); } else if (mg_vcmp(&hm->uri, "/logout") == 0) { serve_logout(conn, hm); // } else if (mg_vcmp(&hm->uri, "/users") == 0) { // serve_users(conn, hm); // } else if (mg_vcmp(&hm->uri, "/users/add") == 0) { // serve_users_add(conn, hm); // } else if (mg_vcmp(&hm->uri, "/users/remove") == 0) { // serve_users_remove(conn, hm); } else if (has_prefix(&hm->uri, "/oauth2")) { serve_oauth2(conn, hm); } else if (has_prefix(&hm->uri, "/api/v1/")) { m_apiServer->handleRequest(this, get_session(hm), conn, hm); } else { if (hm->uri.p[hm->uri.len - 1] != '/') { std::string url(hm->uri.p, hm->uri.len); if (url.find(".") == std::string::npos) { url += "/"; redirect_to(conn, hm, url.c_str()); conn->flags |= MG_F_SEND_AND_CLOSE; return; } } mg_serve_http(conn, hm, s_http_server_opts); } conn->flags |= MG_F_SEND_AND_CLOSE; }
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 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); }
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 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 void tcp_recv_handler(int flags, void *arg) { struct tcp_conn *tc = arg; struct mbuf *mb = NULL; bool hlp_estab = false; struct le *le; ssize_t n; int err; socklen_t err_len = sizeof(err); if (flags & FD_EXCEPT) { DEBUG_INFO("recv handler: got FD_EXCEPT on fd=%d\n", tc->fdc); } /* check for any errors */ if (-1 == getsockopt(tc->fdc, SOL_SOCKET, SO_ERROR, BUF_CAST &err, &err_len)) { DEBUG_WARNING("recv handler: getsockopt: (%m)\n", errno); return; } if (err) { conn_close(tc, err); return; } #if 0 if (EINPROGRESS != err && EALREADY != err) { DEBUG_WARNING("recv handler: Socket error (%m)\n", err); return; } #endif if (flags & FD_WRITE) { if (tc->connected) { uint32_t nrefs; mem_ref(tc); err = dequeue(tc); nrefs = mem_nrefs(tc); mem_deref(tc); /* check if connection was deref'd from send handler */ if (nrefs == 1) return; if (err) { conn_close(tc, err); return; } if (!tc->sendq.head && !tc->sendh) { err = fd_listen(tc->fdc, FD_READ, tcp_recv_handler, tc); if (err) { conn_close(tc, err); return; } } if (flags & FD_READ) goto read; return; } tc->connected = true; err = fd_listen(tc->fdc, FD_READ, tcp_recv_handler, tc); if (err) { DEBUG_WARNING("recv handler: fd_listen(): %m\n", err); conn_close(tc, err); return; } le = tc->helpers.head; while (le) { struct tcp_helper *th = le->data; le = le->next; if (th->estabh(&err, tc->active, th->arg) || err) { if (err) conn_close(tc, err); return; } } if (tc->estabh) tc->estabh(tc->arg); return; } read: mb = mbuf_alloc(tc->rxsz); if (!mb) return; n = recv(tc->fdc, BUF_CAST mb->buf, mb->size, 0); if (0 == n) { mem_deref(mb); conn_close(tc, 0); return; } else if (n < 0) { DEBUG_WARNING("recv handler: recv(): %m\n", errno); goto out; } mb->end = n; le = tc->helpers.head; while (le) { struct tcp_helper *th = le->data; bool hdld = false; le = le->next; if (hlp_estab) { hdld |= th->estabh(&err, tc->active, th->arg); if (err) { conn_close(tc, err); goto out; } } if (mb->pos < mb->end) { hdld |= th->recvh(&err, mb, &hlp_estab, th->arg); if (err) { conn_close(tc, err); goto out; } } if (hdld) goto out; } mbuf_trim(mb); if (hlp_estab && tc->estabh) { uint32_t nrefs; mem_ref(tc); tc->estabh(tc->arg); nrefs = mem_nrefs(tc); mem_deref(tc); /* check if connection was deref'ed from establish handler */ if (nrefs == 1) goto out; } if (mb->pos < mb->end && tc->recvh) { tc->recvh(mb, tc->arg); } out: mem_deref(mb); }