示例#1
0
static SilcThreadPoolThread silc_thread_pool_new_thread(SilcThreadPool tp)
{
  SilcThreadPoolThread t;

  t = silc_scalloc(tp->stack, 1, sizeof(*t));
  if (!t)
    return NULL;

  if (!silc_mutex_alloc(&t->lock)) {
    silc_sfree(tp->stack, t);
    return NULL;
  }

  if (!silc_cond_alloc(&t->thread_signal)) {
    silc_mutex_free(t->lock);
    silc_sfree(tp->stack, t);
    return NULL;
  }

  t->tp = tp;
  silc_list_init(t->queue, struct SilcThreadPoolThreadStruct, next);
  silc_list_init(t->free_queue, struct SilcThreadPoolThreadStruct, next);

  /* Add to thread pool */
  silc_list_add(tp->threads, t);
  silc_list_add(tp->free_threads, t);
  silc_thread_pool_ref(tp);

  SILC_LOG_DEBUG(("Start thread %p", t));

  /* Start the thread */
  silc_thread_create(silc_thread_pool_run_thread, t, FALSE);

  return t;
}
示例#2
0
SilcThreadPool silc_thread_pool_alloc(SilcStack stack,
				      SilcUInt32 min_threads,
				      SilcUInt32 max_threads,
				      SilcBool start_min_threads)
{
  SilcThreadPool tp;
  int i;

  if (max_threads < min_threads) {
    silc_set_errno_reason(SILC_ERR_INVALID_ARGUMENT,
			  "Max threads is smaller than min threads (%d < %d)",
			  max_threads, min_threads);
    return NULL;
  }
  if (!max_threads) {
    silc_set_errno_reason(SILC_ERR_INVALID_ARGUMENT, "Max threads is 0");
    return NULL;
  }

  if (stack)
    stack = silc_stack_alloc(0, stack);

  tp = silc_scalloc(stack, 1, sizeof(*tp));
  if (!tp) {
    silc_stack_free(stack);
    return NULL;
  }

  SILC_LOG_DEBUG(("Starting thread pool %p, min threads %d, max threads %d",
		  tp, min_threads, max_threads));

  tp->stack = stack;
  tp->min_threads = min_threads;
  tp->max_threads = max_threads;
  tp->refcnt++;

  if (!silc_mutex_alloc(&tp->lock)) {
    silc_sfree(stack, tp);
    silc_stack_free(stack);
    return NULL;
  }

  if (!silc_cond_alloc(&tp->pool_signal)) {
    silc_mutex_free(tp->lock);
    silc_sfree(stack, tp);
    silc_stack_free(stack);
    return NULL;
  }

  silc_list_init(tp->threads, struct SilcThreadPoolThreadStruct, next);
  silc_list_init(tp->free_threads, struct SilcThreadPoolThreadStruct, next2);

  for (i = 0; i < tp->min_threads && start_min_threads; i++)
    silc_thread_pool_new_thread(tp);

  silc_list_start(tp->threads);

  return tp;
}
SilcTls silc_thread_tls_init(void)
{
  SilcTls tls;

  if (silc_thread_get_tls())
    return silc_thread_get_tls();

  /* Allocate Tls for the thread */
  tls = (SilcTls)silc_calloc(1, sizeof(*tls));
  if (!tls)
    return NULL;

  Dll::SetTls(tls);

  /* Allocate global lock */
  silc_mutex_alloc(&tls->lock);

  return tls;
}
SilcBool silc_rwlock_alloc(SilcRwLock *rwlock)
{
#ifdef SILC_THREADS
  *rwlock = (SilcRwLock)silc_calloc(1, sizeof(**rwlock));
  if (!(*rwlock))
    return FALSE;
  if (!silc_mutex_alloc(&(*rwlock)->mutex)) {
    silc_free(*rwlock);
    return FALSE;
  }
  if (!silc_cond_alloc(&(*rwlock)->cond)) {
    silc_mutex_free((*rwlock)->mutex);
    silc_free(*rwlock);
    return FALSE;
  }
  return TRUE;
#else
  return FALSE;
#endif /* SILC_THREADS */
}
示例#5
0
SilcBool silc_client_init(SilcClient client, const char *username,
			  const char *hostname, const char *realname,
			  SilcClientRunning running, void *context)
{
  SILC_LOG_DEBUG(("Initializing client"));

  if (!client)
    return FALSE;

  if (!username || !hostname) {
    SILC_LOG_ERROR(("Username and hostname must be given to "
		    "silc_client_init"));
    return FALSE;
  }
  if (!realname)
    realname = username;

  /* Validate essential strings */
  if (!silc_identifier_verify(username, strlen(username),
			      SILC_STRING_UTF8, 128)) {
    SILC_LOG_ERROR(("Malformed username '%s'. Username must be UTF-8 string",
		    client->username));
    return FALSE;
  }
  if (!silc_identifier_verify(hostname, strlen(hostname),
			      SILC_STRING_UTF8, 256)) {
    SILC_LOG_ERROR(("Malformed hostname '%s'. Hostname must be UTF-8 string",
		    client->hostname));
    return FALSE;
  }
  if (!silc_utf8_valid(realname, strlen(realname))) {
    SILC_LOG_ERROR(("Malformed realname '%s'. Realname must be UTF-8 string",
		    client->realname));
    return FALSE;
  }

  /* Take the name strings */
  client->username = strdup(username);
  client->hostname = strdup(hostname);
  client->realname = strdup(realname);
  if (!username || !hostname || !realname)
    return FALSE;

  client->internal->ftp_sessions = silc_dlist_init();
  if (!client->internal->ftp_sessions)
    return FALSE;

  if (!client->internal->params->dont_register_crypto_library) {
    /* Initialize the crypto library.  If application has done this already
       this has no effect.  Also, we will not be overriding something
       application might have registered earlier. */
    silc_cipher_register_default();
    silc_pkcs_register_default();
    silc_hash_register_default();
    silc_hmac_register_default();
  }

  /* Initialize random number generator */
  client->rng = silc_rng_alloc();
  if (!client->rng)
    return FALSE;
  silc_rng_init(client->rng);
  silc_rng_global_init(client->rng);

  /* Initialize the scheduler */
  client->schedule = silc_schedule_init(0, client);
  if (!client->schedule)
    return FALSE;

  /* Allocate client lock */
  silc_mutex_alloc(&client->internal->lock);

  /* Register commands */
  silc_client_commands_register(client);

  /* Start packet engine */
  client->internal->packet_engine =
    silc_packet_engine_start(client->rng, FALSE, &silc_client_stream_cbs,
			     client);
  if (!client->internal->packet_engine)
    return FALSE;

  /* Initialize and start the client FSM */
  client->internal->running = running;
  client->internal->running_context = context;
  silc_fsm_init(&client->internal->fsm, client, NULL, NULL, client->schedule);
  silc_fsm_event_init(&client->internal->wait_event, &client->internal->fsm);
  silc_fsm_start_sync(&client->internal->fsm, silc_client_st_run);

  /* Signal the application when we are running */
  client->internal->run_callback = TRUE;
  SILC_FSM_EVENT_SIGNAL(&client->internal->wait_event);

  return TRUE;
}
示例#6
0
SilcClientConnection
silc_client_add_connection(SilcClient client,
			   SilcConnectionType conn_type,
			   SilcBool connect,
			   SilcClientConnectionParams *params,
			   SilcPublicKey public_key,
			   SilcPrivateKey private_key,
			   char *remote_host, int port,
			   SilcClientConnectCallback callback,
			   void *context)
{
  SilcClientConnection conn;
  SilcFSMThread thread;

  if (!callback)
    return NULL;

  SILC_LOG_DEBUG(("Adding new connection to %s:%d", remote_host, port));

  conn = silc_calloc(1, sizeof(*conn));
  if (!conn)
    return NULL;

  conn->client = client;
  conn->public_key = public_key;
  conn->private_key = private_key;
  conn->remote_host = strdup(remote_host);
  conn->remote_port = port ? port : 706;
  conn->type = conn_type;
  conn->callback = callback;
  conn->callback_context = context;

  conn->internal = silc_calloc(1, sizeof(*conn->internal));
  if (!conn->internal) {
    silc_free(conn);
    return NULL;
  }
  conn->internal->retry_timer = SILC_CLIENT_RETRY_MIN;
  silc_mutex_alloc(&conn->internal->lock);
  silc_atomic_init16(&conn->internal->cmd_ident, 0);

  if (!silc_hash_alloc("sha1", &conn->internal->sha1hash)) {
    silc_free(conn);
    silc_free(conn->internal);
    return NULL;
  }

  /* Set parameters */
  if (params) {
    conn->internal->params = *params;
    conn->context = params->context;
  }
  if (!conn->internal->params.rekey_secs)
    conn->internal->params.rekey_secs = 3600;
  if (conn->internal->params.rekey_secs < 300)
    conn->internal->params.rekey_secs = 300;

  conn->internal->verbose = TRUE;
  silc_list_init(conn->internal->pending_commands,
		 struct SilcClientCommandContextStruct, next);
  silc_list_init(conn->internal->thread_pool, SilcFSMThreadStruct, next);

  /* Allocate client, channel and serve caches */
  if (conn_type != SILC_CONN_CLIENT) {
    conn->internal->client_cache = silc_idcache_alloc(0, SILC_ID_CLIENT,
						      NULL, NULL);
    conn->internal->channel_cache = silc_idcache_alloc(0, SILC_ID_CHANNEL,
						       NULL, NULL);
    conn->internal->server_cache = silc_idcache_alloc(0, SILC_ID_SERVER,
						      NULL, NULL);
    if (!conn->internal->client_cache || !conn->internal->channel_cache ||
	!conn->internal->server_cache) {
      silc_client_del_connection(client, conn);
      return NULL;
    }
  }

  if (connect) {
    /* Initialize our async operation so that application may abort us
       while we're connecting. */
    conn->internal->cop = silc_async_alloc(silc_client_connect_abort,
					   NULL, conn);
    if (!conn->internal->cop) {
      silc_client_del_connection(client, conn);
      return NULL;
    }
  }

  /* Run the connection state machine.  If threads are in use the connection
     machine is always run in a real thread. */
  thread = silc_fsm_thread_alloc(&client->internal->fsm, conn,
				 silc_client_connection_finished, NULL,
				 client->internal->params->threads);
  if (!thread) {
    silc_client_del_connection(client, conn);
    return NULL;
  }
  silc_fsm_set_state_context(thread, client);
  silc_fsm_start(thread, silc_client_connection_st_start);

  SILC_LOG_DEBUG(("New connection %p", conn));
  silc_atomic_add_int32(&client->internal->conns, 1);

  return conn;
}