- SilcProtocol protocol;
- SilcClientKEInternalContext *proto_ctx;
- void *context;
-
- /* Allocate new socket connection object */
- silc_socket_alloc(fd, SILC_SOCKET_TYPE_SERVER, (void *)conn, &conn->sock);
-
- conn->nickname = strdup(client->username);
- conn->sock->hostname = conn->remote_host;
- conn->sock->ip = strdup(conn->remote_host);
- conn->sock->port = conn->remote_port;
-
- /* Allocate internal Key Exchange context. This is sent to the
- protocol as context. */
- proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
- proto_ctx->client = (void *)client;
- proto_ctx->sock = conn->sock;
- proto_ctx->rng = client->rng;
- proto_ctx->responder = FALSE;
- proto_ctx->send_packet = silc_client_protocol_ke_send_packet;
- proto_ctx->verify = silc_client_protocol_ke_verify_key;
-
- /* Perform key exchange protocol. silc_client_connect_to_server_final
- will be called after the protocol is finished. */
- silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
- &protocol, (void *)proto_ctx,
- silc_client_connect_to_server_second);
- if (!protocol) {
- client->ops->say(client, conn,
- "Error: Could not start authentication protocol");
- return FALSE;
- }
- conn->sock->protocol = protocol;
-
- /* Register the connection for network input and output. This sets
- that scheduler will listen for incoming packets for this connection
- and sets that outgoing packets may be sent to this connection as well.
- However, this doesn't set the scheduler for outgoing traffic, it will
- be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
- later when outgoing data is available. */
- context = (void *)client;
- SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(fd);
-
- /* Execute the protocol */
- protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
- return TRUE;
+ SilcClientConnection conn = fsm_context;
+ SilcFSM connfsm;
+
+ /* Take scheduler for connection */
+ conn->internal->schedule = silc_fsm_get_schedule(fsm);
+
+ /*** Run connection machine */
+ connfsm = &conn->internal->fsm;
+ silc_fsm_init(connfsm, conn, silc_client_connection_destructor,
+ fsm, conn->internal->schedule);
+ silc_fsm_event_init(&conn->internal->wait_event, connfsm);
+ silc_fsm_start_sync(connfsm, silc_client_connection_st_run);
+
+ /* Schedule any events possibly set in initialization */
+ if (conn->internal->disconnected)
+ SILC_FSM_EVENT_SIGNAL(&conn->internal->wait_event);
+ if (conn->internal->connect)
+ SILC_FSM_EVENT_SIGNAL(&conn->internal->wait_event);
+ if (conn->internal->key_exchange)
+ SILC_FSM_EVENT_SIGNAL(&conn->internal->wait_event);
+
+ /* Wait until this thread is terminated from the machine destructor */
+ return SILC_FSM_WAIT;