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);
  }
}
Exemple #2
0
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--;
  }
}
Exemple #5
0
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
      }
    }
  }
}