1 /*-
2 * Copyright (c) 2003-2005 MAEKAWA Masahide <maekawa@cvsync.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the author nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30 #include <sys/types.h>
31 #include <sys/socket.h>
32
33 #include <stdlib.h>
34
35 #include <errno.h>
36 #include <limits.h>
37 #include <pthread.h>
38 #include <string.h>
39
40 #include <zlib.h>
41
42 #include "compat_stdbool.h"
43 #include "compat_stdint.h"
44 #include "compat_inttypes.h"
45 #include "compat_limits.h"
46 #include "basedef.h"
47
48 #include "cvsync.h"
49 #include "logmsg.h"
50 #include "mux.h"
51 #include "mux_zlib.h"
52 #include "network.h"
53
54 bool
mux_init_zlib(struct mux * mx,int level)55 mux_init_zlib(struct mux *mx, int level)
56 {
57 struct mux_stream_zlib *stream;
58
59 if ((stream = malloc(sizeof(*stream))) == NULL) {
60 logmsg_err("Mux Error: %s", strerror(errno));
61 return (false);
62 }
63 stream->ms_zbufsize_in = sizeof(stream->ms_zbuffer_in);
64 stream->ms_zbufsize_out = sizeof(stream->ms_zbuffer_out);
65
66 stream->ms_zstream_in.zalloc = Z_NULL;
67 stream->ms_zstream_in.zfree = Z_NULL;
68 stream->ms_zstream_in.opaque = Z_NULL;
69 if (inflateInit(&stream->ms_zstream_in) != Z_OK) {
70 logmsg_err("Mux Error: INFLATE init: %s",
71 stream->ms_zstream_in.msg);
72 free(stream);
73 return (false);
74 }
75
76 stream->ms_zstream_out.zalloc = Z_NULL;
77 stream->ms_zstream_out.zfree = Z_NULL;
78 stream->ms_zstream_out.opaque = Z_NULL;
79 if (deflateInit(&stream->ms_zstream_out, level) != Z_OK) {
80 logmsg_err("Mux Error: DEFLATE init: %s",
81 stream->ms_zstream_out.msg);
82 inflateEnd(&stream->ms_zstream_in);
83 free(stream);
84 return (false);
85 }
86 stream->ms_zstream_out.next_out = stream->ms_zbuffer_out;
87 stream->ms_zstream_out.avail_out = stream->ms_zbufsize_out;
88
89 mx->mx_stream = stream;
90
91 return (true);
92 }
93
94 void
mux_destroy_zlib(struct mux * mx)95 mux_destroy_zlib(struct mux *mx)
96 {
97 struct mux_stream_zlib *stream = mx->mx_stream;
98
99 inflateEnd(&stream->ms_zstream_in);
100 deflateEnd(&stream->ms_zstream_out);
101 free(stream);
102 }
103
104 bool
mux_send_zlib(struct mux * mx,uint8_t chnum,const void * buffer,size_t bufsize)105 mux_send_zlib(struct mux *mx, uint8_t chnum, const void *buffer, size_t bufsize)
106 {
107 struct muxbuf *mxb = &mx->mx_buffer[MUX_OUT][chnum];
108 struct mux_stream_zlib *stream = mx->mx_stream;
109 z_stream *z = &stream->ms_zstream_out;
110 uint8_t cmd[MUX_CMDLEN_DATA];
111
112 if (mxb->mxb_length > 0) {
113 z->next_in = mxb->mxb_buffer;
114 z->avail_in = mxb->mxb_length;
115 if (deflate(z, Z_NO_FLUSH) != Z_OK) {
116 logmsg_err("Mux(SEND) Error: DEFLATE: %s", z->msg);
117 return (false);
118 }
119 }
120 z->next_in = (void *)(unsigned long)buffer;
121 z->avail_in = bufsize;
122 if (deflate(z, Z_FINISH) != Z_STREAM_END) {
123 logmsg_err("Mux(SEND) Error: DEFLATE: %s", z->msg);
124 return (false);
125 }
126 if (z->total_out > mxb->mxb_mss) {
127 logmsg_err("Mux(SEND) Error: DEFLATE: %u > %u(mss)",
128 z->total_out, mxb->mxb_mss);
129 return (false);
130 }
131
132 logmsg_debug(DEBUG_ZLIB, "DEFLATE: %u => %u",
133 mxb->mxb_length + bufsize, z->total_out);
134
135 cmd[0] = MUX_CMD_DATA;
136 cmd[1] = chnum;
137 SetWord(&cmd[2], z->total_out);
138
139 if (!sock_send(mx->mx_socket, cmd, MUX_CMDLEN_DATA)) {
140 logmsg_err("Mux(SEND) Error: send");
141 return (false);
142 }
143 if (!sock_send(mx->mx_socket, stream->ms_zbuffer_out,
144 (size_t)z->total_out)) {
145 logmsg_err("Mux(SEND) Error: send");
146 return (false);
147 }
148 mx->mx_xfer_out += mxb->mxb_length + bufsize;
149
150 if (deflateReset(z) != Z_OK) {
151 logmsg_err("Mux(SEND) Error: DEFLATE: %s", z->msg);
152 return (false);
153 }
154 z->next_out = stream->ms_zbuffer_out;
155 z->avail_out = stream->ms_zbufsize_out;
156 z->total_out = 0;
157
158 return (true);
159 }
160
161 bool
mux_flush_zlib(struct mux * mx,uint8_t chnum)162 mux_flush_zlib(struct mux *mx, uint8_t chnum)
163 {
164 struct muxbuf *mxb = &mx->mx_buffer[MUX_OUT][chnum];
165 struct mux_stream_zlib *stream = mx->mx_stream;
166 z_stream *z = &stream->ms_zstream_out;
167 uint8_t cmd[MUX_CMDLEN_DATA];
168
169 z->next_in = mxb->mxb_buffer;
170 z->avail_in = mxb->mxb_length;
171 if (deflate(z, Z_FINISH) != Z_STREAM_END) {
172 logmsg_err("Mux(FLUSH) Error: DEFLATE: %s", z->msg);
173 return (false);
174 }
175 if (z->total_out > mxb->mxb_mss) {
176 logmsg_err("Mux(FLUSH) Error: DEFLATE: %u > %u(mss)",
177 z->total_out, mxb->mxb_mss);
178 return (false);
179 }
180
181 logmsg_debug(DEBUG_ZLIB, "DEFLATE: %u => %u", mxb->mxb_length,
182 z->total_out);
183
184 cmd[0] = MUX_CMD_DATA;
185 cmd[1] = chnum;
186 SetWord(&cmd[2], z->total_out);
187
188 if (!sock_send(mx->mx_socket, cmd, MUX_CMDLEN_DATA)) {
189 logmsg_err("Mux(FLUSH) Error: send");
190 return (false);
191 }
192 if (!sock_send(mx->mx_socket, stream->ms_zbuffer_out,
193 (size_t)z->total_out)) {
194 logmsg_err("Mux(FLUSH) Error: send");
195 return (false);
196 }
197 mx->mx_xfer_out += mxb->mxb_length;
198
199 if (deflateReset(z) != Z_OK) {
200 logmsg_err("Mux(FLUSH) Error: DEFLATE: %s", z->msg);
201 return (false);
202 }
203 z->next_out = stream->ms_zbuffer_out;
204 z->avail_out = stream->ms_zbufsize_out;
205 z->total_out = 0;
206
207 return (true);
208 }
209