xref: /inferno-os/appl/lib/plumbmsg.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
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