Flow::Flow(FlowTable* flow_table, pjsip_transport* transport, const pj_sockaddr* remote_addr) : _flow_table(flow_table), _transport(transport), _tp_state_listener_key(NULL), _remote_addr(*remote_addr), _token(), _authorized_ids(), _default_id(), _refs(1), _dialogs(0) { // Create the lock for protecting the authorized_ids and default_id. pthread_mutex_init(&_flow_lock, NULL); // Create a random base64 encoded token for the flow. Utils::create_random_token(Flow::TOKEN_LENGTH, _token); if (PJSIP_TRANSPORT_IS_RELIABLE(_transport)) { // We're adding a new reliable transport, so make sure it stays around // until we remove it from the map. pjsip_transport_add_ref(_transport); // Add a state listener so we find out when the flow is destroyed. pjsip_transport_add_state_listener(_transport, &on_transport_state_changed, this, &_tp_state_listener_key); LOG_DEBUG("Added transport listener for flow %p", this); } // Initialize the timer. pj_timer_entry_init(&_timer, PJ_FALSE, (void*)this, &on_timer_expiry); _timer.id = 0; // Start the timer as an idle timer. restart_timer(IDLE_TIMER, IDLE_TIMEOUT); }
void ConnectionTracker::connection_active(pjsip_transport *tp) { // We only track connection-oriented transports. if ((tp->flag & PJSIP_TRANSPORT_DATAGRAM) == 0) { pthread_mutex_lock(&_lock); if (_connection_listeners.find(tp) == _connection_listeners.end()) { // New connection. Register a state listener so we know when it gets // destroyed. pjsip_tp_state_listener_key *key; pjsip_transport_add_state_listener(tp, &connection_state, (void *)this, &key); // Record the listener. _connection_listeners[tp] = key; // If we're quiescing, shutdown the transport immediately. The connection // will be closed when all transactions that use it have ended. // // This catches cases where the connection was established before // quiescing started, but the first message was sent afterwards (so the // first time the connection tracker heard about it was after quiesing had // started). Trying to establish new connections after quiescing has // started should fail as the listening socket will have been closed. if (_quiescing) { pjsip_transport_shutdown(tp); } } pthread_mutex_unlock(&_lock); } }
pj_status_t ConnectionPool::create_connection(int hash_slot) { // Resolve the target host to an IP address. pj_sockaddr remote_addr; pj_status_t status = resolve_host(&_target.host, _target.port, &remote_addr); if (status != PJ_SUCCESS) { TRC_ERROR("Failed to resolve %.*s to an IP address - %s", _target.host.slen, _target.host.ptr, PJUtils::pj_status_to_string(status).c_str()); return status; } // Call TPMGR to create a new transport connection. pjsip_transport* tp; pjsip_tpselector tp_sel; tp_sel.type = PJSIP_TPSELECTOR_LISTENER; tp_sel.u.listener = _tpfactory; status = pjsip_tpmgr_acquire_transport(pjsip_endpt_get_tpmgr(_endpt), (remote_addr.addr.sa_family == pj_AF_INET6()) ? PJSIP_TRANSPORT_TCP6 : PJSIP_TRANSPORT_TCP, &remote_addr, (remote_addr.addr.sa_family == pj_AF_INET6()) ? sizeof(pj_sockaddr_in6) : sizeof(pj_sockaddr_in), &tp_sel, &tp); if (status != PJ_SUCCESS) { return status; } // TPMGR will have already added a reference to the new transport to stop it // being destroyed while we have pointers referencing it. TRC_DEBUG("Created transport %s in slot %d (%.*s:%d to %.*s:%d)", tp->obj_name, hash_slot, (int)tp->local_name.host.slen, tp->local_name.host.ptr, tp->local_name.port, (int)tp->remote_name.host.slen, tp->remote_name.host.ptr, tp->remote_name.port); // Register for transport state callbacks. pjsip_tp_state_listener_key* key; status = pjsip_transport_add_state_listener(tp, &transport_state, (void*)this, &key); // Store the new transport in the hash slot, but marked as disconnected. pthread_mutex_lock(&_tp_hash_lock); _tp_hash[hash_slot].tp = tp; _tp_hash[hash_slot].listener_key = key; _tp_hash[hash_slot].connected = PJ_FALSE; _tp_map[tp] = hash_slot; // Don't increment the connection count here, wait until we get confirmation // that the transport is connected. pthread_mutex_unlock(&_tp_hash_lock); return PJ_SUCCESS; }
pj_status_t ConnectionPool::create_connection(int hash_slot) { // Resolve the target host to an IP address. pj_sockaddr remote_addr; pj_status_t status = resolve_host(&_target.host, &remote_addr); if (status != PJ_SUCCESS) { LOG_ERROR("Failed to resolve %.*s to an IP address - %s", _target.host.slen, _target.host.ptr, PJUtils::pj_status_to_string(status).c_str()); return status; } pj_sockaddr_set_port(&remote_addr, _target.port); // Call the factory to create a new transport connection. pjsip_transport* tp; status = _tpfactory->create_transport(_tpfactory, pjsip_endpt_get_tpmgr(_endpt), _endpt, &remote_addr, sizeof(pj_sockaddr_in), &tp); if (status != PJ_SUCCESS) { return status; } // Add a reference to the new transport to stop it being destroyed while we // have pointers referencing it. pjsip_transport_add_ref(tp); LOG_DEBUG("Created transport %s in slot %d (%.*s:%d to %.*s:%d)", tp->obj_name, hash_slot, (int)tp->local_name.host.slen, tp->local_name.host.ptr, tp->local_name.port, (int)tp->remote_name.host.slen, tp->remote_name.host.ptr, tp->remote_name.port); // Register for transport state callbacks. pjsip_tp_state_listener_key* key; status = pjsip_transport_add_state_listener(tp, &transport_state, (void*)this, &key); // Store the new transport in the hash slot, but marked as disconnected. pthread_mutex_lock(&_tp_hash_lock); _tp_hash[hash_slot].tp = tp; _tp_hash[hash_slot].state = PJSIP_TP_STATE_DISCONNECTED; _tp_map[tp] = hash_slot; // Don't increment the connection count here, wait until we get confirmation // that the transport is connected. pthread_mutex_unlock(&_tp_hash_lock); return PJ_SUCCESS; }