conn-zip.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. /*
  2. * ngIRCd -- The Next Generation IRC Daemon
  3. * Copyright (c)2001-2006 Alexander Barton (alex@barton.de)
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. * Please read the file COPYING, README and AUTHORS for more information.
  10. *
  11. * Connection compression using ZLIB
  12. */
  13. #include "portab.h"
  14. #define CONN_MODULE
  15. #ifdef ZLIB
  16. /* enable more zlib related debug messages: */
  17. /* #define DEBUG_ZLIB */
  18. static char UNUSED id[] = "$Id: conn-zip.c,v 1.11 2006/07/23 15:19:20 alex Exp $";
  19. #include "imp.h"
  20. #include <assert.h>
  21. #include <string.h>
  22. #include <zlib.h>
  23. #include "conn.h"
  24. #include "conn-func.h"
  25. #include "log.h"
  26. #include "array.h"
  27. #include "exp.h"
  28. #include "conn-zip.h"
  29. GLOBAL bool
  30. Zip_InitConn( CONN_ID Idx )
  31. {
  32. /* Kompression fuer Link initialisieren */
  33. assert( Idx > NONE );
  34. My_Connections[Idx].zip.in.avail_in = 0;
  35. My_Connections[Idx].zip.in.total_in = 0;
  36. My_Connections[Idx].zip.in.total_out = 0;
  37. My_Connections[Idx].zip.in.zalloc = NULL;
  38. My_Connections[Idx].zip.in.zfree = NULL;
  39. My_Connections[Idx].zip.in.data_type = Z_ASCII;
  40. if( inflateInit( &My_Connections[Idx].zip.in ) != Z_OK )
  41. {
  42. /* Fehler! */
  43. Log( LOG_ALERT, "Can't initialize compression on connection %d (zlib inflate)!", Idx );
  44. return false;
  45. }
  46. My_Connections[Idx].zip.out.total_in = 0;
  47. My_Connections[Idx].zip.out.total_in = 0;
  48. My_Connections[Idx].zip.out.zalloc = NULL;
  49. My_Connections[Idx].zip.out.zfree = NULL;
  50. My_Connections[Idx].zip.out.data_type = Z_ASCII;
  51. if( deflateInit( &My_Connections[Idx].zip.out, Z_DEFAULT_COMPRESSION ) != Z_OK )
  52. {
  53. /* Fehler! */
  54. Log( LOG_ALERT, "Can't initialize compression on connection %d (zlib deflate)!", Idx );
  55. return false;
  56. }
  57. My_Connections[Idx].zip.bytes_in = My_Connections[Idx].bytes_in;
  58. My_Connections[Idx].zip.bytes_out = My_Connections[Idx].bytes_out;
  59. Log( LOG_INFO, "Enabled link compression (zlib) on connection %d.", Idx );
  60. Conn_OPTION_ADD( &My_Connections[Idx], CONN_ZIP );
  61. return true;
  62. } /* Zip_InitConn */
  63. GLOBAL bool
  64. Zip_Buffer( CONN_ID Idx, char *Data, size_t Len )
  65. {
  66. /* Daten zum Komprimieren im "Kompressions-Puffer" sammeln.
  67. * Es wird true bei Erfolg, sonst false geliefert. */
  68. assert( Idx > NONE );
  69. assert( Data != NULL );
  70. assert( Len > 0 );
  71. assert( Len <= ZWRITEBUFFER_LEN );
  72. if (Len > ZWRITEBUFFER_LEN)
  73. return false;
  74. if ( array_bytes( &My_Connections[Idx].zip.wbuf ) >= ZWRITEBUFFER_LEN ) {
  75. /* compression buffer is full, flush */
  76. if( ! Zip_Flush( Idx )) return false;
  77. }
  78. return array_catb(&My_Connections[Idx].zip.wbuf, Data, Len);
  79. } /* Zip_Buffer */
  80. GLOBAL bool
  81. Zip_Flush( CONN_ID Idx )
  82. {
  83. /* Daten komprimieren und in Schreibpuffer kopieren.
  84. * Es wird true bei Erfolg, sonst false geliefert. */
  85. int result;
  86. unsigned char zipbuf[WRITEBUFFER_LEN];
  87. int zipbuf_used = 0;
  88. z_stream *out;
  89. out = &My_Connections[Idx].zip.out;
  90. out->next_in = array_start(&My_Connections[Idx].zip.wbuf);
  91. if (!out->next_in)
  92. return false;
  93. out->avail_in = (uInt)array_bytes(&My_Connections[Idx].zip.wbuf);
  94. out->next_out = zipbuf;
  95. out->avail_out = (uInt)sizeof zipbuf;
  96. #ifdef DEBUG_ZIP
  97. Log(LOG_DEBUG, "out->avail_in %d, out->avail_out %d",
  98. out->avail_in, out->avail_out);
  99. #endif
  100. result = deflate( out, Z_SYNC_FLUSH );
  101. if(( result != Z_OK ) || ( out->avail_in > 0 ))
  102. {
  103. Log( LOG_ALERT, "Compression error: code %d!?", result );
  104. Conn_Close( Idx, "Compression error!", NULL, false );
  105. return false;
  106. }
  107. assert(out->avail_out <= WRITEBUFFER_LEN);
  108. zipbuf_used = WRITEBUFFER_LEN - out->avail_out;
  109. #ifdef DEBUG_ZIP
  110. Log(LOG_DEBUG, "zipbuf_used: %d", zipbuf_used);
  111. #endif
  112. if (!array_catb(&My_Connections[Idx].wbuf,
  113. (char *)zipbuf, (size_t) zipbuf_used))
  114. return false;
  115. My_Connections[Idx].bytes_out += zipbuf_used;
  116. My_Connections[Idx].zip.bytes_out += array_bytes(&My_Connections[Idx].zip.wbuf);
  117. array_trunc(&My_Connections[Idx].zip.wbuf);
  118. return true;
  119. } /* Zip_Flush */
  120. GLOBAL bool
  121. Unzip_Buffer( CONN_ID Idx )
  122. {
  123. /* Daten entpacken und in Lesepuffer kopieren. Bei Fehlern
  124. * wird false geliefert, ansonsten true. Der Fall, dass keine
  125. * Daten mehr zu entpacken sind, ist _kein_ Fehler! */
  126. int result;
  127. unsigned char unzipbuf[READBUFFER_LEN];
  128. int unzipbuf_used = 0;
  129. unsigned int z_rdatalen;
  130. unsigned int in_len;
  131. z_stream *in;
  132. assert( Idx > NONE );
  133. z_rdatalen = (unsigned int)array_bytes(&My_Connections[Idx].zip.rbuf);
  134. if (z_rdatalen == 0)
  135. return true;
  136. in = &My_Connections[Idx].zip.in;
  137. in->next_in = array_start(&My_Connections[Idx].zip.rbuf);
  138. if (!in->next_in)
  139. return false;
  140. in->avail_in = z_rdatalen;
  141. in->next_out = unzipbuf;
  142. in->avail_out = (uInt)sizeof unzipbuf;
  143. #ifdef DEBUG_ZIP
  144. Log(LOG_DEBUG, "in->avail_in %d, in->avail_out %d",
  145. in->avail_in, in->avail_out);
  146. #endif
  147. result = inflate( in, Z_SYNC_FLUSH );
  148. if( result != Z_OK )
  149. {
  150. Log( LOG_ALERT, "Decompression error: %s (code=%d, ni=%d, ai=%d, no=%d, ao=%d)!?", in->msg, result, in->next_in, in->avail_in, in->next_out, in->avail_out );
  151. Conn_Close( Idx, "Decompression error!", NULL, false );
  152. return false;
  153. }
  154. assert(z_rdatalen >= in->avail_in);
  155. in_len = z_rdatalen - in->avail_in;
  156. unzipbuf_used = READBUFFER_LEN - in->avail_out;
  157. #ifdef DEBUG_ZIP
  158. Log(LOG_DEBUG, "unzipbuf_used: %d - %d = %d", READBUFFER_LEN,
  159. in->avail_out, unzipbuf_used);
  160. #endif
  161. assert(unzipbuf_used <= READBUFFER_LEN);
  162. if (!array_catb(&My_Connections[Idx].rbuf, (char*) unzipbuf,
  163. (size_t)unzipbuf_used))
  164. return false;
  165. if( in->avail_in > 0 ) {
  166. array_moveleft(&My_Connections[Idx].zip.rbuf, 1, in_len );
  167. } else {
  168. array_trunc( &My_Connections[Idx].zip.rbuf );
  169. My_Connections[Idx].zip.bytes_in += unzipbuf_used;
  170. }
  171. return true;
  172. } /* Unzip_Buffer */
  173. GLOBAL long
  174. Zip_SendBytes( CONN_ID Idx )
  175. {
  176. /* Anzahl gesendeter Bytes (komprimiert!) liefern */
  177. assert( Idx > NONE );
  178. return My_Connections[Idx].zip.bytes_out;
  179. } /* Zip_SendBytes */
  180. GLOBAL long
  181. Zip_RecvBytes( CONN_ID Idx )
  182. {
  183. /* Anzahl gesendeter Bytes (komprimiert!) liefern */
  184. assert( Idx > NONE );
  185. return My_Connections[Idx].zip.bytes_in;
  186. } /* Zip_RecvBytes */
  187. #endif
  188. /* -eof- */