Buffer a message for the multiplexed output stream. Is not used for (normal) MSG_DATA. */
| 963 | |
| 964 | /* Buffer a message for the multiplexed output stream. Is not used for (normal) MSG_DATA. */ |
| 965 | int send_msg(enum msgcode code, const char *buf, size_t len, int convert) |
| 966 | { |
| 967 | char *hdr; |
| 968 | size_t needed, pos; |
| 969 | BOOL want_debug = DEBUG_GTE(IO, 1) && convert >= 0 && (msgs2stderr == 1 || code != MSG_INFO); |
| 970 | |
| 971 | if (!OUT_MULTIPLEXED) |
| 972 | return 0; |
| 973 | |
| 974 | if (want_debug) { |
| 975 | rprintf(FINFO, "[%s] send_msg(%d, %" SIZE_T_FMT_MOD "d)\n", |
| 976 | who_am_i(), (int)code, (SIZE_T_FMT_CAST)len); |
| 977 | } |
| 978 | |
| 979 | /* When checking for enough free space for this message, we need to |
| 980 | * make sure that there is space for the 4-byte header, plus we'll |
| 981 | * assume that we may waste up to 3 bytes (if the header doesn't fit |
| 982 | * at the physical end of the buffer). */ |
| 983 | #ifdef ICONV_OPTION |
| 984 | if (convert > 0 && ic_send == (iconv_t)-1) |
| 985 | convert = 0; |
| 986 | if (convert > 0) { |
| 987 | /* Ensuring double-size room leaves space for maximal conversion expansion. */ |
| 988 | needed = len*2 + 4 + 3; |
| 989 | } else |
| 990 | #endif |
| 991 | needed = len + 4 + 3; |
| 992 | if (iobuf.msg.len + needed > iobuf.msg.size) { |
| 993 | if (am_sender) |
| 994 | perform_io(needed, PIO_NEED_MSGROOM); |
| 995 | else { /* We sometimes allow the iobuf.msg size to increase to avoid a deadlock. */ |
| 996 | size_t old_size = iobuf.msg.size; |
| 997 | restore_iobuf_size(&iobuf.msg); |
| 998 | realloc_xbuf(&iobuf.msg, iobuf.msg.size * 2); |
| 999 | if (iobuf.msg.pos + iobuf.msg.len > old_size) |
| 1000 | memcpy(iobuf.msg.buf + old_size, iobuf.msg.buf, iobuf.msg.pos + iobuf.msg.len - old_size); |
| 1001 | } |
| 1002 | } |
| 1003 | |
| 1004 | pos = iobuf.msg.pos + iobuf.msg.len; /* Must be set after any flushing. */ |
| 1005 | if (pos >= iobuf.msg.size) |
| 1006 | pos -= iobuf.msg.size; |
| 1007 | else if (pos + 4 > iobuf.msg.size) { |
| 1008 | /* The 4-byte header won't fit at the end of the buffer, |
| 1009 | * so we'll temporarily reduce the message buffer's size |
| 1010 | * and put the header at the start of the buffer. */ |
| 1011 | reduce_iobuf_size(&iobuf.msg, pos); |
| 1012 | pos = 0; |
| 1013 | } |
| 1014 | hdr = iobuf.msg.buf + pos; |
| 1015 | |
| 1016 | iobuf.msg.len += 4; /* Allocate room for the coming header bytes. */ |
| 1017 | |
| 1018 | #ifdef ICONV_OPTION |
| 1019 | if (convert > 0) { |
| 1020 | xbuf inbuf; |
| 1021 | |
| 1022 | INIT_XBUF(inbuf, (char*)buf, len, (size_t)-1); |
no test coverage detected