static err_t mg_lwip_accept_cb(void *arg, struct tcp_pcb *newtpcb, err_t err) { struct mg_connection *lc = (struct mg_connection *) arg; (void) err; DBG(("%p conn %p from %s:%u", lc, newtpcb, ipaddr_ntoa(&newtpcb->remote_ip), newtpcb->remote_port)); struct mg_connection *nc = mg_if_accept_new_conn(lc); if (nc == NULL) { tcp_abort(newtpcb); return ERR_ABRT; } struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; cs->pcb.tcp = newtpcb; tcp_arg(newtpcb, nc); tcp_err(newtpcb, mg_lwip_tcp_error_cb); tcp_sent(newtpcb, mg_lwip_tcp_sent_cb); tcp_recv(newtpcb, mg_lwip_tcp_recv_cb); #ifdef SSL_KRYPTON if (lc->ssl_ctx != NULL) { nc->ssl = SSL_new(lc->ssl_ctx); if (nc->ssl == NULL || SSL_set_fd(nc->ssl, (intptr_t) nc) != 1) { LOG(LL_ERROR, ("SSL error")); tcp_close(newtpcb); } } else #endif { mg_lwip_accept_conn(nc, newtpcb); } return ERR_OK; }
static void mg_lwip_ssl_do_hs(struct mg_connection *nc) { struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; int server_side = (nc->listener != NULL); int ret = server_side ? SSL_accept(nc->ssl) : SSL_connect(nc->ssl); int err = SSL_get_error(nc->ssl, ret); DBG(("%s %d %d", (server_side ? "SSL_accept" : "SSL_connect"), ret, err)); if (ret <= 0) { if (err == SSL_ERROR_WANT_WRITE) { nc->flags |= MG_F_WANT_WRITE; cs->err = 0; } else if (err == SSL_ERROR_WANT_READ) { /* Nothing, we are callback-driven. */ cs->err = 0; } else { cs->err = err; LOG(LL_ERROR, ("SSL handshake error: %d", cs->err)); if (server_side) { system_os_post(MG_TASK_PRIORITY, MG_SIG_CLOSE_CONN, (uint32_t) nc); } else { system_os_post(MG_TASK_PRIORITY, MG_SIG_CONNECT_RESULT, (uint32_t) nc); } } } else { cs->err = 0; nc->flags &= ~MG_F_WANT_WRITE; nc->flags |= MG_F_SSL_HANDSHAKE_DONE; if (server_side) { mg_lwip_accept_conn(nc, cs->pcb.tcp); } else { system_os_post(MG_TASK_PRIORITY, MG_SIG_CONNECT_RESULT, (uint32_t) nc); } } }
void mg_lwip_ssl_do_hs(struct mg_connection *nc) { struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; int server_side = (nc->listener != NULL); enum mg_ssl_if_result res; if (nc->flags & MG_F_CLOSE_IMMEDIATELY) return; res = mg_ssl_if_handshake(nc); DBG(("%p %lu %d %d", nc, nc->flags, server_side, res)); if (res != MG_SSL_OK) { if (res == MG_SSL_WANT_WRITE) { nc->flags |= MG_F_WANT_WRITE; cs->err = 0; } else if (res == MG_SSL_WANT_READ) { /* * Nothing to do in particular, we are callback-driven. * What we definitely do not need anymore is SSL reading (nothing left). */ nc->flags &= ~MG_F_WANT_READ; cs->err = 0; } else { cs->err = res; if (server_side) { mg_lwip_post_signal(MG_SIG_CLOSE_CONN, nc); } else { mg_lwip_post_signal(MG_SIG_CONNECT_RESULT, nc); } } } else { cs->err = 0; nc->flags &= ~MG_F_WANT_WRITE; /* * Handshake is done. Schedule a read immediately to consume app data * which may already be waiting. */ nc->flags |= (MG_F_SSL_HANDSHAKE_DONE | MG_F_WANT_READ); if (server_side) { mg_lwip_accept_conn(nc, cs->pcb.tcp); } else { mg_lwip_post_signal(MG_SIG_CONNECT_RESULT, nc); } } }