Implement an ioctl for replace bottom-level transport layers in a stream chain.
* include/mailutils/stream.h (MU_IOCTL_SWAP_STREAM): New ioctl op. (mu_stream_seterr): New function. * include/mailutils/sys/stream.h (_MU_SWAP_FIRST_ONLY) (_MU_SWAP_IOCTL_MUST_SUCCEED): New defines. (_mu_stream_swap_streams): New proto. * mailbox/amd.c (amd_body_stream_read): Always update *pnread. * mailbox/errors (MU_ERR_NO_TRANSPORT): New error code. * mailbox/stream.c (_stream_seterror): Rename to mu_stream_seterr, remove static qualifier. All uses updated. (_mu_stream_swap_streams): New function. * mailbox/filter_iconv.c (_icvt_ioctl): Implement MU_IOCTL_SWAP_STREAM. * mailbox/iostream.c (_iostream_ctl): Likewise. * mailbox/xscript-stream.c (_xscript_ctl): Likewise. * pop3d/extra.c (real_istream, real_ostream): Remove statics. (pop3d_init_tls_server): Use MU_IOCTL_SWAP_STREAM to replace bottom-level transport layers without recreating the entire stream chain.
Showing
10 changed files
with
157 additions
and
57 deletions
... | @@ -32,8 +32,6 @@ enum mu_buffer_type | ... | @@ -32,8 +32,6 @@ enum mu_buffer_type |
32 | #define MU_SEEK_CUR 1 | 32 | #define MU_SEEK_CUR 1 |
33 | #define MU_SEEK_END 2 | 33 | #define MU_SEEK_END 2 |
34 | 34 | ||
35 | #define MU_STREAM_NO_CHECK 0 /* for backward compatibility */ | ||
36 | |||
37 | #define MU_STREAM_READ 0x00000001 | 35 | #define MU_STREAM_READ 0x00000001 |
38 | #define MU_STREAM_WRITE 0x00000002 | 36 | #define MU_STREAM_WRITE 0x00000002 |
39 | #define MU_STREAM_RDWR (MU_STREAM_READ|MU_STREAM_WRITE) | 37 | #define MU_STREAM_RDWR (MU_STREAM_READ|MU_STREAM_WRITE) |
... | @@ -63,6 +61,7 @@ enum mu_buffer_type | ... | @@ -63,6 +61,7 @@ enum mu_buffer_type |
63 | #define MU_IOCTL_ABRIDGE_SEEK MU_IOCTL_SET_SEEK_LIMITS | 61 | #define MU_IOCTL_ABRIDGE_SEEK MU_IOCTL_SET_SEEK_LIMITS |
64 | #define MU_IOCTL_GET_SEEK_LIMITS 5 | 62 | #define MU_IOCTL_GET_SEEK_LIMITS 5 |
65 | #define MU_IOCTL_SET_TRANSPORT 6 | 63 | #define MU_IOCTL_SET_TRANSPORT 6 |
64 | #define MU_IOCTL_SWAP_STREAM 7 | ||
66 | 65 | ||
67 | void mu_stream_ref (mu_stream_t stream); | 66 | void mu_stream_ref (mu_stream_t stream); |
68 | void mu_stream_unref (mu_stream_t stream); | 67 | void mu_stream_unref (mu_stream_t stream); |
... | @@ -72,6 +71,8 @@ const char *mu_stream_strerror (mu_stream_t stream, int rc); | ... | @@ -72,6 +71,8 @@ const char *mu_stream_strerror (mu_stream_t stream, int rc); |
72 | int mu_stream_err (mu_stream_t stream); | 71 | int mu_stream_err (mu_stream_t stream); |
73 | int mu_stream_last_error (mu_stream_t stream); | 72 | int mu_stream_last_error (mu_stream_t stream); |
74 | void mu_stream_clearerr (mu_stream_t stream); | 73 | void mu_stream_clearerr (mu_stream_t stream); |
74 | int mu_stream_seterr (struct _mu_stream *stream, int code, int perm); | ||
75 | |||
75 | int mu_stream_eof (mu_stream_t stream); | 76 | int mu_stream_eof (mu_stream_t stream); |
76 | int mu_stream_seek (mu_stream_t stream, mu_off_t offset, int whence, | 77 | int mu_stream_seek (mu_stream_t stream, mu_off_t offset, int whence, |
77 | mu_off_t *pres); | 78 | mu_off_t *pres); | ... | ... |
... | @@ -65,4 +65,11 @@ int mu_stream_write_unbuffered (mu_stream_t stream, | ... | @@ -65,4 +65,11 @@ int mu_stream_write_unbuffered (mu_stream_t stream, |
65 | const void *buf, size_t size, | 65 | const void *buf, size_t size, |
66 | int full_write, size_t *pnwritten); | 66 | int full_write, size_t *pnwritten); |
67 | 67 | ||
68 | #define _MU_SWAP_FIRST_ONLY 0x01 | ||
69 | #define _MU_SWAP_IOCTL_MUST_SUCCEED 0x02 | ||
70 | |||
71 | int _mu_stream_swap_streams (mu_stream_t stream, mu_stream_t *curtrans, | ||
72 | mu_stream_t *newtrans, int flags); | ||
73 | |||
74 | |||
68 | #endif | 75 | #endif | ... | ... |
... | @@ -1604,7 +1604,6 @@ amd_body_stream_read (mu_stream_t is, char *buffer, size_t buflen, | ... | @@ -1604,7 +1604,6 @@ amd_body_stream_read (mu_stream_t is, char *buffer, size_t buflen, |
1604 | 1604 | ||
1605 | if (buffer == NULL || buflen == 0) | 1605 | if (buffer == NULL || buflen == 0) |
1606 | { | 1606 | { |
1607 | if (pnread) | ||
1608 | *pnread = nread; | 1607 | *pnread = nread; |
1609 | return 0; | 1608 | return 0; |
1610 | } | 1609 | } |
... | @@ -1626,11 +1625,11 @@ amd_body_stream_read (mu_stream_t is, char *buffer, size_t buflen, | ... | @@ -1626,11 +1625,11 @@ amd_body_stream_read (mu_stream_t is, char *buffer, size_t buflen, |
1626 | { | 1625 | { |
1627 | status = mu_stream_read (mhm->stream, buffer, nread, &nread); | 1626 | status = mu_stream_read (mhm->stream, buffer, nread, &nread); |
1628 | amdstr->off += nread; | 1627 | amdstr->off += nread; |
1629 | if (pnread) | ||
1630 | *pnread = nread; | ||
1631 | } | 1628 | } |
1632 | } | 1629 | } |
1633 | 1630 | ||
1631 | *pnread = nread; | ||
1632 | |||
1634 | mu_monitor_unlock (mhm->amd->mailbox->monitor); | 1633 | mu_monitor_unlock (mhm->amd->mailbox->monitor); |
1635 | #ifdef WITH_PTHREAD | 1634 | #ifdef WITH_PTHREAD |
1636 | pthread_cleanup_pop (0); | 1635 | pthread_cleanup_pop (0); | ... | ... |
... | @@ -83,3 +83,5 @@ MU_ERR_NO_INTERFACE _("No such interface") | ... | @@ -83,3 +83,5 @@ MU_ERR_NO_INTERFACE _("No such interface") |
83 | MU_ERR_BADOP _("Inappropriate operation for this mode") | 83 | MU_ERR_BADOP _("Inappropriate operation for this mode") |
84 | MU_ERR_BAD_FILENAME _("Badly formed file or directory name") | 84 | MU_ERR_BAD_FILENAME _("Badly formed file or directory name") |
85 | MU_ERR_READ _("Read error") | 85 | MU_ERR_READ _("Read error") |
86 | |||
87 | MU_ERR_NO_TRANSPORT _("Transport stream not set") | ... | ... |
... | @@ -400,6 +400,9 @@ _icvt_ioctl (mu_stream_t stream, int code, void *ptr) | ... | @@ -400,6 +400,9 @@ _icvt_ioctl (mu_stream_t stream, int code, void *ptr) |
400 | ptrans[1] = NULL; | 400 | ptrans[1] = NULL; |
401 | break; | 401 | break; |
402 | 402 | ||
403 | case MU_IOCTL_SWAP_STREAM: | ||
404 | return mu_stream_ioctl (s->transport, code, ptr); | ||
405 | |||
403 | default: | 406 | default: |
404 | return EINVAL; | 407 | return EINVAL; |
405 | } | 408 | } | ... | ... |
... | @@ -149,6 +149,11 @@ _iostream_ctl (struct _mu_stream *str, int op, void *arg) | ... | @@ -149,6 +149,11 @@ _iostream_ctl (struct _mu_stream *str, int op, void *arg) |
149 | sp->transport[_MU_STREAM_OUTPUT] = (mu_stream_t) ptrans[1]; | 149 | sp->transport[_MU_STREAM_OUTPUT] = (mu_stream_t) ptrans[1]; |
150 | break; | 150 | break; |
151 | 151 | ||
152 | case MU_IOCTL_SWAP_STREAM: | ||
153 | if (!arg) | ||
154 | return EINVAL; | ||
155 | return _mu_stream_swap_streams (str, sp->transport, arg, 0); | ||
156 | |||
152 | default: | 157 | default: |
153 | return EINVAL; | 158 | return EINVAL; |
154 | } | 159 | } | ... | ... |
... | @@ -32,8 +32,8 @@ | ... | @@ -32,8 +32,8 @@ |
32 | #include <mailutils/stream.h> | 32 | #include <mailutils/stream.h> |
33 | #include <mailutils/sys/stream.h> | 33 | #include <mailutils/sys/stream.h> |
34 | 34 | ||
35 | static int | 35 | int |
36 | _stream_seterror (struct _mu_stream *stream, int code, int perm) | 36 | mu_stream_seterr (struct _mu_stream *stream, int code, int perm) |
37 | { | 37 | { |
38 | stream->last_err = code; | 38 | stream->last_err = code; |
39 | switch (code) | 39 | switch (code) |
... | @@ -236,7 +236,7 @@ mu_stream_open (mu_stream_t stream) | ... | @@ -236,7 +236,7 @@ mu_stream_open (mu_stream_t stream) |
236 | int rc; | 236 | int rc; |
237 | 237 | ||
238 | if (stream->open && (rc = stream->open (stream))) | 238 | if (stream->open && (rc = stream->open (stream))) |
239 | return _stream_seterror (stream, rc, 1); | 239 | return mu_stream_seterr (stream, rc, 1); |
240 | stream->bytes_in = stream->bytes_out = 0; | 240 | stream->bytes_in = stream->bytes_out = 0; |
241 | return 0; | 241 | return 0; |
242 | } | 242 | } |
... | @@ -286,10 +286,10 @@ mu_stream_seek (mu_stream_t stream, mu_off_t offset, int whence, | ... | @@ -286,10 +286,10 @@ mu_stream_seek (mu_stream_t stream, mu_off_t offset, int whence, |
286 | mu_off_t size; | 286 | mu_off_t size; |
287 | 287 | ||
288 | if (!stream->seek) | 288 | if (!stream->seek) |
289 | return _stream_seterror (stream, ENOSYS, 0); | 289 | return mu_stream_seterr (stream, ENOSYS, 0); |
290 | 290 | ||
291 | if (!(stream->flags & MU_STREAM_SEEK)) | 291 | if (!(stream->flags & MU_STREAM_SEEK)) |
292 | return _stream_seterror (stream, EACCES, 1); | 292 | return mu_stream_seterr (stream, EACCES, 1); |
293 | 293 | ||
294 | switch (whence) | 294 | switch (whence) |
295 | { | 295 | { |
... | @@ -308,12 +308,12 @@ mu_stream_seek (mu_stream_t stream, mu_off_t offset, int whence, | ... | @@ -308,12 +308,12 @@ mu_stream_seek (mu_stream_t stream, mu_off_t offset, int whence, |
308 | case MU_SEEK_END: | 308 | case MU_SEEK_END: |
309 | rc = mu_stream_size (stream, &size); | 309 | rc = mu_stream_size (stream, &size); |
310 | if (rc) | 310 | if (rc) |
311 | return _stream_seterror (stream, rc, 1); | 311 | return mu_stream_seterr (stream, rc, 1); |
312 | offset += size; | 312 | offset += size; |
313 | break; | 313 | break; |
314 | 314 | ||
315 | default: | 315 | default: |
316 | return _stream_seterror (stream, EINVAL, 1); | 316 | return mu_stream_seterr (stream, EINVAL, 1); |
317 | } | 317 | } |
318 | 318 | ||
319 | if (stream->buftype == mu_buffer_none | 319 | if (stream->buftype == mu_buffer_none |
... | @@ -326,7 +326,7 @@ mu_stream_seek (mu_stream_t stream, mu_off_t offset, int whence, | ... | @@ -326,7 +326,7 @@ mu_stream_seek (mu_stream_t stream, mu_off_t offset, int whence, |
326 | if (rc == ESPIPE) | 326 | if (rc == ESPIPE) |
327 | return rc; | 327 | return rc; |
328 | if (rc) | 328 | if (rc) |
329 | return _stream_seterror (stream, rc, 1); | 329 | return mu_stream_seterr (stream, rc, 1); |
330 | _stream_cleareof (stream); | 330 | _stream_cleareof (stream); |
331 | } | 331 | } |
332 | 332 | ||
... | @@ -352,7 +352,7 @@ mu_stream_skip_input_bytes (mu_stream_t stream, mu_off_t count, mu_off_t *pres) | ... | @@ -352,7 +352,7 @@ mu_stream_skip_input_bytes (mu_stream_t stream, mu_off_t count, mu_off_t *pres) |
352 | int rc; | 352 | int rc; |
353 | 353 | ||
354 | if (!(stream->flags & MU_STREAM_READ)) | 354 | if (!(stream->flags & MU_STREAM_READ)) |
355 | return _stream_seterror (stream, EACCES, 1); | 355 | return mu_stream_seterr (stream, EACCES, 1); |
356 | 356 | ||
357 | if (stream->buftype == mu_buffer_none) | 357 | if (stream->buftype == mu_buffer_none) |
358 | { | 358 | { |
... | @@ -426,7 +426,7 @@ mu_stream_set_buffer (mu_stream_t stream, enum mu_buffer_type type, | ... | @@ -426,7 +426,7 @@ mu_stream_set_buffer (mu_stream_t stream, enum mu_buffer_type type, |
426 | if (stream->buffer == NULL) | 426 | if (stream->buffer == NULL) |
427 | { | 427 | { |
428 | stream->buftype = mu_buffer_none; | 428 | stream->buftype = mu_buffer_none; |
429 | return _stream_seterror (stream, ENOMEM, 1); | 429 | return mu_stream_seterr (stream, ENOMEM, 1); |
430 | } | 430 | } |
431 | stream->bufsize = size; | 431 | stream->bufsize = size; |
432 | stream->cur = stream->buffer; | 432 | stream->cur = stream->buffer; |
... | @@ -444,10 +444,10 @@ mu_stream_read_unbuffered (mu_stream_t stream, void *buf, size_t size, | ... | @@ -444,10 +444,10 @@ mu_stream_read_unbuffered (mu_stream_t stream, void *buf, size_t size, |
444 | size_t nread; | 444 | size_t nread; |
445 | 445 | ||
446 | if (!stream->read) | 446 | if (!stream->read) |
447 | return _stream_seterror (stream, ENOSYS, 0); | 447 | return mu_stream_seterr (stream, ENOSYS, 0); |
448 | 448 | ||
449 | if (!(stream->flags & MU_STREAM_READ)) | 449 | if (!(stream->flags & MU_STREAM_READ)) |
450 | return _stream_seterror (stream, EACCES, 1); | 450 | return mu_stream_seterr (stream, EACCES, 1); |
451 | 451 | ||
452 | if (stream->flags & _MU_STR_ERR) | 452 | if (stream->flags & _MU_STR_ERR) |
453 | return stream->last_err; | 453 | return stream->last_err; |
... | @@ -479,7 +479,7 @@ mu_stream_read_unbuffered (mu_stream_t stream, void *buf, size_t size, | ... | @@ -479,7 +479,7 @@ mu_stream_read_unbuffered (mu_stream_t stream, void *buf, size_t size, |
479 | 479 | ||
480 | } | 480 | } |
481 | if (size && rc) | 481 | if (size && rc) |
482 | rc = _stream_seterror (stream, rc, 0); | 482 | rc = mu_stream_seterr (stream, rc, 0); |
483 | } | 483 | } |
484 | else | 484 | else |
485 | { | 485 | { |
... | @@ -490,7 +490,7 @@ mu_stream_read_unbuffered (mu_stream_t stream, void *buf, size_t size, | ... | @@ -490,7 +490,7 @@ mu_stream_read_unbuffered (mu_stream_t stream, void *buf, size_t size, |
490 | stream->flags |= _MU_STR_EOF; | 490 | stream->flags |= _MU_STR_EOF; |
491 | stream->bytes_in += nread; | 491 | stream->bytes_in += nread; |
492 | } | 492 | } |
493 | _stream_seterror (stream, rc, rc != 0); | 493 | mu_stream_seterr (stream, rc, rc != 0); |
494 | } | 494 | } |
495 | stream->offset += nread; | 495 | stream->offset += nread; |
496 | if (pnread) | 496 | if (pnread) |
... | @@ -509,10 +509,10 @@ mu_stream_write_unbuffered (mu_stream_t stream, | ... | @@ -509,10 +509,10 @@ mu_stream_write_unbuffered (mu_stream_t stream, |
509 | size_t nwritten; | 509 | size_t nwritten; |
510 | 510 | ||
511 | if (!stream->write) | 511 | if (!stream->write) |
512 | return _stream_seterror (stream, ENOSYS, 0); | 512 | return mu_stream_seterr (stream, ENOSYS, 0); |
513 | 513 | ||
514 | if (!(stream->flags & MU_STREAM_WRITE)) | 514 | if (!(stream->flags & MU_STREAM_WRITE)) |
515 | return _stream_seterror (stream, EACCES, 1); | 515 | return mu_stream_seterr (stream, EACCES, 1); |
516 | 516 | ||
517 | if (stream->flags & _MU_STR_ERR) | 517 | if (stream->flags & _MU_STR_ERR) |
518 | return stream->last_err; | 518 | return stream->last_err; |
... | @@ -555,7 +555,7 @@ mu_stream_write_unbuffered (mu_stream_t stream, | ... | @@ -555,7 +555,7 @@ mu_stream_write_unbuffered (mu_stream_t stream, |
555 | stream->offset += nwritten; | 555 | stream->offset += nwritten; |
556 | if (pnwritten) | 556 | if (pnwritten) |
557 | *pnwritten = nwritten; | 557 | *pnwritten = nwritten; |
558 | _stream_seterror (stream, rc, rc != 0); | 558 | mu_stream_seterr (stream, rc, rc != 0); |
559 | return rc; | 559 | return rc; |
560 | } | 560 | } |
561 | 561 | ||
... | @@ -861,9 +861,9 @@ mu_stream_size (mu_stream_t stream, mu_off_t *psize) | ... | @@ -861,9 +861,9 @@ mu_stream_size (mu_stream_t stream, mu_off_t *psize) |
861 | int rc; | 861 | int rc; |
862 | 862 | ||
863 | if (!stream->size) | 863 | if (!stream->size) |
864 | return _stream_seterror (stream, ENOSYS, 0); | 864 | return mu_stream_seterr (stream, ENOSYS, 0); |
865 | rc = stream->size (stream, psize); | 865 | rc = stream->size (stream, psize); |
866 | return _stream_seterror (stream, rc, rc != 0); | 866 | return mu_stream_seterr (stream, rc, rc != 0); |
867 | } | 867 | } |
868 | 868 | ||
869 | mu_off_t | 869 | mu_off_t |
... | @@ -948,7 +948,87 @@ mu_stream_clr_flags (mu_stream_t stream, int fl) | ... | @@ -948,7 +948,87 @@ mu_stream_clr_flags (mu_stream_t stream, int fl) |
948 | return 0; | 948 | return 0; |
949 | } | 949 | } |
950 | 950 | ||
951 | static void | ||
952 | swapstr (mu_stream_t stream, mu_stream_t *curstr, mu_stream_t *newstr) | ||
953 | { | ||
954 | mu_stream_t tmp; | ||
955 | |||
956 | tmp = *newstr; | ||
957 | *newstr = *curstr; | ||
958 | *curstr = tmp; | ||
959 | if (!(stream->flags & MU_STREAM_AUTOCLOSE)) | ||
960 | { | ||
961 | if (*newstr) | ||
962 | mu_stream_unref (*newstr); | ||
963 | if (tmp) | ||
964 | mu_stream_ref (tmp); | ||
965 | } | ||
966 | if (!tmp) | ||
967 | mu_stream_seterr (stream, MU_ERR_NO_TRANSPORT, 1); | ||
968 | else if (stream->last_err == MU_ERR_NO_TRANSPORT) | ||
969 | mu_stream_clearerr (stream); | ||
970 | } | ||
971 | |||
972 | static int | ||
973 | swapstr_recursive (mu_stream_t stream, mu_stream_t *curstr, | ||
974 | mu_stream_t *newstr, int flags) | ||
975 | { | ||
976 | mu_stream_t strtab[2]; | ||
977 | int rc = ENOSYS; | ||
978 | |||
979 | if (*curstr == NULL && *newstr == NULL) | ||
980 | return 0; | ||
951 | 981 | ||
982 | if (*curstr) | ||
983 | { | ||
984 | strtab[0] = *newstr; | ||
985 | strtab[1] = NULL; | ||
986 | rc = mu_stream_ioctl (*curstr, MU_IOCTL_SWAP_STREAM, strtab); | ||
987 | if (rc) | ||
988 | { | ||
989 | if ((flags & _MU_SWAP_IOCTL_MUST_SUCCEED) | ||
990 | || !(rc == ENOSYS || rc == EINVAL)) | ||
991 | return rc; | ||
992 | } | ||
993 | } | ||
994 | if (rc == 0) | ||
995 | *newstr = strtab[0]; | ||
996 | else | ||
997 | swapstr (stream, curstr, newstr); | ||
998 | return 0; | ||
999 | } | ||
1000 | |||
1001 | /* CURTRANS[2] contains I/O transport streams used by STREAM, | ||
1002 | NEWTRANS[2] contains another pair of streams. | ||
1003 | This function swaps the items of these two arrays using the | ||
1004 | MU_IOCTL_SWAP_STREAM ioctl. It is intended for use by STREAM's | ||
1005 | ioctl method and is currently used by iostream.c */ | ||
1006 | |||
1007 | int | ||
1008 | _mu_stream_swap_streams (mu_stream_t stream, mu_stream_t *curtrans, | ||
1009 | mu_stream_t *newtrans, int flags) | ||
1010 | { | ||
1011 | int rc; | ||
1012 | |||
1013 | rc = swapstr_recursive (stream, &curtrans[0], &newtrans[0], flags); | ||
1014 | if (rc) | ||
1015 | return rc; | ||
1016 | if (flags & _MU_SWAP_FIRST_ONLY) | ||
1017 | return 0; | ||
1018 | rc = swapstr_recursive (stream, &curtrans[1], &newtrans[1], flags); | ||
1019 | if (rc) | ||
1020 | { | ||
1021 | int rc1 = swapstr_recursive (stream, &curtrans[0], &newtrans[0], flags); | ||
1022 | if (rc1) | ||
1023 | { | ||
1024 | mu_diag_output (MU_DIAG_CRIT, | ||
1025 | _("restoring streams on %p failed: %s"), | ||
1026 | stream, mu_strerror (rc1)); | ||
1027 | abort (); | ||
1028 | } | ||
1029 | } | ||
1030 | return rc; | ||
1031 | } | ||
952 | 1032 | ||
953 | 1033 | ||
954 | 1034 | ... | ... |
... | @@ -176,6 +176,7 @@ _xscript_ctl (struct _mu_stream *str, int op, void *arg) | ... | @@ -176,6 +176,7 @@ _xscript_ctl (struct _mu_stream *str, int op, void *arg) |
176 | { | 176 | { |
177 | struct _mu_xscript_stream *sp = (struct _mu_xscript_stream *)str; | 177 | struct _mu_xscript_stream *sp = (struct _mu_xscript_stream *)str; |
178 | mu_transport_t *ptrans; | 178 | mu_transport_t *ptrans; |
179 | mu_stream_t strtab[2]; | ||
179 | 180 | ||
180 | switch (op) | 181 | switch (op) |
181 | { | 182 | { |
... | @@ -197,6 +198,8 @@ _xscript_ctl (struct _mu_stream *str, int op, void *arg) | ... | @@ -197,6 +198,8 @@ _xscript_ctl (struct _mu_stream *str, int op, void *arg) |
197 | sp->logstr = (mu_stream_t) ptrans[1]; | 198 | sp->logstr = (mu_stream_t) ptrans[1]; |
198 | break; | 199 | break; |
199 | 200 | ||
201 | case MU_IOCTL_SWAP_STREAM: | ||
202 | /* fall through */ | ||
200 | default: | 203 | default: |
201 | return mu_stream_ioctl (sp->transport, op, arg); | 204 | return mu_stream_ioctl (sp->transport, op, arg); |
202 | } | 205 | } | ... | ... |
... | @@ -126,14 +126,6 @@ pop3d_abquit (int reason) | ... | @@ -126,14 +126,6 @@ pop3d_abquit (int reason) |
126 | exit (code); | 126 | exit (code); |
127 | } | 127 | } |
128 | 128 | ||
129 | /* Keeps the *real* output stream. Ostream is a RFC822 filter built over | ||
130 | real_ostream, or even over a TLS stream, which in turn is based on this | ||
131 | real_ostream. | ||
132 | FIXME: This is sorta kludge: we could use MU_IOCTL_GET_TRANSPORT call | ||
133 | to retrieve the bottom-level stream, if filter streams supported it. | ||
134 | */ | ||
135 | static mu_stream_t real_istream, real_ostream; | ||
136 | |||
137 | void | 129 | void |
138 | pop3d_setio (FILE *in, FILE *out) | 130 | pop3d_setio (FILE *in, FILE *out) |
139 | { | 131 | { |
... | @@ -147,20 +139,24 @@ pop3d_setio (FILE *in, FILE *out) | ... | @@ -147,20 +139,24 @@ pop3d_setio (FILE *in, FILE *out) |
147 | if (mu_stdio_stream_create (&istream, fileno (in), | 139 | if (mu_stdio_stream_create (&istream, fileno (in), |
148 | MU_STREAM_READ | MU_STREAM_AUTOCLOSE)) | 140 | MU_STREAM_READ | MU_STREAM_AUTOCLOSE)) |
149 | pop3d_abquit (ERR_NO_IFILE); | 141 | pop3d_abquit (ERR_NO_IFILE); |
150 | real_istream = istream; | ||
151 | mu_stream_set_buffer (istream, mu_buffer_line, 1024); | 142 | mu_stream_set_buffer (istream, mu_buffer_line, 1024); |
152 | 143 | ||
153 | if (mu_stdio_stream_create (&str, fileno (out), | 144 | if (mu_stdio_stream_create (&ostream, fileno (out), |
154 | MU_STREAM_WRITE | MU_STREAM_AUTOCLOSE)) | 145 | MU_STREAM_WRITE | MU_STREAM_AUTOCLOSE)) |
155 | pop3d_abquit (ERR_NO_OFILE); | 146 | pop3d_abquit (ERR_NO_OFILE); |
156 | real_ostream = str; | ||
157 | if (mu_filter_create (&ostream, str, "rfc822", MU_FILTER_ENCODE, | ||
158 | MU_STREAM_WRITE)) | ||
159 | pop3d_abquit (ERR_NO_IFILE); | ||
160 | mu_stream_set_buffer (ostream, mu_buffer_line, 1024); | ||
161 | 147 | ||
162 | if (mu_iostream_create (&iostream, istream, ostream)) | 148 | /* Combine the two streams into an I/O one. */ |
149 | if (mu_iostream_create (&str, istream, ostream)) | ||
163 | pop3d_abquit (ERR_FILE); | 150 | pop3d_abquit (ERR_FILE); |
151 | |||
152 | /* Convert all writes to CRLF form. | ||
153 | There is no need to convert reads, as the code ignores extra \r anyway. | ||
154 | This also installs an extra full buffering, which is needed for TLS | ||
155 | code (see below). */ | ||
156 | if (mu_filter_create (&iostream, str, "rfc822", MU_FILTER_ENCODE, | ||
157 | MU_STREAM_WRITE | MU_STREAM_RDTHRU)) | ||
158 | pop3d_abquit (ERR_NO_IFILE); | ||
159 | |||
164 | if (pop3d_transcript) | 160 | if (pop3d_transcript) |
165 | { | 161 | { |
166 | int rc; | 162 | int rc; |
... | @@ -192,36 +188,40 @@ pop3d_setio (FILE *in, FILE *out) | ... | @@ -192,36 +188,40 @@ pop3d_setio (FILE *in, FILE *out) |
192 | int | 188 | int |
193 | pop3d_init_tls_server () | 189 | pop3d_init_tls_server () |
194 | { | 190 | { |
195 | mu_stream_t stream; | 191 | mu_stream_t tlsstream, stream[2]; |
196 | int rc; | 192 | int rc; |
197 | 193 | ||
198 | rc = mu_tls_server_stream_create (&stream, real_istream, real_ostream, 0); | 194 | stream[0] = stream[1] = NULL; |
195 | rc = mu_stream_ioctl (iostream, MU_IOCTL_SWAP_STREAM, stream); | ||
196 | if (rc) | ||
197 | { | ||
198 | mu_error (_("%s failed: %s"), "MU_IOCTL_SWAP_STREAM", | ||
199 | mu_stream_strerror (iostream, rc)); | ||
200 | return 1; | ||
201 | } | ||
202 | |||
203 | rc = mu_tls_server_stream_create (&tlsstream, stream[0], stream[1], 0); | ||
199 | if (rc) | 204 | if (rc) |
200 | return 1; | 205 | return 1; |
201 | 206 | ||
202 | rc = mu_stream_open (stream); | 207 | rc = mu_stream_open (tlsstream); |
203 | if (rc) | 208 | if (rc) |
204 | { | 209 | { |
205 | mu_diag_output (MU_DIAG_ERROR, _("cannot open TLS stream: %s"), | 210 | mu_diag_output (MU_DIAG_ERROR, _("cannot open TLS stream: %s"), |
206 | mu_stream_strerror (stream, rc)); | 211 | mu_stream_strerror (tlsstream, rc)); |
207 | mu_stream_destroy (&stream); | 212 | mu_stream_destroy (&tlsstream); |
208 | return 1; | 213 | return 1; |
209 | } | 214 | } |
215 | else | ||
216 | stream[0] = stream[1] = tlsstream; | ||
210 | 217 | ||
211 | if (mu_filter_create (&stream, stream, "rfc822", MU_FILTER_ENCODE, | 218 | rc = mu_stream_ioctl (iostream, MU_IOCTL_SWAP_STREAM, stream); |
212 | MU_STREAM_WRITE | MU_STREAM_RDTHRU)) | 219 | if (rc) |
213 | pop3d_abquit (ERR_NO_IFILE); | ||
214 | |||
215 | if (pop3d_transcript) | ||
216 | { | 220 | { |
217 | mu_transport_t trans[2]; | 221 | mu_error (_("%s failed: %s"), "MU_IOCTL_SWAP_STREAM", |
218 | 222 | mu_stream_strerror (iostream, rc)); | |
219 | trans[0] = (mu_transport_t) stream; | 223 | pop3d_abquit (ERR_IO); |
220 | trans[1] = NULL; | ||
221 | mu_stream_ioctl (iostream, MU_IOCTL_SET_TRANSPORT, trans); | ||
222 | } | 224 | } |
223 | else | ||
224 | iostream = stream; | ||
225 | return 0; | 225 | return 0; |
226 | } | 226 | } |
227 | #endif | 227 | #endif | ... | ... |
-
Please register or sign in to post a comment