/* Destructor */
 ~SilcSymbianTCPConnect()
 {
   silc_free(remote);
   if (op)
     silc_async_free(op);
   Cancel();
 }
Beispiel #2
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;
}
Beispiel #3
0
void silc_client_del_connection(SilcClient client, SilcClientConnection conn)
{
  SilcList list;
  SilcIDCacheEntry entry;
  SilcFSMThread thread;

  SILC_LOG_DEBUG(("Freeing connection %p", conn));

  silc_schedule_task_del_by_context(conn->internal->schedule, conn);

  /* Free all cache entries */
  if (conn->internal->server_cache) {
    if (silc_idcache_get_all(conn->internal->server_cache, &list)) {
      silc_list_start(list);
      while ((entry = silc_list_get(list)))
	silc_client_del_server(client, conn, entry->context);
    }
  }
  if (conn->internal->channel_cache) {
    if (silc_idcache_get_all(conn->internal->channel_cache, &list)) {
      silc_list_start(list);
      while ((entry = silc_list_get(list))) {
	silc_client_empty_channel(client, conn, entry->context);
	silc_client_del_channel(client, conn, entry->context);
      }
    }
  }
  if (conn->internal->client_cache) {
    if (silc_idcache_get_all(conn->internal->client_cache, &list)) {
      silc_list_start(list);
      while ((entry = silc_list_get(list)))
	silc_client_del_client(client, conn, entry->context);
    }
  }

  /* Free ID caches */
  if (conn->internal->client_cache)
    silc_idcache_free(conn->internal->client_cache);
  if (conn->internal->channel_cache)
    silc_idcache_free(conn->internal->channel_cache);
  if (conn->internal->server_cache)
    silc_idcache_free(conn->internal->server_cache);

  /* Free thread pool */
  silc_list_start(conn->internal->thread_pool);
  while ((thread = silc_list_get(conn->internal->thread_pool)))
    silc_fsm_free(thread);

  silc_free(conn->remote_host);
  silc_buffer_free(conn->internal->local_idp);
  silc_buffer_free(conn->internal->remote_idp);
  silc_mutex_free(conn->internal->lock);
  if (conn->internal->hash)
    silc_hash_free(conn->internal->hash);
  if (conn->internal->sha1hash)
    silc_hash_free(conn->internal->sha1hash);
  silc_atomic_uninit16(&conn->internal->cmd_ident);
  silc_free(conn->internal->away_message);
  if (conn->internal->rekey)
    silc_ske_free_rekey_material(conn->internal->rekey);
  if (conn->internal->cop)
    silc_async_free(conn->internal->cop);

  silc_free(conn->internal);
  memset(conn, 'F', sizeof(*conn));
  silc_free(conn);
}
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;
}