50d5c562e6d1a35da4860ad7d6ce07fba7cfdcc3
[silc.git] / lib / silcclient / client_notify.c
1 /*
2
3   client_notify.c 
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1997 - 2002 Pekka Riikonen
8
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; version 2 of the License.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19 /* $Id$ */
20 /* This file includes the Notify packet handling. Notify packets are
21    important packets sent by the server. They tell different things to the
22    client such as nick changes, mode changes etc. */
23
24 #include "silcincludes.h"
25 #include "silcclient.h"
26 #include "client_internal.h"
27
28 /* Context used for resolving client, channel and server info. */
29 typedef struct {
30   void *packet;
31   void *context;
32   SilcSocketConnection sock;
33 } *SilcClientNotifyResolve;
34
35 SILC_TASK_CALLBACK(silc_client_notify_check_client)
36
37   SilcClientNotifyResolve res = (SilcClientNotifyResolve)context;
38   SilcClient client = res->context;
39   SilcClientConnection conn = res->sock->user_data;
40   SilcClientID *client_id = res->packet;
41   silc_client_get_client_by_id_resolve(client, conn, client_id,
42                                        NULL, NULL, NULL);
43   silc_free(client_id);
44   silc_socket_free(res->sock);
45   silc_free(res);
46 }
47
48 SILC_TASK_CALLBACK(silc_client_notify_del_client_cb)
49 {
50   SilcClientNotifyResolve res = (SilcClientNotifyResolve)context;
51   SilcClient client = res->context;
52   SilcClientConnection conn = res->sock->user_data;
53   SilcClientID *client_id = res->packet;
54   SilcClientEntry client_entry;
55   client_entry = silc_client_get_client_by_id(client, conn, client_id);
56   if (client_entry)
57     silc_client_del_client(client, conn, client_entry);
58   silc_free(client_id);
59   silc_socket_free(res->sock);
60   silc_free(res);
61 }
62
63 /* Called when notify is received and some async operation (such as command)
64    is required before processing the notify message. This calls again the
65    silc_client_notify_by_server and reprocesses the original notify packet. */
66
67 static void silc_client_notify_by_server_pending(void *context, void *context2)
68 {
69   SilcClientNotifyResolve res = (SilcClientNotifyResolve)context;
70   SilcClientCommandReplyContext reply = 
71     (SilcClientCommandReplyContext)context2;
72
73   SILC_LOG_DEBUG(("Start"));
74
75   if (reply && !silc_command_get_status(reply->payload, NULL, NULL))
76     goto out;
77
78   silc_client_notify_by_server(res->context, res->sock, res->packet);
79
80  out:
81   silc_socket_free(res->sock);
82   silc_packet_context_free(res->packet);
83   silc_free(res);
84 }
85
86 /* Resets the channel entry's resolve_cmd_ident after whatever-thing
87    was resolved is completed. */
88
89 static void silc_client_channel_cond(void *context, void *context2)
90 {
91   SilcClientNotifyResolve res = (SilcClientNotifyResolve)context;
92   SilcClient client = res->context;
93   SilcClientConnection conn = res->sock->user_data;
94   SilcChannelID *channel_id = res->packet;
95   SilcChannelEntry channel;
96   channel = silc_client_get_channel_by_id(client, conn, channel_id);
97   if (channel)
98     channel->resolve_cmd_ident = 0;
99   silc_free(channel_id);
100   silc_socket_free(res->sock);
101   silc_free(res);
102 }
103
104 /* Function that starts waiting for the `cmd_ident' to arrive and
105    marks the channel info being resolved.  */
106
107 static void silc_client_channel_set_wait(SilcClient client,
108                                          SilcClientConnection conn,
109                                          SilcChannelEntry channel,
110                                          SilcUInt16 cmd_ident)
111 {
112   SilcClientNotifyResolve res;
113
114   if (!channel->resolve_cmd_ident) {
115     res = silc_calloc(1, sizeof(*res));
116     res->context = client;
117     res->sock = silc_socket_dup(conn->sock);
118     res->packet = silc_id_dup(channel->id, SILC_ID_CHANNEL);
119     silc_client_command_pending(conn, SILC_COMMAND_NONE, cmd_ident,
120                                 silc_client_channel_cond, res);
121     channel->resolve_cmd_ident = cmd_ident;
122   }
123 }
124
125 /* Attaches to the channel's resolving cmd ident and calls the 
126    notify handling with `packet' after it's received. */
127
128 static void silc_client_channel_wait(SilcClient client,
129                                      SilcClientConnection conn,
130                                      SilcChannelEntry channel,
131                                      SilcPacketContext *packet)
132 {
133   SilcClientNotifyResolve res;
134
135   if (!channel->resolve_cmd_ident)
136     return;
137
138   res = silc_calloc(1, sizeof(*res));
139   res->packet = silc_packet_context_dup(packet);
140   res->context = client;
141   res->sock = silc_socket_dup(conn->sock);
142
143   silc_client_command_pending(conn, SILC_COMMAND_NONE,
144                               channel->resolve_cmd_ident,
145                               silc_client_notify_by_server_pending, res);
146 }
147
148 /* Resolve client, channel or server information. */
149
150 static void silc_client_notify_by_server_resolve(SilcClient client,
151                                                  SilcClientConnection conn,
152                                                  SilcPacketContext *packet,
153                                                  SilcIdType id_type,
154                                                  void *id)
155 {
156   SilcClientNotifyResolve res = silc_calloc(1, sizeof(*res));
157   SilcBuffer idp = silc_id_payload_encode(id, id_type);
158
159   res->packet = silc_packet_context_dup(packet);
160   res->context = client;
161   res->sock = silc_socket_dup(conn->sock);
162
163   /* For client resolving use WHOIS, and otherwise use IDENTIFY */
164   if (id_type == SILC_ID_CLIENT) {
165     silc_client_command_register(client, SILC_COMMAND_WHOIS, NULL, NULL,
166                                  silc_client_command_reply_whois_i, 0,
167                                  ++conn->cmd_ident);
168     silc_client_command_send(client, conn, SILC_COMMAND_WHOIS, conn->cmd_ident,
169                              1, 4, idp->data, idp->len);
170     silc_client_command_pending(conn, SILC_COMMAND_WHOIS, conn->cmd_ident,
171                                 silc_client_notify_by_server_pending, res);
172   } else {
173     silc_client_command_register(client, SILC_COMMAND_IDENTIFY, NULL, NULL,
174                                  silc_client_command_reply_identify_i, 0,
175                                  ++conn->cmd_ident);
176     silc_client_command_send(client, conn, SILC_COMMAND_IDENTIFY, 
177                              conn->cmd_ident, 1, 5, idp->data, idp->len);
178     silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY, conn->cmd_ident,
179                                 silc_client_notify_by_server_pending, res);
180   }
181   silc_buffer_free(idp);
182 }
183
184 /* Received notify message from server */
185
186 void silc_client_notify_by_server(SilcClient client,
187                                   SilcSocketConnection sock,
188                                   SilcPacketContext *packet)
189 {
190   SilcBuffer buffer = packet->buffer;
191   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
192   SilcNotifyPayload payload;
193   SilcNotifyType type;
194   SilcArgumentPayload args;
195
196   void *id;
197   SilcIdType id_type;
198   SilcClientID *client_id = NULL;
199   SilcChannelID *channel_id = NULL;
200   SilcServerID *server_id = NULL;
201   SilcClientEntry client_entry = NULL;
202   SilcClientEntry client_entry2 = NULL;
203   SilcChannelEntry channel;
204   SilcChannelUser chu;
205   SilcServerEntry server;
206   unsigned char *tmp;
207   SilcUInt32 tmp_len, mode;
208
209   SILC_LOG_DEBUG(("Start"));
210
211   payload = silc_notify_payload_parse(buffer->data, buffer->len);
212   if (!payload)
213     goto out;
214
215   type = silc_notify_get_type(payload);
216   args = silc_notify_get_args(payload);
217   if (!args)
218     goto out;
219
220   switch(type) {
221   case SILC_NOTIFY_TYPE_NONE:
222     /* Notify application */
223     client->internal->ops->notify(client, conn, type, 
224                                   silc_argument_get_arg_type(args, 1, NULL));
225     break;
226
227   case SILC_NOTIFY_TYPE_INVITE:
228     /* 
229      * Someone invited me to a channel. Find Client and Channel entries
230      * for the application.
231      */
232     
233     SILC_LOG_DEBUG(("Notify: INVITE"));
234
235     /* Get Channel ID */
236     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
237     if (!tmp)
238       goto out;
239
240     channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
241     if (!channel_id)
242       goto out;
243
244     /* Get the channel entry */
245     channel = silc_client_get_channel_by_id(client, conn, channel_id);
246
247     /* Get sender Client ID */
248     tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
249     if (!tmp)
250       goto out;
251
252     client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
253     if (!client_id)
254       goto out;
255
256     /* Find Client entry and if not found query it */
257     client_entry = silc_client_get_client_by_id(client, conn, client_id);
258     if (!client_entry) {
259       silc_client_notify_by_server_resolve(client, conn, packet, 
260                                            SILC_ID_CLIENT, client_id);
261       goto out;
262     }
263
264     /* Get the channel name */
265     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
266     if (!tmp)
267       goto out;
268
269     /* Notify application */
270     client->internal->ops->notify(client, conn, type, channel, tmp, 
271                                   client_entry);
272     break;
273
274   case SILC_NOTIFY_TYPE_JOIN:
275     /*
276      * Someone has joined to a channel. Get their ID and nickname and
277      * cache them for later use.
278      */
279
280     SILC_LOG_DEBUG(("Notify: JOIN"));
281
282     /* Get Client ID */
283     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
284     if (!tmp)
285       goto out;
286
287     client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
288     if (!client_id)
289       goto out;
290
291     /* Find Client entry and if not found query it */
292     client_entry = silc_client_get_client_by_id(client, conn, client_id);
293     if (!client_entry) {
294       silc_client_notify_by_server_resolve(client, conn, packet, 
295                                            SILC_ID_CLIENT, client_id);
296       goto out;
297     }
298
299     /* If nickname or username hasn't been resolved, do so */
300     if (!client_entry->nickname || !client_entry->username) {
301       if (client_entry->status & SILC_CLIENT_STATUS_RESOLVING) {
302         client_entry->status &= ~SILC_CLIENT_STATUS_RESOLVING;
303         goto out;
304       }
305       silc_client_notify_by_server_resolve(client, conn, packet, 
306                                            SILC_ID_CLIENT, client_id);
307       client_entry->status |= SILC_CLIENT_STATUS_RESOLVING;
308       client_entry->resolve_cmd_ident = conn->cmd_ident;
309       goto out;
310     } else {
311       if (client_entry != conn->local_entry)
312         silc_client_nickname_format(client, conn, client_entry);
313     }
314
315     /* Get Channel ID */
316     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
317     if (!tmp)
318       goto out;
319
320     channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
321     if (!channel_id)
322       goto out;
323
324     /* Get channel entry */
325     channel = silc_client_get_channel_by_id(client, conn, channel_id);
326     if (!channel)
327       break;
328
329     /* Join the client to channel */
330     if (!silc_client_on_channel(channel, client_entry)) {
331       chu = silc_calloc(1, sizeof(*chu));
332       chu->client = client_entry;
333       chu->channel = channel;
334       silc_hash_table_add(channel->user_list, client_entry, chu);
335       silc_hash_table_add(client_entry->channels, channel, chu);
336     }
337
338     /* Notify application. The channel entry is sent last as this notify
339        is for channel but application don't know it from the arguments
340        sent by server. */
341     client->internal->ops->notify(client, conn, type, client_entry, channel);
342     break;
343
344   case SILC_NOTIFY_TYPE_LEAVE:
345     /*
346      * Someone has left a channel. We will remove it from the channel but
347      * we'll keep it in the cache in case we'll need it later.
348      */
349     
350     SILC_LOG_DEBUG(("Notify: LEAVE"));
351
352     /* Get Client ID */
353     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
354     if (!tmp)
355       goto out;
356
357     client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
358     if (!client_id)
359       goto out;
360
361     /* Find Client entry */
362     client_entry = 
363       silc_client_get_client_by_id(client, conn, client_id);
364     if (!client_entry)
365       goto out;
366
367     /* Get channel entry */
368     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
369                                 SILC_ID_CHANNEL);
370     if (!channel_id)
371       goto out;
372     channel = silc_client_get_channel_by_id(client, conn, channel_id);
373     if (!channel)
374       break;
375
376     /* Remove client from channel */
377     chu = silc_client_on_channel(channel, client_entry);
378     if (chu) {
379       silc_hash_table_del(client_entry->channels, channel);
380       silc_hash_table_del(channel->user_list, client_entry);
381       silc_free(chu);
382     }
383
384     /* Some client implementations actually quit network by first doing
385        LEAVE and then immediately SIGNOFF.  We'll check for this by doing 
386        check for the client after 5 - 34 seconds.  If it is not valid after
387        that we'll remove the client from cache. */
388     if (!silc_hash_table_count(client_entry->channels)) {
389       SilcClientNotifyResolve res = silc_calloc(1, sizeof(*res));
390       res->context = client;
391       res->sock = silc_socket_dup(conn->sock);
392       res->packet = silc_id_dup(client_id, SILC_ID_CLIENT);
393       silc_schedule_task_add(client->schedule, conn->sock->sock,
394                              silc_client_notify_check_client, res,
395                              (5 + (silc_rng_get_rn16(client->rng) % 29)),
396                              0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
397     }
398
399     /* Notify application. The channel entry is sent last as this notify
400        is for channel but application don't know it from the arguments
401        sent by server. */
402     client->internal->ops->notify(client, conn, type, client_entry, channel);
403     break;
404
405   case SILC_NOTIFY_TYPE_SIGNOFF:
406     /*
407      * Someone left SILC. We'll remove it from all channels and from cache.
408      */
409
410     SILC_LOG_DEBUG(("Notify: SIGNOFF"));
411
412     /* Get Client ID */
413     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
414     if (!tmp)
415       goto out;
416
417     client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
418     if (!client_id)
419       goto out;
420
421     /* Find Client entry */
422     client_entry = 
423       silc_client_get_client_by_id(client, conn, client_id);
424     if (!client_entry)
425       goto out;
426
427     /* Remove from all channels */
428     silc_client_remove_from_channels(client, conn, client_entry);
429
430     /* Remove from cache */
431     silc_idcache_del_by_context(conn->internal->client_cache, client_entry);
432
433     /* Get signoff message */
434     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
435     if (tmp_len > 128)
436       tmp = NULL;
437
438     /* Notify application */
439     client->internal->ops->notify(client, conn, type, client_entry, tmp);
440
441     /* Free data */
442     silc_client_del_client_entry(client, conn, client_entry);
443     break;
444
445   case SILC_NOTIFY_TYPE_TOPIC_SET:
446     /*
447      * Someone set the topic on a channel.
448      */
449
450     SILC_LOG_DEBUG(("Notify: TOPIC_SET"));
451
452     /* Get channel entry */
453     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
454                                 SILC_ID_CHANNEL);
455     if (!channel_id)
456       goto out;
457     channel = silc_client_get_channel_by_id(client, conn, channel_id);
458     if (!channel)
459       break;
460
461     /* Get ID */
462     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
463     if (!tmp)
464       goto out;
465     id = silc_id_payload_parse_id(tmp, tmp_len, &id_type);
466     if (!id)
467       goto out;
468
469     /* Find Client entry */
470     if (id_type == SILC_ID_CLIENT) {
471       /* Find Client entry */
472       client_id = id;
473       client_entry = silc_client_get_client_by_id(client, conn, client_id);
474       if (!client_entry) {
475         silc_client_channel_set_wait(client, conn, channel,
476                                      conn->cmd_ident + 1);
477         silc_client_notify_by_server_resolve(client, conn, packet, 
478                                              SILC_ID_CLIENT, client_id);
479         goto out;
480       }
481     } else if (id_type == SILC_ID_SERVER) {
482       /* Find Server entry */
483       server_id = id;
484       server = silc_client_get_server_by_id(client, conn, server_id);
485       if (!server) {
486         silc_client_channel_set_wait(client, conn, channel,
487                                      conn->cmd_ident + 1);
488         silc_client_notify_by_server_resolve(client, conn, packet, 
489                                              SILC_ID_SERVER, server_id);
490         server = silc_client_add_server(client, conn, NULL, NULL, server_id);
491         if (!server)
492           goto out;
493
494         server->resolve_cmd_ident = conn->cmd_ident;
495         server_id = NULL;
496         goto out;
497       }
498
499       /* If entry being resoled, wait for it before processing this notify */
500       if (server->resolve_cmd_ident) {
501         SilcClientNotifyResolve res = silc_calloc(1, sizeof(*res));
502         res->packet = silc_packet_context_dup(packet);
503         res->context = client;
504         res->sock = silc_socket_dup(conn->sock);
505         silc_client_command_pending(conn, SILC_COMMAND_NONE, 
506                                     server->resolve_cmd_ident,
507                                     silc_client_notify_by_server_pending, res);
508         goto out;
509       }
510       
511       /* Save the pointer to the client_entry pointer */
512       client_entry = (SilcClientEntry)server;
513     } else {
514       /* Find Channel entry */
515       silc_free(channel_id);
516       channel_id = id;
517       client_entry = (SilcClientEntry)
518         silc_client_get_channel_by_id(client, conn, channel_id);
519       if (!client_entry) {
520         silc_client_channel_set_wait(client, conn, channel,
521                                      conn->cmd_ident + 1);
522         silc_client_notify_by_server_resolve(client, conn, packet, 
523                                              SILC_ID_CHANNEL, channel_id);
524         goto out;
525       }
526     }
527
528     /* Get topic */
529     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
530     if (!tmp)
531       goto out;
532
533     /* If information is being resolved for this channel, wait for it */
534     if (channel->resolve_cmd_ident) {
535       silc_client_channel_wait(client, conn, channel, packet);
536       goto out;
537     }
538
539     /* Notify application. The channel entry is sent last as this notify
540        is for channel but application don't know it from the arguments
541        sent by server. */
542     client->internal->ops->notify(client, conn, type, id_type,
543                                   client_entry, tmp, channel);
544
545     break;
546
547   case SILC_NOTIFY_TYPE_NICK_CHANGE:
548     /*
549      * Someone changed their nickname. If we don't have entry for the new
550      * ID we will query it and return here after it's done. After we've
551      * returned we fetch the old entry and free it and notify the 
552      * application.
553      */
554
555     SILC_LOG_DEBUG(("Notify: NICK_CHANGE"));
556
557     /* Get old Client ID */
558     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
559     if (!tmp)
560       goto out;
561
562     client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
563     if (!client_id)
564       goto out;
565
566     /* Ignore my ID */
567     if (conn->local_id && SILC_ID_CLIENT_COMPARE(client_id, conn->local_id))
568       break;
569
570     /* Find old Client entry */
571     client_entry = silc_client_get_client_by_id(client, conn, client_id);
572     if (!client_entry)
573       goto out;
574     silc_free(client_id);
575     client_id = NULL;
576
577     /* Wait for resolving if necessary */
578     if (client_entry->status & SILC_CLIENT_STATUS_RESOLVING) {
579       SilcClientNotifyResolve res = silc_calloc(1, sizeof(*res));
580       res->packet = silc_packet_context_dup(packet);
581       res->context = client;
582       res->sock = silc_socket_dup(conn->sock);
583       silc_client_command_pending(conn, SILC_COMMAND_NONE, 
584                                   client_entry->resolve_cmd_ident,
585                                   silc_client_notify_by_server_pending, res);
586       goto out;
587     }
588
589     client_entry->valid = FALSE;
590
591     /* Get new Client ID */
592     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
593     if (!tmp)
594       goto out;
595
596     client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
597     if (!client_id)
598       goto out;
599
600     /* From protocol version 1.1 we get the new nickname in notify as well,
601        so we don't have to resolve it.  Do it the hard way if server doesn't
602        send it to us. */
603     tmp = silc_argument_get_arg_type(args, 3, NULL);
604     if (tmp) {
605       /* Protocol version 1.1 */
606       char *tmp_nick = NULL;
607
608       /* Check whether nickname changed at all.  It is possible that nick
609          change notify is received but nickname didn't changed, only the
610          ID changes. */
611       if (client->internal->params->nickname_parse)
612         client->internal->params->nickname_parse(client_entry->nickname,
613                                                  &tmp_nick);
614       else
615         tmp_nick = strdup(tmp);
616
617       if (tmp_nick && !strcmp(tmp, tmp_nick)) {
618         /* Nickname didn't change. Update only the ID */
619         silc_idcache_del_by_context(conn->internal->client_cache,
620                                     client_entry);
621         silc_free(client_entry->id);
622         client_entry->id = silc_id_dup(client_id, SILC_ID_CLIENT);
623         silc_idcache_add(conn->internal->client_cache, strdup(tmp),
624                          client_entry->id, client_entry, 0, NULL);
625
626         /* Notify application */
627         client->internal->ops->notify(client, conn, type, 
628                                       client_entry, client_entry);
629         break;
630       }
631       silc_free(tmp_nick);
632
633       /* Create new client entry, and save all old information with the
634          new nickname and client ID */
635       client_entry2 = silc_client_add_client(client, conn, NULL, NULL, 
636                                              client_entry->realname,
637                                              silc_id_dup(client_id, 
638                                                          SILC_ID_CLIENT), 0);
639       if (!client_entry2)
640         goto out;
641
642       if (client_entry->server)
643         client_entry2->server = strdup(client_entry->server);
644       if (client_entry->username)
645         client_entry2->username = strdup(client_entry->username);
646       if (client_entry->hostname)
647         client_entry2->hostname = strdup(client_entry->hostname);
648       silc_client_update_client(client, conn, client_entry2, tmp, NULL, NULL,
649                                 client_entry->mode);
650     } else {
651       /* Protocol version 1.0 */
652
653       /* Find client entry and if not found resolve it */
654       client_entry2 = silc_client_get_client_by_id(client, conn, client_id);
655       if (!client_entry2) {
656         /* Resolve the entry information */
657         silc_client_notify_by_server_resolve(client, conn, packet, 
658                                              SILC_ID_CLIENT, client_id);
659
660         /* Add the new entry even though we resolved it. This is because we
661            want to replace the old entry with the new entry here right now. */
662         client_entry2 = 
663           silc_client_add_client(client, conn, NULL, NULL, NULL, 
664                                  silc_id_dup(client_id, SILC_ID_CLIENT), 
665                                  client_entry->mode);
666
667         /* Replace old ID entry with new one on all channels. */
668         silc_client_replace_from_channels(client, conn, client_entry,
669                                           client_entry2);
670         break;
671       }
672
673       if (client_entry2 != conn->local_entry)
674         silc_client_nickname_format(client, conn, client_entry2);
675     }
676
677     /* Remove the old from cache */
678     silc_idcache_del_by_context(conn->internal->client_cache, client_entry);
679     
680     /* Replace old ID entry with new one on all channels. */
681     silc_client_replace_from_channels(client, conn, client_entry,
682                                       client_entry2);
683
684     /* Notify application */
685     client->internal->ops->notify(client, conn, type, 
686                                   client_entry, client_entry2);
687     
688     /* Free old client entry */
689     silc_client_del_client_entry(client, conn, client_entry);
690
691     break;
692
693   case SILC_NOTIFY_TYPE_CMODE_CHANGE:
694     /*
695      * Someone changed a channel mode
696      */
697
698     SILC_LOG_DEBUG(("Notify: CMODE_CHANGE"));
699
700     /* Get channel entry */
701     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
702                                 SILC_ID_CHANNEL);
703     if (!channel_id)
704       goto out;
705     channel = silc_client_get_channel_by_id(client, conn, channel_id);
706     if (!channel)
707       goto out;
708
709     /* Get ID */
710     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
711     if (!tmp)
712       goto out;
713     id = silc_id_payload_parse_id(tmp, tmp_len, &id_type);
714     if (!id)
715       goto out;
716
717     /* Find Client entry */
718     if (id_type == SILC_ID_CLIENT) {
719       /* Find Client entry */
720       client_id = id;
721       client_entry = silc_client_get_client_by_id(client, conn, client_id);
722       if (!client_entry) {
723         silc_client_channel_set_wait(client, conn, channel,
724                                      conn->cmd_ident + 1);
725         silc_client_notify_by_server_resolve(client, conn, packet, 
726                                              SILC_ID_CLIENT, client_id);
727         goto out;
728       }
729
730       if (!client_entry->nickname) {
731         if (client_entry->status & SILC_CLIENT_STATUS_RESOLVING) {
732           /* Attach to existing resolving */
733           SilcClientNotifyResolve res = silc_calloc(1, sizeof(*res));
734           res->packet = silc_packet_context_dup(packet);
735           res->context = client;
736           res->sock = silc_socket_dup(conn->sock);
737           silc_client_command_pending(conn, SILC_COMMAND_NONE, 
738                                       client_entry->resolve_cmd_ident,
739                                       silc_client_notify_by_server_pending,
740                                       res);
741           goto out;
742         }
743
744         /* Do new resolving */
745         silc_client_channel_set_wait(client, conn, channel,
746                                      conn->cmd_ident + 1);
747         silc_client_notify_by_server_resolve(client, conn, packet, 
748                                              SILC_ID_CLIENT, client_id);
749         goto out;
750       }
751     } else if (id_type == SILC_ID_SERVER) {
752       /* Find Server entry */
753       server_id = id;
754       server = silc_client_get_server_by_id(client, conn, server_id);
755       if (!server) {
756         silc_client_channel_set_wait(client, conn, channel,
757                                      conn->cmd_ident + 1);
758         silc_client_notify_by_server_resolve(client, conn, packet, 
759                                              SILC_ID_SERVER, server_id);
760         server = silc_client_add_server(client, conn, NULL, NULL, server_id);
761         if (!server)
762           goto out;
763
764         server->resolve_cmd_ident = conn->cmd_ident;
765         server_id = NULL;
766         goto out;
767       }
768
769       /* If entry being resoled, wait for it before processing this notify */
770       if (server->resolve_cmd_ident) {
771         SilcClientNotifyResolve res = silc_calloc(1, sizeof(*res));
772         res->packet = silc_packet_context_dup(packet);
773         res->context = client;
774         res->sock = silc_socket_dup(conn->sock);
775         silc_client_command_pending(conn, SILC_COMMAND_NONE, 
776                                     server->resolve_cmd_ident,
777                                     silc_client_notify_by_server_pending, res);
778         goto out;
779       }
780       
781       /* Save the pointer to the client_entry pointer */
782       client_entry = (SilcClientEntry)server;
783     } else {
784       /* Find Channel entry */
785       silc_free(channel_id);
786       channel_id = id;
787       client_entry = (SilcClientEntry)
788         silc_client_get_channel_by_id(client, conn, channel_id);
789       if (!client_entry) {
790         silc_client_channel_set_wait(client, conn, channel,
791                                      conn->cmd_ident + 1);
792         silc_client_notify_by_server_resolve(client, conn, packet, 
793                                              SILC_ID_CHANNEL, channel_id);
794         goto out;
795       }
796     }
797
798     /* Get the mode */
799     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
800     if (!tmp)
801       goto out;
802
803     SILC_GET32_MSB(mode, tmp);
804
805     /* If information is being resolved for this channel, wait for it */
806     if (channel->resolve_cmd_ident) {
807       silc_client_channel_wait(client, conn, channel, packet);
808       goto out;
809     }
810
811     /* Save the new mode */
812     channel->mode = mode;
813
814     /* Get the hmac */
815     tmp = silc_argument_get_arg_type(args, 4, &tmp_len);
816     if (tmp) {
817       unsigned char hash[32];
818
819       if (channel->hmac)
820         silc_hmac_free(channel->hmac);
821       if (!silc_hmac_alloc(tmp, NULL, &channel->hmac))
822         goto out;
823
824       silc_hash_make(silc_hmac_get_hash(channel->hmac), 
825                      channel->key, channel->key_len / 8,
826                      hash);
827       silc_hmac_set_key(channel->hmac, hash, 
828                         silc_hash_len(silc_hmac_get_hash(channel->hmac)));
829       memset(hash, 0, sizeof(hash));
830     }
831
832     /* Notify application. The channel entry is sent last as this notify
833        is for channel but application don't know it from the arguments
834        sent by server. */
835     client->internal->ops->notify(client, conn, type, id_type,
836                                   client_entry, mode, NULL, tmp, channel);
837     break;
838
839   case SILC_NOTIFY_TYPE_CUMODE_CHANGE:
840     /*
841      * Someone changed user's mode on a channel
842      */
843
844     SILC_LOG_DEBUG(("Notify: CUMODE_CHANGE"));
845
846     /* Get channel entry */
847     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
848                                 SILC_ID_CHANNEL);
849     if (!channel_id)
850       goto out;
851     channel = silc_client_get_channel_by_id(client, conn, channel_id);
852     if (!channel)
853       break;
854
855     /* Get ID */
856     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
857     if (!tmp)
858       goto out;
859     id = silc_id_payload_parse_id(tmp, tmp_len, &id_type);
860     if (!id)
861       goto out;
862
863     /* Find Client entry */
864     if (id_type == SILC_ID_CLIENT) {
865       /* Find Client entry */
866       client_id = id;
867       client_entry = silc_client_get_client_by_id(client, conn, client_id);
868       if (!client_entry) {
869         silc_client_channel_set_wait(client, conn, channel,
870                                      conn->cmd_ident + 1);
871         silc_client_notify_by_server_resolve(client, conn, packet, 
872                                              SILC_ID_CLIENT, client_id);
873         goto out;
874       }
875
876       if (!client_entry->nickname) {
877         if (client_entry->status & SILC_CLIENT_STATUS_RESOLVING) {
878           /* Attach to existing resolving */
879           SilcClientNotifyResolve res = silc_calloc(1, sizeof(*res));
880           res->packet = silc_packet_context_dup(packet);
881           res->context = client;
882           res->sock = silc_socket_dup(conn->sock);
883           silc_client_command_pending(conn, SILC_COMMAND_NONE, 
884                                       client_entry->resolve_cmd_ident,
885                                       silc_client_notify_by_server_pending,
886                                       res);
887           goto out;
888         }
889
890         /* Do new resolving */
891         silc_client_channel_set_wait(client, conn, channel,
892                                      conn->cmd_ident + 1);
893         silc_client_notify_by_server_resolve(client, conn, packet, 
894                                              SILC_ID_CLIENT, client_id);
895         goto out;
896       }
897     } else if (id_type == SILC_ID_SERVER) {
898       /* Find Server entry */
899       server_id = id;
900       server = silc_client_get_server_by_id(client, conn, server_id);
901       if (!server) {
902         silc_client_channel_set_wait(client, conn, channel,
903                                      conn->cmd_ident + 1);
904         silc_client_notify_by_server_resolve(client, conn, packet, 
905                                              SILC_ID_SERVER, server_id);
906         server = silc_client_add_server(client, conn, NULL, NULL, server_id);
907         if (!server)
908           goto out;
909
910         server->resolve_cmd_ident = conn->cmd_ident;
911         server_id = NULL;
912         goto out;
913       }
914
915       /* If entry being resoled, wait for it before processing this notify */
916       if (server->resolve_cmd_ident) {
917         SilcClientNotifyResolve res = silc_calloc(1, sizeof(*res));
918         res->packet = silc_packet_context_dup(packet);
919         res->context = client;
920         res->sock = silc_socket_dup(conn->sock);
921         silc_client_command_pending(conn, SILC_COMMAND_NONE, 
922                                     server->resolve_cmd_ident,
923                                     silc_client_notify_by_server_pending, res);
924         goto out;
925       }
926
927       /* Save the pointer to the client_entry pointer */
928       client_entry = (SilcClientEntry)server;
929     } else {
930       /* Find Channel entry */
931       silc_free(channel_id);
932       channel_id = id;
933       client_entry = (SilcClientEntry)
934         silc_client_get_channel_by_id(client, conn, channel_id);
935       if (!client_entry) {
936         silc_client_channel_set_wait(client, conn, channel,
937                                      conn->cmd_ident + 1);
938         silc_client_notify_by_server_resolve(client, conn, packet, 
939                                              SILC_ID_CHANNEL, channel_id);
940         goto out;
941       }
942     }
943
944     /* Get the mode */
945     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
946     if (!tmp)
947       goto out;
948
949     SILC_GET32_MSB(mode, tmp);
950
951     /* If information is being resolved for this channel, wait for it */
952     if (channel->resolve_cmd_ident) {
953       silc_client_channel_wait(client, conn, channel, packet);
954       goto out;
955     }
956
957     /* Get target Client ID */
958     tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
959     if (!tmp)
960       goto out;
961
962     silc_free(client_id);
963     client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
964     if (!client_id)
965       goto out;
966
967     /* Find target Client entry */
968     client_entry2 = 
969       silc_client_get_client_by_id(client, conn, client_id);
970     if (!client_entry2) {
971       silc_client_notify_by_server_resolve(client, conn, packet, 
972                                            SILC_ID_CLIENT, client_id);
973       goto out;
974     }
975
976     /* Save the mode */
977     chu = silc_client_on_channel(channel, client_entry2);
978     if (chu)
979       chu->mode = mode;
980
981     /* Notify application. The channel entry is sent last as this notify
982        is for channel but application don't know it from the arguments
983        sent by server. */
984     client->internal->ops->notify(client, conn, type,
985                                   id_type, client_entry, mode, 
986                                   client_entry2, channel);
987     break;
988
989   case SILC_NOTIFY_TYPE_MOTD:
990     /*
991      * Received Message of the day
992      */
993
994     SILC_LOG_DEBUG(("Notify: MOTD"));
995
996     /* Get motd */
997     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
998     if (!tmp)
999       goto out;
1000     
1001     /* Notify application */
1002     client->internal->ops->notify(client, conn, type, tmp);
1003     break;
1004
1005   case SILC_NOTIFY_TYPE_CHANNEL_CHANGE:
1006     /*
1007      * Router has enforced a new ID to a channel. Let's change the old
1008      * ID to the one provided here.
1009      */
1010
1011     SILC_LOG_DEBUG(("Notify: CHANNEL_CHANGE"));
1012
1013     /* Get the old ID */
1014     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1015     if (!tmp)
1016       goto out;
1017     channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1018     if (!channel_id)
1019       goto out;
1020
1021     /* Get the channel entry */
1022     channel = silc_client_get_channel_by_id(client, conn, channel_id);
1023     if (!channel)
1024       goto out;
1025
1026     silc_free(channel_id);
1027     channel_id = NULL;
1028
1029     /* Get the new ID */
1030     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1031     if (!tmp)
1032       goto out;
1033     channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1034     if (!channel_id)
1035       goto out;
1036
1037     /* Replace the Channel ID */
1038     if (silc_client_replace_channel_id(client, conn, channel, channel_id))
1039       channel_id = NULL;
1040
1041     /* Notify application */
1042     client->internal->ops->notify(client, conn, type, channel, channel);
1043     break;
1044
1045   case SILC_NOTIFY_TYPE_KICKED:
1046     /*
1047      * A client (maybe me) was kicked from a channel
1048      */
1049
1050     SILC_LOG_DEBUG(("Notify: KICKED"));
1051
1052     /* Get Client ID */
1053     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1054     if (!tmp)
1055       goto out;
1056
1057     client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1058     if (!client_id)
1059       goto out;
1060
1061     /* Find Client entry */
1062     client_entry = silc_client_get_client_by_id(client, conn, client_id);
1063     if (!client_entry)
1064       goto out;
1065
1066     /* Get channel entry */
1067     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1068                                 SILC_ID_CHANNEL);
1069     if (!channel_id)
1070       goto out;
1071     channel = silc_client_get_channel_by_id(client, conn, channel_id);
1072     if (!channel)
1073       break;
1074
1075     /* From protocol version 1.1 we get the kicker's client ID as well */
1076     tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
1077     if (tmp) {
1078       silc_free(client_id);
1079       client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1080       if (!client_id)
1081         goto out;
1082
1083       /* Find kicker's client entry and if not found resolve it */
1084       client_entry2 = silc_client_get_client_by_id(client, conn, client_id);
1085       if (!client_entry2) {
1086         silc_client_notify_by_server_resolve(client, conn, packet, 
1087                                              SILC_ID_CLIENT, client_id);
1088         goto out;
1089       } else {
1090         if (client_entry2 != conn->local_entry)
1091           silc_client_nickname_format(client, conn, client_entry2);
1092       }
1093     }
1094
1095     /* Get comment */
1096     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1097
1098     /* Notify application. The channel entry is sent last as this notify
1099        is for channel but application don't know it from the arguments
1100        sent by server. */
1101     client->internal->ops->notify(client, conn, type, client_entry, tmp, 
1102                                   client_entry2, channel);
1103
1104     /* Remove kicked client from channel */
1105     if (client_entry == conn->local_entry) {
1106       /* If I was kicked from channel, remove the channel */
1107       if (conn->current_channel == channel)
1108         conn->current_channel = NULL;
1109       silc_client_del_channel(client, conn, channel);
1110     } else {
1111       chu = silc_client_on_channel(channel, client_entry);
1112       if (chu) {
1113         silc_hash_table_del(client_entry->channels, channel);
1114         silc_hash_table_del(channel->user_list, client_entry);
1115         silc_free(chu);
1116       }
1117
1118       if (!silc_hash_table_count(client_entry->channels)) {
1119         SilcClientNotifyResolve res = silc_calloc(1, sizeof(*res));
1120         res->context = client;
1121         res->sock = silc_socket_dup(conn->sock);
1122         res->packet = silc_id_dup(client_entry->id, SILC_ID_CLIENT);
1123         silc_schedule_task_add(client->schedule, conn->sock->sock,
1124                                silc_client_notify_check_client, res,
1125                                (5 + (silc_rng_get_rn16(client->rng) % 529)),
1126                                0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1127       }
1128     }
1129     break;
1130
1131   case SILC_NOTIFY_TYPE_KILLED:
1132     {
1133       /*
1134        * A client (maybe me) was killed from the network.
1135        */
1136       char *comment;
1137       SilcUInt32 comment_len;
1138
1139       SILC_LOG_DEBUG(("Notify: KILLED"));
1140
1141       /* Get Client ID */
1142       tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1143       if (!tmp)
1144         goto out;
1145
1146       client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1147       if (!client_id)
1148         goto out;
1149
1150       /* Find Client entry */
1151       client_entry = silc_client_get_client_by_id(client, conn, client_id);
1152       if (!client_entry)
1153         goto out;
1154
1155       /* Get comment */
1156       comment = silc_argument_get_arg_type(args, 2, &comment_len);
1157
1158       /* From protocol version 1.1 we get killer's client ID as well */
1159       tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
1160       if (tmp) {
1161         silc_free(client_id);
1162         client_id = NULL;
1163         id = silc_id_payload_parse_id(tmp, tmp_len, &id_type);
1164         if (!id)
1165           goto out;
1166
1167         /* Find Client entry */
1168         if (id_type == SILC_ID_CLIENT) {
1169           /* Find Client entry */
1170           client_id = id;
1171           client_entry2 = silc_client_get_client_by_id(client, conn, 
1172                                                        client_id);
1173           if (!client_entry) {
1174             silc_client_notify_by_server_resolve(client, conn, packet, 
1175                                                  SILC_ID_CLIENT, client_id);
1176             goto out;
1177           }
1178         } else if (id_type == SILC_ID_SERVER) {
1179           /* Find Server entry */
1180           server_id = id;
1181           server = silc_client_get_server_by_id(client, conn, server_id);
1182           if (!server) {
1183             silc_client_notify_by_server_resolve(client, conn, packet, 
1184                                                  SILC_ID_SERVER, server_id);
1185             server = silc_client_add_server(client, conn, NULL, NULL,
1186                                             server_id);
1187             if (!server)
1188               goto out;
1189
1190             server->resolve_cmd_ident = conn->cmd_ident;
1191             server_id = NULL;
1192             goto out;
1193           }
1194
1195           if (server->resolve_cmd_ident) {
1196             SilcClientNotifyResolve res = silc_calloc(1, sizeof(*res));
1197             res->packet = silc_packet_context_dup(packet);
1198             res->context = client;
1199             res->sock = silc_socket_dup(conn->sock);
1200             silc_client_command_pending(conn, SILC_COMMAND_NONE, 
1201                                         server->resolve_cmd_ident,
1202                                         silc_client_notify_by_server_pending,
1203                                         res);
1204             goto out;
1205           }
1206       
1207           /* Save the pointer to the client_entry pointer */
1208           client_entry2 = (SilcClientEntry)server;
1209         } else {
1210           /* Find Channel entry */
1211           channel_id = id;
1212           channel = silc_client_get_channel_by_id(client, conn, channel_id);
1213           if (!channel) {
1214             silc_client_notify_by_server_resolve(client, conn, packet, 
1215                                                  SILC_ID_CHANNEL, channel_id);
1216             goto out;
1217           }
1218           
1219           /* Save the pointer to the client_entry pointer */
1220           client_entry2 = (SilcClientEntry)channel;
1221           silc_free(channel_id);
1222           channel_id = NULL;
1223         }
1224       }
1225
1226       /* Notify application. */
1227       client->internal->ops->notify(client, conn, type, client_entry, 
1228                                     comment, id_type, client_entry2);
1229
1230       if (client_entry != conn->local_entry)
1231         /* Remove the client from all channels and free it */
1232         silc_client_del_client(client, conn, client_entry);
1233     }
1234     break;
1235     
1236   case SILC_NOTIFY_TYPE_SERVER_SIGNOFF:
1237     {
1238       /*
1239        * A server quit the SILC network and some clients must be removed
1240        * from channels as they quit as well.
1241        */
1242       SilcClientEntry *clients = NULL;
1243       SilcUInt32 clients_count = 0;
1244       int i;
1245
1246       SILC_LOG_DEBUG(("Notify: SIGNOFF"));
1247
1248       for (i = 1; i < silc_argument_get_arg_num(args); i++) {
1249         /* Get Client ID */
1250         tmp = silc_argument_get_arg_type(args, i + 1, &tmp_len);
1251         if (tmp) {
1252           client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1253           if (!client_id)
1254             goto out;
1255           
1256           /* Get the client entry */
1257           client_entry = silc_client_get_client_by_id(client, conn, client_id);
1258           if (client_entry) {
1259             clients = silc_realloc(clients, sizeof(*clients) * 
1260                                    (clients_count + 1));
1261             clients[clients_count] = client_entry;
1262             clients_count++;
1263           }
1264           silc_free(client_id);
1265         }
1266       }
1267       client_id = NULL;
1268
1269       /* Notify application. We don't keep server entries so the server
1270          entry is returned as NULL. The client's are returned as array
1271          of SilcClientEntry pointers. */
1272       client->internal->ops->notify(client, conn, type, NULL, 
1273                                     clients, clients_count);
1274
1275       for (i = 0; i < clients_count; i++) {
1276         /* Remove client from all channels */
1277         client_entry = clients[i];
1278         if (client_entry == conn->local_entry)
1279           continue;
1280
1281         /* Remove the client from all channels and free it */
1282         silc_client_del_client(client, conn, client_entry);
1283       }
1284       silc_free(clients);
1285
1286     }
1287     break;
1288
1289   case SILC_NOTIFY_TYPE_ERROR:
1290     {
1291       /*
1292        * Some has occurred and server is notifying us about it.
1293        */
1294       SilcStatus error;
1295
1296       tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1297       if (!tmp && tmp_len != 1)
1298         goto out;
1299       error = (SilcStatus)tmp[0];
1300
1301       SILC_LOG_DEBUG(("Notify: ERROR (%d)", error));
1302
1303       if (error == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) {
1304         tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1305         if (tmp) {
1306           client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1307           if (!client_id)
1308             goto out;
1309           client_entry = silc_client_get_client_by_id(client, conn,
1310                                                       client_id);
1311           if (client_entry)
1312             silc_client_del_client(client, conn, client_entry);
1313         }
1314       }
1315
1316       /* Notify application. */
1317       client->internal->ops->notify(client, conn, type, error);
1318     }
1319     break;
1320
1321   case SILC_NOTIFY_TYPE_WATCH:
1322     {
1323       /*
1324        * Received notify about some client we are watching
1325        */
1326       SilcNotifyType notify = 0;
1327       bool del_client = FALSE;
1328
1329       SILC_LOG_DEBUG(("Notify: WATCH"));
1330
1331       /* Get sender Client ID */
1332       tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1333       if (!tmp)
1334         goto out;
1335       client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1336       if (!client_id)
1337         goto out;
1338
1339       /* Find Client entry and if not found query it */
1340       client_entry = silc_client_get_client_by_id(client, conn, client_id);
1341       if (!client_entry) {
1342         silc_client_notify_by_server_resolve(client, conn, packet, 
1343                                              SILC_ID_CLIENT, client_id);
1344         goto out;
1345       }
1346
1347       /* Get user mode */
1348       tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
1349       if (!tmp || tmp_len != 4)
1350         goto out;
1351       SILC_GET32_MSB(mode, tmp);
1352
1353       /* Get notify type */
1354       tmp = silc_argument_get_arg_type(args, 4, &tmp_len);
1355       if (tmp && tmp_len != 2)
1356         goto out;
1357       if (tmp)
1358         SILC_GET16_MSB(notify, tmp);
1359
1360       /* Get nickname */
1361       tmp = silc_argument_get_arg_type(args, 2, NULL);
1362       if (tmp) {
1363         char *tmp_nick = NULL;
1364
1365         if (client->internal->params->nickname_parse)
1366           client->internal->params->nickname_parse(client_entry->nickname,
1367                                                    &tmp_nick);
1368         else
1369           tmp_nick = strdup(tmp);
1370
1371         /* If same nick, the client was new to us and has become "present"
1372            to network.  Send NULL as nick to application. */
1373         if (tmp_nick && !strcmp(tmp, tmp_nick))
1374           tmp = NULL;
1375
1376         silc_free(tmp_nick);
1377       }
1378
1379       /* Notify application. */
1380       client->internal->ops->notify(client, conn, type, client_entry,
1381                                     tmp, mode, notify);
1382
1383       client_entry->mode = mode;
1384
1385       /* If nickname was changed, remove the client entry unless the
1386          client is on some channel */
1387       if (tmp && notify == SILC_NOTIFY_TYPE_NICK_CHANGE &&
1388           !silc_hash_table_count(client_entry->channels))
1389         del_client = TRUE;
1390       else if (notify == SILC_NOTIFY_TYPE_SIGNOFF ||
1391                notify == SILC_NOTIFY_TYPE_SERVER_SIGNOFF ||
1392                notify == SILC_NOTIFY_TYPE_KILLED)
1393         del_client = TRUE;
1394
1395       if (del_client) {
1396         SilcClientNotifyResolve res = silc_calloc(1, sizeof(*res));
1397         res->context = client;
1398         res->sock = silc_socket_dup(conn->sock);
1399         res->packet = client_id;
1400         client_id = NULL;
1401         silc_schedule_task_add(client->schedule, conn->sock->sock,
1402                                silc_client_notify_del_client_cb, res,
1403                                1, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1404       }
1405     }
1406     break;
1407
1408   default:
1409     break;
1410   }
1411
1412  out:
1413   silc_notify_payload_free(payload);
1414   silc_free(client_id);
1415   silc_free(channel_id);
1416   silc_free(server_id);
1417 }