static int transport_shutdown(void *data)
{
	pjsip_transport *transport = data;

	pjsip_transport_shutdown(transport);
	return 0;
}
Esempio n. 2
0
void ConnectionPool::quiesce_connection(int hash_slot)
{
  pthread_mutex_lock(&_tp_hash_lock);
  pjsip_transport* tp = _tp_hash[hash_slot].tp;

  if (tp != NULL)
  {
    if (_tp_hash[hash_slot].state == PJSIP_TP_STATE_CONNECTED) 
    {
      // Connection was established, so update statistics.
      --_active_connections;
      decrement_connection_count(tp);
    }

    // Remove the transport from the hash and the map.
    _tp_hash[hash_slot].tp = NULL;
    _tp_hash[hash_slot].state = PJSIP_TP_STATE_DISCONNECTED;
    _tp_map.erase(tp);
    
    // Release the lock now so we don't have a deadlock if pjsip_transport_shutdown
    // calls the transport state listener.
    pthread_mutex_unlock(&_tp_hash_lock);

    // Quiesce the transport.  PJSIP will destroy the transport when there
    // are no further references to it.
    pjsip_transport_shutdown(tp);

    // Remove our reference to the transport.
    pjsip_transport_dec_ref(tp);
  }
  else
  {
    pthread_mutex_unlock(&_tp_hash_lock);
  }
}
Esempio n. 3
0
SipTransport::~SipTransport()
{
    if (transport) {
        pjsip_transport_shutdown(transport);
        pjsip_transport_dec_ref(transport); // ??
        DEBUG("Destroying transport (refcount: %u)",  pj_atomic_get(transport->ref_cnt));
        transport = nullptr;
    }
}
void
SipTransportBroker::shutdown()
{
    std::unique_lock<std::mutex> lock(transportMapMutex_);
    for (auto& t : transports_) {
        if (auto transport = t.second.lock()) {
            pjsip_transport_shutdown(transport->get());
        }
    }
}
static void tls_init_shutdown(struct tls_transport *tls, pj_status_t status)
{
    pjsip_tp_state_callback state_cb;

    if (tls->close_reason == PJ_SUCCESS)
	tls->close_reason = status;

    if (tls->base.is_shutdown || tls->base.is_destroying)
	return;

    /* Prevent immediate transport destroy by application, as transport
     * state notification callback may be stacked and transport instance
     * must remain valid at any point in the callback.
     */
    pjsip_transport_add_ref(&tls->base);

    /* Notify application of transport disconnected state */
    state_cb = pjsip_tpmgr_get_state_cb(tls->base.tpmgr);
    if (state_cb) {
	pjsip_transport_state_info state_info;
	pjsip_tls_state_info tls_info;
	pj_ssl_sock_info ssl_info;
	
	/* Init transport state info */
	pj_bzero(&state_info, sizeof(state_info));
	state_info.status = tls->close_reason;

	if (tls->ssock && 
	    pj_ssl_sock_get_info(tls->ssock, &ssl_info) == PJ_SUCCESS)
	{
	    pj_bzero(&tls_info, sizeof(tls_info));
	    tls_info.ssl_sock_info = &ssl_info;
	    state_info.ext_info = &tls_info;
	}

	(*state_cb)(&tls->base, PJSIP_TP_STATE_DISCONNECTED, &state_info);
    }

    /* check again */
    if (tls->base.is_shutdown || tls->base.is_destroying) {
        pjsip_transport_dec_ref(&tls->base);
	return;
    }

    /* We can not destroy the transport since high level objects may
     * still keep reference to this transport. So we can only 
     * instruct transport manager to gracefully start the shutdown
     * procedure for this transport.
     */
    pjsip_transport_shutdown(&tls->base);

    /* Now, it is ok to destroy the transport. */
    pjsip_transport_dec_ref(&tls->base);
}
static int transport_shutdown(void *data)
{
	RAII_VAR(struct ast_sip_contact_transport *, ct, NULL, ao2_cleanup);
	pjsip_transport *transport = data;

	if ((ct = ast_sip_location_retrieve_contact_transport_by_transport(transport))) {
		ast_sip_location_delete_contact_transport(ct);
	}

	pjsip_transport_shutdown(transport);
	return 0;
}
static int transport_shutdown(void *data)
{
	struct ws_transport *wstransport = data;

	if (!wstransport->transport.is_shutdown && !wstransport->transport.is_destroying) {
		pjsip_transport_shutdown(&wstransport->transport);
	}

	/* Note that the destructor calls PJSIP functions,
	 * therefore it must be called in a PJSIP thread.
	 */
	ao2_ref(wstransport, -1);

	return 0;
}
Esempio n. 8
0
static int destroy_sip_transport_state(void *data)
{
	struct ast_sip_transport_state *transport_state = data;

	ast_free(transport_state->id);
	ast_free_ha(transport_state->localnet);

	if (transport_state->external_address_refresher) {
		ast_dnsmgr_release(transport_state->external_address_refresher);
	}
	if (transport_state->transport) {
		pjsip_transport_shutdown(transport_state->transport);
	}

	return 0;
}
Esempio n. 9
0
/* 
 * Callback from ioqueue when packet is sent.
 */
static pj_bool_t on_data_sent(pj_ssl_sock_t *ssock,
			      pj_ioqueue_op_key_t *op_key,
			      pj_ssize_t bytes_sent)
{
    struct tls_transport *tls = (struct tls_transport*) 
    				pj_ssl_sock_get_user_data(ssock);
    pjsip_tx_data_op_key *tdata_op_key = (pjsip_tx_data_op_key*)op_key;

    /* Note that op_key may be the op_key from keep-alive, thus
     * it will not have tdata etc.
     */

    tdata_op_key->tdata = NULL;

    if (tdata_op_key->callback) {
	/*
	 * Notify sip_transport.c that packet has been sent.
	 */
	if (bytes_sent == 0)
	    bytes_sent = -PJ_RETURN_OS_ERROR(OSERR_ENOTCONN);

	tdata_op_key->callback(&tls->base, tdata_op_key->token, bytes_sent);

	/* Mark last activity time */
	pj_gettimeofday(&tls->last_activity);

    }

    /* Check for error/closure */
    if (bytes_sent <= 0) {
	pj_status_t status;

	PJ_LOG(5,(tls->base.obj_name, "TLS send() error, sent=%d", 
		  bytes_sent));

	status = (bytes_sent == 0) ? PJ_RETURN_OS_ERROR(OSERR_ENOTCONN) :
				     -bytes_sent;
	if (tls->close_reason==PJ_SUCCESS) tls->close_reason = status;
	pjsip_transport_shutdown(&tls->base);

	return PJ_FALSE;
    }
    
    return PJ_TRUE;
}
Esempio n. 10
0
void ConnectionTracker::quiesce()
{
  pj_bool_t quiesce_complete = PJ_FALSE;

  TRC_DEBUG("Start quiescing connections");

  pthread_mutex_lock(&_lock);

  // Flag that we're now quiescing. It is illegal to call this method if we're
  // already quiescing.
  assert(!_quiescing);
  _quiescing = PJ_TRUE;

  if (_connection_listeners.empty())
  {
    // There are no active connections, so quiescing is already complete.
    TRC_DEBUG("Connection quiescing complete");
    quiesce_complete = PJ_TRUE;
  }
  else
  {
    // Call shutdown on each connection. PJSIP's reference counting means a
    // connection will be closed once all transactions that use it have
    // completed.
    for (std::map<pjsip_transport *, pjsip_tp_state_listener_key *>::iterator 
                                             it = _connection_listeners.begin();
         it != _connection_listeners.end();
         ++it)
    {
      TRC_DEBUG("Shutdown connection %p", it->first);
      pjsip_transport_shutdown(it->first);
    }
  }

  pthread_mutex_unlock(&_lock);

  // If quiescing is now complete notify the quiescing manager.  This is done
  // without holding the lock to avoid potential deadlocks.
  if (quiesce_complete) {
    _on_quiesced_handler->connections_quiesced();
  }
}
Esempio n. 11
0
void ConnectionPool::quiesce_connection(int hash_slot)
{
  pthread_mutex_lock(&_tp_hash_lock);
  pjsip_transport* tp = _tp_hash[hash_slot].tp;

  if (tp != NULL)
  {
    if (_tp_hash[hash_slot].connected)
    {
      // Connection was established, so update statistics.
      --_active_connections;
      decrement_connection_count(tp);
    }

    // Don't listen for any more state changes on this connection.
    pjsip_transport_remove_state_listener(tp,
                                          _tp_hash[hash_slot].listener_key,
                                          (void *)this);

    // Remove the transport from the hash and the map.
    _tp_hash[hash_slot].tp = NULL;
    _tp_hash[hash_slot].listener_key = NULL;
    _tp_hash[hash_slot].connected = PJ_FALSE;
    _tp_map.erase(tp);

    // Release the lock now so we don't have a deadlock if pjsip_transport_shutdown
    // calls the transport state listener.
    pthread_mutex_unlock(&_tp_hash_lock);

    // Quiesce the transport.  PJSIP will destroy the transport when there
    // are no further references to it.
    pjsip_transport_shutdown(tp);

    // Remove our reference to the transport.
    pjsip_transport_dec_ref(tp);
  }
  else
  {
    pthread_mutex_unlock(&_tp_hash_lock);
  }
}
Esempio n. 12
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);
  }
}
Esempio n. 13
0
/*
 * This callback is called by SSL socket when pending accept() operation
 * has completed.
 */
static pj_bool_t on_accept_complete(pj_ssl_sock_t *ssock,
				    pj_ssl_sock_t *new_ssock,
				    const pj_sockaddr_t *src_addr,
				    int src_addr_len)
{
    struct tls_listener *listener;
    struct tls_transport *tls;
    pj_ssl_sock_info ssl_info;
    char addr[PJ_INET6_ADDRSTRLEN+10];
    pjsip_tp_state_callback state_cb;
    pj_bool_t is_shutdown;
    pj_status_t status;

    PJ_UNUSED_ARG(src_addr_len);

    listener = (struct tls_listener*) pj_ssl_sock_get_user_data(ssock);

    PJ_ASSERT_RETURN(new_ssock, PJ_TRUE);

    PJ_LOG(4,(listener->factory.obj_name, 
	      "TLS listener %.*s:%d: got incoming TLS connection "
	      "from %s, sock=%d",
	      (int)listener->factory.addr_name.host.slen,
	      listener->factory.addr_name.host.ptr,
	      listener->factory.addr_name.port,
	      pj_sockaddr_print(src_addr, addr, sizeof(addr), 3),
	      new_ssock));

    /* Retrieve SSL socket info, close the socket if this is failed
     * as the SSL socket info availability is rather critical here.
     */
    status = pj_ssl_sock_get_info(new_ssock, &ssl_info);
    if (status != PJ_SUCCESS) {
	pj_ssl_sock_close(new_ssock);
	return PJ_TRUE;
    }

    /* 
     * Incoming connection!
     * Create TLS transport for the new socket.
     */
    status = tls_create( listener, NULL, new_ssock, PJ_TRUE,
			 (const pj_sockaddr_in*)&listener->factory.local_addr,
			 (const pj_sockaddr_in*)src_addr, NULL, &tls);
    
    if (status != PJ_SUCCESS)
	return PJ_TRUE;

    /* Set the "pending" SSL socket user data */
    pj_ssl_sock_set_user_data(new_ssock, tls);

    /* Prevent immediate transport destroy as application may access it 
     * (getting info, etc) in transport state notification callback.
     */
    pjsip_transport_add_ref(&tls->base);

    /* If there is verification error and verification is mandatory, shutdown
     * and destroy the transport.
     */
    if (ssl_info.verify_status && listener->tls_setting.verify_client) {
	if (tls->close_reason == PJ_SUCCESS) 
	    tls->close_reason = PJSIP_TLS_ECERTVERIF;
	pjsip_transport_shutdown(&tls->base);
    }

    /* Notify transport state to application */
    state_cb = pjsip_tpmgr_get_state_cb(tls->base.tpmgr);
    if (state_cb) {
	pjsip_transport_state_info state_info;
	pjsip_tls_state_info tls_info;
	pjsip_transport_state tp_state;

	/* Init transport state info */
	pj_bzero(&tls_info, sizeof(tls_info));
	pj_bzero(&state_info, sizeof(state_info));
	tls_info.ssl_sock_info = &ssl_info;
	state_info.ext_info = &tls_info;

	/* Set transport state based on verification status */
	if (ssl_info.verify_status && listener->tls_setting.verify_client)
	{
	    tp_state = PJSIP_TP_STATE_DISCONNECTED;
	    state_info.status = PJSIP_TLS_ECERTVERIF;
	} else {
	    tp_state = PJSIP_TP_STATE_CONNECTED;
	    state_info.status = PJ_SUCCESS;
	}

	(*state_cb)(&tls->base, tp_state, &state_info);
    }

    /* Release transport reference. If transport is shutting down, it may
     * get destroyed here.
     */
    is_shutdown = tls->base.is_shutdown;
    pjsip_transport_dec_ref(&tls->base);
    if (is_shutdown)
	return PJ_TRUE;


    status = tls_start_read(tls);
    if (status != PJ_SUCCESS) {
	PJ_LOG(3,(tls->base.obj_name, "New transport cancelled"));
	tls_init_shutdown(tls, status);
	tls_destroy(&tls->base, status);
    } else {
	/* Start keep-alive timer */
	if (PJSIP_TLS_KEEP_ALIVE_INTERVAL) {
	    pj_time_val delay = {PJSIP_TLS_KEEP_ALIVE_INTERVAL, 0};
	    pjsip_endpt_schedule_timer(listener->endpt, 
				       &tls->ka_timer, 
				       &delay);
	    tls->ka_timer.id = PJ_TRUE;
	    pj_gettimeofday(&tls->last_activity);
	}
    }

    return PJ_TRUE;
}
Esempio n. 14
0
void
SipTransport::deleteTransport(pjsip_transport* t)
{
    pjsip_transport_shutdown(t);
    pjsip_transport_dec_ref(t);
}