static int ms_zrtp_rtp_process_on_receive(struct _RtpTransportModifier *t, mblk_t *msg){ uint32_t *magicField; MSZrtpContext *userData = (MSZrtpContext*) t->data; bzrtpContext_t *zrtpContext = userData->zrtpContext; uint8_t* rtp; int rtpVersion; int msgLength = msgdsize(msg); // send a timer tick to the zrtp engine bzrtp_iterate(zrtpContext, userData->self_ssrc, get_timeval_in_millis()); // check incoming message length if (msgLength<RTP_FIXED_HEADER_SIZE) { return msgLength; } rtp=msg->b_rptr; rtpVersion = ((rtp_header_t*)rtp)->version; magicField=(uint32_t *)(rtp + 4); // Check if there is a ZRTP packet to receive if (rtpVersion!=0 || ntohl(*magicField) != ZRTP_MAGIC_COOKIE) { return msgLength; } // display received message ms_message("ZRTP Receive packet type %.8s", rtp+16); // send ZRTP packet to engine bzrtp_processMessage(zrtpContext, userData->self_ssrc, rtp, msgLength); return 0; }
static void schedule_rtcp(struct _RtpTransportModifier *t) { MSDtlsSrtpContext *ctx = (MSDtlsSrtpContext *)t->data; if (ctx->role == MSDtlsSrtpRoleIsClient) { /* only if we are client */ uint64_t current_time = get_timeval_in_millis(); if (ctx->rtcp_time_reference>0) { /* only when retransmission timer is armed */ if (current_time - ctx->rtcp_time_reference > READ_TIMEOUT_MS) { ms_message("DTLS repeating rtcp ssl_handshake for context [%p]",ctx); ms_mutex_lock(&ctx->rtcp_dtls_context->ssl_context_mutex); ssl_handshake(&(ctx->rtcp_dtls_context->ssl)); ms_mutex_unlock(&ctx->rtcp_dtls_context->ssl_context_mutex); ctx->rtcp_time_reference = get_timeval_in_millis(); } } } }
void ms_dtls_srtp_start(MSDtlsSrtpContext* context) { if (context == NULL ) { ms_warning("DTLS start but no context\n"); return; } ms_message("DTLS start stream on stream sessions [%p]", context->stream_sessions); /* if we are client, start the handshake(send a clientHello) */ if (context->role == MSDtlsSrtpRoleIsClient) { ms_mutex_lock(&context->rtp_dtls_context->ssl_context_mutex); ms_mutex_lock(&context->rtcp_dtls_context->ssl_context_mutex); ssl_set_endpoint(&(context->rtp_dtls_context->ssl), SSL_IS_CLIENT); ssl_handshake(&(context->rtp_dtls_context->ssl)); context->rtp_time_reference = get_timeval_in_millis(); /* arm the timer for retransmission */ ssl_set_endpoint(&(context->rtcp_dtls_context->ssl), SSL_IS_CLIENT); ssl_handshake(&(context->rtcp_dtls_context->ssl)); context->rtcp_time_reference = get_timeval_in_millis(); /* arm the timer for retransmission */ ms_mutex_unlock(&context->rtp_dtls_context->ssl_context_mutex); ms_mutex_unlock(&context->rtcp_dtls_context->ssl_context_mutex); } }
/** * Check if the incoming message is a DTLS packet. * If it is, store it in the context incoming buffer and call the polarssl function wich will process it. * This function also manages the client retransmission timer * * @param[in] msg the incoming message * @param[in/out] ctx the context containing the incoming buffer to store the DTLS packet * @param[out] ret the value returned by the polarssl function processing the packet(ssl_handshake) * @param[in] is_rtp TRUE if we are dealing with a RTP channel packet, FALSE for RTCP channel * @return TRUE if packet is a DTLS one, false otherwise */ static bool_t ms_dtls_srtp_process_dtls_packet(mblk_t *msg, MSDtlsSrtpContext *ctx, int *ret, bool_t is_rtp) { size_t msgLength = msgdsize(msg); uint64_t *time_reference = (is_rtp == TRUE)?&(ctx->rtp_time_reference):&(ctx->rtcp_time_reference); ssl_context *ssl = (is_rtp == TRUE)?&(ctx->rtp_dtls_context->ssl):&(ctx->rtcp_dtls_context->ssl); ms_mutex_t *mutex = (is_rtp == TRUE)?&ctx->rtp_dtls_context->ssl_context_mutex:&ctx->rtcp_dtls_context->ssl_context_mutex; // check if incoming message length is compatible with potential DTLS message if (msgLength<RTP_FIXED_HEADER_SIZE) { return FALSE; } /* check if it is a DTLS packet (first byte B as 19 < B < 64) rfc5764 section 5.1.2 */ if ((*(msg->b_rptr)>19) && (*(msg->b_rptr)<64)) { DtlsRawPacket *incoming_dtls_packet; RtpSession *rtp_session = ctx->stream_sessions->rtp_session; OrtpStream *ortp_stream = is_rtp?&rtp_session->rtp.gs:&rtp_session->rtcp.gs; incoming_dtls_packet = (DtlsRawPacket *)ms_malloc0(sizeof(DtlsRawPacket)); //DtlsRawPacket *incoming_dtls_packet = (DtlsRawPacket *)ms_malloc0(sizeof(DtlsRawPacket)); incoming_dtls_packet->next=NULL; incoming_dtls_packet->data=(unsigned char *)ms_malloc(msgLength); incoming_dtls_packet->length=msgLength; memcpy(incoming_dtls_packet->data, msg->b_rptr, msgLength); /*required by webrtc in server case when ice is not completed yet*/ if (!rtp_session->use_connect){ struct sockaddr *addr = NULL; socklen_t addrlen; addr = (struct sockaddr *)&msg->net_addr; addrlen = msg->net_addrlen; if (ortp_stream->socket>0 && rtp_session->symmetric_rtp){ /* store the sender rtp address to do symmetric DTLS */ memcpy(&ortp_stream->rem_addr,addr,addrlen); ortp_stream->rem_addrlen=addrlen; } } /* store the packet in the incoming buffer */ if (is_rtp == TRUE) { if (ctx->rtp_incoming_buffer==NULL) { /* buffer is empty */ ctx->rtp_incoming_buffer = incoming_dtls_packet; } else { /* queue it at the end of current buffer */ DtlsRawPacket *last_packet = ctx->rtp_incoming_buffer; while (last_packet->next != NULL) last_packet = last_packet->next; last_packet->next = incoming_dtls_packet; } } else { if (ctx->rtcp_incoming_buffer==NULL) { /* buffer is empty */ ctx->rtcp_incoming_buffer = incoming_dtls_packet; } else { /* queue it at the end of current buffer */ DtlsRawPacket *last_packet = ctx->rtcp_incoming_buffer; while (last_packet->next != NULL) last_packet = last_packet->next; last_packet->next = incoming_dtls_packet; } } /* role is unset but we receive a packet: we are caller and shall initialise as server and then process the incoming packet */ if (ctx->role == MSDtlsSrtpRoleUnset) { ms_dtls_srtp_set_role(ctx, MSDtlsSrtpRoleIsServer); /* this call will update role and complete server setup */ } ms_mutex_lock(mutex); /* process the packet and store result */ *ret = ssl_handshake(ssl); /* when we are server, we may issue a hello verify, so reset session, keep cookies(transport id) and expect an other Hello from client */ if (*ret==POLARSSL_ERR_SSL_HELLO_VERIFY_REQUIRED) { ssl_session_reset(ssl); ssl_set_client_transport_id(ssl, (const unsigned char *)(&(ctx->stream_sessions->rtp_session->snd.ssrc)), 4); } /* if we are client, manage the retransmission timer */ if (ctx->role == MSDtlsSrtpRoleIsClient) { *time_reference = get_timeval_in_millis(); } ms_mutex_unlock(mutex); return TRUE; } return FALSE; }