Targeted say-operation messages
authorPekka Riikonen <priikone@silcnet.org>
Mon, 28 Apr 2014 18:47:58 +0000 (21:47 +0300)
committerPekka Riikonen <priikone@silcnet.org>
Mon, 28 Apr 2014 18:47:58 +0000 (21:47 +0300)
Add support for including the client, channel or server with the say()
client operation library can generate.  This allows application to
better target the message to correct window or recipient.

lib/silcclient/client.c
lib/silcclient/client_channel.c
lib/silcclient/client_ftp.c
lib/silcclient/silcclient.h

index 255339941bd5d6d79151be6baf62a997fcabcbd4..38afc4537e297fb61f6ad6f1b88cc85c32571286 100644 (file)
@@ -452,7 +452,7 @@ SILC_FSM_STATE(silc_client_error)
   msg = silc_memdup(silc_buffer_data(&packet->buffer),
                    silc_buffer_len(&packet->buffer));
   if (msg)
-    client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT, msg);
+    client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR, msg);
 
   silc_free(msg);
   silc_packet_free(packet);
index 4120695d76af08286853fa5fc5bdf31f0f767220..3b020c5daa90ce030646805f13ed52694d07f9ac 100644 (file)
@@ -53,9 +53,12 @@ SilcBool silc_client_send_channel_message(SilcClient client,
 
   chu = silc_client_on_channel(channel, conn->local_entry);
   if (silc_unlikely(!chu)) {
+    conn->context_type = SILC_ID_CHANNEL;
+    conn->channel_entry = channel;
     client->internal->ops->say(conn->client, conn,
-                              SILC_CLIENT_MESSAGE_AUDIT,
+                              SILC_CLIENT_MESSAGE_ERROR,
                               "Cannot talk to channel: not joined");
+    conn->context_type = SILC_ID_NONE;
     return FALSE;
   }
 
@@ -423,21 +426,27 @@ SilcBool silc_client_save_channel_key(SilcClient client,
   /* Get channel cipher */
   cipher = silc_channel_key_get_cipher(payload, NULL);
   if (!silc_cipher_alloc(cipher, &channel->internal.send_key)) {
+    conn->context_type = SILC_ID_CHANNEL;
+    conn->channel_entry = channel;
     client->internal->ops->say(
                           conn->client, conn,
-                          SILC_CLIENT_MESSAGE_AUDIT,
+                          SILC_CLIENT_MESSAGE_ERROR,
                           "Cannot talk to channel: unsupported cipher %s",
                           cipher);
+    conn->context_type = SILC_ID_NONE;
     silc_client_unref_channel(client, conn, channel);
     silc_channel_key_payload_free(payload);
     return FALSE;
   }
   if (!silc_cipher_alloc(cipher, &channel->internal.receive_key)) {
+    conn->context_type = SILC_ID_CHANNEL;
+    conn->channel_entry = channel;
     client->internal->ops->say(
                           conn->client, conn,
-                          SILC_CLIENT_MESSAGE_AUDIT,
+                          SILC_CLIENT_MESSAGE_ERROR,
                           "Cannot talk to channel: unsupported cipher %s",
                           cipher);
+    conn->context_type = SILC_ID_NONE;
     silc_client_unref_channel(client, conn, channel);
     silc_channel_key_payload_free(payload);
     return FALSE;
@@ -453,11 +462,14 @@ SilcBool silc_client_save_channel_key(SilcClient client,
          (char *)silc_hmac_get_name(channel->internal.hmac) :
          SILC_DEFAULT_HMAC);
   if (!silc_hmac_alloc(hmac, NULL, &channel->internal.hmac)) {
+    conn->context_type = SILC_ID_CHANNEL;
+    conn->channel_entry = channel;
     client->internal->ops->say(
                           conn->client, conn,
-                          SILC_CLIENT_MESSAGE_AUDIT,
+                          SILC_CLIENT_MESSAGE_ERROR,
                           "Cannot talk to channel: unsupported HMAC %s",
                           hmac);
+    conn->context_type = SILC_ID_NONE;
     silc_client_unref_channel(client, conn, channel);
     silc_channel_key_payload_free(payload);
     return FALSE;
index a38d03c009873b315aea103310d6d94e9335213b..ac53a0c5ead3e1f2a3cda16a2f290962e0ced2d9 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2001 - 2007 Pekka Riikonen
+  Copyright (C) 2001 - 2014 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -189,11 +189,14 @@ static void silc_client_ftp_open_handle(SilcSFTP sftp,
   session->fd = silc_file_open(path, O_RDWR | O_CREAT | O_EXCL);
   if (session->fd < 0) {
     /* Call monitor callback */
+    session->conn->context_type = SILC_ID_CLIENT;
+    session->conn->client_entry = session->client_entry;
     session->client->internal->ops->say(session->client, session->conn,
                                        SILC_CLIENT_MESSAGE_ERROR,
                                        "File `%s' open failed: %s",
                                        session->filepath,
                                        strerror(errno));
+    session->conn->context_type = SILC_ID_NONE;
 
     if (session->monitor)
       (*session->monitor)(session->client, session->conn,
@@ -736,9 +739,12 @@ silc_client_file_send(SilcClient client,
                               silc_client_ftp_connect_completion,
                               session);
     if (!session->listener) {
+      conn->context_type = SILC_ID_CLIENT;
+      conn->client_entry = session->client_entry;
       client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
                                 "Cannot create listener for file transfer: "
                                 "%s", strerror(errno));
+      conn->context_type = SILC_ID_NONE;
       silc_free(session);
       return SILC_CLIENT_FILE_NO_MEMORY;
     }
@@ -855,11 +861,14 @@ silc_client_file_receive(SilcClient client,
     /* Add the listener for the key agreement */
     SILC_LOG_DEBUG(("Creating listener for file transfer"));
     if (!params || (!params->local_ip && !params->bind_ip)) {
+      session->conn->context_type = SILC_ID_CLIENT;
+      session->conn->client_entry = session->client_entry;
       session->client->internal->ops->say(session->client, session->conn,
                                          SILC_CLIENT_MESSAGE_ERROR,
                                          "Cannot create listener for file "
                                          "transfer; IP address and/or port "
                                          "not provided");
+      session->conn->context_type = SILC_ID_NONE;
       silc_free(session);
       return SILC_CLIENT_FILE_ERROR;
     }
@@ -869,9 +878,12 @@ silc_client_file_receive(SilcClient client,
                               silc_client_ftp_connect_completion,
                               session);
     if (!session->listener) {
+      session->conn->context_type = SILC_ID_CLIENT;
+      session->conn->client_entry = session->client_entry;
       client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
                                 "Cannot create listener for file transfer: "
                                 "%s", strerror(errno));
+      session->conn->context_type = SILC_ID_NONE;
       silc_free(session);
       return SILC_CLIENT_FILE_NO_MEMORY;
     }
index 00d0b5e58fbca0458059a82ae3f8db50a2271615..0d07b93867d7abb84e6775fae8cb35f11aa3a5ca 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2000 - 2008 Pekka Riikonen
+  Copyright (C) 2000 - 2014 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -232,6 +232,18 @@ struct SilcClientConnectionStruct {
   void *callback_context;             /* Connection context */
   SilcClient client;                  /* Pointer back to SilcClient */
 
+  /* Current say() operation associated context, identifies the client,
+     channel or server the message is related to.  Application can use
+     this information to target the message better. */
+  union {
+    SilcClientEntry client_entry;
+    SilcChannelEntry channel_entry;
+    SilcServerEntry server_entry;
+  };
+  SilcIdType context_type;             /* Defines which pointer is set
+                                          in the union.  If SILC_ID_NONE
+                                          pointer is NULL. */
+
   /* Application specific data.  Application may set here whatever it wants. */
   void *context;
 
@@ -506,7 +518,9 @@ typedef struct SilcClientOperationsStruct {
      The `type' indicates the type of the message sent by the library.
      The application can for example filter the message according the
      type.  The variable argument list is arguments to the formatted
-     message that `msg' may be. */
+     message `msg'.  A SilcClientEntry, SilcChannelEntry or SilcServerEntry
+     can be associated with the message inside the `conn' by the library,
+     and application may use it to better target the message. */
   void (*say)(SilcClient client, SilcClientConnection conn,
              SilcClientMessageType type, char *msg, ...);