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; }
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; }
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; }