static int encode(struct aucodec_st *st, struct mbuf *dst, struct mbuf *src) { int len; if (!mbuf_get_left(src)) return 0; if (mbuf_get_left(src) != st->fsize) { DEBUG_WARNING("encode: got %d bytes, expected %d\n", mbuf_get_left(src), st->fsize); return EINVAL; } if (mbuf_get_space(dst) < MAX_PACKET) { int err = mbuf_resize(dst, dst->pos + MAX_PACKET); if (err) return err; } len = opus_encode(st->enc, (short *)mbuf_buf(src), st->frame_size, mbuf_buf(dst), (int)mbuf_get_space(dst)); if (len < 0) { DEBUG_WARNING("encode error: %d (%u bytes)\n", len, mbuf_get_left(src)); return EPROTO; } src->pos = src->end; dst->end = dst->pos + len; return 0; }
/* src=NULL means lost packet */ static int decode(struct aucodec_st *st, struct mbuf *dst, struct mbuf *src) { int r; if (!mbuf_get_left(src) && !st->got_packet) return 0; /* Make sure there is enough space in the buffer */ if (mbuf_get_space(dst) < st->fsize) { int err = mbuf_resize(dst, dst->pos + st->fsize); if (err) return err; } r = opus_decode(st->dec, mbuf_buf(src), (int)mbuf_get_left(src), (short *)mbuf_buf(dst), st->frame_size, 0); if (r <= 0) { DEBUG_WARNING("opus_decode: r=%d (%u bytes)\n", r, mbuf_get_left(src)); return EBADMSG; } if (src) src->pos = src->end; dst->end += 2 * r * aucodec_ch(st->ac); st->got_packet = true; return 0; }
/** * Write a block of memory to a memory buffer * * @param mb Memory buffer * @param buf Memory block to write * @param size Number of bytes to write * * @return 0 if success, otherwise errorcode */ int mbuf_write_mem(struct mbuf *mb, const uint8_t *buf, size_t size) { size_t rsize; if (!mb || !buf) return EINVAL; rsize = mb->pos + size; if (rsize > mb->size) { const size_t dsize = mb->size ? (mb->size * 2) : DEFAULT_SIZE; int err; err = mbuf_resize(mb, MAX(rsize, dsize)); if (err) return err; } memcpy(mb->buf + mb->pos, buf, size); mb->pos += size; mb->end = MAX(mb->end, mb->pos); return 0; }
static int decode_frame(struct aucodec_st *st, struct mbuf *dst, struct mbuf *src, uint16_t src_len) { int ret, err; if (mbuf_get_left(src) < src_len) { DEBUG_WARNING("dec: corrupt frame %u < %u\n", mbuf_get_left(src), src_len); return EPROTO; } /* Make sure there is enough space in the buffer */ if (mbuf_get_space(dst) < st->fsize) { err = mbuf_resize(dst, dst->size + st->fsize); if (err) return err; } ret = celt_decode(st->dec, mbuf_buf(src), src_len, (short *)mbuf_buf(dst), st->frame_size); if (CELT_OK != ret) { DEBUG_WARNING("celt_decode: ret=%d\n", ret); } DEBUG_INFO("decode: %u -> %u\n", src_len, st->fsize); if (src) mbuf_advance(src, src_len); dst->end += st->fsize; return 0; }
/* PLC is only valid for Decoding (RX) */ static int dec(struct aufilt_st *st, struct mbuf *mb) { int nsamp = (int)mbuf_get_left(mb) / 2; if (nsamp) { nsamp = plc_rx(&st->plc, (int16_t *)mbuf_buf(mb), nsamp); if (nsamp >= 0) mb->end = mb->pos + (2*nsamp); } else { nsamp = (int)st->psize / 2; re_printf("plc: concealing %u bytes\n", st->psize); if (mbuf_get_space(mb) < st->psize) { int err = mbuf_resize(mb, st->psize); if (err) return err; } nsamp = plc_fillin(&st->plc, (int16_t *)mbuf_buf(mb), nsamp); mb->end = mb->pos + 2 * nsamp; } return 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; }
/** * Allocate a new memory buffer * * @param size Initial buffer size * * @return New memory buffer, NULL if no memory */ struct mbuf *mbuf_alloc(size_t size) { struct mbuf *mb; mb = mem_zalloc(sizeof(*mb), mbuf_destructor); if (!mb) return NULL; if (mbuf_resize(mb, size ? size : DEFAULT_SIZE)) return mem_deref(mb); return mb; }
/** * Trim unused trailing bytes in a memory buffer, resize if necessary * * @param mb Memory buffer to trim */ void mbuf_trim(struct mbuf *mb) { int err; if (!mb || !mb->end || mb->end == mb->size) return; /* We shrink - this cannot fail */ err = mbuf_resize(mb, mb->end); if (err) { DEBUG_WARNING("trim: resize failed (%s)\n", strerror(err)); } }
void mgos_uart_hal_dispatch_rx_top(struct mgos_uart_state *us) { int uart_no = us->uart_no; struct mbuf *rxb = &us->rx_buf; uint32_t rxn = 0; /* RX */ if (mgos_uart_rxb_free(us) > 0 && esp_uart_rx_fifo_len(uart_no) > 0) { int linger_counter = 0; /* 32 here is a constant measured (using system_get_time) to provide * linger time of rx_linger_micros. It basically means that one iteration * of the loop takes 3.2 us. * * Note: lingering may starve TX FIFO if the flow is bidirectional. * TODO(rojer): keep transmitting from tx_buf while lingering. */ int max_linger = us->cfg.rx_linger_micros / 10 * 32; #ifdef MEASURE_LINGER_TIME uint32_t st = system_get_time(); #endif while (mgos_uart_rxb_free(us) > 0 && linger_counter <= max_linger) { size_t rx_len = esp_uart_rx_fifo_len(uart_no); if (rx_len > 0) { rx_len = MIN(rx_len, mgos_uart_rxb_free(us)); if (rxb->size < rxb->len + rx_len) mbuf_resize(rxb, rxb->len + rx_len); while (rx_len > 0) { uint8_t b = rx_byte(uart_no); mbuf_append(rxb, &b, 1); rx_len--; rxn++; } if (linger_counter > 0) { us->stats.rx_linger_conts++; linger_counter = 0; } } else { linger_counter++; } } #ifdef MEASURE_LINGER_TIME fprintf(stderr, "Time spent reading: %u us\n", system_get_time() - st); #endif us->stats.rx_bytes += rxn; } CLEAR_PERI_REG_MASK(UART_INT_CLR(uart_no), UART_RX_INTS); }
static bool send_handler(int *err, struct sa *dst, struct mbuf *mb, void *arg) { struct menc_st *st = arg; err_status_t e; int len; (void)dst; if (!st->use_srtp || !is_rtp_or_rtcp(mb)) return false; len = (int)mbuf_get_left(mb); if (mbuf_get_space(mb) < ((size_t)len + SRTP_MAX_TRAILER_LEN)) { mbuf_resize(mb, mb->pos + len + SRTP_MAX_TRAILER_LEN); } if (is_rtcp_packet(mb)) { e = srtp_protect_rtcp(st->srtp_tx, mbuf_buf(mb), &len); } else { e = srtp_protect(st->srtp_tx, mbuf_buf(mb), &len); } if (err_status_ok != e) { DEBUG_WARNING("send: failed to protect %s-packet" " with %d bytes (%H)\n", is_rtcp_packet(mb) ? "RTCP" : "RTP", len, errstatus_print, e); *err = EPROTO; return false; } mbuf_set_end(mb, mb->pos + len); return false; /* continue processing */ }
static void udp_read(struct udp_sock *us, int fd) { struct mbuf *mb = mbuf_alloc(us->rxsz); struct sa src; struct le *le; int err = 0; ssize_t n; if (!mb) return; src.len = sizeof(src.u); n = recvfrom(fd, BUF_CAST mb->buf + us->rx_presz, mb->size - us->rx_presz, 0, &src.u.sa, &src.len); if (n < 0) { err = errno; if (EAGAIN == err) goto out; #ifdef EWOULDBLOCK if (EWOULDBLOCK == err) goto out; #endif #if TARGET_OS_IPHONE if (ENOTCONN == err) { struct udp_sock *us_new; struct sa laddr; err = udp_local_get(us, &laddr); if (err) goto out; if (-1 != us->fd) { fd_close(us->fd); (void)close(us->fd); us->fd = -1; } if (-1 != us->fd6) { fd_close(us->fd6); (void)close(us->fd6); us->fd6 = -1; } err = udp_listen(&us_new, &laddr, NULL, NULL); if (err) goto out; us->fd = us_new->fd; us->fd6 = us_new->fd6; us_new->fd = -1; us_new->fd6 = -1; mem_deref(us_new); udp_thread_attach(us); goto out; } #endif /* cache error code */ us->err = err; goto out; } mb->pos = us->rx_presz; mb->end = n + us->rx_presz; (void)mbuf_resize(mb, mb->end); /* call helpers */ le = us->helpers.head; while (le) { struct udp_helper *uh = le->data; bool hdld; le = le->next; hdld = uh->recvh(&src, mb, uh->arg); if (hdld) goto out; } us->rh(&src, mb, us->arg); out: mem_deref(mb); }
static bool recv_handler(int *err, struct mbuf *mb, bool *estab, void *arg) { struct tls_conn *tc = arg; int r; /* feed SSL data to the BIO */ r = BIO_write(tc->sbio_in, mbuf_buf(mb), (int)mbuf_get_left(mb)); if (r <= 0) { DEBUG_WARNING("recv: BIO_write %d\n", r); *err = ENOMEM; return true; } if (SSL_state(tc->ssl) != SSL_ST_OK) { if (tc->up) { *err = EPROTO; return true; } if (tc->active) { *err = tls_connect(tc); } else { *err = tls_accept(tc); } DEBUG_INFO("state=0x%04x\n", SSL_state(tc->ssl)); /* TLS connection is established */ if (SSL_state(tc->ssl) != SSL_ST_OK) return true; *estab = true; tc->up = true; } mbuf_set_pos(mb, 0); for (;;) { int n; if (mbuf_get_space(mb) < 4096) { *err = mbuf_resize(mb, mb->size + 8192); if (*err) return true; } n = SSL_read(tc->ssl, mbuf_buf(mb), (int)mbuf_get_space(mb)); if (n < 0) { const int ssl_err = SSL_get_error(tc->ssl, n); switch (ssl_err) { case SSL_ERROR_WANT_READ: break; default: *err = EPROTO; return true; } break; } else if (n == 0) break; mb->pos += n; } mbuf_set_end(mb, mb->pos); mbuf_set_pos(mb, 0); return false; }
static bool recv_handler(struct sa *src, struct mbuf *mb, void *arg) { struct tls_sock *ts = arg; struct tls_conn *tc; int r; tc = tls_udp_conn(ts, src); if (!tc) { /* No connection found, assuming Server role */ tc = conn_alloc(ts, src); if (!tc) return true; SSL_set_verify(tc->ssl, 0, 0); SSL_set_accept_state(tc->ssl); } /* feed SSL data to the BIO */ r = BIO_write(tc->sbio_in, mbuf_buf(mb), (int)mbuf_get_left(mb)); if (r <= 0) return true; check_timer(tc); mbuf_set_pos(mb, 0); for (;;) { int n; if (mbuf_get_space(mb) < 4096) { if (mbuf_resize(mb, mb->size + 8192)) return true; } n = SSL_read(tc->ssl, mbuf_buf(mb), (int)mbuf_get_space(mb)); if (n < 0) { const int ssl_err = SSL_get_error(tc->ssl, n); switch (ssl_err) { case SSL_ERROR_WANT_READ: break; default: return true; } break; } else if (n == 0) break; mb->pos += n; } if (!mb->pos) return true; mbuf_set_end(mb, mb->pos); mbuf_set_pos(mb, 0); return false; }