123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- #include <u.h>
- #include <libc.h>
- enum {
- Soh= 0x1,
- Eot= 0x4,
- Ack= 0x6,
- Nak= 0x15,
- Cancel= 0x18,
- };
- int notifyf(void*, char*);
- int readupto(uchar*, int);
- int receive(int, uchar);
- void send(int);
- int debug, dfd;
- void
- main(int argc, char **argv)
- {
- int fd;
- uchar seqno;
- ulong bytes;
- ARGBEGIN {
- case 'd':
- dfd = 2;
- debug = 1;
- break;
- } ARGEND
- if(argc != 1){
- fprint(2, "usage: xmr filename\n");
- exits("usage");
- }
- fd = open("/dev/consctl", OWRITE);
- if(fd >= 0)
- write(fd, "rawon", 5);
- fd = create(argv[0], ORDWR, 0666);
- if(fd < 0){
- perror("xmr: create");
- exits("create");
- }
- atnotify(notifyf, 1);
- send(Nak);
- /*
- * keep receiving till the other side gives up
- */
- bytes = 0;
- for(seqno = 1; ; seqno++){
- if(receive(fd, seqno) == -1)
- break;
- bytes += 128;
- }
- fprint(2, "xmr: received %ld bytes\n", bytes);
- exits(0);
- }
- void
- send(int byte)
- {
- uchar c;
- c = byte;
- if(write(1, &c, 1) != 1){
- fprint(2, "xmr: hungup\n");
- exits("hangup");
- }
- }
- int
- readupto(uchar *a, int len)
- {
- int n;
- int sofar;
- for(sofar = 0; sofar < len; sofar += n){
- n = read(0, a, len-sofar);
- if(n <= 0){
- send(Nak);
- return sofar;
- }
- if(*a == Eot || *a == Cancel)
- return sofar + n;
- a += n;
- }
- return sofar;
- }
- int
- receive(int fd, uchar seqno)
- {
- uchar buf[128+4];
- uchar sum;
- uchar *p;
- int n;
- int tries;
- int have;
- for(have = 0, tries = 0;; tries++){
- if(debug)
- fprint(dfd, "have == %d\n", have);
- if(tries > 10){
- fprint(2, "xmr: timed out\n");
- if(debug)
- close(dfd);
- exits("timeout");
- }
- /* try to gather up a block */
- alarm(15*1000);
- n = readupto(&buf[have], 132-have);
- alarm(0);
- have += n;
- if(have){
- switch(buf[0]){
- case Eot:
- send(Ack);
- return -1;
- case Cancel:
- fprint(2, "xmr: transfer aborted by sender\n");
- exits("cancel");
- }
- }
- if(have != 132)
- continue;
- /* checksum */
- for(p = buf, sum = 0; p < &buf[128+3]; p++)
- sum += *p;
- /* If invalid block, resynchronize */
- if(buf[0] != Soh || buf[2] != (255-buf[1]) || sum != buf[131]){
- if(debug){
- fprint(dfd, "resync %2.2ux %d %d %ux %ux\n", buf[0],
- buf[1], buf[2], sum, buf[131]);
- write(dfd, (char*)buf+3, 128);
- fprint(dfd, "\n");
- }
- p = memchr(buf+1, Soh, 131);
- if(p){
- have = 132-(p-buf);
- memmove(buf, p, have);
- } else
- have = 0;
- continue;
- }
- /* it's probably a real block, so dump it if there's an error */
- have = 0;
- /* if this is the last block, ack */
- if(buf[1] == seqno-1){
- tries = 0;
- send(Ack);
- }else if(buf[1] == seqno){
- if(debug)
- fprint(dfd, "Ack\n");
- send(Ack);
- if(write(fd, buf+3, 128) != 128){
- fprint(2, "xmr: abort, error writing file\n");
- exits("write");
- }
- return 0;
- } else {
- send(Nak);
- }
- }
- }
- int
- notifyf(void *a, char *msg)
- {
- USED(a);
- if(strcmp(msg, "alarm") == 0)
- return 1;
- return 0;
- }
|