Esempio n. 1
0
/** Allow caller of altcp_write() to limit to negotiated chunk size
 *  or remaining sndbuf space of inner_conn.
 */
static u16_t
altcp_mbedtls_sndbuf(struct altcp_pcb *conn)
{
  if (conn) {
    altcp_mbedtls_state_t *state;
    state = (altcp_mbedtls_state_t*)conn->state;
    if (!state || !(state->flags & ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE)) {
      return 0;
    }
    if (conn->inner_conn) {
      u16_t sndbuf = altcp_sndbuf(conn->inner_conn);
      /* Take care of record header, IV, AuthTag */
      int ssl_expan = mbedtls_ssl_get_record_expansion(&state->ssl_context);
      if (ssl_expan > 0) {
        size_t ssl_added = (u16_t)LWIP_MIN(ssl_expan, 0xFFFF);
        /* internal sndbuf smaller than our offset */
        if (ssl_added < sndbuf) {
          size_t max_len = 0xFFFF;
          size_t ret;
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
          /* @todo: adjust ssl_added to real value related to negociated cipher */
          size_t max_frag_len = mbedtls_ssl_get_max_frag_len(&state->ssl_context);
          max_len = LWIP_MIN(max_frag_len, max_len);
#endif
          /* Adjust sndbuf of inner_conn with what added by SSL */
          ret = LWIP_MIN(sndbuf - ssl_added, max_len);
          LWIP_ASSERT("sndbuf overflow", ret <= 0xFFFF);
          return (u16_t)ret;
        }
      }
    }
  }
  /* fallback: use sendbuf of the inner connection */
  return altcp_default_sndbuf(conn);
}
Esempio n. 2
0
u16_t
altcp_default_sndbuf(struct altcp_pcb *conn)
{
  if (conn && conn->inner_conn) {
    return altcp_sndbuf(conn->inner_conn);
  }
  return 0;
}
Esempio n. 3
0
/**
 * Try send as many bytes as possible from output ring buffer
 * @param rb Output ring buffer
 * @param tpcb TCP connection handle
 */
static void
mqtt_output_send(struct mqtt_ringbuf_t *rb, struct altcp_pcb *tpcb)
{
  err_t err;
  u8_t wrap = 0;
  u16_t ringbuf_lin_len = mqtt_ringbuf_linear_read_length(rb);
  u16_t send_len = altcp_sndbuf(tpcb);
  LWIP_ASSERT("mqtt_output_send: tpcb != NULL", tpcb != NULL);

  if (send_len == 0 || ringbuf_lin_len == 0) {
    return;
  }

  LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_output_send: tcp_sndbuf: %d bytes, ringbuf_linear_available: %d, get %d, put %d\n",
                                 send_len, ringbuf_lin_len, rb->get, rb->put));

  if (send_len > ringbuf_lin_len) {
    /* Space in TCP output buffer is larger than available in ring buffer linear portion */
    send_len = ringbuf_lin_len;
    /* Wrap around if more data in ring buffer after linear portion */
    wrap = (mqtt_ringbuf_len(rb) > ringbuf_lin_len);
  }
  err = altcp_write(tpcb, mqtt_ringbuf_get_ptr(rb), send_len, TCP_WRITE_FLAG_COPY | (wrap ? TCP_WRITE_FLAG_MORE : 0));
  if ((err == ERR_OK) && wrap) {
    mqtt_ringbuf_advance_get_idx(rb, send_len);
    /* Use the lesser one of ring buffer linear length and TCP send buffer size */
    send_len = LWIP_MIN(altcp_sndbuf(tpcb), mqtt_ringbuf_linear_read_length(rb));
    err = altcp_write(tpcb, mqtt_ringbuf_get_ptr(rb), send_len, TCP_WRITE_FLAG_COPY);
  }

  if (err == ERR_OK) {
    mqtt_ringbuf_advance_get_idx(rb, send_len);
    /* Flush */
    altcp_output(tpcb);
  } else {
    LWIP_DEBUGF(MQTT_DEBUG_WARN, ("mqtt_output_send: Send failed with err %d (\"%s\")\n", err, lwip_strerr(err)));
  }
}
Esempio n. 4
0
/** If in state SMTP_BODY, try to send more body data */
static void
smtp_send_body(struct smtp_session *s, struct altcp_pcb *pcb)
{
  err_t err;

  if (s->state == SMTP_BODY) {
#if SMTP_BODYDH
    if (s->bodydh) {
      smtp_send_body_data_handler(s, pcb);
    } else
#endif /* SMTP_BODYDH */
    {
      u16_t send_len = (u16_t)(s->body_len - s->body_sent);
      if (send_len > 0) {
        u16_t snd_buf = altcp_sndbuf(pcb);
        if (send_len > snd_buf) {
          send_len = snd_buf;
        }
        if (send_len > 0) {
          /* try to send something out */
          err = altcp_write(pcb, &s->body[s->body_sent], (u16_t)send_len, TCP_WRITE_FLAG_COPY);
          if (err == ERR_OK) {
            s->timer = SMTP_TIMEOUT_DATABLOCK;
            s->body_sent = (u16_t)(s->body_sent + send_len);
            if (s->body_sent < s->body_len) {
              LWIP_DEBUGF(SMTP_DEBUG_STATE, ("smtp_send_body: %d of %d bytes written\n",
                s->body_sent, s->body_len));
            }
          }
        }
      }
    }
    if (s->body_sent == s->body_len) {
      /* the whole body has been written, write last line */
      LWIP_DEBUGF(SMTP_DEBUG_STATE, ("smtp_send_body: body completely written (%d bytes), appending end-of-body\n",
        s->body_len));
      err = altcp_write(pcb, SMTP_CMD_BODY_FINISHED, SMTP_CMD_BODY_FINISHED_LEN, 0);
      if (err == ERR_OK) {
        s->timer = SMTP_TIMEOUT_DATATERM;
        LWIP_DEBUGF(SMTP_DEBUG_STATE, ("smtp_send_body: end-of-body written, changing state to %s\n",
          smtp_state_str[SMTP_QUIT]));
        /* last line written, change state, wait for confirmation */
        s->state = SMTP_QUIT;
      }
    }
  }
}
Esempio n. 5
0
/** Elementary sub-function to send data
 *
 * @returns: BDHALLDATASENT all data has been written
 *           BDHSOMEDATASENT some data has been written
 *           0 no data has been written
 */
static int
smtp_send_bodyh_data(struct altcp_pcb *pcb, const char **from, u16_t *howmany)
{
  err_t err;
  u16_t len = *howmany;

  len = (u16_t)LWIP_MIN(len, altcp_sndbuf(pcb));
  err = altcp_write(pcb, *from, len, TCP_WRITE_FLAG_COPY);
  if (err == ERR_OK) {
    *from += len;
    if ((*howmany -= len) > 0) {
      return BDHSOMEDATASENT;
    }
    return BDHALLDATASENT;
  }
  return 0;
}