5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2000 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 /* Free's client object */
54 void silc_client_free(SilcClient client)
61 /* Initializes the client. This makes all the necessary steps to make
62 the client ready to be run. One must call silc_client_run to run the
65 int silc_client_init(SilcClient client)
67 SILC_LOG_DEBUG(("Initializing client"));
69 /* Initialize hash functions for client to use */
70 silc_hash_alloc("md5", &client->md5hash);
71 silc_hash_alloc("sha1", &client->sha1hash);
73 /* Initialize none cipher */
74 silc_cipher_alloc("none", &client->none_cipher);
76 /* Initialize random number generator */
77 client->rng = silc_rng_alloc();
78 silc_rng_init(client->rng);
79 silc_math_primegen_init(); /* XXX */
81 /* Register protocols */
82 silc_client_protocols_register();
84 /* Initialize the scheduler */
85 silc_schedule_init(&client->io_queue, &client->timeout_queue,
86 &client->generic_queue, 5000);
91 /* Stops the client. This is called to stop the client and thus to stop
94 void silc_client_stop(SilcClient client)
96 SILC_LOG_DEBUG(("Stopping client"));
98 /* Stop the scheduler, although it might be already stopped. This
99 doesn't hurt anyone. This removes all the tasks and task queues,
101 silc_schedule_stop();
102 silc_schedule_uninit();
104 silc_client_protocols_unregister();
106 SILC_LOG_DEBUG(("Client stopped"));
109 /* Runs the client. */
111 void silc_client_run(SilcClient client)
113 SILC_LOG_DEBUG(("Running client"));
115 /* Start the scheduler, the heart of the SILC client. When this returns
116 the program will be terminated. */
120 /* Allocates and adds new connection to the client. This adds the allocated
121 connection to the connection table and returns a pointer to it. A client
122 can have multiple connections to multiple servers. Every connection must
123 be added to the client using this function. User data `context' may
124 be sent as argument. */
126 SilcClientConnection silc_client_add_connection(SilcClient client,
131 SilcClientConnection conn;
134 conn = silc_calloc(1, sizeof(*conn));
136 /* Initialize ID caches */
137 conn->client_cache = silc_idcache_alloc(0);
138 conn->channel_cache = silc_idcache_alloc(0);
139 conn->server_cache = silc_idcache_alloc(0);
140 conn->client = client;
141 conn->remote_host = strdup(hostname);
142 conn->remote_port = port;
143 conn->context = context;
145 /* Add the connection to connections table */
146 for (i = 0; i < client->conns_count; i++)
147 if (client->conns && !client->conns[i]) {
148 client->conns[i] = conn;
152 client->conns = silc_realloc(client->conns, sizeof(*client->conns)
153 * (client->conns_count + 1));
154 client->conns[client->conns_count] = conn;
155 client->conns_count++;
160 /* Removes connection from client. */
162 void silc_client_del_connection(SilcClient client, SilcClientConnection conn)
166 for (i = 0; i < client->conns_count; i++)
167 if (client->conns[i] == conn) {
169 client->conns[i] = NULL;
173 /* Internal context for connection process. This is needed as we
174 doing asynchronous connecting. */
177 SilcClientConnection conn;
183 } SilcClientInternalConnectContext;
186 silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx)
190 /* XXX In the future we should give up this non-blocking connect all
191 together and use threads instead. */
192 /* Create connection to server asynchronously */
193 sock = silc_net_create_connection_async(ctx->port, ctx->host);
197 /* Register task that will receive the async connect and will
199 ctx->task = silc_task_register(ctx->client->io_queue, sock,
200 silc_client_connect_to_server_start,
203 SILC_TASK_PRI_NORMAL);
204 silc_task_reset_iotype(ctx->task, SILC_TASK_WRITE);
205 silc_schedule_set_listen_fd(sock, ctx->task->iomask);
212 /* Connects to remote server. This is the main routine used to connect
213 to SILC server. Returns -1 on error and the created socket otherwise.
214 The `context' is user context that is saved into the SilcClientConnection
215 that is created after the connection is created. */
217 int silc_client_connect_to_server(SilcClient client, int port,
218 char *host, void *context)
220 SilcClientInternalConnectContext *ctx;
221 SilcClientConnection conn;
224 SILC_LOG_DEBUG(("Connecting to port %d of server %s",
227 conn = silc_client_add_connection(client, host, port, context);
229 client->ops->say(client, conn,
230 "Connecting to port %d of server %s", port, host);
232 /* Allocate internal context for connection process. This is
233 needed as we are doing async connecting. */
234 ctx = silc_calloc(1, sizeof(*ctx));
235 ctx->client = client;
237 ctx->host = strdup(host);
241 /* Do the actual connecting process */
242 sock = silc_client_connect_to_server_internal(ctx);
244 silc_client_del_connection(client, conn);
248 /* Start SILC Key Exchange (SKE) protocol to negotiate shared secret
249 key material between client and server. This function can be called
250 directly if application is performing its own connecting and does not
251 use the connecting provided by this library. */
253 int silc_client_start_key_exchange(SilcClient client,
254 SilcClientConnection conn,
257 SilcProtocol protocol;
258 SilcClientKEInternalContext *proto_ctx;
261 /* Allocate new socket connection object */
262 silc_socket_alloc(fd, SILC_SOCKET_TYPE_SERVER, (void *)conn, &conn->sock);
263 if (conn->sock == NULL) {
264 client->ops->say(client, conn,
265 "Error: Could not allocate connection socket");
269 conn->nickname = strdup(client->username);
270 conn->sock->hostname = conn->remote_host;
271 conn->sock->port = conn->remote_port;
273 /* Allocate internal Key Exchange context. This is sent to the
274 protocol as context. */
275 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
276 proto_ctx->client = (void *)client;
277 proto_ctx->sock = conn->sock;
278 proto_ctx->rng = client->rng;
279 proto_ctx->responder = FALSE;
281 /* Perform key exchange protocol. silc_client_connect_to_server_final
282 will be called after the protocol is finished. */
283 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
284 &protocol, (void *)proto_ctx,
285 silc_client_connect_to_server_second);
287 client->ops->say(client, conn,
288 "Error: Could not start authentication protocol");
291 conn->sock->protocol = protocol;
293 /* Register the connection for network input and output. This sets
294 that scheduler will listen for incoming packets for this connection
295 and sets that outgoing packets may be sent to this connection as well.
296 However, this doesn't set the scheduler for outgoing traffic, it will
297 be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
298 later when outgoing data is available. */
299 context = (void *)client;
300 SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(fd);
302 /* Execute the protocol */
303 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
307 /* Start of the connection to the remote server. This is called after
308 succesful TCP/IP connection has been established to the remote host. */
310 SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
312 SilcClientInternalConnectContext *ctx =
313 (SilcClientInternalConnectContext *)context;
314 SilcClient client = ctx->client;
315 SilcClientConnection conn = ctx->conn;
316 int opt, opt_len = sizeof(opt);
318 SILC_LOG_DEBUG(("Start"));
320 /* Check the socket status as it might be in error */
321 getsockopt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
323 if (ctx->tries < 2) {
324 /* Connection failed but lets try again */
325 client->ops->say(client, conn, "Could not connect to server %s: %s",
326 ctx->host, strerror(opt));
327 client->ops->say(client, conn,
328 "Connecting to port %d of server %s resumed",
329 ctx->port, ctx->host);
331 /* Unregister old connection try */
332 silc_schedule_unset_listen_fd(fd);
333 silc_net_close_connection(fd);
334 silc_task_unregister(client->io_queue, ctx->task);
337 silc_client_connect_to_server_internal(ctx);
340 /* Connection failed and we won't try anymore */
341 client->ops->say(client, conn, "Could not connect to server %s: %s",
342 ctx->host, strerror(opt));
343 silc_schedule_unset_listen_fd(fd);
344 silc_net_close_connection(fd);
345 silc_task_unregister(client->io_queue, ctx->task);
348 /* Notify application of failure */
349 client->ops->connect(client, conn, FALSE);
350 silc_client_del_connection(client, conn);
355 silc_schedule_unset_listen_fd(fd);
356 silc_task_unregister(client->io_queue, ctx->task);
359 if (!silc_client_start_key_exchange(client, conn, fd)) {
360 silc_net_close_connection(fd);
361 client->ops->connect(client, conn, FALSE);
365 /* Second part of the connecting to the server. This executed
366 authentication protocol. */
368 SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
370 SilcProtocol protocol = (SilcProtocol)context;
371 SilcClientKEInternalContext *ctx =
372 (SilcClientKEInternalContext *)protocol->context;
373 SilcClient client = (SilcClient)ctx->client;
374 SilcSocketConnection sock = NULL;
375 SilcClientConnAuthInternalContext *proto_ctx;
377 SILC_LOG_DEBUG(("Start"));
379 if (protocol->state == SILC_PROTOCOL_STATE_ERROR) {
380 /* Error occured during protocol */
381 SILC_LOG_DEBUG(("Error during KE protocol"));
382 silc_protocol_free(protocol);
384 silc_ske_free(ctx->ske);
386 silc_free(ctx->dest_id);
387 ctx->sock->protocol = NULL;
389 /* Notify application of failure */
390 client->ops->connect(client, ctx->sock->user_data, FALSE);
395 /* Allocate internal context for the authentication protocol. This
396 is sent as context for the protocol. */
397 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
398 proto_ctx->client = (void *)client;
399 proto_ctx->sock = sock = ctx->sock;
400 proto_ctx->ske = ctx->ske; /* Save SKE object from previous protocol */
401 proto_ctx->dest_id_type = ctx->dest_id_type;
402 proto_ctx->dest_id = ctx->dest_id;
404 /* Resolve the authentication method to be used in this connection */
405 if (!client->ops->get_auth_method(client, sock->user_data, sock->hostname,
406 sock->port, &proto_ctx->auth_meth,
407 &proto_ctx->auth_data,
408 &proto_ctx->auth_data_len))
410 /* XXX do AUTH_REQUEST resolcing with server */
411 proto_ctx->auth_meth = SILC_PROTOCOL_CONN_AUTH_NONE;
414 /* Free old protocol as it is finished now */
415 silc_protocol_free(protocol);
417 silc_buffer_free(ctx->packet);
419 /* silc_free(ctx->keymat....); */
420 sock->protocol = NULL;
422 /* Allocate the authentication protocol. This is allocated here
423 but we won't start it yet. We will be receiving party of this
424 protocol thus we will wait that connecting party will make
426 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
427 &sock->protocol, (void *)proto_ctx,
428 silc_client_connect_to_server_final);
430 /* Execute the protocol */
431 sock->protocol->execute(client->timeout_queue, 0, sock->protocol, fd, 0, 0);
434 /* Finalizes the connection to the remote SILC server. This is called
435 after authentication protocol has been completed. This send our
436 user information to the server to receive our client ID from
439 SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
441 SilcProtocol protocol = (SilcProtocol)context;
442 SilcClientConnAuthInternalContext *ctx =
443 (SilcClientConnAuthInternalContext *)protocol->context;
444 SilcClient client = (SilcClient)ctx->client;
445 SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
448 SILC_LOG_DEBUG(("Start"));
450 if (protocol->state == SILC_PROTOCOL_STATE_ERROR) {
451 /* Error occured during protocol */
452 SILC_LOG_DEBUG(("Error during authentication protocol"));
453 silc_protocol_free(protocol);
455 silc_free(ctx->auth_data);
457 silc_ske_free(ctx->ske);
459 silc_free(ctx->dest_id);
460 conn->sock->protocol = NULL;
462 /* Notify application of failure */
463 client->ops->connect(client, ctx->sock->user_data, FALSE);
468 /* Send NEW_CLIENT packet to the server. We will become registered
469 to the SILC network after sending this packet and we will receive
470 client ID from the server. */
471 packet = silc_buffer_alloc(2 + 2 + strlen(client->username) +
472 strlen(client->realname));
473 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
474 silc_buffer_format(packet,
475 SILC_STR_UI_SHORT(strlen(client->username)),
476 SILC_STR_UI_XNSTRING(client->username,
477 strlen(client->username)),
478 SILC_STR_UI_SHORT(strlen(client->realname)),
479 SILC_STR_UI_XNSTRING(client->realname,
480 strlen(client->realname)),
483 /* Send the packet */
484 silc_client_packet_send(client, ctx->sock, SILC_PACKET_NEW_CLIENT,
486 packet->data, packet->len, TRUE);
487 silc_buffer_free(packet);
489 /* Save remote ID. */
490 conn->remote_id = ctx->dest_id;
491 conn->remote_id_data = silc_id_id2str(ctx->dest_id, SILC_ID_SERVER);
492 conn->remote_id_data_len = SILC_ID_SERVER_LEN;
494 /* Notify application of successful connection */
495 client->ops->connect(client, conn, TRUE);
497 silc_protocol_free(protocol);
499 silc_free(ctx->auth_data);
501 silc_ske_free(ctx->ske);
503 silc_free(ctx->dest_id);
505 conn->sock->protocol = NULL;
508 /* Internal routine that sends packet or marks packet to be sent. This
509 is used directly only in special cases. Normal cases should use
510 silc_server_packet_send. Returns < 0 on error. */
512 static int silc_client_packet_send_real(SilcClient client,
513 SilcSocketConnection sock,
518 /* Send the packet */
519 ret = silc_packet_send(sock, force_send);
523 /* Mark that there is some outgoing data available for this connection.
524 This call sets the connection both for input and output (the input
525 is set always and this call keeps the input setting, actually).
526 Actual data sending is performed by silc_client_packet_process. */
527 SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(sock->sock);
529 /* Mark to socket that data is pending in outgoing buffer. This flag
530 is needed if new data is added to the buffer before the earlier
531 put data is sent to the network. */
532 SILC_SET_OUTBUF_PENDING(sock);
537 /* Packet processing callback. This is used to send and receive packets
538 from network. This is generic task. */
540 SILC_TASK_CALLBACK(silc_client_packet_process)
542 SilcClient client = (SilcClient)context;
543 SilcSocketConnection sock = NULL;
544 SilcClientConnection conn;
547 SILC_LOG_DEBUG(("Processing packet"));
549 SILC_CLIENT_GET_SOCK(client, fd, sock);
553 conn = (SilcClientConnection)sock->user_data;
556 if (type == SILC_TASK_WRITE) {
557 SILC_LOG_DEBUG(("Writing data to connection"));
559 if (sock->outbuf->data - sock->outbuf->head)
560 silc_buffer_push(sock->outbuf,
561 sock->outbuf->data - sock->outbuf->head);
563 ret = silc_client_packet_send_real(client, sock, TRUE);
565 /* If returned -2 could not write to connection now, will do
570 /* The packet has been sent and now it is time to set the connection
571 back to only for input. When there is again some outgoing data
572 available for this connection it will be set for output as well.
573 This call clears the output setting and sets it only for input. */
574 SILC_CLIENT_SET_CONNECTION_FOR_INPUT(fd);
575 SILC_UNSET_OUTBUF_PENDING(sock);
577 silc_buffer_clear(sock->outbuf);
581 /* Packet receiving */
582 if (type == SILC_TASK_READ) {
583 SILC_LOG_DEBUG(("Reading data from connection"));
585 /* Read data from network */
586 ret = silc_packet_receive(sock);
592 SILC_LOG_DEBUG(("Read EOF"));
594 /* If connection is disconnecting already we will finally
595 close the connection */
596 if (SILC_IS_DISCONNECTING(sock)) {
597 client->ops->disconnect(client, conn);
598 silc_client_close_connection(client, sock);
602 client->ops->say(client, conn, "Connection closed: premature EOF");
603 SILC_LOG_DEBUG(("Premature EOF from connection %d", sock->sock));
604 client->ops->disconnect(client, conn);
605 silc_client_close_connection(client, sock);
609 /* Process the packet. This will call the parser that will then
610 decrypt and parse the packet. */
611 silc_packet_receive_process(sock, conn->receive_key, conn->hmac,
612 silc_client_packet_parse, client);
616 /* Parses whole packet, received earlier. */
618 SILC_TASK_CALLBACK(silc_client_packet_parse_real)
620 SilcPacketParserContext *parse_ctx = (SilcPacketParserContext *)context;
621 SilcClient client = (SilcClient)parse_ctx->context;
622 SilcPacketContext *packet = parse_ctx->packet;
623 SilcBuffer buffer = packet->buffer;
624 SilcSocketConnection sock = parse_ctx->sock;
625 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
628 SILC_LOG_DEBUG(("Start"));
630 /* Decrypt the received packet */
631 ret = silc_packet_decrypt(conn->receive_key, conn->hmac, buffer, packet);
636 /* Parse the packet. Packet type is returned. */
637 ret = silc_packet_parse(packet);
639 /* Parse the packet header in special way as this is "special"
641 ret = silc_packet_parse_special(packet);
644 if (ret == SILC_PACKET_NONE)
647 /* Parse the incoming packet type */
648 silc_client_packet_parse_type(client, sock, packet);
651 silc_buffer_clear(buffer);
653 silc_free(packet->src_id);
655 silc_free(packet->dst_id);
657 silc_free(parse_ctx);
660 /* Parser callback called by silc_packet_receive_process. Thie merely
661 registers timeout that will handle the actual parsing when appropriate. */
663 void silc_client_packet_parse(SilcPacketParserContext *parser_context)
665 SilcClient client = (SilcClient)parser_context->context;
667 /* Parse the packet */
668 silc_task_register(client->timeout_queue, parser_context->sock->sock,
669 silc_client_packet_parse_real,
670 (void *)parser_context, 0, 1,
672 SILC_TASK_PRI_NORMAL);
675 /* Parses the packet type and calls what ever routines the packet type
676 requires. This is done for all incoming packets. */
678 void silc_client_packet_parse_type(SilcClient client,
679 SilcSocketConnection sock,
680 SilcPacketContext *packet)
682 SilcBuffer buffer = packet->buffer;
683 SilcPacketType type = packet->type;
685 SILC_LOG_DEBUG(("Parsing packet type %d", type));
687 /* Parse the packet type */
689 case SILC_PACKET_DISCONNECT:
690 silc_client_disconnected_by_server(client, sock, buffer);
692 case SILC_PACKET_SUCCESS:
694 * Success received for something. For now we can have only
695 * one protocol for connection executing at once hence this
696 * success message is for whatever protocol is executing currently.
698 if (sock->protocol) {
699 sock->protocol->execute(client->timeout_queue, 0,
700 sock->protocol, sock->sock, 0, 0);
703 case SILC_PACKET_FAILURE:
705 * Failure received for some protocol. Set the protocol state to
706 * error and call the protocol callback. This fill cause error on
707 * protocol and it will call the final callback.
709 if (sock->protocol) {
710 sock->protocol->state = SILC_PROTOCOL_STATE_FAILURE;
711 sock->protocol->execute(client->timeout_queue, 0,
712 sock->protocol, sock->sock, 0, 0);
714 /* XXX We have only two protocols currently thus we know what this
715 failure indication is. */
716 if (buffer->len >= 4) {
717 unsigned int failure;
719 SILC_GET32_MSB(failure, buffer->data);
721 /* Notify application */
722 client->ops->failure(client, sock->user_data, sock->protocol,
727 case SILC_PACKET_REJECT:
730 case SILC_PACKET_NOTIFY:
732 * Received notify message
734 silc_client_notify_by_server(client, sock, packet);
737 case SILC_PACKET_ERROR:
739 * Received error message
741 silc_client_error_by_server(client, sock, buffer);
744 case SILC_PACKET_CHANNEL_MESSAGE:
746 * Received message to (from, actually) a channel
748 silc_client_channel_message(client, sock, packet);
750 case SILC_PACKET_CHANNEL_KEY:
752 * Received key for a channel. By receiving this key the client will be
753 * able to talk to the channel it has just joined. This can also be
754 * a new key for existing channel as keys expire peridiocally.
756 silc_client_receive_channel_key(client, sock, buffer);
759 case SILC_PACKET_PRIVATE_MESSAGE:
761 * Received private message
763 silc_client_private_message(client, sock, packet);
765 case SILC_PACKET_PRIVATE_MESSAGE_KEY:
767 * Received private message key
771 case SILC_PACKET_COMMAND_REPLY:
773 * Recived reply for a command
775 silc_client_command_reply_process(client, sock, packet);
778 case SILC_PACKET_KEY_EXCHANGE:
779 if (sock->protocol) {
780 SilcClientKEInternalContext *proto_ctx =
781 (SilcClientKEInternalContext *)sock->protocol->context;
783 proto_ctx->packet = buffer;
784 proto_ctx->dest_id_type = packet->src_id_type;
785 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_type);
787 /* Let the protocol handle the packet */
788 sock->protocol->execute(client->timeout_queue, 0,
789 sock->protocol, sock->sock, 0, 0);
791 SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
792 "protocol active, packet dropped."));
794 /* XXX Trigger KE protocol?? Rekey actually! */
798 case SILC_PACKET_KEY_EXCHANGE_1:
799 if (sock->protocol) {
802 SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
803 "protocol active, packet dropped."));
806 case SILC_PACKET_KEY_EXCHANGE_2:
807 if (sock->protocol) {
808 SilcClientKEInternalContext *proto_ctx =
809 (SilcClientKEInternalContext *)sock->protocol->context;
811 if (proto_ctx->packet)
812 silc_buffer_free(proto_ctx->packet);
814 proto_ctx->packet = buffer;
815 proto_ctx->dest_id_type = packet->src_id_type;
816 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_type);
818 /* Let the protocol handle the packet */
819 sock->protocol->execute(client->timeout_queue, 0,
820 sock->protocol, sock->sock, 0, 0);
822 SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
823 "protocol active, packet dropped."));
827 case SILC_PACKET_NEW_ID:
830 * Received new ID from server. This packet is received at
831 * the connection to the server. New ID is also received when
832 * user changes nickname but in that case the new ID is received
833 * as command reply and not as this packet type.
837 idp = silc_id_payload_parse(buffer);
838 if (silc_id_payload_get_type(idp) != SILC_ID_CLIENT)
841 silc_client_receive_new_id(client, sock, idp);
842 silc_id_payload_free(idp);
847 SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
852 /* Sends packet. This doesn't actually send the packet instead it assembles
853 it and marks it to be sent. However, if force_send is TRUE the packet
854 is sent immediately. if dst_id, cipher and hmac are NULL those parameters
855 will be derived from sock argument. Otherwise the valid arguments sent
858 void silc_client_packet_send(SilcClient client,
859 SilcSocketConnection sock,
862 SilcIdType dst_id_type,
866 unsigned int data_len,
869 SilcPacketContext packetdata;
871 SILC_LOG_DEBUG(("Sending packet, type %d", type));
873 /* Get data used in the packet sending, keys and stuff */
874 if ((!cipher || !hmac || !dst_id) && sock->user_data) {
875 if (!cipher && ((SilcClientConnection)sock->user_data)->send_key)
876 cipher = ((SilcClientConnection)sock->user_data)->send_key;
878 if (!hmac && ((SilcClientConnection)sock->user_data)->hmac)
879 hmac = ((SilcClientConnection)sock->user_data)->hmac;
881 if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
882 dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
883 dst_id_type = SILC_ID_SERVER;
887 /* Set the packet context pointers */
888 packetdata.flags = 0;
889 packetdata.type = type;
890 if (((SilcClientConnection)sock->user_data)->local_id_data)
891 packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
893 packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
894 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
895 packetdata.src_id_type = SILC_ID_CLIENT;
897 packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
898 packetdata.dst_id_len = silc_id_get_len(dst_id_type);
899 packetdata.dst_id_type = dst_id_type;
901 packetdata.dst_id = NULL;
902 packetdata.dst_id_len = 0;
903 packetdata.dst_id_type = SILC_ID_NONE;
905 packetdata.rng = client->rng;
906 packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
907 packetdata.src_id_len + packetdata.dst_id_len;
908 packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
910 /* Prepare outgoing data buffer for packet sending */
911 silc_packet_send_prepare(sock,
912 SILC_PACKET_HEADER_LEN +
913 packetdata.src_id_len +
914 packetdata.dst_id_len,
918 SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len));
920 packetdata.buffer = sock->outbuf;
922 /* Put the data to the buffer */
923 if (data && data_len)
924 silc_buffer_put(sock->outbuf, data, data_len);
926 /* Create the outgoing packet */
927 silc_packet_assemble(&packetdata);
929 /* Encrypt the packet */
931 silc_packet_encrypt(cipher, hmac, sock->outbuf, sock->outbuf->len);
933 SILC_LOG_HEXDUMP(("Packet, len %d", sock->outbuf->len),
934 sock->outbuf->data, sock->outbuf->len);
936 /* Now actually send the packet */
937 silc_client_packet_send_real(client, sock, force_send);
940 /* Sends packet to a channel. Packet to channel is always encrypted
941 differently from "normal" packets. SILC header of the packet is
942 encrypted with the next receiver's key and the rest of the packet is
943 encrypted with the channel specific key. Padding and HMAC is computed
944 with the next receiver's key. */
946 void silc_client_packet_send_to_channel(SilcClient client,
947 SilcSocketConnection sock,
948 SilcChannelEntry channel,
950 unsigned int data_len,
954 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
956 SilcPacketContext packetdata;
959 unsigned char *id_string;
961 SILC_LOG_DEBUG(("Sending packet to channel"));
963 if (!channel || !channel->key) {
964 client->ops->say(client, conn,
965 "Cannot talk to channel: key does not exist");
971 for (i = 0; i < 16; i++)
972 channel->iv[i] = silc_rng_get_byte(client->rng);
974 silc_hash_make(client->md5hash, channel->iv, 16, channel->iv);
976 /* Encode the channel payload */
977 payload = silc_channel_payload_encode(data_len, data, 16, channel->iv,
980 client->ops->say(client, conn,
981 "Error: Could not create packet to be sent to channel");
985 /* Get data used in packet header encryption, keys and stuff. Rest
986 of the packet (the payload) is, however, encrypted with the
987 specified channel key. */
988 cipher = conn->send_key;
990 id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
992 /* Set the packet context pointers. The destination ID is always
993 the Channel ID of the channel. Server and router will handle the
994 distribution of the packet. */
995 packetdata.flags = 0;
996 packetdata.type = SILC_PACKET_CHANNEL_MESSAGE;
997 packetdata.src_id = conn->local_id_data;
998 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
999 packetdata.src_id_type = SILC_ID_CLIENT;
1000 packetdata.dst_id = id_string;
1001 packetdata.dst_id_len = SILC_ID_CHANNEL_LEN;
1002 packetdata.dst_id_type = SILC_ID_CHANNEL;
1003 packetdata.rng = client->rng;
1004 packetdata.truelen = payload->len + SILC_PACKET_HEADER_LEN +
1005 packetdata.src_id_len + packetdata.dst_id_len;
1006 packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
1007 packetdata.src_id_len +
1008 packetdata.dst_id_len));
1010 /* Prepare outgoing data buffer for packet sending */
1011 silc_packet_send_prepare(sock,
1012 SILC_PACKET_HEADER_LEN +
1013 packetdata.src_id_len +
1014 packetdata.dst_id_len,
1018 packetdata.buffer = sock->outbuf;
1020 /* Encrypt payload of the packet. This is encrypted with the channel key. */
1021 channel->channel_key->cipher->encrypt(channel->channel_key->context,
1022 payload->data, payload->data,
1023 payload->len - 16, /* -IV_LEN */
1026 /* Put the actual encrypted payload data into the buffer. */
1027 silc_buffer_put(sock->outbuf, payload->data, payload->len);
1029 /* Create the outgoing packet */
1030 silc_packet_assemble(&packetdata);
1032 /* Encrypt the header and padding of the packet. This is encrypted
1033 with normal session key shared with our server. */
1034 silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN +
1035 packetdata.src_id_len + packetdata.dst_id_len +
1038 SILC_LOG_HEXDUMP(("Packet to channel, len %d", sock->outbuf->len),
1039 sock->outbuf->data, sock->outbuf->len);
1041 /* Now actually send the packet */
1042 silc_client_packet_send_real(client, sock, force_send);
1043 silc_buffer_free(payload);
1044 silc_free(id_string);
1047 /* Sends private message to remote client. If private message key has
1048 not been set with this client then the message will be encrypted using
1049 normal session keys. Private messages are special packets in SILC
1050 network hence we need this own function for them. This is similiar
1051 to silc_client_packet_send_to_channel except that we send private
1054 void silc_client_packet_send_private_message(SilcClient client,
1055 SilcSocketConnection sock,
1056 SilcClientEntry client_entry,
1057 unsigned char *data,
1058 unsigned int data_len,
1061 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1063 SilcPacketContext packetdata;
1064 unsigned int nick_len;
1068 SILC_LOG_DEBUG(("Sending private message"));
1070 /* Create private message payload */
1071 nick_len = strlen(conn->nickname);
1072 buffer = silc_buffer_alloc(2 + nick_len + data_len);
1073 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
1074 silc_buffer_format(buffer,
1075 SILC_STR_UI_SHORT(nick_len),
1076 SILC_STR_UI_XNSTRING(conn->nickname,
1078 SILC_STR_UI_XNSTRING(data, data_len),
1081 /* If we don't have private message specific key then private messages
1082 are just as any normal packet thus call normal packet sending. If
1083 the key exist then the encryption process is a bit different and
1084 will be done in the rest of this function. */
1085 if (!client_entry->send_key) {
1086 silc_client_packet_send(client, sock, SILC_PACKET_PRIVATE_MESSAGE,
1087 client_entry->id, SILC_ID_CLIENT, NULL, NULL,
1088 buffer->data, buffer->len, force_send);
1092 /* We have private message specific key */
1094 /* Get data used in the encryption */
1095 cipher = client_entry->send_key;
1098 /* Set the packet context pointers. */
1099 packetdata.flags = 0;
1100 packetdata.type = SILC_PACKET_PRIVATE_MESSAGE;
1101 packetdata.src_id = conn->local_id_data;
1102 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1103 packetdata.src_id_type = SILC_ID_CLIENT;
1105 packetdata.dst_id = silc_id_id2str(client_entry->id, SILC_ID_CLIENT);
1107 packetdata.dst_id = conn->local_id_data;
1108 packetdata.dst_id_len = SILC_ID_CLIENT_LEN;
1109 packetdata.dst_id_type = SILC_ID_CLIENT;
1110 packetdata.rng = client->rng;
1111 packetdata.truelen = buffer->len + SILC_PACKET_HEADER_LEN +
1112 packetdata.src_id_len + packetdata.dst_id_len;
1113 packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
1114 packetdata.src_id_len +
1115 packetdata.dst_id_len));
1117 /* Prepare outgoing data buffer for packet sending */
1118 silc_packet_send_prepare(sock,
1119 SILC_PACKET_HEADER_LEN +
1120 packetdata.src_id_len +
1121 packetdata.dst_id_len,
1125 packetdata.buffer = sock->outbuf;
1127 /* Encrypt payload of the packet. Encrypt with private message specific
1128 key if it exist, otherwise with session key. */
1129 cipher->cipher->encrypt(cipher->context, buffer->data, buffer->data,
1130 buffer->len, cipher->iv);
1132 /* Put the actual encrypted payload data into the buffer. */
1133 silc_buffer_put(sock->outbuf, buffer->data, buffer->len);
1135 /* Create the outgoing packet */
1136 silc_packet_assemble(&packetdata);
1138 /* Encrypt the header and padding of the packet. */
1139 silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN +
1140 packetdata.src_id_len + packetdata.dst_id_len +
1143 SILC_LOG_HEXDUMP(("Private message packet, len %d", sock->outbuf->len),
1144 sock->outbuf->data, sock->outbuf->len);
1146 /* Now actually send the packet */
1147 silc_client_packet_send_real(client, sock, force_send);
1148 silc_free(packetdata.dst_id);
1154 /* Closes connection to remote end. Free's all allocated data except
1155 for some information such as nickname etc. that are valid at all time. */
1157 void silc_client_close_connection(SilcClient client,
1158 SilcSocketConnection sock)
1160 SilcClientConnection conn;
1162 /* We won't listen for this connection anymore */
1163 silc_schedule_unset_listen_fd(sock->sock);
1165 /* Unregister all tasks */
1166 silc_task_unregister_by_fd(client->io_queue, sock->sock);
1167 silc_task_unregister_by_fd(client->timeout_queue, sock->sock);
1169 /* Close the actual connection */
1170 silc_net_close_connection(sock->sock);
1172 client->ops->say(client, sock->user_data,
1173 "Closed connection to host %s", sock->hostname ?
1174 sock->hostname : sock->ip);
1176 /* Free everything */
1177 if (sock->user_data) {
1178 conn = (SilcClientConnection)sock->user_data;
1180 /* XXX Free all client entries and channel entries. */
1182 /* Clear ID caches */
1183 silc_idcache_del_all(conn->client_cache);
1184 silc_idcache_del_all(conn->channel_cache);
1187 if (conn->remote_host)
1188 silc_free(conn->remote_host);
1190 silc_free(conn->local_id);
1191 if (conn->local_id_data)
1192 silc_free(conn->local_id_data);
1194 silc_cipher_free(conn->send_key);
1195 if (conn->receive_key)
1196 silc_cipher_free(conn->receive_key);
1198 silc_hmac_free(conn->hmac);
1199 if (conn->hmac_key) {
1200 memset(conn->hmac_key, 0, conn->hmac_key_len);
1201 silc_free(conn->hmac_key);
1205 conn->remote_port = 0;
1206 conn->remote_type = 0;
1207 conn->send_key = NULL;
1208 conn->receive_key = NULL;
1210 conn->hmac_key = NULL;
1211 conn->hmac_key_len = 0;
1212 conn->local_id = NULL;
1213 conn->local_id_data = NULL;
1214 conn->remote_host = NULL;
1215 conn->current_channel = NULL;
1217 silc_client_del_connection(client, conn);
1220 if (sock->protocol) {
1221 silc_protocol_free(sock->protocol);
1222 sock->protocol = NULL;
1224 silc_socket_free(sock);
1227 /* Called when we receive disconnection packet from server. This
1228 closes our end properly and displays the reason of the disconnection
1231 void silc_client_disconnected_by_server(SilcClient client,
1232 SilcSocketConnection sock,
1237 SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1239 msg = silc_calloc(message->len + 1, sizeof(char));
1240 memcpy(msg, message->data, message->len);
1241 client->ops->say(client, sock->user_data, msg);
1244 SILC_SET_DISCONNECTED(sock);
1245 silc_client_close_connection(client, sock);
1248 /* Received error message from server. Display it on the screen.
1249 We don't take any action what so ever of the error message. */
1251 void silc_client_error_by_server(SilcClient client,
1252 SilcSocketConnection sock,
1257 msg = silc_calloc(message->len + 1, sizeof(char));
1258 memcpy(msg, message->data, message->len);
1259 client->ops->say(client, sock->user_data, msg);
1263 /* Called when notify is received and some async operation (such as command)
1264 is required before processing the notify message. This calls again the
1265 silc_client_notify_by_server and reprocesses the original notify packet. */
1267 static void silc_client_notify_by_server_pending(void *context)
1269 SilcPacketContext *p = (SilcPacketContext *)context;
1270 silc_client_notify_by_server(p->context, p->sock, p);
1272 silc_free(p->src_id);
1274 silc_free(p->dst_id);
1275 silc_buffer_free(p->buffer);
1279 /* Received notify message from server */
1281 void silc_client_notify_by_server(SilcClient client,
1282 SilcSocketConnection sock,
1283 SilcPacketContext *packet)
1285 SilcBuffer buffer = packet->buffer;
1286 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1287 SilcNotifyPayload payload;
1288 SilcNotifyType type;
1289 SilcArgumentPayload args;
1292 SilcClientID *client_id = NULL;
1293 SilcChannelID *channel_id = NULL;
1294 SilcClientEntry client_entry;
1295 SilcClientEntry client_entry2;
1296 SilcChannelEntry channel;
1297 SilcIDCacheEntry id_cache = NULL;
1299 unsigned int tmp_len, mode;
1301 payload = silc_notify_payload_parse(buffer);
1302 type = silc_notify_get_type(payload);
1303 args = silc_notify_get_args(payload);
1308 case SILC_NOTIFY_TYPE_NONE:
1309 /* Notify application */
1310 client->ops->notify(client, conn, type,
1311 silc_argument_get_arg_type(args, 1, NULL));
1314 case SILC_NOTIFY_TYPE_INVITE:
1316 * Someone invited me to a channel. Find Client and Channel entries
1317 * for the application.
1321 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1325 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1327 /* Find Client entry and if not found query it */
1328 client_entry = silc_idlist_get_client_by_id(client, conn, client_id, TRUE);
1329 if (!client_entry) {
1330 SilcPacketContext *p = silc_packet_context_dup(packet);
1331 p->context = (void *)client;
1333 silc_client_command_pending(SILC_COMMAND_WHOIS,
1334 silc_client_notify_by_server_pending, p);
1338 /* Get Channel ID */
1339 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1343 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1345 /* XXX Will ALWAYS fail because currently we don't have way to resolve
1346 channel information for channel that we're not joined to. */
1347 /* XXX ways to fix: use (extended) LIST command, or define the channel
1348 name to the notfy type when name resolving is not mandatory. */
1349 /* Find channel entry */
1350 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1351 SILC_ID_CHANNEL, &id_cache))
1354 channel = (SilcChannelEntry)id_cache->context;
1356 /* Notify application */
1357 client->ops->notify(client, conn, type, client_entry, channel);
1360 case SILC_NOTIFY_TYPE_JOIN:
1362 * Someone has joined to a channel. Get their ID and nickname and
1363 * cache them for later use.
1367 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1371 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1373 /* Find Client entry and if not found query it */
1374 client_entry = silc_idlist_get_client_by_id(client, conn, client_id, TRUE);
1375 if (!client_entry) {
1376 SilcPacketContext *p = silc_packet_context_dup(packet);
1377 p->context = (void *)client;
1379 silc_client_command_pending(SILC_COMMAND_WHOIS,
1380 silc_client_notify_by_server_pending, p);
1384 /* Get channel entry */
1385 channel_id = silc_id_str2id(packet->dst_id, SILC_ID_CHANNEL);
1386 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1387 SILC_ID_CHANNEL, &id_cache))
1390 channel = (SilcChannelEntry)id_cache->context;
1392 /* Add client to channel */
1393 for (i = 0; i < channel->clients_count; i++) {
1394 if (channel->clients[i].client == NULL) {
1395 channel->clients[channel->clients_count].client = client_entry;
1396 channel->clients_count++;
1401 if (i == channel->clients_count) {
1402 channel->clients = silc_realloc(channel->clients,
1403 sizeof(*channel->clients) *
1404 (channel->clients_count + 1));
1405 channel->clients[channel->clients_count].client = client_entry;
1406 channel->clients[channel->clients_count].mode = 0;
1407 channel->clients_count++;
1410 /* XXX add support for multiple same nicks on same channel. Check
1413 /* Notify application. The channel entry is sent last as this notify
1414 is for channel but application don't know it from the arguments
1416 client->ops->notify(client, conn, type, client_entry, channel);
1419 case SILC_NOTIFY_TYPE_LEAVE:
1421 * Someone has left a channel. We will remove it from the channel but
1422 * we'll keep it in the cache in case we'll need it later.
1426 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1430 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1432 /* Find Client entry */
1434 silc_idlist_get_client_by_id(client, conn, client_id, FALSE);
1438 /* Get channel entry */
1439 channel_id = silc_id_str2id(packet->dst_id, SILC_ID_CHANNEL);
1440 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1441 SILC_ID_CHANNEL, &id_cache))
1444 channel = (SilcChannelEntry)id_cache->context;
1446 /* Remove client from channel */
1447 for (i = 0; i < channel->clients_count; i++) {
1448 if (channel->clients[i].client == client_entry) {
1449 channel->clients[i].client = NULL;
1450 channel->clients_count--;
1455 /* Notify application. The channel entry is sent last as this notify
1456 is for channel but application don't know it from the arguments
1458 client->ops->notify(client, conn, type, client_entry, channel);
1461 case SILC_NOTIFY_TYPE_SIGNOFF:
1463 * Someone left SILC. We'll remove it from all channels and from cache.
1467 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1471 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1473 /* Find Client entry */
1475 silc_idlist_get_client_by_id(client, conn, client_id, FALSE);
1479 /* Remove from all channels */
1480 silc_client_remove_from_channels(client, conn, client_entry);
1482 /* Remove from cache */
1483 silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT,
1486 /* Notify application */
1487 client->ops->notify(client, conn, type, client_entry);
1490 if (client_entry->nickname)
1491 silc_free(client_entry->nickname);
1492 if (client_entry->server)
1493 silc_free(client_entry->server);
1494 if (client_entry->id)
1495 silc_free(client_entry->id);
1496 if (client_entry->send_key)
1497 silc_cipher_free(client_entry->send_key);
1498 if (client_entry->receive_key)
1499 silc_cipher_free(client_entry->receive_key);
1502 case SILC_NOTIFY_TYPE_TOPIC_SET:
1504 * Someone set the topic on a channel.
1508 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1512 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1514 /* Find Client entry */
1516 silc_idlist_get_client_by_id(client, conn, client_id, FALSE);
1521 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1525 /* Get channel entry */
1526 channel_id = silc_id_str2id(packet->dst_id, SILC_ID_CHANNEL);
1527 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1528 SILC_ID_CHANNEL, &id_cache))
1531 channel = (SilcChannelEntry)id_cache->context;
1533 /* Notify application. The channel entry is sent last as this notify
1534 is for channel but application don't know it from the arguments
1536 client->ops->notify(client, conn, type, client_entry, tmp, channel);
1539 case SILC_NOTIFY_TYPE_NICK_CHANGE:
1541 * Someone changed their nickname. If we don't have entry for the new
1542 * ID we will query it and return here after it's done. After we've
1543 * returned we fetch the old entry and free it and notify the
1547 /* Get new Client ID */
1548 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1552 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1555 if (!SILC_ID_CLIENT_COMPARE(client_id, conn->local_id))
1558 /* Find Client entry and if not found query it */
1560 silc_idlist_get_client_by_id(client, conn, client_id, TRUE);
1561 if (!client_entry2) {
1562 SilcPacketContext *p = silc_packet_context_dup(packet);
1563 p->context = (void *)client;
1565 silc_client_command_pending(SILC_COMMAND_WHOIS,
1566 silc_client_notify_by_server_pending, p);
1570 /* Get old Client ID */
1571 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1575 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1577 /* Find old Client entry */
1579 silc_idlist_get_client_by_id(client, conn, client_id, FALSE);
1583 /* Remove the old from cache */
1584 silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT,
1587 /* Replace old ID entry with new one on all channels. */
1588 silc_client_replace_from_channels(client, conn, client_entry,
1591 /* Notify application */
1592 client->ops->notify(client, conn, type, client_entry, client_entry2);
1595 if (client_entry->nickname)
1596 silc_free(client_entry->nickname);
1597 if (client_entry->server)
1598 silc_free(client_entry->server);
1599 if (client_entry->id)
1600 silc_free(client_entry->id);
1601 if (client_entry->send_key)
1602 silc_cipher_free(client_entry->send_key);
1603 if (client_entry->receive_key)
1604 silc_cipher_free(client_entry->receive_key);
1607 case SILC_NOTIFY_TYPE_CMODE_CHANGE:
1609 * Someone changed a channel mode
1613 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1617 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1619 /* Find Client entry */
1621 silc_idlist_get_client_by_id(client, conn, client_id, FALSE);
1626 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1630 SILC_GET32_MSB(mode, tmp);
1632 /* Get channel entry */
1633 channel_id = silc_id_str2id(packet->dst_id, SILC_ID_CHANNEL);
1634 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1635 SILC_ID_CHANNEL, &id_cache))
1638 channel = (SilcChannelEntry)id_cache->context;
1640 /* Save the new mode */
1641 channel->mode = mode;
1643 /* Notify application. The channel entry is sent last as this notify
1644 is for channel but application don't know it from the arguments
1646 client->ops->notify(client, conn, type, client_entry, mode, channel);
1649 case SILC_NOTIFY_TYPE_CUMODE_CHANGE:
1651 * Someone changed user's mode on a channel
1655 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1659 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1661 /* Find Client entry */
1663 silc_idlist_get_client_by_id(client, conn, client_id, FALSE);
1668 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1672 SILC_GET32_MSB(mode, tmp);
1674 /* Get target Client ID */
1675 tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
1679 silc_free(client_id);
1680 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1682 /* Find target Client entry */
1684 silc_idlist_get_client_by_id(client, conn, client_id, FALSE);
1688 /* Get channel entry */
1689 channel_id = silc_id_str2id(packet->dst_id, SILC_ID_CHANNEL);
1690 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1691 SILC_ID_CHANNEL, &id_cache))
1694 channel = (SilcChannelEntry)id_cache->context;
1697 for (i = 0; i < channel->clients_count; i++) {
1698 if (channel->clients[i].client == client_entry2) {
1699 channel->clients[i].mode = mode;
1704 /* Notify application. The channel entry is sent last as this notify
1705 is for channel but application don't know it from the arguments
1707 client->ops->notify(client, conn, type, client_entry, mode,
1708 client_entry2, channel);
1711 case SILC_NOTIFY_TYPE_MOTD:
1713 * Received Message of the day
1717 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1721 /* Notify application */
1722 client->ops->notify(client, conn, type, tmp);
1730 silc_notify_payload_free(payload);
1732 silc_free(client_id);
1734 silc_free(channel_id);
1737 /* Processes the received new Client ID from server. Old Client ID is
1738 deleted from cache and new one is added. */
1740 void silc_client_receive_new_id(SilcClient client,
1741 SilcSocketConnection sock,
1744 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1746 /* Delete old ID from ID cache */
1747 silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, conn->local_id);
1749 /* Save the new ID */
1751 silc_free(conn->local_id);
1752 if (conn->local_id_data)
1753 silc_free(conn->local_id_data);
1755 conn->local_id = silc_id_payload_get_id(idp);
1756 conn->local_id_data = silc_id_payload_get_data(idp);
1757 conn->local_id_data_len = silc_id_payload_get_len(idp);;
1759 if (!conn->local_entry)
1760 conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1762 conn->local_entry->nickname = conn->nickname;
1763 if (!conn->local_entry->username) {
1764 conn->local_entry->username =
1765 silc_calloc(strlen(client->username) + strlen(client->hostname) + 1,
1766 sizeof(conn->local_entry->username));
1767 sprintf(conn->local_entry->username, "%s@%s", client->username,
1770 conn->local_entry->id = conn->local_id;
1772 /* Put it to the ID cache */
1773 silc_idcache_add(conn->client_cache, conn->nickname, SILC_ID_CLIENT,
1774 conn->local_id, (void *)conn->local_entry, TRUE);
1777 /* Processed received Channel ID for a channel. This is called when client
1778 joins to channel and server replies with channel ID. The ID is cached. */
1780 void silc_client_new_channel_id(SilcClient client,
1781 SilcSocketConnection sock,
1783 unsigned int mode, SilcIDPayload idp)
1785 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1786 SilcChannelEntry channel;
1788 SILC_LOG_DEBUG(("New channel ID"));
1790 channel = silc_calloc(1, sizeof(*channel));
1791 channel->channel_name = channel_name;
1792 channel->id = silc_id_payload_get_id(idp);
1793 channel->mode = mode;
1794 conn->current_channel = channel;
1796 /* Put it to the ID cache */
1797 silc_idcache_add(conn->channel_cache, channel_name, SILC_ID_CHANNEL,
1798 (void *)channel->id, (void *)channel, TRUE);
1801 /* Processes received key for channel. The received key will be used
1802 to protect the traffic on the channel for now on. Client must receive
1803 the key to the channel before talking on the channel is possible.
1804 This is the key that server has generated, this is not the channel
1805 private key, it is entirely local setting. */
1807 void silc_client_receive_channel_key(SilcClient client,
1808 SilcSocketConnection sock,
1811 unsigned char *id_string, *key, *cipher;
1812 unsigned int tmp_len;
1813 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1815 SilcIDCacheEntry id_cache = NULL;
1816 SilcChannelEntry channel;
1817 SilcChannelKeyPayload payload;
1819 SILC_LOG_DEBUG(("Received key for channel"));
1821 payload = silc_channel_key_payload_parse(packet);
1825 id_string = silc_channel_key_get_id(payload, &tmp_len);
1827 silc_channel_key_payload_free(payload);
1830 id = silc_id_payload_parse_id(id_string, tmp_len);
1833 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
1834 SILC_ID_CHANNEL, &id_cache))
1838 key = silc_channel_key_get_key(payload, &tmp_len);
1839 cipher = silc_channel_key_get_cipher(payload, NULL);
1841 channel = (SilcChannelEntry)id_cache->context;
1842 channel->key_len = tmp_len;
1843 channel->key = silc_calloc(tmp_len, sizeof(*channel->key));
1844 memcpy(channel->key, key, tmp_len);
1846 if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
1847 client->ops->say(client, conn,
1848 "Cannot talk to channel: unsupported cipher %s", cipher);
1851 channel->channel_key->cipher->set_key(channel->channel_key->context,
1854 /* Client is now joined to the channel */
1855 channel->on_channel = TRUE;
1859 silc_channel_key_payload_free(payload);
1862 /* Process received message to a channel (or from a channel, really). This
1863 decrypts the channel message with channel specific key and parses the
1864 channel payload. Finally it displays the message on the screen. */
1866 void silc_client_channel_message(SilcClient client,
1867 SilcSocketConnection sock,
1868 SilcPacketContext *packet)
1870 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1871 SilcBuffer buffer = packet->buffer;
1872 SilcChannelPayload payload = NULL;
1873 SilcChannelID *id = NULL;
1874 SilcChannelEntry channel;
1875 SilcIDCacheEntry id_cache = NULL;
1876 SilcClientID *client_id = NULL;
1881 if (packet->dst_id_type != SILC_ID_CHANNEL)
1884 client_id = silc_id_str2id(packet->src_id, SILC_ID_CLIENT);
1885 id = silc_id_str2id(packet->dst_id, SILC_ID_CHANNEL);
1887 /* Find the channel entry from channels on this connection */
1888 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
1889 SILC_ID_CHANNEL, &id_cache))
1892 channel = (SilcChannelEntry)id_cache->context;
1894 /* Decrypt the channel message payload. Push the IV out of the way,
1895 since it is not encrypted (after pushing buffer->tail has the IV). */
1896 silc_buffer_push_tail(buffer, 16);
1897 channel->channel_key->cipher->decrypt(channel->channel_key->context,
1898 buffer->data, buffer->data,
1899 buffer->len, buffer->tail);
1900 silc_buffer_pull_tail(buffer, 16);
1902 /* Parse the channel message payload */
1903 payload = silc_channel_payload_parse(buffer);
1908 nickname = "[unknown]";
1909 for (i = 0; i < channel->clients_count; i++) {
1910 if (channel->clients[i].client &&
1911 !SILC_ID_CLIENT_COMPARE(channel->clients[i].client->id, client_id))
1912 nickname = channel->clients[i].client->nickname;
1915 /* Pass the message to application */
1916 client->ops->channel_message(client, conn, nickname,
1917 channel->channel_name,
1918 silc_channel_get_data(payload, NULL));
1924 silc_free(client_id);
1926 silc_channel_payload_free(payload);
1929 /* Private message received. This processes the private message and
1930 finally displays it on the screen. */
1932 void silc_client_private_message(SilcClient client,
1933 SilcSocketConnection sock,
1934 SilcPacketContext *packet)
1936 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1937 SilcBuffer buffer = packet->buffer;
1938 unsigned short nick_len;
1939 unsigned char *nickname, *message;
1942 silc_buffer_unformat(buffer,
1943 SILC_STR_UI16_NSTRING_ALLOC(&nickname, &nick_len),
1945 silc_buffer_pull(buffer, 2 + nick_len);
1947 message = silc_calloc(buffer->len + 1, sizeof(char));
1948 memcpy(message, buffer->data, buffer->len);
1950 /* Pass the private message to application */
1951 client->ops->private_message(client, conn, nickname, message);
1953 /* See if we are away (gone). If we are away we will reply to the
1954 sender with the set away message. */
1955 if (conn->away && conn->away->away) {
1956 SilcClientID *remote_id;
1957 SilcClientEntry remote_client;
1958 SilcIDCacheEntry id_cache;
1960 if (packet->src_id_type != SILC_ID_CLIENT)
1963 remote_id = silc_id_str2id(packet->src_id, SILC_ID_CLIENT);
1967 /* If it's me, ignore */
1968 if (!SILC_ID_CLIENT_COMPARE(remote_id, conn->local_id))
1971 /* Check whether we know this client already */
1972 if (!silc_idcache_find_by_id_one(conn->client_cache, remote_id,
1973 SILC_ID_CLIENT, &id_cache))
1975 /* Allocate client entry */
1976 remote_client = silc_calloc(1, sizeof(*remote_client));
1977 remote_client->id = remote_id;
1978 silc_parse_nickname(nickname, &remote_client->nickname,
1979 &remote_client->server, &remote_client->num);
1981 /* Save the client to cache */
1982 silc_idcache_add(conn->client_cache, remote_client->nickname,
1983 SILC_ID_CLIENT, remote_client->id, remote_client,
1986 silc_free(remote_id);
1987 remote_client = (SilcClientEntry)id_cache->context;
1990 /* Send the away message */
1991 silc_client_packet_send_private_message(client, sock, remote_client,
1993 strlen(conn->away->away), TRUE);
1997 memset(message, 0, buffer->len);
1999 silc_free(nickname);
2002 /* Removes a client entry from all channel it has joined. This really is
2003 a performance killer (client_entry should have pointers to channel
2006 void silc_client_remove_from_channels(SilcClient client,
2007 SilcClientConnection conn,
2008 SilcClientEntry client_entry)
2010 SilcIDCacheEntry id_cache;
2011 SilcIDCacheList list;
2012 SilcChannelEntry channel;
2015 if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
2016 SILC_ID_CHANNEL, &list))
2019 silc_idcache_list_first(list, &id_cache);
2020 channel = (SilcChannelEntry)id_cache->context;
2024 /* Remove client from channel */
2025 for (i = 0; i < channel->clients_count; i++) {
2026 if (channel->clients[i].client == client_entry) {
2027 channel->clients[i].client = NULL;
2028 channel->clients_count--;
2033 if (!silc_idcache_list_next(list, &id_cache))
2036 channel = (SilcChannelEntry)id_cache->context;
2039 silc_idcache_list_free(list);
2042 /* Replaces `old' client entries from all channels to `new' client entry.
2043 This can be called for example when nickname changes and old ID entry
2044 is replaced from ID cache with the new one. If the old ID entry is only
2045 updated, then this fucntion needs not to be called. */
2047 void silc_client_replace_from_channels(SilcClient client,
2048 SilcClientConnection conn,
2049 SilcClientEntry old,
2050 SilcClientEntry new)
2052 SilcIDCacheEntry id_cache;
2053 SilcIDCacheList list;
2054 SilcChannelEntry channel;
2057 if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
2058 SILC_ID_CHANNEL, &list))
2061 silc_idcache_list_first(list, &id_cache);
2062 channel = (SilcChannelEntry)id_cache->context;
2066 /* Remove client from channel */
2067 for (i = 0; i < channel->clients_count; i++) {
2068 if (channel->clients[i].client == old) {
2069 channel->clients[i].client = new;
2074 if (!silc_idcache_list_next(list, &id_cache))
2077 channel = (SilcChannelEntry)id_cache->context;
2080 silc_idcache_list_free(list);
2083 /* Parses mode mask and returns the mode as string. */
2085 char *silc_client_chmode(unsigned int mode)
2092 memset(string, 0, sizeof(string));
2094 if (mode & SILC_CHANNEL_MODE_PRIVATE)
2095 strncat(string, "p", 1);
2097 if (mode & SILC_CHANNEL_MODE_SECRET)
2098 strncat(string, "s", 1);
2100 if (mode & SILC_CHANNEL_MODE_PRIVKEY)
2101 strncat(string, "k", 1);
2103 if (mode & SILC_CHANNEL_MODE_INVITE)
2104 strncat(string, "i", 1);
2106 if (mode & SILC_CHANNEL_MODE_TOPIC)
2107 strncat(string, "t", 1);
2109 if (mode & SILC_CHANNEL_MODE_ULIMIT)
2110 strncat(string, "l", 1);
2112 if (mode & SILC_CHANNEL_MODE_PASSPHRASE)
2113 strncat(string, "a", 1);
2115 /* Rest of mode is ignored */
2117 return strdup(string);
2120 /* Parses channel user mode mask and returns te mode as string */
2122 char *silc_client_chumode(unsigned int mode)
2129 memset(string, 0, sizeof(string));
2131 if (mode & SILC_CHANNEL_UMODE_CHANFO)
2132 strncat(string, "f", 1);
2134 if (mode & SILC_CHANNEL_UMODE_CHANOP)
2135 strncat(string, "o", 1);
2137 return strdup(string);
2140 /* Parses channel user mode and returns it as special mode character. */
2142 char *silc_client_chumode_char(unsigned int mode)
2149 memset(string, 0, sizeof(string));
2151 if (mode & SILC_CHANNEL_UMODE_CHANFO)
2152 strncat(string, "*", 1);
2154 if (mode & SILC_CHANNEL_UMODE_CHANOP)
2155 strncat(string, "@", 1);
2157 return strdup(string);