*/
/* $Id$ */
-#include "clientlibincludes.h"
+#include "silcincludes.h"
+#include "silcclient.h"
#include "client_internal.h"
/* Static task callback prototypes */
void silc_client_resolve_auth_method(bool success,
SilcProtocolAuthMeth auth_meth,
const unsigned char *auth_data,
- uint32 auth_data_len, void *context);
+ SilcUInt32 auth_data_len, void *context);
/* Allocates new client object. This has to be done before client may
work. After calling this one must call silc_client_init to initialize
application performed the connecting outside the library. The library
however may use this internally. */
-SilcClientConnection silc_client_add_connection(SilcClient client,
- char *hostname,
- int port,
- void *context)
+SilcClientConnection
+silc_client_add_connection(SilcClient client,
+ SilcClientConnectionParams *params,
+ char *hostname, int port, void *context)
{
SilcClientConnection conn;
int i;
conn->pending_commands = silc_dlist_init();
conn->ftp_sessions = silc_dlist_init();
+ if (params) {
+ if (params->detach_data)
+ conn->params.detach_data = silc_memdup(params->detach_data,
+ params->detach_data_len);
+ conn->params.detach_data_len = params->detach_data_len;
+ }
+
/* Add the connection to connections table */
for (i = 0; i < client->internal->conns_count; i++)
if (client->internal->conns && !client->internal->conns[i]) {
case then this function is not used at all. When the connecting is
done the `connect' client operation is called. */
-int silc_client_connect_to_server(SilcClient client, int port,
- char *host, void *context)
+int silc_client_connect_to_server(SilcClient client,
+ SilcClientConnectionParams *params,
+ int port, char *host, void *context)
{
SilcClientInternalConnectContext *ctx;
SilcClientConnection conn;
SILC_LOG_DEBUG(("Connecting to port %d of server %s",
port, host));
- conn = silc_client_add_connection(client, host, port, context);
+ conn = silc_client_add_connection(client, params, host, port, context);
client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
"Connecting to port %d of server %s", port, host);
void silc_client_resolve_auth_method(bool success,
SilcProtocolAuthMeth auth_meth,
const unsigned char *auth_data,
- uint32 auth_data_len, void *context)
+ SilcUInt32 auth_data_len, void *context)
{
SilcClientConnAuthInternalContext *proto_ctx =
(SilcClientConnAuthInternalContext *)context;
proto_ctx->auth_meth = auth_meth;
if (auth_data && auth_data_len) {
- proto_ctx->auth_data = silc_calloc(auth_data_len, sizeof(*auth_data));
- memcpy(proto_ctx->auth_data, auth_data, auth_data_len);
+ proto_ctx->auth_data = silc_memdup(auth_data, auth_data_len);
proto_ctx->auth_data_len = auth_data_len;
}
if (SILC_IS_DISCONNECTED(sock))
return;
- if (sock->outbuf->data - sock->outbuf->head)
- silc_buffer_push(sock->outbuf, sock->outbuf->data - sock->outbuf->head);
-
ret = silc_packet_send(sock, TRUE);
/* If returned -2 could not write to connection now, will do
if (SILC_IS_DISCONNECTING(sock)) {
if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT)
client->internal->ops->disconnect(client, conn);
- silc_client_close_connection(client, sock, conn);
+ silc_client_close_connection_real(client, sock, conn);
return;
}
SILC_LOG_DEBUG(("EOF from connection %d", sock->sock));
if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT)
client->internal->ops->disconnect(client, conn);
- silc_client_close_connection(client, sock, conn);
+ silc_client_close_connection_real(client, sock, conn);
return;
}
SilcCipher cipher,
SilcHmac hmac,
unsigned char *data,
- uint32 data_len,
+ SilcUInt32 data_len,
int force_send)
{
SilcPacketContext packetdata;
+ const SilcBufferStruct packet;
int block_len;
- uint32 sequence = 0;
+ SilcUInt32 sequence = 0;
if (!sock)
return;
packetdata.dst_id_len = 0;
packetdata.dst_id_type = SILC_ID_NONE;
}
+ data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN +
+ packetdata.src_id_len +
+ packetdata.dst_id_len));
packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
packetdata.src_id_len + packetdata.dst_id_len;
packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen, block_len);
- /* Prepare outgoing data buffer for packet sending */
- silc_packet_send_prepare(sock,
- SILC_PACKET_HEADER_LEN +
- packetdata.src_id_len +
- packetdata.dst_id_len,
- packetdata.padlen,
- data_len);
-
- SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len));
-
- packetdata.buffer = sock->outbuf;
-
- /* Put the data to the buffer */
- if (data && data_len)
- silc_buffer_put(sock->outbuf, data, data_len);
-
/* Create the outgoing packet */
- silc_packet_assemble(&packetdata, cipher);
+ if (!silc_packet_assemble(&packetdata, client->rng, cipher, hmac, sock,
+ data, data_len, (const SilcBuffer)&packet)) {
+ SILC_LOG_ERROR(("Error assembling packet"));
+ return;
+ }
/* Encrypt the packet */
if (cipher)
- silc_packet_encrypt(cipher, hmac, sequence, sock->outbuf,
- sock->outbuf->len);
+ silc_packet_encrypt(cipher, hmac, sequence, (SilcBuffer)&packet,
+ packet.len);
- SILC_LOG_HEXDUMP(("Packet (%d), len %d", sequence, sock->outbuf->len),
- sock->outbuf->data, sock->outbuf->len);
+ SILC_LOG_HEXDUMP(("Packet (%d), len %d", sequence, packet.len),
+ packet.data, packet.len);
/* Now actually send the packet */
silc_client_packet_send_real(client, sock, force_send);
{
if (sock && SILC_IS_OUTBUF_PENDING(sock) &&
(SILC_IS_DISCONNECTED(sock) == FALSE)) {
- if (sock->outbuf->data - sock->outbuf->head)
- silc_buffer_push(sock->outbuf, sock->outbuf->data - sock->outbuf->head);
-
silc_packet_send(sock, TRUE);
-
SILC_CLIENT_SET_CONNECTION_FOR_INPUT(client->schedule, sock->sock);
SILC_UNSET_OUTBUF_PENDING(sock);
silc_buffer_clear(sock->outbuf);
connection but `conn->sock' might be actually a different connection
than the `sock'). */
-void silc_client_close_connection(SilcClient client,
- SilcSocketConnection sock,
- SilcClientConnection conn)
+void silc_client_close_connection_real(SilcClient client,
+ SilcSocketConnection sock,
+ SilcClientConnection conn)
{
int del = FALSE;
silc_socket_free(sock);
}
+/* Closes the connection to the remote end */
+
+void silc_client_close_connection(SilcClient client,
+ SilcClientConnection conn)
+{
+ silc_client_close_connection_real(client, NULL, conn);
+}
+
/* Called when we receive disconnection packet from server. This
closes our end properly and displays the reason of the disconnection
on the screen. */
if (sock == NULL)
return;
- silc_client_close_connection(client, sock, sock->user_data);
+ silc_client_close_connection_real(client, sock, sock->user_data);
}
/* Called when we receive disconnection packet from server. This
SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
- msg = silc_calloc(message->len + 1, sizeof(char));
- memcpy(msg, message->data, message->len);
+ msg = silc_memdup(message->data, message->len);
client->internal->ops->say(client, sock->user_data,
SILC_CLIENT_MESSAGE_AUDIT, msg);
silc_free(msg);
{
char *msg;
- msg = silc_calloc(message->len + 1, sizeof(char));
- memcpy(msg, message->data, message->len);
+ msg = silc_memdup(message->data, message->len);
client->internal->ops->say(client, sock->user_data,
SILC_CLIENT_MESSAGE_AUDIT, msg);
silc_free(msg);
conn->local_entry->username = strdup(client->username);
if (!conn->local_entry->hostname)
conn->local_entry->hostname = strdup(client->hostname);
- conn->local_entry->server = strdup(conn->remote_host);
+ if (!conn->local_entry->server)
+ conn->local_entry->server = strdup(conn->remote_host);
conn->local_entry->id = conn->local_id;
conn->local_entry->valid = TRUE;
- conn->local_entry->channels = silc_hash_table_alloc(1, silc_hash_ptr,
- NULL, NULL,
- NULL, NULL, NULL, TRUE);
+ if (!conn->local_entry->channels)
+ conn->local_entry->channels = silc_hash_table_alloc(1, silc_hash_ptr,
+ NULL, NULL,
+ NULL, NULL, NULL,
+ TRUE);
/* Put it to the ID cache */
silc_idcache_add(conn->client_cache, strdup(conn->nickname), conn->local_id,
SilcChannelUser chu;
silc_hash_table_list(client_entry->channels, &htl);
- while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
+ while (silc_hash_table_get(&htl, NULL, (void **)&chu)) {
silc_hash_table_del(chu->client->channels, chu->channel);
silc_hash_table_del(chu->channel->user_list, chu->client);
silc_free(chu);
}
+
silc_hash_table_list_reset(&htl);
}
SilcChannelUser chu;
silc_hash_table_list(old->channels, &htl);
- while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
+ while (silc_hash_table_get(&htl, NULL, (void **)&chu)) {
/* Replace client entry */
silc_hash_table_del(chu->client->channels, chu->channel);
silc_hash_table_del(chu->channel->user_list, chu->client);
SilcSocketConnection sock,
SilcPacketContext *packet)
{
- uint32 failure = 0;
+ SilcUInt32 failure = 0;
if (sock->protocol) {
if (packet->buffer->len >= 4)
SilcPacketContext *packet)
{
SilcClientConnection conn = (SilcClientConnection)sock->user_data;
- uint16 conn_type, auth_meth;
+ SilcUInt16 conn_type, auth_meth;
int ret;
/* If we haven't send our request then ignore this one. */
client->internal->params->connauth_request_secs, 0,
SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
}
+
+SilcBuffer silc_client_get_detach_data(SilcClient client,
+ SilcClientConnection conn)
+{
+ SilcBuffer detach;
+ SilcHashTableList htl;
+ SilcChannelUser chu;
+
+ SILC_LOG_DEBUG(("Creating detachment data"));
+
+ /* Save the nickname, Client ID and user mode in SILC network */
+ detach = silc_buffer_alloc_size(2 + strlen(conn->nickname) +
+ 2 + conn->local_id_data_len + 4);
+ silc_buffer_format(detach,
+ SILC_STR_UI_SHORT(strlen(conn->nickname)),
+ SILC_STR_UI_XNSTRING(conn->nickname,
+ strlen(conn->nickname)),
+ SILC_STR_UI_SHORT(conn->local_id_data_len),
+ SILC_STR_UI_XNSTRING(conn->local_id_data,
+ conn->local_id_data_len),
+ SILC_STR_UI_INT(conn->local_entry->mode),
+ SILC_STR_END);
+
+ /* Save all joined channels */
+ silc_hash_table_list(conn->local_entry->channels, &htl);
+ while (silc_hash_table_get(&htl, NULL, (void **)&chu)) {
+ unsigned char *chid = silc_id_id2str(chu->channel->id, SILC_ID_CHANNEL);
+ SilcUInt16 chid_len = silc_id_get_len(chu->channel->id, SILC_ID_CHANNEL);
+
+ detach = silc_buffer_realloc(detach, detach->truelen + 2 +
+ strlen(chu->channel->channel_name) +
+ 2 + chid_len + 4);
+ silc_buffer_pull(detach, detach->len);
+ silc_buffer_format(detach,
+ SILC_STR_UI_SHORT(strlen(chu->channel->channel_name)),
+ SILC_STR_UI_XNSTRING(chu->channel->channel_name,
+ strlen(chu->channel->channel_name)),
+ SILC_STR_UI_SHORT(chid_len),
+ SILC_STR_UI_XNSTRING(chid, chid_len),
+ SILC_STR_UI_INT(chu->channel->mode),
+ SILC_STR_END);
+
+ silc_free(chid);
+ }
+ silc_hash_table_list_reset(&htl);
+
+ silc_buffer_push(detach, detach->data - detach->head);
+
+ SILC_LOG_HEXDUMP(("Detach data"), detach->data, detach->len);
+
+ return detach;
+}