Create new send API

This API is used to send small messages. The message may consist of
several smaller buffers or it may just be one buffer containing all the
data.

The total size of buffers must not exceed the MAX_PAYLOAD limit
This commit is contained in:
Aaro Altonen 2019-07-18 11:57:32 +03:00
parent 9484444699
commit 6b89c779d7
4 changed files with 79 additions and 88 deletions

View File

@ -16,7 +16,7 @@
#include "writer.hh"
// TODO implement frame splitting if data_len > MTU
rtp_error_t kvz_rtp::generic::push_generic_frame(connection *conn, uint8_t *data, size_t data_len, uint32_t timestamp)
rtp_error_t kvz_rtp::generic::push_generic_frame(kvz_rtp::connection *conn, uint8_t *data, size_t data_len, uint32_t timestamp)
{
if (data_len > MAX_PAYLOAD) {
LOG_WARN("packet is larger (%zu bytes) than MAX_PAYLOAD (%u bytes)", data_len, MAX_PAYLOAD);
@ -25,7 +25,7 @@ rtp_error_t kvz_rtp::generic::push_generic_frame(connection *conn, uint8_t *data
uint8_t header[kvz_rtp::frame::HEADER_SIZE_RTP];
conn->fill_rtp_header(header, timestamp);
return kvz_rtp::sender::write_frame(conn, header, sizeof(header), data, data_len);
return kvz_rtp::send::send_frame(conn, header, sizeof(header), data, data_len);
}
kvz_rtp::frame::rtp_frame *kvz_rtp::generic::process_generic_frame(

View File

@ -9,6 +9,9 @@
/* Validity of arguments is checked by kvz_rtp::sender. We just need to relay them there */
rtp_error_t kvz_rtp::opus::push_opus_frame(connection *conn, uint8_t *data, uint32_t data_len, uint32_t timestamp)
{
return kvz_rtp::generic::push_generic_frame(conn, data, data_len, timestamp);
#if 0
rtp_error_t ret;
if ((ret = kvz_rtp::sender::write_rtp_header(conn, timestamp)) != RTP_OK) {
@ -18,7 +21,6 @@ rtp_error_t kvz_rtp::opus::push_opus_frame(connection *conn, uint8_t *data, uint
return kvz_rtp::sender::write_payload(conn, data, data_len);
#if 0
uint8_t buffer[MAX_PACKET] = { 0 };
RTPOpus::OpusConfig *config = (RTPOpus::OpusConfig *)conn->getConfig();

View File

@ -16,76 +16,49 @@
#include "util.hh"
#include "writer.hh"
rtp_error_t kvz_rtp::sender::write_payload(kvz_rtp::connection *conn, uint8_t *payload, size_t payload_len)
rtp_error_t kvz_rtp::send::send_frame(
kvz_rtp::connection *conn,
uint8_t *frame, size_t frame_len
)
{
if (!conn)
if (!conn || !frame || frame_len == 0)
return RTP_INVALID_VALUE;
conn->inc_sent_bytes(payload_len);
if (frame_len >= MAX_PAYLOAD) {
LOG_WARN("Frame length (%lu) is larger than MAX_PAYLOAD (%u)", frame_len, MAX_PAYLOAD);
}
conn->inc_sent_bytes(frame_len);
conn->inc_sent_pkts();
conn->inc_rtp_sequence();
return conn->get_socket().sendto(payload, payload_len, 0, NULL);
return conn->get_socket().sendto(frame, frame_len, 0, NULL);
}
rtp_error_t kvz_rtp::sender::write_generic_header(kvz_rtp::connection *conn, uint8_t *header, size_t header_len)
{
if (!conn)
return RTP_INVALID_VALUE;
#ifdef __linux__
return conn->get_socket().sendto(header, header_len, MSG_MORE, NULL);
#else
return conn->get_socket().sendto(header, header_len, MSG_PARTIAL, NULL);
#endif
}
rtp_error_t kvz_rtp::sender::write_rtp_header(kvz_rtp::connection *conn, uint32_t timestamp)
{
if (!conn)
return RTP_INVALID_VALUE;
uint8_t header[kvz_rtp::frame::HEADER_SIZE_RTP] = { 0 };
conn->fill_rtp_header(header, timestamp);
return kvz_rtp::sender::write_generic_header(conn, header, kvz_rtp::frame::HEADER_SIZE_RTP);
}
rtp_error_t kvz_rtp::sender::write_generic_frame(kvz_rtp::connection *conn, kvz_rtp::frame::rtp_frame *frame)
{
if (!frame)
return RTP_INVALID_VALUE;
rtp_error_t ret;
if ((ret = kvz_rtp::sender::write_payload(conn, frame->data, frame->total_len)) != RTP_OK) {
LOG_ERROR("Failed to send payload! Size %zu, Type %d", frame->total_len, frame->type);
return ret;
}
return RTP_OK;
}
rtp_error_t kvz_rtp::sender::write_frame(
rtp_error_t kvz_rtp::send::send_frame(
kvz_rtp::connection *conn,
uint8_t *header, size_t header_len,
uint8_t *payload, size_t payload_len
)
{
if (!conn || !header || !payload || header_len == 0 || payload_len == 0)
if (!conn || !header || header_len == 0 || !payload || payload_len == 0)
return RTP_INVALID_VALUE;
rtp_error_t ret;
std::vector<std::pair<size_t, uint8_t *>> buffers;
if ((ret = kvz_rtp::sender::write_generic_header(conn, header, header_len)) != RTP_OK) {
LOG_ERROR("Failed to write generic header, length: %zu", header_len);
return ret;
}
buffers.push_back(std::make_pair(header_len, header));
buffers.push_back(std::make_pair(payload_len, payload));
if ((ret = kvz_rtp::sender::write_payload(conn, payload, payload_len)) != RTP_OK) {
LOG_ERROR("Failed to write payload, length: %zu", payload_len);
return ret;
}
return ret;
return conn->get_socket().sendto(buffers, 0);
}
rtp_error_t kvz_rtp::send::send_frame(
kvz_rtp::connection *conn,
std::vector<std::pair<size_t, uint8_t *>>& buffers
)
{
if (!conn)
return RTP_INVALID_VALUE;
return conn->get_socket().sendto(buffers, 0);
}

View File

@ -7,43 +7,59 @@
namespace kvz_rtp {
class connection;
namespace sender {
namespace send {
/* Send RTP Frame to remote
*
* This functions assumes "frame_len" is smaller than MAX_PAYLOAD
* No measures are taken (apart from print a warning) if it's larger
* TODO: should it split the frame?
*
* send_frame() assumes that "frame" starts with a valid RTP header
*
* Return RTP_OK on success
* Return RTP_INVALID_VALUE if one of the values are invalid
* Return RTP_SEND_ERROR if sending the frame failed */
rtp_error_t send_frame(
kvz_rtp::connection *conn,
uint8_t *frame, size_t frame_len
);
/* Write RTP Header to OS buffers. This should be called first when sending new RTP packet.
/* Send RTP Frame to remote
*
* Return RTP_OK on success and RTP_ERROR on error */
rtp_error_t write_rtp_header(kvz_rtp::connection *conn, uint32_t timestamp);
/* To minimize the amount of copying, write all headers directly to operating system's buffers
* This function uses MSG_MORE/MSG_PARTIAL to prevent the actual sending.
* This functions assumes "frame_len" + "header_len" is smaller than MAX_PAYLOAD
* No measures are taken (apart from print a warning) if it's larger
* TODO: should it split the frame?
*
* Return RTP_OK on success and RTP_ERROR on error */
rtp_error_t write_generic_header(kvz_rtp::connection *conn, uint8_t *header, size_t header_len);
/* Write the actual data payload and send the full datagram to remote
* send_frame() assumes that "header" points to a valid RTP header
*
* Caller should first write the RTP and all other necessary headers by calling
* write_*_header() and then finalize the send by calling writePayload()
*
* return RTP_OK on success and RTP_ERROR on error */
rtp_error_t write_payload(kvz_rtp::connection *conn, uint8_t *payload, size_t payload_len);
/* Write a generic frame
* This function sends the datagram immediately,
*
* Return RTP_OK on success and RTP_ERROR on error */
rtp_error_t write_generic_frame(kvz_rtp::connection *conn, kvz_rtp::frame::rtp_frame *frame);
/* If the header and payload of RTP messages are separate, the can be combined and sent
* using write_frame()
*
* This function will send the message right away.
*
* return RTP_OK on success and RTP_ERROR on error */
rtp_error_t write_frame(
* Return RTP_OK on success
* Return RTP_INVALID_VALUE if one of the values are invalid
* Return RTP_SEND_ERROR if sending the frame failed */
rtp_error_t send_frame(
kvz_rtp::connection *conn,
uint8_t *header, size_t header_len,
uint8_t *payload, size_t payload_len
);
/* Send RTP Frame to remote
*
* This functions assumes "frame_len" is smaller than MAX_PAYLOAD
* No measures are taken (apart from print a warning) if it's larger
* TODO: should it split the frame?
*
* send_frame() assumes that "buffers" contains at least two buffers:
* - RTP header
* - RTP payload
*
* RTP header must be the first buffer of the "buffers" vector
*
* Return RTP_OK on success
* Return RTP_INVALID_VALUE if one of the values are invalid
* Return RTP_SEND_ERROR if sending the frame failed */
rtp_error_t send_frame(
kvz_rtp::connection *conn,
std::vector<std::pair<size_t, uint8_t *>>& buffers
);
};
};