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; }
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); }
/* 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); }
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; }
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; }
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 }
/* * 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; }
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 != ®c->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(®c->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, ®c->timer); regc->timer.id = 0; } regc->auto_reg = autoreg; pj_lock_release(regc->lock); /* Done */ *p_tdata = tdata; return PJ_SUCCESS; }
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( "es[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( "es[1], 1, st->user_data) ); return PJ_SUCCESS; }
/* * 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); }
/* * 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; }
/* * 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; } }
/* * 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; }
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)); }
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 {
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; }
/* * 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; }
/* * 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; }
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; }
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; }
/* * 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; }
/* * 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; }
/* 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); }
/* * 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; }