diff --git a/.gitignore b/.gitignore index d98b38f..6a04dfc 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,5 @@ build.mak build/zsrtp/docs/html zrtp/ - +.DS_Store +ZRTP4J.xcodeproj/ diff --git a/build/zsrtp/Makefile b/build/zsrtp/Makefile index 866f93e..88dfa46 100644 --- a/build/zsrtp/Makefile +++ b/build/zsrtp/Makefile @@ -1,6 +1,6 @@ # Adapt this path to your pjproject path -export PJDIR := ~/devhome/pjproject.git +# export PJDIR := ~/devhome/pjproject.git include $(PJDIR)/build.mak include $(PJDIR)/build/common.mak @@ -126,7 +126,7 @@ $(ZSRTP_LIB): clean: $(MAKE) -f $(RULES_MAK) APP=ZSRTP app=libzsrtp $@ - rm -f $(ZSRTP_LIB) + rm -f $(LIBDIR)/$(ZSRTP_LIB) print_lib: $(MAKE) -f $(RULES_MAK) APP=ZSRTP app=libzsrtp $@ diff --git a/example/simple_pjsua.c b/example/simple_pjsua.c index de37cdc..bffbee9 100644 --- a/example/simple_pjsua.c +++ b/example/simple_pjsua.c @@ -209,7 +209,7 @@ pjmedia_transport* on_create_media_transport(pjsua_call_id call_id, * our partners ZID, shared data etc. If the files does not exists it will * be created an initialized. */ - pjmedia_transport_zrtp_initialize(zrtp_tp, "simple.zid", PJ_TRUE); + pjmedia_transport_zrtp_initialize(zrtp_tp, "/tmp/simple.zid", PJ_TRUE); return zrtp_tp; } diff --git a/zrtp_patch_1.10.patch b/zrtp_patch_1.10.patch deleted file mode 100644 index a472ef5..0000000 --- a/zrtp_patch_1.10.patch +++ /dev/null @@ -1,131 +0,0 @@ -diff --git a/pjsip/include/pjsua-lib/pjsua.h b/pjsip/include/pjsua-lib/pjsua.h -index 0a6cbdd..394c893 100644 ---- a/pjsip/include/pjsua-lib/pjsua.h -+++ b/pjsip/include/pjsua-lib/pjsua.h -@@ -420,6 +420,18 @@ typedef struct pjsua_reg_info - } pjsua_reg_info; - - -+typedef enum pjsua_create_media_transport_flag -+{ -+ /** -+ * This flag indicates that the media transport must also close its -+ * "member" or "child" transport when pjmedia_transport_close() is -+ * called. If this flag is not specified, then the media transport -+ * must not call pjmedia_transport_close() of its member transport. -+ */ -+ PJSUA_MED_TP_CLOSE_MEMBER = 1 -+ -+} pjsua_create_media_transport_flag; -+ - /** - * This structure describes application callback to receive various event - * notification from PJSUA-API. All of these callbacks are OPTIONAL, -@@ -918,6 +930,31 @@ typedef struct pjsua_callback - void (*on_ice_transport_error)(int index, pj_ice_strans_op op, - pj_status_t status, void *param); - -+ /** -+ * This callback can be used by application to implement custom media -+ * transport adapter for the call, or to replace the media transport -+ * with something completely new altogether. -+ * -+ * This callback is called when a new call is created. The library has -+ * created a media transport for the call, and it is provided as the -+ * \a base_tp argument of this callback. Upon returning, the callback -+ * must return an instance of media transport to be used by the call. -+ * -+ * @param call_id Call ID -+ * @param media_idx The media index in the SDP for which this media -+ * transport will be used. -+ * @param base_tp The media transport which otherwise will be -+ * used by the call has this callback not been -+ * implemented. -+ * @param flags Bitmask from pjsua_create_media_transport_flag. -+ * -+ * @return The callback must return an instance of media -+ * transport to be used by the call. -+ */ -+ pjmedia_transport* (*on_create_media_transport)(pjsua_call_id call_id, -+ unsigned media_idx, -+ pjmedia_transport *base_tp, -+ unsigned flags); - } pjsua_callback; - - -diff --git a/pjsip/src/pjsua-lib/pjsua_media.c b/pjsip/src/pjsua-lib/pjsua_media.c -index 47cf1e7..57f9f27 100644 ---- a/pjsip/src/pjsua-lib/pjsua_media.c -+++ b/pjsip/src/pjsua-lib/pjsua_media.c -@@ -1174,7 +1174,8 @@ pj_status_t pjsua_media_channel_init(pjsua_call_id call_id, - { - pjsua_call *call = &pjsua_var.calls[call_id]; - pj_status_t status; -- -+ pjmedia_transport *app_tp = NULL; -+ - #if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0) - pjsua_acc *acc = &pjsua_var.acc[call->acc_id]; - pjmedia_srtp_setting srtp_opt; -@@ -1232,7 +1233,8 @@ pj_status_t pjsua_media_channel_init(pjsua_call_id call_id, - call->med_tp = srtp; - } - #else -- call->med_orig = call->med_tp; -+ if (!call->media_orig) -+ call->med_orig = call->med_tp; - PJ_UNUSED_ARG(security_level); - #endif - -@@ -1258,6 +1260,48 @@ pj_status_t pjsua_media_channel_init(pjsua_call_id call_id, - call->audio_idx = find_audio_index(rem_sdp, srtp_active); - } - -+ /* -+ * Check if applicaton wnats a callback on media transport creation. -+ * -+ * Similar to check to create SRTP above: -+ * Call the application's callback only on first channel_init, not on -+ * a re-invite that does not change the channel setup. -+ * -+ * If SRTP was compiled pjsua always creates the SRTP transport. In this -+ * case check if the current transport is SRTP transport. If yes then -+ * call the callback. -+ * -+ * If SRTP was not compiled then check if med_orig and med_tp are the same. -+ * If yes call the callback. -+ */ -+ if (pjsua_var.ua_cfg.cb.on_create_media_transport) -+ { -+ pjsua_create_media_transport_flag flag = 0; -+ -+#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0) -+ if (call->med_tp == srtp) -+ { -+ -+ /* If the current transport is SRTP then the application's -+ * transport shall close SRTP (SRTP itself will not close -+ * it's slave transport, see above). -+ */ -+ flag = PJSUA_MED_TP_CLOSE_MEMBER; -+#else -+ if (call->med_tp == call->med_orig) -+ { -+#endif -+ app_tp = pjsua_var.ua_cfg.cb.on_create_media_transport(call_id, -+ call->audio_idx, -+ call->med_tp, -+ flag); -+ if (app_tp != NULL && app_tp != call->med_tp) -+ { -+ call->med_tp = app_tp; -+ } -+ } -+ } -+ - /* Reject offer if we couldn't find a good m=audio line in offer */ - if (call->audio_idx < 0) { - if (sip_err_code) *sip_err_code = PJSIP_SC_NOT_ACCEPTABLE_HERE; --- -1.7.3.4 - diff --git a/zsrtp/getzrtp.sh b/zsrtp/getzrtp.sh old mode 100644 new mode 100755 diff --git a/zsrtp/transport_zrtp.c b/zsrtp/transport_zrtp.c index c7557c7..eda02e1 100644 --- a/zsrtp/transport_zrtp.c +++ b/zsrtp/transport_zrtp.c @@ -108,6 +108,11 @@ struct tp_zrtp void (*stream_rtp_cb)(void *user_data, void *pkt, pj_ssize_t); +#if defined(PJ_VERSION_NUM_MAJOR) && defined(PJ_VERSION_NUM_MINOR) + #if (PJ_VERSION_NUM_MAJOR >= 2) && (PJ_VERSION_NUM_MINOR >= 8) + void (*stream_rtp_cb2)(pjmedia_tp_cb_param *param); + #endif +#endif void (*stream_rtcp_cb)(void *user_data, void *pkt, pj_ssize_t); @@ -1021,7 +1026,107 @@ static void transport_rtp_cb(void *user_data, void *pkt, pj_ssize_t size) } if (!zrtp->started && zrtp->enableZrtp) pjmedia_transport_zrtp_startZrtp((pjmedia_transport *)zrtp); + return; + } + + // We assume all other packets are ZRTP packets here. Process + // if ZRTP processing is enabled. Because valid RTP packets are + // already handled we delete any packets here after processing. + if (zrtp->enableZrtp && zrtp->zrtpCtx != NULL) + { + unsigned char* zrtpMsg = NULL; + pj_uint32_t magic = *(pj_uint32_t*)(buffer + 4); + + // Get CRC value into crc (see above how to compute the offset) + pj_uint16_t temp = (pj_uint16_t)(size - CRC_SIZE); + pj_uint32_t crc = *(uint32_t*)(buffer + temp); + crc = pj_ntohl(crc); + + if (!zrtp_CheckCksum(buffer, temp, crc)) + { + if (zrtp->userCallback.zrtp_showMessage != NULL) + zrtp->userCallback.zrtp_showMessage(zrtp->userCallback.userData, zrtp_Warning, zrtp_WarningCRCmismatch); + return; + } + magic = pj_ntohl(magic); + + // Check if it is really a ZRTP packet, return, no further processing + if (magic != ZRTP_MAGIC || zrtp->zrtpCtx == NULL) + { + return; + } + // cover the case if the other party sends _only_ ZRTP packets at the + // beginning of a session. Start ZRTP in this case as well. + if (!zrtp->started) + { + pjmedia_transport_zrtp_startZrtp((pjmedia_transport *)zrtp); + } + // this now points beyond the undefined and length field. + // We need them, thus adjust + zrtpMsg = (buffer + 12); + + // store peer's SSRC in host order, used when creating the CryptoContext + zrtp->peerSSRC = *(pj_uint32_t*)(buffer + 8); + zrtp->peerSSRC = pj_ntohl(zrtp->peerSSRC); + zrtp_processZrtpMessage(zrtp->zrtpCtx, zrtpMsg, zrtp->peerSSRC, size); + } +} + +#if defined(PJ_VERSION_NUM_MAJOR) && defined(PJ_VERSION_NUM_MINOR) + #if (PJ_VERSION_NUM_MAJOR >= 2) && (PJ_VERSION_NUM_MINOR >= 8) +static void transport_rtp_cb2(pjmedia_tp_cb_param *param) +{ + struct tp_zrtp *zrtp = (struct tp_zrtp*)param->user_data; + void *pkt = param->pkt; + pj_uint8_t* buffer = (pj_uint8_t*)pkt; + int32_t newLen = 0; + pj_ssize_t size = param->size; + pj_status_t rc = PJ_SUCCESS; + + pj_assert(zrtp && zrtp->stream_rtcp_cb && pkt); + + // check if this could be a real RTP/SRTP packet. + if ((*buffer & 0xf0) != 0x10) + { + // Could be real RTP, check if we are in secure mode + if (zrtp->srtpReceive == NULL || size < 0) + { + struct pjmedia_tp_cb_param tp = { zrtp->stream_user_data, pkt, size, NULL, PJ_FALSE }; + zrtp->stream_rtp_cb2(&tp); + } + else + { + rc = zsrtp_unprotect(zrtp->srtpReceive, (pj_uint8_t*)pkt, size, &newLen); + if (rc == 1) + { + zrtp->unprotect++; + struct pjmedia_tp_cb_param tp = { zrtp->stream_user_data, pkt, newLen, NULL, PJ_FALSE }; + zrtp->stream_rtp_cb2(&tp); + // zrtp->stream_rtp_cb2(zrtp->stream_user_data, pkt, + // newLen); + zrtp->unprotect_err = 0; + } + else + { + if (zrtp->userCallback.zrtp_showMessage != NULL) + { + if (rc == -1) { + zrtp->userCallback.zrtp_showMessage(zrtp->userCallback.userData, + zrtp_Warning, + zrtp_WarningSRTPauthError); + } + else { + zrtp->userCallback.zrtp_showMessage(zrtp->userCallback.userData, + zrtp_Warning, + zrtp_WarningSRTPreplayError); + } + } + zrtp->unprotect_err = rc; + } + } + if (!zrtp->started && zrtp->enableZrtp) + pjmedia_transport_zrtp_startZrtp((pjmedia_transport *)zrtp); return; } @@ -1067,6 +1172,8 @@ static void transport_rtp_cb(void *user_data, void *pkt, pj_ssize_t size) zrtp_processZrtpMessage(zrtp->zrtpCtx, zrtpMsg, zrtp->peerSSRC, size); } } + #endif +#endif /* This is our RTCP callback, that is called by the slave transport when it @@ -1161,6 +1268,11 @@ static void transport_detach(pjmedia_transport *tp, void *strm) pjmedia_transport_detach(zrtp->slave_tp, zrtp); zrtp->stream_user_data = NULL; zrtp->stream_rtp_cb = NULL; +#if defined(PJ_VERSION_NUM_MAJOR) && defined(PJ_VERSION_NUM_MINOR) + #if (PJ_VERSION_NUM_MAJOR >= 2) && (PJ_VERSION_NUM_MINOR >= 8) + zrtp->stream_rtp_cb2 = NULL; + #endif +#endif zrtp->stream_rtcp_cb = NULL; } } @@ -1488,8 +1600,17 @@ static pj_status_t transport_attach2(pjmedia_transport *tp, pjmedia_transport_at pj_assert(zrtp->stream_user_data == NULL); zrtp->stream_user_data = att_param->user_data; zrtp->stream_rtp_cb = att_param->rtp_cb; +#if defined(PJ_VERSION_NUM_MAJOR) && defined(PJ_VERSION_NUM_MINOR) + #if (PJ_VERSION_NUM_MAJOR >= 2) && (PJ_VERSION_NUM_MINOR >= 8) + zrtp->stream_rtp_cb2 = att_param->rtp_cb2; + #endif +#endif + // zrtp->stream_rtp_cb = att_param->rtp_cb; //! att_param->rtp_cb is NULL zrtp->stream_rtcp_cb = att_param->rtcp_cb; + //! zrtp->stream_rtp_cb is NULL here + PJ_LOG(4, (THIS_FILE, "Assigned within transport_attach2 to zrtp->stream_rtp_cb2: %p", zrtp->stream_rtp_cb2)); + pjmedia_transport_attach_param param = {NULL, PJMEDIA_TYPE_AUDIO, //Video calls later? att_param->rem_addr, @@ -1497,7 +1618,13 @@ static pj_status_t transport_attach2(pjmedia_transport *tp, pjmedia_transport_at att_param->addr_len, zrtp, &transport_rtp_cb, - &transport_rtcp_cb}; + &transport_rtcp_cb +#if defined(PJ_VERSION_NUM_MAJOR) && defined(PJ_VERSION_NUM_MINOR) + #if (PJ_VERSION_NUM_MAJOR >= 2) && (PJ_VERSION_NUM_MINOR >= 8) + , &transport_rtp_cb2 + #endif +#endif + }; @@ -1506,6 +1633,11 @@ static pj_status_t transport_attach2(pjmedia_transport *tp, pjmedia_transport_at { zrtp->stream_user_data = NULL; zrtp->stream_rtp_cb = NULL; +#if defined(PJ_VERSION_NUM_MAJOR) && defined(PJ_VERSION_NUM_MINOR) + #if (PJ_VERSION_NUM_MAJOR >= 2) && (PJ_VERSION_NUM_MINOR >= 8) + zrtp->stream_rtp_cb2 = NULL; + #endif +#endif zrtp->stream_rtcp_cb = NULL; return status; }