Beispiel #1
0
static void validate_sets(const pj_ioqueue_t *ioqueue,
			  const pj_fd_set_t *rfdset,
			  const pj_fd_set_t *wfdset,
			  const pj_fd_set_t *xfdset)
{
    pj_ioqueue_key_t *key;

    /*
     * This basicly would not work anymore.
     * We need to lock key before performing the check, but we can't do
     * so because we're holding ioqueue mutex. If we acquire key's mutex
     * now, the will cause deadlock.
     */
    pj_assert(0);

    key = ioqueue->active_list.next;
    while (key != &ioqueue->active_list) {
	if (!pj_list_empty(&key->read_list)
#if defined(PJ_HAS_TCP) && PJ_HAS_TCP != 0
	    || !pj_list_empty(&key->accept_list)
#endif
	    ) 
	{
	    pj_assert(PJ_FD_ISSET(key->fd, rfdset));
	} 
	else {
	    pj_assert(PJ_FD_ISSET(key->fd, rfdset) == 0);
	}
	if (!pj_list_empty(&key->write_list)
#if defined(PJ_HAS_TCP) && PJ_HAS_TCP != 0
	    || key->connecting
#endif
	   )
	{
	    pj_assert(PJ_FD_ISSET(key->fd, wfdset));
	}
	else {
	    pj_assert(PJ_FD_ISSET(key->fd, wfdset) == 0);
	}
#if defined(PJ_HAS_TCP) && PJ_HAS_TCP != 0
	if (key->connecting)
	{
	    pj_assert(PJ_FD_ISSET(key->fd, xfdset));
	}
	else {
	    pj_assert(PJ_FD_ISSET(key->fd, xfdset) == 0);
	}
#endif /* PJ_HAS_TCP */

	key = key->next;
    }
}
/* Scan the closing list, and put pending closing keys to free list.
 * Must do this with ioqueue mutex held.
 */
static void scan_closing_keys(pj_ioqueue_t *ioqueue)
{
    if (!pj_list_empty(&ioqueue->closing_list)) {
	pj_time_val now;
	pj_ioqueue_key_t *key;

	pj_gettickcount(&now);
	
	/* Move closing keys to free list when they've finished the closing
	 * idle time.
	 */
	key = ioqueue->closing_list.next;
	while (key != &ioqueue->closing_list) {
	    pj_ioqueue_key_t *next = key->next;

	    pj_assert(key->closing != 0);

	    if (PJ_TIME_VAL_GTE(now, key->free_time)) {
		pj_list_erase(key);
		pj_list_push_back(&ioqueue->free_list, key);
	    }
	    key = next;
	}
    }
}
static int rewrite_route_set(pjsip_rx_data *rdata, pjsip_dialog *dlg)
{
	pjsip_rr_hdr *rr = NULL;
	pjsip_sip_uri *uri;

	if (rdata->msg_info.msg->type == PJSIP_RESPONSE_MSG) {
		pjsip_hdr *iter;
		for (iter = rdata->msg_info.msg->hdr.prev; iter != &rdata->msg_info.msg->hdr; iter = iter->prev) {
			if (iter->type == PJSIP_H_RECORD_ROUTE) {
				rr = (pjsip_rr_hdr *)iter;
				break;
			}
		}
	} else if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_register_method)) {
		rr = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_RECORD_ROUTE, NULL);
	}

	if (rr) {
		uri = pjsip_uri_get_uri(&rr->name_addr);
		rewrite_uri(rdata, uri);
		if (dlg && !pj_list_empty(&dlg->route_set) && !dlg->route_set_frozen) {
			pjsip_routing_hdr *route = dlg->route_set.next;
			uri = pjsip_uri_get_uri(&route->name_addr);
			rewrite_uri(rdata, uri);
		}

		return 0;
	}

	return -1;
}
Beispiel #4
0
int main(int argc, const char *argv[])
{
	int i; 

	struct _Data *head = (struct _Data *)calloc(1, sizeof(struct _Data));
	head->value = 0;
	/* 1. 初始化 */		
	pj_list_init(head);	

	if (pj_list_empty(head)) {
		printf("the list is empty\n");
	}

	/* 2. 尾部追加 */
	struct _Data *data1 = (struct _Data *)calloc(1, sizeof(struct _Data));
	data1->value = 1;
	pj_list_push_back(head, data1);

	/* 3. */

	printf("the size of list is %d.\n", pj_list_size(head));

	for (i = 0; i < pj_list_size(head); i++) {
				
	}
	
	
	exit(EXIT_SUCCESS);
}
Beispiel #5
0
/* Flush all delayed transmision once the socket is connected. */
static void tls_flush_pending_tx(struct tls_transport *tls)
{
    pj_lock_acquire(tls->base.lock);
    while (!pj_list_empty(&tls->delayed_list)) {
	struct delayed_tdata *pending_tx;
	pjsip_tx_data *tdata;
	pj_ioqueue_op_key_t *op_key;
	pj_ssize_t size;
	pj_status_t status;

	pending_tx = tls->delayed_list.next;
	pj_list_erase(pending_tx);

	tdata = pending_tx->tdata_op_key->tdata;
	op_key = (pj_ioqueue_op_key_t*)pending_tx->tdata_op_key;

	/* send! */
	size = tdata->buf.cur - tdata->buf.start;
	status = pj_ssl_sock_send(tls->ssock, op_key, tdata->buf.start, 
				  &size, 0);

	if (status != PJ_EPENDING) {
	    on_data_sent(tls->ssock, op_key, size);
	}
    }
    pj_lock_release(tls->base.lock);
}
Beispiel #6
0
int main()
{
    struct my_node nodes[10];
    struct my_node list;
    struct my_node *it;
    int i;
    
    // Initialize the list as empty.
    pj_list_init(&list);
    
    // Insert nodes.
    for (i=0; i<10; ++i) {
        nodes[i].value = i;
        pj_list_insert_before(&list, &nodes[i]);
    }
    
    // Iterate list nodes.
    it = list.next;
    while (it != &list) {
        PJ_LOG(3,("list", "value = %d", it->value));
        it = it->next;
    }
    
    // Erase all nodes.
    for (i=0; i<10; ++i) {
        pj_list_erase(&nodes[i]);
    }
    
    // List must be empty by now.
    pj_assert( pj_list_empty(&list) );
    
    return 0;
};
/* Destroy TCP transport */
static pj_status_t tcp_destroy(pjsip_transport *transport, 
			       pj_status_t reason)
{
    struct tcp_transport *tcp = (struct tcp_transport*)transport;

    if (tcp->close_reason == 0)
	tcp->close_reason = reason;

    if (tcp->is_registered) {
	tcp->is_registered = PJ_FALSE;
	pjsip_transport_destroy(transport);

	/* pjsip_transport_destroy will recursively call this function
	 * again.
	 */
	return PJ_SUCCESS;
    }

    /* Mark transport as closing */
    tcp->is_closing = PJ_TRUE;

    /* Stop keep-alive timer. */
    if (tcp->ka_timer.id) {
	pjsip_endpt_cancel_timer(tcp->base.endpt, &tcp->ka_timer);
	tcp->ka_timer.id = PJ_FALSE;
    }

    /* Cancel all delayed transmits */
    while (!pj_list_empty(&tcp->delayed_list)) {
	struct delayed_tdata *pending_tx;
	pj_ioqueue_op_key_t *op_key;

	pending_tx = tcp->delayed_list.next;
	pj_list_erase(pending_tx);

	op_key = (pj_ioqueue_op_key_t*)pending_tx->tdata_op_key;

	on_data_sent(tcp->asock, op_key, -reason);
    }

    if (tcp->asock) {
	pj_activesock_close(tcp->asock);
	tcp->asock = NULL;
	tcp->sock = PJ_INVALID_SOCKET;
    } else if (tcp->sock != PJ_INVALID_SOCKET) {
	pj_sock_close(tcp->sock);
	tcp->sock = PJ_INVALID_SOCKET;
    }

    if (tcp->grp_lock) {
	pj_grp_lock_t *grp_lock = tcp->grp_lock;
	tcp->grp_lock = NULL;
	pj_grp_lock_dec_ref(grp_lock);
	/* Transport may have been deleted at this point */
    } else {
	tcp_on_destroy(tcp);
    }

    return PJ_SUCCESS;
}
Beispiel #8
0
PJ_DEF(pj_status_t) pj_grp_lock_add_ref_dbg(pj_grp_lock_t *glock,
                                            const char *file,
                                            int line)
{
    grp_lock_ref *ref;
    pj_status_t status;

    pj_enter_critical_section();
    if (!pj_list_empty(&glock->ref_free_list)) {
	ref = glock->ref_free_list.next;
	pj_list_erase(ref);
    } else {
	ref = PJ_POOL_ALLOC_T(glock->pool, grp_lock_ref);
    }

    ref->file = file;
    ref->line = line;
    pj_list_push_back(&glock->ref_list, ref);

    pj_leave_critical_section();

    status = grp_lock_add_ref(glock);

    if (status != PJ_SUCCESS) {
	pj_enter_critical_section();
	pj_list_erase(ref);
	pj_list_push_back(&glock->ref_free_list, ref);
	pj_leave_critical_section();
    }

    return status;
}
Beispiel #9
0
PJ_INLINE(int) key_has_pending_accept(pj_ioqueue_key_t *key)
{
#if PJ_HAS_TCP
    return !pj_list_empty(&key->accept_list);
#else
    PJ_UNUSED_ARG(key);
    return 0;
#endif
}
Beispiel #10
0
/*
 * Allocate a new G722 codec instance.
 */
static pj_status_t g722_alloc_codec(pjmedia_codec_factory *factory, 
				    const pjmedia_codec_info *id,
				    pjmedia_codec **p_codec)
{
    pjmedia_codec *codec;
    struct g722_data *g722_data;

    PJ_ASSERT_RETURN(factory && id && p_codec, PJ_EINVAL);
    PJ_ASSERT_RETURN(factory == &g722_codec_factory.base, PJ_EINVAL);

    pj_mutex_lock(g722_codec_factory.mutex);

    /* Get free nodes, if any. */
    if (!pj_list_empty(&g722_codec_factory.codec_list)) {
	codec = g722_codec_factory.codec_list.next;
	pj_list_erase(codec);
    } else {
	pj_status_t status;

	codec = PJ_POOL_ZALLOC_T(g722_codec_factory.pool, pjmedia_codec);
	PJ_ASSERT_RETURN(codec != NULL, PJ_ENOMEM);
	codec->op = &g722_op;
	codec->factory = factory;

	g722_data = PJ_POOL_ZALLOC_T(g722_codec_factory.pool, struct g722_data);
	codec->codec_data = g722_data;

#if !PLC_DISABLED
    	/* Create PLC */
    	status = pjmedia_plc_create(g722_codec_factory.pool, 16000, 
			            SAMPLES_PER_FRAME, 0, &g722_data->plc);
	if (status != PJ_SUCCESS) {
	    pj_mutex_unlock(g722_codec_factory.mutex);
	    return status;
	}
#endif

	/* Create silence detector */
	status = pjmedia_silence_det_create(g722_codec_factory.pool,
					    16000, SAMPLES_PER_FRAME,
					    &g722_data->vad);
	if (status != PJ_SUCCESS) {
	    pj_mutex_unlock(g722_codec_factory.mutex);
	    TRACE_((THIS_FILE, "Create silence detector failed (status = %d)", 
                               status));
	    return status;
	}
    }


    pj_mutex_unlock(g722_codec_factory.mutex);

    *p_codec = codec;
    return PJ_SUCCESS;
}
Beispiel #11
0
PJ_DEF(pj_status_t) pjsip_regc_register(pjsip_regc *regc, pj_bool_t autoreg,
					pjsip_tx_data **p_tdata)
{
    pjsip_msg *msg;
    pjsip_contact_hdr *hdr;
    pj_status_t status;
    pjsip_tx_data *tdata;

    PJ_ASSERT_RETURN(regc && p_tdata, PJ_EINVAL);

    pj_lock_acquire(regc->lock);

    status = create_request(regc, &tdata);
    if (status != PJ_SUCCESS) {
	pj_lock_release(regc->lock);
	return status;
    }

    msg = tdata->msg;

    /* Add Contact headers. */
    hdr = regc->contact_hdr_list.next;
    while (hdr != &regc->contact_hdr_list) {
	pjsip_msg_add_hdr(msg, (pjsip_hdr*)
			       pjsip_hdr_shallow_clone(tdata->pool, hdr));
	hdr = hdr->next;
    }

    /* Also add bindings which are to be removed */
    while (!pj_list_empty(&regc->removed_contact_hdr_list)) {
	hdr = regc->removed_contact_hdr_list.next;
	pjsip_msg_add_hdr(msg, (pjsip_hdr*)
			       pjsip_hdr_clone(tdata->pool, hdr));
	pj_list_erase(hdr);
    }
    

    if (regc->expires_hdr)
	pjsip_msg_add_hdr(msg, (pjsip_hdr*)
			       pjsip_hdr_shallow_clone(tdata->pool,
						       regc->expires_hdr));

    if (regc->timer.id != 0) {
	pjsip_endpt_cancel_timer(regc->endpt, &regc->timer);
	regc->timer.id = 0;
    }

    regc->auto_reg = autoreg;

    pj_lock_release(regc->lock);

    /* Done */
    *p_tdata = tdata;
    return PJ_SUCCESS;
}
Beispiel #12
0
static pj_status_t write_children(const pj_json_list *list,
                                  const char quotes[2],
                                  struct write_state *st)
{
    unsigned flags = (quotes[0]=='[') ? NO_NAME : 0;
    pj_status_t status;

    //CHECK( st->writer( st->indent_buf, st->indent, st->user_data) );
    CHECK( st->writer( &quotes[0], 1, st->user_data) );
    CHECK( st->writer( " ", 1, st->user_data) );

    if (!pj_list_empty(list)) {
	pj_bool_t indent_added = PJ_FALSE;
	pj_json_elem *child = list->next;

	if (child->name.slen == 0) {
	    /* Simple list */
	    while (child != (pj_json_elem*)list) {
		status = elem_write(child, st, flags);
		if (status != PJ_SUCCESS)
		    return status;

		if (child->next != (pj_json_elem*)list)
		    CHECK( st->writer( ", ", 2, st->user_data) );
		child = child->next;
	    }
	} else {
	    if (st->indent < sizeof(st->indent_buf)) {
		st->indent += PJ_JSON_INDENT_SIZE;
		indent_added = PJ_TRUE;
	    }
	    CHECK( st->writer( "\n", 1, st->user_data) );
	    while (child != (pj_json_elem*)list) {
		status = elem_write(child, st, flags);
		if (status != PJ_SUCCESS)
		    return status;

		if (child->next != (pj_json_elem*)list)
		    CHECK( st->writer( ",\n", 2, st->user_data) );
		else
		    CHECK( st->writer( "\n", 1, st->user_data) );
		child = child->next;
	    }
	    if (indent_added) {
		st->indent -= PJ_JSON_INDENT_SIZE;
	    }
	    CHECK( st->writer( st->indent_buf, st->indent, st->user_data) );
	}
    }
    CHECK( st->writer( &quotes[1], 1, st->user_data) );

    return PJ_SUCCESS;
}
Beispiel #13
0
/*
 * Reset the echo canceller.
 */
void pjs_echo_canceller::reset() {
	PPJ_WaitAndLock wl(*lock);
	while (!pj_list_empty(&lat_buf)) {
		struct frame *frm;
		frm = lat_buf.next;
		pj_list_erase(frm);
		pj_list_push_back(&lat_free, frm);
	}
	lat_ready = PJ_FALSE;
	speex_echo_state_reset(state);
	pjmedia_delay_buf_reset(delay_buf);
}
Beispiel #14
0
/*
 * Allocate a new CODEC2 codec instance.
 */
static pj_status_t codec2_alloc_codec( pjmedia_codec_factory *factory,
				    const pjmedia_codec_info *id,
				    pjmedia_codec **p_codec)
{
    pjmedia_codec *codec;
    struct codec2_data *codec2_data;
    pj_status_t status;

    PJ_ASSERT_RETURN(factory && id && p_codec, PJ_EINVAL);
    PJ_ASSERT_RETURN(factory == &codec2_codec_factory.base, PJ_EINVAL);
    PJ_LOG(4, (THIS_FILE, "codec2 alloc codecs"));

    pj_mutex_lock(codec2_codec_factory.mutex);

    /* Get free nodes, if any. */
    if (!pj_list_empty(&codec2_codec_factory.codec_list)) {
	codec = codec2_codec_factory.codec_list.next;
	pj_list_erase(codec);
    } else {
	codec = PJ_POOL_ZALLOC_T(codec2_codec_factory.pool, pjmedia_codec);
	PJ_ASSERT_RETURN(codec != NULL, PJ_ENOMEM);
	codec->op = &codec2_op;
	codec->factory = factory;

	codec2_data = PJ_POOL_ZALLOC_T(codec2_codec_factory.pool, struct codec2_data);
	codec->codec_data = codec2_data;

#if !PLC_DISABLED
	/* Create PLC */
	status = pjmedia_plc_create(codec2_codec_factory.pool, 8000,
				    160, 0, &codec2_data->plc);
	if (status != PJ_SUCCESS) {
	    pj_mutex_unlock(codec2_codec_factory.mutex);
	    return status;
	}
#endif

	/* Create silence detector */
	status = pjmedia_silence_det_create(codec2_codec_factory.pool,
					    8000, 160,
					    &codec2_data->vad);
	if (status != PJ_SUCCESS) {
	    pj_mutex_unlock(codec2_codec_factory.mutex);
	    return status;
	}
    }

    pj_mutex_unlock(codec2_codec_factory.mutex);

    *p_codec = codec;
    return PJ_SUCCESS;
}
/* Handler to destroy the transport; called by transport manager */
static pj_status_t loop_destroy(pjsip_transport *tp)
{
    struct loop_transport *loop = (struct loop_transport*)tp;
    
    PJ_ASSERT_RETURN(tp && (tp->key.type == PJSIP_TRANSPORT_LOOP ||
	             tp->key.type == PJSIP_TRANSPORT_LOOP_DGRAM), PJ_EINVAL);
    
    loop->thread_quit_flag = 1;
    /* Unlock transport mutex before joining thread. */
    pj_lock_release(tp->lock);
    pj_thread_join(loop->thread);
    pj_thread_destroy(loop->thread);

    /* Clear pending send notifications. */
    while (!pj_list_empty(&loop->send_list)) {
	struct send_list *node = loop->send_list.next;
	/* Notify callback. */
	if (node->callback) {
	    (*node->callback)(&loop->base, node->token, -PJSIP_ESHUTDOWN);
	}
	pj_list_erase(node);
	pjsip_tx_data_dec_ref(node->tdata);
    }

    /* Clear "incoming" packets in the queue. */
    while (!pj_list_empty(&loop->recv_list)) {
	struct recv_list *node = loop->recv_list.next;
	pj_list_erase(node);
	pjsip_endpt_release_pool(loop->base.endpt,
				 node->rdata.tp_info.pool);
    }

    /* Self destruct.. heheh.. */
    pj_lock_destroy(loop->base.lock);
    pj_atomic_destroy(loop->base.ref_cnt);
    pjsip_endpt_release_pool(loop->base.endpt, loop->base.pool);

    return PJ_SUCCESS;
}
Beispiel #16
0
/*
 * Acquire one dlg_set node to be put in the hash table.
 * This will first look in the free nodes list, then allocate
 * a new one from UA's pool when one is not available.
 */
static struct dlg_set *alloc_dlgset_node(void)
{
    struct dlg_set *set;

    if (!pj_list_empty(&mod_ua.free_dlgset_nodes)) {
	set = mod_ua.free_dlgset_nodes.next;
	pj_list_erase(set);
	return set;
    } else {
	set = PJ_POOL_ALLOC_T(mod_ua.pool, struct dlg_set);
	return set;
    }
}
Beispiel #17
0
/*
 * Reset the echo canceller.
 */
PJ_DEF(pj_status_t) pjmedia_echo_reset(pjmedia_echo_state *echo )
{
    while (!pj_list_empty(&echo->lat_buf)) {
	struct frame *frm;
	frm = echo->lat_buf.next;
	pj_list_erase(frm);
	pj_list_push_back(&echo->lat_free, frm);
    }
    echo->lat_ready = PJ_FALSE;
    pjmedia_delay_buf_reset(echo->delay_buf);
    echo->op->ec_reset(echo->state);
    return PJ_SUCCESS;
}
Beispiel #18
0
static void stun_sess_on_destroy(void *comp)
{
    pj_stun_session *sess = (pj_stun_session*)comp;

    while (!pj_list_empty(&sess->pending_request_list)) {
	pj_stun_tx_data *tdata = sess->pending_request_list.next;
	destroy_tdata(tdata, PJ_TRUE);
    }

    while (!pj_list_empty(&sess->cached_response_list)) {
	pj_stun_tx_data *tdata = sess->cached_response_list.next;
	destroy_tdata(tdata, PJ_TRUE);
    }

    if (sess->rx_pool) {
	pj_pool_release(sess->rx_pool);
	sess->rx_pool = NULL;
    }

    pj_pool_release(sess->pool);

    TRACE_((THIS_FILE, "STUN session %p destroyed", sess));
}
Beispiel #19
0
static pj_status_t g711_alloc_codec( pjmedia_codec_factory *factory, 
				     const pjmedia_codec_info *id,
				     pjmedia_codec **p_codec)
{
    pjmedia_codec *codec = NULL;
    pj_status_t status;

    PJ_ASSERT_RETURN(factory==&g711_factory.base, PJ_EINVAL);

    /* Lock mutex. */
    pj_mutex_lock(g711_factory.mutex);

    /* Allocate new codec if no more is available */
    if (pj_list_empty(&g711_factory.codec_list)) {
	struct g711_private *codec_priv;

	codec = PJ_POOL_ALLOC_T(g711_factory.pool, pjmedia_codec);
	codec_priv = PJ_POOL_ZALLOC_T(g711_factory.pool, struct g711_private);
	if (!codec || !codec_priv) {
	    pj_mutex_unlock(g711_factory.mutex);
	    return PJ_ENOMEM;
	}

	/* Set the payload type */
	codec_priv->pt = id->pt;

#if !PLC_DISABLED
	/* Create PLC, always with 10ms ptime */
	status = pjmedia_plc_create(g711_factory.pool, 8000,
				    SAMPLES_PER_FRAME,
				    0, &codec_priv->plc);
	if (status != PJ_SUCCESS) {
	    pj_mutex_unlock(g711_factory.mutex);
	    return status;
	}
#endif

	/* Create VAD */
	status = pjmedia_silence_det_create(g711_factory.pool,
					    8000, SAMPLES_PER_FRAME,
					    &codec_priv->vad);
	if (status != PJ_SUCCESS) {
	    pj_mutex_unlock(g711_factory.mutex);
	    return status;
	}

	codec->factory = factory;
	codec->op = &g711_op;
	codec->codec_data = codec_priv;
    } else {
Beispiel #20
0
PJ_DEF(pj_status_t) pj_stun_session_destroy(pj_stun_session *sess)
{
    PJ_ASSERT_RETURN(sess, PJ_EINVAL);

    pj_lock_acquire(sess->lock);

    /* Can't destroy if we're in a callback */
    sess->destroy_request = PJ_TRUE;
    if (pj_atomic_get(sess->busy)) {
	pj_lock_release(sess->lock);
	return PJ_EPENDING;
    }

    while (!pj_list_empty(&sess->pending_request_list)) {
	pj_stun_tx_data *tdata = sess->pending_request_list.next;
	destroy_tdata(tdata, PJ_TRUE);
    }

    while (!pj_list_empty(&sess->cached_response_list)) {
	pj_stun_tx_data *tdata = sess->cached_response_list.next;
	destroy_tdata(tdata, PJ_TRUE);
    }
    pj_lock_release(sess->lock);

    if (sess->delete_lock) {
	pj_lock_destroy(sess->lock);
    }

    if (sess->rx_pool) {
	pj_pool_release(sess->rx_pool);
	sess->rx_pool = NULL;
    }

    pj_pool_release(sess->pool);

    return PJ_SUCCESS;
}
Beispiel #21
0
/*
 * Let the Echo Canceller know that a frame has been played to the speaker.
 */
pj_status_t pjs_echo_canceller::playback(pj_int16_t *play_frm, unsigned size) {
	/* Playing frame should be stored, as it will be used by echo_capture()
	 * as reference frame, delay buffer is used for storing the playing frames
	 * as in case there was clock drift between mic & speaker.
	 *
	 * Ticket #830:
	 * Note that pjmedia_delay_buf_put() may modify the input frame and those
	 * modified frames may not be smooth, i.e: if there were two or more
	 * consecutive pjmedia_delay_buf_get() before next pjmedia_delay_buf_put(),
	 * so we'll just feed the delay buffer with the copy of playing frame,
	 * instead of the original playing frame. However this will cause the EC
	 * uses slight 'different' frames (for reference) than actually played
	 * by the speaker.
	 */
	if(samples_per_frame!=size)
	{
		PJ_LOG(1, (THIS_FILE, "WRONG SIZE ON PLAYBACK %d != %d",size,samples_per_frame));
		return -1;
	}

	PPJ_WaitAndLock wl(*lock);

	pjmedia_copy_samples(frm_buf, play_frm, samples_per_frame);
	pjmedia_delay_buf_put(delay_buf, frm_buf);

	if (!lat_ready) {
		/* We've not built enough latency in the buffer, so put this frame
		 * in the latency buffer list.
		 */
		struct frame *frm;

		if (pj_list_empty(&lat_free)) {
			lat_ready = PJ_TRUE;
			PJ_LOG(4, (THIS_FILE, "Latency bufferring complete"));
			return PJ_SUCCESS;
		}

		frm = lat_free.prev;
		pj_list_erase(frm);

		/* Move one frame from delay buffer to the latency buffer. */
		pjmedia_delay_buf_get(delay_buf, frm_buf);
		pjmedia_copy_samples(frm->buf, frm_buf, samples_per_frame);
		pj_list_push_back(&lat_buf, frm);
	}

	return PJ_SUCCESS;
}
Beispiel #22
0
/*
 * Let the Echo Canceller know that a frame has been played to the speaker.
 */
PJ_DEF(pj_status_t) pjmedia_echo_playback( pjmedia_echo_state *echo,
					   pj_int16_t *play_frm )
{
    /* If EC algo has playback handler, just pass the frame. */
    if (echo->op->ec_playback) {
	return (*echo->op->ec_playback)(echo->state, play_frm);
    }

    /* Playing frame should be stored, as it will be used by echo_capture() 
     * as reference frame, delay buffer is used for storing the playing frames
     * as in case there was clock drift between mic & speaker.
     *
     * Ticket #830:
     * Note that pjmedia_delay_buf_put() may modify the input frame and those
     * modified frames may not be smooth, i.e: if there were two or more
     * consecutive pjmedia_delay_buf_get() before next pjmedia_delay_buf_put(),
     * so we'll just feed the delay buffer with the copy of playing frame,
     * instead of the original playing frame. However this will cause the EC 
     * uses slight 'different' frames (for reference) than actually played 
     * by the speaker.
     */
    pjmedia_copy_samples(echo->frm_buf, play_frm, 
			 echo->samples_per_frame);
    pjmedia_delay_buf_put(echo->delay_buf, echo->frm_buf);

    if (!echo->lat_ready) {
	/* We've not built enough latency in the buffer, so put this frame
	 * in the latency buffer list.
	 */
	struct frame *frm;

	if (pj_list_empty(&echo->lat_free)) {
	    echo->lat_ready = PJ_TRUE;
	    PJ_LOG(5,(echo->obj_name, "Latency bufferring complete"));
	    return PJ_SUCCESS;
	}
	    
	frm = echo->lat_free.prev;
	pj_list_erase(frm);

	/* Move one frame from delay buffer to the latency buffer. */
	pjmedia_delay_buf_get(echo->delay_buf, echo->frm_buf);
	pjmedia_copy_samples(frm->buf, echo->frm_buf, echo->samples_per_frame);
	pj_list_push_back(&echo->lat_buf, frm);
    }

    return PJ_SUCCESS;
}
Beispiel #23
0
pjsip_multipart_get_first_part(const pjsip_msg_body *mp)
{
    struct multipart_data *m_data;

    /* Must specify mandatory params */
    PJ_ASSERT_RETURN(mp, NULL);

    /* mp must really point to an actual multipart msg body */
    PJ_ASSERT_RETURN(mp->print_body==&multipart_print_body, NULL);

    m_data = (struct multipart_data*)mp->data;
    if (pj_list_empty(&m_data->part_head))
	return NULL;

    return m_data->part_head.next;
}
Beispiel #24
0
PJ_DEF(pj_status_t) pjsip_ua_unregister_dlg( pjsip_user_agent *ua,
					     pjsip_dialog *dlg )
{
    struct dlg_set *dlg_set;
    pjsip_dialog *d;

    /* Sanity-check arguments. */
    PJ_ASSERT_RETURN(ua && dlg, PJ_EINVAL);

    /* Check that dialog has been registered. */
    PJ_ASSERT_RETURN(dlg->dlg_set, PJ_EINVALIDOP);

    /* Lock user agent. */
    pj_mutex_lock(mod_ua.mutex);

    /* Find this dialog from the dialog set. */
    dlg_set = (struct dlg_set*) dlg->dlg_set;
    d = dlg_set->dlg_list.next;
    while (d != (pjsip_dialog*)&dlg_set->dlg_list && d != dlg) {
	d = d->next;
    }

    if (d != dlg) {
	pj_assert(!"Dialog is not registered!");
	pj_mutex_unlock(mod_ua.mutex);
	return PJ_EINVALIDOP;
    }

    /* Remove this dialog from the list. */
    pj_list_erase(dlg);

    /* If dialog list is empty, remove the dialog set from the hash table. */
    if (pj_list_empty(&dlg_set->dlg_list)) {
	pj_hash_set_lower(NULL, mod_ua.dlg_table, dlg->local.info->tag.ptr,
		          (unsigned)dlg->local.info->tag.slen, 
			  dlg->local.tag_hval, NULL);

	/* Return dlg_set to free nodes. */
	pj_list_push_back(&mod_ua.free_dlgset_nodes, dlg_set);
    }

    /* Unlock user agent. */
    pj_mutex_unlock(mod_ua.mutex);

    /* Done. */
    return PJ_SUCCESS;
}
Beispiel #25
0
/*
 * Allocate a new Speex codec instance.
 */
static pj_status_t spx_alloc_codec( pjmedia_codec_factory *factory, 
				    const pjmedia_codec_info *id,
				    pjmedia_codec **p_codec)
{
    pjmedia_codec *codec;
    struct spx_private *spx;

    PJ_ASSERT_RETURN(factory && id && p_codec, PJ_EINVAL);
    PJ_ASSERT_RETURN(factory == &spx_factory.base, PJ_EINVAL);


    pj_mutex_lock(spx_factory.mutex);

    /* Get free nodes, if any. */
    if (!pj_list_empty(&spx_factory.codec_list)) {
	codec = spx_factory.codec_list.next;
	pj_list_erase(codec);
    } else {
	codec = PJ_POOL_ZALLOC_T(spx_factory.pool, pjmedia_codec);
	PJ_ASSERT_RETURN(codec != NULL, PJ_ENOMEM);
	codec->op = &spx_op;
	codec->factory = factory;
	codec->codec_data = pj_pool_alloc(spx_factory.pool,
					  sizeof(struct spx_private));
    }

    pj_mutex_unlock(spx_factory.mutex);

    spx = (struct spx_private*) codec->codec_data;
    spx->enc = NULL;
    spx->dec = NULL;

    if (id->clock_rate <= 8000)
	spx->param_id = PARAM_NB;
    else if (id->clock_rate <= 16000)
	spx->param_id = PARAM_WB;
    else
	spx->param_id = PARAM_UWB;

    *p_codec = codec;
    return PJ_SUCCESS;
}
static int rewrite_contact(pjsip_rx_data *rdata, pjsip_dialog *dlg)
{
	pjsip_contact_hdr *contact;

	contact = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, NULL);
	if (contact && !contact->star && (PJSIP_URI_SCHEME_IS_SIP(contact->uri) || PJSIP_URI_SCHEME_IS_SIPS(contact->uri))) {
		pjsip_sip_uri *uri = pjsip_uri_get_uri(contact->uri);

		rewrite_uri(rdata, uri);

		if (dlg && pj_list_empty(&dlg->route_set) && (!dlg->remote.contact
			|| pjsip_uri_cmp(PJSIP_URI_IN_REQ_URI, dlg->remote.contact->uri, contact->uri))) {
			dlg->remote.contact = (pjsip_contact_hdr*)pjsip_hdr_clone(dlg->pool, contact);
			dlg->target = dlg->remote.contact->uri;
		}
		return 0;
	}

	return -1;
}
Beispiel #27
0
/*
 * Allocate a new SILK codec instance.
 */
static pj_status_t silk_alloc_codec(pjmedia_codec_factory *factory,
				    const pjmedia_codec_info *id,
				    pjmedia_codec **p_codec)
{
    pjmedia_codec *codec;
    struct silk_private *silk;

    PJ_ASSERT_RETURN(factory && id && p_codec, PJ_EINVAL);
    PJ_ASSERT_RETURN(factory == &silk_factory.base, PJ_EINVAL);


    pj_mutex_lock(silk_factory.mutex);

    /* Get free nodes, if any. */
    if (!pj_list_empty(&silk_factory.codec_list)) {
		codec = silk_factory.codec_list.next;
		pj_list_erase(codec);
    } else {
		codec = PJ_POOL_ZALLOC_T(silk_factory.pool, pjmedia_codec);
		PJ_ASSERT_RETURN(codec != NULL, PJ_ENOMEM);
		codec->op = &silk_op;
		codec->factory = factory;
		codec->codec_data = pj_pool_alloc(silk_factory.pool,
						  sizeof(struct silk_private));
    }

    pj_mutex_unlock(silk_factory.mutex);

    silk = (struct silk_private*) codec->codec_data;
    silk->enc_ready = PJ_FALSE;
    silk->dec_ready = PJ_FALSE;
    silk->param_id = silk_get_type_for_clock_rate(id->clock_rate);

    /* Create pool for codec instance */
    silk->pool = pjmedia_endpt_create_pool(silk_factory.endpt, "silkcodec", 512, 512);

    *p_codec = codec;
    return PJ_SUCCESS;
}
/*
 * pj_ioqueue_poll()
 *
 * Poll for events.
 */
PJ_DEF(int) pj_ioqueue_poll( pj_ioqueue_t *ioqueue, const pj_time_val *timeout)
{
    DWORD dwMsec;
#if PJ_HAS_TCP
    int connect_count = 0;
#endif
    int event_count = 0;

    PJ_ASSERT_RETURN(ioqueue, -PJ_EINVAL);

    /* Calculate miliseconds timeout for GetQueuedCompletionStatus */
    dwMsec = timeout ? timeout->sec*1000 + timeout->msec : INFINITE;

    /* Poll for completion status. */
    event_count = poll_iocp(ioqueue->iocp, dwMsec, NULL, NULL);

#if PJ_HAS_TCP
    /* Check the connecting array, only when there's no activity. */
    if (event_count == 0) {
	connect_count = check_connecting(ioqueue);
	if (connect_count > 0)
	    event_count += connect_count;
    }
#endif

#if PJ_IOQUEUE_HAS_SAFE_UNREG
    /* Check the closing keys only when there's no activity and when there are
     * pending closing keys.
     */
    if (event_count == 0 && !pj_list_empty(&ioqueue->closing_list)) {
	pj_lock_acquire(ioqueue->lock);
	scan_closing_keys(ioqueue);
	pj_lock_release(ioqueue->lock);
    }
#endif

    /* Return number of events. */
    return event_count;
}
Beispiel #29
0
/* Flush all delayed transmision once the socket is connected. */
static void tcp_flush_pending_tx(struct tcp_transport *tcp)
{
    pj_time_val now;

    pj_gettickcount(&now);
    pj_lock_acquire(tcp->base.lock);
    while (!pj_list_empty(&tcp->delayed_list)) {
	struct delayed_tdata *pending_tx;
	pjsip_tx_data *tdata;
	pj_ioqueue_op_key_t *op_key;
	pj_ssize_t size;
	pj_status_t status;

	pending_tx = tcp->delayed_list.next;
	pj_list_erase(pending_tx);

	tdata = pending_tx->tdata_op_key->tdata;
	op_key = (pj_ioqueue_op_key_t*)pending_tx->tdata_op_key;

        if (pending_tx->timeout.sec > 0 &&
            PJ_TIME_VAL_GT(now, pending_tx->timeout))
        {
            continue;
        }

	/* send! */
	size = tdata->buf.cur - tdata->buf.start;
	status = pj_activesock_send(tcp->asock, op_key, tdata->buf.start, 
				    &size, 0);
	if (status != PJ_EPENDING) {
            pj_lock_release(tcp->base.lock);
	    on_data_sent(tcp->asock, op_key, size);
            pj_lock_acquire(tcp->base.lock);
	}

    }
    pj_lock_release(tcp->base.lock);
}
Beispiel #30
0
/*
 * Allocate a new OPUS codec instance.
 */
static pj_status_t opus_alloc_codec(pjmedia_codec_factory *factory,
                                    const pjmedia_codec_info *id,
                                    pjmedia_codec **p_codec) {
  pjmedia_codec *codec;
  struct opus_private *opus;

  PJ_ASSERT_RETURN(factory && id && p_codec, PJ_EINVAL);
  PJ_ASSERT_RETURN(factory == &opus_factory.base, PJ_EINVAL);

  pj_mutex_lock(opus_factory.mutex);

  /* Get free nodes, if any. */
  if (!pj_list_empty(&opus_factory.codec_list)) {
    codec = opus_factory.codec_list.next;
    pj_list_erase(codec);
  } else {
    codec = PJ_POOL_ZALLOC_T(opus_factory.pool, pjmedia_codec);
    PJ_ASSERT_RETURN(codec != NULL, PJ_ENOMEM);
    codec->op = &opus_op;
    codec->factory = factory;
    codec->codec_data =
        pj_pool_alloc(opus_factory.pool, sizeof(struct opus_private));
  }

  pj_mutex_unlock(opus_factory.mutex);

  opus = (struct opus_private *)codec->codec_data;
  opus->enc_ready = PJ_FALSE;
  opus->dec_ready = PJ_FALSE;

  /* Create pool for codec instance */
  opus->pool =
      pjmedia_endpt_create_pool(opus_factory.endpt, "opuscodec", 512, 512);

  *p_codec = codec;
  return PJ_SUCCESS;
}