Added randomization to the checking for success of outgoing connections and the arrival of incoming connections

This commit is contained in:
Mark Pizzolato 2013-05-15 15:34:45 -07:00
parent 7edcf5f36e
commit e8e751c2fd

View file

@ -807,6 +807,7 @@ if (mp->last_poll_time == 0) { /* first poll initializa
if ((poll_time - mp->last_poll_time) < TMXR_CONNECT_POLL_INTERVAL) if ((poll_time - mp->last_poll_time) < TMXR_CONNECT_POLL_INTERVAL)
return -1; /* too soon to try */ return -1; /* too soon to try */
srand((unsigned int)poll_time);
tmxr_debug_trace (mp, "tmxr_poll_conn()"); tmxr_debug_trace (mp, "tmxr_poll_conn()");
mp->last_poll_time = poll_time; mp->last_poll_time = poll_time;
@ -862,95 +863,108 @@ if (mp->master) {
/* Look for per line listeners or outbound connecting sockets */ /* Look for per line listeners or outbound connecting sockets */
for (i = 0; i < mp->lines; i++) { /* check each line in sequence */ for (i = 0; i < mp->lines; i++) { /* check each line in sequence */
int j, r = rand();
lp = mp->ldsc + i; /* get pointer to line descriptor */ lp = mp->ldsc + i; /* get pointer to line descriptor */
if (lp->connecting) { /* connecting? */ /* If two simulators are configured with symmetric virtual null modem
char *sockname, *peername; cables pointing at each other, there may be a problem establishing
a connection if both systems happen to be checking for the success
of their connections in the exact same order. They can each observe
success in their respective outgoing connections, which haven't
actually been 'accept'ed on the peer end of the connection.
We address this issue by checking for the success of an outgoing
connection and the arrival of an incoming one in a random order.
*/
for (j=0; j<2; j++)
switch ((j+r)&1) {
case 0:
if (lp->connecting) { /* connecting? */
char *sockname, *peername;
switch (sim_check_conn(lp->connecting, FALSE)) switch (sim_check_conn(lp->connecting, FALSE))
{ {
case 1: /* successful connection */ case 1: /* successful connection */
lp->conn = TRUE; /* record connection */ lp->conn = TRUE; /* record connection */
lp->sock = lp->connecting; /* it now looks normal */ lp->sock = lp->connecting; /* it now looks normal */
lp->connecting = 0; lp->connecting = 0;
lp->ipad = realloc (lp->ipad, 1+strlen (lp->destination)); lp->ipad = realloc (lp->ipad, 1+strlen (lp->destination));
strcpy (lp->ipad, lp->destination); strcpy (lp->ipad, lp->destination);
lp->cnms = sim_os_msec (); lp->cnms = sim_os_msec ();
sim_getnames_sock (lp->sock, &sockname, &peername); sim_getnames_sock (lp->sock, &sockname, &peername);
sprintf (msg, "tmxr_poll_conn() - Outgoing Line Connection to %s (%s->%s) established", lp->destination, sockname, peername); sprintf (msg, "tmxr_poll_conn() - Outgoing Line Connection to %s (%s->%s) established", lp->destination, sockname, peername);
tmxr_debug_connect_line (lp, msg); tmxr_debug_connect_line (lp, msg);
free (sockname); free (sockname);
free (peername); free (peername);
break; break;
case -1: /* failed connection */ case -1: /* failed connection */
sprintf (msg, "tmxr_poll_conn() - Outgoing Line Connection to %s failed", lp->destination); sprintf (msg, "tmxr_poll_conn() - Outgoing Line Connection to %s failed", lp->destination);
tmxr_debug_connect_line (lp, msg); tmxr_debug_connect_line (lp, msg);
tmxr_reset_ln (lp); /* retry */ tmxr_reset_ln (lp); /* retry */
break; break;
}
}
/* Check for a pending Telnet/tcp connection */
if (lp->master) {
while (INVALID_SOCKET != (newsock = sim_accept_conn (lp->master, &address))) {/* got a live one? */
char *sockname, *peername;
sim_getnames_sock (newsock, &sockname, &peername);
sprintf (msg, "tmxr_poll_conn() - Incoming Line Connection from %s (%s->%s)", address, peername, sockname);
tmxr_debug_connect_line (lp, msg);
free (sockname);
free (peername);
++mp->sessions; /* count the new session */
if (lp->destination) { /* Virtual Null Modem Cable? */
char host[CBUFSIZE];
if (sim_parse_addr (lp->destination, host, sizeof(host), NULL, NULL, 0, NULL, address)) {
tmxr_msg (newsock, "Rejecting connection from unexpected source\r\n");
sprintf (msg, "tmxr_poll_conn() - Rejecting line connection from: %s, Expected: %s", address, host);
tmxr_debug_connect_line (lp, msg);
sim_close_sock (newsock, 0);
free (address);
continue; /* Try for another connection */
}
if (lp->connecting) {
sprintf (msg, "tmxr_poll_conn() - aborting outgoing line connection attempt to: %s", lp->destination);
tmxr_debug_connect_line (lp, msg);
sim_close_sock (lp->connecting, 0); /* abort our as yet unconnnected socket */
lp->connecting = 0;
}
}
if (lp->conn == FALSE) { /* is the line available? */
if ((!lp->modem_control) || (lp->modembits & TMXR_MDM_DTR)) {
tmxr_init_line (lp); /* init line */
lp->conn = TRUE; /* record connection */
lp->sock = newsock; /* save socket */
lp->ipad = address; /* ip address */
if (!lp->notelnet) {
sim_write_sock (newsock, (char *)mantra, sizeof(mantra));
tmxr_debug (TMXR_DBG_XMT, lp, "Sending", (char *)mantra, sizeof(mantra));
} }
tmxr_report_connection (mp, lp);
lp->cnms = sim_os_msec (); /* time of connection */
return i;
} }
else { break;
tmxr_msg (newsock, "Line connection not available\r\n"); case 1:
tmxr_debug_connect_line (lp, "tmxr_poll_conn() - Line connection not available"); if (lp->master) { /* Check for a pending Telnet/tcp connection */
sim_close_sock (newsock, 0); while (INVALID_SOCKET != (newsock = sim_accept_conn (lp->master, &address))) {/* got a live one? */
free (address); char *sockname, *peername;
sim_getnames_sock (newsock, &sockname, &peername);
sprintf (msg, "tmxr_poll_conn() - Incoming Line Connection from %s (%s->%s)", address, peername, sockname);
tmxr_debug_connect_line (lp, msg);
free (sockname);
free (peername);
++mp->sessions; /* count the new session */
if (lp->destination) { /* Virtual Null Modem Cable? */
char host[CBUFSIZE];
if (sim_parse_addr (lp->destination, host, sizeof(host), NULL, NULL, 0, NULL, address)) {
tmxr_msg (newsock, "Rejecting connection from unexpected source\r\n");
sprintf (msg, "tmxr_poll_conn() - Rejecting line connection from: %s, Expected: %s", address, host);
tmxr_debug_connect_line (lp, msg);
sim_close_sock (newsock, 0);
free (address);
continue; /* Try for another connection */
}
if (lp->connecting) {
sprintf (msg, "tmxr_poll_conn() - aborting outgoing line connection attempt to: %s", lp->destination);
tmxr_debug_connect_line (lp, msg);
sim_close_sock (lp->connecting, 0); /* abort our as yet unconnnected socket */
lp->connecting = 0;
}
}
if (lp->conn == FALSE) { /* is the line available? */
if ((!lp->modem_control) || (lp->modembits & TMXR_MDM_DTR)) {
tmxr_init_line (lp); /* init line */
lp->conn = TRUE; /* record connection */
lp->sock = newsock; /* save socket */
lp->ipad = address; /* ip address */
if (!lp->notelnet) {
sim_write_sock (newsock, (char *)mantra, sizeof(mantra));
tmxr_debug (TMXR_DBG_XMT, lp, "Sending", (char *)mantra, sizeof(mantra));
}
tmxr_report_connection (mp, lp);
lp->cnms = sim_os_msec (); /* time of connection */
return i;
}
else {
tmxr_msg (newsock, "Line connection not available\r\n");
tmxr_debug_connect_line (lp, "tmxr_poll_conn() - Line connection not available");
sim_close_sock (newsock, 0);
free (address);
}
}
else {
tmxr_msg (newsock, "Line connection busy\r\n");
tmxr_debug_connect_line (lp, "tmxr_poll_conn() - Line connection busy");
sim_close_sock (newsock, 0);
free (address);
}
}
} }
} break;
else {
tmxr_msg (newsock, "Line connection busy\r\n");
tmxr_debug_connect_line (lp, "tmxr_poll_conn() - Line connection busy");
sim_close_sock (newsock, 0);
free (address);
}
} }
}
/* Check for pending serial port connection notification */ /* Check for pending serial port connection notification */