2 * OpenVPN -- An application to securely tunnel IP networks
3 * over a single UDP port, with support for SSL/TLS-based
4 * session authentication and key exchange,
5 * packet encryption, packet authentication, and
8 * Copyright (C) 2002-2005 OpenVPN Solutions LLC <info@openvpn.net>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program (see the file COPYING included with this
21 * distribution); if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #include "config-win32.h"
42 lzo_adaptive_compress_test (struct lzo_adaptive_compress
*ac
)
44 const bool save
= ac
->compress_state
;
45 const time_t local_now
= now
;
50 if (!ac
->compress_state
)
52 if (local_now
>= ac
->next
)
54 if (ac
->n_total
> AC_MIN_BYTES
55 && (ac
->n_total
- ac
->n_comp
) < (ac
->n_total
/ (100 / AC_SAVE_PCT
)))
57 ac
->compress_state
= true;
58 ac
->next
= local_now
+ AC_OFF_SEC
;
62 ac
->next
= local_now
+ AC_SAMP_SEC
;
64 dmsg (D_COMP
, "lzo_adaptive_compress_test: comp=%d total=%d", ac
->n_comp
, ac
->n_total
);
65 ac
->n_total
= ac
->n_comp
= 0;
70 if (local_now
>= ac
->next
)
72 ac
->next
= local_now
+ AC_SAMP_SEC
;
73 ac
->n_total
= ac
->n_comp
= 0;
74 ac
->compress_state
= false;
78 if (ac
->compress_state
!= save
)
79 dmsg (D_COMP_LOW
, "Adaptive compression state %s", (ac
->compress_state
? "OFF" : "ON"));
81 return !ac
->compress_state
;
85 lzo_adaptive_compress_data (struct lzo_adaptive_compress
*ac
, int n_total
, int n_comp
)
89 ac
->n_total
+= n_total
;
94 void lzo_adjust_frame_parameters (struct frame
*frame
)
96 /* Leave room for our one-byte compressed/didn't-compress prefix byte. */
97 frame_add_to_extra_frame (frame
, LZO_PREFIX_LEN
);
99 /* Leave room for compression buffer to expand in worst case scenario
100 where data is totally uncompressible */
101 frame_add_to_extra_buffer (frame
, LZO_EXTRA_BUFFER (EXPANDED_SIZE(frame
)));
105 lzo_compress_init (struct lzo_compress_workspace
*lzowork
, bool adaptive
)
109 lzowork
->wmem_size
= LZO_WORKSPACE
;
110 lzowork
->ac
.enabled
= adaptive
;
112 if (lzo_init () != LZO_E_OK
)
113 msg (M_FATAL
, "Cannot initialize LZO compression library");
114 lzowork
->wmem
= (lzo_voidp
) lzo_malloc (lzowork
->wmem_size
);
115 check_malloc_return (lzowork
->wmem
);
116 msg (M_INFO
, "LZO compression initialized");
120 lzo_compress_uninit (struct lzo_compress_workspace
*lzowork
)
124 lzo_free (lzowork
->wmem
);
125 lzowork
->wmem
= NULL
;
129 /* Magic numbers to tell our peer if we compressed or not */
130 #define YES_COMPRESS 0x66
131 #define NO_COMPRESS 0xFA
134 lzo_compress (struct buffer
*buf
, struct buffer work
,
135 struct lzo_compress_workspace
*lzowork
,
136 const struct frame
* frame
)
140 bool compressed
= false;
146 * In order to attempt compression, length must be at least COMPRESS_THRESHOLD,
147 * and our adaptive level must give the OK.
149 if (buf
->len
>= COMPRESS_THRESHOLD
&& lzo_adaptive_compress_test (&lzowork
->ac
))
151 ASSERT (buf_init (&work
, FRAME_HEADROOM (frame
)));
152 ASSERT (buf_safe (&work
, LZO_EXTRA_BUFFER (PAYLOAD_SIZE (frame
))));
153 ASSERT (buf
->len
<= PAYLOAD_SIZE (frame
));
155 err
= LZO_COMPRESS (BPTR (buf
), BLEN (buf
), BPTR (&work
), &zlen
, lzowork
->wmem
);
158 dmsg (D_COMP_ERRORS
, "LZO compression error: %d", err
);
163 ASSERT (buf_safe (&work
, zlen
));
167 dmsg (D_COMP
, "compress %d -> %d", buf
->len
, work
.len
);
168 lzowork
->pre_compress
+= buf
->len
;
169 lzowork
->post_compress
+= work
.len
;
171 /* tell adaptive level about our success or lack thereof in getting any size reduction */
172 lzo_adaptive_compress_data(&lzowork
->ac
, buf
->len
, work
.len
);
175 /* did compression save us anything ? */
176 if (compressed
&& work
.len
< buf
->len
)
178 uint8_t *header
= buf_prepend (&work
, 1);
179 *header
= YES_COMPRESS
;
184 uint8_t *header
= buf_prepend (buf
, 1);
185 *header
= NO_COMPRESS
;
190 lzo_decompress (struct buffer
*buf
, struct buffer work
,
191 struct lzo_compress_workspace
*lzowork
,
192 const struct frame
* frame
)
194 lzo_uint zlen
= EXPANDED_SIZE (frame
);
195 uint8_t c
; /* flag indicating whether or not our peer compressed */
201 ASSERT (buf_init (&work
, FRAME_HEADROOM (frame
)));
204 ASSERT (buf_advance (buf
, 1));
206 if (c
== YES_COMPRESS
) /* packet was compressed */
208 ASSERT (buf_safe (&work
, zlen
));
209 err
= LZO_DECOMPRESS (BPTR (buf
), BLEN (buf
), BPTR (&work
), &zlen
,
213 dmsg (D_COMP_ERRORS
, "LZO decompression error: %d", err
);
218 ASSERT (buf_safe (&work
, zlen
));
221 dmsg (D_COMP
, "decompress %d -> %d", buf
->len
, work
.len
);
222 lzowork
->pre_decompress
+= buf
->len
;
223 lzowork
->post_decompress
+= work
.len
;
227 else if (c
== NO_COMPRESS
) /* packet was not compressed */
233 dmsg (D_COMP_ERRORS
, "Bad LZO decompression header byte: %d", c
);
241 void lzo_print_stats (const struct lzo_compress_workspace
*lzo_compwork
, struct status_output
*so
)
243 status_printf (so
, "pre-compress bytes," counter_format
, lzo_compwork
->pre_compress
);
244 status_printf (so
, "post-compress bytes," counter_format
, lzo_compwork
->post_compress
);
245 status_printf (so
, "pre-decompress bytes," counter_format
, lzo_compwork
->pre_decompress
);
246 status_printf (so
, "post-decompress bytes," counter_format
, lzo_compwork
->post_decompress
);
250 static void dummy(void) {}