conn-zip.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /*
  2. * ngIRCd -- The Next Generation IRC Daemon
  3. * Copyright (c)2001,2002 by 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. static char UNUSED id[] = "$Id: conn-zip.c,v 1.7 2005/04/25 18:37:16 fw Exp $";
  17. #include "imp.h"
  18. #include <assert.h>
  19. #include <string.h>
  20. #include <zlib.h>
  21. #include "conn.h"
  22. #include "conn-func.h"
  23. #include "log.h"
  24. #include "exp.h"
  25. #include "conn-zip.h"
  26. GLOBAL bool
  27. Zip_InitConn( CONN_ID Idx )
  28. {
  29. /* Kompression fuer Link initialisieren */
  30. assert( Idx > NONE );
  31. My_Connections[Idx].zip.in.avail_in = 0;
  32. My_Connections[Idx].zip.in.total_in = 0;
  33. My_Connections[Idx].zip.in.total_out = 0;
  34. My_Connections[Idx].zip.in.zalloc = NULL;
  35. My_Connections[Idx].zip.in.zfree = NULL;
  36. My_Connections[Idx].zip.in.data_type = Z_ASCII;
  37. if( inflateInit( &My_Connections[Idx].zip.in ) != Z_OK )
  38. {
  39. /* Fehler! */
  40. Log( LOG_ALERT, "Can't initialize compression on connection %d (zlib inflate)!", Idx );
  41. return false;
  42. }
  43. My_Connections[Idx].zip.out.total_in = 0;
  44. My_Connections[Idx].zip.out.total_in = 0;
  45. My_Connections[Idx].zip.out.zalloc = NULL;
  46. My_Connections[Idx].zip.out.zfree = NULL;
  47. My_Connections[Idx].zip.out.data_type = Z_ASCII;
  48. if( deflateInit( &My_Connections[Idx].zip.out, Z_DEFAULT_COMPRESSION ) != Z_OK )
  49. {
  50. /* Fehler! */
  51. Log( LOG_ALERT, "Can't initialize compression on connection %d (zlib deflate)!", Idx );
  52. return false;
  53. }
  54. My_Connections[Idx].zip.bytes_in = My_Connections[Idx].bytes_in;
  55. My_Connections[Idx].zip.bytes_out = My_Connections[Idx].bytes_out;
  56. Log( LOG_INFO, "Enabled link compression (zlib) on connection %d.", Idx );
  57. Conn_OPTION_ADD( &My_Connections[Idx], CONN_ZIP );
  58. return true;
  59. } /* Zip_InitConn */
  60. GLOBAL bool
  61. Zip_Buffer( CONN_ID Idx, char *Data, int Len )
  62. {
  63. /* Daten zum Komprimieren im "Kompressions-Puffer" sammeln.
  64. * Es wird true bei Erfolg, sonst false geliefert. */
  65. assert( Idx > NONE );
  66. assert( Data != NULL );
  67. assert( Len > 0 );
  68. /* Ist noch Platz im Kompressions-Puffer? */
  69. if( ZWRITEBUFFER_LEN - My_Connections[Idx].zip.wdatalen < Len + 50 )
  70. {
  71. /* Nein! Puffer zunaechst leeren ...*/
  72. if( ! Zip_Flush( Idx )) return false;
  73. }
  74. /* Daten kopieren */
  75. memmove( My_Connections[Idx].zip.wbuf + My_Connections[Idx].zip.wdatalen, Data, Len );
  76. My_Connections[Idx].zip.wdatalen += Len;
  77. return true;
  78. } /* Zip_Buffer */
  79. GLOBAL bool
  80. Zip_Flush( CONN_ID Idx )
  81. {
  82. /* Daten komprimieren und in Schreibpuffer kopieren.
  83. * Es wird true bei Erfolg, sonst false geliefert. */
  84. int result, out_len;
  85. z_stream *out;
  86. out = &My_Connections[Idx].zip.out;
  87. out->next_in = (void *)My_Connections[Idx].zip.wbuf;
  88. out->avail_in = My_Connections[Idx].zip.wdatalen;
  89. out->next_out = (void *)(My_Connections[Idx].wbuf + My_Connections[Idx].wdatalen);
  90. out->avail_out = WRITEBUFFER_LEN - My_Connections[Idx].wdatalen;
  91. result = deflate( out, Z_SYNC_FLUSH );
  92. if(( result != Z_OK ) || ( out->avail_in > 0 ))
  93. {
  94. Log( LOG_ALERT, "Compression error: code %d!?", result );
  95. Conn_Close( Idx, "Compression error!", NULL, false );
  96. return false;
  97. }
  98. out_len = WRITEBUFFER_LEN - My_Connections[Idx].wdatalen - out->avail_out;
  99. My_Connections[Idx].wdatalen += out_len;
  100. My_Connections[Idx].bytes_out += out_len;
  101. My_Connections[Idx].zip.bytes_out += My_Connections[Idx].zip.wdatalen;
  102. My_Connections[Idx].zip.wdatalen = 0;
  103. return true;
  104. } /* Zip_Flush */
  105. GLOBAL bool
  106. Unzip_Buffer( CONN_ID Idx )
  107. {
  108. /* Daten entpacken und in Lesepuffer kopieren. Bei Fehlern
  109. * wird false geliefert, ansonsten true. Der Fall, dass keine
  110. * Daten mehr zu entpacken sind, ist _kein_ Fehler! */
  111. int result, in_len, out_len;
  112. z_stream *in;
  113. assert( Idx > NONE );
  114. if( My_Connections[Idx].zip.rdatalen <= 0 ) return true;
  115. in = &My_Connections[Idx].zip.in;
  116. in->next_in = (void *)My_Connections[Idx].zip.rbuf;
  117. in->avail_in = My_Connections[Idx].zip.rdatalen;
  118. in->next_out = (void *)(My_Connections[Idx].rbuf + My_Connections[Idx].rdatalen);
  119. in->avail_out = READBUFFER_LEN - My_Connections[Idx].rdatalen - 1;
  120. result = inflate( in, Z_SYNC_FLUSH );
  121. if( result != Z_OK )
  122. {
  123. 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 );
  124. Conn_Close( Idx, "Decompression error!", NULL, false );
  125. return false;
  126. }
  127. in_len = My_Connections[Idx].zip.rdatalen - in->avail_in;
  128. out_len = READBUFFER_LEN - My_Connections[Idx].rdatalen - 1 - in->avail_out;
  129. My_Connections[Idx].rdatalen += out_len;
  130. if( in->avail_in > 0 )
  131. {
  132. /* es konnten nicht alle Daten entpackt werden, vermutlich war
  133. * im Ziel-Puffer kein Platz mehr. Umkopieren ... */
  134. My_Connections[Idx].zip.rdatalen -= in_len;
  135. memmove( My_Connections[Idx].zip.rbuf, My_Connections[Idx].zip.rbuf + in_len, My_Connections[Idx].zip.rdatalen );
  136. }
  137. else My_Connections[Idx].zip.rdatalen = 0;
  138. My_Connections[Idx].zip.bytes_in += out_len;
  139. return true;
  140. } /* Unzip_Buffer */
  141. GLOBAL long
  142. Zip_SendBytes( CONN_ID Idx )
  143. {
  144. /* Anzahl gesendeter Bytes (komprimiert!) liefern */
  145. assert( Idx > NONE );
  146. return My_Connections[Idx].zip.bytes_out;
  147. } /* Zip_SendBytes */
  148. GLOBAL long
  149. Zip_RecvBytes( CONN_ID Idx )
  150. {
  151. /* Anzahl gesendeter Bytes (komprimiert!) liefern */
  152. assert( Idx > NONE );
  153. return My_Connections[Idx].zip.bytes_in;
  154. } /* Zip_RecvBytes */
  155. #endif
  156. /* -eof- */