Example #1
0
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);
}
Example #2
0
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);
  }
}
Example #3
0
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);
  }
}
Example #4
0
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);
}
Example #5
0
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);
}
Example #6
0
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);
}
Example #7
0
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;
}
Example #8
0
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);
}
Example #9
0
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);
}
Example #10
0
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;
}
Example #11
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);
  }
}
Example #12
0
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);
}