summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharles.Forsyth <devnull@localhost>2008-01-30 11:21:46 +0000
committerCharles.Forsyth <devnull@localhost>2008-01-30 11:21:46 +0000
commita182ad059370106bdb7caf521599e39612bfc7cf (patch)
tree982b1d4362e4ffc00439cb8c5e35e9e9b8cead48
parent279831cd5663f49afc0f72634e6e022b45cb9877 (diff)
20080130-1128
-rw-r--r--CHANGES1
-rw-r--r--appl/lib/mkfile2
-rw-r--r--appl/lib/msgio.b152
-rw-r--r--dis/lib/msgio.disbin0 -> 1391 bytes
-rw-r--r--lib/proto/inferno3
-rw-r--r--man/2/INDEX9
-rw-r--r--man/2/msgio155
-rw-r--r--module/msgio.m23
8 files changed, 345 insertions, 0 deletions
diff --git a/CHANGES b/CHANGES
index 2d7bb40e..25e2db41 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,7 @@
20080130
failed to return nil from Jvalue.get in appl/lib/json.b if member name didn't match
similar problem in appl/lib/ubfa.b
+ add msgio(2)
20080124
fix emu/port/devssl.c os/port/devssl.c not to keep the directory numbers(!)
20080122
diff --git a/appl/lib/mkfile b/appl/lib/mkfile
index 34062c42..67de72ac 100644
--- a/appl/lib/mkfile
+++ b/appl/lib/mkfile
@@ -71,6 +71,7 @@ TARG=\
login.dis\
man.dis\
mpeg.dis\
+ msgio.dis\
nametree.dis\
names.dis\
newns.dis\
@@ -237,3 +238,4 @@ lists.dis: $ROOT/module/lists.m
vac.dis: $ROOT/module/vac.m $ROOT/module/venti.m
dial.dis: $ROOT/module/dial.m
styxflush.dis: $ROOT/module/styxflush.m
+msgio.dis: $ROOT/module/msgio.m
diff --git a/appl/lib/msgio.b b/appl/lib/msgio.b
new file mode 100644
index 00000000..035b1783
--- /dev/null
+++ b/appl/lib/msgio.b
@@ -0,0 +1,152 @@
+implement Msgio;
+
+# probably need Authio or Auth instead, to include Authinfo, Certificate and signing operations?
+# eliminates certificates and sigalgs from Keyring
+# might be better just to have mp.m and sec.m?
+# general signature module?
+# Keyring->dhparams is is only needed by createsignerkey (and others creating Authinfo)
+# should also improve pkcs
+
+include "sys.m";
+ sys: Sys;
+
+include "keyring.m";
+
+include "msgio.m";
+
+init()
+{
+ sys = load Sys Sys->PATH;
+}
+
+seterr(r: int)
+{
+ if(r > 0)
+ sys->werrstr("input or format error");
+ else if(r == 0)
+ sys->werrstr("hungup");
+}
+
+#
+# i/o on a channel that might or might not retain record boundaries
+#
+getmsg(fd: ref Sys->FD): array of byte
+{
+ num := array[5] of byte;
+ r := sys->readn(fd, num, len num);
+ if(r != len num) {
+ seterr(r);
+ return nil;
+ }
+ h := string num;
+ if(h[0] == '!')
+ m := int h[1:];
+ else
+ m = int h;
+ if(m < 0 || m > Maxmsg) {
+ seterr(1);
+ return nil;
+ }
+ buf := array[m] of byte;
+ r = sys->readn(fd, buf, m);
+ if(r != m){
+ seterr(r);
+ return nil;
+ }
+ if(h[0] == '!'){
+ sys->werrstr(string buf);
+ return nil;
+ }
+ return buf;
+}
+
+sendmsg(fd: ref Sys->FD, buf: array of byte, n: int): int
+{
+ if(sys->fprint(fd, "%4.4d\n", n) < 0)
+ return -1;
+ return sys->write(fd, buf, n);
+}
+
+senderrmsg(fd: ref Sys->FD, s: string): int
+{
+ buf := array of byte s;
+ if(sys->fprint(fd, "!%3.3d\n", len buf) < 0)
+ return -1;
+ if(sys->write(fd, buf, len buf) <= 0)
+ return -1;
+ return 0;
+}
+
+#
+# i/o on a delimited channel
+#
+getbuf(fd: ref Sys->FD, buf: array of byte, n: int): (int, string)
+{
+ n = sys->read(fd, buf, n);
+ if(n <= 0){
+ seterr(n);
+ return (-1, sys->sprint("%r"));
+ }
+ if(buf[0] == byte 0)
+ return (n, nil);
+ if(buf[0] == byte 16rFF){
+ # garbled, possibly the wrong encryption
+ return (-1, "failure");
+ }
+ # error string
+ if(--n < 1)
+ return (-1, "unknown");
+ return (-1, string buf[1:]);
+}
+
+getbytearray(fd: ref Sys->FD): (array of byte, string)
+{
+ buf := array[Maxmsg] of byte;
+ (n, err) := getbuf(fd, buf, len buf);
+ if(n < 0)
+ return (nil, err);
+ return (buf[1: n], nil);
+}
+
+getstring(fd: ref Sys->FD): (string, string)
+{
+ (a, err) := getbytearray(fd);
+ if(a != nil)
+ return (string a, err);
+ return (nil, err);
+}
+
+putbuf(fd: ref Sys->FD, data: array of byte, n: int): int
+{
+ buf := array[Maxmsg] of byte;
+ if(n < 0) {
+ buf[0] = byte 16rFF;
+ n = -n;
+ }else
+ buf[0] = byte 0;
+ if(n >= Maxmsg)
+ n = Maxmsg-1;
+ buf[1:] = data;
+ return sys->write(fd, buf, n+1);
+}
+
+putstring(fd: ref Sys->FD, s: string): int
+{
+ a := array of byte s;
+ return putbuf(fd, a, len a);
+}
+
+putbytearray(fd: ref Sys->FD, a: array of byte, n: int): int
+{
+ if(n > len a)
+ n = len a;
+ return putbuf(fd, a, n);
+}
+
+puterror(fd: ref Sys->FD, s: string): int
+{
+ if(s == nil)
+ s = "unknown";
+ a := array of byte s;
+ return putbuf(fd, a, -len a);
+}
diff --git a/dis/lib/msgio.dis b/dis/lib/msgio.dis
new file mode 100644
index 00000000..34ff350c
--- /dev/null
+++ b/dis/lib/msgio.dis
Binary files differ
diff --git a/lib/proto/inferno b/lib/proto/inferno
index d041465b..25c8c4ac 100644
--- a/lib/proto/inferno
+++ b/lib/proto/inferno
@@ -1028,6 +1028,7 @@ appl
memfs.b
mkfile
mpeg.b
+ msgio.b
nametree.b
names.b
newns.b
@@ -1641,6 +1642,7 @@ dis
mashparse.dis
memfs.dis
mpeg.dis
+ msgio.dis
nametree.dis
names.dis
newns.dis
@@ -2290,6 +2292,7 @@ module
*
memfs.m
mpeg.m
+ msgio.m
multistyx.m
muxclient.m
names.m
diff --git a/man/2/INDEX b/man/2/INDEX
index c1c27311..07b31546 100644
--- a/man/2/INDEX
+++ b/man/2/INDEX
@@ -282,6 +282,15 @@ norm1 math-linalg
norm2 math-linalg
sort math-linalg
mpeg mpeg
+getbytearray msgio
+getmsg msgio
+getstring msgio
+msgio msgio
+putbytearray msgio
+puterror msgio
+putstring msgio
+senderrmsg msgio
+sendmsg msgio
basename names
cleanname names
dirname names
diff --git a/man/2/msgio b/man/2/msgio
new file mode 100644
index 00000000..8bb4e4df
--- /dev/null
+++ b/man/2/msgio
@@ -0,0 +1,155 @@
+.TH MSGIO 2
+.SH NAME
+msgio: getmsg, sendmsg, senderrmsg, getstring, putstring, getbytearray, putbytearray, puterror \- exchange data on delimited and undelimited streams
+.SH SYNOPSIS
+.EX
+include "msgio.m";
+msgio := load Msgio Msgio->PATH;
+
+init: fn();
+
+getmsg: fn(fd: ref Sys->FD): array of byte;
+sendmsg: fn(fd: ref Sys->FD, buf: array of byte, n: int): int;
+senderrmsg: fn(fd: ref Sys->FD, s: string): int;
+
+getstring: fn(fd: ref Sys->FD): (string, string);
+putstring: fn(fd: ref Sys->FD, s: string): int;
+getbytearray: fn(fd: ref Sys->FD): (array of byte, string);
+putbytearray: fn(fd: ref Sys->FD, a: array of byte, n: int): int;
+puterror: fn(fd: ref Sys->FD, s: string): int;
+.EE
+.SH DESCRIPTION
+.B Msgio
+provides two complementary sets of functions for the exchange of data over a network
+connection that uses a connection-oriented transport protocols.
+The connection is represented by a file descriptor
+.IR fd .
+.PP
+.B Init
+must be called before any other operation of the module.
+.PP
+The first set allows arbitrary data, packed into arrays of bytes, to be exchanged
+on network connections using protocols such as TCP/IP that do not preserve
+record boundaries.
+They are used to implement various authentication protocols, including
+.IR auth (6).
+.PP
+Each data message is transmitted with a five-byte header containing a four-character zero-padded decimal count
+.I n
+terminated by a newline, followed by
+.I n
+bytes of message data.
+An error message has a similar structure, except that the first character
+of the count is replaced by an exclamation mark
+.RB ( ! );
+the message data following
+contains the diagnostic string in its UTF-8 encoding (see
+.IR utf (6)).
+.PP
+.B Getmsg
+reads the next message from
+.I fd
+and returns its data content.
+.PP
+.B Sendmsg
+sends the first
+.I n
+bytes of
+.I buf
+as a message on
+.IR fd ,
+and returns
+.IR n .
+.PP
+.B Senderrmsg
+sends the error message
+.IR s .
+.PP
+The second set of functions provide
+I/O for strings, byte arrays and error strings over network connections that
+provide a record structure for communication (as provided for arbitrary
+networks by
+.IR ssl (3)).
+.PP
+.B Putstring
+writes string
+.I s
+to
+.IR fd.
+It returns the number of bytes written, or -1 if an error occurred.
+Messages written by
+.B putstring
+are truncated to 4096 bytes.
+.PP
+.B Getstring
+reads a string as written by
+.B putstring
+from
+.IR fd
+and returns a tuple
+.RI ( result , error ).
+If successful, the error
+string is nil.
+.PP
+.B Putbytearray
+writes the array of bytes
+.I a
+to
+.IR fd .
+It returns the number of bytes written, or -1 if an error occurred.
+Messages written by
+.B putbytearray
+are truncated to 4096 bytes.
+.PP
+.B Getbytearray
+reads an array of bytes as written by
+.B putbytearray
+from
+.IR fd
+and returns a tuple of the form
+.RI ( result , error ).
+If successful, the error string is nil.
+.PP
+.B Puterror
+writes an error string
+.I s
+to
+.IR fd .
+It can be used in place of
+.B putstring
+or
+.B putbytearray
+to cause a corresponding
+.B getstring
+or
+.B getbytearray
+to fail
+(in the receiving process),
+forcing them to return the error string
+.IR s .
+It may not be longer than
+.BR Sys->ERRMAX
+bytes.
+.SH SOURCE
+.B /appl/lib/msgio.b
+.SH DIAGNOSTICS
+The output functions return an
+.B int
+which is -1 if there was an I/O error,
+and a non-negative value otherwise;
+they also set the system error string.
+.B Getmsg
+returns nil if there was an error reading from
+.IR fd ;
+it sets the system error string to reflect the cause.
+It also returns nil
+if an error message was received instead of a data message;
+the system error string will contain the error message's diagnostic.
+The other input functions (for streams with delimiters)
+return a tuple that includes a string indicating the cause of the
+error, as the second element of the tuple.
+.SH BUGS
+The module is really intended to retrofit the original Inferno authentication
+protocols into a new regime, and is not yet intended for general-purpose use,
+hence the irregular naming and calling conventions, inherited from the original implementation in
+.BR Keyring .
diff --git a/module/msgio.m b/module/msgio.m
new file mode 100644
index 00000000..262fcf87
--- /dev/null
+++ b/module/msgio.m
@@ -0,0 +1,23 @@
+Msgio: module
+{
+ PATH: con "/dis/lib/msgio.dis";
+
+ init: fn();
+
+ Maxmsg: con 4096;
+
+ # message io on a delimited connection (ssl for example)
+ # messages >= Maxmsg bytes are truncated
+ # errors > 64 bytes are truncated
+ # getstring and getbytearray return (result, error).
+ getstring: fn(fd: ref Sys->FD): (string, string);
+ putstring: fn(fd: ref Sys->FD, s: string): int;
+ getbytearray: fn(fd: ref Sys->FD): (array of byte, string);
+ putbytearray: fn(fd: ref Sys->FD, a: array of byte, n: int): int;
+ puterror: fn(fd: ref Sys->FD, s: string): int;
+
+ # to send and receive messages when ssl isn't pushed
+ getmsg: fn(fd: ref Sys->FD): array of byte;
+ sendmsg: fn(fd: ref Sys->FD, buf: array of byte, n: int): int;
+ senderrmsg: fn(fd: ref Sys->FD, s: string): int;
+};