#include "silcclient.h"
#include "client_internal.h"
+/* Context used for resolving client, channel and server info. */
typedef struct {
- SilcPacketContext *packet;
+ void *packet;
void *context;
SilcSocketConnection sock;
} *SilcClientNotifyResolve;
+SILC_TASK_CALLBACK(silc_client_notify_check_client)
+{
+ SilcClientNotifyResolve res = (SilcClientNotifyResolve)context;
+ SilcClientConnection conn = res->context;
+ SilcClient client = conn->client;
+ SilcClientID *client_id = res->packet;
+ silc_client_get_client_by_id_resolve(client, conn, client_id, NULL, NULL);
+ silc_free(client_id);
+ silc_free(res);
+}
+
/* Called when notify is received and some async operation (such as command)
is required before processing the notify message. This calls again the
silc_client_notify_by_server and reprocesses the original notify packet. */
res->context = client;
res->sock = silc_socket_dup(conn->sock);
- /* For client resolving use WHOIS, and oterhwise use IDENTIFY */
+ /* For client resolving use WHOIS, and otherwise use IDENTIFY */
if (id_type == SILC_ID_CLIENT) {
silc_client_command_register(client, SILC_COMMAND_WHOIS, NULL, NULL,
silc_client_command_reply_whois_i, 0,
silc_free(chu);
}
+ /* Some client implementations actually quit network by first doing
+ LEAVE and then immediately SIGNOFF. We'll check for this by doing
+ check for the client after 15 seconds. If it is not valid after
+ that we'll remove the client from cache. */
+ if (!silc_hash_table_count(client_entry->channels)) {
+ SilcClientNotifyResolve res = silc_calloc(1, sizeof(*res));
+ res->context = conn;
+ res->packet = silc_id_dup(client_id, SILC_ID_CLIENT);
+ silc_schedule_task_add(client->schedule, 0,
+ silc_client_notify_check_client, conn,
+ 15, 0, SILC_TASK_TIMEOUT,
+ SILC_TASK_PRI_NORMAL);
+ }
+
/* Notify application. The channel entry is sent last as this notify
is for channel but application don't know it from the arguments
sent by server. */
/* Get the client */
entry = silc_client_get_client_by_id(i->client, i->conn, i->client_id);
- if (entry)
- i->completion(i->client, i->conn, &entry, 1, i->context);
- else
- i->completion(i->client, i->conn, NULL, 0, i->context);
+ if (entry) {
+ if (i->completion)
+ i->completion(i->client, i->conn, &entry, 1, i->context);
+ } else {
+ if (i->completion)
+ i->completion(i->client, i->conn, NULL, 0, i->context);
+ }
silc_free(i->client_id);
silc_free(i);