Commit d515df04 authored by Simon Morlat's avatar Simon Morlat

implement network simulator in outbound mode

parent e55c2cfb
......@@ -310,6 +310,8 @@ ORTP_PUBLIC int ortp_file_exist(const char *pathname);
ORTP_PUBLIC void ortp_get_cur_time(ortpTimeSpec *ret);
ORTP_PUBLIC uint64_t ortp_get_cur_time_ms(void);
ORTP_PUBLIC void ortp_sleep_ms(int ms);
ORTP_PUBLIC void ortp_sleep_until(const ortpTimeSpec *ts);
ORTP_PUBLIC unsigned int ortp_random(void);
/* portable named pipes and shared memory*/
......
......@@ -118,24 +118,35 @@ typedef struct _RtpTransport
void (*t_destroy)(struct _RtpTransport *transport);
} RtpTransport;
typedef enum _OrtpNetworkSimulatorMode{
OrtpNetworkSimulatorInbound,/**<simulation is applied when receiving packets*/
OrtpNetworkSimulatorOutbound, /**<simulation is applied to sent packets*/
OrtpNetworkSimulatorOutboundControlled /**<simulation is applied to sent packets according to sent timestamp
set in the timestamp field of mblk_t, which is definied only with -DORTP_TIMESTAMP */
}OrtpNetworkSimulatorMode;
/**
* Structure describing the network simulator parameters
**/
typedef struct _OrtpNetworkSimulatorParams{
int enabled;
float max_bandwidth; /*IP bandwidth, in bit/s*/
int max_buffer_size; /*Max number of bit buffered before being discarded*/
float loss_rate; /*Percentage*/
uint32_t latency; /*Packet transmission delay, in ms*/
float consecutive_loss_probability;/* a probablity of having a subsequent loss after a loss occured, in a 0-1 range.*/
float jitter_burst_density; /*density of gap/bursts events. A value of 1 means one gap/burst per second approximately*/
float jitter_strength; /*percentage of max_bandwidth */
int enabled; /**<Whether simulation is enabled or off.*/
float max_bandwidth; /**<IP bandwidth, in bit/s*/
int max_buffer_size; /**<Max number of bit buffered before being discarded*/
float loss_rate; /**<Percentage of lost packets*/
uint32_t latency; /**<Packet transmission delay, in ms*/
float consecutive_loss_probability;/**< a probablity of having a subsequent loss after a loss occured, in a 0-1 range. Useful to simulate burst of lost packets*/
float jitter_burst_density; /**<density of gap/bursts events. A value of 1 means one gap/burst per second approximately*/
float jitter_strength; /**<percentage of max_bandwidth artifically consumed during bursts events*/
OrtpNetworkSimulatorMode mode; /**<whether simulation is applied to inboud or outbound stream.*/
}OrtpNetworkSimulatorParams;
typedef struct _OrtpNetworkSimulatorCtx{
OrtpNetworkSimulatorParams params;
int bit_budget;
int qsize;
queue_t q;
queue_t q;/*queue used for simulating bandwidth limit*/
queue_t latency_q;
queue_t send_q; /*used only for OrtpNetworkSimulatorOutbound direction*/
struct timeval last_check;
uint64_t last_jitter_event;
int consecutive_drops;
......@@ -143,7 +154,10 @@ typedef struct _OrtpNetworkSimulatorCtx{
int drop_by_congestion;
int drop_by_loss;
int total_count; /*total number of packets gone through the simulator*/
ortp_mutex_t mutex;
ortp_thread_t thread;
bool_t in_jitter_event;
bool_t thread_started;
}OrtpNetworkSimulatorCtx;
typedef struct OrtpRtcpSendAlgorithm {
......@@ -559,6 +573,7 @@ ORTP_PUBLIC float rtp_session_get_round_trip_propagation(RtpSession *session);
ORTP_PUBLIC void rtp_session_enable_network_simulation(RtpSession *session, const OrtpNetworkSimulatorParams *params);
ORTP_PUBLIC void rtp_session_rtcp_set_lost_packet_value( RtpSession *session, const int64_t value );
ORTP_PUBLIC void rtp_session_rtcp_set_jitter_value(RtpSession *session, const unsigned int value );
ORTP_PUBLIC void rtp_session_rtcp_set_delay_value(RtpSession *session, const unsigned int value );
......
......@@ -59,9 +59,9 @@ typedef struct msgb
#if defined(ORTP_TIMESTAMP)
struct timeval timestamp;
#endif
ortp_recv_addr_t recv_addr;
struct sockaddr_storage src_addr; /*source address incoming packet used by simulator*/
socklen_t src_addrlen; /*source address incoming packet length used by simulator*/
ortp_recv_addr_t recv_addr; /*contains the destination address of incoming packets, used for ICE processing*/
struct sockaddr_storage net_addr; /*source address of incoming packet, or dest address of outgoing packet, used only by simulator and modifiers*/
socklen_t net_addrlen; /*source (dest) address of incoming (outgoing) packet length used by simulator and modifiers*/
uint8_t ttl_or_hl;
} mblk_t;
......
......@@ -23,10 +23,14 @@
#include "ortp/rtpsession.h"
#include "rtpsession_priv.h"
static void rtp_session_schedule_outbound_network_simulator(RtpSession *session, ortpTimeSpec *sleep_until);
static OrtpNetworkSimulatorCtx* simulator_ctx_new(void){
OrtpNetworkSimulatorCtx *ctx=(OrtpNetworkSimulatorCtx*)ortp_malloc0(sizeof(OrtpNetworkSimulatorCtx));
qinit(&ctx->latency_q);
qinit(&ctx->q);
qinit(&ctx->send_q);
ortp_mutex_init(&ctx->mutex,NULL);
return ctx;
}
......@@ -44,9 +48,78 @@ void ortp_network_simulator_destroy(OrtpNetworkSimulatorCtx *sim){
}
flushq(&sim->latency_q,0);
flushq(&sim->q,0);
flushq(&sim->send_q,0);
if (sim->thread_started){
sim->thread_started=FALSE;
ortp_thread_join(sim->thread, NULL);
}
ortp_mutex_destroy(&sim->mutex);
ortp_free(sim);
}
static void set_high_prio(){
#ifndef WIN32
const char *sched_pref=getenv("ORTP_SIMULATOR_SCHED_POLICY");
int policy=SCHED_OTHER;
struct sched_param param;
int result=0;
char* env_prio_c=NULL;
int min_prio, max_prio, env_prio;
if (sched_pref && strcasecmp(sched_pref,"SCHED_RR")==0){
policy=SCHED_RR;
}else if (sched_pref && strcasecmp(sched_pref,"SCHED_FIFO")==0){
policy=SCHED_FIFO;
}
memset(&param,0,sizeof(param));
min_prio = sched_get_priority_min(policy);
max_prio = sched_get_priority_max(policy);
env_prio_c = getenv("ORTP_SIMULATOR_SCHED_PRIO");
env_prio = (env_prio_c == NULL)?max_prio:atoi(env_prio_c);
env_prio = MAX(MIN(env_prio, max_prio), min_prio);
param.sched_priority=env_prio;
if((result=pthread_setschedparam(pthread_self(),policy, &param))) {
ortp_warning("Ortp simulator: set pthread_setschedparam failed: %s",strerror(result));
} else {
ortp_message("Priority set to %i and value (%i)",
policy, param.sched_priority);
}
#endif
}
static void * outboud_simulator_thread(void *ctx){
RtpSession *session=(RtpSession*)ctx;
OrtpNetworkSimulatorCtx *sim=session->net_sim_ctx;
ortpTimeSpec sleep_until;
set_high_prio();
while(sim->thread_started){
sleep_until.tv_sec=0;
sleep_until.tv_nsec=0;
rtp_session_schedule_outbound_network_simulator(session, &sleep_until);
if (sleep_until.tv_sec!=0 || sleep_until.tv_nsec!=0 ) ortp_sleep_until(&sleep_until);
else ortp_sleep_ms(1);
}
return NULL;
}
static const char *simulator_mode_to_string(OrtpNetworkSimulatorMode mode){
switch(mode){
case OrtpNetworkSimulatorInbound:
return "Inbound";
case OrtpNetworkSimulatorOutbound:
return "Outbound";
case OrtpNetworkSimulatorOutboundControlled:
return "OutboundControlled";
}
return "invalid";
}
void rtp_session_enable_network_simulation(RtpSession *session, const OrtpNetworkSimulatorParams *params){
OrtpNetworkSimulatorCtx *sim=session->net_sim_ctx;
if (params->enabled){
......@@ -63,6 +136,10 @@ void rtp_session_enable_network_simulation(RtpSession *session, const OrtpNetwor
sim->params.max_buffer_size=sim->params.max_bandwidth;
ortp_message("Network simulation: Max buffer size not set for RTP session [%p], using [%i]",session,sim->params.max_buffer_size);
}
if (params->mode==OrtpNetworkSimulatorOutbound && !sim->thread_started){
sim->thread_started=TRUE;
ortp_thread_create(&sim->thread, NULL, outboud_simulator_thread, session);
}
session->net_sim_ctx=sim;
ortp_message("Network simulation: enabled with the following parameters:\n"
......@@ -72,17 +149,20 @@ void rtp_session_enable_network_simulation(RtpSession *session, const OrtpNetwor
"\tmax_bandwidth=%.1f\n"
"\tmax_buffer_size=%d\n"
"\tjitter_density=%.1f\n"
"\tjitter_strength=%.1f\n",
"\tjitter_strength=%.1f\n"
"\tmode=%s\n",
params->latency,
params->loss_rate,
params->consecutive_loss_probability,
params->max_bandwidth,
params->max_buffer_size,
params->jitter_burst_density,
params->jitter_strength);
params->jitter_strength,
simulator_mode_to_string(params->mode)
);
}else{
if (sim!=NULL) ortp_network_simulator_destroy(sim);
session->net_sim_ctx=NULL;
if (sim!=NULL) ortp_network_simulator_destroy(sim);
}
}
......@@ -110,7 +190,6 @@ static mblk_t * simulate_latency(RtpSession *session, mblk_t *input){
if (TIME_IS_NEWER_THAN(current_ts, output->reserved2)){
output->reserved2=0;
getq(&sim->latency_q);
/*return the first dequeued packet*/
return output;
}
......@@ -268,3 +347,87 @@ mblk_t * rtp_session_network_simulate(RtpSession *session, mblk_t *input, bool_t
return om;
}
static void rtp_session_schedule_outbound_network_simulator(RtpSession *session, ortpTimeSpec *sleep_until){
mblk_t *om;
int count=0;
bool_t is_rtp_packet;
if (!session->net_sim_ctx)
return;
if (!session->net_sim_ctx->params.enabled)
return;
if (session->net_sim_ctx->params.mode==OrtpNetworkSimulatorOutbound){
sleep_until->tv_sec=0;
sleep_until->tv_nsec=0;
ortp_mutex_lock(&session->net_sim_ctx->mutex);
while((om=getq(&session->net_sim_ctx->send_q))!=NULL){
count++;
ortp_mutex_unlock(&session->net_sim_ctx->mutex);
is_rtp_packet=om->reserved1; /*it was set by _rtp_session_sendto()*/
om=rtp_session_network_simulate(session,om, &is_rtp_packet);
if (om){
_ortp_sendto(is_rtp_packet ? session->rtp.gs.socket : session->rtcp.gs.socket, om, 0, (struct sockaddr*)&om->net_addr, om->net_addrlen);
freemsg(om);
}
ortp_mutex_lock(&session->net_sim_ctx->mutex);
}
ortp_mutex_unlock(&session->net_sim_ctx->mutex);
if (count==0){
/*even if no packets were queued, we have to schedule the simulator*/
is_rtp_packet=TRUE;
om=rtp_session_network_simulate(session,NULL, &is_rtp_packet);
if (om){
_ortp_sendto(is_rtp_packet ? session->rtp.gs.socket : session->rtcp.gs.socket, om, 0, (struct sockaddr*)&om->net_addr, om->net_addrlen);
freemsg(om);
}
}
}else if (session->net_sim_ctx->params.mode==OrtpNetworkSimulatorOutboundControlled){
#if defined(ORTP_TIMESTAMP)
ortpTimeSpec current;
ortpTimeSpec packet_time;
mblk_t *todrop=NULL;
ortp_mutex_lock(&session->net_sim_ctx->mutex);
while((om=peekq(&session->net_sim_ctx->send_q))!=NULL){
ortp_mutex_unlock(&session->net_sim_ctx->mutex);
if (todrop) {
freemsg(todrop); /*free the last message while the mutex is not held*/
todrop=NULL;
}
ortp_get_cur_time(&current);
packet_time.tv_sec=om->timestamp.tv_sec;
packet_time.tv_nsec=om->timestamp.tv_usec*1000LL;
if (packet_time.tv_sec<=current.tv_sec && packet_time.tv_nsec<=current.tv_nsec){
is_rtp_packet=om->reserved1; /*it was set by _rtp_session_sendto()*/
_ortp_sendto(is_rtp_packet ? session->rtp.gs.socket : session->rtcp.gs.socket, om, 0, (struct sockaddr*)&om->net_addr, om->net_addrlen);
todrop=om;
}else if (om->timestamp.tv_sec==0 && om->timestamp.tv_usec==0){
todrop=om; /*simulate a packet loss*/
}else {
/*no packet is to be sent yet; set the time at which we want to be called*/
*sleep_until=packet_time;
break;
}
ortp_mutex_lock(&session->net_sim_ctx->mutex);
if (todrop) getq(&session->net_sim_ctx->send_q); /* pop the message while the mutex is held*/
}
ortp_mutex_unlock(&session->net_sim_ctx->mutex);
if (todrop) freemsg(todrop);
if (sleep_until->tv_sec==0){
/*no packet in the queue yet, schedule a wake up not too far*/
sleep_until->tv_sec=current.tv_sec;
sleep_until->tv_nsec=current.tv_nsec+1000000LL; /*in 1 ms*/
}
#else
ortp_mutex_lock(&session->net_sim_ctx->mutex);
while((om=getq(&session->net_sim_ctx->send_q))!=NULL){
ortp_mutex_unlock(&session->net_sim_ctx->mutex);
freemsg(om);
ortp_error("Network simulator is in mode OrtpNetworkSimulatorOutboundControlled but oRTP wasn't compiled with --enable-ntp-timestamp.");
ortp_mutex_lock(&session->net_sim_ctx->mutex);
}
#endif
}
}
......@@ -101,10 +101,7 @@ char * ortp_strdup(const char *tmp){
* ioctlsocket on Win32.
* int retrun the result of the system method
*/
int set_non_blocking_socket (ortp_socket_t sock)
{
int set_non_blocking_socket (ortp_socket_t sock){
#if !defined(_WIN32) && !defined(_WIN32_WCE)
return fcntl (sock, F_SETFL, O_NONBLOCK);
#else
......@@ -758,6 +755,56 @@ uint64_t ortp_get_cur_time_ms(void) {
return (ts.tv_sec * 1000LL) + ((ts.tv_nsec + 500000LL) / 1000000LL);
}
void ortp_sleep_ms(int ms){
#ifdef WIN32
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
Sleep(ms);
#else
HANDLE sleepEvent = CreateEventEx(NULL, NULL, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS);
if (!sleepEvent) return;
WaitForSingleObjectEx(sleepEvent, ms, FALSE);
CloseHandle(sleepEvent);
#endif
#else
struct timespec ts;
ts.tv_sec=0;
ts.tv_nsec=ms*1000000LL;
nanosleep(&ts,NULL);
#endif
}
void ortp_sleep_until(const ortpTimeSpec *ts){
#ifdef __linux
struct timespec rq;
rq.tv_sec=ts->tv_sec;
rq.tv_nsec=ts->tv_nsec;
while (clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &rq, NULL)==-1 && errno==EINTR){
}
#else
ortpTimeSpec current;
ortpTimeSpec diff;
ortp_get_cur_time(&current);
diff.tv_sec=ts->tv_sec-current.tv_sec;
diff.tv_nsec=ts->tv_nsec-current.tv_nsec;
if (diff.tv_nsec<0){
diff.tv_nsec+=1000000000LL;
diff.tv_sec-=1;
}
# ifdef WIN32
ortp_sleep_ms((diff.tv_sec * 1000LL) + (diff.tv_nsec/1000000LL));
# else
{
struct timespec dur,rem;
dur.tv_sec=diff.tv_sec;
dur.tv_nsec=diff.tv_nsec;
while (nanosleep(&dur,&rem)==-1 && errno==EINTR){
dur=rem;
};
}
# endif
#endif
}
#if defined(_WIN32) && !defined(_MSC_VER)
char* strtok_r(char *str, const char *delim, char **nextp){
char *ret;
......
......@@ -2039,7 +2039,7 @@ int meta_rtp_transport_sendto(RtpTransport *t, mblk_t *msg , int flags, const st
if (m->endpoint!=NULL){
ret=m->endpoint->t_sendto(m->endpoint,msg,flags,to,tolen);
}else{
ret=_ortp_sendto(m->is_rtp?t->session->rtp.gs.socket:t->session->rtcp.gs.socket,msg,flags,to,tolen);
ret=_rtp_session_sendto(t->session, m->is_rtp,msg,flags,to,tolen);
}
return ret;
}
......@@ -2105,7 +2105,7 @@ int meta_rtp_transport_modifier_inject_packet_to(const RtpTransport *t, RtpTrans
if (m->endpoint!=NULL){
ret=m->endpoint->t_sendto(m->endpoint,msg,flags,to,tolen);
}else{
ret=sendto(m->is_rtp?t->session->rtp.gs.socket:t->session->rtcp.gs.socket,(void*)msg->b_rptr,msgdsize(msg),flags,to,tolen);
ret=_rtp_session_sendto(t->session, m->is_rtp,msg,flags,to,tolen);
}
return ret;
}
......@@ -2142,9 +2142,9 @@ int meta_rtp_transport_recvfrom(RtpTransport *t, mblk_t *msg, int flags, struct
prev_ret=ret;
msg->b_wptr+=ret;
/*store recv addr for futur use*/
memcpy(&msg->src_addr,from,*fromlen);
msg->src_addrlen = *fromlen;
/*store recv addr for use by modifiers*/
memcpy(&msg->net_addr,from,*fromlen);
msg->net_addrlen = *fromlen;
for (;last_elem!=NULL;last_elem=o_list_prev(last_elem)){
RtpTransportModifier *rtm=(RtpTransportModifier*)last_elem->data;
......
......@@ -1022,6 +1022,25 @@ int _ortp_sendto(ortp_socket_t sockfd, mblk_t *m, int flags, const struct sockad
return error;
}
int _rtp_session_sendto(RtpSession *session, bool_t is_rtp, mblk_t *m, int flags, const struct sockaddr *destaddr, socklen_t destlen){
int ret;
if (session->net_sim_ctx && session->net_sim_ctx->params.mode==OrtpNetworkSimulatorOutbound){
ret=msgdsize(m);
m=dupmsg(m);
memcpy(&m->net_addr,destaddr,destlen);
m->net_addrlen=destlen;
m->reserved1=is_rtp;
ortp_mutex_lock(&session->net_sim_ctx->mutex);
putq(&session->net_sim_ctx->send_q, m);
ortp_mutex_unlock(&session->net_sim_ctx->mutex);
}else{
ortp_socket_t sockfd=is_rtp ? session->rtp.gs.socket : session->rtcp.gs.socket;
ret=_ortp_sendto(sockfd, m, flags, destaddr, destlen);
}
return ret;
}
static void update_sent_bytes(OrtpStream *os, int nbytes) {
int overhead = ortp_stream_is_ipv6(os) ? IP6_UDP_OVERHEAD : IP_UDP_OVERHEAD;
if ((os->sent_bytes == 0) && (os->send_bw_start.tv_sec == 0) && (os->send_bw_start.tv_usec == 0)) {
......@@ -1049,12 +1068,11 @@ static void log_send_error(RtpSession *session, const char *type, mblk_t *m, str
static int rtp_session_rtp_sendto(RtpSession * session, mblk_t * m, struct sockaddr *destaddr, socklen_t destlen, bool_t is_aux){
int error;
ortp_socket_t sockfd=session->rtp.gs.socket;
if (rtp_session_using_transport(session, rtp)){
error = (session->rtp.gs.tr->t_sendto) (session->rtp.gs.tr,m,0,destaddr,destlen);
}else{
error=_ortp_sendto(sockfd,m,0,destaddr,destlen);
error=_rtp_session_sendto(session, TRUE,m,0,destaddr,destlen);
}
if (!is_aux){
/*errors to auxiliary destinations are not notified*/
......@@ -1070,8 +1088,7 @@ static int rtp_session_rtp_sendto(RtpSession * session, mblk_t * m, struct socka
return error;
}
int
rtp_session_rtp_send (RtpSession * session, mblk_t * m){
int rtp_session_rtp_send (RtpSession * session, mblk_t * m){
int error=0;
int i;
rtp_header_t *hdr;
......@@ -1113,16 +1130,8 @@ static int rtp_session_rtcp_sendto(RtpSession * session, mblk_t * m, struct sock
if (rtp_session_using_transport(session, rtcp)){
error = (session->rtcp.gs.tr->t_sendto) (session->rtcp.gs.tr, m, 0,
destaddr, destlen);
}
else{
#ifdef USE_SENDMSG
error=rtp_sendmsg(sockfd,m,destaddr, destlen);
#else
if (m->b_cont!=NULL){
msgpullup(m,-1);
}
error = sendto(sockfd, (char*)m->b_rptr,(int) (m->b_wptr - m->b_rptr), 0, destaddr, destlen);
#endif
}else{
error=_ortp_sendto(sockfd,m,0,destaddr,destlen);
}
if (!is_aux){
if (error < 0){
......@@ -1162,9 +1171,8 @@ rtp_session_rtcp_send (RtpSession * session, mblk_t * m){
OrtpAddress *addr=(OrtpAddress*)elem->data;
rtp_session_rtcp_sendto(session,m,(struct sockaddr*)&addr->addr,addr->len,TRUE);
}
}else ortp_message("Not sending rtcp report, rtcp disabled.");
freemsg (m);
freemsg(m);
return error;
}
......@@ -1430,8 +1438,8 @@ static void rtp_process_incoming_packet(RtpSession * session, mblk_t * mp, bool_
if (!mp){
return;
}
remaddr = (struct sockaddr *)&mp->src_addr;
addrlen = mp->src_addrlen;
remaddr = (struct sockaddr *)&mp->net_addr;
addrlen = mp->net_addrlen;
if (is_rtp_packet){
if (session->use_connect){
......@@ -1504,9 +1512,9 @@ int rtp_session_rtp_recv (RtpSession * session, uint32_t user_ts) {
mp->b_wptr+=error;
/*if we use the network simulator, store packet source address for later use(otherwise it will be used immediately)*/
memcpy(&mp->src_addr,&remaddr,addrlen);
mp->src_addrlen = addrlen;
if (session->net_sim_ctx){
memcpy(&mp->net_addr,&remaddr,addrlen);
mp->net_addrlen = addrlen;
if (session->net_sim_ctx && session->net_sim_ctx->params.mode==OrtpNetworkSimulatorInbound){
mp=rtp_session_network_simulate(session,mp,&is_rtp_packet);
}
rtp_process_incoming_packet(session,mp,is_rtp_packet,user_ts);
......@@ -1530,7 +1538,7 @@ int rtp_session_rtp_recv (RtpSession * session, uint32_t user_ts) {
#endif
}else{
/*EWOULDBLOCK errors or transports returning 0 are ignored.*/
if (session->net_sim_ctx){
if (session->net_sim_ctx && session->net_sim_ctx->params.mode==OrtpNetworkSimulatorInbound){
/*drain possible packets queued in the network simulator*/
mp=rtp_session_network_simulate(session,NULL,&is_rtp_packet);
rtp_process_incoming_packet(session,mp,is_rtp_packet,user_ts);
......@@ -1581,11 +1589,12 @@ int rtp_session_rtcp_recv (RtpSession * session) {
{
mp->b_wptr += error;
memcpy(&mp->src_addr,&remaddr,addrlen);
mp->src_addrlen = addrlen;
memcpy(&mp->net_addr,&remaddr,addrlen);
mp->net_addrlen = addrlen;
if (session->net_sim_ctx)
if (session->net_sim_ctx && session->net_sim_ctx->params.mode==OrtpNetworkSimulatorInbound){
mp=rtp_session_network_simulate(session,mp,&is_rtp_packet);
}
rtp_process_incoming_packet(session,mp,is_rtp_packet,session->rtp.rcv_last_app_ts);
session->rtcp.gs.cached_mp=NULL;
}
......@@ -1607,7 +1616,7 @@ int rtp_session_rtcp_recv (RtpSession * session) {
session->rtp.recv_errno=errnum;
}else{
/*EWOULDBLOCK errors or transports returning 0 are ignored.*/
if (session->net_sim_ctx){
if (session->net_sim_ctx && session->net_sim_ctx->params.mode==OrtpNetworkSimulatorInbound){
/*drain possible packets queued in the network simulator*/
mp=rtp_session_network_simulate(session,NULL,&is_rtp_packet);
rtp_process_incoming_packet(session,mp,is_rtp_packet,session->rtp.rcv_last_app_ts);
......
......@@ -23,7 +23,7 @@
int main(int argc, char *argv[]){
char value[256]={0};
if (argc<3){
fprintf(stderr,"%s <fmtp-line> <param-to-extract>\n");
fprintf(stderr,"%s <fmtp-line> <param-to-extract>\n", argv[0]);
return -1;
}
if (fmtp_get_value(argv[1],argv[2],value,sizeof(value))){
......
......@@ -83,6 +83,6 @@ uint64_t ortp_timeval_to_ntp(const struct timeval *tv);
bool_t ortp_stream_is_ipv6(OrtpStream *os);
int _ortp_sendto(ortp_socket_t sockfd, mblk_t *m, int flags, const struct sockaddr *destaddr, socklen_t destlen);
int _rtp_session_sendto(RtpSession *session, bool_t is_rtp, mblk_t *m, int flags, const struct sockaddr *destaddr, socklen_t destlen);
int _ortp_sendto(ortp_socket_t sockfd, mblk_t *m, int flags, const struct sockaddr *destaddr, socklen_t destlen);
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment