예제 #1
0
static pj_status_t transport_send_rtp( pjmedia_transport *tp,
				       const void *pkt,
				       pj_size_t size)
{
    pj_status_t status;
    transport_srtp *srtp = (transport_srtp*) tp;
    int len = size;
    err_status_t err;

    if (srtp->bypass_srtp)
	return pjmedia_transport_send_rtp(srtp->member_tp, pkt, size);

    if (!srtp->session_inited)
	return PJ_SUCCESS;

    if (size > sizeof(srtp->rtp_tx_buffer))
	return PJ_ETOOBIG;

    pj_memcpy(srtp->rtp_tx_buffer, pkt, size);

    pj_lock_acquire(srtp->mutex);
    err = srtp_protect(srtp->srtp_tx_ctx, srtp->rtp_tx_buffer, &len);
    pj_lock_release(srtp->mutex);

    if (err == err_status_ok) {
	status = pjmedia_transport_send_rtp(srtp->member_tp, srtp->rtp_tx_buffer, len);
    } else {
	status = PJMEDIA_ERRNO_FROM_LIBSRTP(err);
    }
    
    return status;
}
/*
 * send_rtp() is called to send RTP packet. The "pkt" and "size" argument
 * contain both the RTP header and the payload.
 */
static pj_status_t transport_send_rtp( pjmedia_transport *tp,
                                       const void *pkt,
                                       pj_size_t size)
{
    struct tp_adapter *adapter = (struct tp_adapter*)tp;

    /* You may do some processing to the RTP packet here if you want. */

    /* Send the packet using the slave transport */
    return pjmedia_transport_send_rtp(adapter->slave_tp, pkt, size);
}
예제 #3
0
/*
 * send_rtp() is called to send RTP packet. The "pkt" and "size" argument
 * contain both the RTP header and the payload.
 */
static pj_status_t transport_send_rtp(pjmedia_transport *tp,
                                      const void *pkt,
                                      pj_size_t size)
{
    struct tp_zrtp *zrtp = (struct tp_zrtp*)tp;
    pj_uint32_t* pui = (pj_uint32_t*)pkt;
    int32_t newLen = 0;
    pj_status_t rc = PJ_SUCCESS;

    PJ_ASSERT_RETURN(tp && pkt, PJ_EINVAL);


    if (!zrtp->started && zrtp->enableZrtp)
    {
        if (zrtp->localSSRC == 0)
            zrtp->localSSRC = pj_ntohl(pui[2]);   /* Learn own SSRC before starting ZRTP */

        pjmedia_transport_zrtp_startZrtp((pjmedia_transport *)zrtp);
    }

    if (zrtp->srtpSend == NULL)
    {
        return pjmedia_transport_send_rtp(zrtp->slave_tp, pkt, size);
    }
    else
    {
        if (size+80 > MAX_RTP_BUFFER_LEN)
            return PJ_ETOOBIG;

        pj_memcpy(zrtp->sendBuffer, pkt, size);
        rc = zsrtp_protect(zrtp->srtpSend, zrtp->sendBuffer, size, &newLen);
        zrtp->protect++;

        if (rc == 1)
            return pjmedia_transport_send_rtp(zrtp->slave_tp, zrtp->sendBuffer, newLen);
        else
            return PJ_EIGNORED;
    }
}
예제 #4
0
/*
 * Here start with callback functions that support the ZRTP core
 */
static int32_t zrtp_sendDataZRTP(ZrtpContext* ctx, const uint8_t* data, int32_t length)
{
    struct tp_zrtp *zrtp = (struct tp_zrtp*)ctx->userData;
    pj_uint16_t totalLen = length + 12;     /* Fixed number of bytes of ZRTP header */
    pj_uint32_t crc;
    pj_uint8_t* buffer = zrtp->zrtpBuffer;
    pj_uint16_t* pus;
    pj_uint32_t* pui;

    if ((totalLen) > MAX_ZRTP_SIZE)
        return 0;

    /* Get some handy pointers */
    pus = (pj_uint16_t*)buffer;
    pui = (pj_uint32_t*)buffer;

    /* set up fixed ZRTP header */
    *buffer = 0x10;     /* invalid RTP version - refer to ZRTP spec chap 5 */
    *(buffer + 1) = 0;
    pus[1] = pj_htons(zrtp->zrtpSeq++);
    pui[1] = pj_htonl(ZRTP_MAGIC);
    pui[2] = pj_htonl(zrtp->localSSRC);   /* stored in host order */

    /* Copy ZRTP message data behind the header data */
    pj_memcpy(buffer+12, data, length);

    /* Setup and compute ZRTP CRC */
    crc = zrtp_GenerateCksum(buffer, totalLen-CRC_SIZE);

    /* convert and store CRC in ZRTP packet.*/
    crc = zrtp_EndCksum(crc);
    *(uint32_t*)(buffer+totalLen-CRC_SIZE) = pj_htonl(crc);

    /* Send the ZRTP packet using the slave transport */
    return (pjmedia_transport_send_rtp(zrtp->slave_tp, buffer, totalLen) == PJ_SUCCESS) ? 1 : 0;
}
예제 #5
0
int CChannel::sendto(const sockaddr* addr, CPacket& packet) const
{

   // convert control information into network order
   if (packet.getFlag()) {
      for (int i = 0, n = packet.getLength() / 4; i < n; ++ i)
         *((uint32_t *)packet.m_pcData + i) = htonl(*((uint32_t *)packet.m_pcData + i));
   } 

   uint32_t* p = packet.m_nHeader;
   for (int j = 0; j < 4; ++ j)
   {
      *p = htonl(*p);
      ++ p;
   }

#ifdef DEBUGP
   //dump ctrl packet
    printf("\nSend Header:\n");
    dumpHex((char *)packet.m_PacketVector[0].iov_base, packet.m_PacketVector[0].iov_len);
   char *bb = (char *)packet.m_PacketVector[0].iov_base;
   if(bb[0]&0x80) {
      printf("Data:\n");
      dumpHex((char *)packet.m_PacketVector[1].iov_base, packet.m_PacketVector[1].iov_len);
      printf("================\n");
   }
#endif

   int res = -1;
   unsigned size;
   unsigned len;
   natnl_hdr hdr = {0xff, 0x00, 0x0000};
   int is_tnl_data = 0;
   pj_thread_desc desc;
   pj_thread_t *thread = 0;

   if(m_iSocket == -1) {
      pjsua_call *call = (pjsua_call *)m_call;
	  if(call == NULL) return -1;

	  // DEAN, prevent assert fail while garbage collector remove UDT socket on multiple instance. 
	  if (!pj_thread_is_registered(call->inst_id)) {
		  int status = pj_thread_register(call->inst_id, "CChannel::sendto", desc, &thread );
		  if (status != PJ_SUCCESS)
			  return -1;
	  }

	  pj_mutex_lock(call->tnl_stream_lock2);

	  natnl_stream *stream = (natnl_stream *)call->tnl_stream;
	  if(stream == NULL) {
	     pj_mutex_unlock(call->tnl_stream_lock2);
	     return -1;
	  }

     size = CPacket::m_iPktHdrSize + packet.getLength() + sizeof(natnl_hdr);
     len = (CPacket::m_iPktHdrSize + packet.getLength());
	  hdr.length = htons(len);

      memcpy((char *)&m_pktBuffer[sizeof(natnl_hdr)], packet.m_PacketVector[0].iov_base, packet.m_PacketVector[0].iov_len);
      memcpy((char *)&m_pktBuffer[packet.m_PacketVector[0].iov_len+sizeof(natnl_hdr)], packet.m_PacketVector[1].iov_base, packet.m_PacketVector[1].iov_len);
      memcpy((char *)&m_pktBuffer[0], &hdr, sizeof(natnl_hdr));

resend:
	  // DEAN, check if this is tunnel data. If true, update last_data time.
	  is_tnl_data = pjmedia_natnl_udt_packet_is_tnl_data(&m_pktBuffer[0], size);

	  pj_assert(size < sizeof(m_pktBuffer));
		
	  ((pj_uint8_t*)m_pktBuffer)[size] = 0;  // tunnel data flag off

	  if (is_tnl_data) {
		  pj_get_timestamp(&stream->last_data);  // DEAN save current time 
		  ((pj_uint8_t*)m_pktBuffer)[size] = 1;  // tunnel data flag on
	  }

	  res = pjmedia_transport_send_rtp(stream->med_tp, m_pktBuffer, size);	// +Roger modified - stream pointer to med_tp
#if 0 // No need to resend it, because UDT will handle this.
	  if(res == 70011) { //EAGAIN
		  m_pTimer->sleepto(50000); //sleep for 50 us
	      goto resend;   
      }
#endif
      pj_mutex_unlock(call->tnl_stream_lock2);
   }
   res = (0 == res) ? size : -1;

   // convert back into local host order
   //for (int k = 0; k < 4; ++ k)
   //   packet.m_nHeader[k] = ntohl(packet.m_nHeader[k]);
   p = packet.m_nHeader;
   for (int k = 0; k < 4; ++ k)
   {
      *p = ntohl(*p);
       ++ p;
   }

   if (packet.getFlag())
   {
      for (int l = 0, n = packet.getLength() / 4; l < n; ++ l)
         *((uint32_t *)packet.m_pcData + l) = ntohl(*((uint32_t *)packet.m_pcData + l));
   }

   return res;
}
예제 #6
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 = (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);
    }
}