15
15
#include "imp.h"
16
16
#include "wire.h"
17
17
18
+ #define RFNM_TIMEOUT 10
19
+ #define RRP_TIMEOUT 20
20
+ #define ERP_TIMEOUT 20
21
+
18
22
#define IMP_REGULAR 0
19
23
#define IMP_LEADER_ERROR 1
20
24
#define IMP_DOWN 2
@@ -71,6 +75,7 @@ static int fd;
71
75
static struct sockaddr_un server ;
72
76
static struct sockaddr_un client ;
73
77
static socklen_t len ;
78
+ static unsigned long time_unit ;
74
79
75
80
typedef struct
76
81
{
@@ -86,9 +91,11 @@ struct
86
91
int listen ;
87
92
struct { int link , size ; uint32_t lsock , rsock ; } rcv , snd ;
88
93
void (* rrp_callback ) (int );
89
- void (* rrp_timeout ) (int );
94
+ void (* rrp_timed_out ) (int );
95
+ unsigned long rrp_timeout ;
90
96
void (* rfnm_callback ) (int );
91
- void (* rfnm_timeout ) (int );
97
+ void (* rfnm_timed_out ) (int );
98
+ unsigned long rfnm_timeout ;
92
99
} connection [CONNECTIONS ];
93
100
94
101
struct
@@ -104,6 +111,7 @@ static struct
104
111
#define HOST_ALIVE 0001
105
112
106
113
client_t echo ;
114
+ unsigned long erp_timeout ;
107
115
int outstanding_rfnm ;
108
116
} hosts [256 ];
109
117
@@ -128,10 +136,12 @@ static const char *type_name[] =
128
136
static uint8_t packet [200 ];
129
137
static uint8_t app [200 ];
130
138
131
- static void when_rrp (int i , void (* cb ) (int ), void (* to ) (int ))
139
+ static void when_rrp (int i , void (* cb ) (int ),
140
+ unsigned timeout , void (* to ) (int ))
132
141
{
133
142
connection [i ].rrp_callback = cb ;
134
- connection [i ].rrp_timeout = to ;
143
+ connection [i ].rrp_timed_out = to ;
144
+ connection [i ].rrp_timeout = time_unit + timeout ;
135
145
}
136
146
137
147
static void check_rrp (int host )
@@ -141,18 +151,20 @@ static void check_rrp (int host)
141
151
for (i = 0 ; i < CONNECTIONS ; i ++ ) {
142
152
if (connection [i ].host != host )
143
153
continue ;
144
- if (connection [i ].rrp_callback == NULL )
145
- continue ;
146
154
cb = connection [i ].rrp_callback ;
155
+ if (cb == NULL )
156
+ continue ;
147
157
connection [i ].rrp_callback = NULL ;
148
158
cb (i );
149
159
}
150
160
}
151
161
152
- static void when_rfnm (int i , void (* cb ) (int ), void (* to ) (int ))
162
+ static void when_rfnm (int i , void (* cb ) (int ),
163
+ unsigned timeout , void (* to ) (int ))
153
164
{
154
165
connection [i ].rfnm_callback = cb ;
155
- connection [i ].rfnm_timeout = to ;
166
+ connection [i ].rfnm_timed_out = to ;
167
+ connection [i ].rfnm_timeout = time_unit + timeout ;
156
168
}
157
169
158
170
static void check_rfnm (int host )
@@ -312,6 +324,8 @@ static int make_open (int host,
312
324
connection [i ].snd .lsock = snd_lsock ;
313
325
connection [i ].snd .rsock = snd_rsock ;
314
326
connection [i ].flags = 0 ;
327
+ connection [i ].rrp_timeout = time_unit - 1 ;
328
+ connection [i ].rfnm_timeout = time_unit - 1 ;
315
329
316
330
return i ;
317
331
}
@@ -730,12 +744,13 @@ static int process_cls (uint8_t source, uint8_t *data)
730
744
731
745
static void just_drop (int i )
732
746
{
747
+ fprintf (stderr , "NCP: RFNM timeout, drop connection %d.\n" , i );
733
748
destroy (i );
734
749
}
735
750
736
751
static void cls_and_drop (int i )
737
752
{
738
- fprintf (stderr , "NCP: Timeout, drop connection %d.\n" , i );
753
+ fprintf (stderr , "NCP: RFNM timeout, close connection %d.\n" , i );
739
754
ncp_cls (connection [i ].host ,
740
755
connection [i ].snd .lsock , connection [i ].snd .rsock );
741
756
ncp_cls (connection [i ].host ,
@@ -764,7 +779,7 @@ static void send_str_and_rts (int i)
764
779
connection [i ].snd .rsock , connection [i ].snd .size );
765
780
connection [i ].flags |= CONN_SENT_STR ;
766
781
}
767
- when_rfnm (i , send_rts , cls_and_drop );
782
+ when_rfnm (i , send_rts , RFNM_TIMEOUT , cls_and_drop );
768
783
check_rfnm (connection [i ].host );
769
784
}
770
785
@@ -825,8 +840,8 @@ static int process_all (uint8_t source, uint8_t *data)
825
840
fprintf (stderr , "NCP: New connection %d.\n" , j );
826
841
connection [j ].snd .size = 8 ;
827
842
connection [j ].rcv .link = 44 ;
828
- when_rfnm (j , send_str_and_rts , cls_and_drop );
829
- when_rfnm (i , send_cls_snd , just_drop );
843
+ when_rfnm (j , send_str_and_rts , RFNM_TIMEOUT , cls_and_drop );
844
+ when_rfnm (i , send_cls_snd , RFNM_TIMEOUT , just_drop );
830
845
check_rfnm (source );
831
846
}
832
847
return 7 ;
@@ -1062,7 +1077,7 @@ static void process_regular (uint8_t *packet, int length)
1062
1077
if (connection [i ].flags & CONN_CLIENT ) {
1063
1078
uint32_t s = sock (& packet [9 ]);
1064
1079
fprintf (stderr , "NCP: ICP link %u socket %u.\n" , link , s );
1065
- when_rfnm (i , send_cls_rcv , just_drop );
1080
+ when_rfnm (i , send_cls_rcv , RFNM_TIMEOUT , just_drop );
1066
1081
connection [i ].snd .rsock = s ;
1067
1082
1068
1083
j = find_rcv_sockets (source , connection [i ].rcv .lsock + 2 , s + 1 );
@@ -1075,7 +1090,7 @@ static void process_regular (uint8_t *packet, int length)
1075
1090
connection [j ].snd .size = 8 ;
1076
1091
connection [j ].rcv .link = 45 ;
1077
1092
fprintf (stderr , "NCP: New connection %d.\n" , j );
1078
- when_rfnm (j , send_str_and_rts , cls_and_drop );
1093
+ when_rfnm (j , send_str_and_rts , RFNM_TIMEOUT , cls_and_drop );
1079
1094
}
1080
1095
connection [j ].listen = connection [i ].rcv .rsock ;
1081
1096
connection [j ].flags |= CONN_GOT_SOCKET ;
@@ -1269,6 +1284,7 @@ static void app_echo (void)
1269
1284
1270
1285
memcpy (& hosts [host ].echo .addr , & client , len );
1271
1286
hosts [host ].echo .len = len ;
1287
+ hosts [host ].erp_timeout = time_unit + ERP_TIMEOUT ;
1272
1288
ncp_eco (host , app [2 ]);
1273
1289
}
1274
1290
@@ -1281,6 +1297,7 @@ static void app_open_send_rts (int i)
1281
1297
1282
1298
static void app_open_fail (int i )
1283
1299
{
1300
+ fprintf (stderr , "NCP: Timed out waiting for RRP.\n" );
1284
1301
reply_open (connection [i ].host , connection [i ].rcv .rsock , 255 );
1285
1302
}
1286
1303
@@ -1305,7 +1322,7 @@ static void app_open (void)
1305
1322
// We haven't communicated with this host yet.
1306
1323
ncp_rst (host );
1307
1324
// Wait for RRP, then send RTS.
1308
- when_rrp (i , app_open_send_rts , app_open_fail );
1325
+ when_rrp (i , app_open_send_rts , RRP_TIMEOUT , app_open_fail );
1309
1326
} else {
1310
1327
// Ok to send RTS directly.
1311
1328
app_open_send_rts (i );
@@ -1417,6 +1434,35 @@ static void application (void)
1417
1434
}
1418
1435
}
1419
1436
1437
+ static void tick (void )
1438
+ {
1439
+ void (* to ) (int );
1440
+ int i ;
1441
+ time_unit ++ ;
1442
+ for (i = 0 ; i < CONNECTIONS ; i ++ ) {
1443
+ to = connection [i ].rrp_timed_out ;
1444
+ if (to != NULL && connection [i ].rrp_timeout == time_unit ) {
1445
+ connection [i ].rrp_timed_out = NULL ;
1446
+ connection [i ].rrp_timeout = time_unit - 1 ;
1447
+ to (i );
1448
+ }
1449
+ to = connection [i ].rfnm_timed_out ;
1450
+ if (to != NULL && connection [i ].rfnm_timeout == time_unit ) {
1451
+ connection [i ].rfnm_timed_out = NULL ;
1452
+ connection [i ].rrp_timeout = time_unit - 1 ;
1453
+ to (i );
1454
+ }
1455
+ }
1456
+ for (i = 0 ; i < 256 ; i ++ ) {
1457
+ if (hosts [i ].echo .len == 0 )
1458
+ continue ;
1459
+ if (hosts [i ].erp_timeout != time_unit )
1460
+ continue ;
1461
+ reply_echo (i , 0 , 0x20 );
1462
+ hosts [i ].echo .len = 0 ;
1463
+ }
1464
+ }
1465
+
1420
1466
static void cleanup (void )
1421
1467
{
1422
1468
unlink (server .sun_path );
@@ -1444,6 +1490,7 @@ void ncp_init (void)
1444
1490
signal (SIGQUIT , sigcleanup );
1445
1491
signal (SIGTERM , sigcleanup );
1446
1492
atexit (cleanup );
1493
+ time_unit = 0 ;
1447
1494
}
1448
1495
1449
1496
int main (int argc , char * * argv )
@@ -1456,13 +1503,20 @@ int main (int argc, char **argv)
1456
1503
for (;;) {
1457
1504
int n ;
1458
1505
fd_set rfds ;
1506
+ struct timeval tv ;
1459
1507
FD_ZERO (& rfds );
1460
1508
FD_SET (fd , & rfds );
1461
1509
imp_fd_set (& rfds );
1462
- n = select (33 , & rfds , NULL , NULL , NULL );
1510
+ tv .tv_sec = 1 ;
1511
+ tv .tv_usec = 0 ;
1512
+ n = select (33 , & rfds , NULL , NULL , & tv );
1463
1513
if (n == -1 )
1464
1514
fprintf (stderr , "NCP: select error.\n" );
1465
- else if (n > 0 ) {
1515
+ else if (n == 0 ) {
1516
+ tick ();
1517
+ tv .tv_sec = 1 ;
1518
+ tv .tv_usec = 0 ;
1519
+ } else {
1466
1520
if (imp_fd_isset (& rfds )) {
1467
1521
memset (packet , 0 , sizeof packet );
1468
1522
imp_receive_message (packet , & n );
0 commit comments