Commit c84d02bb authored by Sergio Ammirata's avatar Sergio Ammirata
Browse files

Merge branch 'master' into tun_support

parents f51437ef 547e8044
......@@ -179,6 +179,14 @@ enum rist_stats_type
RIST_STATS_RECEIVER_FLOW
};
enum rist_connection_status
{
RIST_CONNECTION_ESTABLISHED = 0,
RIST_CONNECTION_TIMED_OUT = 1,
RIST_CLIENT_CONNECTED = 2,
RIST_CLIENT_TIMED_OUT = 3
};
struct rist_ctx;
struct rist_peer;
......
......@@ -374,6 +374,27 @@ RIST_API int rist_logging_settings_free(const struct rist_logging_settings **log
*/
RIST_API int rist_udp_config_free(const struct rist_udp_config **udp_config);
/**
* @brief Connection status callback function
*
* Optional calling application provided function for receiving connection status changes for peers.
*
* @param arg optional user data set via rist_connection_status_callback_set
* @param peer peer associated with the event
* @param rist_peer_connection_status status value
* @return void.
*/
typedef void (*connection_status_callback_t)(void *arg, struct rist_peer *peer, enum rist_connection_status peer_connection_status);
/**
* @brief Set callback for receiving connection status change events
*
* @param ctx RIST context
* @param connection_status_callback_t Callback function that will be called.
* @param arg extra arguments for callback function
*/
RIST_API int rist_connection_status_callback_set(struct rist_ctx *ctx, connection_status_callback_t, void *arg);
/**
* @brief Get the version of libRIST
*
......
......@@ -116,6 +116,14 @@ void rist_delete_flow(struct rist_receiver *ctx, struct rist_flow *f)
p->parent->flow = NULL;
}
}
struct rist_peer *peer = ctx->common.PEERS;
while (peer)
{
if (peer->flow == f) {
peer->flow = NULL;
}
peer = peer->next;
}
rist_log_priv(&ctx->common, RIST_LOG_INFO, "Free flow peer list\n");
f->peer_lst_len = 0;
......@@ -236,10 +244,16 @@ int rist_receiver_associate_flow(struct rist_peer *p, uint32_t flow_id)
// Find the flow based on the flow_id
struct rist_flow *f;
for (f = ctx->common.FLOWS; f != NULL; f = f->next) {
if (f->flow_id == flow_id) {
break;
if (ctx->common.profile > RIST_PROFILE_SIMPLE)
{
for (f = ctx->common.FLOWS; f != NULL; f = f->next) {
if (f->flow_id == flow_id) {
break;
}
}
} else
{
f = p->parent->flow;
}
/* create flow if necessary */
......
......@@ -53,7 +53,7 @@ static inline void rist_log_impl(struct rist_logging_settings *log_settings, enu
ssize_t msglen;
struct timeval tv;
gettimeofday(&tv, NULL);
msglen = asprintf(&logmsg, "%d.%6.6d|%ld.%ld|%s %s", (int)tv.tv_sec,
msglen = asprintf(&logmsg, "%d.%6.6d|%"PRIdPTR".%"PRIdPTR"|%s %s", (int)tv.tv_sec,
(int)tv.tv_usec, receiver_id, sender_id, prefix, msg);
if (RIST_UNLIKELY(msglen <= 0)) {
fprintf(stderr, "[ERROR] Failed to format log message\n");
......
......@@ -512,6 +512,7 @@ static int receiver_enqueue(struct rist_peer *peer, uint64_t source_time, const
return -1;
if (RIST_UNLIKELY(!f->receiver_queue_has_items)) {
/* we just received our first packet for this flow */
pthread_mutex_lock(&f->mutex);
if (atomic_load_explicit(&f->receiver_queue_size, memory_order_acquire) > 0)
{
/* Clear the queue if the queue had data */
......@@ -546,6 +547,7 @@ static int receiver_enqueue(struct rist_peer *peer, uint64_t source_time, const
/* reset stats */
memset(&f->stats_instant, 0, sizeof(f->stats_instant));
f->receiver_queue_has_items = true;
pthread_mutex_unlock(&f->mutex);
return 0; // not a dupe
}
......@@ -1508,6 +1510,11 @@ static bool rist_receiver_data_authenticate(struct rist_peer *peer, uint32_t flo
while (tmp) {
if (tmp->is_rtcp) {
if (tmp->local_port == rtcp_port && peer->adv_flow_id == tmp->adv_flow_id && address_compare(&peer->u.address, &tmp->u.address)) {
if (tmp->dead)
{
tmp = tmp->sibling_next;
continue;
}
peer->peer_rtcp = tmp;
tmp->peer_data = peer;
break;
......@@ -1520,6 +1527,11 @@ static bool rist_receiver_data_authenticate(struct rist_peer *peer, uint32_t flo
while (tmp) {
if (tmp->is_rtcp) {
if (tmp->local_port == rtcp_port && address_compare(&peer->u.address, &tmp->u.address)) {
if (tmp->dead)
{
tmp = tmp->sibling_next;
continue;
}
peer->peer_rtcp = tmp;
tmp->peer_data = peer;
break;
......@@ -1635,6 +1647,11 @@ static bool rist_receiver_rtcp_authenticate(struct rist_peer *peer, uint32_t seq
while (tmp) {
if (tmp->is_data) {
if (tmp->local_port == data_port && peer->adv_flow_id == tmp->adv_flow_id && address_compare(&peer->u.address, &tmp->u.address)) {
if (tmp->dead)
{
tmp = tmp->sibling_next;
continue;
}
peer->peer_data = tmp;
tmp->peer_rtcp = peer;
break;
......@@ -1647,6 +1664,11 @@ static bool rist_receiver_rtcp_authenticate(struct rist_peer *peer, uint32_t seq
while (tmp) {
if (tmp->is_data) {
if (tmp->local_port == data_port && address_compare(&peer->u.address, &tmp->u.address)) {
if (tmp->dead)
{
tmp = tmp->sibling_next;
continue;
}
peer->peer_data = tmp;
tmp->peer_rtcp = peer;
break;
......@@ -1662,7 +1684,8 @@ static bool rist_receiver_rtcp_authenticate(struct rist_peer *peer, uint32_t seq
if (tmp->is_data) {
if (tmp->local_port == data_port && tmp->peer_rtcp == NULL) {
peer->peer_data = tmp;
tmp->peer_rtcp = peer;
if (tmp->peer_rtcp->dead)
tmp->peer_rtcp = peer;
break;
}
}
......@@ -1692,10 +1715,13 @@ static bool rist_receiver_rtcp_authenticate(struct rist_peer *peer, uint32_t seq
rist_log_priv(&ctx->common, RIST_LOG_INFO,
"Authenticated RTCP peer %d and flow %"PRIu32" for connection with cname: %s\n",
peer->adv_peer_id, peer->adv_flow_id, peer->receiver_name);
if (ctx->common.profile == RIST_PROFILE_SIMPLE && peer->parent->flow == NULL) {
peer->parent->flow = peer->flow;
peer->parent->flow->authenticated = true;
if (ctx->common.profile == RIST_PROFILE_SIMPLE)
{
peer->parent->authenticated = true;
if (peer->parent->flow == NULL) {
peer->parent->flow = peer->flow;
peer->parent->flow->authenticated = true;
}
}
}
}
......@@ -1877,6 +1903,30 @@ static void rist_handle_xr_pkt(struct rist_peer *peer, uint8_t xr_pkt[])
}
}
static char *get_ip_str(struct sockaddr *sa, char *s, uint16_t *port, size_t maxlen)
{
switch(sa->sa_family) {
case AF_INET:
inet_ntop(AF_INET, &(((struct sockaddr_in *)sa)->sin_addr),
s, (socklen_t)maxlen);
break;
case AF_INET6:
inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)sa)->sin6_addr),
s, (socklen_t)maxlen);
break;
default:
strncpy(s, "Unknown AF", maxlen);
return NULL;
}
struct sockaddr_in *sin = (struct sockaddr_in *)s;
*port = htons (sin->sin_port);
return s;
}
static void rist_recv_rtcp(struct rist_peer *peer, uint32_t seq,
uint32_t flow_id, struct rist_buffer *payload)
{
......@@ -1887,6 +1937,7 @@ static void rist_recv_rtcp(struct rist_peer *peer, uint32_t seq,
uint8_t subtype;
uint32_t nack_seq_msb = 0;
peer->stats_receiver_instant.received_rtcp++;
struct rist_common_ctx *ctx = get_cctx(peer);
while (processed_bytes < payload->size) {
pkt = (uint8_t*)payload->data + processed_bytes;
......@@ -1897,7 +1948,7 @@ static void rist_recv_rtcp(struct rist_peer *peer, uint32_t seq,
if ( bytes_left < 4 )
{
/* we must have at least 4 bytes */
rist_log_priv(get_cctx(peer), RIST_LOG_ERROR, "Rist rtcp packet must have at least 4 bytes, we have %d\n",
rist_log_priv(ctx, RIST_LOG_ERROR, "Rist rtcp packet must have at least 4 bytes, we have %d\n",
bytes_left);
return;
}
......@@ -1909,7 +1960,7 @@ static void rist_recv_rtcp(struct rist_peer *peer, uint32_t seq,
if (bytes > bytes_left)
{
/* check for a sane number of bytes */
rist_log_priv(get_cctx(peer), RIST_LOG_ERROR, "Malformed feedback packet, expecting %u bytes in the" \
rist_log_priv(ctx, RIST_LOG_ERROR, "Malformed feedback packet, expecting %u bytes in the" \
" packet, got a buffer of %u bytes. ptype = %d\n", bytes,
bytes_left, ptype);
return;
......@@ -1938,7 +1989,7 @@ static void rist_recv_rtcp(struct rist_peer *peer, uint32_t seq,
RIST_FALLTHROUGH;
}
else {
rist_log_priv(get_cctx(peer), RIST_LOG_DEBUG, "Unsupported rtcp custom subtype %d, ignoring ...\n", subtype);
rist_log_priv(ctx, RIST_LOG_DEBUG, "Unsupported rtcp custom subtype %d, ignoring ...\n", subtype);
break;
}
case PTYPE_NACK_BITMASK:
......@@ -1959,26 +2010,41 @@ static void rist_recv_rtcp(struct rist_peer *peer, uint32_t seq,
if (name_length > bytes_left)
{
/* check for a sane number of bytes */
rist_log_priv(get_cctx(peer), RIST_LOG_ERROR, "Malformed SDES packet, wrong cname len %u, got a " \
rist_log_priv(ctx, RIST_LOG_ERROR, "Malformed SDES packet, wrong cname len %u, got a " \
"buffer of %u bytes.\n", name_length, bytes_left);
return;
}
bool new_peer = false;
if (memcmp(pkt + RTCP_SDES_SIZE, peer->receiver_name, name_length) != 0)
{
memcpy(peer->receiver_name, pkt + RTCP_SDES_SIZE, name_length);
rist_log_priv(get_cctx(peer), RIST_LOG_INFO, "Peer %"PRIu32" receiver name is now: %s\n",
rist_log_priv(ctx, RIST_LOG_INFO, "Peer %"PRIu32" receiver name is now: %s\n",
peer->adv_peer_id, peer->receiver_name);
new_peer = true;
}
//}
bool peer_authenticated = peer->authenticated;
int connection_message = 0;
if (peer->receiver_mode) {
rist_receiver_rtcp_authenticate(peer, seq, flow_id);
connection_message = RIST_CLIENT_CONNECTED;
} else if (peer->sender_ctx && peer->listening) {
// TODO: create rist_sender_recv_rtcp
if (!peer->authenticated) {
rist_peer_authenticate(peer);
}
connection_message = RIST_CLIENT_CONNECTED;
}
else {
connection_message = RIST_CONNECTION_ESTABLISHED;
}
if (peer->timed_out || new_peer || (!peer_authenticated && peer->authenticated)) {
if (!new_peer)
rist_log_priv(ctx, RIST_LOG_INFO, "Peer %"PRIu32" receiver with name %s reconnected\n",
peer->adv_peer_id, peer->receiver_name);
peer->timed_out = 0;
if (ctx->connection_status_callback)
ctx->connection_status_callback(ctx->connection_status_callback_argument, peer, connection_message);
}
break;
}
case PTYPE_SR:;
......@@ -1989,7 +2055,7 @@ static void rist_recv_rtcp(struct rist_peer *peer, uint32_t seq,
rist_handle_xr_pkt(peer, pkt);
break;
default:
rist_log_priv(get_cctx(peer), RIST_LOG_DEBUG, "Unrecognized RTCP packet with PTYPE=%02x!!\n", ptype);
rist_log_priv(ctx, RIST_LOG_DEBUG, "Unrecognized RTCP packet with PTYPE=%02x!!\n", ptype);
}
processed_bytes += bytes;
}
......@@ -2102,30 +2168,6 @@ void rist_peer_rtcp(struct evsocket_ctx *evctx, void *arg)
init_peer_settings(peer);
}
static char *get_ip_str(struct sockaddr *sa, char *s, uint16_t *port, size_t maxlen)
{
switch(sa->sa_family) {
case AF_INET:
inet_ntop(AF_INET, &(((struct sockaddr_in *)sa)->sin_addr),
s, (socklen_t)maxlen);
break;
case AF_INET6:
inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)sa)->sin6_addr),
s, (socklen_t)maxlen);
break;
default:
strncpy(s, "Unknown AF", maxlen);
return NULL;
}
struct sockaddr_in *sin = (struct sockaddr_in *)s;
*port = htons (sin->sin_port);
return s;
}
static void kill_peer(struct rist_peer *peer)
{
bool current_state = peer->dead;
......@@ -2838,9 +2880,11 @@ protocol_bypass:
//uint64_t now = timestampNTP_u64();
while (!flow->shutdown) {
pthread_mutex_lock(&(flow->mutex));
if (atomic_load_explicit(&flow->receiver_queue_size, memory_order_acquire) > 0) {
receiver_output(receiver_ctx, flow);
}
pthread_mutex_unlock(&(flow->mutex));
pthread_mutex_lock(&(flow->mutex));
int ret = pthread_cond_timedwait_ms(&(flow->condition), &(flow->mutex), max_output_jitter_ms);
pthread_mutex_unlock(&(flow->mutex));
......@@ -2875,32 +2919,42 @@ protocol_bypass:
}
void rist_timeout_check(struct rist_common_ctx *cctx, uint64_t now)
{
struct rist_peer *peer = cctx->PEERS;
while (peer)
void rist_timeout_check(struct rist_common_ctx *cctx, uint64_t now)
{
struct rist_peer *next = peer->next;
if (!peer->dead && peer->parent && now > peer->last_rtcp_received && peer->last_rtcp_received > 0)
struct rist_peer *peer = cctx->PEERS;
while (peer)
{
if (peer->parent && (now - peer->last_rtcp_received) > peer->session_timeout &&
peer->last_rtcp_received > 0)
struct rist_peer *next = peer->next;
if (!peer->dead && now > peer->last_rtcp_received && peer->last_rtcp_received > 0)
{
rist_log_priv2(cctx->logging_settings, RIST_LOG_WARN,
"Peer %u timed out\n", peer->adv_peer_id);
kill_peer(peer);
}
} else if (peer->dead && peer->parent)
{
if ( peer->dead_since < now && (now - peer->dead_since) > 5000 * RIST_CLOCK)
if ((now - peer->last_rtcp_received) > peer->session_timeout)
{
if (peer->parent)
{
rist_log_priv2(cctx->logging_settings, RIST_LOG_WARN, "Listening peer %u timed out\n", peer->adv_peer_id);
if (cctx->connection_status_callback)
cctx->connection_status_callback(cctx->connection_status_callback_argument, peer, RIST_CLIENT_TIMED_OUT);
kill_peer(peer);
}
else if (!peer->timed_out)
{
rist_log_priv2(cctx->logging_settings, RIST_LOG_WARN, "Peer %u timed out\n", peer->adv_peer_id);
if (cctx->connection_status_callback)
cctx->connection_status_callback(cctx->connection_status_callback_argument, peer, RIST_CONNECTION_TIMED_OUT);
peer->timed_out = 1;
}
}
} else if (peer->dead && peer->parent)
{
rist_log_priv2(cctx->logging_settings, RIST_LOG_INFO, "Removing timed-out peer %u\n", peer->adv_peer_id);
rist_peer_remove(cctx, peer, NULL);
if ( peer->dead_since < now && (now - peer->dead_since) > 5000 * RIST_CLOCK)
{
rist_log_priv2(cctx->logging_settings, RIST_LOG_INFO, "Removing timed-out peer %u\n", peer->adv_peer_id);
rist_peer_remove(cctx, peer, NULL);
}
}
peer = next;
}
peer = next;
}
}
PTHREAD_START_FUNC(sender_pthread_protocol, arg)
{
......@@ -3075,13 +3129,20 @@ int rist_peer_remove(struct rist_common_ctx *ctx, struct rist_peer *peer, struct
}
}
if (peer->peer_data != NULL && peer->peer_data != peer)
peer->peer_data->peer_rtcp = NULL;
if (peer->peer_rtcp != NULL && peer->peer_rtcp != peer)
peer->peer_rtcp->peer_data = NULL;
struct rist_peer *check = ctx->PEERS;
while (check)
{
if (check->peer_data == peer)
check->peer_data = NULL;
if (check->peer_rtcp == peer)
check->peer_rtcp = NULL;
check = check->next;
}
if (peer->parent) {
peer_remove_child(peer);
if (peer->parent->child == NULL) {
peer->parent->authenticated = false;
}
}
peer_remove_linked_list(peer);
......@@ -3098,10 +3159,17 @@ int rist_peer_remove(struct rist_common_ctx *ctx, struct rist_peer *peer, struct
}
if (found)
{
peer->flow->peer_lst = realloc(peer->flow->peer_lst, sizeof(peer) * (peer->flow->peer_lst_len -1));
peer->flow->peer_lst_len--;
if (peer->flow->peer_lst_len == 0)
if (peer->flow->peer_lst_len > 1)
{
peer->flow->peer_lst = realloc(peer->flow->peer_lst, sizeof(peer) * (peer->flow->peer_lst_len -1));
peer->flow->peer_lst_len--;
} else
{
free(peer->flow->peer_lst);
peer->flow->peer_lst_len = 0;
peer->flow->peer_lst = NULL;
}
}
}
......@@ -3115,10 +3183,16 @@ int rist_peer_remove(struct rist_common_ctx *ctx, struct rist_peer *peer, struct
}
}
if (found) {
peer->sender_ctx->peer_lst = realloc(peer->sender_ctx->peer_lst, sizeof(peer) * (peer->sender_ctx->peer_lst_len -1));
peer->sender_ctx->peer_lst_len--;
if (peer->sender_ctx->peer_lst_len == 0)
if (peer->sender_ctx->peer_lst_len > 1)
{
peer->sender_ctx->peer_lst = realloc(peer->sender_ctx->peer_lst, sizeof(peer) * (peer->sender_ctx->peer_lst_len -1));
peer->sender_ctx->peer_lst_len--;
} else
{
free(peer->sender_ctx->peer_lst);
peer->sender_ctx->peer_lst_len = 0;
peer->sender_ctx->peer_lst = NULL;
}
}
}
......
......@@ -336,6 +336,10 @@ struct rist_common_ctx {
bool debug;
uint32_t birthtime_rtp_offset;
/* Connection status callback */
connection_status_callback_t connection_status_callback;
void *connection_status_callback_argument;
};
struct rist_receiver {
......@@ -539,6 +543,7 @@ struct rist_peer {
struct rist_peer_receiver_stats stats_receiver_total;
int dead;
int timed_out;
uint64_t dead_since;
uint64_t birthtime_peer;
uint64_t birthtime_local;
......
......@@ -219,6 +219,30 @@ int rist_receiver_data_notify_fd_set(struct rist_ctx *rist_ctx, int fd)
return 0;
}
int rist_connection_status_callback_set(struct rist_ctx *ctx, connection_status_callback_t connection_status_callback,
void *arg)
{
if (RIST_UNLIKELY(!ctx))
{
rist_log_priv3(RIST_LOG_ERROR, "ctx is null on rist_connection_status_callback_set call!\n");
return -1;
}
struct rist_common_ctx *cctx = NULL;
if (ctx->mode == RIST_RECEIVER_MODE && ctx->receiver_ctx) {
cctx = &ctx->receiver_ctx->common;
}
else if (ctx->mode == RIST_SENDER_MODE && ctx->sender_ctx) {
cctx = &ctx->sender_ctx->common;
}
else {
rist_log_priv3(RIST_LOG_ERROR, "Unknown error in rist_connection_status_callback_set call!\n");
return -1;
}
cctx->connection_status_callback = connection_status_callback;
cctx->connection_status_callback_argument = arg;
return 0;
}
int rist_receiver_data_callback_set(struct rist_ctx *rist_ctx,
int (*data_callback)(void *arg, const struct rist_data_block *data_block),
void *arg)
......
......@@ -293,7 +293,7 @@ int main (int argc, char **argv) {
int option_index;
int c;
while ((c = (char)getopt_long(argc, argv, "r:i:o:s:e:N:v:S:h:u", long_options, &option_index)) != -1) {
while ((c = getopt_long(argc, argv, "r:i:o:s:e:N:v:S:h:u", long_options, &option_index)) != -1) {
switch (c) {
case 'i':
inputurl = strdup(optarg);
......
......@@ -46,6 +46,7 @@
static int signalReceived = 0;
static struct rist_logging_settings *logging_settings;
enum rist_profile profile = RIST_PROFILE_MAIN;
static int peer_connected_count = 0;
static struct option long_options[] = {
{ "inputurl", required_argument, NULL, 'i' },
......@@ -143,6 +144,17 @@ static uint32_t risttools_convertNTPtoRTP(uint64_t i_ntp)
return (uint32_t)i_ntp;
}
static void connection_status_callback(void *arg, struct rist_peer *peer, enum rist_connection_status peer_connection_status)
{
(void)arg;
if (peer_connection_status == RIST_CONNECTION_ESTABLISHED || peer_connection_status == RIST_CLIENT_CONNECTED)
peer_connected_count++;
else
peer_connected_count--;
rist_log(logging_settings, RIST_LOG_INFO,"Connection Status changed for Peer %"PRIu64", new status is %d, peer connected count is %d\n",
peer, peer_connection_status, peer_connected_count);
}
static int cb_recv(void *arg, const struct rist_data_block *b)
{
struct rist_callback_object *callback_object = (void *) arg;
......@@ -479,7 +491,7 @@ int main(int argc, char *argv[])
rist_log(logging_settings, RIST_LOG_INFO, "Starting ristreceiver version: %s libRIST library: %s API version: %s\n", LIBRIST_VERSION, librist_version(), librist_api_version());
while ((c = (char)getopt_long(argc, argv, "r:i:o:b:s:e:t:m:p:S:v:F:h:u", long_options, &option_index)) != -1) {
while ((c = getopt_long(argc, argv, "r:i:o:b:s:e:t:m:p:S:v:F:h:u", long_options, &option_index)) != -1) {
switch (c) {
case 'i':
inputurl = strdup(optarg);
......@@ -566,6 +578,11 @@ int main(int argc, char *argv[])
exit(1);
}
if (rist_connection_status_callback_set(ctx, connection_status_callback, NULL) == -1) {
rist_log(logging_settings, RIST_LOG_ERROR, "Could not initialize rist connection status callback\n");
exit(1);
}
if (profile != RIST_PROFILE_SIMPLE) {
if (rist_oob_callback_set(ctx, cb_recv_oob, (void *)&callback_object) == -1) {
rist_log(logging_settings, RIST_LOG_ERROR, "Could not add enable out-of-band data\n");
......
......@@ -41,6 +41,7 @@
#define MAX_OUTPUT_COUNT 20
static int signalReceived = 0;
static int peer_connected_count = 0;
static struct rist_logging_settings *logging_settings;
struct rist_callback_object {
......@@ -100,6 +101,7 @@ static struct option long_options[] = {
#ifdef USE_MBEDTLS
{ "srpfile", required_argument, NULL, 'F' },
#endif
{ "fast-start", no_argument, NULL, 'f' },
{ "help", no_argument, NULL, 'h' },
{ "help-url", no_argument, NULL, 'u' },
{ 0, 0, 0, 0 },
......@@ -132,6 +134,7 @@ const char help_str[] = "Usage: %s [OPTIONS] \nWhere OPTIONS are:\n"
" | 1 = only non udp data is accepted (default) |\n"
" | 2 = no data goes in our out of oob channel |\n"
#endif
" -f | --fast-start | Starts sending rtp data before handshake is completed |\n"
" -h | --help | Show this help |\n"
" -u | --help-url | Show all the possible url options |\n"
" * == mandatory value \n"
......@@ -221,8 +224,10 @@ static void input_udp_recv(struct evsocket_ctx *evctx, int fd, short revents, vo
data_block.payload = recv_buf + offset + ipheader_bytes;
data_block.payload_len = recv_bufsize - offset;
}
if (rist_sender_data_write(callback_object->sender_ctx, &data_block) < 0)
rist_log(logging_settings, RIST_LOG_ERROR, "Error writing data in input_udp_recv, socket=%d\n", callback_object->sd);
if (peer_connected_count) {
if (rist_sender_data_write(callback_object->sender_ctx, &data_block) < 0)
rist_log(logging_settings, RIST_LOG_ERROR, "Error writing data in input_udp_recv, socket=%d\n", callback_object->sd);
}
}
else
{
......@@ -247,6 +252,17 @@ static void usage(char *cmd)
exit(1);
}
static void connection_status_callback(void *arg, struct rist_peer *peer, enum rist_connection_status peer_connection_status)