コード例 #1
0
PJ_DEF(pj_status_t) pjmedia_srtp_init_lib(pjmedia_endpt *endpt)
{
#if PJMEDIA_LIBSRTP_AUTO_INIT_DEINIT
    if (libsrtp_initialized == PJ_FALSE) {
	err_status_t err;

	err = srtp_init();
	if (err != err_status_ok) {
	    PJ_LOG(4, (THIS_FILE, "Failed to initialize libsrtp: %s",
		       get_libsrtp_errstr(err)));
	    return PJMEDIA_ERRNO_FROM_LIBSRTP(err);
	}

	if (pjmedia_endpt_atexit(endpt, pjmedia_srtp_deinit_lib) != PJ_SUCCESS)
	{
	    /* There will be memory leak when it fails to schedule libsrtp
	     * deinitialization, however the memory leak could be harmless,
	     * since in modern OS's memory used by an application is released
	     * when the application terminates.
	     */
	    PJ_LOG(4, (THIS_FILE, "Failed to register libsrtp deinit."));
	}

	libsrtp_initialized = PJ_TRUE;
    }
#else
    PJ_UNUSED_ARG(endpt);
#endif

    return PJ_SUCCESS;
}
コード例 #2
0
ファイル: transport_srtp.c プロジェクト: max3903/SFLphone
static void pjmedia_srtp_deinit_lib(void)
{
    err_status_t err;

    err = srtp_deinit();
    if (err != err_status_ok) {
	PJ_LOG(4, (THIS_FILE, "Failed to deinitialize libsrtp: %s", 
		   get_libsrtp_errstr(err)));
    }

    libsrtp_initialized = PJ_FALSE;
}
コード例 #3
0
ファイル: transport_srtp.c プロジェクト: deveck/Deveck.TAM
static pj_status_t pjmedia_srtp_init_lib(void)
{
    static pj_bool_t initialized = PJ_FALSE;

    if (initialized == PJ_FALSE) {
	err_status_t err;
	err = srtp_init();
	if (err != err_status_ok) { 
	    PJ_LOG(4, (THIS_FILE, "Failed to initialize libsrtp: %s", 
		       get_libsrtp_errstr(err)));
	    return PJMEDIA_ERRNO_FROM_LIBSRTP(err);
	}

	initialized = PJ_TRUE;
    }
    
    return PJ_SUCCESS;
}
コード例 #4
0
/*
 * This callback is called by transport when incoming rtcp is received
 */
static void srtp_rtcp_cb( void *user_data, void *pkt, pj_ssize_t size)
{
    transport_srtp *srtp = (transport_srtp *) user_data;
    int len = size;
    err_status_t err;
    void (*cb)(void*, void*, pj_ssize_t) = NULL;
    void *cb_data = NULL;

    if (srtp->bypass_srtp) {
	srtp->rtcp_cb(srtp->user_data, pkt, size);
	return;
    }

    if (size < 0) {
	return;
    }

    /* Make sure buffer is 32bit aligned */
    PJ_ASSERT_ON_FAIL( (((pj_ssize_t)pkt) & 0x03)==0, return );

    pj_lock_acquire(srtp->mutex);

    if (!srtp->session_inited) {
	pj_lock_release(srtp->mutex);
	return;
    }
    err = srtp_unprotect_rtcp(srtp->srtp_rx_ctx, (pj_uint8_t*)pkt, &len);
    if (err != err_status_ok) {
	PJ_LOG(5,(srtp->pool->obj_name,
		  "Failed to unprotect SRTCP, pkt size=%d, err=%s",
		  size, get_libsrtp_errstr(err)));
    } else {
	cb = srtp->rtcp_cb;
	cb_data = srtp->user_data;
    }

    pj_lock_release(srtp->mutex);

    if (cb) {
	(*cb)(cb_data, pkt, len);
    }
}
コード例 #5
0
ファイル: transport_srtp.c プロジェクト: krisk84/PJSIP
static void pjmedia_srtp_deinit_lib(pjmedia_endpt *endpt)
{
    err_status_t err;

    /* Note that currently this SRTP init/deinit is not equipped with
     * reference counter, it should be safe as normally there is only
     * one single instance of media endpoint and even if it isn't, the
     * pjmedia_transport_srtp_create() will invoke SRTP init (the only
     * drawback should be the delay described by #788).
     */

    PJ_UNUSED_ARG(endpt);

    err = srtp_shutdown();
    if (err != err_status_ok) {
	PJ_LOG(4, (THIS_FILE, "Failed to deinitialize libsrtp: %s", 
		   get_libsrtp_errstr(err)));
    }

    libsrtp_initialized = PJ_FALSE;
}
コード例 #6
0
ファイル: transport_srtp.c プロジェクト: batk0/pjsip
/* Utility */
PJ_DEF(pj_status_t) pjmedia_transport_srtp_decrypt_pkt(pjmedia_transport *tp,
						       pj_bool_t is_rtp,
						       void *pkt,
						       int *pkt_len)
{
    transport_srtp *srtp = (transport_srtp *)tp;
    srtp_err_status_t err;

    if (srtp->bypass_srtp)
	return PJ_SUCCESS;

    PJ_ASSERT_RETURN(tp && pkt && (*pkt_len>0), PJ_EINVAL);
    PJ_ASSERT_RETURN(srtp->session_inited, PJ_EINVALIDOP);

    /* Make sure buffer is 32bit aligned */
    PJ_ASSERT_ON_FAIL( (((pj_ssize_t)pkt) & 0x03)==0, return PJ_EINVAL);

    pj_lock_acquire(srtp->mutex);

    if (!srtp->session_inited) {
	pj_lock_release(srtp->mutex);
	return PJ_EINVALIDOP;
    }

    if (is_rtp)
	err = srtp_unprotect(srtp->srtp_rx_ctx, pkt, pkt_len);
    else
	err = srtp_unprotect_rtcp(srtp->srtp_rx_ctx, pkt, pkt_len);

    if (err != srtp_err_status_ok) {
	PJ_LOG(5,(srtp->pool->obj_name,
		  "Failed to unprotect SRTP, pkt size=%d, err=%s",
		  *pkt_len, get_libsrtp_errstr(err)));
    }

    pj_lock_release(srtp->mutex);

    return (err==srtp_err_status_ok) ? PJ_SUCCESS :
				       PJMEDIA_ERRNO_FROM_LIBSRTP(err);
}
コード例 #7
0
ファイル: transport_srtp.c プロジェクト: batk0/pjsip
PJ_DEF(pj_status_t) pjmedia_srtp_init_lib(pjmedia_endpt *endpt)
{
    pj_status_t status = PJ_SUCCESS;

    if (libsrtp_initialized)
	return PJ_SUCCESS;

#if PJMEDIA_LIBSRTP_AUTO_INIT_DEINIT
    /* Init libsrtp */
    {
	srtp_err_status_t err;

	err = srtp_init();
	if (err != srtp_err_status_ok) {
	    PJ_LOG(4, (THIS_FILE, "Failed to initialize libsrtp: %s",
		       get_libsrtp_errstr(err)));
	    return PJMEDIA_ERRNO_FROM_LIBSRTP(err);
	}
    }
#endif

#if defined(PJMEDIA_SRTP_HAS_DTLS) && (PJMEDIA_SRTP_HAS_DTLS != 0)
    dtls_init();
#endif

    if (pjmedia_endpt_atexit(endpt, pjmedia_srtp_deinit_lib) != PJ_SUCCESS)
    {
	/* There will be memory leak when it fails to schedule libsrtp
	 * deinitialization, however the memory leak could be harmless,
	 * since in modern OS's memory used by an application is released
	 * when the application terminates.
	 */
	PJ_LOG(4, (THIS_FILE, "Failed to register libsrtp deinit."));
    }

    libsrtp_initialized = PJ_TRUE;

    return status;
}
コード例 #8
0
ファイル: transport_srtp.c プロジェクト: batk0/pjsip
static void pjmedia_srtp_deinit_lib(pjmedia_endpt *endpt)
{
    srtp_err_status_t err;

    /* Note that currently this SRTP init/deinit is not equipped with
     * reference counter, it should be safe as normally there is only
     * one single instance of media endpoint and even if it isn't, the
     * pjmedia_transport_srtp_create() will invoke SRTP init (the only
     * drawback should be the delay described by #788).
     */

    PJ_UNUSED_ARG(endpt);

#if !defined(PJMEDIA_SRTP_HAS_DEINIT) && !defined(PJMEDIA_SRTP_HAS_SHUTDOWN)
# define PJMEDIA_SRTP_HAS_SHUTDOWN 1
#endif

#if PJMEDIA_LIBSRTP_AUTO_INIT_DEINIT

# if defined(PJMEDIA_SRTP_HAS_DEINIT) && PJMEDIA_SRTP_HAS_DEINIT!=0
    err = srtp_deinit();
# elif defined(PJMEDIA_SRTP_HAS_SHUTDOWN) && PJMEDIA_SRTP_HAS_SHUTDOWN!=0
    err = srtp_shutdown();
# else
    err = srtp_err_status_ok;
# endif
    if (err != srtp_err_status_ok) {
	PJ_LOG(4, (THIS_FILE, "Failed to deinitialize libsrtp: %s",
		   get_libsrtp_errstr(err)));
    }
#endif // PJMEDIA_LIBSRTP_AUTO_INIT_DEINIT

#if defined(PJMEDIA_SRTP_HAS_DTLS) && (PJMEDIA_SRTP_HAS_DTLS != 0)
    dtls_deinit();
#endif

    libsrtp_initialized = PJ_FALSE;
}
コード例 #9
0
ファイル: errno.c プロジェクト: RyanLee27/pjproject
/*
 * pjmedia_strerror()
 */
PJ_DEF(pj_str_t) pjmedia_strerror( pj_status_t statcode, 
				   char *buf, pj_size_t bufsize )
{
    pj_str_t errstr;

#if defined(PJ_HAS_ERROR_STRING) && (PJ_HAS_ERROR_STRING != 0)

    /* See if the error comes from PortAudio. */
#if defined(PJMEDIA_SOUND_IMPLEMENTATION) && \
    PJMEDIA_SOUND_IMPLEMENTATION == PJMEDIA_SOUND_PORTAUDIO_SOUND
    if (statcode >= PJMEDIA_PORTAUDIO_ERRNO_START &&
	statcode <= PJMEDIA_PORTAUDIO_ERRNO_END)
    {

	//int pa_err = statcode - PJMEDIA_ERRNO_FROM_PORTAUDIO(0);
	int pa_err = PJMEDIA_PORTAUDIO_ERRNO_START - statcode;
	pj_str_t msg;
	
	msg.ptr = (char*)Pa_GetErrorText(pa_err);
	msg.slen = pj_ansi_strlen(msg.ptr);

	errstr.ptr = buf;
	pj_strncpy_with_null(&errstr, &msg, bufsize);
	return errstr;

    } else 
#endif	/* PJMEDIA_SOUND_IMPLEMENTATION */

#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
    /* LIBSRTP error */
    if (statcode >= PJMEDIA_LIBSRTP_ERRNO_START &&
	statcode <  PJMEDIA_LIBSRTP_ERRNO_END)
    {
	int err = statcode - PJMEDIA_LIBSRTP_ERRNO_START;
	pj_str_t msg;
	
	msg = pj_str((char*)get_libsrtp_errstr(err));

	errstr.ptr = buf;
	pj_strncpy_with_null(&errstr, &msg, bufsize);
	return errstr;
    
    } else
#endif
    
    /* PJMEDIA error */
    if (statcode >= PJMEDIA_ERRNO_START && 
	       statcode < PJMEDIA_ERRNO_END)
    {
	/* Find the error in the table.
	 * Use binary search!
	 */
	int first = 0;
	int n = PJ_ARRAY_SIZE(err_str);

	while (n > 0) {
	    int half = n/2;
	    int mid = first + half;

	    if (err_str[mid].code < statcode) {
		first = mid+1;
		n -= (half+1);
	    } else if (err_str[mid].code > statcode) {
		n = half;
	    } else {
		first = mid;
		break;
	    }
	}


	if (PJ_ARRAY_SIZE(err_str) && err_str[first].code == statcode) {
	    pj_str_t msg;
	    
	    msg.ptr = (char*)err_str[first].msg;
	    msg.slen = pj_ansi_strlen(err_str[first].msg);

	    errstr.ptr = buf;
	    pj_strncpy_with_null(&errstr, &msg, bufsize);
	    return errstr;

	} 
    } 
#endif	/* PJ_HAS_ERROR_STRING */

    /* Error not found. */
    errstr.ptr = buf;
    errstr.slen = pj_ansi_snprintf(buf, bufsize, 
				   "Unknown pjmedia error %d",
				   statcode);
    if (errstr.slen < 1 || errstr.slen >= (pj_ssize_t)bufsize)
	errstr.slen = bufsize - 1;
    return errstr;
}
コード例 #10
0
ファイル: transport_srtp.c プロジェクト: max3903/SFLphone
/* Generate crypto attribute, including crypto key.
 * If crypto-suite chosen is crypto NULL, just return PJ_SUCCESS,
 * and set buffer_len = 0.
 */
static pj_status_t generate_crypto_attr_value(pj_pool_t *pool,
					      char *buffer, int *buffer_len, 
					      pjmedia_srtp_crypto *crypto,
					      int tag)
{
    pj_status_t status;
    int cs_idx = get_crypto_idx(&crypto->name);
    char b64_key[PJ_BASE256_TO_BASE64_LEN(MAX_KEY_LEN)+1];
    int b64_key_len = sizeof(b64_key);

    if (cs_idx == -1)
	return PJMEDIA_SRTP_ENOTSUPCRYPTO;

    /* Crypto-suite NULL. */
    if (cs_idx == 0) {
	*buffer_len = 0;
	return PJ_SUCCESS;
    }

    /* Generate key if not specified. */
    if (crypto->key.slen == 0) {
	pj_bool_t key_ok;
	char key[MAX_KEY_LEN];
	err_status_t err;
	unsigned i;

	PJ_ASSERT_RETURN(MAX_KEY_LEN >= crypto_suites[cs_idx].cipher_key_len,
			 PJ_ETOOSMALL);

	do {
	    key_ok = PJ_TRUE;

	    err = crypto_get_random((unsigned char*)key, 
				     crypto_suites[cs_idx].cipher_key_len);
	    if (err != err_status_ok) {
		PJ_LOG(5,(THIS_FILE, "Failed generating random key: %s",
			  get_libsrtp_errstr(err)));
		return PJMEDIA_ERRNO_FROM_LIBSRTP(err);
	    }
	    for (i=0; i<crypto_suites[cs_idx].cipher_key_len && key_ok; ++i)
		if (key[i] == 0) key_ok = PJ_FALSE;

	} while (!key_ok);
	crypto->key.ptr = (char*)
			  pj_pool_zalloc(pool, 
					 crypto_suites[cs_idx].cipher_key_len);
	pj_memcpy(crypto->key.ptr, key, crypto_suites[cs_idx].cipher_key_len);
	crypto->key.slen = crypto_suites[cs_idx].cipher_key_len;
    }

    if (crypto->key.slen != (pj_ssize_t)crypto_suites[cs_idx].cipher_key_len)
	return PJMEDIA_SRTP_EINKEYLEN;

    /* Key transmitted via SDP should be base64 encoded. */
    status = pj_base64_encode((pj_uint8_t*)crypto->key.ptr, crypto->key.slen,
			      b64_key, &b64_key_len);
    if (status != PJ_SUCCESS) {
	PJ_LOG(5,(THIS_FILE, "Failed encoding plain key to base64"));
	return status;
    }

    b64_key[b64_key_len] = '\0';
    
    PJ_ASSERT_RETURN(*buffer_len >= (crypto->name.slen + \
		     b64_key_len + 16), PJ_ETOOSMALL);

    /* Print the crypto attribute value. */
    *buffer_len = pj_ansi_snprintf(buffer, *buffer_len, "%d %s inline:%s",
				   tag, 
				   crypto_suites[cs_idx].name,
				   b64_key);

    return PJ_SUCCESS;
}
コード例 #11
0
/*
 * This callback is called by transport when incoming rtp is received
 */
static void srtp_rtp_cb( void *user_data, void *pkt, pj_ssize_t size)
{
    transport_srtp *srtp = (transport_srtp *) user_data;
    int len = size;
    err_status_t err;
    void (*cb)(void*, void*, pj_ssize_t) = NULL;
    void *cb_data = NULL;

    if (srtp->bypass_srtp) {
	srtp->rtp_cb(srtp->user_data, pkt, size);
	return;
    }

    if (size < 0) {
	return;
    }

    /* Make sure buffer is 32bit aligned */
    PJ_ASSERT_ON_FAIL( (((pj_ssize_t)pkt) & 0x03)==0, return );

    if (srtp->probation_cnt > 0)
	--srtp->probation_cnt;

    pj_lock_acquire(srtp->mutex);

    if (!srtp->session_inited) {
	pj_lock_release(srtp->mutex);
	return;
    }
    err = srtp_unprotect(srtp->srtp_rx_ctx, (pj_uint8_t*)pkt, &len);
    if (srtp->probation_cnt > 0 &&
	(err == err_status_replay_old || err == err_status_replay_fail))
    {
	/* Handle such condition that stream is updated (RTP seq is reinited
	 * & SRTP is restarted), but some old packets are still coming
	 * so SRTP is learning wrong RTP seq. While the newly inited RTP seq
	 * comes, SRTP thinks the RTP seq is replayed, so srtp_unprotect()
	 * will return err_status_replay_*. Restarting SRTP can resolve this.
	 */
	pjmedia_srtp_crypto tx, rx;
	pj_status_t status;

	tx = srtp->tx_policy;
	rx = srtp->rx_policy;
	status = pjmedia_transport_srtp_start((pjmedia_transport*)srtp,
					      &tx, &rx);
	if (status != PJ_SUCCESS) {
	    PJ_LOG(5,(srtp->pool->obj_name, "Failed to restart SRTP, err=%s",
		      get_libsrtp_errstr(err)));
	} else if (!srtp->bypass_srtp) {
	    err = srtp_unprotect(srtp->srtp_rx_ctx, (pj_uint8_t*)pkt, &len);
	}
    }

    if (err != err_status_ok) {
	PJ_LOG(5,(srtp->pool->obj_name,
		  "Failed to unprotect SRTP, pkt size=%d, err=%s",
		  size, get_libsrtp_errstr(err)));
    } else {
	cb = srtp->rtp_cb;
	cb_data = srtp->user_data;
    }

    pj_lock_release(srtp->mutex);

    if (cb) {
	(*cb)(cb_data, pkt, len);
    }
}
コード例 #12
0
ファイル: transport_srtp.c プロジェクト: batk0/pjsip
/*
 * This callback is called by transport when incoming rtp is received
 */
static void srtp_rtp_cb( void *user_data, void *pkt, pj_ssize_t size)
{
    transport_srtp *srtp = (transport_srtp *) user_data;
    int len = (int)size;
    srtp_err_status_t err;
    void (*cb)(void*, void*, pj_ssize_t) = NULL;
    void *cb_data = NULL;

    if (srtp->bypass_srtp) {
	srtp->rtp_cb(srtp->user_data, pkt, size);
	return;
    }

    if (size < 0) {
	return;
    }

    /* Give the packet to keying first by invoking its send_rtp() op.
     * Yes, the usage of send_rtp() is rather hacky, but it is convenient
     * as the signature suits the purpose and it is ready to use
     * (no futher registration/setting needed), and it may never be used
     * by any keying method in the future.
     */
    {
	unsigned i;
	pj_status_t status;
	for (i=0; i < srtp->keying_cnt; i++) {
	    if (!srtp->keying[i]->op->send_rtp)
		continue;
	    status = pjmedia_transport_send_rtp(srtp->keying[i], pkt, size);
	    if (status != PJ_EIGNORED) {
		/* Packet is already consumed by the keying method */
		return;
	    }
	}
    }

    /* Make sure buffer is 32bit aligned */
    PJ_ASSERT_ON_FAIL( (((pj_ssize_t)pkt) & 0x03)==0, return );

    if (srtp->probation_cnt > 0)
	--srtp->probation_cnt;

    pj_lock_acquire(srtp->mutex);

    if (!srtp->session_inited) {
	pj_lock_release(srtp->mutex);
	return;
    }
    err = srtp_unprotect(srtp->srtp_rx_ctx, (pj_uint8_t*)pkt, &len);
    if (srtp->probation_cnt > 0 &&
	(err == srtp_err_status_replay_old ||
	 err == srtp_err_status_replay_fail))
    {
	/* Handle such condition that stream is updated (RTP seq is reinited
	 * & SRTP is restarted), but some old packets are still coming
	 * so SRTP is learning wrong RTP seq. While the newly inited RTP seq
	 * comes, SRTP thinks the RTP seq is replayed, so srtp_unprotect()
	 * will return err_status_replay_*. Restarting SRTP can resolve this.
	 */
	pjmedia_srtp_crypto tx, rx;
	pj_status_t status;

	tx = srtp->tx_policy;
	rx = srtp->rx_policy;
	status = pjmedia_transport_srtp_start((pjmedia_transport*)srtp,
					      &tx, &rx);
	if (status != PJ_SUCCESS) {
	    PJ_LOG(5,(srtp->pool->obj_name, "Failed to restart SRTP, err=%s",
		      get_libsrtp_errstr(err)));
	} else if (!srtp->bypass_srtp) {
	    err = srtp_unprotect(srtp->srtp_rx_ctx, (pj_uint8_t*)pkt, &len);
	}
    }

    if (err != srtp_err_status_ok) {
	PJ_LOG(5,(srtp->pool->obj_name,
		  "Failed to unprotect SRTP, pkt size=%d, err=%s",
		  size, get_libsrtp_errstr(err)));
    } else {
	cb = srtp->rtp_cb;
	cb_data = srtp->user_data;
    }

    pj_lock_release(srtp->mutex);

    if (cb) {
	(*cb)(cb_data, pkt, len);
    }
}