Пример #1
0
SilcAsyncOperation silc_net_tcp_connect(const char *local_ip_addr,
					const char *remote_ip_addr,
					int remote_port,
					SilcSchedule schedule,
					SilcNetCallback callback,
					void *context)
{
  SilcNetConnect conn;

  if (!remote_ip_addr || remote_port < 1 || !schedule || !callback)
    return NULL;

  SILC_LOG_DEBUG(("Creating connection to host %s port %d",
		  remote_ip_addr, remote_port));

  conn = silc_calloc(1, sizeof(*conn));
  if (!conn) {
    callback(SILC_NET_NO_MEMORY, NULL, context);
    return NULL;
  }

  /* Start async operation */
  conn->op = silc_async_alloc(silc_net_connect_abort, NULL, conn);
  if (!conn->op) {
    silc_free(conn);
    callback(SILC_NET_NO_MEMORY, NULL, context);
    return NULL;
  }

  if (local_ip_addr)
    conn->local_ip = strdup(local_ip_addr);
  conn->remote = strdup(remote_ip_addr);
  if (!conn->remote) {
    silc_async_free(conn->op);
    silc_free(conn->local_ip);
    silc_free(conn);
    callback(SILC_NET_NO_MEMORY, NULL, context);
    return NULL;
  }
  conn->port = remote_port;
  conn->callback = callback;
  conn->context = context;
  conn->retry = 1;
  conn->status = SILC_NET_ERROR;

  silc_fsm_init(&conn->fsm, conn, silc_net_connect_destructor, NULL, schedule);
  silc_fsm_start(&conn->fsm, silc_net_connect_st_start);

  return conn->op;
}
Пример #2
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;
}
Пример #3
0
SilcAsyncOperation silc_net_tcp_connect(const char *local_ip_addr,
					const char *remote_ip_addr,
					int remote_port,
					SilcSchedule schedule,
					SilcNetCallback callback,
					void *context)
{
  SilcSymbianTCPConnect *conn;
  TInetAddr local, remote;
  SilcResult status;
  TInt ret;

  if (!schedule) {
    schedule = silc_schedule_get_global();
    if (!schedule) {
      silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
      return NULL;
    }
  }

  if (!remote_ip_addr || remote_port < 1 || !callback) {
    silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
    return NULL;
  }

  SILC_LOG_DEBUG(("Creating connection to host %s port %d",
		  remote_ip_addr, remote_port));

  conn = new SilcSymbianTCPConnect;
  if (!conn) {
    callback(SILC_ERR_OUT_OF_MEMORY, NULL, context);
    return NULL;
  }
  conn->schedule = schedule;
  conn->callback = callback;
  conn->context = context;
  conn->port = remote_port;
  conn->remote = strdup(remote_ip_addr);
  if (!conn->remote) {
    status = SILC_ERR_OUT_OF_MEMORY;
    goto err;
  }

  /* Allocate socket */
  conn->sock = new RSocket;
  if (!conn->sock) {
    status = SILC_ERR_OUT_OF_MEMORY;
    goto err;
  }

  /* Allocate socket server */
  conn->ss = new RSocketServ;
  if (!conn->ss) {
    status = SILC_ERR_OUT_OF_MEMORY;
    goto err;
  }

  /* Connect to socket server */
  ret = conn->ss->Connect();
  if (ret != KErrNone) {
    SILC_LOG_ERROR(("Error connecting to socket server, error %d", ret));
    status = SILC_ERR;
    goto err;
  }

#ifdef SILC_THREADS
  /* Make our socket shareable between threads */
  conn->ss->ShareAuto();
#endif /* SILC_THREADS */

  /* Start async operation */
  conn->op = silc_async_alloc(silc_net_connect_abort, NULL, (void *)conn);
  if (!conn->op) {
    status = SILC_ERR_OUT_OF_MEMORY;
    goto err;
  }

  /* Do host lookup */
  if (!silc_net_gethostbyname(remote_ip_addr, FALSE, conn->remote_ip,
			      sizeof(conn->remote_ip))) {
    SILC_LOG_ERROR(("Network (%s) unreachable: could not resolve the "
		    "host", conn->remote));
    status = SILC_ERR_UNREACHABLE;
    goto err;
  }

  /* Create the connection socket */
  ret = conn->sock->Open(*conn->ss, KAfInet, KSockStream, KProtocolInetTcp);
  if (ret != KErrNone) {
    SILC_LOG_ERROR(("Cannot create socket, error %d", ret));
    status = SILC_ERR;
    goto err;
  }

  /* Set appropriate options */
  conn->sock->SetOpt(KSoTcpNoDelay, KSolInetTcp, 1);
  conn->sock->SetOpt(KSoTcpKeepAlive, KSolInetTcp, 1);

  /* Bind to the local address if provided */
  if (local_ip_addr)
    if (silc_net_set_sockaddr(&local, local_ip_addr, 0))
      conn->sock->Bind(local);

  /* Connect to the host */
  if (!silc_net_set_sockaddr(&remote, conn->remote_ip, remote_port)) {
    SILC_LOG_ERROR(("Cannot connect (cannot set address)"));
    status = SILC_ERR;
    goto err;
  }
  conn->Connect(remote);

  SILC_LOG_DEBUG(("Connection operation in progress"));

  return conn->op;

 err:
  if (conn->ss) {
    conn->ss->Close();
    delete conn->ss;
  }
  if (conn->sock)
    delete conn->sock;
  if (conn->remote)
    silc_free(conn->remote);
  if (conn->op)
    silc_async_free(conn->op);
  callback(status, NULL, context);
  delete conn;
  return NULL;
}