194 |
return sd; |
return sd; |
195 |
} |
} |
196 |
|
|
197 |
|
static const char * |
198 |
|
_def_strerror(int rc) |
199 |
|
{ |
200 |
|
return strerror(rc); |
201 |
|
} |
202 |
|
|
203 |
|
static int |
204 |
|
_def_write(void *sd, char *data, size_t size, size_t *nbytes) |
205 |
|
{ |
206 |
|
int rc = send((int)sd, data, size, 0); |
207 |
|
if (rc >= 0) { |
208 |
|
*nbytes = rc; |
209 |
|
return 0; |
210 |
|
} |
211 |
|
return errno; |
212 |
|
} |
213 |
|
|
214 |
|
static int |
215 |
|
_def_read(void *sd, char *data, size_t size, size_t *nbytes) |
216 |
|
{ |
217 |
|
int rc = recv((int)sd, data, size, 0); |
218 |
|
if (rc >= 0) { |
219 |
|
*nbytes = rc; |
220 |
|
return 0; |
221 |
|
} |
222 |
|
return errno; |
223 |
|
} |
224 |
|
|
225 |
|
static int |
226 |
|
_def_close(void *sd_unused) |
227 |
|
{ |
228 |
|
return 0; |
229 |
|
} |
230 |
|
|
231 |
|
struct io_data { |
232 |
|
net_io_t read; |
233 |
|
net_io_t write; |
234 |
|
strerror_t strerror; |
235 |
|
net_close_t close; |
236 |
|
}; |
237 |
|
|
238 |
|
struct io_data io_data[2] = { |
239 |
|
/* CLIENT */ |
240 |
|
{ _def_read, _def_write, _def_strerror, _def_close }, |
241 |
|
/* SERVER */ |
242 |
|
{ _def_read, _def_write, _def_strerror, _def_close } |
243 |
|
}; |
244 |
|
|
245 |
|
void |
246 |
|
net_set_io(int method, net_io_t read, net_io_t write, |
247 |
|
net_close_t close, |
248 |
|
strerror_t strerror) |
249 |
|
{ |
250 |
|
io_data[method].read = read ? read : _def_read; |
251 |
|
io_data[method].write = write ? write : _def_write; |
252 |
|
io_data[method].close = close; |
253 |
|
io_data[method].strerror = strerror ? strerror : _def_strerror; |
254 |
|
} |
255 |
|
|
256 |
|
void |
257 |
|
net_close(int method, void *sd) |
258 |
|
{ |
259 |
|
if (io_data[method].close) { |
260 |
|
io_data[method].close(sd); |
261 |
|
net_set_io(method, NULL, NULL, NULL, NULL); |
262 |
|
} |
263 |
|
} |
264 |
|
|
265 |
/************** |
/************** |
266 |
Send a data |
Send a data |
267 |
***************/ |
***************/ |
269 |
void |
void |
270 |
swrite(int method, void *sd, char *ptr) |
swrite(int method, void *sd, char *ptr) |
271 |
{ |
{ |
272 |
unsigned long nleft; |
int rc; |
273 |
unsigned long nwritten = 0; |
size_t nleft, nwritten = 0; |
274 |
|
|
275 |
if (ptr == 0) |
if (ptr == 0) |
276 |
return; |
return; |
277 |
|
|
278 |
nleft = (unsigned long)strlen(ptr); |
nleft = (unsigned long)strlen(ptr); |
279 |
while (nleft > 0) |
while (nleft > 0) { |
280 |
{ |
rc = io_data[method].write(sd, ptr, nleft, &nwritten); |
281 |
if (method == CLIENT) { |
if (rc) { |
282 |
|
socket_error(io_data[method].strerror(rc)); |
|
#ifdef HAVE_TLS |
|
|
if (topt & T_SSL_CLIENT) { |
|
|
if ((nwritten = (unsigned long)gnutls_record_send( |
|
|
(gnutls_session)sd, ptr, nleft)) <= 0) { |
|
|
socket_error(); |
|
|
return; |
|
|
} |
|
|
} else |
|
|
#endif /* HAVE_TLS */ |
|
|
|
|
|
#ifdef HAVE_SSL |
|
|
if (topt & T_SSL_CLIENT) { |
|
|
if ((nwritten = (unsigned long)SSL_write((SSL *)sd, |
|
|
ptr, nleft)) <= 0) { |
|
|
socket_error(); |
|
|
return; |
|
|
} |
|
|
} else |
|
|
#endif /* HAVE_SSL */ |
|
|
|
|
|
if (!(topt & T_SSL_CLIENT)) { |
|
|
if ((nwritten = (unsigned long)send((int)sd, |
|
|
ptr, nleft, 0)) == -1) { |
|
|
socket_error(); |
|
|
return; |
|
|
} |
|
|
} |
|
|
} |
|
|
else if (method == SERVER) { |
|
|
|
|
|
#ifdef HAVE_TLS |
|
|
if (topt & T_SSL_SERVER) { |
|
|
if ((nwritten = (unsigned long)gnutls_record_send( |
|
|
(gnutls_session)sd, ptr, nleft)) <= 0) { |
|
|
socket_error(); |
|
|
return; |
|
|
} |
|
|
} else |
|
|
#endif /* HAVE_TLS */ |
|
|
|
|
|
#ifdef HAVE_SSL |
|
|
if (topt & T_SSL_SERVER) { |
|
|
if ((nwritten = (unsigned long)SSL_write((SSL *)sd, |
|
|
ptr, nleft)) <= 0) { |
|
|
socket_error(); |
|
|
return; |
|
|
} |
|
|
} else |
|
|
#endif /* HAVE_SSL */ |
|
|
|
|
|
if ((int)sd == -1) { /* standard output */ |
|
|
nwritten = (unsigned long)write(1, ptr, nleft); |
|
|
} |
|
|
else if (!(topt & T_SSL_SERVER)) { |
|
|
if ((nwritten = (unsigned long)send((int)sd, |
|
|
ptr, nleft, 0)) == -1) { |
|
|
socket_error(); |
|
|
return; |
|
|
} |
|
|
} |
|
|
} |
|
|
DPRINTF(method, 1, nleft, ptr); |
|
|
if (nwritten <= 0) |
|
283 |
return; |
return; |
284 |
|
} |
285 |
|
DPRINTF(method, 1, nwritten, ptr); |
286 |
nleft -= nwritten; |
nleft -= nwritten; |
287 |
ptr += nwritten; |
ptr += nwritten; |
288 |
} |
} |
296 |
static int |
static int |
297 |
mread(int method, void *sd, char *ptr) |
mread(int method, void *sd, char *ptr) |
298 |
{ |
{ |
299 |
static int nread = 0; |
static size_t nread = 0; |
300 |
static char *read_ptr = 0; |
static char *read_ptr = 0; |
301 |
static char buf[LINEBUFFER+1]; |
static char buf[LINEBUFFER+1]; |
302 |
|
|
303 |
if (nread <= 0) { |
if (nread <= 0) { |
304 |
again: |
int rc = io_data[method].read(sd, buf, LINEBUFFER, &nread); |
305 |
if (method == CLIENT) { |
if (rc) { |
306 |
|
socket_error(io_data[method].strerror(rc)); |
|
#ifdef HAVE_TLS |
|
|
if (topt & T_SSL_CLIENT) |
|
|
nread = gnutls_record_recv((gnutls_session)sd, buf, LINEBUFFER); |
|
|
else |
|
|
#endif /* HAVE_TLS */ |
|
|
|
|
|
#ifdef HAVE_SSL |
|
|
if (topt & T_SSL_CLIENT) |
|
|
nread = SSL_read((SSL *)sd, buf, LINEBUFFER); |
|
|
else |
|
|
#endif /* HAVE_SSL */ |
|
|
|
|
|
if (!(topt & T_SSL_CLIENT)) |
|
|
nread = recv((int)sd, buf, LINEBUFFER, 0); |
|
|
} |
|
|
else if (method == SERVER) { |
|
|
|
|
|
#ifdef HAVE_TLS |
|
|
if (topt & T_SSL_SERVER) |
|
|
nread = gnutls_record_recv((gnutls_session)sd, buf, LINEBUFFER); |
|
|
else |
|
|
#endif /* HAVE_TLS */ |
|
|
|
|
|
#ifdef HAVE_SSL |
|
|
if (topt & T_SSL_SERVER) |
|
|
nread = SSL_read((SSL *)sd, buf, LINEBUFFER); |
|
|
else |
|
|
#endif /* HAVE_SSL */ |
|
|
|
|
|
if (!(topt & T_SSL_SERVER)) |
|
|
nread = recv((int)sd, buf, LINEBUFFER, 0); |
|
|
} |
|
|
if (nread < 0) { |
|
|
if (errno == EINTR) |
|
|
goto again; |
|
307 |
return -1; |
return -1; |
308 |
} |
} |
309 |
else if (nread == 0) |
if (nread == 0) |
310 |
return 0; |
return 0; |
311 |
read_ptr = buf; |
read_ptr = buf; |
312 |
} |
} |
321 |
int n, rc; |
int n, rc; |
322 |
char c, *ptr; |
char c, *ptr; |
323 |
|
|
|
if ((int)sd == -1 && method == SERVER) { /* standard input */ |
|
|
memset(vptr, 0, maxlen); |
|
|
#ifdef HAVE_ISATTY |
|
|
if (!isatty(fileno(stdin))) { |
|
|
fgets((char *)vptr, maxlen, stdin); |
|
|
remcrlf((char *)vptr); |
|
|
strcat((char *)vptr, CRLF); |
|
|
if (vptr) |
|
|
n = strlen((char *)vptr); |
|
|
else |
|
|
n = 0; |
|
|
} |
|
|
else |
|
|
#endif /* HAVE_ISATTY */ |
|
|
{ |
|
|
n = read(0, (char *)vptr, maxlen - 1); |
|
|
remcrlf((char *)vptr); |
|
|
strcat((char *)vptr, CRLF); |
|
|
} |
|
|
return n; |
|
|
} |
|
|
|
|
324 |
ptr = vptr; |
ptr = vptr; |
325 |
for (n = 1; n < maxlen; n++) |
for (n = 1; n < maxlen; n++) { |
|
{ |
|
326 |
if ((rc = mread(method, sd, &c)) == 1) { |
if ((rc = mread(method, sd, &c)) == 1) { |
327 |
|
if (c == '\n' && n > 1 && ptr[-1] != '\r') |
328 |
|
*ptr++ = '\r'; |
329 |
*ptr++ = c; |
*ptr++ = c; |
330 |
if (c == '\n') |
if (c == '\n') |
331 |
break; |
break; |
332 |
} |
} else if (rc == 0) { |
|
else if (rc == 0) { |
|
333 |
if (n == 1) |
if (n == 1) |
334 |
return 0; |
return 0; |
335 |
else |
else |
336 |
break; |
break; |
337 |
} |
} else |
|
else |
|
338 |
return -1; |
return -1; |
339 |
} |
} |
340 |
*ptr = 0; |
*ptr = 0; |