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 = mg_ssl_if_write(nc, nc->send_mbuf.buf, len); DBG(("%p SSL_write %u = %d", nc, len, ret)); if (ret > 0) { mg_if_sent_cb(nc, ret); 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 (ret == len) { nc->flags &= ~MG_F_WANT_WRITE; } else if (ret == MG_SSL_WANT_WRITE) { nc->flags |= MG_F_WANT_WRITE; } else { mg_lwip_post_signal(MG_SIG_CLOSE_CONN, nc); } }
static void mg_write_to_socket(struct mg_connection *nc) { struct mbuf *io = &nc->send_mbuf; int n = 0; #if MG_LWIP /* With LWIP we don't know if the socket is ready */ if (io->len == 0) return; #endif assert(io->len > 0); if (nc->flags & MG_F_UDP) { int n = sendto(nc->sock, io->buf, io->len, 0, &nc->sa.sa, sizeof(nc->sa.sin)); DBG(("%p %d %d %d %s:%hu", nc, nc->sock, n, mg_get_errno(), inet_ntoa(nc->sa.sin.sin_addr), ntohs(nc->sa.sin.sin_port))); mg_if_sent_cb(nc, n); return; } #if MG_ENABLE_SSL if (nc->flags & MG_F_SSL) { if (nc->flags & MG_F_SSL_HANDSHAKE_DONE) { n = mg_ssl_if_write(nc, io->buf, io->len); DBG(("%p %d bytes -> %d (SSL)", nc, n, nc->sock)); if (n < 0) { if (n != MG_SSL_WANT_READ && n != MG_SSL_WANT_WRITE) { nc->flags |= MG_F_CLOSE_IMMEDIATELY; } return; } else { /* Successful SSL operation, clear off SSL wait flags */ nc->flags &= ~(MG_F_WANT_READ | MG_F_WANT_WRITE); } } else { mg_ssl_begin(nc); return; } } else #endif { n = (int) MG_SEND_FUNC(nc->sock, io->buf, io->len, 0); DBG(("%p %d bytes -> %d", nc, n, nc->sock)); } mg_if_sent_cb(nc, n); }
static void mg_lwip_task(os_event_t *e) { struct mg_mgr *mgr = NULL; DBG(("sig %d", e->sig)); poll_scheduled = 0; switch ((enum mg_sig_type) e->sig) { case MG_SIG_TOMBSTONE: break; case MG_SIG_POLL: { mgr = (struct mg_mgr *) e->par; break; } case MG_SIG_CONNECT_RESULT: { struct mg_connection *nc = (struct mg_connection *) e->par; mgr = nc->mgr; mg_if_connect_cb(nc, nc->err); break; } case MG_SIG_CLOSE_CONN: { struct mg_connection *nc = (struct mg_connection *) e->par; mgr = nc->mgr; nc->flags |= MG_F_CLOSE_IMMEDIATELY; mg_close_conn(nc); break; } case MG_SIG_SENT_CB: { struct mg_connection *nc = (struct mg_connection *) e->par; mgr = nc->mgr; mg_if_sent_cb(nc, nc->err); break; } case MG_SIG_V7_CALLBACK: { #ifndef NO_V7 struct v7_callback_args *cba = (struct v7_callback_args *) e->par; _sj_invoke_cb(cba->v7, cba->func, cba->this_obj, cba->args); v7_disown(cba->v7, &cba->func); v7_disown(cba->v7, &cba->this_obj); v7_disown(cba->v7, &cba->args); free(cba); #endif break; } } if (mgr != NULL) { mg_mgr_poll(mgr, 0); } }
void mg_ev_mgr_lwip_process_signals(struct mg_mgr *mgr) { struct mg_ev_mgr_lwip_data *md = (struct mg_ev_mgr_lwip_data *) mgr->ifaces[MG_MAIN_IFACE]->data; while (md->sig_queue_len > 0) { struct mg_connection *nc = md->sig_queue[md->start_index].nc; struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; switch (md->sig_queue[md->start_index].sig) { case MG_SIG_CONNECT_RESULT: { #if MG_ENABLE_SSL if (cs->err == 0 && (nc->flags & MG_F_SSL) && !(nc->flags & MG_F_SSL_HANDSHAKE_DONE)) { mg_lwip_ssl_do_hs(nc); } else #endif { mg_if_connect_cb(nc, cs->err); } break; } case MG_SIG_CLOSE_CONN: { nc->flags |= MG_F_CLOSE_IMMEDIATELY; mg_close_conn(nc); break; } case MG_SIG_RECV: { mg_lwip_handle_recv(nc); break; } case MG_SIG_SENT_CB: { if (cs->num_sent > 0) mg_if_sent_cb(nc, cs->num_sent); cs->num_sent = 0; break; } case MG_SIG_TOMBSTONE: { break; } } md->start_index = (md->start_index + 1) % MG_SIG_QUEUE_LEN; md->sig_queue_len--; } }
static void mg_lwip_task(os_event_t *e) { struct mg_mgr *mgr = NULL; poll_scheduled = 0; switch ((enum mg_sig_type) e->sig) { case MG_SIG_TOMBSTONE: break; case MG_SIG_POLL: { mgr = (struct mg_mgr *) e->par; break; } case MG_SIG_CONNECT_RESULT: { struct mg_connection *nc = (struct mg_connection *) e->par; struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; mgr = nc->mgr; mg_if_connect_cb(nc, cs->err); break; } case MG_SIG_CLOSE_CONN: { struct mg_connection *nc = (struct mg_connection *) e->par; mgr = nc->mgr; nc->flags |= MG_F_CLOSE_IMMEDIATELY; mg_close_conn(nc); break; } case MG_SIG_SENT_CB: { struct mg_connection *nc = (struct mg_connection *) e->par; struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; mgr = nc->mgr; if (cs->num_sent > 0) mg_if_sent_cb(nc, cs->num_sent); cs->num_sent = 0; break; } case MG_SIG_V7_CALLBACK: { #ifndef NO_V7 struct v7_callback_args *cba = (struct v7_callback_args *) e->par; _sj_invoke_cb(cba->v7, cba->func, cba->this_obj, cba->args); v7_disown(cba->v7, &cba->func); v7_disown(cba->v7, &cba->this_obj); v7_disown(cba->v7, &cba->args); free(cba); #endif break; } } if (mgr != NULL) { mg_mgr_poll(mgr, 0); if (s_suspended) { int can_suspend = 1; struct mg_connection *nc; /* Looking for data to send and if there isn't any - suspending */ for (nc = mgr->active_connections; nc != NULL; nc = nc->next) { if (nc->send_mbuf.len > 0) { can_suspend = 0; break; } } if (can_suspend) { os_timer_disarm(&s_poll_tmr); #if MG_LWIP_REXMIT_INTERVAL_MS > 0 os_timer_disarm(&s_rexmit_tmr); #endif } } } }