Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
- Copyright (C) 1997 - 2000 Pekka Riikonen
+ Copyright (C) 1997 - 2001 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_H
#define CLIENT_H
-/* Forward declaration for client */
-typedef struct SilcClientObject *SilcClient;
-
-/* Forward declaration for client connection */
-typedef struct SilcClientConnectionObject *SilcClientConnection;
+/* Forward declarations */
+typedef struct SilcClientStruct *SilcClient;
+typedef struct SilcClientConnectionStruct *SilcClientConnection;
+typedef struct SilcClientPingStruct SilcClientPing;
+typedef struct SilcClientAwayStruct SilcClientAway;
+typedef struct SilcClientKeyAgreementStruct *SilcClientKeyAgreement;
#include "idlist.h"
#include "command.h"
-#include "ops.h"
-
-/* 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. */
-typedef struct SilcClientPingStruct {
- time_t start_time;
- void *dest_id;
- char *dest_name;
-} SilcClientPing;
-
-/* 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. */
-typedef struct SilcClientAwayStruct {
- char *away;
- struct SilcClientAwayStruct *next;
-} SilcClientAway;
+#include "silcapi.h"
+
+/* Generic rekey context for connections */
+typedef struct {
+ /* Current sending encryption key, provided for re-key. The `pfs'
+ is TRUE if the Perfect Forward Secrecy is performed in re-key. */
+ unsigned char *send_enc_key;
+ uint32 enc_key_len;
+ int ske_group;
+ bool pfs;
+ uint32 timeout;
+ void *context;
+} *SilcClientRekey;
/* Connection structure used in client to associate all the important
connection specific data to this structure. */
-struct SilcClientConnectionObject {
+struct SilcClientConnectionStruct {
/*
* Local data
*/
/* Decoded local ID so that the above defined ID would not have
to be decoded for every packet. */
unsigned char *local_id_data;
- unsigned int local_id_data_len;
+ uint32 local_id_data_len;
/* Own client entry. */
SilcClientEntry local_entry;
/* Decoded remote ID so that the above defined ID would not have
to be decoded for every packet. */
unsigned char *remote_id_data;
- unsigned int remote_id_data_len;
+ uint32 remote_id_data_len;
/*
* Common data
*/
- /* Keys */
+ /* Keys and stuff negotiated in the SKE protocol */
SilcCipher send_key;
SilcCipher receive_key;
- SilcHmac hmac;
- unsigned char *hmac_key;
- unsigned int hmac_key_len;
+ SilcHmac hmac_send;
+ SilcHmac hmac_receive;
+ SilcHash hash;
/* Client ID and Channel ID cache. Messages transmitted in SILC network
are done using different unique ID's. These are the cache for
referencing (sock->user_data). */
SilcSocketConnection sock;
+ /* Pending command queue for this connection */
+ SilcDList pending_commands;
+
+ /* Current command identifier, 0 not used */
+ uint16 cmd_ident;
+
/* Requested pings. */
SilcClientPing *ping;
- unsigned int ping_count;
+ uint32 ping_count;
/* Set away message */
SilcClientAway *away;
+ /* Re-key context */
+ SilcClientRekey rekey;
+
/* Pointer back to the SilcClient. This object is passed to the application
- and the actual client object is accesible thourh this pointer. */
+ and the actual client object is accesible through this pointer. */
SilcClient client;
/* User data context. Library does not touch this. */
};
/* Main client structure. */
-struct SilcClientObject {
+struct SilcClientStruct {
/*
* Public data. All the following pointers must be set by the allocator
* of this structure.
*/
- /* Users's username and realname. */
+ /* Users's username, hostname and realname. */
char *username;
+ char *hostname;
char *realname;
/* Private and public key of the user. */
/* All client operations that are implemented in the application. */
SilcClientOperations *ops;
- /* SILC client task queues */
+ /* SILC client scheduler and task queues */
+ SilcSchedule schedule;
SilcTaskQueue io_queue;
SilcTaskQueue timeout_queue;
SilcTaskQueue generic_queue;
/* Table of connections in client. All the connection data is saved here. */
SilcClientConnection *conns;
- unsigned int conns_count;
+ uint32 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;
+ uint32 sockets_count;
/* Generic cipher and hash objects. These can be used and referenced
by the application as well. */
silc_task_set_iotype(tmptask, SILC_TASK_WRITE); \
} while(0)
-#define SILC_CLIENT_SET_CONNECTION_FOR_INPUT(fd) \
-do { \
- silc_schedule_set_listen_fd((fd), (1L << SILC_TASK_READ)); \
-} while(0) \
+#define SILC_CLIENT_SET_CONNECTION_FOR_INPUT(s, fd) \
+do { \
+ silc_schedule_set_listen_fd((s), (fd), (1L << SILC_TASK_READ)); \
+} while(0)
-#define SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(fd) \
-do { \
- silc_schedule_set_listen_fd((fd), ((1L << SILC_TASK_READ) | \
- (1L << SILC_TASK_WRITE))); \
+#define SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(s, fd) \
+do { \
+ silc_schedule_set_listen_fd((s), (fd), ((1L << SILC_TASK_READ) | \
+ (1L << SILC_TASK_WRITE))); \
} while(0)
/* Finds socket connection object by file descriptor */
int __i; \
\
for (__i = 0; __i < (__x)->conns_count; __i++) \
- if ((__x)->conns[__i]->sock->sock == (__fd)) \
+ if ((__x)->conns[__i] && \
+ (__x)->conns[__i]->sock->sock == (__fd)) \
break; \
\
- if (__i >= (__x)->conns_count) \
+ if (__i >= (__x)->conns_count) { \
(__sock) = NULL; \
- (__sock) = (__x)->conns[__i]->sock; \
+ for (__i = 0; __i < (__x)->sockets_count; __i++) \
+ if ((__x)->sockets[__i] && \
+ (__x)->sockets[__i]->sock == (__fd)) \
+ (__sock) = (__x)->sockets[__i]; \
+ } else \
+ (__sock) = (__x)->conns[__i]->sock; \
} while(0)
-/* Prototypes */
-
-SilcClient silc_client_alloc(SilcClientOperations *ops, void *application);
-void silc_client_free(SilcClient client);
-int silc_client_init(SilcClient client);
-void silc_client_stop(SilcClient client);
-void silc_client_run(SilcClient client);
-SilcClientConnection silc_client_add_connection(SilcClient client,
- char *hostname,
- int port,
- void *context);
-int silc_client_connect_to_server(SilcClient client, int port,
- char *host, void *context);
-int silc_client_start_key_exchange(SilcClient client,
- SilcClientConnection conn,
- int fd);
+/* 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 (some of the prototypes are defined in the silcapi.h) */
+
void silc_client_packet_send(SilcClient client,
SilcSocketConnection sock,
SilcPacketType type,
SilcCipher cipher,
SilcHmac hmac,
unsigned char *data,
- unsigned int data_len,
+ uint32 data_len,
int force_send);
-void silc_client_packet_send_to_channel(SilcClient client,
- SilcSocketConnection sock,
- SilcChannelEntry channel,
- unsigned char *data,
- unsigned int data_len,
- int force_send);
-void silc_client_packet_send_private_message(SilcClient client,
- SilcSocketConnection sock,
- SilcClientEntry client_entry,
- unsigned char *data,
- unsigned int data_len,
- int force_send);
-void silc_client_close_connection(SilcClient client,
- SilcSocketConnection sock);
void silc_client_disconnected_by_server(SilcClient client,
SilcSocketConnection sock,
SilcBuffer message);
void silc_client_error_by_server(SilcClient client,
SilcSocketConnection sock,
SilcBuffer message);
-void silc_client_notify_by_server(SilcClient client,
- SilcSocketConnection sock,
- SilcBuffer message);
void silc_client_receive_new_id(SilcClient client,
SilcSocketConnection sock,
- unsigned char *id_string);
-void silc_client_new_channel_id(SilcClient client,
- SilcSocketConnection sock,
- char *channel_name,
- unsigned int mode,
- unsigned char *id_string);
+ SilcIDPayload idp);
+SilcChannelEntry silc_client_new_channel_id(SilcClient client,
+ SilcSocketConnection sock,
+ char *channel_name,
+ uint32 mode,
+ SilcIDPayload idp);
+void silc_client_save_channel_key(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 new);
+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);
+
#endif