Attach to existing client resolvings in CUMODE and CMODE notifys.
[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->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
576     /* Wait for resolving if necessary */
577     if (client_entry->status & SILC_CLIENT_STATUS_RESOLVING) {
578       SilcClientNotifyResolve res = silc_calloc(1, sizeof(*res));
579       res->packet = silc_packet_context_dup(packet);
580       res->context = client;
581       res->sock = silc_socket_dup(conn->sock);
582       silc_client_command_pending(conn, SILC_COMMAND_NONE, 
583                                   client_entry->resolve_cmd_ident,
584                                   silc_client_notify_by_server_pending, res);
585       goto out;
586     }
587
588     client_entry->valid = FALSE;
589
590     /* Get new Client ID */
591     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
592     if (!tmp)
593       goto out;
594
595     client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
596     if (!client_id)
597       goto out;
598
599     /* From protocol version 1.1 we get the new nickname in notify as well,
600        so we don't have to resolve it.  Do it the hard way if server doesn't
601        send it to us. */
602     tmp = silc_argument_get_arg_type(args, 3, NULL);
603     if (tmp) {
604       /* Protocol version 1.1 */
605       char *tmp_nick = NULL;
606
607       /* Check whether nickname changed at all.  It is possible that nick
608          change notify is received but nickname didn't changed, only the
609          ID changes. */
610       if (client->internal->params->nickname_parse)
611         client->internal->params->nickname_parse(client_entry->nickname,
612                                                  &tmp_nick);
613       else
614         tmp_nick = strdup(tmp);
615
616       if (tmp_nick && !strcmp(tmp, tmp_nick)) {
617         /* Nickname didn't change. Update only the ID */
618         silc_idcache_del_by_context(conn->client_cache, client_entry);
619         silc_free(client_entry->id);
620         client_entry->id = silc_id_dup(client_id, SILC_ID_CLIENT);
621         silc_idcache_add(conn->client_cache, strdup(tmp),
622                          client_entry->id, client_entry, 0, NULL);
623
624         /* Notify application */
625         client->internal->ops->notify(client, conn, type, 
626                                       client_entry, client_entry);
627         break;
628       }
629       silc_free(tmp_nick);
630
631       /* Create new client entry, and save all old information with the
632          new nickname and client ID */
633       client_entry2 = silc_client_add_client(client, conn, NULL, NULL, 
634                                              client_entry->realname,
635                                              silc_id_dup(client_id, 
636                                                          SILC_ID_CLIENT), 0);
637       if (!client_entry2)
638         goto out;
639
640       if (client_entry->server)
641         client_entry2->server = strdup(client_entry->server);
642       if (client_entry->username)
643         client_entry2->username = strdup(client_entry->username);
644       if (client_entry->hostname)
645         client_entry2->hostname = strdup(client_entry->hostname);
646       silc_client_update_client(client, conn, client_entry2, tmp, NULL, NULL,
647                                 client_entry->mode);
648     } else {
649       /* Protocol version 1.0 */
650
651       /* Find client entry and if not found resolve it */
652       client_entry2 = silc_client_get_client_by_id(client, conn, client_id);
653       if (!client_entry2) {
654         /* Resolve the entry information */
655         silc_client_notify_by_server_resolve(client, conn, packet, 
656                                              SILC_ID_CLIENT, client_id);
657
658         /* Add the new entry even though we resolved it. This is because we
659            want to replace the old entry with the new entry here right now. */
660         client_entry2 = 
661           silc_client_add_client(client, conn, NULL, NULL, NULL, 
662                                  silc_id_dup(client_id, SILC_ID_CLIENT), 
663                                  client_entry->mode);
664
665         /* Replace old ID entry with new one on all channels. */
666         silc_client_replace_from_channels(client, conn, client_entry,
667                                           client_entry2);
668         break;
669       }
670
671       if (client_entry2 != conn->local_entry)
672         silc_client_nickname_format(client, conn, client_entry2);
673     }
674
675     /* Remove the old from cache */
676     silc_idcache_del_by_context(conn->client_cache, client_entry);
677     
678     /* Replace old ID entry with new one on all channels. */
679     silc_client_replace_from_channels(client, conn, client_entry,
680                                       client_entry2);
681
682     /* Notify application */
683     client->internal->ops->notify(client, conn, type, 
684                                   client_entry, client_entry2);
685     
686     /* Free old client entry */
687     silc_client_del_client_entry(client, conn, client_entry);
688
689     break;
690
691   case SILC_NOTIFY_TYPE_CMODE_CHANGE:
692     /*
693      * Someone changed a channel mode
694      */
695
696     SILC_LOG_DEBUG(("Notify: CMODE_CHANGE"));
697
698     /* Get channel entry */
699     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
700                                 SILC_ID_CHANNEL);
701     if (!channel_id)
702       goto out;
703     channel = silc_client_get_channel_by_id(client, conn, channel_id);
704     if (!channel)
705       goto out;
706
707     /* Get ID */
708     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
709     if (!tmp)
710       goto out;
711     id = silc_id_payload_parse_id(tmp, tmp_len, &id_type);
712     if (!id)
713       goto out;
714
715     /* Find Client entry */
716     if (id_type == SILC_ID_CLIENT) {
717       /* Find Client entry */
718       client_id = id;
719       client_entry = silc_client_get_client_by_id(client, conn, client_id);
720       if (!client_entry) {
721         silc_client_channel_set_wait(client, conn, channel,
722                                      conn->cmd_ident + 1);
723         silc_client_notify_by_server_resolve(client, conn, packet, 
724                                              SILC_ID_CLIENT, client_id);
725         goto out;
726       }
727
728       if (!client_entry->nickname) {
729         if (client_entry->status & SILC_CLIENT_STATUS_RESOLVING) {
730           /* Attach to existing resolving */
731           SilcClientNotifyResolve res = silc_calloc(1, sizeof(*res));
732           res->packet = silc_packet_context_dup(packet);
733           res->context = client;
734           res->sock = silc_socket_dup(conn->sock);
735           silc_client_command_pending(conn, SILC_COMMAND_NONE, 
736                                       client_entry->resolve_cmd_ident,
737                                       silc_client_notify_by_server_pending,
738                                       res);
739           goto out;
740         }
741
742         /* Do new resolving */
743         silc_client_channel_set_wait(client, conn, channel,
744                                      conn->cmd_ident + 1);
745         silc_client_notify_by_server_resolve(client, conn, packet, 
746                                              SILC_ID_CLIENT, client_id);
747         goto out;
748       }
749     } else if (id_type == SILC_ID_SERVER) {
750       /* Find Server entry */
751       server_id = id;
752       server = silc_client_get_server_by_id(client, conn, server_id);
753       if (!server) {
754         silc_client_channel_set_wait(client, conn, channel,
755                                      conn->cmd_ident + 1);
756         silc_client_notify_by_server_resolve(client, conn, packet, 
757                                              SILC_ID_SERVER, server_id);
758         server = silc_client_add_server(client, conn, NULL, NULL, server_id);
759         if (!server)
760           goto out;
761
762         server->resolve_cmd_ident = conn->cmd_ident;
763         server_id = NULL;
764         goto out;
765       }
766
767       /* If entry being resoled, wait for it before processing this notify */
768       if (server->resolve_cmd_ident) {
769         SilcClientNotifyResolve res = silc_calloc(1, sizeof(*res));
770         res->packet = silc_packet_context_dup(packet);
771         res->context = client;
772         res->sock = silc_socket_dup(conn->sock);
773         silc_client_command_pending(conn, SILC_COMMAND_NONE, 
774                                     server->resolve_cmd_ident,
775                                     silc_client_notify_by_server_pending, res);
776         goto out;
777       }
778       
779       /* Save the pointer to the client_entry pointer */
780       client_entry = (SilcClientEntry)server;
781     } else {
782       /* Find Channel entry */
783       silc_free(channel_id);
784       channel_id = id;
785       client_entry = (SilcClientEntry)
786         silc_client_get_channel_by_id(client, conn, channel_id);
787       if (!client_entry) {
788         silc_client_channel_set_wait(client, conn, channel,
789                                      conn->cmd_ident + 1);
790         silc_client_notify_by_server_resolve(client, conn, packet, 
791                                              SILC_ID_CHANNEL, channel_id);
792         goto out;
793       }
794     }
795
796     /* Get the mode */
797     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
798     if (!tmp)
799       goto out;
800
801     SILC_GET32_MSB(mode, tmp);
802
803     /* If information is being resolved for this channel, wait for it */
804     if (channel->resolve_cmd_ident) {
805       silc_client_channel_wait(client, conn, channel, packet);
806       goto out;
807     }
808
809     /* Save the new mode */
810     channel->mode = mode;
811
812     /* Get the hmac */
813     tmp = silc_argument_get_arg_type(args, 4, &tmp_len);
814     if (tmp) {
815       unsigned char hash[32];
816
817       if (channel->hmac)
818         silc_hmac_free(channel->hmac);
819       if (!silc_hmac_alloc(tmp, NULL, &channel->hmac))
820         goto out;
821
822       silc_hash_make(silc_hmac_get_hash(channel->hmac), 
823                      channel->key, channel->key_len / 8,
824                      hash);
825       silc_hmac_set_key(channel->hmac, hash, 
826                         silc_hash_len(silc_hmac_get_hash(channel->hmac)));
827       memset(hash, 0, sizeof(hash));
828     }
829
830     /* Notify application. The channel entry is sent last as this notify
831        is for channel but application don't know it from the arguments
832        sent by server. */
833     client->internal->ops->notify(client, conn, type, id_type,
834                                   client_entry, mode, NULL, tmp, channel);
835     break;
836
837   case SILC_NOTIFY_TYPE_CUMODE_CHANGE:
838     /*
839      * Someone changed user's mode on a channel
840      */
841
842     SILC_LOG_DEBUG(("Notify: CUMODE_CHANGE"));
843
844     /* Get channel entry */
845     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
846                                 SILC_ID_CHANNEL);
847     if (!channel_id)
848       goto out;
849     channel = silc_client_get_channel_by_id(client, conn, channel_id);
850     if (!channel)
851       break;
852
853     /* Get ID */
854     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
855     if (!tmp)
856       goto out;
857     id = silc_id_payload_parse_id(tmp, tmp_len, &id_type);
858     if (!id)
859       goto out;
860
861     /* Find Client entry */
862     if (id_type == SILC_ID_CLIENT) {
863       /* Find Client entry */
864       client_id = id;
865       client_entry = silc_client_get_client_by_id(client, conn, client_id);
866       if (!client_entry) {
867         silc_client_channel_set_wait(client, conn, channel,
868                                      conn->cmd_ident + 1);
869         silc_client_notify_by_server_resolve(client, conn, packet, 
870                                              SILC_ID_CLIENT, client_id);
871         goto out;
872       }
873
874       if (!client_entry->nickname) {
875         if (client_entry->status & SILC_CLIENT_STATUS_RESOLVING) {
876           /* Attach to existing resolving */
877           SilcClientNotifyResolve res = silc_calloc(1, sizeof(*res));
878           res->packet = silc_packet_context_dup(packet);
879           res->context = client;
880           res->sock = silc_socket_dup(conn->sock);
881           silc_client_command_pending(conn, SILC_COMMAND_NONE, 
882                                       client_entry->resolve_cmd_ident,
883                                       silc_client_notify_by_server_pending,
884                                       res);
885           goto out;
886         }
887
888         /* Do new resolving */
889         silc_client_channel_set_wait(client, conn, channel,
890                                      conn->cmd_ident + 1);
891         silc_client_notify_by_server_resolve(client, conn, packet, 
892                                              SILC_ID_CLIENT, client_id);
893         goto out;
894       }
895     } else if (id_type == SILC_ID_SERVER) {
896       /* Find Server entry */
897       server_id = id;
898       server = silc_client_get_server_by_id(client, conn, server_id);
899       if (!server) {
900         silc_client_channel_set_wait(client, conn, channel,
901                                      conn->cmd_ident + 1);
902         silc_client_notify_by_server_resolve(client, conn, packet, 
903                                              SILC_ID_SERVER, server_id);
904         server = silc_client_add_server(client, conn, NULL, NULL, server_id);
905         if (!server)
906           goto out;
907
908         server->resolve_cmd_ident = conn->cmd_ident;
909         server_id = NULL;
910         goto out;
911       }
912
913       /* If entry being resoled, wait for it before processing this notify */
914       if (server->resolve_cmd_ident) {
915         SilcClientNotifyResolve res = silc_calloc(1, sizeof(*res));
916         res->packet = silc_packet_context_dup(packet);
917         res->context = client;
918         res->sock = silc_socket_dup(conn->sock);
919         silc_client_command_pending(conn, SILC_COMMAND_NONE, 
920                                     server->resolve_cmd_ident,
921                                     silc_client_notify_by_server_pending, res);
922         goto out;
923       }
924
925       /* Save the pointer to the client_entry pointer */
926       client_entry = (SilcClientEntry)server;
927     } else {
928       /* Find Channel entry */
929       silc_free(channel_id);
930       channel_id = id;
931       client_entry = (SilcClientEntry)
932         silc_client_get_channel_by_id(client, conn, channel_id);
933       if (!client_entry) {
934         silc_client_channel_set_wait(client, conn, channel,
935                                      conn->cmd_ident + 1);
936         silc_client_notify_by_server_resolve(client, conn, packet, 
937                                              SILC_ID_CHANNEL, channel_id);
938         goto out;
939       }
940     }
941
942     /* Get the mode */
943     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
944     if (!tmp)
945       goto out;
946
947     SILC_GET32_MSB(mode, tmp);
948
949     /* If information is being resolved for this channel, wait for it */
950     if (channel->resolve_cmd_ident) {
951       silc_client_channel_wait(client, conn, channel, packet);
952       goto out;
953     }
954
955     /* Get target Client ID */
956     tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
957     if (!tmp)
958       goto out;
959
960     silc_free(client_id);
961     client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
962     if (!client_id)
963       goto out;
964
965     /* Find target Client entry */
966     client_entry2 = 
967       silc_client_get_client_by_id(client, conn, client_id);
968     if (!client_entry2) {
969       silc_client_notify_by_server_resolve(client, conn, packet, 
970                                            SILC_ID_CLIENT, client_id);
971       goto out;
972     }
973
974     /* Save the mode */
975     chu = silc_client_on_channel(channel, client_entry2);
976     if (chu)
977       chu->mode = mode;
978
979     /* Notify application. The channel entry is sent last as this notify
980        is for channel but application don't know it from the arguments
981        sent by server. */
982     client->internal->ops->notify(client, conn, type,
983                                   id_type, client_entry, mode, 
984                                   client_entry2, channel);
985     break;
986
987   case SILC_NOTIFY_TYPE_MOTD:
988     /*
989      * Received Message of the day
990      */
991
992     SILC_LOG_DEBUG(("Notify: MOTD"));
993
994     /* Get motd */
995     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
996     if (!tmp)
997       goto out;
998     
999     /* Notify application */
1000     client->internal->ops->notify(client, conn, type, tmp);
1001     break;
1002
1003   case SILC_NOTIFY_TYPE_CHANNEL_CHANGE:
1004     /*
1005      * Router has enforced a new ID to a channel. Let's change the old
1006      * ID to the one provided here.
1007      */
1008
1009     SILC_LOG_DEBUG(("Notify: CHANNEL_CHANGE"));
1010
1011     /* Get the old ID */
1012     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1013     if (!tmp)
1014       goto out;
1015     channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1016     if (!channel_id)
1017       goto out;
1018
1019     /* Get the channel entry */
1020     channel = silc_client_get_channel_by_id(client, conn, channel_id);
1021     if (!channel)
1022       goto out;
1023
1024     silc_free(channel_id);
1025
1026     /* Get the new ID */
1027     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1028     if (!tmp)
1029       goto out;
1030     channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1031     if (!channel_id)
1032       goto out;
1033
1034     /* Replace the Channel ID */
1035     if (silc_client_replace_channel_id(client, conn, channel, channel_id))
1036       channel_id = NULL;
1037
1038     /* Notify application */
1039     client->internal->ops->notify(client, conn, type, channel, channel);
1040     break;
1041
1042   case SILC_NOTIFY_TYPE_KICKED:
1043     /*
1044      * A client (maybe me) was kicked from a channel
1045      */
1046
1047     SILC_LOG_DEBUG(("Notify: KICKED"));
1048
1049     /* Get Client ID */
1050     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1051     if (!tmp)
1052       goto out;
1053
1054     client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1055     if (!client_id)
1056       goto out;
1057
1058     /* Find Client entry */
1059     client_entry = silc_client_get_client_by_id(client, conn, client_id);
1060     if (!client_entry)
1061       goto out;
1062
1063     /* Get channel entry */
1064     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1065                                 SILC_ID_CHANNEL);
1066     if (!channel_id)
1067       goto out;
1068     channel = silc_client_get_channel_by_id(client, conn, channel_id);
1069     if (!channel)
1070       break;
1071
1072     /* From protocol version 1.1 we get the kicker's client ID as well */
1073     tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
1074     if (tmp) {
1075       silc_free(client_id);
1076       client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1077       if (!client_id)
1078         goto out;
1079
1080       /* Find kicker's client entry and if not found resolve it */
1081       client_entry2 = silc_client_get_client_by_id(client, conn, client_id);
1082       if (!client_entry2) {
1083         silc_client_notify_by_server_resolve(client, conn, packet, 
1084                                              SILC_ID_CLIENT, client_id);
1085         goto out;
1086       } else {
1087         if (client_entry2 != conn->local_entry)
1088           silc_client_nickname_format(client, conn, client_entry2);
1089       }
1090     }
1091
1092     /* Get comment */
1093     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1094
1095     /* Notify application. The channel entry is sent last as this notify
1096        is for channel but application don't know it from the arguments
1097        sent by server. */
1098     client->internal->ops->notify(client, conn, type, client_entry, tmp, 
1099                                   client_entry2, channel);
1100
1101     /* Remove kicked client from channel */
1102     if (client_entry == conn->local_entry) {
1103       /* If I was kicked from channel, remove the channel */
1104       if (conn->current_channel == channel)
1105         conn->current_channel = NULL;
1106       silc_client_del_channel(client, conn, channel);
1107     } else {
1108       chu = silc_client_on_channel(channel, client_entry);
1109       if (chu) {
1110         silc_hash_table_del(client_entry->channels, channel);
1111         silc_hash_table_del(channel->user_list, client_entry);
1112         silc_free(chu);
1113       }
1114
1115       if (!silc_hash_table_count(client_entry->channels)) {
1116         SilcClientNotifyResolve res = silc_calloc(1, sizeof(*res));
1117         res->context = client;
1118         res->sock = silc_socket_dup(conn->sock);
1119         res->packet = silc_id_dup(client_entry->id, SILC_ID_CLIENT);
1120         silc_schedule_task_add(client->schedule, conn->sock->sock,
1121                                silc_client_notify_check_client, res,
1122                                (5 + (silc_rng_get_rn16(client->rng) % 529)),
1123                                0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1124       }
1125     }
1126     break;
1127
1128   case SILC_NOTIFY_TYPE_KILLED:
1129     {
1130       /*
1131        * A client (maybe me) was killed from the network.
1132        */
1133       char *comment;
1134       SilcUInt32 comment_len;
1135
1136       SILC_LOG_DEBUG(("Notify: KILLED"));
1137
1138       /* Get Client ID */
1139       tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1140       if (!tmp)
1141         goto out;
1142
1143       client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1144       if (!client_id)
1145         goto out;
1146
1147       /* Find Client entry */
1148       client_entry = silc_client_get_client_by_id(client, conn, client_id);
1149       if (!client_entry)
1150         goto out;
1151
1152       /* Get comment */
1153       comment = silc_argument_get_arg_type(args, 2, &comment_len);
1154
1155       /* From protocol version 1.1 we get killer's client ID as well */
1156       tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
1157       if (tmp) {
1158         silc_free(client_id);
1159         id = silc_id_payload_parse_id(tmp, tmp_len, &id_type);
1160         if (!id)
1161           goto out;
1162
1163         /* Find Client entry */
1164         if (id_type == SILC_ID_CLIENT) {
1165           /* Find Client entry */
1166           client_id = id;
1167           client_entry2 = silc_client_get_client_by_id(client, conn, 
1168                                                        client_id);
1169           if (!client_entry) {
1170             silc_client_notify_by_server_resolve(client, conn, packet, 
1171                                                  SILC_ID_CLIENT, client_id);
1172             goto out;
1173           }
1174         } else if (id_type == SILC_ID_SERVER) {
1175           /* Find Server entry */
1176           server_id = id;
1177           server = silc_client_get_server_by_id(client, conn, server_id);
1178           if (!server) {
1179             silc_client_notify_by_server_resolve(client, conn, packet, 
1180                                                  SILC_ID_SERVER, server_id);
1181             server = silc_client_add_server(client, conn, NULL, NULL,
1182                                             server_id);
1183             if (!server)
1184               goto out;
1185
1186             server->resolve_cmd_ident = conn->cmd_ident;
1187             server_id = NULL;
1188             goto out;
1189           }
1190
1191           if (server->resolve_cmd_ident) {
1192             SilcClientNotifyResolve res = silc_calloc(1, sizeof(*res));
1193             res->packet = silc_packet_context_dup(packet);
1194             res->context = client;
1195             res->sock = silc_socket_dup(conn->sock);
1196             silc_client_command_pending(conn, SILC_COMMAND_NONE, 
1197                                         server->resolve_cmd_ident,
1198                                         silc_client_notify_by_server_pending,
1199                                         res);
1200             goto out;
1201           }
1202       
1203           /* Save the pointer to the client_entry pointer */
1204           client_entry2 = (SilcClientEntry)server;
1205         } else {
1206           /* Find Channel entry */
1207           channel_id = id;
1208           channel = silc_client_get_channel_by_id(client, conn, channel_id);
1209           if (!channel) {
1210             silc_client_notify_by_server_resolve(client, conn, packet, 
1211                                                  SILC_ID_CHANNEL, channel_id);
1212             goto out;
1213           }
1214           
1215           /* Save the pointer to the client_entry pointer */
1216           client_entry2 = (SilcClientEntry)channel;
1217           silc_free(channel_id);
1218           channel_id = NULL;
1219         }
1220       }
1221
1222       /* Notify application. */
1223       client->internal->ops->notify(client, conn, type, client_entry, 
1224                                     comment, id_type, client_entry2);
1225
1226       if (client_entry != conn->local_entry)
1227         /* Remove the client from all channels and free it */
1228         silc_client_del_client(client, conn, client_entry);
1229     }
1230     break;
1231     
1232   case SILC_NOTIFY_TYPE_SERVER_SIGNOFF:
1233     {
1234       /*
1235        * A server quit the SILC network and some clients must be removed
1236        * from channels as they quit as well.
1237        */
1238       SilcClientEntry *clients = NULL;
1239       SilcUInt32 clients_count = 0;
1240       int i;
1241
1242       SILC_LOG_DEBUG(("Notify: SIGNOFF"));
1243
1244       for (i = 1; i < silc_argument_get_arg_num(args); i++) {
1245         /* Get Client ID */
1246         tmp = silc_argument_get_arg_type(args, i + 1, &tmp_len);
1247         if (tmp) {
1248           client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1249           if (!client_id)
1250             goto out;
1251           
1252           /* Get the client entry */
1253           client_entry = silc_client_get_client_by_id(client, conn, client_id);
1254           if (client_entry) {
1255             clients = silc_realloc(clients, sizeof(*clients) * 
1256                                    (clients_count + 1));
1257             clients[clients_count] = client_entry;
1258             clients_count++;
1259           }
1260           silc_free(client_id);
1261         }
1262       }
1263       client_id = NULL;
1264
1265       /* Notify application. We don't keep server entries so the server
1266          entry is returned as NULL. The client's are returned as array
1267          of SilcClientEntry pointers. */
1268       client->internal->ops->notify(client, conn, type, NULL, 
1269                                     clients, clients_count);
1270
1271       for (i = 0; i < clients_count; i++) {
1272         /* Remove client from all channels */
1273         client_entry = clients[i];
1274         if (client_entry == conn->local_entry)
1275           continue;
1276
1277         /* Remove the client from all channels and free it */
1278         silc_client_del_client(client, conn, client_entry);
1279       }
1280       silc_free(clients);
1281
1282     }
1283     break;
1284
1285   case SILC_NOTIFY_TYPE_ERROR:
1286     {
1287       /*
1288        * Some has occurred and server is notifying us about it.
1289        */
1290       SilcStatus error;
1291
1292       tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1293       if (!tmp && tmp_len != 1)
1294         goto out;
1295       error = (SilcStatus)tmp[0];
1296
1297       SILC_LOG_DEBUG(("Notify: ERROR (%d)", error));
1298
1299       if (error == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) {
1300         tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1301         if (tmp) {
1302           client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1303           if (!client_id)
1304             goto out;
1305           client_entry = silc_client_get_client_by_id(client, conn,
1306                                                       client_id);
1307           if (client_entry)
1308             silc_client_del_client(client, conn, client_entry);
1309         }
1310       }
1311
1312       /* Notify application. */
1313       client->internal->ops->notify(client, conn, type, error);
1314     }
1315     break;
1316
1317   case SILC_NOTIFY_TYPE_WATCH:
1318     {
1319       /*
1320        * Received notify about some client we are watching
1321        */
1322       SilcNotifyType notify = 0;
1323       bool del_client = FALSE;
1324
1325       SILC_LOG_DEBUG(("Notify: WATCH"));
1326
1327       /* Get sender Client ID */
1328       tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1329       if (!tmp)
1330         goto out;
1331       client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1332       if (!client_id)
1333         goto out;
1334
1335       /* Find Client entry and if not found query it */
1336       client_entry = silc_client_get_client_by_id(client, conn, client_id);
1337       if (!client_entry) {
1338         silc_client_notify_by_server_resolve(client, conn, packet, 
1339                                              SILC_ID_CLIENT, client_id);
1340         goto out;
1341       }
1342
1343       /* Get user mode */
1344       tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
1345       if (!tmp || tmp_len != 4)
1346         goto out;
1347       SILC_GET32_MSB(mode, tmp);
1348
1349       /* Get notify type */
1350       tmp = silc_argument_get_arg_type(args, 4, &tmp_len);
1351       if (tmp && tmp_len != 2)
1352         goto out;
1353       if (tmp)
1354         SILC_GET16_MSB(notify, tmp);
1355
1356       /* Get nickname */
1357       tmp = silc_argument_get_arg_type(args, 2, NULL);
1358       if (tmp) {
1359         char *tmp_nick = NULL;
1360
1361         if (client->internal->params->nickname_parse)
1362           client->internal->params->nickname_parse(client_entry->nickname,
1363                                                    &tmp_nick);
1364         else
1365           tmp_nick = strdup(tmp);
1366
1367         /* If same nick, the client was new to us and has become "present"
1368            to network.  Send NULL as nick to application. */
1369         if (tmp_nick && !strcmp(tmp, tmp_nick))
1370           tmp = NULL;
1371
1372         silc_free(tmp_nick);
1373       }
1374
1375       /* Notify application. */
1376       client->internal->ops->notify(client, conn, type, client_entry,
1377                                     tmp, mode, notify);
1378
1379       client_entry->mode = mode;
1380
1381       /* If nickname was changed, remove the client entry unless the
1382          client is on some channel */
1383       if (tmp && notify == SILC_NOTIFY_TYPE_NICK_CHANGE &&
1384           !silc_hash_table_count(client_entry->channels))
1385         del_client = TRUE;
1386       else if (notify == SILC_NOTIFY_TYPE_SIGNOFF ||
1387                notify == SILC_NOTIFY_TYPE_SERVER_SIGNOFF ||
1388                notify == SILC_NOTIFY_TYPE_KILLED)
1389         del_client = TRUE;
1390
1391       if (del_client) {
1392         SilcClientNotifyResolve res = silc_calloc(1, sizeof(*res));
1393         res->context = client;
1394         res->sock = silc_socket_dup(conn->sock);
1395         res->packet = client_id;
1396         client_id = NULL;
1397         silc_schedule_task_add(client->schedule, conn->sock->sock,
1398                                silc_client_notify_del_client_cb, res,
1399                                1, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1400       }
1401     }
1402     break;
1403
1404   default:
1405     break;
1406   }
1407
1408  out:
1409   silc_notify_payload_free(payload);
1410   silc_free(client_id);
1411   silc_free(channel_id);
1412   silc_free(server_id);
1413 }