From a182ad059370106bdb7caf521599e39612bfc7cf Mon Sep 17 00:00:00 2001 From: "Charles.Forsyth" Date: Wed, 30 Jan 2008 11:21:46 +0000 Subject: 20080130-1128 --- CHANGES | 1 + appl/lib/mkfile | 2 + appl/lib/msgio.b | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++++ dis/lib/msgio.dis | Bin 0 -> 1391 bytes lib/proto/inferno | 3 ++ man/2/INDEX | 9 ++++ man/2/msgio | 155 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ module/msgio.m | 23 ++++++++ 8 files changed, 345 insertions(+) create mode 100644 appl/lib/msgio.b create mode 100644 dis/lib/msgio.dis create mode 100644 man/2/msgio create mode 100644 module/msgio.m 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 Binary files /dev/null and b/dis/lib/msgio.dis 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; +}; -- cgit v1.2.3