1*37da2899SCharles.Forsythimplement Plumbmsg; 2*37da2899SCharles.Forsyth 3*37da2899SCharles.Forsythinclude "sys.m"; 4*37da2899SCharles.Forsyth sys: Sys; 5*37da2899SCharles.Forsyth 6*37da2899SCharles.Forsythinclude "plumbmsg.m"; 7*37da2899SCharles.Forsyth 8*37da2899SCharles.Forsythinput: ref Sys->FD; 9*37da2899SCharles.Forsythport: ref Sys->FD; 10*37da2899SCharles.Forsythportname: string; 11*37da2899SCharles.Forsythmaxdatasize: int; 12*37da2899SCharles.Forsyth 13*37da2899SCharles.Forsythinit(doinput: int, rcvport: string, maxdata: int): int 14*37da2899SCharles.Forsyth{ 15*37da2899SCharles.Forsyth sys = load Sys Sys->PATH; 16*37da2899SCharles.Forsyth 17*37da2899SCharles.Forsyth if(!doinput && rcvport == nil) # server, not client 18*37da2899SCharles.Forsyth return 1; 19*37da2899SCharles.Forsyth input = sys->open("/chan/plumb.input", Sys->OWRITE); 20*37da2899SCharles.Forsyth if(input == nil) 21*37da2899SCharles.Forsyth return -1; 22*37da2899SCharles.Forsyth if(rcvport == nil) # sending messages but never receiving them 23*37da2899SCharles.Forsyth return 1; 24*37da2899SCharles.Forsyth port = sys->open("/chan/plumb."+rcvport, Sys->OREAD); 25*37da2899SCharles.Forsyth if(port == nil){ 26*37da2899SCharles.Forsyth input = nil; 27*37da2899SCharles.Forsyth return -1; 28*37da2899SCharles.Forsyth } 29*37da2899SCharles.Forsyth maxdatasize = maxdata; 30*37da2899SCharles.Forsyth portname = rcvport; 31*37da2899SCharles.Forsyth msg := ref Msg; 32*37da2899SCharles.Forsyth msg.src = portname; 33*37da2899SCharles.Forsyth msg.dst = "plumb"; 34*37da2899SCharles.Forsyth msg.kind = "text"; 35*37da2899SCharles.Forsyth msg.data = array of byte "start"; 36*37da2899SCharles.Forsyth if(msg.send() < 0){ 37*37da2899SCharles.Forsyth port = nil; 38*37da2899SCharles.Forsyth input = nil; 39*37da2899SCharles.Forsyth return -1; 40*37da2899SCharles.Forsyth } 41*37da2899SCharles.Forsyth return 1; 42*37da2899SCharles.Forsyth} 43*37da2899SCharles.Forsyth 44*37da2899SCharles.Forsythshutdown() 45*37da2899SCharles.Forsyth{ 46*37da2899SCharles.Forsyth msg := ref Msg; 47*37da2899SCharles.Forsyth msg.src = portname; 48*37da2899SCharles.Forsyth msg.dst = "plumb"; 49*37da2899SCharles.Forsyth msg.kind = "text"; 50*37da2899SCharles.Forsyth msg.data = array of byte "stop"; 51*37da2899SCharles.Forsyth msg.send(); 52*37da2899SCharles.Forsyth} 53*37da2899SCharles.Forsyth 54*37da2899SCharles.ForsythMsg.send(msg: self ref Msg): int 55*37da2899SCharles.Forsyth{ 56*37da2899SCharles.Forsyth hdr := 57*37da2899SCharles.Forsyth msg.src+"\n"+ 58*37da2899SCharles.Forsyth msg.dst+"\n"+ 59*37da2899SCharles.Forsyth msg.dir+"\n"+ 60*37da2899SCharles.Forsyth msg.kind+"\n"+ 61*37da2899SCharles.Forsyth msg.attr+"\n"+ 62*37da2899SCharles.Forsyth string len msg.data+"\n"; 63*37da2899SCharles.Forsyth ahdr := array of byte hdr; 64*37da2899SCharles.Forsyth b := array[len ahdr+len msg.data] of byte; 65*37da2899SCharles.Forsyth b[0:] = ahdr; 66*37da2899SCharles.Forsyth b[len ahdr:] = msg.data; 67*37da2899SCharles.Forsyth return sys->write(input, b, len b); 68*37da2899SCharles.Forsyth} 69*37da2899SCharles.Forsyth 70*37da2899SCharles.ForsythMsg.recv(): ref Msg 71*37da2899SCharles.Forsyth{ 72*37da2899SCharles.Forsyth b := array[maxdatasize+1000] of byte; 73*37da2899SCharles.Forsyth n := sys->read(port, b, len b); 74*37da2899SCharles.Forsyth if(n <= 0) 75*37da2899SCharles.Forsyth return nil; 76*37da2899SCharles.Forsyth return Msg.unpack(b[0:n]); 77*37da2899SCharles.Forsyth} 78*37da2899SCharles.Forsyth 79*37da2899SCharles.ForsythMsg.unpack(b: array of byte): ref Msg 80*37da2899SCharles.Forsyth{ 81*37da2899SCharles.Forsyth (hdr, data) := unpack(b, 6); 82*37da2899SCharles.Forsyth if(hdr == nil) 83*37da2899SCharles.Forsyth return nil; 84*37da2899SCharles.Forsyth 85*37da2899SCharles.Forsyth msg := ref Msg; 86*37da2899SCharles.Forsyth msg.src = hdr[0]; 87*37da2899SCharles.Forsyth msg.dst = hdr[1]; 88*37da2899SCharles.Forsyth msg.dir = hdr[2]; 89*37da2899SCharles.Forsyth msg.kind = hdr[3]; 90*37da2899SCharles.Forsyth msg.attr = hdr[4]; 91*37da2899SCharles.Forsyth msg.data = data; 92*37da2899SCharles.Forsyth 93*37da2899SCharles.Forsyth return msg; 94*37da2899SCharles.Forsyth} 95*37da2899SCharles.Forsyth 96*37da2899SCharles.ForsythMsg.pack(msg: self ref Msg): array of byte 97*37da2899SCharles.Forsyth{ 98*37da2899SCharles.Forsyth hdr := 99*37da2899SCharles.Forsyth msg.src+"\n"+ 100*37da2899SCharles.Forsyth msg.dst+"\n"+ 101*37da2899SCharles.Forsyth msg.dir+"\n"+ 102*37da2899SCharles.Forsyth msg.kind+"\n"+ 103*37da2899SCharles.Forsyth msg.attr+"\n"+ 104*37da2899SCharles.Forsyth string len msg.data+"\n"; 105*37da2899SCharles.Forsyth ahdr := array of byte hdr; 106*37da2899SCharles.Forsyth b := array[len ahdr+len msg.data] of byte; 107*37da2899SCharles.Forsyth b[0:] = ahdr; 108*37da2899SCharles.Forsyth b[len ahdr:] = msg.data; 109*37da2899SCharles.Forsyth return b; 110*37da2899SCharles.Forsyth} 111*37da2899SCharles.Forsyth 112*37da2899SCharles.Forsyth# unpack message from array of bytes. last string in message 113*37da2899SCharles.Forsyth# is number of bytes in data portion of message 114*37da2899SCharles.Forsythunpack(b: array of byte, ns: int): (array of string, array of byte) 115*37da2899SCharles.Forsyth{ 116*37da2899SCharles.Forsyth i := 0; 117*37da2899SCharles.Forsyth a := array[ns] of string; 118*37da2899SCharles.Forsyth for(n:=0; n<ns; n++){ 119*37da2899SCharles.Forsyth (i, a[n]) = unpackstring(b, i); 120*37da2899SCharles.Forsyth if(i < 0) 121*37da2899SCharles.Forsyth return (nil, nil); 122*37da2899SCharles.Forsyth } 123*37da2899SCharles.Forsyth nb := int a[ns-1]; 124*37da2899SCharles.Forsyth if((len b)-i != nb){ 125*37da2899SCharles.Forsyth sys->print("unpack: bad message format: wrong nbytes\n"); 126*37da2899SCharles.Forsyth return (nil, nil); 127*37da2899SCharles.Forsyth } 128*37da2899SCharles.Forsyth # copy data so b can be reused or freed 129*37da2899SCharles.Forsyth data := array[nb] of byte; 130*37da2899SCharles.Forsyth data[0:] = b[i:]; 131*37da2899SCharles.Forsyth return (a, data); 132*37da2899SCharles.Forsyth} 133*37da2899SCharles.Forsyth 134*37da2899SCharles.Forsythunpackstring(b: array of byte, i: int): (int, string) 135*37da2899SCharles.Forsyth{ 136*37da2899SCharles.Forsyth starti := i; 137*37da2899SCharles.Forsyth while(i < len b){ 138*37da2899SCharles.Forsyth if(b[i] == byte '\n') 139*37da2899SCharles.Forsyth return (i+1, string b[starti:i]); 140*37da2899SCharles.Forsyth i++; 141*37da2899SCharles.Forsyth } 142*37da2899SCharles.Forsyth return (-1, nil); 143*37da2899SCharles.Forsyth} 144*37da2899SCharles.Forsyth 145*37da2899SCharles.Forsythstring2attrs(s: string): list of ref Attr 146*37da2899SCharles.Forsyth{ 147*37da2899SCharles.Forsyth (nil, pairs) := sys->tokenize(s, "\t"); 148*37da2899SCharles.Forsyth if(pairs == nil) 149*37da2899SCharles.Forsyth return nil; 150*37da2899SCharles.Forsyth attrs: list of ref Attr; 151*37da2899SCharles.Forsyth while(pairs != nil){ 152*37da2899SCharles.Forsyth pair := hd pairs; 153*37da2899SCharles.Forsyth pairs = tl pairs; 154*37da2899SCharles.Forsyth a := ref Attr; 155*37da2899SCharles.Forsyth for(i:=0; i<len pair; i++) 156*37da2899SCharles.Forsyth if(pair[i] == '='){ 157*37da2899SCharles.Forsyth a.name = pair[0:i]; 158*37da2899SCharles.Forsyth if(++i < len pair) 159*37da2899SCharles.Forsyth a.val = pair[i:]; 160*37da2899SCharles.Forsyth break; 161*37da2899SCharles.Forsyth } 162*37da2899SCharles.Forsyth attrs = a :: attrs; 163*37da2899SCharles.Forsyth } 164*37da2899SCharles.Forsyth return attrs; 165*37da2899SCharles.Forsyth} 166*37da2899SCharles.Forsyth 167*37da2899SCharles.Forsythattrs2string(l: list of ref Attr): string 168*37da2899SCharles.Forsyth{ 169*37da2899SCharles.Forsyth s := ""; 170*37da2899SCharles.Forsyth while(l != nil){ 171*37da2899SCharles.Forsyth a := hd l; 172*37da2899SCharles.Forsyth l = tl l; 173*37da2899SCharles.Forsyth if(s == "") 174*37da2899SCharles.Forsyth s = a.name + "=" + a.val; 175*37da2899SCharles.Forsyth else 176*37da2899SCharles.Forsyth s += "\t" + a.name + "=" + a.val; 177*37da2899SCharles.Forsyth } 178*37da2899SCharles.Forsyth return s; 179*37da2899SCharles.Forsyth} 180*37da2899SCharles.Forsyth 181*37da2899SCharles.Forsythlookup(attrs: list of ref Attr, name: string): (int, string) 182*37da2899SCharles.Forsyth{ 183*37da2899SCharles.Forsyth while(attrs != nil){ 184*37da2899SCharles.Forsyth a := hd attrs; 185*37da2899SCharles.Forsyth attrs = tl attrs; 186*37da2899SCharles.Forsyth if(a.name == name) 187*37da2899SCharles.Forsyth return (1, a.val); 188*37da2899SCharles.Forsyth } 189*37da2899SCharles.Forsyth return (0, nil); 190*37da2899SCharles.Forsyth} 191