Merge commit 'origin/silc.1.1.branch'
[silc.git] / lib / silcclient / client_internal.h
index d5e6fc781fffa5345f5de29a9d3509ca44fcfdf1..a297182024c827335a6caf89aa4e7ac4de015e22 100644 (file)
@@ -1,10 +1,10 @@
 /*
 
-  client_internal.h 
+  client_internal.h
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2001 Pekka Riikonen
+  Copyright (C) 1997 - 2007 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
 #ifndef CLIENT_INTERNAL_H
 #define CLIENT_INTERNAL_H
 
-/* Internal context for connection process. This is needed as we
-   doing asynchronous connecting. */
+#include "command.h"
+#include "command_reply.h"
+#include "client_connect.h"
+#include "client_register.h"
+#include "client_entry.h"
+#include "client_prvmsg.h"
+#include "client_channel.h"
+#include "client_notify.h"
+#include "client_keyagr.h"
+#include "client_ftp.h"
+#include "client_listener.h"
+
+/****************************** Definitions *********************************/
+
+/* Packet retry counter and timer defines, for exponential backoff algorithm.
+   Meaningful with UDP transport when packets may get lost. */
+#define SILC_CLIENT_RETRY_COUNT   4      /* Max packet retry count */
+#define SILC_CLIENT_RETRY_MUL     2      /* Retry timer interval growth */
+#define SILC_CLIENT_RETRY_RAND    2      /* Randomizer, timeout += rnd % 2 */
+#define SILC_CLIENT_RETRY_MIN     1      /* Min retry timeout, seconds */
+#define SLIC_CLIENT_RETRY_MAX     16    /* Max retry timeout, seconds */
+
+/********************************** Types ***********************************/
+
+/* Public key verification context */
 typedef struct {
-  SilcClient client;
-  SilcClientConnection conn;
-  SilcTask task;
-  int sock;
-  char *host;
-  int port;
-  int tries;
-  void *context;
-} SilcClientInternalConnectContext;
-
-/* Structure to hold ping time information. Every PING command will 
-   add entry of this structure and is removed after reply to the ping
-   as been received. */
-struct SilcClientPingStruct {
-  time_t start_time;
-  void *dest_id;
-  char *dest_name;
-};
-
-/* Structure to hold away messages set by user. This is mainly created
-   for future extensions where away messages could be set according filters
-   such as nickname and hostname. For now only one away message can 
-   be set in one connection. */
-struct SilcClientAwayStruct {
-  char *away;
-  struct SilcClientAwayStruct *next;
-};
+  SilcSKE ske;
+  SilcSKEVerifyCbCompletion completion;
+  void *completion_context;
+} *SilcVerifyKeyContext;
+
+/* Command and command reply context used to hold registered commands
+   in the SILC client. */
+typedef struct SilcClientCommandStruct {
+  struct SilcClientCommandStruct *next;
+  SilcCommand cmd;                   /* Command type */
+  SilcFSMStateCallback command;              /* Command function */
+  SilcFSMStateCallback reply;        /* Command reply callback */
+  char *name;                        /* Name of the command (optional) */
+  SilcUInt8 max_args;                /* Maximum arguments (optional)  */
+} *SilcClientCommand;
+
+/* Command reply callback structure */
+typedef struct SilcClientCommandReplyCallbackStruct  {
+  struct SilcClientCommandReplyCallbackStruct *next;
+  SilcClientCommandReply reply;              /* Command reply callback */
+  void *context;                     /* Command reply context */
+  unsigned int do_not_call     : 1;   /* Set to not call the callback */
+} *SilcClientCommandReplyCallback;
+
+/* Command context given as argument to command state functions.  This same
+   context is used when calling, sending and procesing command and command
+   reply. */
+typedef struct SilcClientCommandContextStruct {
+  struct SilcClientCommandContextStruct *next;
+  SilcClientConnection conn;          /* Connection */
+  SilcFSMThreadStruct thread;        /* FSM thread for command call */
+
+  SilcCommand cmd;                   /* Command */
+  SilcUInt16 cmd_ident;                      /* Command identifier */
+  SilcUInt32 argc;                   /* Number of arguments */
+  unsigned char **argv;                      /* Arguments, may be NULL */
+  SilcUInt32 *argv_lens;             /* Argument lengths, may be NULL */
+  SilcUInt32 *argv_types;            /* Argument types, may be NULL */
+
+  SilcList reply_callbacks;          /* Command reply callbacks */
+  SilcStatus status;                 /* Current command reply status */
+  SilcStatus error;                  /* Current command reply error */
+
+  void *context;                     /* Context for free use */
+  unsigned int called        : 1;     /* Set when called by application */
+  unsigned int verbose       : 1;     /* Verbose with 'say' client operation */
+  unsigned int resolved      : 1;     /* Set when resolving something */
+} *SilcClientCommandContext;
 
 /* Internal context for the client->internal pointer in the SilcClient. */
 struct SilcClientInternalStruct {
-  /* All client operations that are implemented by the application. */
-  SilcClientOperations *ops;
-
-  /* Client Parameters */
-  SilcClientParams *params;
-
-  /* Table of connections in client. All the connection data is saved here. */
-  SilcClientConnection *conns;
-  SilcUInt32 conns_count;
-
-  /* Table of listenning sockets in client.  Client can have listeners
-     (like key agreement protocol server) and those sockets are saved here.
-     This table is checked always if the connection object cannot be found
-     from the `conns' table. */
-  SilcSocketConnection *sockets;
-  SilcUInt32 sockets_count;
-
-  /* Registered commands */
-  SilcList commands;
-
-  /* Generic cipher and hash objects. */
-  SilcCipher none_cipher;
-  SilcHash md5hash;
-  SilcHash sha1hash;
-  SilcHmac md5hmac;
-  SilcHmac sha1hmac;
-
-  /* Client version. Used to compare to remote host's version strings. */
-  char *silc_client_version;
+  SilcFSMStruct fsm;                    /* Client's FSM */
+  SilcFSMEventStruct wait_event;        /* Event signaller */
+  SilcClientOperations *ops;            /* Client operations */
+  SilcClientParams *params;             /* Client parameters */
+  SilcPacketEngine packet_engine;        /* Packet engine */
+  SilcMutex lock;                       /* Client lock */
+  SilcList commands;                    /* Registered commands */
+  SilcDList ftp_sessions;               /* FTP sessions */
+  char *silc_client_version;            /* Version set by application */
+  SilcClientRunning running;            /* Running/Stopped callback */
+  void *running_context;                /* Context for runnign callback */
+  SilcAtomic32 conns;                   /* Number of connections in client */
+  SilcUInt16 next_session_id;           /* Next FTP session ID */
+
+  /* Events */
+  unsigned int stop              : 1;   /* Stop client */
+  unsigned int run_callback      : 1;   /* Call running/stopped callback */
+  unsigned int connection_closed : 1;   /* A connection closed */
+};
+
+/* Internal context for conn->internal in SilcClientConnection. */
+struct SilcClientConnectionInternalStruct {
+  SilcClientConnectionParams params;    /* Connection parameters */
+  SilcFSMStruct fsm;                    /* Connection FSM */
+  SilcFSMThreadStruct event_thread;      /* FSM thread for events */
+  SilcFSMEventStruct wait_event;        /* Event signaller */
+  SilcSchedule schedule;                /* Connection's scheduler */
+  SilcMutex lock;                       /* Connection lock */
+  SilcSKE ske;                          /* Key exchange protocol */
+  SilcSKERekeyMaterial rekey;           /* Rekey material */
+  SilcList thread_pool;                         /* Packet thread pool */
+  SilcList pending_commands;            /* Pending commands list */
+  SilcHash hash;                        /* Negotiated hash function */
+  SilcHash sha1hash;                    /* SHA-1 default hash context */
+  SilcBuffer local_idp;                         /* Local ID Payload */
+  SilcBuffer remote_idp;                /* Remote ID Payload */
+  SilcAsyncOperation op;                /* Protocols async operation */
+  SilcAsyncOperation cop;               /* Async operation for application */
+  SilcHashTable attrs;                  /* Configured user attributes */
+  SilcStream user_stream;               /* Low level stream in connecting */
+  char *disconnect_message;             /* Disconnection message */
+  char *away_message;                   /* Away message */
+
+  SilcIDCache client_cache;             /* Client entry cache */
+  SilcIDCache channel_cache;            /* Channel entry cache */
+  SilcIDCache server_cache;             /* Server entry cache */
+
+  SilcUInt32 remote_version;            /* Remote SILC protocol version */
+  SilcAtomic16 cmd_ident;               /* Current command identifier */
+  SilcUInt8 retry_count;                /* Packet retry counter */
+  SilcUInt8 retry_timer;                /* Packet retry timer */
+  SilcClientConnectionStatus status;    /* Connection callback status */
+  SilcStatus error;                     /* Connection callback error */
+
+  /* Events */
+  unsigned int connect            : 1;  /* Connect remote host */
+  unsigned int disconnected       : 1;  /* Disconnect remote connection */
+  unsigned int key_exchange       : 1;   /* Start key exchange */
+  unsigned int rekeying           : 1;   /* Start rekey */
+
+  /* Flags */
+  unsigned int verbose            : 1;   /* Notify application */
+  unsigned int registering        : 1;  /* Set when registering to network */
+  unsigned int rekey_responder    : 1;   /* Set when rekeying as responder */
+  unsigned int auth_request       : 1;   /* Set when requesting auth method */
 };
 
-/* Session resuming callback */
-typedef void (*SilcClientResumeSessionCallback)(SilcClient client,
-                                               SilcClientConnection conn,
-                                               bool success,
-                                               void *context);
-
-/* Macros */
-
-/* Registers generic task for file descriptor for reading from network and
-   writing to network. As being generic task the actual task is allocated 
-   only once and after that the same task applies to all registered fd's. */
-#define SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(fd)     \
-do {                                                   \
-  silc_schedule_task_add(client->schedule, (fd),       \
-                        silc_client_packet_process,    \
-                        context, 0, 0,                 \
-                        SILC_TASK_GENERIC,             \
-                        SILC_TASK_PRI_NORMAL);         \
-} while(0)
-
-#define SILC_CLIENT_SET_CONNECTION_FOR_INPUT(s, fd)            \
-do {                                                           \
-  silc_schedule_set_listen_fd((s), (fd), SILC_TASK_READ);      \
-} while(0)
-     
-#define SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(s, fd)           \
-do {                                                           \
-  silc_schedule_set_listen_fd((s), (fd), (SILC_TASK_READ |     \
-                                         SILC_TASK_WRITE));    \
-} while(0)
-
-/* Finds socket connection object by file descriptor */
-#define SILC_CLIENT_GET_SOCK(__x, __fd, __sock)                        \
-do {                                                           \
-  int __i;                                                     \
-                                                               \
-  for (__i = 0; __i < (__x)->internal->conns_count; __i++)     \
-    if ((__x)->internal->conns[__i] &&                         \
-       (__x)->internal->conns[__i]->sock->sock == (__fd))      \
-      break;                                                   \
-                                                               \
-  if (__i >= (__x)->internal->conns_count) {                   \
-    (__sock) = NULL;                                           \
-    for (__i = 0; __i < (__x)->internal->sockets_count; __i++) \
-      if ((__x)->internal->sockets[__i] &&                     \
-         (__x)->internal->sockets[__i]->sock == (__fd))        \
-        (__sock) = (__x)->internal->sockets[__i];              \
-  } else                                                       \
-    (__sock) = (__x)->internal->conns[__i]->sock;              \
-} while(0)
-
-/* Check whether rekey protocol is active */
-#define SILC_CLIENT_IS_REKEY(sock)                                     \
-  (sock->protocol && sock->protocol->protocol &&                       \
-   sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)
-
-/* Prototypes */
-
-SILC_TASK_CALLBACK_GLOBAL(silc_client_packet_process);
-int silc_client_packet_send_real(SilcClient client,
-                                SilcSocketConnection sock,
-                                bool force_send);
-void silc_client_ftp_free_sessions(SilcClient client,
-                                  SilcClientConnection conn);
-void silc_client_ftp_session_free(SilcClientFtpSession session);
-void silc_client_ftp_session_free_client(SilcClientConnection conn,
-                                        SilcClientEntry client_entry);
-void silc_client_packet_send(SilcClient client, 
-                            SilcSocketConnection sock,
-                            SilcPacketType type, 
-                            void *dst_id,
-                            SilcIdType dst_id_type,
-                            SilcCipher cipher,
-                            SilcHmac hmac,
-                            unsigned char *data, 
-                            SilcUInt32 data_len, 
-                            int force_send);
-void silc_client_close_connection_real(SilcClient client,
-                                      SilcSocketConnection sock,
-                                      SilcClientConnection conn);
-void silc_client_disconnected_by_server(SilcClient client,
-                                       SilcSocketConnection sock,
-                                       SilcBuffer packet);
-void silc_client_error_by_server(SilcClient client,
-                                SilcSocketConnection sock,
-                                SilcBuffer message);
-void silc_client_receive_new_id(SilcClient client,
-                               SilcSocketConnection sock,
-                               SilcIDPayload idp);
-void silc_client_save_channel_key(SilcClient client,
-                                 SilcClientConnection conn,
-                                 SilcBuffer key_payload, 
-                                 SilcChannelEntry channel);
-void silc_client_receive_channel_key(SilcClient client,
-                                    SilcSocketConnection sock,
-                                    SilcBuffer packet);
-void silc_client_channel_message(SilcClient client, 
-                                SilcSocketConnection sock, 
-                                SilcPacketContext *packet);
-void silc_client_remove_from_channels(SilcClient client,
-                                     SilcClientConnection conn,
-                                     SilcClientEntry client_entry);
-void silc_client_replace_from_channels(SilcClient client, 
-                                      SilcClientConnection conn,
-                                      SilcClientEntry old,
-                                      SilcClientEntry newclient);
-void silc_client_process_failure(SilcClient client,
-                                SilcSocketConnection sock,
-                                SilcPacketContext *packet);
-void silc_client_key_agreement(SilcClient client,
-                              SilcSocketConnection sock,
-                              SilcPacketContext *packet);
-void silc_client_notify_by_server(SilcClient client,
-                                 SilcSocketConnection sock,
-                                 SilcPacketContext *packet);
-void silc_client_private_message(SilcClient client, 
-                                SilcSocketConnection sock, 
-                                SilcPacketContext *packet);
-void silc_client_connection_auth_request(SilcClient client,
-                                        SilcSocketConnection sock,
-                                        SilcPacketContext *packet);
-void silc_client_ftp(SilcClient client,
-                    SilcSocketConnection sock,
-                    SilcPacketContext *packet);
-SilcBuffer silc_client_get_detach_data(SilcClient client,
-                                      SilcClientConnection conn);
-bool silc_client_process_detach_data(SilcClient client,
-                                    SilcClientConnection conn,
-                                    unsigned char **old_id,
-                                    SilcUInt16 *old_id_len);
-void silc_client_resume_session(SilcClient client,
-                               SilcClientConnection conn,
-                               SilcClientResumeSessionCallback callback,
-                               void *context);
-SilcBuffer silc_client_attributes_process(SilcClient client,
-                                         SilcSocketConnection sock,
-                                         SilcDList attrs);
-
-#endif
+SILC_FSM_STATE(silc_client_connection_st_run);
+SILC_FSM_STATE(silc_client_connection_st_packet);
+SILC_FSM_STATE(silc_client_connection_st_close);
+SILC_FSM_STATE(silc_client_error);
+SILC_FSM_STATE(silc_client_disconnect);
+SILC_FSM_STATE(silc_client_st_stop);
+
+void silc_client_del_connection(SilcClient client, SilcClientConnection conn);
+void silc_client_fsm_destructor(SilcFSM fsm, void *fsm_context,
+                               void *destructor_context);
+void silc_client_command_free(SilcClientCommandContext cmd);
+SilcClientConnection
+silc_client_add_connection(SilcClient client,
+                          SilcConnectionType conn_type,
+                          SilcBool connect,
+                          SilcClientConnectionParams *params,
+                          SilcPublicKey public_key,
+                          SilcPrivateKey private_key,
+                          char *remote_host, int port,
+                          SilcClientConnectCallback callback,
+                          void *context);
+void silc_client_attributes_process(SilcClient client,
+                                   SilcClientConnection conn,
+                                   SilcDList attrs,
+                                   SilcPKCSSignCb sign_cb,
+                                   void *context);
+
+#endif /* CLIENT_INTERNAL_H */