5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2001 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
22 #include "clientlibincludes.h"
24 /* Static task callback prototypes */
25 SILC_TASK_CALLBACK(silc_client_connect_to_server_start);
26 SILC_TASK_CALLBACK(silc_client_connect_to_server_second);
27 SILC_TASK_CALLBACK(silc_client_connect_to_server_final);
28 SILC_TASK_CALLBACK(silc_client_packet_process);
29 SILC_TASK_CALLBACK(silc_client_packet_parse_real);
31 static void silc_client_packet_parse(SilcPacketParserContext *parser_context);
32 static void silc_client_packet_parse_type(SilcClient client,
33 SilcSocketConnection sock,
34 SilcPacketContext *packet);
36 /* Allocates new client object. This has to be done before client may
37 work. After calling this one must call silc_client_init to initialize
38 the client. The `application' is application specific user data pointer
39 and caller must free it. */
41 SilcClient silc_client_alloc(SilcClientOperations *ops, void *application)
43 SilcClient new_client;
45 new_client = silc_calloc(1, sizeof(*new_client));
46 new_client->application = application;
47 new_client->ops = ops;
52 /* Frees client object and its internals. */
54 void silc_client_free(SilcClient client)
58 silc_rng_free(client->rng);
64 /* Initializes the client. This makes all the necessary steps to make
65 the client ready to be run. One must call silc_client_run to run the
66 client. Returns FALSE if error occured, TRUE otherwise. */
68 int silc_client_init(SilcClient client)
70 SILC_LOG_DEBUG(("Initializing client"));
72 /* Initialize hash functions for client to use */
73 silc_hash_alloc("md5", &client->md5hash);
74 silc_hash_alloc("sha1", &client->sha1hash);
76 /* Initialize none cipher */
77 silc_cipher_alloc("none", &client->none_cipher);
79 /* Initialize random number generator */
80 client->rng = silc_rng_alloc();
81 silc_rng_init(client->rng);
82 silc_rng_global_init(client->rng);
84 /* Register protocols */
85 silc_client_protocols_register();
87 /* Initialize the scheduler */
88 silc_schedule_init(&client->io_queue, &client->timeout_queue,
89 &client->generic_queue, 5000);
94 /* Stops the client. This is called to stop the client and thus to stop
97 void silc_client_stop(SilcClient client)
99 SILC_LOG_DEBUG(("Stopping client"));
101 /* Stop the scheduler, although it might be already stopped. This
102 doesn't hurt anyone. This removes all the tasks and task queues,
104 silc_schedule_stop();
105 silc_schedule_uninit();
107 silc_client_protocols_unregister();
109 SILC_LOG_DEBUG(("Client stopped"));
112 /* Runs the client. This starts the scheduler from the utility library.
113 When this functions returns the execution of the appliation is over. */
115 void silc_client_run(SilcClient client)
117 SILC_LOG_DEBUG(("Running client"));
119 /* Start the scheduler, the heart of the SILC client. When this returns
120 the program will be terminated. */
124 /* Allocates and adds new connection to the client. This adds the allocated
125 connection to the connection table and returns a pointer to it. A client
126 can have multiple connections to multiple servers. Every connection must
127 be added to the client using this function. User data `context' may
128 be sent as argument. This function is normally used only if the
129 application performed the connecting outside the library. The library
130 however may use this internally. */
132 SilcClientConnection silc_client_add_connection(SilcClient client,
137 SilcClientConnection conn;
140 conn = silc_calloc(1, sizeof(*conn));
142 /* Initialize ID caches */
143 conn->client_cache = silc_idcache_alloc(0);
144 conn->channel_cache = silc_idcache_alloc(0);
145 conn->server_cache = silc_idcache_alloc(0);
146 conn->client = client;
147 conn->remote_host = strdup(hostname);
148 conn->remote_port = port;
149 conn->context = context;
150 conn->pending_commands = silc_dlist_init();
152 /* Add the connection to connections table */
153 for (i = 0; i < client->conns_count; i++)
154 if (client->conns && !client->conns[i]) {
155 client->conns[i] = conn;
159 client->conns = silc_realloc(client->conns, sizeof(*client->conns)
160 * (client->conns_count + 1));
161 client->conns[client->conns_count] = conn;
162 client->conns_count++;
167 /* Removes connection from client. Frees all memory. */
169 void silc_client_del_connection(SilcClient client, SilcClientConnection conn)
173 for (i = 0; i < client->conns_count; i++)
174 if (client->conns[i] == conn) {
175 if (conn->pending_commands)
176 silc_dlist_uninit(conn->pending_commands);
178 client->conns[i] = NULL;
182 /* Internal context for connection process. This is needed as we
183 doing asynchronous connecting. */
186 SilcClientConnection conn;
192 } SilcClientInternalConnectContext;
195 silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx)
199 /* XXX In the future we should give up this non-blocking connect all
200 together and use threads instead. */
201 /* Create connection to server asynchronously */
202 sock = silc_net_create_connection_async(ctx->port, ctx->host);
206 /* Register task that will receive the async connect and will
208 ctx->task = silc_task_register(ctx->client->io_queue, sock,
209 silc_client_connect_to_server_start,
212 SILC_TASK_PRI_NORMAL);
213 silc_task_reset_iotype(ctx->task, SILC_TASK_WRITE);
214 silc_schedule_set_listen_fd(sock, ctx->task->iomask);
221 /* Connects to remote server. This is the main routine used to connect
222 to SILC server. Returns -1 on error and the created socket otherwise.
223 The `context' is user context that is saved into the SilcClientConnection
224 that is created after the connection is created. Note that application
225 may handle the connecting process outside the library. If this is the
226 case then this function is not used at all. When the connecting is
227 done the `connect' client operation is called. */
229 int silc_client_connect_to_server(SilcClient client, int port,
230 char *host, void *context)
232 SilcClientInternalConnectContext *ctx;
233 SilcClientConnection conn;
236 SILC_LOG_DEBUG(("Connecting to port %d of server %s",
239 conn = silc_client_add_connection(client, host, port, context);
241 client->ops->say(client, conn,
242 "Connecting to port %d of server %s", port, host);
244 /* Allocate internal context for connection process. This is
245 needed as we are doing async connecting. */
246 ctx = silc_calloc(1, sizeof(*ctx));
247 ctx->client = client;
249 ctx->host = strdup(host);
253 /* Do the actual connecting process */
254 sock = silc_client_connect_to_server_internal(ctx);
256 silc_client_del_connection(client, conn);
260 /* Start SILC Key Exchange (SKE) protocol to negotiate shared secret
261 key material between client and server. This function can be called
262 directly if application is performing its own connecting and does not
263 use the connecting provided by this library. This function is normally
264 used only if the application performed the connecting outside the library.
265 The library however may use this internally. */
267 int silc_client_start_key_exchange(SilcClient client,
268 SilcClientConnection conn,
271 SilcProtocol protocol;
272 SilcClientKEInternalContext *proto_ctx;
275 /* Allocate new socket connection object */
276 silc_socket_alloc(fd, SILC_SOCKET_TYPE_SERVER, (void *)conn, &conn->sock);
277 if (conn->sock == NULL) {
278 client->ops->say(client, conn,
279 "Error: Could not allocate connection socket");
283 conn->nickname = strdup(client->username);
284 conn->sock->hostname = conn->remote_host;
285 conn->sock->ip = strdup(conn->remote_host);
286 conn->sock->port = conn->remote_port;
288 /* Allocate internal Key Exchange context. This is sent to the
289 protocol as context. */
290 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
291 proto_ctx->client = (void *)client;
292 proto_ctx->sock = conn->sock;
293 proto_ctx->rng = client->rng;
294 proto_ctx->responder = FALSE;
296 /* Perform key exchange protocol. silc_client_connect_to_server_final
297 will be called after the protocol is finished. */
298 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
299 &protocol, (void *)proto_ctx,
300 silc_client_connect_to_server_second);
302 client->ops->say(client, conn,
303 "Error: Could not start authentication protocol");
306 conn->sock->protocol = protocol;
308 /* Register the connection for network input and output. This sets
309 that scheduler will listen for incoming packets for this connection
310 and sets that outgoing packets may be sent to this connection as well.
311 However, this doesn't set the scheduler for outgoing traffic, it will
312 be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
313 later when outgoing data is available. */
314 context = (void *)client;
315 SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(fd);
317 /* Execute the protocol */
318 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
322 /* Start of the connection to the remote server. This is called after
323 succesful TCP/IP connection has been established to the remote host. */
325 SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
327 SilcClientInternalConnectContext *ctx =
328 (SilcClientInternalConnectContext *)context;
329 SilcClient client = ctx->client;
330 SilcClientConnection conn = ctx->conn;
331 int opt, opt_len = sizeof(opt);
333 SILC_LOG_DEBUG(("Start"));
335 /* Check the socket status as it might be in error */
336 getsockopt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
338 if (ctx->tries < 2) {
339 /* Connection failed but lets try again */
340 client->ops->say(client, conn, "Could not connect to server %s: %s",
341 ctx->host, strerror(opt));
342 client->ops->say(client, conn,
343 "Connecting to port %d of server %s resumed",
344 ctx->port, ctx->host);
346 /* Unregister old connection try */
347 silc_schedule_unset_listen_fd(fd);
348 silc_net_close_connection(fd);
349 silc_task_unregister(client->io_queue, ctx->task);
352 silc_client_connect_to_server_internal(ctx);
355 /* Connection failed and we won't try anymore */
356 client->ops->say(client, conn, "Could not connect to server %s: %s",
357 ctx->host, strerror(opt));
358 silc_schedule_unset_listen_fd(fd);
359 silc_net_close_connection(fd);
360 silc_task_unregister(client->io_queue, ctx->task);
363 /* Notify application of failure */
364 client->ops->connect(client, conn, FALSE);
365 silc_client_del_connection(client, conn);
370 silc_schedule_unset_listen_fd(fd);
371 silc_task_unregister(client->io_queue, ctx->task);
374 if (!silc_client_start_key_exchange(client, conn, fd)) {
375 silc_net_close_connection(fd);
376 client->ops->connect(client, conn, FALSE);
380 /* Second part of the connecting to the server. This executed
381 authentication protocol. */
383 SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
385 SilcProtocol protocol = (SilcProtocol)context;
386 SilcClientKEInternalContext *ctx =
387 (SilcClientKEInternalContext *)protocol->context;
388 SilcClient client = (SilcClient)ctx->client;
389 SilcSocketConnection sock = NULL;
390 SilcClientConnAuthInternalContext *proto_ctx;
392 SILC_LOG_DEBUG(("Start"));
394 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
395 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
396 /* Error occured during protocol */
397 SILC_LOG_DEBUG(("Error during KE protocol"));
398 silc_protocol_free(protocol);
400 silc_ske_free(ctx->ske);
402 silc_free(ctx->dest_id);
403 ctx->sock->protocol = NULL;
405 /* Notify application of failure */
406 client->ops->connect(client, ctx->sock->user_data, FALSE);
411 /* Allocate internal context for the authentication protocol. This
412 is sent as context for the protocol. */
413 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
414 proto_ctx->client = (void *)client;
415 proto_ctx->sock = sock = ctx->sock;
416 proto_ctx->ske = ctx->ske; /* Save SKE object from previous protocol */
417 proto_ctx->dest_id_type = ctx->dest_id_type;
418 proto_ctx->dest_id = ctx->dest_id;
420 /* Resolve the authentication method to be used in this connection */
421 if (!client->ops->get_auth_method(client, sock->user_data, sock->hostname,
422 sock->port, &proto_ctx->auth_meth,
423 &proto_ctx->auth_data,
424 &proto_ctx->auth_data_len))
426 /* XXX do AUTH_REQUEST resolcing with server */
427 proto_ctx->auth_meth = SILC_AUTH_NONE;
430 /* Free old protocol as it is finished now */
431 silc_protocol_free(protocol);
433 silc_packet_context_free(ctx->packet);
435 /* silc_free(ctx->keymat....); */
436 sock->protocol = NULL;
438 /* Allocate the authentication protocol. This is allocated here
439 but we won't start it yet. We will be receiving party of this
440 protocol thus we will wait that connecting party will make
442 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
443 &sock->protocol, (void *)proto_ctx,
444 silc_client_connect_to_server_final);
446 /* Execute the protocol */
447 sock->protocol->execute(client->timeout_queue, 0, sock->protocol, fd, 0, 0);
450 /* Finalizes the connection to the remote SILC server. This is called
451 after authentication protocol has been completed. This send our
452 user information to the server to receive our client ID from
455 SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
457 SilcProtocol protocol = (SilcProtocol)context;
458 SilcClientConnAuthInternalContext *ctx =
459 (SilcClientConnAuthInternalContext *)protocol->context;
460 SilcClient client = (SilcClient)ctx->client;
461 SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
464 SILC_LOG_DEBUG(("Start"));
466 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
467 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
468 /* Error occured during protocol */
469 SILC_LOG_DEBUG(("Error during authentication protocol"));
470 silc_protocol_free(protocol);
472 silc_free(ctx->auth_data);
474 silc_ske_free(ctx->ske);
476 silc_free(ctx->dest_id);
477 conn->sock->protocol = NULL;
479 /* Notify application of failure */
480 client->ops->connect(client, ctx->sock->user_data, FALSE);
485 /* Send NEW_CLIENT packet to the server. We will become registered
486 to the SILC network after sending this packet and we will receive
487 client ID from the server. */
488 packet = silc_buffer_alloc(2 + 2 + strlen(client->username) +
489 strlen(client->realname));
490 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
491 silc_buffer_format(packet,
492 SILC_STR_UI_SHORT(strlen(client->username)),
493 SILC_STR_UI_XNSTRING(client->username,
494 strlen(client->username)),
495 SILC_STR_UI_SHORT(strlen(client->realname)),
496 SILC_STR_UI_XNSTRING(client->realname,
497 strlen(client->realname)),
500 /* Send the packet */
501 silc_client_packet_send(client, ctx->sock, SILC_PACKET_NEW_CLIENT,
503 packet->data, packet->len, TRUE);
504 silc_buffer_free(packet);
506 /* Save remote ID. */
507 conn->remote_id = ctx->dest_id;
508 conn->remote_id_data = silc_id_id2str(ctx->dest_id, SILC_ID_SERVER);
509 conn->remote_id_data_len = SILC_ID_SERVER_LEN;
511 silc_protocol_free(protocol);
513 silc_free(ctx->auth_data);
515 silc_ske_free(ctx->ske);
517 conn->sock->protocol = NULL;
520 /* Internal routine that sends packet or marks packet to be sent. This
521 is used directly only in special cases. Normal cases should use
522 silc_server_packet_send. Returns < 0 on error. */
524 static int silc_client_packet_send_real(SilcClient client,
525 SilcSocketConnection sock,
530 /* Send the packet */
531 ret = silc_packet_send(sock, force_send);
535 /* Mark that there is some outgoing data available for this connection.
536 This call sets the connection both for input and output (the input
537 is set always and this call keeps the input setting, actually).
538 Actual data sending is performed by silc_client_packet_process. */
539 SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(sock->sock);
541 /* Mark to socket that data is pending in outgoing buffer. This flag
542 is needed if new data is added to the buffer before the earlier
543 put data is sent to the network. */
544 SILC_SET_OUTBUF_PENDING(sock);
549 /* Packet processing callback. This is used to send and receive packets
550 from network. This is generic task. */
552 SILC_TASK_CALLBACK(silc_client_packet_process)
554 SilcClient client = (SilcClient)context;
555 SilcSocketConnection sock = NULL;
556 SilcClientConnection conn;
559 SILC_LOG_DEBUG(("Processing packet"));
561 SILC_CLIENT_GET_SOCK(client, fd, sock);
565 conn = (SilcClientConnection)sock->user_data;
568 if (type == SILC_TASK_WRITE) {
569 SILC_LOG_DEBUG(("Writing data to connection"));
571 if (sock->outbuf->data - sock->outbuf->head)
572 silc_buffer_push(sock->outbuf,
573 sock->outbuf->data - sock->outbuf->head);
575 ret = silc_client_packet_send_real(client, sock, TRUE);
577 /* If returned -2 could not write to connection now, will do
582 /* The packet has been sent and now it is time to set the connection
583 back to only for input. When there is again some outgoing data
584 available for this connection it will be set for output as well.
585 This call clears the output setting and sets it only for input. */
586 SILC_CLIENT_SET_CONNECTION_FOR_INPUT(fd);
587 SILC_UNSET_OUTBUF_PENDING(sock);
589 silc_buffer_clear(sock->outbuf);
593 /* Packet receiving */
594 if (type == SILC_TASK_READ) {
595 SILC_LOG_DEBUG(("Reading data from connection"));
597 /* Read data from network */
598 ret = silc_packet_receive(sock);
604 SILC_LOG_DEBUG(("Read EOF"));
606 /* If connection is disconnecting already we will finally
607 close the connection */
608 if (SILC_IS_DISCONNECTING(sock)) {
609 client->ops->disconnect(client, conn);
610 silc_client_close_connection(client, conn);
614 SILC_LOG_DEBUG(("EOF from connection %d", sock->sock));
615 client->ops->disconnect(client, conn);
616 silc_client_close_connection(client, conn);
620 /* Process the packet. This will call the parser that will then
621 decrypt and parse the packet. */
622 silc_packet_receive_process(sock, conn->receive_key, conn->hmac,
623 silc_client_packet_parse, client);
627 /* Parses whole packet, received earlier. */
629 SILC_TASK_CALLBACK(silc_client_packet_parse_real)
631 SilcPacketParserContext *parse_ctx = (SilcPacketParserContext *)context;
632 SilcClient client = (SilcClient)parse_ctx->context;
633 SilcPacketContext *packet = parse_ctx->packet;
634 SilcBuffer buffer = packet->buffer;
635 SilcSocketConnection sock = parse_ctx->sock;
636 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
639 SILC_LOG_DEBUG(("Start"));
641 /* Decrypt the received packet */
642 ret = silc_packet_decrypt(conn->receive_key, conn->hmac, buffer, packet);
647 /* Parse the packet. Packet type is returned. */
648 ret = silc_packet_parse(packet);
650 /* Parse the packet header in special way as this is "special"
652 ret = silc_packet_parse_special(packet);
655 if (ret == SILC_PACKET_NONE)
658 /* Parse the incoming packet type */
659 silc_client_packet_parse_type(client, sock, packet);
662 silc_buffer_clear(sock->inbuf);
663 silc_packet_context_free(packet);
664 silc_free(parse_ctx);
667 /* Parser callback called by silc_packet_receive_process. Thie merely
668 registers timeout that will handle the actual parsing when appropriate. */
670 void silc_client_packet_parse(SilcPacketParserContext *parser_context)
672 SilcClient client = (SilcClient)parser_context->context;
674 /* Parse the packet */
675 silc_task_register(client->timeout_queue, parser_context->sock->sock,
676 silc_client_packet_parse_real,
677 (void *)parser_context, 0, 1,
679 SILC_TASK_PRI_NORMAL);
682 /* Parses the packet type and calls what ever routines the packet type
683 requires. This is done for all incoming packets. */
685 void silc_client_packet_parse_type(SilcClient client,
686 SilcSocketConnection sock,
687 SilcPacketContext *packet)
689 SilcBuffer buffer = packet->buffer;
690 SilcPacketType type = packet->type;
692 SILC_LOG_DEBUG(("Parsing packet type %d", type));
694 /* Parse the packet type */
696 case SILC_PACKET_DISCONNECT:
697 silc_client_disconnected_by_server(client, sock, buffer);
699 case SILC_PACKET_SUCCESS:
701 * Success received for something. For now we can have only
702 * one protocol for connection executing at once hence this
703 * success message is for whatever protocol is executing currently.
705 if (sock->protocol) {
706 sock->protocol->execute(client->timeout_queue, 0,
707 sock->protocol, sock->sock, 0, 0);
710 case SILC_PACKET_FAILURE:
712 * Failure received for some protocol. Set the protocol state to
713 * error and call the protocol callback. This fill cause error on
714 * protocol and it will call the final callback.
716 if (sock->protocol) {
717 sock->protocol->state = SILC_PROTOCOL_STATE_FAILURE;
718 sock->protocol->execute(client->timeout_queue, 0,
719 sock->protocol, sock->sock, 0, 0);
721 /* XXX We have only two protocols currently thus we know what this
722 failure indication is. */
723 if (buffer->len >= 4) {
724 unsigned int failure;
726 SILC_GET32_MSB(failure, buffer->data);
728 /* Notify application */
729 client->ops->failure(client, sock->user_data, sock->protocol,
734 case SILC_PACKET_REJECT:
737 case SILC_PACKET_NOTIFY:
739 * Received notify message
741 silc_client_notify_by_server(client, sock, packet);
744 case SILC_PACKET_ERROR:
746 * Received error message
748 silc_client_error_by_server(client, sock, buffer);
751 case SILC_PACKET_CHANNEL_MESSAGE:
753 * Received message to (from, actually) a channel
755 silc_client_channel_message(client, sock, packet);
757 case SILC_PACKET_CHANNEL_KEY:
759 * Received key for a channel. By receiving this key the client will be
760 * able to talk to the channel it has just joined. This can also be
761 * a new key for existing channel as keys expire peridiocally.
763 silc_client_receive_channel_key(client, sock, buffer);
766 case SILC_PACKET_PRIVATE_MESSAGE:
768 * Received private message
770 silc_client_private_message(client, sock, packet);
772 case SILC_PACKET_PRIVATE_MESSAGE_KEY:
774 * Received private message key
778 case SILC_PACKET_COMMAND_REPLY:
780 * Recived reply for a command
782 silc_client_command_reply_process(client, sock, packet);
785 case SILC_PACKET_KEY_EXCHANGE:
786 if (sock->protocol) {
787 SilcClientKEInternalContext *proto_ctx =
788 (SilcClientKEInternalContext *)sock->protocol->context;
790 proto_ctx->packet = silc_packet_context_dup(packet);
791 proto_ctx->dest_id_type = packet->src_id_type;
792 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
793 packet->src_id_type);
794 if (!proto_ctx->dest_id)
797 /* Let the protocol handle the packet */
798 sock->protocol->execute(client->timeout_queue, 0,
799 sock->protocol, sock->sock, 0, 0);
801 SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
802 "protocol active, packet dropped."));
804 /* XXX Trigger KE protocol?? Rekey actually! */
808 case SILC_PACKET_KEY_EXCHANGE_1:
809 if (sock->protocol) {
812 SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
813 "protocol active, packet dropped."));
816 case SILC_PACKET_KEY_EXCHANGE_2:
817 if (sock->protocol) {
818 SilcClientKEInternalContext *proto_ctx =
819 (SilcClientKEInternalContext *)sock->protocol->context;
821 if (proto_ctx->packet)
822 silc_packet_context_free(proto_ctx->packet);
824 proto_ctx->packet = silc_packet_context_dup(packet);
825 proto_ctx->dest_id_type = packet->src_id_type;
826 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
827 packet->src_id_type);
828 if (!proto_ctx->dest_id)
831 /* Let the protocol handle the packet */
832 sock->protocol->execute(client->timeout_queue, 0,
833 sock->protocol, sock->sock, 0, 0);
835 SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
836 "protocol active, packet dropped."));
840 case SILC_PACKET_NEW_ID:
843 * Received new ID from server. This packet is received at
844 * the connection to the server. New ID is also received when
845 * user changes nickname but in that case the new ID is received
846 * as command reply and not as this packet type.
850 idp = silc_id_payload_parse(buffer);
853 if (silc_id_payload_get_type(idp) != SILC_ID_CLIENT)
856 silc_client_receive_new_id(client, sock, idp);
857 silc_id_payload_free(idp);
861 case SILC_PACKET_HEARTBEAT:
863 * Received heartbeat packet
865 SILC_LOG_DEBUG(("Heartbeat packet"));
869 SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
874 /* Sends packet. This doesn't actually send the packet instead it assembles
875 it and marks it to be sent. However, if force_send is TRUE the packet
876 is sent immediately. if dst_id, cipher and hmac are NULL those parameters
877 will be derived from sock argument. Otherwise the valid arguments sent
880 void silc_client_packet_send(SilcClient client,
881 SilcSocketConnection sock,
884 SilcIdType dst_id_type,
888 unsigned int data_len,
891 SilcPacketContext packetdata;
893 SILC_LOG_DEBUG(("Sending packet, type %d", type));
895 /* Get data used in the packet sending, keys and stuff */
896 if ((!cipher || !hmac || !dst_id) && sock->user_data) {
897 if (!cipher && ((SilcClientConnection)sock->user_data)->send_key)
898 cipher = ((SilcClientConnection)sock->user_data)->send_key;
900 if (!hmac && ((SilcClientConnection)sock->user_data)->hmac)
901 hmac = ((SilcClientConnection)sock->user_data)->hmac;
903 if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
904 dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
905 dst_id_type = SILC_ID_SERVER;
909 /* Set the packet context pointers */
910 packetdata.flags = 0;
911 packetdata.type = type;
912 if (((SilcClientConnection)sock->user_data)->local_id_data)
913 packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
915 packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
916 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
917 packetdata.src_id_type = SILC_ID_CLIENT;
919 packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
920 packetdata.dst_id_len = silc_id_get_len(dst_id_type);
921 packetdata.dst_id_type = dst_id_type;
923 packetdata.dst_id = NULL;
924 packetdata.dst_id_len = 0;
925 packetdata.dst_id_type = SILC_ID_NONE;
927 packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
928 packetdata.src_id_len + packetdata.dst_id_len;
929 packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
931 /* Prepare outgoing data buffer for packet sending */
932 silc_packet_send_prepare(sock,
933 SILC_PACKET_HEADER_LEN +
934 packetdata.src_id_len +
935 packetdata.dst_id_len,
939 SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len));
941 packetdata.buffer = sock->outbuf;
943 /* Put the data to the buffer */
944 if (data && data_len)
945 silc_buffer_put(sock->outbuf, data, data_len);
947 /* Create the outgoing packet */
948 silc_packet_assemble(&packetdata);
950 /* Encrypt the packet */
952 silc_packet_encrypt(cipher, hmac, sock->outbuf, sock->outbuf->len);
954 SILC_LOG_HEXDUMP(("Packet, len %d", sock->outbuf->len),
955 sock->outbuf->data, sock->outbuf->len);
957 /* Now actually send the packet */
958 silc_client_packet_send_real(client, sock, force_send);
961 /* Sends packet to the `channel'. Packet to channel is always encrypted
962 differently from "normal" packets. SILC header of the packet is
963 encrypted with the next receiver's key and the rest of the packet is
964 encrypted with the channel specific key. Padding and HMAC is computed
965 with the next receiver's key. The `data' is the channel message. If
966 the `force_send' is TRUE then the packet is sent immediately. */
968 void silc_client_send_channel_message(SilcClient client,
969 SilcClientConnection conn,
970 SilcChannelEntry channel,
972 unsigned int data_len,
976 SilcSocketConnection sock = conn->sock;
978 SilcPacketContext packetdata;
981 unsigned char *id_string;
982 unsigned int block_len;
984 SILC_LOG_DEBUG(("Sending packet to channel"));
986 if (!channel || !channel->key) {
987 client->ops->say(client, conn,
988 "Cannot talk to channel: key does not exist");
993 block_len = silc_cipher_get_block_len(channel->channel_key);
994 if (channel->iv[0] == '\0')
995 for (i = 0; i < block_len; i++) channel->iv[i] = silc_rng_get_byte(client->rng);
997 silc_hash_make(client->md5hash, channel->iv, block_len, channel->iv);
999 /* Encode the channel payload */
1000 payload = silc_channel_payload_encode(data_len, data, block_len,
1001 channel->iv, client->rng);
1003 client->ops->say(client, conn,
1004 "Error: Could not create packet to be sent to channel");
1008 /* Get data used in packet header encryption, keys and stuff. Rest
1009 of the packet (the payload) is, however, encrypted with the
1010 specified channel key. */
1011 cipher = conn->send_key;
1013 id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1015 /* Set the packet context pointers. The destination ID is always
1016 the Channel ID of the channel. Server and router will handle the
1017 distribution of the packet. */
1018 packetdata.flags = 0;
1019 packetdata.type = SILC_PACKET_CHANNEL_MESSAGE;
1020 packetdata.src_id = conn->local_id_data;
1021 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1022 packetdata.src_id_type = SILC_ID_CLIENT;
1023 packetdata.dst_id = id_string;
1024 packetdata.dst_id_len = SILC_ID_CHANNEL_LEN;
1025 packetdata.dst_id_type = SILC_ID_CHANNEL;
1026 packetdata.truelen = payload->len + SILC_PACKET_HEADER_LEN +
1027 packetdata.src_id_len + packetdata.dst_id_len;
1028 packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
1029 packetdata.src_id_len +
1030 packetdata.dst_id_len));
1032 /* Prepare outgoing data buffer for packet sending */
1033 silc_packet_send_prepare(sock,
1034 SILC_PACKET_HEADER_LEN +
1035 packetdata.src_id_len +
1036 packetdata.dst_id_len,
1040 packetdata.buffer = sock->outbuf;
1042 /* Encrypt payload of the packet. This is encrypted with the channel key. */
1043 channel->channel_key->cipher->encrypt(channel->channel_key->context,
1044 payload->data, payload->data,
1045 payload->len - block_len, /* -IV_LEN */
1048 /* Put the actual encrypted payload data into the buffer. */
1049 silc_buffer_put(sock->outbuf, payload->data, payload->len);
1051 /* Create the outgoing packet */
1052 silc_packet_assemble(&packetdata);
1054 /* Encrypt the header and padding of the packet. This is encrypted
1055 with normal session key shared with our server. */
1056 silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN +
1057 packetdata.src_id_len + packetdata.dst_id_len +
1060 SILC_LOG_HEXDUMP(("Packet to channel, len %d", sock->outbuf->len),
1061 sock->outbuf->data, sock->outbuf->len);
1063 /* Now actually send the packet */
1064 silc_client_packet_send_real(client, sock, force_send);
1065 silc_buffer_free(payload);
1066 silc_free(id_string);
1069 /* Sends private message to remote client. If private message key has
1070 not been set with this client then the message will be encrypted using
1071 normal session keys. Private messages are special packets in SILC
1072 network hence we need this own function for them. This is similiar
1073 to silc_client_packet_send_to_channel except that we send private
1074 message. The `data' is the private message. If the `force_send' is
1075 TRUE the packet is sent immediately. */
1077 void silc_client_send_private_message(SilcClient client,
1078 SilcClientConnection conn,
1079 SilcClientEntry client_entry,
1080 unsigned char *data,
1081 unsigned int data_len,
1084 SilcSocketConnection sock = conn->sock;
1086 SilcPacketContext packetdata;
1087 unsigned int nick_len;
1091 SILC_LOG_DEBUG(("Sending private message"));
1093 /* Create private message payload */
1094 nick_len = strlen(conn->nickname);
1095 buffer = silc_buffer_alloc(2 + nick_len + data_len);
1096 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
1097 silc_buffer_format(buffer,
1098 SILC_STR_UI_SHORT(nick_len),
1099 SILC_STR_UI_XNSTRING(conn->nickname,
1101 SILC_STR_UI_XNSTRING(data, data_len),
1104 /* If we don't have private message specific key then private messages
1105 are just as any normal packet thus call normal packet sending. If
1106 the key exist then the encryption process is a bit different and
1107 will be done in the rest of this function. */
1108 if (!client_entry->send_key) {
1109 silc_client_packet_send(client, sock, SILC_PACKET_PRIVATE_MESSAGE,
1110 client_entry->id, SILC_ID_CLIENT, NULL, NULL,
1111 buffer->data, buffer->len, force_send);
1115 /* We have private message specific key */
1117 /* Get data used in the encryption */
1118 cipher = client_entry->send_key;
1121 /* Set the packet context pointers. */
1122 packetdata.flags = 0;
1123 packetdata.type = SILC_PACKET_PRIVATE_MESSAGE;
1124 packetdata.src_id = conn->local_id_data;
1125 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1126 packetdata.src_id_type = SILC_ID_CLIENT;
1128 packetdata.dst_id = silc_id_id2str(client_entry->id, SILC_ID_CLIENT);
1130 packetdata.dst_id = conn->local_id_data;
1131 packetdata.dst_id_len = SILC_ID_CLIENT_LEN;
1132 packetdata.dst_id_type = SILC_ID_CLIENT;
1133 packetdata.truelen = buffer->len + SILC_PACKET_HEADER_LEN +
1134 packetdata.src_id_len + packetdata.dst_id_len;
1135 packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
1136 packetdata.src_id_len +
1137 packetdata.dst_id_len));
1139 /* Prepare outgoing data buffer for packet sending */
1140 silc_packet_send_prepare(sock,
1141 SILC_PACKET_HEADER_LEN +
1142 packetdata.src_id_len +
1143 packetdata.dst_id_len,
1147 packetdata.buffer = sock->outbuf;
1149 /* Encrypt payload of the packet. Encrypt with private message specific
1150 key if it exist, otherwise with session key. */
1151 cipher->cipher->encrypt(cipher->context, buffer->data, buffer->data,
1152 buffer->len, cipher->iv);
1154 /* Put the actual encrypted payload data into the buffer. */
1155 silc_buffer_put(sock->outbuf, buffer->data, buffer->len);
1157 /* Create the outgoing packet */
1158 silc_packet_assemble(&packetdata);
1160 /* Encrypt the header and padding of the packet. */
1161 silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN +
1162 packetdata.src_id_len + packetdata.dst_id_len +
1165 SILC_LOG_HEXDUMP(("Private message packet, len %d", sock->outbuf->len),
1166 sock->outbuf->data, sock->outbuf->len);
1168 /* Now actually send the packet */
1169 silc_client_packet_send_real(client, sock, force_send);
1170 silc_free(packetdata.dst_id);
1176 /* Closes connection to remote end. Free's all allocated data except
1177 for some information such as nickname etc. that are valid at all time. */
1179 void silc_client_close_connection(SilcClient client,
1180 SilcClientConnection conn)
1182 SilcSocketConnection sock = conn->sock;
1184 /* We won't listen for this connection anymore */
1185 silc_schedule_unset_listen_fd(sock->sock);
1187 /* Unregister all tasks */
1188 silc_task_unregister_by_fd(client->io_queue, sock->sock);
1189 silc_task_unregister_by_fd(client->timeout_queue, sock->sock);
1191 /* Close the actual connection */
1192 silc_net_close_connection(sock->sock);
1194 client->ops->say(client, sock->user_data,
1195 "Closed connection to host %s", sock->hostname);
1197 /* Free everything */
1198 if (sock->user_data) {
1199 /* XXX Free all client entries and channel entries. */
1201 /* Clear ID caches */
1202 silc_idcache_del_all(conn->client_cache);
1203 silc_idcache_del_all(conn->channel_cache);
1206 if (conn->remote_host)
1207 silc_free(conn->remote_host);
1209 silc_free(conn->local_id);
1210 if (conn->local_id_data)
1211 silc_free(conn->local_id_data);
1213 silc_cipher_free(conn->send_key);
1214 if (conn->receive_key)
1215 silc_cipher_free(conn->receive_key);
1217 silc_hmac_free(conn->hmac);
1218 if (conn->hmac_key) {
1219 memset(conn->hmac_key, 0, conn->hmac_key_len);
1220 silc_free(conn->hmac_key);
1222 if (conn->pending_commands)
1223 silc_dlist_uninit(conn->pending_commands);
1226 conn->remote_port = 0;
1227 conn->remote_type = 0;
1228 conn->send_key = NULL;
1229 conn->receive_key = NULL;
1231 conn->hmac_key = NULL;
1232 conn->hmac_key_len = 0;
1233 conn->local_id = NULL;
1234 conn->local_id_data = NULL;
1235 conn->remote_host = NULL;
1236 conn->current_channel = NULL;
1237 conn->pending_commands = NULL;
1239 silc_client_del_connection(client, conn);
1242 if (sock->protocol) {
1243 silc_protocol_free(sock->protocol);
1244 sock->protocol = NULL;
1246 silc_socket_free(sock);
1249 /* Called when we receive disconnection packet from server. This
1250 closes our end properly and displays the reason of the disconnection
1253 void silc_client_disconnected_by_server(SilcClient client,
1254 SilcSocketConnection sock,
1259 SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1261 msg = silc_calloc(message->len + 1, sizeof(char));
1262 memcpy(msg, message->data, message->len);
1263 client->ops->say(client, sock->user_data, msg);
1266 SILC_SET_DISCONNECTED(sock);
1267 silc_client_close_connection(client, sock->user_data);
1270 /* Received error message from server. Display it on the screen.
1271 We don't take any action what so ever of the error message. */
1273 void silc_client_error_by_server(SilcClient client,
1274 SilcSocketConnection sock,
1279 msg = silc_calloc(message->len + 1, sizeof(char));
1280 memcpy(msg, message->data, message->len);
1281 client->ops->say(client, sock->user_data, msg);
1285 /* Called when notify is received and some async operation (such as command)
1286 is required before processing the notify message. This calls again the
1287 silc_client_notify_by_server and reprocesses the original notify packet. */
1289 static void silc_client_notify_by_server_pending(void *context)
1291 SilcPacketContext *p = (SilcPacketContext *)context;
1292 silc_client_notify_by_server(p->context, p->sock, p);
1295 /* Destructor for the pending command callback */
1297 static void silc_client_notify_by_server_destructor(void *context)
1299 silc_packet_context_free((SilcPacketContext *)context);
1302 /* Resolve client information from server by Client ID. */
1304 static void silc_client_notify_by_server_resolve(SilcClient client,
1305 SilcClientConnection conn,
1306 SilcPacketContext *packet,
1307 SilcClientID *client_id)
1309 SilcPacketContext *p = silc_packet_context_dup(packet);
1310 SilcBuffer idp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
1312 p->context = (void *)client;
1313 p->sock = conn->sock;
1315 silc_client_send_command(client, conn, SILC_COMMAND_WHOIS, ++conn->cmd_ident,
1316 1, 3, idp->data, idp->len);
1317 silc_client_command_pending(conn, SILC_COMMAND_WHOIS, conn->cmd_ident,
1318 silc_client_notify_by_server_destructor,
1319 silc_client_notify_by_server_pending, p);
1320 silc_buffer_free(idp);
1323 /* Received notify message from server */
1325 void silc_client_notify_by_server(SilcClient client,
1326 SilcSocketConnection sock,
1327 SilcPacketContext *packet)
1329 SilcBuffer buffer = packet->buffer;
1330 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1331 SilcNotifyPayload payload;
1332 SilcNotifyType type;
1333 SilcArgumentPayload args;
1335 SilcClientID *client_id = NULL;
1336 SilcChannelID *channel_id = NULL;
1337 SilcClientEntry client_entry;
1338 SilcClientEntry client_entry2;
1339 SilcChannelEntry channel;
1340 SilcChannelUser chu;
1341 SilcIDCacheEntry id_cache = NULL;
1343 unsigned int tmp_len, mode;
1345 payload = silc_notify_payload_parse(buffer);
1349 type = silc_notify_get_type(payload);
1350 args = silc_notify_get_args(payload);
1355 case SILC_NOTIFY_TYPE_NONE:
1356 /* Notify application */
1357 client->ops->notify(client, conn, type,
1358 silc_argument_get_arg_type(args, 1, NULL));
1361 case SILC_NOTIFY_TYPE_INVITE:
1363 * Someone invited me to a channel. Find Client and Channel entries
1364 * for the application.
1368 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1372 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1376 /* Find Client entry and if not found query it */
1377 client_entry = silc_client_get_client_by_id(client, conn, client_id);
1378 if (!client_entry) {
1379 silc_client_notify_by_server_resolve(client, conn, packet, client_id);
1383 /* Get Channel ID */
1384 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1388 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1392 /* XXX Will ALWAYS fail because currently we don't have way to resolve
1393 channel information for channel that we're not joined to. */
1394 /* XXX ways to fix: use (extended) LIST command, or define the channel
1395 name to the notfy type when name resolving is not mandatory. */
1396 /* Find channel entry */
1397 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1398 SILC_ID_CHANNEL, &id_cache))
1401 channel = (SilcChannelEntry)id_cache->context;
1403 /* Notify application */
1404 client->ops->notify(client, conn, type, client_entry, channel);
1407 case SILC_NOTIFY_TYPE_JOIN:
1409 * Someone has joined to a channel. Get their ID and nickname and
1410 * cache them for later use.
1414 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1418 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1422 /* Find Client entry and if not found query it */
1423 client_entry = silc_client_get_client_by_id(client, conn, client_id);
1424 if (!client_entry) {
1425 silc_client_notify_by_server_resolve(client, conn, packet, client_id);
1429 /* If nickname or username hasn't been resolved, do so */
1430 if (!client_entry->nickname || !client_entry->username) {
1431 silc_client_notify_by_server_resolve(client, conn, packet, client_id);
1435 /* Get Channel ID */
1436 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1440 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1444 /* Get channel entry */
1445 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1446 SILC_ID_CHANNEL, &id_cache))
1449 channel = (SilcChannelEntry)id_cache->context;
1451 /* Add client to channel */
1452 chu = silc_calloc(1, sizeof(*chu));
1453 chu->client = client_entry;
1454 silc_list_add(channel->clients, chu);
1456 /* XXX add support for multiple same nicks on same channel. Check
1459 /* Notify application. The channel entry is sent last as this notify
1460 is for channel but application don't know it from the arguments
1462 client->ops->notify(client, conn, type, client_entry, channel);
1465 case SILC_NOTIFY_TYPE_LEAVE:
1467 * Someone has left a channel. We will remove it from the channel but
1468 * we'll keep it in the cache in case we'll need it later.
1472 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1476 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1480 /* Find Client entry */
1482 silc_client_get_client_by_id(client, conn, client_id);
1486 /* Get channel entry */
1487 channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1491 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1492 SILC_ID_CHANNEL, &id_cache))
1495 channel = (SilcChannelEntry)id_cache->context;
1497 /* Remove client from channel */
1498 silc_list_start(channel->clients);
1499 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1500 if (chu->client == client_entry) {
1501 silc_list_del(channel->clients, chu);
1507 /* Notify application. The channel entry is sent last as this notify
1508 is for channel but application don't know it from the arguments
1510 client->ops->notify(client, conn, type, client_entry, channel);
1513 case SILC_NOTIFY_TYPE_SIGNOFF:
1515 * Someone left SILC. We'll remove it from all channels and from cache.
1519 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1523 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1527 /* Find Client entry */
1529 silc_client_get_client_by_id(client, conn, client_id);
1533 /* Remove from all channels */
1534 silc_client_remove_from_channels(client, conn, client_entry);
1536 /* Remove from cache */
1537 silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT,
1540 /* Get signoff message */
1541 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1545 /* Notify application */
1546 client->ops->notify(client, conn, type, client_entry, tmp);
1549 if (client_entry->nickname)
1550 silc_free(client_entry->nickname);
1551 if (client_entry->server)
1552 silc_free(client_entry->server);
1553 if (client_entry->id)
1554 silc_free(client_entry->id);
1555 if (client_entry->send_key)
1556 silc_cipher_free(client_entry->send_key);
1557 if (client_entry->receive_key)
1558 silc_cipher_free(client_entry->receive_key);
1561 case SILC_NOTIFY_TYPE_TOPIC_SET:
1563 * Someone set the topic on a channel.
1567 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1571 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1575 /* Find Client entry */
1577 silc_client_get_client_by_id(client, conn, client_id);
1582 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1586 /* Get channel entry */
1587 channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1591 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1592 SILC_ID_CHANNEL, &id_cache))
1595 channel = (SilcChannelEntry)id_cache->context;
1597 /* Notify application. The channel entry is sent last as this notify
1598 is for channel but application don't know it from the arguments
1600 client->ops->notify(client, conn, type, client_entry, tmp, channel);
1603 case SILC_NOTIFY_TYPE_NICK_CHANGE:
1605 * Someone changed their nickname. If we don't have entry for the new
1606 * ID we will query it and return here after it's done. After we've
1607 * returned we fetch the old entry and free it and notify the
1611 /* Get new Client ID */
1612 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1616 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1621 if (!SILC_ID_CLIENT_COMPARE(client_id, conn->local_id))
1624 /* Find Client entry and if not found query it */
1626 silc_client_get_client_by_id(client, conn, client_id);
1627 if (!client_entry2) {
1628 silc_client_notify_by_server_resolve(client, conn, packet, client_id);
1631 silc_free(client_id);
1633 /* Get old Client ID */
1634 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1638 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1642 /* Find old Client entry */
1644 silc_client_get_client_by_id(client, conn, client_id);
1648 /* Remove the old from cache */
1649 silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT,
1652 /* Replace old ID entry with new one on all channels. */
1653 silc_client_replace_from_channels(client, conn, client_entry,
1656 /* Notify application */
1657 client->ops->notify(client, conn, type, client_entry, client_entry2);
1660 if (client_entry->nickname)
1661 silc_free(client_entry->nickname);
1662 if (client_entry->server)
1663 silc_free(client_entry->server);
1664 if (client_entry->id)
1665 silc_free(client_entry->id);
1666 if (client_entry->send_key)
1667 silc_cipher_free(client_entry->send_key);
1668 if (client_entry->receive_key)
1669 silc_cipher_free(client_entry->receive_key);
1672 case SILC_NOTIFY_TYPE_CMODE_CHANGE:
1674 * Someone changed a channel mode
1678 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1682 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1686 /* Find Client entry */
1688 silc_client_get_client_by_id(client, conn, client_id);
1693 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1697 SILC_GET32_MSB(mode, tmp);
1699 /* Get channel entry */
1700 channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1704 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1705 SILC_ID_CHANNEL, &id_cache))
1708 channel = (SilcChannelEntry)id_cache->context;
1710 /* Save the new mode */
1711 channel->mode = mode;
1713 /* Notify application. The channel entry is sent last as this notify
1714 is for channel but application don't know it from the arguments
1716 client->ops->notify(client, conn, type, client_entry, mode, channel);
1719 case SILC_NOTIFY_TYPE_CUMODE_CHANGE:
1721 * Someone changed user's mode on a channel
1725 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1729 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1733 /* Find Client entry */
1735 silc_client_get_client_by_id(client, conn, client_id);
1740 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1744 SILC_GET32_MSB(mode, tmp);
1746 /* Get target Client ID */
1747 tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
1751 silc_free(client_id);
1752 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1756 /* Find target Client entry */
1758 silc_client_get_client_by_id(client, conn, client_id);
1762 /* Get channel entry */
1763 channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1767 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1768 SILC_ID_CHANNEL, &id_cache))
1771 channel = (SilcChannelEntry)id_cache->context;
1774 silc_list_start(channel->clients);
1775 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1776 if (chu->client == client_entry) {
1782 /* Notify application. The channel entry is sent last as this notify
1783 is for channel but application don't know it from the arguments
1785 client->ops->notify(client, conn, type, client_entry, mode,
1786 client_entry2, channel);
1789 case SILC_NOTIFY_TYPE_MOTD:
1791 * Received Message of the day
1795 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1799 /* Notify application */
1800 client->ops->notify(client, conn, type, tmp);
1803 case SILC_NOTIFY_TYPE_CHANNEL_CHANGE:
1805 * Router has enforced a new ID to a channel. Let's change the old
1806 * ID to the one provided here.
1809 /* Get the old ID */
1810 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1813 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1817 /* Get the channel entry */
1818 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1819 SILC_ID_CHANNEL, &id_cache))
1822 channel = (SilcChannelEntry)id_cache->context;
1824 /* Free the old ID */
1825 silc_free(channel_id);
1826 silc_free(channel->id);
1828 /* Get the new ID */
1829 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1832 channel->id = silc_id_payload_parse_id(tmp, tmp_len);
1836 id_cache->id = (void *)channel->id;
1838 /* Notify application */
1839 client->ops->notify(client, conn, type, channel, channel);
1842 case SILC_NOTIFY_TYPE_KICKED:
1844 * A client (maybe me) was kicked from a channel
1848 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1852 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1856 /* Find Client entry */
1858 silc_client_get_client_by_id(client, conn, client_id);
1862 /* Get channel entry */
1863 channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1867 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1868 SILC_ID_CHANNEL, &id_cache))
1871 channel = (SilcChannelEntry)id_cache->context;
1874 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1876 /* Notify application. The channel entry is sent last as this notify
1877 is for channel but application don't know it from the arguments
1879 client->ops->notify(client, conn, type, client_entry, tmp, channel);
1881 /* If I was kicked from channel, remove the channel */
1882 if (client_entry == conn->local_entry) {
1883 if (conn->current_channel == channel)
1884 conn->current_channel = NULL;
1885 silc_idcache_del_by_id(conn->channel_cache,
1886 SILC_ID_CHANNEL, channel->id);
1887 silc_free(channel->channel_name);
1888 silc_free(channel->id);
1889 silc_free(channel->key);
1890 silc_cipher_free(channel->channel_key);
1900 silc_notify_payload_free(payload);
1902 silc_free(client_id);
1904 silc_free(channel_id);
1907 /* Processes the received new Client ID from server. Old Client ID is
1908 deleted from cache and new one is added. */
1910 void silc_client_receive_new_id(SilcClient client,
1911 SilcSocketConnection sock,
1914 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1915 int connecting = FALSE;
1917 if (!conn->local_entry)
1920 /* Delete old ID from ID cache */
1921 silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, conn->local_id);
1923 /* Save the new ID */
1925 silc_free(conn->local_id);
1926 if (conn->local_id_data)
1927 silc_free(conn->local_id_data);
1929 conn->local_id = silc_id_payload_get_id(idp);
1930 conn->local_id_data = silc_id_payload_get_data(idp);
1931 conn->local_id_data_len = silc_id_payload_get_len(idp);;
1933 if (!conn->local_entry)
1934 conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1936 conn->local_entry->nickname = conn->nickname;
1937 if (!conn->local_entry->username) {
1938 conn->local_entry->username =
1939 silc_calloc(strlen(client->username) + strlen(client->hostname) + 1,
1940 sizeof(conn->local_entry->username));
1941 sprintf(conn->local_entry->username, "%s@%s", client->username,
1944 conn->local_entry->server = strdup(conn->remote_host);
1945 conn->local_entry->id = conn->local_id;
1947 /* Put it to the ID cache */
1948 silc_idcache_add(conn->client_cache, conn->nickname, SILC_ID_CLIENT,
1949 conn->local_id, (void *)conn->local_entry, TRUE);
1951 /* Notify application of successful connection. We do it here now that
1952 we've received the Client ID and are allowed to send traffic. */
1954 client->ops->connect(client, conn, TRUE);
1957 /* Processed received Channel ID for a channel. This is called when client
1958 joins to channel and server replies with channel ID. The ID is cached. */
1960 void silc_client_new_channel_id(SilcClient client,
1961 SilcSocketConnection sock,
1963 unsigned int mode, SilcIDPayload idp)
1965 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1966 SilcChannelEntry channel;
1968 SILC_LOG_DEBUG(("New channel ID"));
1970 channel = silc_calloc(1, sizeof(*channel));
1971 channel->channel_name = channel_name;
1972 channel->id = silc_id_payload_get_id(idp);
1973 channel->mode = mode;
1974 silc_list_init(channel->clients, struct SilcChannelUserStruct, next);
1976 conn->current_channel = channel;
1978 /* Put it to the ID cache */
1979 silc_idcache_add(conn->channel_cache, channel_name, SILC_ID_CHANNEL,
1980 (void *)channel->id, (void *)channel, TRUE);
1983 /* Saves channel key from encoded `key_payload'. This is used when we
1984 receive Channel Key Payload and when we are processing JOIN command
1987 void silc_client_save_channel_key(SilcClientConnection conn,
1988 SilcBuffer key_payload,
1989 SilcChannelEntry channel)
1991 unsigned char *id_string, *key, *cipher;
1992 unsigned int tmp_len;
1994 SilcIDCacheEntry id_cache = NULL;
1995 SilcChannelKeyPayload payload;
1997 payload = silc_channel_key_payload_parse(key_payload);
2001 id_string = silc_channel_key_get_id(payload, &tmp_len);
2003 silc_channel_key_payload_free(payload);
2007 id = silc_id_str2id(id_string, tmp_len, SILC_ID_CHANNEL);
2009 silc_channel_key_payload_free(payload);
2015 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
2016 SILC_ID_CHANNEL, &id_cache))
2019 /* Get channel entry */
2020 channel = (SilcChannelEntry)id_cache->context;
2024 key = silc_channel_key_get_key(payload, &tmp_len);
2025 cipher = silc_channel_key_get_cipher(payload, NULL);
2026 channel->key_len = tmp_len * 8;
2027 channel->key = silc_calloc(tmp_len, sizeof(*channel->key));
2028 memcpy(channel->key, key, tmp_len);
2030 if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
2031 conn->client->ops->say(conn->client, conn,
2032 "Cannot talk to channel: unsupported cipher %s", cipher);
2035 channel->channel_key->cipher->set_key(channel->channel_key->context,
2036 key, channel->key_len);
2038 /* Client is now joined to the channel */
2039 channel->on_channel = TRUE;
2043 silc_channel_key_payload_free(payload);
2046 /* Processes received key for channel. The received key will be used
2047 to protect the traffic on the channel for now on. Client must receive
2048 the key to the channel before talking on the channel is possible.
2049 This is the key that server has generated, this is not the channel
2050 private key, it is entirely local setting. */
2052 void silc_client_receive_channel_key(SilcClient client,
2053 SilcSocketConnection sock,
2056 SILC_LOG_DEBUG(("Received key for channel"));
2059 silc_client_save_channel_key(sock->user_data, packet, NULL);
2062 /* Process received message to a channel (or from a channel, really). This
2063 decrypts the channel message with channel specific key and parses the
2064 channel payload. Finally it displays the message on the screen. */
2066 void silc_client_channel_message(SilcClient client,
2067 SilcSocketConnection sock,
2068 SilcPacketContext *packet)
2070 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
2071 SilcBuffer buffer = packet->buffer;
2072 SilcChannelPayload payload = NULL;
2073 SilcChannelID *id = NULL;
2074 SilcChannelEntry channel;
2075 SilcChannelUser chu;
2076 SilcIDCacheEntry id_cache = NULL;
2077 SilcClientID *client_id = NULL;
2079 unsigned int block_len;
2082 if (packet->dst_id_type != SILC_ID_CHANNEL)
2085 client_id = silc_id_str2id(packet->src_id, packet->src_id_len,
2089 id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CHANNEL);
2093 /* Find the channel entry from channels on this connection */
2094 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
2095 SILC_ID_CHANNEL, &id_cache))
2098 channel = (SilcChannelEntry)id_cache->context;
2100 /* Decrypt the channel message payload. Push the IV out of the way,
2101 since it is not encrypted (after pushing buffer->tail has the IV). */
2102 block_len = silc_cipher_get_block_len(channel->channel_key);
2103 silc_buffer_push_tail(buffer, block_len);
2104 channel->channel_key->cipher->decrypt(channel->channel_key->context,
2105 buffer->data, buffer->data,
2106 buffer->len, buffer->tail);
2107 silc_buffer_pull_tail(buffer, block_len);
2109 /* Parse the channel message payload */
2110 payload = silc_channel_payload_parse(buffer);
2114 /* Find client entry */
2115 silc_list_start(channel->clients);
2116 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
2117 if (!SILC_ID_CLIENT_COMPARE(chu->client->id, client_id)) {
2123 /* Pass the message to application */
2124 client->ops->channel_message(client, conn, found ? chu->client : NULL,
2125 channel, silc_channel_get_data(payload, NULL));
2131 silc_free(client_id);
2133 silc_channel_payload_free(payload);
2136 /* Private message received. This processes the private message and
2137 finally displays it on the screen. */
2139 void silc_client_private_message(SilcClient client,
2140 SilcSocketConnection sock,
2141 SilcPacketContext *packet)
2143 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
2144 SilcBuffer buffer = packet->buffer;
2145 SilcIDCacheEntry id_cache;
2146 SilcClientID *remote_id = NULL;
2147 SilcClientEntry remote_client;
2148 unsigned short nick_len;
2149 unsigned char *nickname, *message = NULL;
2152 if (packet->src_id_type != SILC_ID_CLIENT)
2156 ret = silc_buffer_unformat(buffer,
2157 SILC_STR_UI16_NSTRING_ALLOC(&nickname, &nick_len),
2162 silc_buffer_pull(buffer, 2 + nick_len);
2164 message = silc_calloc(buffer->len + 1, sizeof(char));
2165 memcpy(message, buffer->data, buffer->len);
2167 remote_id = silc_id_str2id(packet->src_id, packet->src_id_len,
2172 /* Check whether we know this client already */
2173 if (!silc_idcache_find_by_id_one(conn->client_cache, remote_id,
2174 SILC_ID_CLIENT, &id_cache))
2176 /* Allocate client entry */
2177 remote_client = silc_calloc(1, sizeof(*remote_client));
2178 remote_client->id = remote_id;
2179 silc_parse_nickname(nickname, &remote_client->nickname,
2180 &remote_client->server, &remote_client->num);
2182 /* Save the client to cache */
2183 silc_idcache_add(conn->client_cache, remote_client->nickname,
2184 SILC_ID_CLIENT, remote_client->id, remote_client,
2187 remote_client = (SilcClientEntry)id_cache->context;
2190 /* Pass the private message to application */
2191 client->ops->private_message(client, conn, remote_client, message);
2193 /* See if we are away (gone). If we are away we will reply to the
2194 sender with the set away message. */
2195 if (conn->away && conn->away->away) {
2196 /* If it's me, ignore */
2197 if (!SILC_ID_CLIENT_COMPARE(remote_id, conn->local_id))
2200 /* Send the away message */
2201 silc_client_send_private_message(client, conn, remote_client,
2203 strlen(conn->away->away), TRUE);
2208 silc_free(remote_id);
2211 memset(message, 0, buffer->len);
2214 silc_free(nickname);
2217 /* Removes a client entry from all channel it has joined. This really is
2218 a performance killer (client_entry should have pointers to channel
2221 void silc_client_remove_from_channels(SilcClient client,
2222 SilcClientConnection conn,
2223 SilcClientEntry client_entry)
2225 SilcIDCacheEntry id_cache;
2226 SilcIDCacheList list;
2227 SilcChannelEntry channel;
2228 SilcChannelUser chu;
2230 if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
2231 SILC_ID_CHANNEL, &list))
2234 silc_idcache_list_first(list, &id_cache);
2235 channel = (SilcChannelEntry)id_cache->context;
2239 /* Remove client from channel */
2240 silc_list_start(channel->clients);
2241 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
2242 if (chu->client == client_entry) {
2243 silc_list_del(channel->clients, chu);
2249 if (!silc_idcache_list_next(list, &id_cache))
2252 channel = (SilcChannelEntry)id_cache->context;
2255 silc_idcache_list_free(list);
2258 /* Replaces `old' client entries from all channels to `new' client entry.
2259 This can be called for example when nickname changes and old ID entry
2260 is replaced from ID cache with the new one. If the old ID entry is only
2261 updated, then this fucntion needs not to be called. */
2263 void silc_client_replace_from_channels(SilcClient client,
2264 SilcClientConnection conn,
2265 SilcClientEntry old,
2266 SilcClientEntry new)
2268 SilcIDCacheEntry id_cache;
2269 SilcIDCacheList list;
2270 SilcChannelEntry channel;
2271 SilcChannelUser chu;
2273 if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
2274 SILC_ID_CHANNEL, &list))
2277 silc_idcache_list_first(list, &id_cache);
2278 channel = (SilcChannelEntry)id_cache->context;
2282 /* Replace client entry */
2283 silc_list_start(channel->clients);
2284 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
2285 if (chu->client == old) {
2291 if (!silc_idcache_list_next(list, &id_cache))
2294 channel = (SilcChannelEntry)id_cache->context;
2297 silc_idcache_list_free(list);
2300 /* Parses mode mask and returns the mode as string. */
2302 char *silc_client_chmode(unsigned int mode)
2309 memset(string, 0, sizeof(string));
2311 if (mode & SILC_CHANNEL_MODE_PRIVATE)
2312 strncat(string, "p", 1);
2314 if (mode & SILC_CHANNEL_MODE_SECRET)
2315 strncat(string, "s", 1);
2317 if (mode & SILC_CHANNEL_MODE_PRIVKEY)
2318 strncat(string, "k", 1);
2320 if (mode & SILC_CHANNEL_MODE_INVITE)
2321 strncat(string, "i", 1);
2323 if (mode & SILC_CHANNEL_MODE_TOPIC)
2324 strncat(string, "t", 1);
2326 if (mode & SILC_CHANNEL_MODE_ULIMIT)
2327 strncat(string, "l", 1);
2329 if (mode & SILC_CHANNEL_MODE_PASSPHRASE)
2330 strncat(string, "a", 1);
2332 /* Rest of mode is ignored */
2334 return strdup(string);
2337 /* Parses channel user mode mask and returns te mode as string */
2339 char *silc_client_chumode(unsigned int mode)
2346 memset(string, 0, sizeof(string));
2348 if (mode & SILC_CHANNEL_UMODE_CHANFO)
2349 strncat(string, "f", 1);
2351 if (mode & SILC_CHANNEL_UMODE_CHANOP)
2352 strncat(string, "o", 1);
2354 return strdup(string);
2357 /* Parses channel user mode and returns it as special mode character. */
2359 char *silc_client_chumode_char(unsigned int mode)
2366 memset(string, 0, sizeof(string));
2368 if (mode & SILC_CHANNEL_UMODE_CHANFO)
2369 strncat(string, "*", 1);
2371 if (mode & SILC_CHANNEL_UMODE_CHANOP)
2372 strncat(string, "@", 1);
2374 return strdup(string);