Read the pty one byte at a time.

There are two things to note: first, see https://sourceforge.net/p/iaxmodem/code/28/ The read() can block for some period of time if the other end of the pty is being written to in order for the read() to meet the requested bytes.  So, in order for us to avoid those delays it's necessary to do the read()s one byte at a time.  Second, the return value of t31_at_rx() must be utilized in case the t31 buffer is full.  If we don't, then we risk losing bytes of data sent by the DTE which will never make it to the modem.
This commit is contained in:
Lee Howard 2022-06-07 16:49:15 -07:00
parent dce03f3331
commit cd6cc31cdf
1 changed files with 30 additions and 17 deletions

View File

@ -1232,7 +1232,7 @@ static int modem_wait_sock(modem_t *modem, int ms, modem_poll_t flags)
static void *SWITCH_THREAD_FUNC modem_thread(switch_thread_t *thread, void *obj)
{
modem_t *modem = obj;
int r, avail;
int r, avail, taken;
#ifdef WIN32
DWORD readBytes;
OVERLAPPED o;
@ -1272,30 +1272,43 @@ static void *SWITCH_THREAD_FUNC modem_thread(switch_thread_t *thread, void *obj)
}
avail = t31_at_rx_free_space(modem->t31_state);
if (avail == 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Buffer Full, retrying....\n");
if (avail == 0 || modem->t31_state->non_ecm_tx.holding) {
if (! modem->t31_state->non_ecm_tx.holding)
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Buffer Full, retrying....\n");
switch_yield(10000);
continue;
}
do {
#ifndef WIN32
r = read(modem->master, buf, avail);
r = read(modem->master, buf, 1);
#else
o.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
o.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
/* Initialize the rest of the OVERLAPPED structure to zero. */
o.Internal = 0;
o.InternalHigh = 0;
o.Offset = 0;
o.OffsetHigh = 0;
assert(o.hEvent);
if (!ReadFile(modem->master, buf, avail, &readBytes, &o)) {
GetOverlappedResult(modem->master, &o, &readBytes,TRUE);
}
CloseHandle (o.hEvent);
r = readBytes;
/* Initialize the rest of the OVERLAPPED structure to zero. */
o.Internal = 0;
o.InternalHigh = 0;
o.Offset = 0;
o.OffsetHigh = 0;
assert(o.hEvent);
if (!ReadFile(modem->master, buf, 1, &readBytes, &o)) {
GetOverlappedResult(modem->master, &o, &readBytes,TRUE);
}
CloseHandle (o.hEvent);
r = readBytes;
#endif
t31_at_rx(modem->t31_state, buf, r);
if (r > 0) {
taken = t31_at_rx(modem->t31_state, buf, r);
if (taken != r) {
/* As we checked the available buffer beforehand and only
read and sent that number of bytes, this should not
happen, and if it does will cause data loss and possibly
timing problems. */
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unexpected modem buffering [%s]. Sent %d bytes, modem buffered %d.\n", modem->devlink, r, taken);
}
avail -= taken;
}
} while (r > 0 && avail > 0);
if (!strncasecmp(buf, "AT", 2)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Command on %s [%s]\n", modem->devlink, buf);