示例#1
0
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);
}
示例#2
0
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);
  }
}
示例#3
0
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;
}
示例#4
0
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;
}