X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=lib%2Fsilcclient%2Fclient.c;h=ddd1285283653f8c688ca5d3b01f22587ebe6c3b;hb=9a85416f729ef965606a688fffb6baa9d22927a5;hp=ba3c70e9b92d1c12b2d6d2f05d0d647fc7c9a7f7;hpb=bd2c9343055303a5517a33401f57a0414639a953;p=silc.git diff --git a/lib/silcclient/client.c b/lib/silcclient/client.c index ba3c70e9..ddd12852 100644 --- a/lib/silcclient/client.c +++ b/lib/silcclient/client.c @@ -360,34 +360,26 @@ int silc_client_connect_to_server(SilcClient client, int port, return sock; } -/* Start SILC Key Exchange (SKE) protocol to negotiate shared secret - key material between client and server. This function can be called - directly if application is performing its own connecting and does not - use the connecting provided by this library. This function is normally - used only if the application performed the connecting outside the library. - The library however may use this internally. */ +/* Socket hostname and IP lookup callback that is called before actually + starting the key exchange. The lookup is called from the function + silc_client_start_key_exchange. */ -bool silc_client_start_key_exchange(SilcClient client, - SilcClientConnection conn, - int fd) +static void silc_client_start_key_exchange_cb(SilcSocketConnection sock, + void *context) { + SilcClientConnection conn = (SilcClientConnection)context; + SilcClient client = conn->client; SilcProtocol protocol; SilcClientKEInternalContext *proto_ctx; - void *context; - /* Allocate new socket connection object */ - silc_socket_alloc(fd, SILC_SOCKET_TYPE_SERVER, (void *)conn, &conn->sock); - - /* Sometimes when doing quick reconnects the new socket may be same as - the old one and there might be pending stuff for the old socket. - If new one is same then those pending sutff might cause problems. - Make sure they do not do that. */ - silc_schedule_task_del_by_fd(client->schedule, fd); + SILC_LOG_DEBUG(("Start")); - conn->nickname = (client->nickname ? strdup(client->nickname) : - strdup(client->username)); + /* XXX We should most likely use the resolved host name instead of the + one user provided for us. */ + silc_free(conn->sock->hostname); conn->sock->hostname = strdup(conn->remote_host); - conn->sock->ip = strdup(conn->remote_host); + if (!conn->sock->ip) + conn->sock->ip = strdup(conn->remote_host); conn->sock->port = conn->remote_port; /* Allocate internal Key Exchange context. This is sent to the @@ -408,7 +400,9 @@ bool silc_client_start_key_exchange(SilcClient client, if (!protocol) { client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR, "Error: Could not start key exchange protocol"); - return FALSE; + silc_net_close_connection(conn->sock->sock); + client->internal->ops->connect(client, conn, FALSE); + return; } conn->sock->protocol = protocol; @@ -419,11 +413,38 @@ bool silc_client_start_key_exchange(SilcClient client, 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); + SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(conn->sock->sock); /* Execute the protocol */ silc_protocol_execute(protocol, client->schedule, 0, 0); - return TRUE; +} + +/* Start SILC Key Exchange (SKE) protocol to negotiate shared secret + key material between client and server. This function can be called + directly if application is performing its own connecting and does not + use the connecting provided by this library. This function is normally + used only if the application performed the connecting outside the library. + The library however may use this internally. */ + +void silc_client_start_key_exchange(SilcClient client, + SilcClientConnection conn, + int fd) +{ + /* Allocate new socket connection object */ + silc_socket_alloc(fd, SILC_SOCKET_TYPE_SERVER, (void *)conn, &conn->sock); + + /* Sometimes when doing quick reconnects the new socket may be same as + the old one and there might be pending stuff for the old socket. + If new one is same then those pending sutff might cause problems. + Make sure they do not do that. */ + silc_schedule_task_del_by_fd(client->schedule, fd); + + conn->nickname = (client->nickname ? strdup(client->nickname) : + strdup(client->username)); + + /* Resolve the remote hostname and IP address for our socket connection */ + silc_socket_host_lookup(conn->sock, FALSE, silc_client_start_key_exchange_cb, + conn, client->schedule); } /* Callback called when error has occurred during connecting to the server. @@ -436,6 +457,8 @@ SILC_TASK_CALLBACK(silc_client_connect_failure) SilcClient client = (SilcClient)ctx->client; client->internal->ops->connect(client, ctx->sock->user_data, FALSE); + if (ctx->packet) + silc_packet_context_free(ctx->packet); silc_free(ctx); } @@ -493,10 +516,7 @@ SILC_TASK_CALLBACK(silc_client_connect_to_server_start) silc_schedule_task_del(client->schedule, ctx->task); silc_free(ctx); - if (!silc_client_start_key_exchange(client, conn, fd)) { - silc_net_close_connection(fd); - client->internal->ops->connect(client, conn, FALSE); - } + silc_client_start_key_exchange(client, conn, fd); } /* Second part of the connecting to the server. This executed @@ -1040,7 +1060,8 @@ void silc_client_packet_parse_type(SilcClient client, if (proto_ctx->packet) silc_packet_context_free(proto_ctx->packet); - + if (proto_ctx->dest_id) + silc_free(proto_ctx->dest_id); proto_ctx->packet = silc_packet_context_dup(packet); proto_ctx->dest_id_type = packet->src_id_type; proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len, @@ -1349,13 +1370,14 @@ void silc_client_close_connection(SilcClient client, /* Clear ID caches */ if (conn->client_cache) - silc_idcache_del_all(conn->client_cache); + silc_idcache_free(conn->client_cache); if (conn->channel_cache) - silc_idcache_del_all(conn->channel_cache); + silc_idcache_free(conn->channel_cache); if (conn->server_cache) - silc_idcache_del_all(conn->server_cache); + silc_idcache_free(conn->server_cache); - /* Free data (my ID is freed in above silc_client_del_client) */ + /* 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) @@ -1494,7 +1516,10 @@ void silc_client_receive_new_id(SilcClient client, conn->local_entry->server = strdup(conn->remote_host); conn->local_entry->id = conn->local_id; conn->local_entry->valid = TRUE; - + conn->local_entry->channels = silc_hash_table_alloc(1, silc_hash_ptr, + NULL, NULL, + NULL, NULL, NULL, TRUE); + /* Put it to the ID cache */ silc_idcache_add(conn->client_cache, strdup(conn->nickname), conn->local_id, (void *)conn->local_entry, 0, NULL); @@ -1523,73 +1548,22 @@ void silc_client_receive_new_id(SilcClient client, } } -/* Processed received Channel ID for a channel. This is called when client - joins to channel and server replies with channel ID. The ID is cached. - Returns the created channel entry. This is also called when received - channel ID in for example USERS command reply that we do not have. */ - -SilcChannelEntry silc_client_new_channel_id(SilcClient client, - SilcSocketConnection sock, - char *channel_name, - uint32 mode, - SilcIDPayload idp) -{ - SilcClientConnection conn = (SilcClientConnection)sock->user_data; - SilcChannelEntry channel; - - SILC_LOG_DEBUG(("New channel ID")); - - channel = silc_calloc(1, sizeof(*channel)); - channel->channel_name = channel_name; - channel->id = silc_id_payload_get_id(idp); - channel->mode = mode; - silc_list_init(channel->clients, struct SilcChannelUserStruct, next); - - /* Put it to the ID cache */ - silc_idcache_add(conn->channel_cache, channel->channel_name, - (void *)channel->id, (void *)channel, 0, NULL); - - return channel; -} - -/* Removes a client entry from all channel it has joined. This really is - a performance killer (client_entry should have pointers to channel - entry list). */ +/* Removes a client entry from all channels it has joined. */ void silc_client_remove_from_channels(SilcClient client, SilcClientConnection conn, SilcClientEntry client_entry) { - SilcIDCacheEntry id_cache; - SilcIDCacheList list; - SilcChannelEntry channel; + SilcHashTableList htl; SilcChannelUser chu; - if (!silc_idcache_get_all(conn->channel_cache, &list)) - return; - - silc_idcache_list_first(list, &id_cache); - channel = (SilcChannelEntry)id_cache->context; - - while (channel) { - - /* Remove client from channel */ - silc_list_start(channel->clients); - while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) { - if (chu->client == client_entry) { - silc_list_del(channel->clients, chu); - silc_free(chu); - break; - } - } - - if (!silc_idcache_list_next(list, &id_cache)) - break; - - channel = (SilcChannelEntry)id_cache->context; + silc_hash_table_list(client_entry->channels, &htl); + while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { + silc_hash_table_del(chu->client->channels, chu->channel); + silc_hash_table_del(chu->channel->user_list, chu->client); + silc_free(chu); } - - silc_idcache_list_free(list); + silc_hash_table_list_reset(&htl); } /* Replaces `old' client entries from all channels to `new' client entry. @@ -1602,35 +1576,20 @@ void silc_client_replace_from_channels(SilcClient client, SilcClientEntry old, SilcClientEntry new) { - SilcIDCacheEntry id_cache; - SilcIDCacheList list; - SilcChannelEntry channel; + SilcHashTableList htl; SilcChannelUser chu; - if (!silc_idcache_get_all(conn->channel_cache, &list)) - return; - - silc_idcache_list_first(list, &id_cache); - channel = (SilcChannelEntry)id_cache->context; - - while (channel) { - + silc_hash_table_list(old->channels, &htl); + while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { /* Replace client entry */ - silc_list_start(channel->clients); - while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) { - if (chu->client == old) { - chu->client = new; - break; - } - } - - if (!silc_idcache_list_next(list, &id_cache)) - break; + silc_hash_table_del(chu->client->channels, chu->channel); + silc_hash_table_del(chu->channel->user_list, chu->client); - channel = (SilcChannelEntry)id_cache->context; + chu->client = new; + silc_hash_table_add(chu->channel->user_list, chu->client, chu); + silc_hash_table_add(chu->client->channels, chu->channel, chu); } - - silc_idcache_list_free(list); + silc_hash_table_list_reset(&htl); } /* Registers failure timeout to process the received failure packet