13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
33e12c5d1SDavid du Colombier
43e12c5d1SDavid du Colombier enum {
53e12c5d1SDavid du Colombier Soh= 0x1,
63e12c5d1SDavid du Colombier Eot= 0x4,
73e12c5d1SDavid du Colombier Ack= 0x6,
83e12c5d1SDavid du Colombier Nak= 0x15,
93e12c5d1SDavid du Colombier Cancel= 0x18,
103e12c5d1SDavid du Colombier };
113e12c5d1SDavid du Colombier
123e12c5d1SDavid du Colombier int notifyf(void*, char*);
133e12c5d1SDavid du Colombier int readupto(uchar*, int);
143e12c5d1SDavid du Colombier int receive(int, uchar);
153e12c5d1SDavid du Colombier void send(int);
163e12c5d1SDavid du Colombier
173e12c5d1SDavid du Colombier int debug, dfd;
183e12c5d1SDavid du Colombier
193e12c5d1SDavid du Colombier void
main(int argc,char ** argv)203e12c5d1SDavid du Colombier main(int argc, char **argv)
213e12c5d1SDavid du Colombier {
223e12c5d1SDavid du Colombier int fd;
233e12c5d1SDavid du Colombier uchar seqno;
243e12c5d1SDavid du Colombier ulong bytes;
253e12c5d1SDavid du Colombier
263e12c5d1SDavid du Colombier ARGBEGIN {
273e12c5d1SDavid du Colombier case 'd':
283e12c5d1SDavid du Colombier dfd = 2;
293e12c5d1SDavid du Colombier debug = 1;
303e12c5d1SDavid du Colombier break;
313e12c5d1SDavid du Colombier } ARGEND
323e12c5d1SDavid du Colombier
333e12c5d1SDavid du Colombier if(argc != 1){
343e12c5d1SDavid du Colombier fprint(2, "usage: xmr filename\n");
353e12c5d1SDavid du Colombier exits("usage");
363e12c5d1SDavid du Colombier }
373e12c5d1SDavid du Colombier fd = open("/dev/consctl", OWRITE);
38*80ee5cbfSDavid du Colombier if(fd >= 0)
393e12c5d1SDavid du Colombier write(fd, "rawon", 5);
403e12c5d1SDavid du Colombier fd = create(argv[0], ORDWR, 0666);
413e12c5d1SDavid du Colombier if(fd < 0){
42219b2ee8SDavid du Colombier perror("xmr: create");
43219b2ee8SDavid du Colombier exits("create");
443e12c5d1SDavid du Colombier }
453e12c5d1SDavid du Colombier
463e12c5d1SDavid du Colombier atnotify(notifyf, 1);
473e12c5d1SDavid du Colombier send(Nak);
483e12c5d1SDavid du Colombier
493e12c5d1SDavid du Colombier /*
503e12c5d1SDavid du Colombier * keep receiving till the other side gives up
513e12c5d1SDavid du Colombier */
523e12c5d1SDavid du Colombier bytes = 0;
533e12c5d1SDavid du Colombier for(seqno = 1; ; seqno++){
543e12c5d1SDavid du Colombier if(receive(fd, seqno) == -1)
553e12c5d1SDavid du Colombier break;
563e12c5d1SDavid du Colombier bytes += 128;
573e12c5d1SDavid du Colombier }
587dd7cddfSDavid du Colombier fprint(2, "xmr: received %ld bytes\n", bytes);
593e12c5d1SDavid du Colombier exits(0);
603e12c5d1SDavid du Colombier }
613e12c5d1SDavid du Colombier
623e12c5d1SDavid du Colombier void
send(int byte)633e12c5d1SDavid du Colombier send(int byte)
643e12c5d1SDavid du Colombier {
653e12c5d1SDavid du Colombier uchar c;
663e12c5d1SDavid du Colombier
673e12c5d1SDavid du Colombier c = byte;
683e12c5d1SDavid du Colombier if(write(1, &c, 1) != 1){
693e12c5d1SDavid du Colombier fprint(2, "xmr: hungup\n");
703e12c5d1SDavid du Colombier exits("hangup");
713e12c5d1SDavid du Colombier }
723e12c5d1SDavid du Colombier }
733e12c5d1SDavid du Colombier
743e12c5d1SDavid du Colombier int
readupto(uchar * a,int len)753e12c5d1SDavid du Colombier readupto(uchar *a, int len)
763e12c5d1SDavid du Colombier {
773e12c5d1SDavid du Colombier int n;
783e12c5d1SDavid du Colombier int sofar;
793e12c5d1SDavid du Colombier
803e12c5d1SDavid du Colombier for(sofar = 0; sofar < len; sofar += n){
813e12c5d1SDavid du Colombier n = read(0, a, len-sofar);
823e12c5d1SDavid du Colombier if(n <= 0){
833e12c5d1SDavid du Colombier send(Nak);
843e12c5d1SDavid du Colombier return sofar;
853e12c5d1SDavid du Colombier }
863e12c5d1SDavid du Colombier if(*a == Eot || *a == Cancel)
873e12c5d1SDavid du Colombier return sofar + n;
883e12c5d1SDavid du Colombier a += n;
893e12c5d1SDavid du Colombier }
903e12c5d1SDavid du Colombier return sofar;
913e12c5d1SDavid du Colombier
923e12c5d1SDavid du Colombier }
933e12c5d1SDavid du Colombier
943e12c5d1SDavid du Colombier int
receive(int fd,uchar seqno)953e12c5d1SDavid du Colombier receive(int fd, uchar seqno)
963e12c5d1SDavid du Colombier {
973e12c5d1SDavid du Colombier uchar buf[128+4];
983e12c5d1SDavid du Colombier uchar sum;
993e12c5d1SDavid du Colombier uchar *p;
1003e12c5d1SDavid du Colombier int n;
1013e12c5d1SDavid du Colombier int tries;
1023e12c5d1SDavid du Colombier int have;
1033e12c5d1SDavid du Colombier
1043e12c5d1SDavid du Colombier for(have = 0, tries = 0;; tries++){
1053e12c5d1SDavid du Colombier if(debug)
1063e12c5d1SDavid du Colombier fprint(dfd, "have == %d\n", have);
1073e12c5d1SDavid du Colombier if(tries > 10){
1083e12c5d1SDavid du Colombier fprint(2, "xmr: timed out\n");
1093e12c5d1SDavid du Colombier if(debug)
1103e12c5d1SDavid du Colombier close(dfd);
1113e12c5d1SDavid du Colombier exits("timeout");
1123e12c5d1SDavid du Colombier }
1133e12c5d1SDavid du Colombier
1143e12c5d1SDavid du Colombier /* try to gather up a block */
1153e12c5d1SDavid du Colombier alarm(15*1000);
1163e12c5d1SDavid du Colombier n = readupto(&buf[have], 132-have);
1173e12c5d1SDavid du Colombier alarm(0);
1183e12c5d1SDavid du Colombier have += n;
1193e12c5d1SDavid du Colombier if(have){
1203e12c5d1SDavid du Colombier switch(buf[0]){
1213e12c5d1SDavid du Colombier case Eot:
1223e12c5d1SDavid du Colombier send(Ack);
1233e12c5d1SDavid du Colombier return -1;
1243e12c5d1SDavid du Colombier case Cancel:
1253e12c5d1SDavid du Colombier fprint(2, "xmr: transfer aborted by sender\n");
1263e12c5d1SDavid du Colombier exits("cancel");
1273e12c5d1SDavid du Colombier }
1283e12c5d1SDavid du Colombier }
1293e12c5d1SDavid du Colombier if(have != 132)
1303e12c5d1SDavid du Colombier continue;
1313e12c5d1SDavid du Colombier
1323e12c5d1SDavid du Colombier /* checksum */
1333e12c5d1SDavid du Colombier for(p = buf, sum = 0; p < &buf[128+3]; p++)
1343e12c5d1SDavid du Colombier sum += *p;
1353e12c5d1SDavid du Colombier
1363e12c5d1SDavid du Colombier /* If invalid block, resynchronize */
1373e12c5d1SDavid du Colombier if(buf[0] != Soh || buf[2] != (255-buf[1]) || sum != buf[131]){
1383e12c5d1SDavid du Colombier if(debug){
139*80ee5cbfSDavid du Colombier fprint(dfd, "resync %2.2ux %d %d %ux %ux\n", buf[0],
1403e12c5d1SDavid du Colombier buf[1], buf[2], sum, buf[131]);
14159cc4ca5SDavid du Colombier write(dfd, (char*)buf+3, 128);
14259cc4ca5SDavid du Colombier fprint(dfd, "\n");
1433e12c5d1SDavid du Colombier }
1443e12c5d1SDavid du Colombier p = memchr(buf+1, Soh, 131);
1453e12c5d1SDavid du Colombier if(p){
1463e12c5d1SDavid du Colombier have = 132-(p-buf);
1473e12c5d1SDavid du Colombier memmove(buf, p, have);
1483e12c5d1SDavid du Colombier } else
1493e12c5d1SDavid du Colombier have = 0;
1503e12c5d1SDavid du Colombier continue;
1513e12c5d1SDavid du Colombier }
1523e12c5d1SDavid du Colombier
1533e12c5d1SDavid du Colombier /* it's probably a real block, so dump it if there's an error */
1543e12c5d1SDavid du Colombier have = 0;
1553e12c5d1SDavid du Colombier
1563e12c5d1SDavid du Colombier /* if this is the last block, ack */
1573e12c5d1SDavid du Colombier if(buf[1] == seqno-1){
1583e12c5d1SDavid du Colombier tries = 0;
1593e12c5d1SDavid du Colombier send(Ack);
1603e12c5d1SDavid du Colombier }else if(buf[1] == seqno){
1613e12c5d1SDavid du Colombier if(debug)
1623e12c5d1SDavid du Colombier fprint(dfd, "Ack\n");
1633e12c5d1SDavid du Colombier send(Ack);
1643e12c5d1SDavid du Colombier if(write(fd, buf+3, 128) != 128){
1653e12c5d1SDavid du Colombier fprint(2, "xmr: abort, error writing file\n");
1663e12c5d1SDavid du Colombier exits("write");
1673e12c5d1SDavid du Colombier }
1683e12c5d1SDavid du Colombier return 0;
1693e12c5d1SDavid du Colombier } else {
1703e12c5d1SDavid du Colombier send(Nak);
1713e12c5d1SDavid du Colombier }
1723e12c5d1SDavid du Colombier }
1733e12c5d1SDavid du Colombier }
1743e12c5d1SDavid du Colombier
1753e12c5d1SDavid du Colombier int
notifyf(void * a,char * msg)1763e12c5d1SDavid du Colombier notifyf(void *a, char *msg)
1773e12c5d1SDavid du Colombier {
1783e12c5d1SDavid du Colombier USED(a);
1793e12c5d1SDavid du Colombier if(strcmp(msg, "alarm") == 0)
1803e12c5d1SDavid du Colombier return 1;
1813e12c5d1SDavid du Colombier return 0;
1823e12c5d1SDavid du Colombier }
183