client.c
- Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+ Author: Pekka Riikonen <priikone@silcnet.org>
Copyright (C) 1997 - 2001 Pekka Riikonen
if (params)
memcpy(new_client->params, params, sizeof(*params));
+ if (!new_client->params->task_max)
+ new_client->params->task_max = 200;
+
if (!new_client->params->rekey_secs)
new_client->params->rekey_secs = 3600;
if (!new_client->params->connauth_request_secs)
new_client->params->connauth_request_secs = 2;
+ new_client->params->
+ nickname_format[sizeof(new_client->params->nickname_format) - 1] = 0;
+
return new_client;
}
silc_schedule(client->schedule);
}
+static void silc_client_entry_destructor(SilcIDCache cache,
+ SilcIDCacheEntry entry)
+{
+ silc_free(entry->name);
+}
+
/* Allocates and adds new connection to the client. This adds the allocated
connection to the connection table and returns a pointer to it. A client
can have multiple connections to multiple servers. Every connection must
conn = silc_calloc(1, sizeof(*conn));
/* Initialize ID caches */
- conn->client_cache = silc_idcache_alloc(0, SILC_ID_CLIENT, NULL);
+ conn->client_cache = silc_idcache_alloc(0, SILC_ID_CLIENT,
+ silc_client_entry_destructor);
conn->channel_cache = silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL);
conn->server_cache = silc_idcache_alloc(0, SILC_ID_SERVER, NULL);
conn->client = client;
used only if the application performed the connecting outside the library.
The library however may use this internally. */
-int silc_client_start_key_exchange(SilcClient client,
- SilcClientConnection conn,
- int fd)
+bool silc_client_start_key_exchange(SilcClient client,
+ SilcClientConnection conn,
+ int fd)
{
SilcProtocol protocol;
SilcClientKEInternalContext *proto_ctx;
silc_client_connect_to_server_second);
if (!protocol) {
client->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
- "Error: Could not start authentication protocol");
+ "Error: Could not start key exchange protocol");
return FALSE;
}
conn->sock->protocol = protocol;
int silc_client_packet_send_real(SilcClient client,
SilcSocketConnection sock,
- bool force_send,
- bool flush)
+ bool force_send)
{
int ret;
/* If rekey protocol is active we must assure that all packets are
sent through packet queue. */
- if (flush == FALSE && SILC_CLIENT_IS_REKEY(sock))
+ if (SILC_CLIENT_IS_REKEY(sock))
+ force_send = FALSE;
+
+ /* If outbound data is already pending do not force send */
+ if (SILC_IS_OUTBUF_PENDING(sock))
force_send = FALSE;
/* Send the packet */
/* Packet sending */
if (type == SILC_TASK_WRITE) {
- SILC_LOG_DEBUG(("Writing data to connection"));
+ /* Do not send data to disconnected connection */
+ if (SILC_IS_DISCONNECTED(sock))
+ return;
if (sock->outbuf->data - sock->outbuf->head)
- silc_buffer_push(sock->outbuf,
- sock->outbuf->data - sock->outbuf->head);
+ silc_buffer_push(sock->outbuf, sock->outbuf->data - sock->outbuf->head);
- ret = silc_client_packet_send_real(client, sock, TRUE, TRUE);
+ ret = silc_packet_send(sock, TRUE);
/* If returned -2 could not write to connection now, will do
it later. */
if (ret == -2)
return;
+
+ /* Error */
+ if (ret == -1)
+ return;
/* The packet has been sent and now it is time to set the connection
back to only for input. When there is again some outgoing data
/* Packet receiving */
if (type == SILC_TASK_READ) {
- SILC_LOG_DEBUG(("Reading data from connection"));
-
/* Read data from network */
ret = silc_packet_receive(sock);
if (ret < 0)
silc_client_connection_auth_request(client, sock, packet);
break;
+ case SILC_PACKET_FTP:
+ /* Received file transfer packet. */
+ silc_client_ftp(client, sock, packet);
+ break;
+
default:
SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
break;
sock->outbuf->data, sock->outbuf->len);
/* Now actually send the packet */
- silc_client_packet_send_real(client, sock, force_send, FALSE);
+ silc_client_packet_send_real(client, sock, force_send);
+}
+
+void silc_client_packet_queue_purge(SilcClient client,
+ SilcSocketConnection sock)
+{
+ 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);
+ }
}
/* Closes connection to remote end. Free's all allocated data except
conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
conn->local_entry->nickname = conn->nickname;
- if (!conn->local_entry->username) {
- conn->local_entry->username =
- silc_calloc(strlen(client->username) + strlen(client->hostname) + 1,
- sizeof(conn->local_entry->username));
- sprintf(conn->local_entry->username, "%s@%s", client->username,
- client->hostname);
- }
+ if (!conn->local_entry->username)
+ 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);
conn->local_entry->id = conn->local_id;
+ conn->local_entry->valid = TRUE;
/* Put it to the ID cache */
- silc_idcache_add(conn->client_cache, conn->nickname, conn->local_id,
+ silc_idcache_add(conn->client_cache, strdup(conn->nickname), conn->local_id,
(void *)conn->local_entry, FALSE);
/* Issue INFO command to fetch the real server name and server information
return;
}
+ /* Purge the outgoing data queue to assure that all rekey packets really
+ go to the network before we quit the protocol. */
+ silc_client_packet_queue_purge(client, sock);
+
/* Cleanup */
silc_protocol_free(protocol);
sock->protocol = NULL;
conn, client->params->connauth_request_secs, 0,
SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
}
+
+/* Called when file transfer packet is received. This will parse the
+ packet and give it to the file transfer protocol. */
+
+void silc_client_ftp(SilcClient client,
+ SilcSocketConnection sock,
+ SilcPacketContext *packet)
+{
+ SilcClientConnection conn = (SilcClientConnection)sock->user_data;
+ uint8 type;
+ int ret;
+
+ /* Parse the payload */
+ ret = silc_buffer_unformat(packet->buffer,
+ SILC_STR_UI_CHAR(&type),
+ SILC_STR_END);
+ if (ret == -1)
+ return;
+
+ /* We support only type number 1 (== SFTP) */
+ if (type != 1)
+ return;
+
+ silc_buffer_pull(packet->buffer, 1);
+
+ /* Give it to the file transfer protocol processor. */
+ //silc_sftp_client_receive_process(xxx, sock, packet);
+}