the client. The `application' is application specific user data pointer
and caller must free it. */
-SilcClient silc_client_alloc(SilcClientOperations *ops, void *application)
+SilcClient silc_client_alloc(SilcClientOperations *ops, void *application,
+ const char *silc_version)
{
SilcClient new_client;
new_client = silc_calloc(1, sizeof(*new_client));
new_client->application = application;
new_client->ops = ops;
+ new_client->silc_client_version = strdup(silc_version);
return new_client;
}
silc_client_protocols_register();
/* Initialize the scheduler */
- silc_schedule_init(&client->io_queue, &client->timeout_queue,
- &client->generic_queue, 5000);
+ client->schedule = silc_schedule_init(&client->io_queue,
+ &client->timeout_queue,
+ &client->generic_queue, 5000);
+ if (!client->schedule)
+ return FALSE;
return TRUE;
}
/* Stop the scheduler, although it might be already stopped. This
doesn't hurt anyone. This removes all the tasks and task queues,
as well. */
- silc_schedule_stop();
- silc_schedule_uninit();
+ silc_schedule_stop(client->schedule);
+ silc_schedule_uninit(client->schedule);
silc_client_protocols_unregister();
/* Start the scheduler, the heart of the SILC client. When this returns
the program will be terminated. */
- silc_schedule();
+ silc_schedule(client->schedule);
}
/* Allocates and adds new connection to the client. This adds the allocated
SILC_TASK_FD,
SILC_TASK_PRI_NORMAL);
silc_task_reset_iotype(ctx->task, SILC_TASK_WRITE);
- silc_schedule_set_listen_fd(sock, ctx->task->iomask);
+ silc_schedule_set_listen_fd(ctx->client->schedule, sock, ctx->task->iomask);
ctx->sock = sock;
conn = silc_client_add_connection(client, host, port, context);
- client->ops->say(client, conn,
+ client->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
"Connecting to port %d of server %s", port, host);
/* Allocate internal context for connection process. This is
&protocol, (void *)proto_ctx,
silc_client_connect_to_server_second);
if (!protocol) {
- client->ops->say(client, conn,
+ client->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
"Error: Could not start authentication protocol");
return FALSE;
}
SILC_LOG_DEBUG(("Start"));
/* Check the socket status as it might be in error */
- getsockopt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
+ silc_net_get_socket_opt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
if (opt != 0) {
if (ctx->tries < 2) {
/* Connection failed but lets try again */
- client->ops->say(client, conn, "Could not connect to server %s: %s",
+ client->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
+ "Could not connect to server %s: %s",
ctx->host, strerror(opt));
- client->ops->say(client, conn,
+ client->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
"Connecting to port %d of server %s resumed",
ctx->port, ctx->host);
/* Unregister old connection try */
- silc_schedule_unset_listen_fd(fd);
+ silc_schedule_unset_listen_fd(client->schedule, fd);
silc_net_close_connection(fd);
silc_task_unregister(client->io_queue, ctx->task);
ctx->tries++;
} else {
/* Connection failed and we won't try anymore */
- client->ops->say(client, conn, "Could not connect to server %s: %s",
+ client->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
+ "Could not connect to server %s: %s",
ctx->host, strerror(opt));
- silc_schedule_unset_listen_fd(fd);
+ silc_schedule_unset_listen_fd(client->schedule, fd);
silc_net_close_connection(fd);
silc_task_unregister(client->io_queue, ctx->task);
silc_free(ctx);
return;
}
- silc_schedule_unset_listen_fd(fd);
+ silc_schedule_unset_listen_fd(client->schedule, fd);
silc_task_unregister(client->io_queue, ctx->task);
silc_free(ctx);
This call sets the connection both for input and output (the input
is set always and this call keeps the input setting, actually).
Actual data sending is performed by silc_client_packet_process. */
- SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(sock->sock);
+ SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(client->schedule, sock->sock);
/* Mark to socket that data is pending in outgoing buffer. This flag
is needed if new data is added to the buffer before the earlier
back to only for input. When there is again some outgoing data
available for this connection it will be set for output as well.
This call clears the output setting and sets it only for input. */
- SILC_CLIENT_SET_CONNECTION_FOR_INPUT(fd);
+ SILC_CLIENT_SET_CONNECTION_FOR_INPUT(client->schedule, fd);
SILC_UNSET_OUTBUF_PENDING(sock);
silc_buffer_clear(sock->outbuf);
sock = conn->sock;
/* We won't listen for this connection anymore */
- silc_schedule_unset_listen_fd(sock->sock);
+ silc_schedule_unset_listen_fd(client->schedule, sock->sock);
/* Unregister all tasks */
silc_task_unregister_by_fd(client->io_queue, sock->sock);
msg = silc_calloc(message->len + 1, sizeof(char));
memcpy(msg, message->data, message->len);
- client->ops->say(client, sock->user_data, msg);
+ client->ops->say(client, sock->user_data, SILC_CLIENT_MESSAGE_AUDIT, msg);
silc_free(msg);
SILC_SET_DISCONNECTED(sock);
msg = silc_calloc(message->len + 1, sizeof(char));
memcpy(msg, message->data, message->len);
- client->ops->say(client, sock->user_data, msg);
+ client->ops->say(client, sock->user_data, SILC_CLIENT_MESSAGE_AUDIT, msg);
silc_free(msg);
}
{
SilcClientConnection conn = (SilcClientConnection)sock->user_data;
int connecting = FALSE;
+ SilcBuffer sidp;
if (!conn->local_entry)
connecting = TRUE;
silc_idcache_add(conn->client_cache, conn->nickname, conn->local_id,
(void *)conn->local_entry, FALSE);
+ /* Issue INFO command to fetch the real server name and server information
+ and other stuff. */
+ sidp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
+ silc_client_send_command(client, conn, SILC_COMMAND_INFO,
+ ++conn->cmd_ident, 1, 2, sidp->data, sidp->len);
+ silc_buffer_free(sidp);
+
/* Notify application of successful connection. We do it here now that
we've received the Client ID and are allowed to send traffic. */
if (connecting)