7 #define NS(x) ((vlong)x)
8 #define US(x) (NS(x) * 1000LL)
9 #define MS(x) (US(x) * 1000LL)
10 #define S(x) (MS(x) * 1000LL)
18 Timer = 0, // Alt channels.
20 Maxto = 24 * 3600, // A full day to reconnect.
25 uchar nb[4]; // Number of data bytes in this message
26 uchar msg[4]; // Message number
27 uchar acked[4]; // Number of messages acked
35 static Channel *unsent;
36 static Channel *unacked;
37 static Channel *empty;
43 static char *dialstring;
44 static int maxto = Maxto;
45 static char *Logname = "aan";
47 static int reader = -1;
52 { nil, nil, CHANRCV }, // timer
53 { nil, nil, CHANRCV }, // unsent
54 { nil, nil, CHANEND },
57 static void fromnet(void*);
58 static void fromclient(void*);
59 static int reconnect(int);
60 static void synchronize(void);
61 static int sendcommand(ulong, ulong);
62 static void showmsg(int, char *, Buf *);
63 static int writen(int, uchar *, int);
64 static void dmessage(int, char *, ...);
65 static void timerproc(void *);
70 fprint(2, "Usage: %s [-cd] [-m maxto] dialstring|netdir\n", argv0);
76 catch(void *, char *s)
78 if (!strcmp(s, "alarm")) {
79 syslog(0, Logname, "Timed out while waiting for reconnect, exiting...");
94 sysfatal("Cannot allocate memory; pc=%lux", pc);
100 threadmain(int argc, char **argv)
116 maxto = (int)strtol(EARGF(usage()), nil, 0);
129 if ((p = strstr(devdir, "/local")) != nil)
133 dialstring = argv[0];
136 int fd = open("#c/cons", OWRITE|OCEXEC);
140 fmtinstall('F', fcallfmt);
145 * Set up initial connection. use short timeout
146 * of 60 seconds so we wont hang arround for too
147 * long if there is some general connection problem
150 netfd = reconnect(60);
152 unsent = chancreate(sizeof(Buf *), Nbuf);
153 unacked = chancreate(sizeof(Buf *), Nbuf);
154 empty = chancreate(sizeof(Buf *), Nbuf);
155 timer = chancreate(sizeof(uchar *), 1);
156 if(unsent == nil || unacked == nil || empty == nil || timer == nil)
157 sysfatal("Cannot allocate channels");
159 for (i = 0; i < Nbuf; i++)
160 sendp(empty, emalloc(sizeof(Buf)));
162 reader = proccreate(fromnet, nil, Stacksize);
164 sysfatal("Cannot start fromnet; %r");
166 if (proccreate(fromclient, nil, Stacksize) < 0)
167 sysfatal("Cannot start fromclient; %r");
169 if (proccreate(timerproc, timer, Stacksize) < 0)
170 sysfatal("Cannot start timerproc; %r");
173 a[Unsent].c = unsent;
177 synctime = nsec() + Synctime;
181 if (netfd < 0 || failed) {
182 // Wait for the netreader to die.
184 dmessage(1, "main; waiting for netreader to die\n");
189 // the reader died; reestablish the world.
190 netfd = reconnect(maxto);
197 if (netfd < 0 || nsec() < synctime)
201 PBIT32(hdr.acked, inmsg);
204 if (writen(netfd, (uchar *)&hdr, Hdrsz) < 0) {
205 dmessage(2, "main; writen failed; %r\n");
211 syslog(0, Logname, "connection seems hung up...");
215 synctime = nsec() + Synctime;
224 PBIT32(b->hdr.acked, inmsg);
226 if (writen(netfd, (uchar *)&b->hdr, Hdrsz) < 0) {
227 dmessage(2, "main; writen failed; %r\n");
231 n = GBIT32(b->hdr.nb);
232 if (writen(netfd, b->buf, n) < 0) {
233 dmessage(2, "main; writen failed; %r\n");
242 syslog(0, Logname, "exiting...");
254 threadsetname("fromclient");
258 n = read(0, b->buf, Bufsize);
261 dmessage(2, "fromclient; Cannot read 9P message; %r\n");
263 dmessage(2, "fromclient; Client terminated\n");
266 PBIT32(b->hdr.nb, n);
267 PBIT32(b->hdr.msg, outmsg);
268 showmsg(1, "fromclient", b);
277 extern void _threadnote(void *, char *);
278 static int lastacked;
279 int n, m, len, acked;
284 threadsetname("fromnet");
286 b = emalloc(sizeof(Buf));
291 dmessage(1, "fromnet; waiting for connection... (inmsg %d)\n", inmsg);
296 len = readn(netfd, (uchar *)&b->hdr, Hdrsz);
299 dmessage(1, "fromnet; (hdr) network failure; %r\n");
301 dmessage(1, "fromnet; (hdr) network closed\n");
306 lostsync = 0; // reset timeout
307 n = GBIT32(b->hdr.nb);
308 m = GBIT32(b->hdr.msg);
309 acked = GBIT32(b->hdr.acked);
310 dmessage(2, "fromnet: Got message, size %d, nb %d, msg %d, acked %d, lastacked %d\n",
311 len, n, m, acked, lastacked);
315 dmessage(1, "fromnet; network closed\n");
322 dmessage(1, "fromnet; message too big %d > %d\n", n, Bufsize);
326 len = readn(netfd, b->buf, n);
327 if (len <= 0 || len != n) {
329 dmessage(1, "fromnet; network closed\n");
331 dmessage(1, "fromnet; network failure; %r\n");
338 dmessage(1, "fromnet; skipping message %d, currently at %d\n", m, inmsg);
342 // Process the acked list.
343 while(lastacked != acked) {
347 m = GBIT32(rb->hdr.msg);
348 if (m != lastacked) {
349 dmessage(1, "fromnet; rb %p, msg %d, lastacked %d\n", rb, m, lastacked);
350 sysfatal("fromnet; bug");
352 PBIT32(rb->hdr.msg, -1);
358 showmsg(1, "fromnet", b);
360 if (writen(1, b->buf, len) < 0)
361 sysfatal("fromnet; cannot write to client; %r");
374 syslog(0, Logname, "dialing %s", dialstring);
376 while ((fd = dial(dialstring, nil, ldir, nil)) < 0) {
380 errstr(err, sizeof err);
381 if (strstr(err, "connection refused")) {
382 dmessage(1, "reconnect; server died...\n");
383 threadexitsall("server died...");
385 dmessage(1, "reconnect: dialed %s; %s\n", dialstring, err);
389 syslog(0, Logname, "reconnected to %s", dialstring);
392 syslog(0, Logname, "waiting for connection on %s", devdir);
394 if ((lcfd = listen(devdir, ldir)) < 0)
395 sysfatal("reconnect; cannot listen; %r");
396 if ((fd = accept(lcfd, ldir)) < 0)
397 sysfatal("reconnect; cannot accept; %r");
402 if(nci = getnetconninfo(ldir, fd)){
403 syslog(0, Logname, "connected from %s", nci->rsys);
404 threadsetname(client? "client %s %s" : "server %s %s", ldir, nci->rsys);
405 freenetconninfo(nci);
407 syslog(0, Logname, "connected");
419 // Ignore network errors here. If we fail during
420 // synchronization, the next alarm will pick up
423 tmp = chancreate(sizeof(Buf *), Nbuf);
424 while ((b = nbrecvp(unacked)) != nil) {
425 n = GBIT32(b->hdr.nb);
426 writen(netfd, (uchar *)&b->hdr, Hdrsz);
427 writen(netfd, b->buf, n);
435 showmsg(int level, char *s, Buf *b)
440 dmessage(level, "%s; b == nil\n", s);
443 n = GBIT32(b->hdr.nb);
444 dmessage(level, "%s; (len %d) %X %X %X %X %X %X %X %X %X (%p)\n", s, n,
445 b->buf[0], b->buf[1], b->buf[2],
446 b->buf[3], b->buf[4], b->buf[5],
447 b->buf[6], b->buf[7], b->buf[8], b);
451 writen(int fd, uchar *buf, int nb)
461 if ((n = write(fd, buf, nb)) < 0) {
462 dmessage(1, "writen; Write failed; %r\n");
465 dmessage(2, "writen: wrote %d bytes\n", n);
478 threadsetname("timer");
481 sleep((Synctime / MS(1)) >> 1);
482 sendp(timer, "timer");
487 dmessage(int level, char *fmt, ...)
495 vfprint(2, fmt, arg);