void silc_client_send_private_message(SilcClient client,
SilcClientConnection conn,
SilcClientEntry client_entry,
+ SilcMessageFlags flags,
unsigned char *data,
- unsigned int data_len,
+ uint32 data_len,
int force_send)
{
SilcSocketConnection sock = conn->sock;
SilcBuffer buffer;
SilcPacketContext packetdata;
- unsigned int nick_len;
SilcCipher cipher;
SilcHmac hmac;
SILC_LOG_DEBUG(("Sending private message"));
- /* Create private message payload */
- nick_len = strlen(conn->nickname);
- buffer = silc_buffer_alloc(2 + nick_len + data_len);
- silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
- silc_buffer_format(buffer,
- SILC_STR_UI_SHORT(nick_len),
- SILC_STR_UI_XNSTRING(conn->nickname,
- nick_len),
- SILC_STR_UI_XNSTRING(data, data_len),
- SILC_STR_END);
+ /* Encode private message payload */
+ buffer = silc_private_message_payload_encode(flags, strlen(conn->nickname),
+ conn->nickname,
+ data_len, data,
+ client_entry->send_key);
/* If we don't have private message specific key then private messages
are just as any normal packet thus call normal packet sending. If
/* Get data used in the encryption */
cipher = client_entry->send_key;
- hmac = conn->hmac;
+ hmac = conn->hmac_send;
/* Set the packet context pointers. */
packetdata.flags = SILC_PACKET_FLAG_PRIVMSG_KEY;
packetdata.buffer = sock->outbuf;
- /* Encrypt payload of the packet. Encrypt with private message specific
- key */
- cipher->cipher->encrypt(cipher->context, buffer->data, buffer->data,
- buffer->len, cipher->iv);
-
- /* Put the actual encrypted payload data into the buffer. */
+ /* Put the actual encrypted message payload data into the buffer. */
silc_buffer_put(sock->outbuf, buffer->data, buffer->len);
/* Create the outgoing packet */
sock->outbuf->data, sock->outbuf->len);
/* Now actually send the packet */
- silc_client_packet_send_real(client, sock, force_send);
+ silc_client_packet_send_real(client, sock, force_send, FALSE);
silc_free(packetdata.dst_id);
out:
- silc_free(buffer);
+ silc_buffer_free(buffer);
}
+static void silc_client_private_message_cb(SilcClient client,
+ SilcClientConnection conn,
+ SilcClientEntry *clients,
+ uint32 clients_count,
+ void *context)
+{
+ SilcPacketContext *packet = (SilcPacketContext *)context;
+
+ silc_client_private_message(client, conn->sock, packet);
+ silc_packet_context_free(packet);
+}
+
/* Private message received. This processes the private message and
finally displays it on the screen. */
SilcPacketContext *packet)
{
SilcClientConnection conn = (SilcClientConnection)sock->user_data;
- SilcBuffer buffer = packet->buffer;
+ SilcPrivateMessagePayload payload = NULL;
SilcIDCacheEntry id_cache;
SilcClientID *remote_id = NULL;
SilcClientEntry remote_client;
- unsigned short nick_len;
- unsigned char *nickname, *message = NULL;
- int ret;
if (packet->src_id_type != SILC_ID_CLIENT)
goto out;
- /* Get nickname */
- ret = silc_buffer_unformat(buffer,
- SILC_STR_UI16_NSTRING_ALLOC(&nickname, &nick_len),
- SILC_STR_END);
- if (ret == -1)
- return;
-
- silc_buffer_pull(buffer, 2 + nick_len);
-
- message = silc_calloc(buffer->len + 1, sizeof(char));
- memcpy(message, buffer->data, buffer->len);
-
remote_id = silc_id_str2id(packet->src_id, packet->src_id_len,
SILC_ID_CLIENT);
if (!remote_id)
/* Check whether we know this client already */
if (!silc_idcache_find_by_id_one(conn->client_cache, remote_id,
- SILC_ID_CLIENT, &id_cache))
- {
- /* Allocate client entry */
- remote_client = silc_calloc(1, sizeof(*remote_client));
- remote_client->id = silc_id_dup(remote_id, SILC_ID_CLIENT);
- silc_parse_nickname(nickname, &remote_client->nickname,
- &remote_client->server, &remote_client->num);
-
- /* Save the client to cache */
- silc_idcache_add(conn->client_cache, remote_client->nickname,
- SILC_ID_CLIENT, remote_client->id, remote_client,
- TRUE);
- } else {
- remote_client = (SilcClientEntry)id_cache->context;
- }
+ SILC_ID_CLIENT, &id_cache)) {
+ /* Resolve the client info */
+ silc_client_get_client_by_id_resolve(client, conn, remote_id,
+ silc_client_private_message_cb,
+ silc_packet_context_dup(packet));
+ return;
+ }
+
+ remote_client = (SilcClientEntry)id_cache->context;
+
+ /* Parse the payload and decrypt it also if private message key is set */
+ payload = silc_private_message_payload_parse(packet->buffer,
+ remote_client->send_key);
+ if (!payload) {
+ silc_free(remote_id);
+ return;
+ }
/* Pass the private message to application */
- client->ops->private_message(client, conn, remote_client, message);
+ client->ops->private_message(client, conn, remote_client,
+ silc_private_message_get_flags(payload),
+ silc_private_message_get_message(payload,
+ NULL));
/* See if we are away (gone). If we are away we will reply to the
sender with the set away message. */
/* Send the away message */
silc_client_send_private_message(client, conn, remote_client,
+ SILC_MESSAGE_FLAG_AUTOREPLY,
conn->away->away,
strlen(conn->away->away), TRUE);
}
out:
+ if (payload)
+ silc_private_message_payload_free(payload);
if (remote_id)
silc_free(remote_id);
-
- if (message) {
- memset(message, 0, buffer->len);
- silc_free(message);
- }
- silc_free(nickname);
}
/* Function that actually employes the received private message key */
static void silc_client_private_message_key_cb(SilcClient client,
SilcClientConnection conn,
SilcClientEntry *clients,
- unsigned int clients_count,
+ uint32 clients_count,
void *context)
{
SilcPacketContext *packet = (SilcPacketContext *)context;
unsigned char *key;
- unsigned short key_len;
+ uint16 key_len;
unsigned char *cipher;
int ret;
SilcClientEntry client_entry,
char *cipher,
unsigned char *key,
- unsigned int key_len,
+ uint32 key_len,
int generate_key)
{
unsigned char private_key[32];
- unsigned int len;
+ uint32 len;
int i;
SilcSKEKeyMaterial *keymat;
return FALSE;
/* Generate key if not provided */
- if (!key && generate_key == TRUE) {
+ if (generate_key == TRUE) {
len = 32;
for (i = 0; i < len; i++) private_key[i] = silc_rng_get_byte(client->rng);
key = private_key;
SilcPrivateMessageKeys
silc_client_list_private_message_keys(SilcClient client,
SilcClientConnection conn,
- unsigned int *key_count)
+ uint32 *key_count)
{
SilcPrivateMessageKeys keys;
- unsigned int count = 0;
+ uint32 count = 0;
SilcIDCacheEntry id_cache;
SilcIDCacheList list;
SilcClientEntry entry;
silc_client_list_private_message_keys. */
void silc_client_free_private_message_keys(SilcPrivateMessageKeys keys,
- unsigned int key_count)
+ uint32 key_count)
{
silc_free(keys);
}