OrtpZrtpContext* ortp_zrtp_multistream_new(OrtpZrtpContext* activeContext, RtpSession *s, OrtpZrtpParams *params) { int32_t length; char *multiparams=NULL; int i=0; if (!zrtp_isMultiStreamAvailable(activeContext->zrtpContext)) { ortp_warning("could't add stream: mutlistream not supported by peer"); } if (zrtp_isMultiStream(activeContext->zrtpContext)) { ortp_fatal("Error: should derive multistream from DH or preshared modes only"); } multiparams=zrtp_getMultiStrParams(activeContext->zrtpContext, &length); ortp_message("ZRTP multiparams length is %d", length); for (;i<length;i++) { ortp_message("%d", multiparams[i]); } ortp_message("Initializing ZRTP context"); ZrtpContext *context = zrtp_CreateWrapper(); OrtpZrtpContext *userData=createUserData(context); userData->session=s; ortp_zrtp_configure(context); zrtp_initializeZrtpEngine(context, &userData->zrtp_cb, userAgentStr, params->zid_file, userData, 0); ortp_message("setting zrtp_setMultiStrParams"); zrtp_setMultiStrParams(context,multiparams,length); return ortp_zrtp_configure_context(userData,s,params); }
static OrtpZrtpContext* ortp_zrtp_configure_context(OrtpZrtpContext *userData, RtpSession *s, OrtpZrtpParams *params) { ZrtpContext *context=userData->zrtpContext; if (s->rtp.tr || s->rtcp.tr) ortp_warning("Overwriting rtp or rtcp transport with ZRTP one"); userData->rtpt.data=context; userData->rtpt.t_getsocket=ozrtp_rtp_getsocket; userData->rtpt.t_sendto=ozrtp_rtp_sendto; userData->rtpt.t_recvfrom=ozrtp_rtp_recvfrom; userData->rtcpt.data=context; userData->rtcpt.t_getsocket=ozrtp_rtcp_getsocket; userData->rtcpt.t_sendto=ozrtp_rtcp_sendto; userData->rtcpt.t_recvfrom=ozrtp_rtcp_recvfrom; rtp_session_set_transports(s, &userData->rtpt, &userData->rtcpt); ortp_message("Starting ZRTP engine"); zrtp_setEnrollmentMode(context,FALSE);//because it is uninitialized in zrtpcpp. zrtp_startZrtpEngine(context); return userData; }
static void print_zrtp_packet(const char *info, const uint8_t *rtp) { const uint8_t *zmessage=rtp+ZRTP_MESSAGE_OFFSET; uint16_t zmessage_seq=get_rtp_seqnumber(rtp); char msgType[9]; parseZrtpMessageType(msgType, zmessage); /* uint16_t zmessage_length = get_zrtp_message_length(zmessage); uint32_t crc = get_zrtp_packet_crc((uint32_t*) rtp, zmessage_length); ortp_message("%s ZRTP seq=%u type=%s CRC=%u, ln=%u", info, zmessage_seq, msgType, crc, zmessage_length); */ if (strcmp(zrtpErrorType, msgType) == 0) { uint32_t *msg32=(uint32_t*)zmessage; uint32_t errcode=ntohl(msg32[3]); ortp_error("%s ZRTP %s 0x%x %u", info, msgType, errcode, zmessage_seq); } else { ortp_message("%s ZRTP %s %u", info, msgType, zmessage_seq); } /* uint32_t *msg32=(uint32_t*)zmessage; int i=0; for (; i<zmessage_length; i++) { ortp_message("%u", ntohl(msg32[i])); }*/ }
void ortp_zrtp_context_destroy(OrtpZrtpContext *ctx) { ortp_message("Stopping ZRTP context"); zrtp_stopZrtpEngine(ctx->zrtpContext); ortp_message("Destroying ZRTP wrapper"); zrtp_DestroyWrapper(ctx->zrtpContext); ortp_message("Destroying ORTP-ZRTP mutex"); ortp_mutex_destroy(&ctx->mutex); ortp_message("Destroying SRTP contexts"); if (ctx->srtpSend != NULL) srtp_dealloc(ctx->srtpSend); if (ctx->srtpRecv != NULL) srtp_dealloc(ctx->srtpRecv); ortp_message("ORTP-ZRTP context destroyed"); }
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(¶m,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, ¶m))) { ortp_warning("Ortp simulator: set pthread_setschedparam failed: %s",strerror(result)); } else { ortp_message("ortp network simulator: sched policy set to %s and priority value (%i)", sched_policy_to_string(policy), param.sched_priority); } #endif }
static void rtp_session_create_and_send_rtcp_packet(RtpSession *session, bool_t full) { mblk_t *m=NULL; bool_t is_sr = FALSE; if (session->rtp.last_rtcp_packet_count < session->stats.packet_sent) { m = make_sr(session); session->rtp.last_rtcp_packet_count = (uint32_t)session->stats.packet_sent; is_sr = TRUE; } else if (session->stats.packet_recv > 0) { /* Don't send RR when no packet are received yet */ m = make_rr(session); is_sr = FALSE; } if (m != NULL) { append_sdes(session, m, full); if ((full == TRUE) && (session->rtcp.xr_conf.enabled == TRUE)) { append_xr_packets(session, m); } if (rtp_session_avpf_enabled(session) == TRUE) { append_fb_packets(session, m); } /* Send the compound packet */ notify_sent_rtcp(session, m); ortp_message("Sending RTCP %s compound message on session [%p].",(is_sr ? "SR" : "RR"), session); rtp_session_rtcp_send(session, m); } }
int main(int argc, char *argv[]) { RtpSession *session; unsigned char buffer[160]; int i; FILE *infile; char *ssrc; uint32_t user_ts=0; int tel=0; if (argc<4){ printf(help); return -1; } ortp_init(); ortp_scheduler_init(); /* set the telephony event payload type to 96 in the av profile.*/ rtp_profile_set_payload(&av_profile,96,&payload_type_telephone_event); session=rtp_session_new(RTP_SESSION_SENDONLY); rtp_session_set_scheduling_mode(session,1); rtp_session_set_blocking_mode(session,1); rtp_session_set_remote_addr(session,argv[2],atoi(argv[3])); rtp_session_set_send_payload_type(session,0); ssrc=getenv("SSRC"); if (ssrc!=NULL) { printf("using SSRC=%i.\n",atoi(ssrc)); rtp_session_set_ssrc(session,atoi(ssrc)); } infile=fopen(argv[1],"rb"); if (infile==NULL) { perror("Cannot open file"); return -1; } signal(SIGINT,stophandler); while( ((i=fread(buffer,1,160,infile))>0) && (runcond) ) { //ortp_message("Sending packet."); rtp_session_send_with_ts(session,buffer,i,user_ts); user_ts+=160; tel++; if (tel==50){ tel=0; ortp_message("Sending telephony event packet."); rtp_session_send_dtmf(session,'*',user_ts); user_ts+=160+160+160; /* the duration of the dtmf */ } } fclose(infile); rtp_session_destroy(session); ortp_exit(); ortp_global_stats_display(); return 0; }
void rtp_session_enable_network_simulation(RtpSession *session, const OrtpNetworkSimulatorParams *params){ OrtpNetworkSimulatorCtx *sim=session->net_sim_ctx; if (params->enabled){ if (sim==NULL) sim=simulator_ctx_new(); sim->drop_by_congestion=sim->drop_by_loss=sim->total_count=0; sim->params=*params; if (sim->params.jitter_burst_density>0 && sim->params.jitter_strength>0 && sim->params.max_bandwidth==0){ sim->params.max_bandwidth=1024000; ortp_message("Network simulation: jitter requested but max_bandwidth is not set. Using default value of %f bits/s.", sim->params.max_bandwidth); } if (sim->params.max_bandwidth && sim->params.max_buffer_size==0) { 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); } session->net_sim_ctx=sim; if ((params->mode==OrtpNetworkSimulatorOutbound || params->mode==OrtpNetworkSimulatorOutboundControlled) && !sim->thread_started){ sim->thread_started=TRUE; ortp_thread_create(&sim->thread, NULL, outboud_simulator_thread, session); } ortp_message("Network simulation: enabled with the following parameters:\n" "\tlatency=%d\n" "\tloss_rate=%.1f\n" "\tconsecutive_loss_probability=%.1f\n" "\tmax_bandwidth=%.1f\n" "\tmax_buffer_size=%d\n" "\tjitter_density=%.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, ortp_network_simulator_mode_to_string(params->mode) ); }else{ session->net_sim_ctx=NULL; if (sim!=NULL) ortp_network_simulator_destroy(sim); } }
OrtpZrtpContext* ortp_zrtp_context_new(RtpSession *s, OrtpZrtpParams *params){ ZrtpContext *context = zrtp_CreateWrapper(); OrtpZrtpContext *userData=createUserData(context); userData->session=s; ortp_zrtp_configure(context); ortp_message("Initialized ZRTP context"); zrtp_initializeZrtpEngine(context, &userData->zrtp_cb, userAgentStr, params->zid_file, userData, 0); return ortp_zrtp_configure_context(userData,s,params); }
static mblk_t *simulate_bandwidth_limit(RtpSession *session, mblk_t *input){ OrtpNetworkSimulatorCtx *sim=session->net_sim_ctx; struct timeval current; int64_t elapsed; int bits; mblk_t *output=NULL; #ifdef ORTP_INET6 int overhead=(session->rtp.sockfamily==AF_INET6) ? IP6_UDP_OVERHEAD : IP_UDP_OVERHEAD; #else int overhead=IP_UDP_OVERHEAD; #endif gettimeofday(¤t,NULL); if (sim->last_check.tv_sec==0){ sim->last_check=current; sim->bit_budget=0; } /*update the budget */ elapsed=elapsed_us(&sim->last_check,¤t); sim->bit_budget+=(elapsed*(int64_t)sim->params.max_bandwidth)/1000000LL; sim->last_check=current; /* queue the packet for sending*/ if (input){ putq(&sim->q,input); bits=(msgdsize(input)+overhead)*8; sim->qsize+=bits; } /*flow control*/ while (sim->qsize>=sim->params.max_bandwidth){ ortp_message("rtp_session_network_simulate(): discarding packets."); output=getq(&sim->q); if (output){ bits=(msgdsize(output)+overhead)*8; sim->qsize-=bits; freemsg(output); } } output=NULL; /*see if we can output a packet*/ if (sim->bit_budget>=0){ output=getq(&sim->q); if (output){ bits=(msgdsize(output)+overhead)*8; sim->bit_budget-=bits; sim->qsize-=bits; } } if (output==NULL && input==NULL && sim->bit_budget>=0){ /* unused budget is lost...*/ sim->last_check.tv_sec=0; } return output; }
/** * Initialize the oRTP library. You should call this function first before using * oRTP API. **/ void ortp_init() { if (ortp_initialized++) return; #ifdef _WIN32 win32_init_sockets(); #endif ortp_init_logger(); av_profile_init(&av_profile); ortp_global_stats_reset(); init_random_number_generator(); ortp_message("oRTP-" ORTP_VERSION " initialized."); }
/** * Switch off the security for the defined part. * * @param ctx * Pointer to the opaque ZrtpContext structure. * @param part Defines for which part (sender or receiver) to * switch off security */ static void ozrtp_srtpSecretsOff (ZrtpContext* ctx, int32_t part ) { OrtpZrtpContext *userData = user_data(ctx); if (userData->srtpRecv != NULL) { srtp_dealloc(userData->srtpRecv); userData->srtpRecv=NULL; } if (userData->srtpSend != NULL) { srtp_dealloc(userData->srtpSend); userData->srtpSend=NULL; } ortp_message("ZRTP secrets off"); }
/** * Initialize the oRTP library. You should call this function first before using * oRTP API. **/ void ortp_init() { static bool_t initialized=FALSE; if (initialized) return; initialized=TRUE; #ifdef WIN32 win32_init_sockets(); #endif av_profile_init(&av_profile); ortp_global_stats_reset(); init_random_number_generator(); ortp_message("oRTP-" ORTP_VERSION " initialized."); }
err_status_t ortp_srtp_init(void) { err_status_t st=0; ortp_message("srtp init"); if (!srtp_init_done) { st=srtp_init(); if (st==0) { srtp_init_done++; }else{ ortp_fatal("Couldn't initialize SRTP library."); err_reporting_init("oRTP"); } }else srtp_init_done++; return st; }
/** * Switch on the security. * * ZRTP calls this method after it has computed the SAS and check * if it is verified or not. In addition ZRTP provides information * about the cipher algorithm and key length for the SRTP session. * * This method must enable SRTP processing if it was not enabled * during sertSecretsReady(). * * @param ctx * Pointer to the opaque ZrtpContext structure. * @param c The name of the used cipher algorithm and mode, or * NULL * * @param s The SAS string * * @param verified if <code>verified</code> is true then SAS was * verified by both parties during a previous call. */ static void ozrtp_rtpSecretsOn (ZrtpContext* ctx, char* c, char* s, int32_t verified ){ // OrtpZrtpContext *userData = user_data(ctx); // srtp processing is enabled in SecretsReady fuction when receiver secrets are ready // Indeed, the secrets on is called before both parts are given to secretsReady. OrtpEventData *eventData; OrtpEvent *ev; ev=ortp_event_new(ORTP_EVENT_ZRTP_SAS_READY); eventData=ortp_event_get_data(ev); memcpy(eventData->info.zrtp_sas.sas,s,4); eventData->info.zrtp_sas.sas[4]=0; eventData->info.zrtp_sas.verified=(verified != 0) ? TRUE : FALSE; rtp_session_dispatch_event(user_data(ctx)->session, ev); ortp_message("ZRTP secrets on: SAS is %s previously verified %s - algo %s", s, verified == 0 ? "no" : "yes", c); }
void ortp_network_simulator_destroy(OrtpNetworkSimulatorCtx *sim){ int drop_by_flush=sim->latency_q.q_mcount+sim->q.q_mcount; if (sim->total_count>0){ ortp_message("Network simulation: destroyed. Statistics are:" "%d/%d(%.1f%%, param=%.1f) packets dropped by loss, " "%d/%d(%.1f%%) packets dropped by congestion, " "%d/%d(%.1f%%) packets flushed." , sim->drop_by_loss, sim->total_count, sim->drop_by_loss*100.f/sim->total_count, sim->params.loss_rate , sim->drop_by_congestion, sim->total_count, sim->drop_by_congestion*100.f/sim->total_count , drop_by_flush, sim->total_count, drop_by_flush*100.f/sim->total_count ); } 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); }
int main(int argc, char *argv[]) { RtpSession *session; unsigned char buffer[160]; int i; FILE *infile; char *ssrc; uint32_t packet_ts=0,send_ts=0; uint32_t send_ts_inc=160; int clockslide=0; int jitter=0; if (argc<4){ printf("%s",help); return -1; } for(i=4;i<argc;i++){ if (strcmp(argv[i],"--with-clockslide")==0){ i++; if (i>=argc) { printf("%s",help); return -1; } clockslide=atoi(argv[i]); ortp_message("Using clockslide of %i milisecond every 50 packets.",clockslide); }else if (strcmp(argv[i],"--with-ptime")==0){ ortp_message("Ptime related jitter will be added to outgoing stream."); i++; if (i>=argc) { printf("%s",help); return -1; } jitter=atoi(argv[i]); send_ts_inc=jitter*8; } } ortp_init(); ortp_scheduler_init(); ortp_set_log_level_mask(NULL, ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR); session=rtp_session_new(RTP_SESSION_SENDONLY); rtp_session_set_scheduling_mode(session,1); rtp_session_set_blocking_mode(session,1); rtp_session_set_connected_mode(session,TRUE); rtp_session_set_remote_addr(session,argv[2],atoi(argv[3])); rtp_session_set_payload_type(session,0); ssrc=getenv("SSRC"); if (ssrc!=NULL) { printf("using SSRC=%i.\n",atoi(ssrc)); rtp_session_set_ssrc(session,atoi(ssrc)); } #ifndef _WIN32 infile=fopen(argv[1],"r"); #else infile=fopen(argv[1],"rb"); #endif if (infile==NULL) { perror("Cannot open file"); return -1; } signal(SIGINT,stophandler); while( ((i=fread(buffer,1,160,infile))>0) && (runcond) ) { mblk_t *m=rtp_session_create_packet(session,RTP_FIXED_HEADER_SIZE,buffer,i); __rtp_session_sendm_with_ts(session,m,packet_ts,send_ts); packet_ts+=160; if ((send_ts+send_ts_inc)<=packet_ts){ send_ts+=send_ts_inc; } if (clockslide!=0 && send_ts%(160*50)==0){ ortp_message("Clock sliding of %i miliseconds now",clockslide); rtp_session_make_time_distorsion(session,clockslide); } } fclose(infile); rtp_session_destroy(session); ortp_exit(); ortp_global_stats_display(); return 0; }
void jitter_control_dump_stats(JitterControl *ctl){ ortp_message("JitterControl:\n\tslide=%g,jitter=%g,count=%i", ctl->slide,ctl->jitter, ctl->count); }
OrtpZrtpContext* ortp_zrtp_multistream_new(OrtpZrtpContext* activeContext, RtpSession *s, OrtpZrtpParams *params) { ortp_message("ZRTP is disabled - not implemented yet - not adding stream"); return NULL; }
OrtpZrtpContext* ortp_zrtp_context_new(RtpSession *s, OrtpZrtpParams *params){ ortp_message("ZRTP is disabled - not implemented yet"); return NULL; }
void jitter_control_dump_stats(JitterControl *ctl){ ortp_message("JitterControl:\n\tslide=%g,jitter=%g,adapt_jitt_comp_ts=%i,corrective_slide=%i, count=%i", (double)ctl->slide,ctl->jitter, ctl->adapt_jitt_comp_ts, ctl->corrective_slide,ctl->count); }
err_status_t ortp_srtp_init(void) { ortp_message("srtp init"); return srtp_init(); }
/** * Send information messages to the hosting environment. * * The ZRTP implementation uses this method to send information * messages to the host. Along with the message ZRTP provides a * severity indicator that defines: Info, Warning, Error, * Alert. Refer to the <code>MessageSeverity</code> enum above. * * @param ctx * Pointer to the opaque ZrtpContext structure. * @param severity * This defines the message's severity * @param subCode * The subcode identifying the reason. * @see ZrtpCodes#MessageSeverity */ static void ozrtp_sendInfo (ZrtpContext* ctx, int32_t severity, int32_t subCode ) { const char* submsg; switch (subCode) { case zrtp_InfoHelloReceived: /*!< Hello received, preparing a Commit */ submsg="zrtp_InfoHelloReceived"; break; case zrtp_InfoCommitDHGenerated: /*!< Commit: Generated a public DH key */ submsg="zrtp_InfoCommitDHGenerated"; break; case zrtp_InfoRespCommitReceived: /*!< Responder: Commit received, preparing DHPart1 */ submsg="zrtp_InfoRespCommitReceived"; break; case zrtp_InfoDH1DHGenerated: /*!< DH1Part: Generated a public DH key */ submsg="zrtp_InfoDH1DHGenerated"; break; case zrtp_InfoInitDH1Received: /*!< Initiator: DHPart1 received, preparing DHPart2 */ submsg="zrtp_InfoInitDH1Received"; break; case zrtp_InfoRespDH2Received: /*!< Responder: DHPart2 received, preparing Confirm1 */ submsg="zrtp_InfoRespDH2Received"; break; case zrtp_InfoInitConf1Received: /*!< Initiator: Confirm1 received, preparing Confirm2 */ submsg="zrtp_InfoInitConf1Received"; break; case zrtp_InfoRespConf2Received: /*!< Responder: Confirm2 received, preparing Conf2Ack */ submsg="zrtp_InfoRespConf2Received"; break; case zrtp_InfoRSMatchFound: /*!< At least one retained secrets matches - security OK */ submsg="zrtp_InfoRSMatchFound"; break; case zrtp_InfoSecureStateOn: /*!< Entered secure state */ submsg="zrtp_InfoSecureStateOn"; break; case zrtp_InfoSecureStateOff: /*!< No more security for this session */ submsg="zrtp_InfoSecureStateOff"; break; default: submsg="unkwown"; break; } switch (severity) { case zrtp_Info: ortp_message("ZRTP INFO %s",submsg); break; case zrtp_Warning: /*!< A Warning message - security can be established */ ortp_warning("ZRTP %s",submsg); break; case zrtp_Severe:/*!< Severe error, security will not be established */ ortp_error("ZRTP SEVERE %s",submsg); break; case zrtp_ZrtpError: ortp_error("ZRTP ERROR %s",submsg); break; default: ortp_error("ZRTP UNKNOWN ERROR %s",submsg); break; } if (subCode == zrtp_InfoSecureStateOn || subCode == zrtp_InfoSecureStateOff) { OrtpEventData *eventData; OrtpEvent *ev; ev=ortp_event_new(ORTP_EVENT_ZRTP_ENCRYPTION_CHANGED); eventData=ortp_event_get_data(ev); eventData->info.zrtp_stream_encrypted=(subCode == zrtp_InfoSecureStateOn); rtp_session_dispatch_event(user_data(ctx)->session, ev); } }
/** * SRTP crypto data ready for the sender or receiver. * * The ZRTP implementation calls this method right after all SRTP * secrets are computed and ready to be used. The parameter points * to a structure that contains pointers to the SRTP secrets and a * <code>enum Role</code>. The called method (the implementation * of this abstract method) must either copy the pointers to the SRTP * data or the SRTP data itself to a save place. The SrtpSecret_t * structure is destroyed after the callback method returns to the * ZRTP implementation. * * The SRTP data themselves are obtained in the ZRtp object and are * valid as long as the ZRtp object is active. TheZRtp's * destructor clears the secrets. Thus the called method needs to * save the pointers only, ZRtp takes care of the data. * * The implementing class may enable SRTP processing in this * method or delay it to srtpSecertsOn(). * * @param ctx * Pointer to the opaque ZrtpContext structure. * @param secrets A pointer to a SrtpSecret_t structure that * contains all necessary data. * * @param part for which part (Sender or Receiver) this data is * valid. * * @return Returns false if something went wrong during * initialization of SRTP context, for example memory shortage. */ static int32_t ozrtp_srtpSecretsReady (ZrtpContext* ctx, C_SrtpSecret_t* secrets, int32_t part ) { srtp_policy_t policy; err_status_t srtpCreateStatus; err_status_t addStreamStatus; OrtpZrtpContext *userData = user_data(ctx); ortp_message("ZRTP secrets for %s are ready; auth tag len is %i", (part == ForSender) ? "sender" : "receiver",secrets->srtpAuthTagLen); // Get authentication and cipher algorithms in srtp format if (secrets->authAlgorithm != zrtp_Sha1) { ortp_fatal("unsupported authentication algorithm by srtp"); } if (secrets->symEncAlgorithm != zrtp_Aes) { ortp_fatal("unsupported cipher algorithm by srtp"); } /* * Don't use crypto_policy_set_from_profile_for_rtp(), it is totally buggy. */ memset(&policy,0,sizeof(policy)); if (secrets->srtpAuthTagLen == 32){ crypto_policy_set_aes_cm_128_hmac_sha1_32(&policy.rtp); crypto_policy_set_aes_cm_128_hmac_sha1_32(&policy.rtcp); }else if (secrets->srtpAuthTagLen == 80){ crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtp); crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp); }else{ ortp_fatal("unsupported auth tag len"); } if (part == ForSender) { srtpCreateStatus=srtp_create(&userData->srtpSend, NULL); policy.ssrc.type=ssrc_specific; policy.ssrc.value=userData->session->snd.ssrc; // us policy.key=key_with_salt(secrets, secrets->role); addStreamStatus=srtp_add_stream(userData->srtpSend, &policy); } else { //if (part == ForReceiver) srtpCreateStatus=srtp_create(&userData->srtpRecv, NULL); policy.ssrc.type = ssrc_any_inbound; /*we don't know the incoming ssrc will be */ int32_t peerRole=secrets->role == Initiator ? Responder : Initiator; policy.key=key_with_salt(secrets,peerRole); addStreamStatus=srtp_add_stream(userData->srtpRecv, &policy); } ortp_free(policy.key); if (srtpCreateStatus != err_status_ok) { ortp_error("ZRTP Error %u during creation of SRTP context for %s", srtpCreateStatus, (part == ForSender) ? "sender" : "receiver"); return 0; } if (addStreamStatus != err_status_ok) { ortp_error("ZRTP Error %u during addition of SRTP stream for %s", addStreamStatus, (part == ForSender) ? "sender" : "receiver"); return 0; } return 1; }
static int ozrtp_rtp_recvfrom(RtpTransport *t, mblk_t *m, int flags, struct sockaddr *from, socklen_t *fromlen){ int rlen; ZrtpContext *zrtpContext = (ZrtpContext*) t->data; OrtpZrtpContext *userData = (OrtpZrtpContext*) zrtpContext->userData; // Do extra stuff first check_timer(zrtpContext, userData); // Check if something to receive rlen=rtp_session_rtp_recv_abstract(t->session->rtp.socket,m,flags,from,fromlen); if (rlen<=0) { // nothing was received or error: pass the information to caller return rlen; } uint8_t* rtp = m->b_rptr; int rtpVersion = ((rtp_header_t*)rtp)->version; // If plain or secured RTP if (rtpVersion == 2) { if (userData->srtpRecv != NULL && zrtp_inState(zrtpContext, SecureState)) { // probably srtp packet, unprotect err_status_t err = srtp_unprotect(userData->srtpRecv,m->b_wptr,&rlen); if (err != err_status_ok) { ortp_warning("srtp_unprotect failed; packet may be plain RTP"); } } // in both cases (RTP plain and deciphered srtp) return rlen; } // if ZRTP packet, send to engine uint32_t *magicField=(uint32_t *)(rtp + 4); if (rlen >= ZRTP_MIN_MSG_LENGTH && rtpVersion==0 && ntohl(*magicField) == ZRTP_MAGIC) { print_zrtp_packet("received", rtp); uint8_t *ext_header = rtp+ZRTP_MESSAGE_OFFSET; uint16_t ext_length = get_zrtp_message_length(ext_header); char messageType[9]; parseZrtpMessageType(messageType, ext_header); // Check max length if (rlen < 12 + ext_length + 4) { ortp_warning("Received malformed ZRTP-like packet: size %d (expected %d)", rlen, 12 + ext_length + 4); return 0; } // Check sequence number uint16_t seq_number = get_rtp_seqnumber(rtp); if (userData->last_recv_zrtp_seq_number != 0 && seq_number <= userData->last_recv_zrtp_seq_number) { // Discard out of order ZRTP packet ortp_message("Discarding received out of order zrtp packet: %d (expected >%d)", seq_number, userData->last_recv_zrtp_seq_number); return 0; } // Check packet checksum uint32_t rcv_crc = get_zrtp_packet_crc((uint32_t*)rtp, ext_length); uint32_t zrtp_total_packet_length = ZRTP_MESSAGE_OFFSET + 4*ext_length + 4; if (!zrtp_CheckCksum(rtp, zrtp_total_packet_length-CRC_SIZE, rcv_crc)) { ortp_warning("Bad ZRTP packet checksum %u total %u", rcv_crc, zrtp_total_packet_length); return 0; } uint32_t peerssrc = ntohl(*(uint32_t*)(rtp+8)); #if HAVE_zrtpcpp_with_len zrtp_processZrtpMessage(zrtpContext, ext_header, peerssrc,rlen); #else zrtp_processZrtpMessage(zrtpContext, ext_header, peerssrc); #endif userData->last_recv_zrtp_seq_number=seq_number; return 0; } else { // Not a ZRTP packet, accept it return rlen; } }
int main(int argc, char *argv[]) { RtpSession *session; unsigned char buffer[160]; int i; FILE *infile; char *ssrc; uint32_t user_ts=0; int clockslide=0; int jitter=0; if (argc<4){ printf("%s", help); return -1; } for(i=4;i<argc;i++){ if (strcmp(argv[i],"--with-clockslide")==0){ i++; if (i>=argc) { printf("%s", help); return -1; } clockslide=atoi(argv[i]); ortp_message("Using clockslide of %i milisecond every 50 packets.",clockslide); }else if (strcmp(argv[i],"--with-jitter")==0){ ortp_message("Jitter will be added to outgoing stream."); i++; if (i>=argc) { printf("%s", help); return -1; } jitter=atoi(argv[i]); } } ortp_init(); ortp_scheduler_init(); ortp_set_log_level_mask(NULL, ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR); session=rtp_session_new(RTP_SESSION_SENDONLY); rtp_session_set_scheduling_mode(session,1); rtp_session_set_blocking_mode(session,1); rtp_session_set_connected_mode(session,TRUE); rtp_session_set_remote_addr(session,argv[2],atoi(argv[3])); rtp_session_set_payload_type(session,0); ssrc=getenv("SSRC"); if (ssrc!=NULL) { printf("using SSRC=%i.\n",atoi(ssrc)); rtp_session_set_ssrc(session,atoi(ssrc)); } #ifndef _WIN32 infile=fopen(argv[1],"r"); #else infile=fopen(argv[1],"rb"); #endif if (infile==NULL) { perror("Cannot open file"); return -1; } signal(SIGINT,stophandler); while( ((i=fread(buffer,1,160,infile))>0) && (runcond) ) { rtp_session_send_with_ts(session,buffer,i,user_ts); user_ts+=160; if (clockslide!=0 && user_ts%(160*50)==0){ ortp_message("Clock sliding of %i miliseconds now",clockslide); rtp_session_make_time_distorsion(session,clockslide); } /*this will simulate a burst of late packets */ if (jitter && (user_ts%(8000)==0)) { ortp_message("Simulating late packets now (%i milliseconds)",jitter); ortp_sleep_ms(jitter); } } fclose(infile); rtp_session_destroy(session); ortp_exit(); ortp_global_stats_display(); return 0; }