static int srtp_recvfrom(RtpTransport *t, mblk_t *m, int flags, struct sockaddr *from, socklen_t *fromlen){ srtp_t srtp=(srtp_t)t->data; int err; int slen; err=rtp_session_rtp_recv_abstract(t->session->rtp.socket,m,flags,from,fromlen); if (err>0){ err_status_t srtp_err; /* keep NON-RTP data unencrypted */ rtp_header_t *rtp; if (err>=RTP_FIXED_HEADER_SIZE) { rtp = (rtp_header_t*)m->b_wptr; if (rtp->version!=2) { return err; } } slen=err; srtp_err = srtp_unprotect(srtp,m->b_wptr,&slen); if (srtp_err==err_status_ok) return slen; else { ortp_error("srtp_unprotect() failed (%d)", srtp_err); return -1; } } return err; }
static int srtcp_recvfrom(RtpTransport *t, mblk_t *m, int flags, struct sockaddr *from, socklen_t *fromlen){ srtp_t srtp=(srtp_t)t->data; int err; int slen; err=rtp_session_rtp_recv_abstract(t->session->rtcp.socket,m,flags,from,fromlen); if (err>0){ err_status_t srtp_err; slen=err; srtp_err=srtp_unprotect_rtcp(srtp,m->b_wptr,&slen); if (srtp_err==err_status_ok) return slen; else { ortp_error("srtp_unprotect_rtcp() failed (%d)", srtp_err); return -1; } } return err; }
static int ozrtp_rtcp_recvfrom(RtpTransport *t, mblk_t *m, int flags, struct sockaddr *from, socklen_t *fromlen){ ZrtpContext *zrtpContext = (ZrtpContext*) t->data; OrtpZrtpContext *userData = (OrtpZrtpContext*) zrtpContext->userData; int rlen = rtp_session_rtp_recv_abstract(t->session->rtcp.socket,m,flags,from,fromlen); if (rlen<=0) { // nothing was received or error: pass the information to caller return rlen; } if (userData->srtpRecv != NULL && zrtp_inState(zrtpContext, SecureState)) { err_status_t err = srtp_unprotect_rtcp(userData->srtpRecv,m->b_wptr,&rlen); if (err != err_status_ok) { ortp_error("srtp_unprotect failed %d ; packet discarded (may be plain RTCP)", err); return 0; } } return rlen; }
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; } }