+ /* Calculate the length of the padding. The padding is calculated from
+ the data that will be encrypted. */
+ if (!ctx->padlen) {
+ if (ctx->long_pad)
+ ctx->padlen = SILC_PACKET_PADLEN_MAX(ctx->truelen);
+ else
+ ctx->padlen = SILC_PACKET_PADLEN(ctx->truelen, block_len);
+ }
+
+ /* Put the start of the data section to the right place. */
+ silc_buffer_push(ctx->buffer, SILC_PACKET_HEADER_LEN +
+ ctx->src_id_len + ctx->dst_id_len + ctx->padlen);
+
+ /* Get random padding */
+#if 1
+ for (i = 0; i < ctx->padlen; i++) tmppad[i] =
+ silc_rng_global_get_byte_fast();
+#else
+ /* XXX: For testing - to be removed */
+ memset(tmppad, 65, sizeof(tmppad));
+#endif
+
+ /* Create the packet. This creates the SILC header and adds padding,
+ rest of the buffer remains as it is. */
+ silc_buffer_format(ctx->buffer,
+ SILC_STR_UI_SHORT(ctx->truelen),
+ SILC_STR_UI_CHAR(ctx->flags),
+ SILC_STR_UI_CHAR(ctx->type),
+ SILC_STR_UI_CHAR(ctx->padlen),
+ SILC_STR_UI_CHAR(0),
+ SILC_STR_UI_CHAR(ctx->src_id_len),
+ SILC_STR_UI_CHAR(ctx->dst_id_len),
+ SILC_STR_UI_CHAR(ctx->src_id_type),
+ SILC_STR_UI_XNSTRING(ctx->src_id, ctx->src_id_len),
+ SILC_STR_UI_CHAR(ctx->dst_id_type),
+ SILC_STR_UI_XNSTRING(ctx->dst_id, ctx->dst_id_len),
+ SILC_STR_UI_XNSTRING(tmppad, ctx->padlen),
+ SILC_STR_END);
+
+ SILC_LOG_HEXDUMP(("Assembled packet, len %d", ctx->buffer->len),
+ ctx->buffer->data, ctx->buffer->len);
+
+ SILC_LOG_DEBUG(("Outgoing packet assembled"));
+}
+
+/* Prepare outgoing data buffer for packet sending. This moves the data
+ area so that new packet may be added into it. If needed this allocates
+ more space to the buffer. This handles directly the connection's
+ outgoing buffer in SilcSocketConnection object. */
+
+void silc_packet_send_prepare(SilcSocketConnection sock,
+ SilcUInt32 header_len,
+ SilcUInt32 padlen,
+ SilcUInt32 data_len)
+{
+ int totlen, oldlen;
+
+ totlen = header_len + padlen + data_len;
+
+ /* Prepare the outgoing buffer for packet sending. */
+ if (!sock->outbuf) {
+ /* Allocate new buffer. This is done only once per connection. */
+ SILC_LOG_DEBUG(("Allocating outgoing data buffer"));
+
+ if (totlen > SILC_PACKET_DEFAULT_SIZE)
+ sock->outbuf = silc_buffer_alloc(totlen);
+ else
+ sock->outbuf = silc_buffer_alloc(SILC_PACKET_DEFAULT_SIZE);
+ silc_buffer_pull_tail(sock->outbuf, totlen);
+ silc_buffer_pull(sock->outbuf, header_len + padlen);
+ } else {
+ if (SILC_IS_OUTBUF_PENDING(sock)) {
+ /* There is some pending data in the buffer. */
+
+ /* Allocate more space if needed */
+ if ((sock->outbuf->end - sock->outbuf->tail) <
+ (totlen + 20)) {
+ SILC_LOG_DEBUG(("Reallocating outgoing data buffer"));
+ sock->outbuf = silc_buffer_realloc(sock->outbuf,
+ sock->outbuf->truelen +
+ (totlen * 2));
+ }
+
+ oldlen = sock->outbuf->len;
+ silc_buffer_pull_tail(sock->outbuf, totlen);
+ silc_buffer_pull(sock->outbuf, header_len + padlen + oldlen);
+ } else {
+ /* Buffer is free for use */
+ silc_buffer_clear(sock->outbuf);
+
+ /* Allocate more space if needed */
+ if ((sock->outbuf->end - sock->outbuf->tail) < (totlen + 20)) {
+ SILC_LOG_DEBUG(("Reallocating outgoing data buffer"));
+ sock->outbuf = silc_buffer_realloc(sock->outbuf,
+ sock->outbuf->truelen +
+ (totlen * 2));
+ }
+
+ silc_buffer_pull_tail(sock->outbuf, totlen);
+ silc_buffer_pull(sock->outbuf, header_len + padlen);