TMXR: Added option to use UDP transport for packet transport
This commit is contained in:
parent
25ded050ed
commit
4259b3c83a
5 changed files with 130 additions and 30 deletions
|
@ -68,6 +68,7 @@ A remote console session will close when an EOF character is entered (i.e. ^D or
|
||||||
Serial Console Support
|
Serial Console Support
|
||||||
Separate TCP listening ports per line
|
Separate TCP listening ports per line
|
||||||
Outgoing connections per line (virtual Null Modem cable).
|
Outgoing connections per line (virtual Null Modem cable).
|
||||||
|
Packet sending and reception semantics for simulated network device support using either TCP or UDP transport.
|
||||||
|
|
||||||
#### Asynchronous I/O
|
#### Asynchronous I/O
|
||||||
* Disk and Tape I/O can be asynchronous. Asynchronous support exists
|
* Disk and Tape I/O can be asynchronous. Asynchronous support exists
|
||||||
|
|
69
sim_sock.c
69
sim_sock.c
|
@ -69,6 +69,8 @@
|
||||||
/* OS dependent routines
|
/* OS dependent routines
|
||||||
|
|
||||||
sim_master_sock create master socket
|
sim_master_sock create master socket
|
||||||
|
sim_connect_sock connect a socket to a remote destination
|
||||||
|
sim_connect_sock_ex connect a socket to a remote destination
|
||||||
sim_accept_conn accept connection
|
sim_accept_conn accept connection
|
||||||
sim_read_sock read from socket
|
sim_read_sock read from socket
|
||||||
sim_write_sock write from socket
|
sim_write_sock write from socket
|
||||||
|
@ -99,6 +101,11 @@ SOCKET sim_connect_sock (const char *hostport, const char *default_host, const c
|
||||||
return INVALID_SOCKET;
|
return INVALID_SOCKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SOCKET sim_connect_sock_ex (const char *sourcehostport, const char *hostport, const char *default_host, const char *default_port, t_bool datagram)
|
||||||
|
{
|
||||||
|
return INVALID_SOCKET;
|
||||||
|
}
|
||||||
|
|
||||||
SOCKET sim_accept_conn (SOCKET master, char **connectaddr);
|
SOCKET sim_accept_conn (SOCKET master, char **connectaddr);
|
||||||
{
|
{
|
||||||
return INVALID_SOCKET;
|
return INVALID_SOCKET;
|
||||||
|
@ -710,12 +717,12 @@ return 0;
|
||||||
|
|
||||||
#endif /* endif !Win32 && !VMS */
|
#endif /* endif !Win32 && !VMS */
|
||||||
|
|
||||||
static SOCKET sim_create_sock (int af)
|
static SOCKET sim_create_sock_ex (int af, t_bool datagram)
|
||||||
{
|
{
|
||||||
SOCKET newsock;
|
SOCKET newsock;
|
||||||
int32 err;
|
int32 err;
|
||||||
|
|
||||||
newsock = socket (af, SOCK_STREAM, 0); /* create socket */
|
newsock = socket (af, (datagram ? SOCK_DGRAM : SOCK_STREAM), 0);/* create socket */
|
||||||
if (newsock == INVALID_SOCKET) { /* socket error? */
|
if (newsock == INVALID_SOCKET) { /* socket error? */
|
||||||
err = WSAGetLastError ();
|
err = WSAGetLastError ();
|
||||||
#if defined(WSAEAFNOSUPPORT)
|
#if defined(WSAEAFNOSUPPORT)
|
||||||
|
@ -727,6 +734,11 @@ if (newsock == INVALID_SOCKET) { /* socket error? */
|
||||||
return newsock;
|
return newsock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static SOCKET sim_create_sock (int af)
|
||||||
|
{
|
||||||
|
return sim_create_sock_ex (af, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Some platforms and/or network stacks have varying support for listening on
|
Some platforms and/or network stacks have varying support for listening on
|
||||||
an IPv6 socket and receiving connections from both IPv4 and IPv6 client
|
an IPv6 socket and receiving connections from both IPv4 and IPv6 client
|
||||||
|
@ -823,28 +835,71 @@ return newsock; /* got it! */
|
||||||
|
|
||||||
SOCKET sim_connect_sock (const char *hostport, const char *default_host, const char *default_port)
|
SOCKET sim_connect_sock (const char *hostport, const char *default_host, const char *default_port)
|
||||||
{
|
{
|
||||||
|
return sim_connect_sock_ex (NULL, hostport, default_host, default_port, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
SOCKET sim_connect_sock_ex (const char *sourcehostport, const char *hostport, const char *default_host, const char *default_port, t_bool datagram)
|
||||||
|
{
|
||||||
SOCKET newsock = INVALID_SOCKET;
|
SOCKET newsock = INVALID_SOCKET;
|
||||||
int32 sta;
|
int32 sta;
|
||||||
char host[CBUFSIZE], port[CBUFSIZE];
|
char host[CBUFSIZE], port[CBUFSIZE];
|
||||||
t_stat r;
|
t_stat r;
|
||||||
struct addrinfo hints;
|
struct addrinfo hints;
|
||||||
struct addrinfo *result = NULL;
|
struct addrinfo *result = NULL, *source = NULL;
|
||||||
|
|
||||||
r = sim_parse_addr (hostport, host, sizeof(host), default_host, port, sizeof(port), default_port, NULL);
|
r = sim_parse_addr (hostport, host, sizeof(host), default_host, port, sizeof(port), default_port, NULL);
|
||||||
if (r != SCPE_OK)
|
if (r != SCPE_OK)
|
||||||
return newsock;
|
return INVALID_SOCKET;
|
||||||
|
|
||||||
memset(&hints, 0, sizeof(hints));
|
memset(&hints, 0, sizeof(hints));
|
||||||
hints.ai_family = AF_UNSPEC;
|
hints.ai_family = AF_UNSPEC;
|
||||||
hints.ai_protocol = IPPROTO_TCP;
|
hints.ai_protocol = (datagram ? IPPROTO_UDP : IPPROTO_TCP);
|
||||||
hints.ai_socktype = SOCK_STREAM;
|
hints.ai_socktype = (datagram ? SOCK_DGRAM : SOCK_STREAM);
|
||||||
if (p_getaddrinfo(host[0] ? host : NULL, port[0] ? port : NULL, &hints, &result))
|
if (p_getaddrinfo(host[0] ? host : NULL, port[0] ? port : NULL, &hints, &result))
|
||||||
|
return INVALID_SOCKET;
|
||||||
|
|
||||||
|
if (sourcehostport) {
|
||||||
|
|
||||||
|
/* Validate the local/source side address which we'll bind to */
|
||||||
|
r = sim_parse_addr (sourcehostport, host, sizeof(host), NULL, port, sizeof(port), NULL, NULL);
|
||||||
|
if (r != SCPE_OK) {
|
||||||
|
p_freeaddrinfo (result);
|
||||||
|
return INVALID_SOCKET;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&hints, 0, sizeof(hints));
|
||||||
|
hints.ai_flags = AI_PASSIVE;
|
||||||
|
hints.ai_family = result->ai_family; /* Same family as connect destination */
|
||||||
|
hints.ai_protocol = (datagram ? IPPROTO_UDP : IPPROTO_TCP);
|
||||||
|
hints.ai_socktype = (datagram ? SOCK_DGRAM : SOCK_STREAM);
|
||||||
|
if (p_getaddrinfo(host[0] ? host : NULL, port[0] ? port : NULL, &hints, &source)) {
|
||||||
|
p_freeaddrinfo (result);
|
||||||
|
return INVALID_SOCKET;
|
||||||
|
}
|
||||||
|
|
||||||
|
newsock = sim_create_sock_ex (result->ai_family, datagram);/* create socket */
|
||||||
|
if (newsock == INVALID_SOCKET) { /* socket error? */
|
||||||
|
p_freeaddrinfo (result);
|
||||||
|
p_freeaddrinfo (source);
|
||||||
return newsock;
|
return newsock;
|
||||||
newsock = sim_create_sock (result->ai_family); /* create socket */
|
}
|
||||||
|
|
||||||
|
sta = bind (newsock, source->ai_addr, source->ai_addrlen);
|
||||||
|
p_freeaddrinfo(source);
|
||||||
|
source = NULL;
|
||||||
|
if (sta == SOCKET_ERROR) { /* bind error? */
|
||||||
|
p_freeaddrinfo (result);
|
||||||
|
return sim_err_sock (newsock, "bind", 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (newsock == INVALID_SOCKET) { /* socket error? */
|
if (newsock == INVALID_SOCKET) { /* socket error? */
|
||||||
|
newsock = sim_create_sock_ex (result->ai_family, datagram);/* create socket */
|
||||||
|
if (newsock == INVALID_SOCKET) { /* socket error? */
|
||||||
p_freeaddrinfo (result);
|
p_freeaddrinfo (result);
|
||||||
return newsock;
|
return newsock;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sta = sim_setnonblock (newsock); /* set nonblocking */
|
sta = sim_setnonblock (newsock); /* set nonblocking */
|
||||||
if (sta == SOCKET_ERROR) { /* fcntl error? */
|
if (sta == SOCKET_ERROR) { /* fcntl error? */
|
||||||
|
|
|
@ -104,6 +104,7 @@
|
||||||
t_stat sim_parse_addr (const char *cptr, char *host, size_t hostlen, const char *default_host, char *port, size_t port_len, const char *default_port, const char *validate_addr);
|
t_stat sim_parse_addr (const char *cptr, char *host, size_t hostlen, const char *default_host, char *port, size_t port_len, const char *default_port, const char *validate_addr);
|
||||||
SOCKET sim_master_sock (const char *hostport, t_stat *parse_status);
|
SOCKET sim_master_sock (const char *hostport, t_stat *parse_status);
|
||||||
SOCKET sim_connect_sock (const char *hostport, const char *default_host, const char *default_port);
|
SOCKET sim_connect_sock (const char *hostport, const char *default_host, const char *default_port);
|
||||||
|
SOCKET sim_connect_sock_ex (const char *sourcehostport, const char *hostport, const char *default_host, const char *default_port, t_bool datagram);
|
||||||
SOCKET sim_accept_conn (SOCKET master, char **connectaddr);
|
SOCKET sim_accept_conn (SOCKET master, char **connectaddr);
|
||||||
int32 sim_check_conn (SOCKET sock, t_bool rd);
|
int32 sim_check_conn (SOCKET sock, t_bool rd);
|
||||||
int32 sim_read_sock (SOCKET sock, char *buf, int32 nbytes);
|
int32 sim_read_sock (SOCKET sock, char *buf, int32 nbytes);
|
||||||
|
|
75
sim_tmxr.c
75
sim_tmxr.c
|
@ -862,6 +862,10 @@ if (lp->destination || lp->port || lp->txlogname) {
|
||||||
sprintf (growstring(&tptr, 32), ",Buffered=%d", lp->txbsz);
|
sprintf (growstring(&tptr, 32), ",Buffered=%d", lp->txbsz);
|
||||||
if (!lp->txbfd && (lp->mp->buffered > 0))
|
if (!lp->txbfd && (lp->mp->buffered > 0))
|
||||||
sprintf (growstring(&tptr, 32), ",UnBuffered");
|
sprintf (growstring(&tptr, 32), ",UnBuffered");
|
||||||
|
if (lp->mp->datagram != lp->datagram)
|
||||||
|
sprintf (growstring(&tptr, 8), ",%s", lp->datagram ? "UDP" : "TCP");
|
||||||
|
if (lp->port)
|
||||||
|
sprintf (growstring(&tptr, 12 + strlen (lp->port)), ",%s%s", lp->port, ((lp->mp->notelnet != lp->notelnet) && (!lp->datagram)) ? (lp->notelnet ? ";notelnet" : ";telnet") : "");
|
||||||
if (lp->destination) {
|
if (lp->destination) {
|
||||||
if (lp->serport) {
|
if (lp->serport) {
|
||||||
char portname[CBUFSIZE];
|
char portname[CBUFSIZE];
|
||||||
|
@ -870,10 +874,8 @@ if (lp->destination || lp->port || lp->txlogname) {
|
||||||
sprintf (growstring(&tptr, 25 + strlen (lp->destination)), ",Connect=%s%s%s", portname, strcmp("9600-8N1", lp->serconfig) ? ";" : "", strcmp("9600-8N1", lp->serconfig) ? lp->serconfig : "");
|
sprintf (growstring(&tptr, 25 + strlen (lp->destination)), ",Connect=%s%s%s", portname, strcmp("9600-8N1", lp->serconfig) ? ";" : "", strcmp("9600-8N1", lp->serconfig) ? lp->serconfig : "");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
sprintf (growstring(&tptr, 25 + strlen (lp->destination)), ",Connect=%s%s", lp->destination, (lp->mp->notelnet != lp->notelnet) ? (lp->notelnet ? ";notelnet" : ";telnet") : "");
|
sprintf (growstring(&tptr, 25 + strlen (lp->destination)), ",Connect=%s%s", lp->destination, ((lp->mp->notelnet != lp->notelnet) && (!lp->datagram)) ? (lp->notelnet ? ";notelnet" : ";telnet") : "");
|
||||||
}
|
}
|
||||||
if (lp->port)
|
|
||||||
sprintf (growstring(&tptr, 12 + strlen (lp->port)), ",%s%s", lp->port, (lp->mp->notelnet != lp->notelnet) ? (lp->notelnet ? ";notelnet" : ";telnet") : "");
|
|
||||||
if (lp->txlogname)
|
if (lp->txlogname)
|
||||||
sprintf (growstring(&tptr, 12 + strlen (lp->txlogname)), ",Log=%s", lp->txlogname);
|
sprintf (growstring(&tptr, 12 + strlen (lp->txlogname)), ",Log=%s", lp->txlogname);
|
||||||
if (lp->loopback)
|
if (lp->loopback)
|
||||||
|
@ -1136,7 +1138,7 @@ for (i = 0; i < mp->lines; i++) { /* check each line in se
|
||||||
(!lp->modem_control || (lp->modembits & TMXR_MDM_DTR))) {
|
(!lp->modem_control || (lp->modembits & TMXR_MDM_DTR))) {
|
||||||
sprintf (msg, "tmxr_poll_conn() - establishing outgoing connection to: %s", lp->destination);
|
sprintf (msg, "tmxr_poll_conn() - establishing outgoing connection to: %s", lp->destination);
|
||||||
tmxr_debug_connect_line (lp, msg);
|
tmxr_debug_connect_line (lp, msg);
|
||||||
lp->connecting = sim_connect_sock (lp->destination, "localhost", NULL);
|
lp->connecting = sim_connect_sock_ex (lp->datagram ? lp->port : NULL, lp->destination, "localhost", NULL, lp->datagram);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1204,7 +1206,7 @@ if ((lp->destination) && (!lp->serport)) {
|
||||||
if ((!lp->modem_control) || (lp->modembits & TMXR_MDM_DTR)) {
|
if ((!lp->modem_control) || (lp->modembits & TMXR_MDM_DTR)) {
|
||||||
sprintf (msg, "tmxr_reset_ln_ex() - connecting to %s", lp->destination);
|
sprintf (msg, "tmxr_reset_ln_ex() - connecting to %s", lp->destination);
|
||||||
tmxr_debug_connect_line (lp, msg);
|
tmxr_debug_connect_line (lp, msg);
|
||||||
lp->connecting = sim_connect_sock (lp->destination, "localhost", NULL);
|
lp->connecting = sim_connect_sock_ex (lp->datagram ? lp->port : NULL, lp->destination, "localhost", NULL, lp->datagram);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tmxr_init_line (lp); /* initialize line state */
|
tmxr_init_line (lp); /* initialize line state */
|
||||||
|
@ -1382,7 +1384,7 @@ if (lp->mp && lp->modem_control) { /* This API ONLY works on mo
|
||||||
|
|
||||||
sprintf (msg, "tmxr_set_get_modem_bits() - establishing outgoing connection to: %s", lp->destination);
|
sprintf (msg, "tmxr_set_get_modem_bits() - establishing outgoing connection to: %s", lp->destination);
|
||||||
tmxr_debug_connect_line (lp, msg);
|
tmxr_debug_connect_line (lp, msg);
|
||||||
lp->connecting = sim_connect_sock (lp->destination, "localhost", NULL);
|
lp->connecting = sim_connect_sock_ex (lp->datagram ? lp->port : NULL, lp->destination, "localhost", NULL, lp->datagram);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1900,6 +1902,8 @@ if (nbytes) { /* >0? write */
|
||||||
lp->txbpr = 0;
|
lp->txbpr = 0;
|
||||||
lp->txcnt = lp->txcnt + sbytes; /* update counts */
|
lp->txcnt = lp->txcnt + sbytes; /* update counts */
|
||||||
nbytes = nbytes - sbytes;
|
nbytes = nbytes - sbytes;
|
||||||
|
if ((nbytes == 0) && (lp->datagram)) /* if Empty buffer on datagram line */
|
||||||
|
lp->txbpi = lp->txbpr = 0; /* Start next packet at beginning of buffer */
|
||||||
}
|
}
|
||||||
if (sbytes < 0) { /* I/O Error? */
|
if (sbytes < 0) { /* I/O Error? */
|
||||||
lp->txbpi = lp->txbpr = 0; /* Drop the data we already know we can't send */
|
lp->txbpi = lp->txbpr = 0; /* Drop the data we already know we can't send */
|
||||||
|
@ -2012,7 +2016,7 @@ char tbuf[CBUFSIZE], listen[CBUFSIZE], destination[CBUFSIZE],
|
||||||
SOCKET sock;
|
SOCKET sock;
|
||||||
SERHANDLE serport;
|
SERHANDLE serport;
|
||||||
char *tptr = cptr;
|
char *tptr = cptr;
|
||||||
t_bool nolog, notelnet, listennotelnet, unbuffered, modem_control, loopback;
|
t_bool nolog, notelnet, listennotelnet, unbuffered, modem_control, loopback, datagram;
|
||||||
TMLN *lp;
|
TMLN *lp;
|
||||||
t_stat r = SCPE_ARG;
|
t_stat r = SCPE_ARG;
|
||||||
|
|
||||||
|
@ -2031,6 +2035,7 @@ while (*tptr) {
|
||||||
memset(port, '\0', sizeof(port));
|
memset(port, '\0', sizeof(port));
|
||||||
memset(option, '\0', sizeof(option));
|
memset(option, '\0', sizeof(option));
|
||||||
nolog = notelnet = listennotelnet = unbuffered = loopback = FALSE;
|
nolog = notelnet = listennotelnet = unbuffered = loopback = FALSE;
|
||||||
|
datagram = mp->datagram;
|
||||||
if (line != -1)
|
if (line != -1)
|
||||||
notelnet = listennotelnet = mp->notelnet;
|
notelnet = listennotelnet = mp->notelnet;
|
||||||
modem_control = mp->modem_control;
|
modem_control = mp->modem_control;
|
||||||
|
@ -2100,6 +2105,18 @@ while (*tptr) {
|
||||||
modem_control = TRUE;
|
modem_control = TRUE;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if ((0 == MATCH_CMD (gbuf, "DATAGRAM")) || (0 == MATCH_CMD (gbuf, "UDP"))) {
|
||||||
|
if ((NULL != cptr) && ('\0' != *cptr))
|
||||||
|
return SCPE_2MARG;
|
||||||
|
notelnet = datagram = TRUE;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ((0 == MATCH_CMD (gbuf, "STREAM")) || (0 == MATCH_CMD (gbuf, "TCP"))) {
|
||||||
|
if ((NULL != cptr) && ('\0' != *cptr))
|
||||||
|
return SCPE_2MARG;
|
||||||
|
datagram = FALSE;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (0 == MATCH_CMD (gbuf, "CONNECT")) {
|
if (0 == MATCH_CMD (gbuf, "CONNECT")) {
|
||||||
if ((NULL == cptr) || ('\0' == *cptr))
|
if ((NULL == cptr) || ('\0' == *cptr))
|
||||||
return SCPE_ARG;
|
return SCPE_ARG;
|
||||||
|
@ -2114,21 +2131,24 @@ while (*tptr) {
|
||||||
strncpy (hostport, cptr, sizeof(hostport)-1);
|
strncpy (hostport, cptr, sizeof(hostport)-1);
|
||||||
if ((cptr = strchr (hostport, ';')))
|
if ((cptr = strchr (hostport, ';')))
|
||||||
*(cptr++) = '\0';
|
*(cptr++) = '\0';
|
||||||
sock = sim_connect_sock (hostport, "localhost", NULL);
|
|
||||||
if (sock != INVALID_SOCKET)
|
|
||||||
sim_close_sock (sock, 0);
|
|
||||||
else
|
|
||||||
return SCPE_ARG;
|
|
||||||
if (cptr) {
|
if (cptr) {
|
||||||
get_glyph (cptr, cptr, 0); /* upcase this string */
|
get_glyph (cptr, cptr, 0); /* upcase this string */
|
||||||
if (0 == MATCH_CMD (cptr, "NOTELNET"))
|
if (0 == MATCH_CMD (cptr, "NOTELNET"))
|
||||||
notelnet = TRUE;
|
notelnet = TRUE;
|
||||||
else
|
else
|
||||||
if (0 == MATCH_CMD (cptr, "TELNET"))
|
if (0 == MATCH_CMD (cptr, "TELNET"))
|
||||||
|
if (datagram)
|
||||||
|
return SCPE_ARG;
|
||||||
|
else
|
||||||
notelnet = FALSE;
|
notelnet = FALSE;
|
||||||
else
|
else
|
||||||
return SCPE_ARG;
|
return SCPE_ARG;
|
||||||
}
|
}
|
||||||
|
sock = sim_connect_sock_ex (NULL, hostport, "localhost", NULL, datagram);
|
||||||
|
if (sock != INVALID_SOCKET)
|
||||||
|
sim_close_sock (sock, 0);
|
||||||
|
else
|
||||||
|
return SCPE_ARG;
|
||||||
cptr = hostport;
|
cptr = hostport;
|
||||||
}
|
}
|
||||||
strcpy(destination, cptr);
|
strcpy(destination, cptr);
|
||||||
|
@ -2231,7 +2251,7 @@ while (*tptr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (listen[0]) {
|
if ((listen[0]) && (!datagram)) {
|
||||||
sock = sim_master_sock (listen, &r); /* make master socket */
|
sock = sim_master_sock (listen, &r); /* make master socket */
|
||||||
if (r != SCPE_OK)
|
if (r != SCPE_OK)
|
||||||
return r;
|
return r;
|
||||||
|
@ -2306,7 +2326,16 @@ while (*tptr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
sock = sim_connect_sock (destination, "localhost", NULL);
|
lp->datagram = datagram;
|
||||||
|
if (datagram) {
|
||||||
|
if (listen[0]) {
|
||||||
|
lp->port = (char *)realloc (lp->port, 1 + strlen (listen));
|
||||||
|
strcpy(lp->port, listen); /* save port */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return SCPE_ARG;
|
||||||
|
}
|
||||||
|
sock = sim_connect_sock_ex (datagram ? listen : NULL, destination, "localhost", NULL, datagram);
|
||||||
if (sock != INVALID_SOCKET) {
|
if (sock != INVALID_SOCKET) {
|
||||||
_mux_detach_line (lp, FALSE, TRUE);
|
_mux_detach_line (lp, FALSE, TRUE);
|
||||||
lp->destination = (char *)malloc(1+strlen(destination));
|
lp->destination = (char *)malloc(1+strlen(destination));
|
||||||
|
@ -2370,7 +2399,7 @@ while (*tptr) {
|
||||||
lp->txlog = NULL;
|
lp->txlog = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (listen[0]) {
|
if ((listen[0]) && (!datagram)) {
|
||||||
if ((mp->lines == 1) && (mp->master)) /* single line mux can have either line specific OR mux listener but NOT both */
|
if ((mp->lines == 1) && (mp->master)) /* single line mux can have either line specific OR mux listener but NOT both */
|
||||||
return SCPE_ARG;
|
return SCPE_ARG;
|
||||||
sock = sim_master_sock (listen, &r); /* make master socket */
|
sock = sim_master_sock (listen, &r); /* make master socket */
|
||||||
|
@ -2409,7 +2438,16 @@ while (*tptr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
sock = sim_connect_sock (destination, "localhost", NULL);
|
lp->datagram = datagram;
|
||||||
|
if (datagram) {
|
||||||
|
if (listen[0]) {
|
||||||
|
lp->port = (char *)realloc (lp->port, 1 + strlen (listen));
|
||||||
|
strcpy(lp->port, listen); /* save port */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return SCPE_ARG;
|
||||||
|
}
|
||||||
|
sock = sim_connect_sock_ex (datagram ? listen : NULL, destination, "localhost", NULL, datagram);
|
||||||
if (sock != INVALID_SOCKET) {
|
if (sock != INVALID_SOCKET) {
|
||||||
_mux_detach_line (lp, FALSE, TRUE);
|
_mux_detach_line (lp, FALSE, TRUE);
|
||||||
lp->destination = (char *)malloc(1+strlen(destination));
|
lp->destination = (char *)malloc(1+strlen(destination));
|
||||||
|
@ -3673,6 +3711,9 @@ if (ln >= 0)
|
||||||
|
|
||||||
if ((lp->sock) || (lp->connecting)) { /* tcp connection? */
|
if ((lp->sock) || (lp->connecting)) { /* tcp connection? */
|
||||||
if (lp->destination) /* remote connection? */
|
if (lp->destination) /* remote connection? */
|
||||||
|
if (lp->datagram)
|
||||||
|
fprintf (st, "Datagram Connection from %s to remote port %s\n", lp->port, lp->destination);/* print port name */
|
||||||
|
else
|
||||||
fprintf (st, "Connection to remote port %s\n", lp->destination);/* print port name */
|
fprintf (st, "Connection to remote port %s\n", lp->destination);/* print port name */
|
||||||
else /* incoming connection */
|
else /* incoming connection */
|
||||||
fprintf (st, "Connection from IP address %s\n", lp->ipad);
|
fprintf (st, "Connection from IP address %s\n", lp->ipad);
|
||||||
|
@ -3689,7 +3730,7 @@ if (lp->sock) {
|
||||||
free (peername);
|
free (peername);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lp->port)
|
if ((lp->port) && (!lp->datagram))
|
||||||
fprintf (st, "Listening on port %s\n", lp->port); /* print port name */
|
fprintf (st, "Listening on port %s\n", lp->port); /* print port name */
|
||||||
|
|
||||||
if (lp->serport) /* serial connection? */
|
if (lp->serport) /* serial connection? */
|
||||||
|
|
|
@ -114,7 +114,7 @@ struct tmln {
|
||||||
int32 tsta; /* Telnet state */
|
int32 tsta; /* Telnet state */
|
||||||
int32 rcve; /* rcv enable */
|
int32 rcve; /* rcv enable */
|
||||||
int32 xmte; /* xmt enable */
|
int32 xmte; /* xmt enable */
|
||||||
int32 dstb; /* disable Tlnt bin */
|
int32 dstb; /* disable Telnet binary mode */
|
||||||
t_bool notelnet; /* raw binary data (no telnet interpretation) */
|
t_bool notelnet; /* raw binary data (no telnet interpretation) */
|
||||||
int32 rxbpr; /* rcv buf remove */
|
int32 rxbpr; /* rcv buf remove */
|
||||||
int32 rxbpi; /* rcv buf insert */
|
int32 rxbpi; /* rcv buf insert */
|
||||||
|
@ -151,6 +151,7 @@ struct tmln {
|
||||||
char *destination; /* Outgoing destination address:port */
|
char *destination; /* Outgoing destination address:port */
|
||||||
t_bool loopback; /* Line in loopback mode */
|
t_bool loopback; /* Line in loopback mode */
|
||||||
t_bool halfduplex; /* Line in half-duplex mode */
|
t_bool halfduplex; /* Line in half-duplex mode */
|
||||||
|
t_bool datagram; /* Line is datagram packet oriented */
|
||||||
int32 lpbpr; /* loopback buf remove */
|
int32 lpbpr; /* loopback buf remove */
|
||||||
int32 lpbpi; /* loopback buf insert */
|
int32 lpbpi; /* loopback buf insert */
|
||||||
int32 lpbcnt; /* loopback buf used count */
|
int32 lpbcnt; /* loopback buf used count */
|
||||||
|
@ -176,6 +177,7 @@ struct tmxr {
|
||||||
uint32 last_poll_time; /* time of last connection poll */
|
uint32 last_poll_time; /* time of last connection poll */
|
||||||
t_bool notelnet; /* default telnet capability for incoming connections */
|
t_bool notelnet; /* default telnet capability for incoming connections */
|
||||||
t_bool modem_control; /* multiplexer supports modem control behaviors */
|
t_bool modem_control; /* multiplexer supports modem control behaviors */
|
||||||
|
t_bool datagram; /* Lines are datagram packet oriented */
|
||||||
};
|
};
|
||||||
|
|
||||||
int32 tmxr_poll_conn (TMXR *mp);
|
int32 tmxr_poll_conn (TMXR *mp);
|
||||||
|
|
Loading…
Add table
Reference in a new issue