diff --git a/src/rtp_generic.cc b/src/rtp_generic.cc index cf21dba..72efb3b 100644 --- a/src/rtp_generic.cc +++ b/src/rtp_generic.cc @@ -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( diff --git a/src/rtp_opus.cc b/src/rtp_opus.cc index 4b2bbfc..d16fadf 100644 --- a/src/rtp_opus.cc +++ b/src/rtp_opus.cc @@ -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(); diff --git a/src/send.cc b/src/send.cc index 64b82da..b5e10ca 100644 --- a/src/send.cc +++ b/src/send.cc @@ -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> 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>& buffers +) +{ + if (!conn) + return RTP_INVALID_VALUE; + + return conn->get_socket().sendto(buffers, 0); } diff --git a/src/send.hh b/src/send.hh index f71f35e..aa45a7d 100644 --- a/src/send.hh +++ b/src/send.hh @@ -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>& buffers + ); + }; };