Added silc_buffer_steal. Optimized some encoding and decoding
authorPekka Riikonen <priikone@silcnet.org>
Tue, 14 Jan 2003 11:43:37 +0000 (11:43 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Tue, 14 Jan 2003 11:43:37 +0000 (11:43 +0000)
routines.

CHANGES
lib/silccore/silcauth.c
lib/silccrypt/silcpkcs.c
lib/silcutil/silcbuffer.h
lib/silcutil/win32/silcwin32schedule.c

diff --git a/CHANGES b/CHANGES
index 7f5327182ccd0eae12e9573b3aee6688c6ab0697..4a253690b60a789c7fab821ea6ceda9ece1527cc 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,8 @@
+Tue Jan 14 12:25:09 CET 2003 Pekka Riikonen <priikone@silcnet.org>
+
+       * Added silc_buffer_steal to steal the data from the buffer.
+         Affected file lib/silcutil/silcbuffer.h.
+
 Sat Jan 11 18:16:29 CET 2003  Giovanni Giacobbi <giovanni@giacobbi.net>
 
        * Fixed server crash with double Primary block in config file.
index 38a1a961392e87fe668cd7110f48dc0418990780..d42dd66fb0ba747268f7a25cc28e46e11b541f2f 100644 (file)
@@ -216,14 +216,8 @@ silc_auth_public_key_encode_data(SilcPublicKey public_key,
                     SILC_STR_UI_XNSTRING(pk, pk_len),
                     SILC_STR_END);
 
-  ret = silc_memdup(buf->data, buf->len);
-  if (!ret)
-    return NULL;
-
-  if (ret_len)
-    *ret_len = buf->len;
+  ret = silc_buffer_steal(buf, ret_len);
 
-  silc_buffer_clear(buf);
   silc_buffer_free(buf);
   silc_free(id_data);
   silc_free(pk);
index 4deddfd96f33b063277784024cd7f1861b4bb98d..83a16d005e4bb6073164dfbc77d171d21c95e274 100644 (file)
@@ -687,8 +687,9 @@ silc_pkcs_public_key_encode(SilcPublicKey public_key, SilcUInt32 *len)
   SilcBuffer buf;
   unsigned char *ret;
 
-  buf = silc_buffer_alloc(public_key->len + 4);
-  silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
+  buf = silc_buffer_alloc_size(public_key->len + 4);
+  if (!buf)
+    return NULL;
 
   silc_buffer_format(buf,
                     SILC_STR_UI_INT(public_key->len),
@@ -699,13 +700,9 @@ silc_pkcs_public_key_encode(SilcPublicKey public_key, SilcUInt32 *len)
                     SILC_STR_UI_XNSTRING(public_key->pk, 
                                          public_key->pk_len),
                     SILC_STR_END);
-  if (len)
-    *len = public_key->len + 4;
 
-  ret = silc_calloc(buf->len, sizeof(*ret));
-  memcpy(ret, buf->data, buf->len);
+  ret = silc_buffer_steal(buf, len);
   silc_buffer_free(buf);
-
   return ret;
 }
 
@@ -721,8 +718,9 @@ silc_pkcs_public_key_data_encode(unsigned char *pk, SilcUInt32 pk_len,
   SilcUInt32 totlen;
 
   totlen = 2 + strlen(pkcs) + 2 + strlen(identifier) + pk_len;
-  buf = silc_buffer_alloc(totlen + 4);
-  silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
+  buf = silc_buffer_alloc_size(totlen + 4);
+  if (!buf)
+    return NULL;
 
   silc_buffer_format(buf,
                     SILC_STR_UI_INT(totlen),
@@ -732,13 +730,9 @@ silc_pkcs_public_key_data_encode(unsigned char *pk, SilcUInt32 pk_len,
                     SILC_STR_UI32_STRING(identifier),
                     SILC_STR_UI_XNSTRING(pk, pk_len),
                     SILC_STR_END);
-  if (len)
-    *len = totlen + 4;
 
-  ret = silc_calloc(buf->len, sizeof(*ret));
-  memcpy(ret, buf->data, buf->len);
+  ret = silc_buffer_steal(buf, len);
   silc_buffer_free(buf);
-
   return ret;
 }
 
@@ -748,40 +742,34 @@ silc_pkcs_public_key_data_encode(unsigned char *pk, SilcUInt32 pk_len,
 bool silc_pkcs_public_key_decode(unsigned char *data, SilcUInt32 data_len,
                                 SilcPublicKey *public_key)
 {
-  SilcBuffer buf;
+  SilcBufferStruct buf;
   SilcPKCS alg;
   SilcUInt16 pkcs_len, identifier_len;
   SilcUInt32 totlen, key_len;
   unsigned char *pkcs_name = NULL, *ident = NULL, *key_data = NULL;
   int ret;
 
-  buf = silc_buffer_alloc(data_len);
-  silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
-  silc_buffer_put(buf, data, data_len);
+  silc_buffer_set(&buf, data, data_len);
 
   /* Get length */
-  ret = silc_buffer_unformat(buf,
+  ret = silc_buffer_unformat(&buf,
                             SILC_STR_UI_INT(&totlen),
                             SILC_STR_END);
-  if (ret == -1) {
-    silc_buffer_free(buf);
+  if (ret == -1)
     return FALSE;
-  }
 
 #if 1 /* Backwards support, remove! */
   if (totlen == data_len)
     totlen -= 4;
 #endif
 
-  if (totlen + 4 != data_len) {
-    silc_buffer_free(buf);
+  if (totlen + 4 != data_len)
     return FALSE;
-  }
 
   /* Get algorithm name and identifier */
-  silc_buffer_pull(buf, 4);
+  silc_buffer_pull(&buf, 4);
   ret =
-    silc_buffer_unformat(buf,
+    silc_buffer_unformat(&buf,
                         SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
                         SILC_STR_UI16_NSTRING_ALLOC(&ident, &identifier_len),
                         SILC_STR_END);
@@ -807,9 +795,9 @@ bool silc_pkcs_public_key_decode(unsigned char *data, SilcUInt32 data_len,
   }
 
   /* Get key data. We assume that rest of the buffer is key data. */
-  silc_buffer_pull(buf, 2 + pkcs_len + 2 + identifier_len);
-  key_len = buf->len;
-  ret = silc_buffer_unformat(buf,
+  silc_buffer_pull(&buf, 2 + pkcs_len + 2 + identifier_len);
+  key_len = buf.len;
+  ret = silc_buffer_unformat(&buf,
                             SILC_STR_UI_XNSTRING_ALLOC(&key_data, key_len),
                             SILC_STR_END);
   if (ret == -1)
@@ -835,17 +823,12 @@ bool silc_pkcs_public_key_decode(unsigned char *data, SilcUInt32 data_len,
     (*public_key)->pk_type = SILC_SKE_PK_TYPE_SILC;
   }
 
-  silc_buffer_free(buf);
   return TRUE;
 
  err:
-  if (pkcs_name)
-    silc_free(pkcs_name);
-  if (ident)
-    silc_free(ident);
-  if (key_data)
-    silc_free(key_data);
-  silc_buffer_free(buf);
+  silc_free(pkcs_name);
+  silc_free(ident);
+  silc_free(key_data);
   return FALSE;
 }
 
@@ -971,8 +954,9 @@ silc_pkcs_private_key_encode(SilcPrivateKey private_key, SilcUInt32 *len)
   SilcUInt32 totlen;
 
   totlen = 2 + strlen(private_key->name) + private_key->prv_len;
-  buf = silc_buffer_alloc(totlen);
-  silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
+  buf = silc_buffer_alloc_size(totlen);
+  if (!buf)
+    return NULL;
 
   silc_buffer_format(buf,
                     SILC_STR_UI_SHORT(strlen(private_key->name)),
@@ -980,14 +964,9 @@ silc_pkcs_private_key_encode(SilcPrivateKey private_key, SilcUInt32 *len)
                     SILC_STR_UI_XNSTRING(private_key->prv, 
                                          private_key->prv_len),
                     SILC_STR_END);
-  if (len)
-    *len = totlen;
 
-  ret = silc_calloc(buf->len, sizeof(*ret));
-  memcpy(ret, buf->data, buf->len);
-  silc_buffer_clear(buf);
+  ret = silc_buffer_steal(buf, len);
   silc_buffer_free(buf);
-
   return ret;
 }
 
@@ -1002,22 +981,18 @@ silc_pkcs_private_key_data_encode(unsigned char *prv, SilcUInt32 prv_len,
   SilcUInt32 totlen;
 
   totlen = 2 + strlen(pkcs) + prv_len;
-  buf = silc_buffer_alloc(totlen);
-  silc_buffer_pull_tail(buf, totlen);
+  buf = silc_buffer_alloc_size(totlen);
+  if (!buf)
+    return NULL;
 
   silc_buffer_format(buf,
                     SILC_STR_UI_SHORT(strlen(pkcs)),
                     SILC_STR_UI32_STRING(pkcs),
                     SILC_STR_UI_XNSTRING(prv, prv_len),
                     SILC_STR_END);
-  if (len)
-    *len = totlen;
 
-  ret = silc_calloc(buf->len, sizeof(*ret));
-  memcpy(ret, buf->data, buf->len);
-  silc_buffer_clear(buf);
+  ret = silc_buffer_steal(buf, len);
   silc_buffer_free(buf);
-
   return ret;
 }
 
@@ -1027,20 +1002,18 @@ silc_pkcs_private_key_data_encode(unsigned char *prv, SilcUInt32 prv_len,
 bool silc_pkcs_private_key_decode(unsigned char *data, SilcUInt32 data_len,
                                  SilcPrivateKey *private_key)
 {
-  SilcBuffer buf;
+  SilcBufferStruct buf;
   SilcPKCS alg;
   SilcUInt16 pkcs_len;
   SilcUInt32 key_len;
   unsigned char *pkcs_name = NULL, *key_data = NULL;
   int ret;
 
-  buf = silc_buffer_alloc(data_len);
-  silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
-  silc_buffer_put(buf, data, data_len);
+  silc_buffer_set(&buf, data, data_len);
 
   /* Get algorithm name and identifier */
   ret = 
-    silc_buffer_unformat(buf,
+    silc_buffer_unformat(&buf,
                         SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
                         SILC_STR_END);
   if (ret == -1) {
@@ -1048,7 +1021,7 @@ bool silc_pkcs_private_key_decode(unsigned char *data, SilcUInt32 data_len,
     goto err;
   }
 
-  if (pkcs_len < 1 || pkcs_len > buf->truelen) {
+  if (pkcs_len < 1 || pkcs_len > buf.truelen) {
     SILC_LOG_DEBUG(("Malformed private key buffer"));
     goto err;
   }
@@ -1060,9 +1033,9 @@ bool silc_pkcs_private_key_decode(unsigned char *data, SilcUInt32 data_len,
   }
 
   /* Get key data. We assume that rest of the buffer is key data. */
-  silc_buffer_pull(buf, 2 + pkcs_len);
-  key_len = buf->len;
-  ret = silc_buffer_unformat(buf,
+  silc_buffer_pull(&buf, 2 + pkcs_len);
+  key_len = buf.len;
+  ret = silc_buffer_unformat(&buf,
                             SILC_STR_UI_XNSTRING_ALLOC(&key_data, key_len),
                             SILC_STR_END);
   if (ret == -1)
@@ -1087,17 +1060,11 @@ bool silc_pkcs_private_key_decode(unsigned char *data, SilcUInt32 data_len,
     (*private_key)->prv_len = key_len;
   }
 
-  silc_buffer_clear(buf);
-  silc_buffer_free(buf);
   return TRUE;
 
  err:
-  if (pkcs_name)
-    silc_free(pkcs_name);
-  if (key_data)
-    silc_free(key_data);
-  silc_buffer_clear(buf);
-  silc_buffer_free(buf);
+  silc_free(pkcs_name);
+  silc_free(key_data);
   return FALSE;
 }
 
@@ -1110,20 +1077,24 @@ static bool silc_pkcs_save_public_key_internal(const char *filename,
 {
   SilcBuffer buf;
   SilcUInt32 len;
+  unsigned char *tmp = NULL;
 
   switch(encoding) {
   case SILC_PKCS_FILE_BIN:
     break;
   case SILC_PKCS_FILE_PEM:
-    data = silc_pem_encode_file(data, data_len);
+    tmp = data = silc_pem_encode_file(data, data_len);
     data_len = strlen(data);
     break;
   }
 
   len = data_len + (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
                    strlen(SILC_PKCS_PUBLIC_KEYFILE_END));
-  buf = silc_buffer_alloc(len);
-  silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
+  buf = silc_buffer_alloc_size(len);
+  if (!buf) {
+    silc_free(tmp);
+    return FALSE;
+  }
 
   silc_buffer_format(buf,
                     SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_BEGIN),
@@ -1133,10 +1104,12 @@ static bool silc_pkcs_save_public_key_internal(const char *filename,
 
   /* Save into file */
   if (silc_file_writefile(filename, buf->data, buf->len)) {
+    silc_free(tmp);
     silc_buffer_free(buf);
     return FALSE;
   }
 
+  silc_free(tmp);
   silc_buffer_free(buf);
   return TRUE;
 }
index b84630446ee9b9924d007b12c04bb2159c068dfc..7b3b13cc5cdb6336bfdd66e11f3c45e94e22646c 100644 (file)
@@ -210,13 +210,43 @@ void silc_buffer_free(SilcBuffer sb)
 {
   if (sb) {
 #if defined(SILC_DEBUG)
-    memset(sb->head, 'F', sb->truelen);
+    if (sb->head)
+      memset(sb->head, 'F', sb->truelen);
 #endif
     silc_free(sb->head);
     silc_free(sb);
   }
 }
 
+/****f* silcutil/SilcBufferAPI/silc_buffer_steal
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    unsigned char *silc_buffer_free(SilcBuffer sb, SilcUInt32 *data_len);
+ *
+ * DESCRIPTION
+ *
+ *    Steals the data from the buffer `sb'.  This returns pointer to the
+ *    start of the buffer and the true length of that buffer.  The `sb'
+ *    cannot be used anymore after calling this function because the
+ *    data buffer was stolen.  The `sb' must be freed with silc_buffer_free.
+ *    The caller is responsible of freeing the stolen data buffer with
+ *    silc_free.
+ *
+ ***/
+
+static inline
+unsigned char *silc_buffer_steal(SilcBuffer sb, SilcUInt32 *data_len)
+{
+  unsigned char *buf = sb->head;
+  if (data_len)
+    *data_len = sb->truelen;
+  sb->head = sb->data = sb->tail = sb->end = NULL;
+  sb->len = sb->truelen = 0;
+  return buf;
+}
+
 /****f* silcutil/SilcBufferAPI/silc_buffer_set
  *
  * SYNOPSIS
index 22445aef9bb1cbe5b869c0e1d58c1a49571627a4..671b126849d25c51f65c37295833b1ca37bfd490 100644 (file)
@@ -52,7 +52,7 @@
 
 int silc_select(SilcScheduleFd fds, SilcUInt32 fds_count, struct timeval *timeout)
 {
-  HANDLE handles[MAXIMUM_WAIT_OBJECTS];
+  static HANDLE handles[MAXIMUM_WAIT_OBJECTS];
   DWORD ready, curtime, timeo;
   int nhandles = 0, i;
   MSG msg;
@@ -83,27 +83,17 @@ int silc_select(SilcScheduleFd fds, SilcUInt32 fds_count, struct timeval *timeou
      and wait just for windows messages. */
   if (nhandles == 0 && timeout) {
     UINT timer = SetTimer(NULL, 0, timeo, NULL);
-    curtime = GetTickCount();
-    while (timer) {
-      WaitMessage();
-
-      while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
-       if (msg.message == WM_TIMER) {
-         KillTimer(NULL, timer);
-         return 0;
-       }
-       TranslateMessage(&msg); 
-       DispatchMessage(&msg); 
-      }
 
+    GetMessage(&msg, NULL, 0, 0);
+    if (msg.message == WM_TIMER) {
       KillTimer(NULL, timer);
-      if (timeo != INFINITE) {
-       timeo -= GetTickCount() - curtime;
-       if (timeo < 0)
-         timeo = 0;
-      }
-      timer = SetTimer(NULL, 0, timeo, NULL);
+      return 0;
     }
+    TranslateMessage(&msg); 
+    DispatchMessage(&msg); 
+
+    KillTimer(NULL, timer);
+    timeo = 0;
   }
 
  retry: