1implement Filter; 2 3include "sys.m"; 4 5include "filter.m"; 6 7End: con byte 8r300; 8Esc: con byte 8r333; 9Eend: con byte 8r334; # encoded End byte 10Eesc: con byte 8r335; # encoded Esc byte 11 12init() 13{ 14} 15 16start(param: string): chan of ref Rq 17{ 18 req := chan of ref Rq; 19 if(param == "encode") 20 spawn encode(req); 21 else 22 spawn decode(req); 23 return req; 24} 25 26encode(reqs: chan of ref Rq) 27{ 28 sys := load Sys Sys->PATH; 29 reqs <-= ref Rq.Start(sys->pctl(0, nil)); 30 buf := array[8192] of byte; 31 rc := chan of int; 32 do{ 33 reqs <-= ref Rq.Fill(buf, rc); 34 if((n := <-rc) <= 0){ 35 if(n == 0) 36 reqs <-= ref Rq.Finished(nil); 37 break; 38 } 39 b := array[2*n + 2] of byte; # optimise time not space 40 o := 1; 41 b[0] = End; 42 for(i := 0; i < n; i++){ 43 if((c := buf[i]) == End || c == Esc){ 44 b[o++] = Esc; 45 c = byte (Eend + (c& byte 1)); 46 } 47 b[o++] = c; 48 } 49 b[o++] = End; 50 if(o != len b) 51 b = b[0:o]; 52 reqs <-= ref Rq.Result(b, rc); 53 }while(<-rc != -1); 54} 55 56Slipesc, Slipend: con (1<<8) + iota; 57Slipsize: con 1006; # rfc's suggestion 58 59slipin(c: byte, esc: int): int 60{ 61 if(esc == Slipesc){ # last byte was Esc 62 if(c == Eend) 63 c = End; 64 else if(c == Eesc) 65 c = Esc; 66 }else{ 67 if(c == Esc) 68 return Slipesc; 69 if(c == End) 70 return Slipend; 71 } 72 return int c; 73} 74 75decode(reqs: chan of ref Rq) 76{ 77 sys := load Sys Sys->PATH; 78 reqs <-= ref Rq.Start(sys->pctl(0, nil)); 79 buf := array[8192] of byte; 80 b := array[Slipsize] of byte; 81 rc := chan of int; 82 c := 0; 83 o := 0; 84 for(;;){ 85 reqs <-= ref Rq.Fill(buf, rc); 86 if((n := <-rc) <= 0){ 87 if(n < 0) 88 exit; 89 break; 90 } 91 for(i := 0; i < n; i++){ 92 c = slipin(buf[i], c); 93 if(c == Slipend){ 94 if(o != 0){ 95 reqs <-= ref Rq.Result(b[0:o], rc); 96 if(<-rc == -1) 97 exit; 98 b = array[Slipsize] of byte; 99 o = 0; 100 } 101 }else if(c != Slipesc){ 102 if(o >= len b){ 103 t := array[3*len b/2] of byte; 104 t[0:] = b; 105 b = t; 106 } 107 b[o++] = byte c; 108 } 109 } 110 } 111 # partial block discarded 112 reqs <-= ref Rq.Finished(nil); 113} 114