Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cf6b334bcc | |||
| 09e96e72f7 | |||
| 688fc53caf | |||
| 4d1d6978e4 | |||
| 8f03aabe30 |
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
m4_define([pkg_version], [0.13])
|
m4_define([pkg_version], [0.14])
|
||||||
#m4_define([pkg_revision], [005])
|
#m4_define([pkg_revision], [005])
|
||||||
m4_define([pkg_version], m4_ifdef([pkg_revision], [pkg_version.pkg_revision], [pkg_version]))
|
m4_define([pkg_version], m4_ifdef([pkg_revision], [pkg_version.pkg_revision], [pkg_version]))
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/poll.h>
|
#include <sys/poll.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <sys/time.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include "telnet.h"
|
#include "telnet.h"
|
||||||
@@ -61,7 +62,9 @@ typedef struct {
|
|||||||
|
|
||||||
struct fuse_pollhandle *ph;
|
struct fuse_pollhandle *ph;
|
||||||
|
|
||||||
volatile char n_fds;
|
volatile int rel_pending;
|
||||||
|
volatile int slave_suspended; /*waiting for application to read data */
|
||||||
|
volatile int master_suspended; /*server is not ready to receive data */
|
||||||
struct pollfd fds[3];
|
struct pollfd fds[3];
|
||||||
|
|
||||||
char net_buf[NET_BUF_SIZE];
|
char net_buf[NET_BUF_SIZE];
|
||||||
@@ -74,6 +77,7 @@ typedef struct {
|
|||||||
int smcr_last;
|
int smcr_last;
|
||||||
|
|
||||||
volatile int pollin;
|
volatile int pollin;
|
||||||
|
volatile int pollout;
|
||||||
volatile int error;
|
volatile int error;
|
||||||
int epipe;
|
int epipe;
|
||||||
|
|
||||||
@@ -83,18 +87,40 @@ typedef struct {
|
|||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
#define gettid() (pid_t)syscall(__NR_gettid)
|
#define gettid() (pid_t)syscall(__NR_gettid)
|
||||||
|
|
||||||
|
static const char *_hms_txt(char *buf, unsigned int len)
|
||||||
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
unsigned int sod, hh, mm, ss;
|
||||||
|
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
|
||||||
|
sod = tv.tv_sec % (24 * 3600);
|
||||||
|
hh = sod / 3600;
|
||||||
|
mm = (sod - hh * 3600) / 60;
|
||||||
|
ss = sod - hh * 3600 - mm * 60;
|
||||||
|
snprintf(buf, len, "%02d:%02d:%02d.%06d",
|
||||||
|
hh, mm, ss, (unsigned int)tv.tv_usec);
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
_PRF2_ static void _log(int prio, const char *fmt, ...)
|
_PRF2_ static void _log(int prio, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list arg;
|
va_list arg;
|
||||||
char buf[256];
|
char buf[256], buft[64];
|
||||||
|
|
||||||
va_start(arg, fmt);
|
va_start(arg, fmt);
|
||||||
vsnprintf(buf, sizeof(buf), fmt, arg);
|
vsnprintf(buf, sizeof(buf), fmt, arg);
|
||||||
|
|
||||||
if (ttynvt_param.logstd)
|
if (ttynvt_param.logstd)
|
||||||
printf("[%d] %d: %s", gettid(), prio, buf);
|
{
|
||||||
|
printf("%s: [%d] %d: %s",
|
||||||
|
_hms_txt(buft, sizeof(buft)), gettid(), prio, buf);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
syslog(prio, "[%d] %s", gettid(), buf);
|
syslog(prio, "[%d] %s", gettid(), buf);
|
||||||
|
}
|
||||||
|
|
||||||
va_end(arg);
|
va_end(arg);
|
||||||
}
|
}
|
||||||
@@ -189,7 +215,7 @@ static void ttynvt_release(fuse_req_t req, struct fuse_file_info *info)
|
|||||||
|
|
||||||
_log(LOG_INFO, "connection closed\n");
|
_log(LOG_INFO, "connection closed\n");
|
||||||
|
|
||||||
tty->n_fds = 0;
|
tty->rel_pending = 1;
|
||||||
_fd_close(tty->fds[FD_NET].fd);
|
_fd_close(tty->fds[FD_NET].fd);
|
||||||
_fd_close(tty->fds[FD_MASTER].fd);
|
_fd_close(tty->fds[FD_MASTER].fd);
|
||||||
_fd_close(tty->fds[FD_SLAVE].fd);
|
_fd_close(tty->fds[FD_SLAVE].fd);
|
||||||
@@ -255,22 +281,26 @@ static void *_read_net(void *arg)
|
|||||||
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
|
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
|
||||||
DBG2("%s: net_cnt=%d\n", __func__, tty->net_cnt);
|
DBG2("%s: net_cnt=%d\n", __func__, tty->net_cnt);
|
||||||
|
|
||||||
while (tty->n_fds > 0)
|
while (!tty->rel_pending)
|
||||||
{
|
{
|
||||||
tty->fds[FD_NET].revents = tty->fds[FD_MASTER].revents =
|
tty->fds[FD_NET].revents = tty->fds[FD_MASTER].revents =
|
||||||
tty->fds[FD_SLAVE].revents = 0;
|
tty->fds[FD_SLAVE].revents = 0;
|
||||||
res = poll(tty->fds, tty->n_fds, -1);
|
tty->fds[FD_SLAVE].events = tty->slave_suspended ? POLLPRI : POLLIN;
|
||||||
DBG2("%s: res=%d N=%d events-N/M/S=%#x/%#x/%#x\n", __func__,
|
tty->fds[FD_MASTER].events = tty->master_suspended ? POLLPRI : POLLIN;
|
||||||
res, tty->n_fds,
|
|
||||||
tty->fds[FD_NET].revents, tty->fds[FD_MASTER].revents,
|
res = poll(tty->fds, 3, -1);
|
||||||
tty->fds[FD_SLAVE].revents);
|
DBG2("%s: res=%d events-N/M/S=%x:%x/%x:%x/%x:%x SS=%d MS=%d\n",
|
||||||
|
__func__, res, tty->fds[FD_NET].events, tty->fds[FD_NET].revents,
|
||||||
|
tty->fds[FD_MASTER].events, tty->fds[FD_MASTER].revents,
|
||||||
|
tty->fds[FD_SLAVE].events, tty->fds[FD_SLAVE].revents,
|
||||||
|
tty->slave_suspended, tty->master_suspended);
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
{
|
{
|
||||||
if (errno == EINTR)
|
if (errno == EINTR)
|
||||||
continue;
|
continue;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (tty->n_fds == 0)
|
if (tty->rel_pending)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (tty->fds[FD_NET].revents & POLLIN)
|
if (tty->fds[FD_NET].revents & POLLIN)
|
||||||
@@ -307,14 +337,20 @@ static void *_read_net(void *arg)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tty->fds[FD_MASTER].revents & POLLIN)
|
if ((tty->fds[FD_MASTER].revents & POLLIN) && !tty->master_suspended)
|
||||||
{
|
{
|
||||||
res = read(tty->fds[FD_MASTER].fd, buf, TMP_BUF_SIZE);
|
res = read(tty->fds[FD_MASTER].fd, buf, TMP_BUF_SIZE);
|
||||||
|
DBG("%s: read res=%d pollout=%d\n", __func__, res, tty->pollout);
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
{
|
{
|
||||||
_log(LOG_ERR, "master read error: %m\n");
|
_log(LOG_ERR, "master read error: %m\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (tty->pollout == 0)
|
||||||
|
{
|
||||||
|
tty->pollout = 1;
|
||||||
|
_notify(tty);
|
||||||
|
}
|
||||||
DBG2_BUF("TtyM in ", buf, res);
|
DBG2_BUF("TtyM in ", buf, res);
|
||||||
telnet_tx(tty->tn, buf, res);
|
telnet_tx(tty->tn, buf, res);
|
||||||
}
|
}
|
||||||
@@ -322,7 +358,7 @@ static void *_read_net(void *arg)
|
|||||||
if (tty->fds[FD_SLAVE].revents & POLLIN)
|
if (tty->fds[FD_SLAVE].revents & POLLIN)
|
||||||
{
|
{
|
||||||
tty->pollin = 1;
|
tty->pollin = 1;
|
||||||
tty->n_fds = 2; /* Disable polling of Slave */
|
tty->slave_suspended = 1; /* Disable polling of Slave */
|
||||||
_notify(tty);
|
_notify(tty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -442,6 +478,10 @@ static void _modem_status_cb(void *cctx, int status)
|
|||||||
if (status & TNS_STATE_CTS)
|
if (status & TNS_STATE_CTS)
|
||||||
mcr |= TIOCM_CTS;
|
mcr |= TIOCM_CTS;
|
||||||
|
|
||||||
|
tty->master_suspended = (mcr & TIOCM_CTS) ? 0 : 1;
|
||||||
|
DBG("%s: tty=%p mcr=%x MS=%d\n", __func__, tty, mcr,
|
||||||
|
tty->master_suspended);
|
||||||
|
|
||||||
pthread_mutex_lock(&tty->tty_lock);
|
pthread_mutex_lock(&tty->tty_lock);
|
||||||
tty->smcr_last = tty->smcr;
|
tty->smcr_last = tty->smcr;
|
||||||
tty->smcr = mcr;
|
tty->smcr = mcr;
|
||||||
@@ -474,6 +514,8 @@ static void ttynvt_open(fuse_req_t req, struct fuse_file_info *info)
|
|||||||
for (n = 0; n < 3; n++)
|
for (n = 0; n < 3; n++)
|
||||||
tty->fds[n].fd = -1;
|
tty->fds[n].fd = -1;
|
||||||
|
|
||||||
|
tty->pollout = 1;
|
||||||
|
|
||||||
tty->tn = telnet_ctx_init(tty, _srv_write, _srv_read, _modem_status_cb);
|
tty->tn = telnet_ctx_init(tty, _srv_write, _srv_read, _modem_status_cb);
|
||||||
if (!tty->tn)
|
if (!tty->tn)
|
||||||
{
|
{
|
||||||
@@ -542,8 +584,6 @@ static void ttynvt_open(fuse_req_t req, struct fuse_file_info *info)
|
|||||||
goto open_err;
|
goto open_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
tty->n_fds = 3; /* Initially poll Net, Master, and Slave */
|
|
||||||
|
|
||||||
info->fh = (uintptr_t) tty;
|
info->fh = (uintptr_t) tty;
|
||||||
info->nonseekable = 1;
|
info->nonseekable = 1;
|
||||||
info->direct_io = 1;
|
info->direct_io = 1;
|
||||||
@@ -574,7 +614,7 @@ ttynvt_read(fuse_req_t req, size_t size, off_t off,
|
|||||||
{
|
{
|
||||||
ttynvt_t *tty = (ttynvt_t *) (uintptr_t) info->fh;
|
ttynvt_t *tty = (ttynvt_t *) (uintptr_t) info->fh;
|
||||||
char buf[TMP_BUF_SIZE];
|
char buf[TMP_BUF_SIZE];
|
||||||
int res;
|
int res, nr;
|
||||||
|
|
||||||
DBG2("%s\n", __func__);
|
DBG2("%s\n", __func__);
|
||||||
|
|
||||||
@@ -601,8 +641,18 @@ ttynvt_read(fuse_req_t req, size_t size, off_t off,
|
|||||||
res = _is_interrupted ? -2 : read(tty->fds[FD_SLAVE].fd, buf, size);
|
res = _is_interrupted ? -2 : read(tty->fds[FD_SLAVE].fd, buf, size);
|
||||||
_is_interrupted = 0;
|
_is_interrupted = 0;
|
||||||
tty->ptid_read = 0;
|
tty->ptid_read = 0;
|
||||||
tty->n_fds = 3; /* Enable polling of Slave */
|
tty->slave_suspended = 0; /* Enable polling of Slave */
|
||||||
fuse_req_interrupt_func(req, NULL, NULL);
|
fuse_req_interrupt_func(req, NULL, NULL);
|
||||||
|
if (res < (int)size)
|
||||||
|
{
|
||||||
|
tty->pollin = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nr = 0;
|
||||||
|
ioctl(tty->fds[FD_SLAVE].fd, FIONREAD, &nr);
|
||||||
|
tty->pollin = nr > 0;
|
||||||
|
}
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
{
|
{
|
||||||
DBG2("%s: error: %m\n", __func__);
|
DBG2("%s: error: %m\n", __func__);
|
||||||
@@ -647,6 +697,10 @@ ttynvt_write(fuse_req_t req, const char *data, size_t size, off_t off,
|
|||||||
fuse_reply_err(req, errno);
|
fuse_reply_err(req, errno);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else if (res != (int)size)
|
||||||
|
{
|
||||||
|
tty->pollout = 0;
|
||||||
|
}
|
||||||
|
|
||||||
fuse_reply_write(req, res);
|
fuse_reply_write(req, res);
|
||||||
}
|
}
|
||||||
@@ -837,7 +891,7 @@ ttynvt_ioctl(fuse_req_t req, int cmd, void *arg,
|
|||||||
ioctl(tty->fds[FD_SLAVE].fd, cmd, tio);
|
ioctl(tty->fds[FD_SLAVE].fd, cmd, tio);
|
||||||
|
|
||||||
if (cmd == TCSETSF)
|
if (cmd == TCSETSF)
|
||||||
tty->n_fds = 3; /* Re-enable polling of Slave */
|
tty->slave_suspended = 0; /* Re-enable polling of Slave */
|
||||||
|
|
||||||
fuse_reply_ioctl(req, 0, 0, 0);
|
fuse_reply_ioctl(req, 0, 0, 0);
|
||||||
}
|
}
|
||||||
@@ -866,14 +920,16 @@ ttynvt_ioctl(fuse_req_t req, int cmd, void *arg,
|
|||||||
default:
|
default:
|
||||||
case TCIFLUSH:
|
case TCIFLUSH:
|
||||||
byte = 1;
|
byte = 1;
|
||||||
tty->n_fds = 3; /* Re-enable polling of Slave */
|
tty->slave_suspended = 0; /* Re-enable polling of Slave */
|
||||||
break;
|
break;
|
||||||
case TCOFLUSH:
|
case TCOFLUSH:
|
||||||
byte = 2;
|
byte = 2;
|
||||||
|
tty->pollout = 1;
|
||||||
break;
|
break;
|
||||||
case TCIOFLUSH:
|
case TCIOFLUSH:
|
||||||
byte = 3;
|
byte = 3;
|
||||||
tty->n_fds = 3; /* Re-enable polling of Slave */
|
tty->slave_suspended = 0; /* Re-enable polling of Slave */
|
||||||
|
tty->pollout = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
telnet_rfc2217_cfg(tty->tn, TNS_SET_PURGE, &byte, 1);
|
telnet_rfc2217_cfg(tty->tn, TNS_SET_PURGE, &byte, 1);
|
||||||
@@ -1023,18 +1079,19 @@ ttynvt_poll(fuse_req_t req, struct fuse_file_info *info,
|
|||||||
struct fuse_pollhandle *ph)
|
struct fuse_pollhandle *ph)
|
||||||
{
|
{
|
||||||
ttynvt_t *tty = (ttynvt_t *) (uintptr_t) info->fh;
|
ttynvt_t *tty = (ttynvt_t *) (uintptr_t) info->fh;
|
||||||
int revents;
|
int revents = 0;
|
||||||
|
|
||||||
DBG2("%s: tty->pollin=%d tty->error/epipe=%d/%d\n",
|
DBG2("%s: tty->pollin=%d tty->error/epipe=%d/%d\n",
|
||||||
__func__, tty->pollin, tty->error, tty->epipe);
|
__func__, tty->pollin, tty->error, tty->epipe);
|
||||||
|
|
||||||
_update_notify(tty, ph);
|
_update_notify(tty, ph);
|
||||||
|
|
||||||
revents = POLLOUT;
|
if (tty->pollout)
|
||||||
|
{
|
||||||
|
revents = POLLOUT;
|
||||||
|
}
|
||||||
if (tty->pollin)
|
if (tty->pollin)
|
||||||
{
|
{
|
||||||
tty->pollin = 0;
|
|
||||||
revents |= POLLIN;
|
revents |= POLLIN;
|
||||||
}
|
}
|
||||||
if (tty->error)
|
if (tty->error)
|
||||||
|
|||||||
Reference in New Issue
Block a user