SILC_TASK_CALLBACK(silc_client_connect_to_server_start);
SILC_TASK_CALLBACK(silc_client_connect_to_server_second);
SILC_TASK_CALLBACK(silc_client_connect_to_server_final);
-SILC_TASK_CALLBACK(silc_client_rekey_callback);
SILC_TASK_CALLBACK(silc_client_rekey_final);
static bool silc_client_packet_parse(SilcPacketParserContext *parser_context,
if (client->rng)
silc_rng_free(client->rng);
+ silc_cipher_unregister_all();
+ silc_pkcs_unregister_all();
+ silc_hash_unregister_all();
+ silc_hmac_unregister_all();
+
+ silc_hash_free(client->md5hash);
+ silc_hash_free(client->sha1hash);
+ silc_hmac_free(client->internal->md5hmac);
+ silc_hmac_free(client->internal->sha1hmac);
+ silc_cipher_free(client->internal->none_cipher);
silc_free(client->internal->params);
silc_free(client->internal->silc_client_version);
silc_free(client->internal);
the client ready to be run. One must call silc_client_run to run the
client. Returns FALSE if error occured, TRUE otherwise. */
-int silc_client_init(SilcClient client)
+bool silc_client_init(SilcClient client)
{
SILC_LOG_DEBUG(("Initializing client"));
+ assert(client);
assert(client->username);
assert(client->hostname);
assert(client->realname);
{
SILC_LOG_DEBUG(("Running client"));
+ assert(client);
assert(client->pkcs);
assert(client->public_key);
assert(client->private_key);
for (i = 0; i < client->internal->conns_count; i++)
if (client->internal->conns[i] == conn) {
+ /* Free all cache entries */
+ SilcIDCacheList list;
+ SilcIDCacheEntry entry;
+ SilcClientCommandPending *r;
+ bool ret;
+
+ if (silc_idcache_get_all(conn->internal->client_cache, &list)) {
+ ret = silc_idcache_list_first(list, &entry);
+ while (ret) {
+ silc_client_del_client(client, conn, entry->context);
+ ret = silc_idcache_list_next(list, &entry);
+ }
+ silc_idcache_list_free(list);
+ }
- silc_idcache_free(conn->internal->client_cache);
- silc_idcache_free(conn->internal->channel_cache);
- silc_idcache_free(conn->internal->server_cache);
- if (conn->internal->pending_commands)
- silc_dlist_uninit(conn->internal->pending_commands);
+ if (silc_idcache_get_all(conn->internal->channel_cache, &list)) {
+ ret = silc_idcache_list_first(list, &entry);
+ while (ret) {
+ silc_client_del_channel(client, conn, entry->context);
+ ret = silc_idcache_list_next(list, &entry);
+ }
+ silc_idcache_list_free(list);
+ }
+
+ if (silc_idcache_get_all(conn->internal->server_cache, &list)) {
+ ret = silc_idcache_list_first(list, &entry);
+ while (ret) {
+ silc_client_del_server(client, conn, entry->context);
+ ret = silc_idcache_list_next(list, &entry);
+ }
+ silc_idcache_list_free(list);
+ }
+
+ /* Clear 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 data (my ID is freed in above silc_client_del_client).
+ conn->nickname is freed when freeing the local_entry->nickname. */
silc_free(conn->remote_host);
- if (conn->internal->ftp_sessions)
- silc_dlist_uninit(conn->internal->ftp_sessions);
+ silc_free(conn->local_id_data);
+ if (conn->internal->send_key)
+ silc_cipher_free(conn->internal->send_key);
+ if (conn->internal->receive_key)
+ silc_cipher_free(conn->internal->receive_key);
+ if (conn->internal->hmac_send)
+ silc_hmac_free(conn->internal->hmac_send);
+ if (conn->internal->hmac_receive)
+ silc_hmac_free(conn->internal->hmac_receive);
+ silc_free(conn->internal->rekey);
+
+ if (conn->internal->active_session) {
+ conn->sock->user_data = NULL;
+ silc_client_ftp_session_free(conn->internal->active_session);
+ conn->internal->active_session = NULL;
+ }
+
+ silc_client_ftp_free_sessions(client, conn);
+
+ if (conn->internal->pending_commands) {
+ silc_dlist_start(conn->internal->pending_commands);
+ while ((r = silc_dlist_get(conn->internal->pending_commands))
+ != SILC_LIST_END)
+ silc_dlist_del(conn->internal->pending_commands, r);
+ silc_dlist_uninit(conn->internal->pending_commands);
+ }
+
silc_free(conn->internal);
+ memset(conn, 0, sizeof(*conn));
silc_free(conn);
client->internal->conns[i] = NULL;
case then this function is not used at all. When the connecting is
done the `connect' client operation is called. */
-int silc_client_connect_to_server(SilcClient client,
+bool silc_client_connect_to_server(SilcClient client,
SilcClientConnectionParams *params,
int port, char *host, void *context)
{
is used directly only in special cases. Normal cases should use
silc_server_packet_send. Returns < 0 on error. */
-int silc_client_packet_send_real(SilcClient client,
+bool silc_client_packet_send_real(SilcClient client,
SilcSocketConnection sock,
bool force_send)
{
if (hmac)
sequence = ((SilcClientConnection)sock->user_data)->internal->psn_send++;
+
+ /* Check for mandatory rekey */
+ if (sequence == SILC_CLIENT_REKEY_THRESHOLD)
+ silc_schedule_task_add(client->schedule, sock->sock,
+ silc_client_rekey_callback, sock, 0, 1,
+ SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
}
block_len = cipher ? silc_cipher_get_block_len(cipher) : 0;
packetdata.dst_id_len));
packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
packetdata.src_id_len + packetdata.dst_id_len;
- packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen, block_len);
+ if (type == SILC_PACKET_CONNECTION_AUTH)
+ SILC_PACKET_PADLEN_MAX(packetdata.truelen, block_len, packetdata.padlen);
+ else
+ SILC_PACKET_PADLEN(packetdata.truelen, block_len, packetdata.padlen);
/* Create the outgoing packet */
if (!silc_packet_assemble(&packetdata, client->rng, cipher, hmac, sock,
silc_client_packet_send_real(client, sock, force_send);
}
+/* Packet sending routine for application. This is the only routine that
+ is provided for application to send SILC packets. */
+
+bool silc_client_send_packet(SilcClient client,
+ SilcClientConnection conn,
+ SilcPacketType type,
+ const unsigned char *data,
+ SilcUInt32 data_len)
+{
+
+ assert(client);
+ if (!conn)
+ return FALSE;
+
+ silc_client_packet_send(client, conn->sock, type, NULL, 0, NULL, NULL,
+ (unsigned char *)data, data_len, TRUE);
+ return TRUE;
+}
+
void silc_client_packet_queue_purge(SilcClient client,
SilcSocketConnection sock)
{
}
/* Free everything */
- if (del && sock->user_data) {
- /* Free all cache entries */
- SilcIDCacheList list;
- SilcIDCacheEntry entry;
- SilcClientCommandPending *r;
- bool ret;
-
- if (silc_idcache_get_all(conn->internal->client_cache, &list)) {
- ret = silc_idcache_list_first(list, &entry);
- while (ret) {
- silc_client_del_client(client, conn, entry->context);
- ret = silc_idcache_list_next(list, &entry);
- }
- silc_idcache_list_free(list);
- }
-
- if (silc_idcache_get_all(conn->internal->channel_cache, &list)) {
- ret = silc_idcache_list_first(list, &entry);
- while (ret) {
- silc_client_del_channel(client, conn, entry->context);
- ret = silc_idcache_list_next(list, &entry);
- }
- silc_idcache_list_free(list);
- }
-
- if (silc_idcache_get_all(conn->internal->server_cache, &list)) {
- ret = silc_idcache_list_first(list, &entry);
- while (ret) {
- silc_client_del_server(client, conn, entry->context);
- ret = silc_idcache_list_next(list, &entry);
- }
- silc_idcache_list_free(list);
- }
-
- /* Clear 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 data (my ID is freed in above silc_client_del_client).
- conn->nickname is freed when freeing the local_entry->nickname. */
- if (conn->remote_host)
- silc_free(conn->remote_host);
- if (conn->local_id_data)
- silc_free(conn->local_id_data);
- if (conn->internal->send_key)
- silc_cipher_free(conn->internal->send_key);
- if (conn->internal->receive_key)
- silc_cipher_free(conn->internal->receive_key);
- if (conn->internal->hmac_send)
- silc_hmac_free(conn->internal->hmac_send);
- if (conn->internal->hmac_receive)
- silc_hmac_free(conn->internal->hmac_receive);
- if (conn->internal->rekey)
- silc_free(conn->internal->rekey);
-
- if (conn->internal->active_session) {
- sock->user_data = NULL;
- silc_client_ftp_session_free(conn->internal->active_session);
- conn->internal->active_session = NULL;
- }
-
- silc_client_ftp_free_sessions(client, conn);
-
- silc_dlist_start(conn->internal->pending_commands);
- while ((r = silc_dlist_get(conn->internal->pending_commands))
- != SILC_LIST_END)
- silc_dlist_del(conn->internal->pending_commands, r);
- if (conn->internal->pending_commands)
- silc_dlist_uninit(conn->internal->pending_commands);
-
- memset(conn, 0, sizeof(*conn));
+ if (del && sock->user_data)
silc_client_del_connection(client, conn);
- }
silc_socket_free(sock);
}
{
SilcClientConnection conn = (SilcClientConnection)context;
SilcClient client = conn->client;
-
- silc_client_command_send(client, conn, SILC_COMMAND_NICK,
- ++conn->cmd_ident, 1, 1,
- client->nickname, strlen(client->nickname));
+ if (client)
+ silc_client_command_send(client, conn, SILC_COMMAND_NICK,
+ ++conn->cmd_ident, 1, 1,
+ client->nickname, strlen(client->nickname));
}
/* Client session resuming callback. If the session was resumed
/* A timeout callback for the re-key. We will be the initiator of the
re-key protocol. */
-SILC_TASK_CALLBACK(silc_client_rekey_callback)
+SILC_TASK_CALLBACK_GLOBAL(silc_client_rekey_callback)
{
SilcSocketConnection sock = (SilcSocketConnection)context;
SilcClientConnection conn = (SilcClientConnection)sock->user_data;
SilcClientConnAuthRequest connauth;
SilcBuffer packet;
+ assert(client && conn);
connauth = silc_calloc(1, sizeof(*connauth));
connauth->callback = callback;
connauth->context = context;