The LysKOM Project -------------------------------- Specification of protocol A between client and server -------------------------------- by Lars Aronsson Swedish original 25 June 1991 Translated to English 25 August 1992 LysKOM LysKOM is a computer conference system. Other similar systems are QZ-KOM and PortaCOM. The copyright (C) of 1990 for the LysKOM software and documents is owned by Lysator, a students' computer society at Linköping University in Linköping, Sweden. Anyone may freely copy, modify and distribute LysKOM software and documents, on conditions that all recipients of such copies are given the same rights. Not Lysator neither none of its members accept any responsibility for the correctness of software or documentation or for the consequences of their use. This text This text specifies version A of the protocol used between a client (the user's program) and a server (the database program). This text is intended to contain all the information you need in order to write a client without known anything about the server, or vice versa. My intention is to keep this text as complete and correct as possible. If you find any errors, or if there is some information missing, please get in touch with me. The following are known deficiencies not yet corrected: - The structure and contents of the ``user-area''. - Some of the calls added lately (around 60). Files This file is a more systematic compilation of information from the files listed below. It is very much possible that the files have changed names and/or contents at the time you read this. These were their names on 3 June 1991: 2kom/doc/com-spec -- gone! 2kom/doc/security-levels.txt 2kom/include/kom-types.h 2kom/include/kom-errno.h 2kom/isc-client/com.h 2kom/server/fncdef.txt -- gone? 2kom/include/services.h Lower layer protocols LysKOM Protocol A can run on top of any reliable, two-way 8-bit/byte channel. Under extreme conditions, it can also run on top of a 7-bit/byte channel. Today it runs only on top of TCP/IP. At Lysator we use TCP port 4894 on Internet host 130.236.254.1 (kom.lysator.liu.se). Data in protocol A are sent in ASCII text. Inside Hollerith strings (details below), any 8-bit values may be represented. The idea, however, is that you should be able to run the ``raw'' protocol using the telnet command from a dumb text terminal. Abstract syntax notation Within this specification, a grammar similar to BNF has been used to represent the data elements of the protocol. This is indeed a very scientific method, for so do they who specify ISO/OSI protocols. The grammar used here is supposed to emulate OSI's ASN.1, but I don't have the specification of ASN.1 at hand. Data fields have been given lower-case names and data types have names in upper case. For type definitions, the ::= operator is used, as is the case in BNF. For data field declaration, the : operator is used, as it is in Pascal. Comments are introduced with a ! and last until end of the line, this is known to all BLISS programmers. Semicolons are used as they are in C. Next, the basic data types and their notation is described. Basic data types The data elements transported across the protocol are separated by (any sequence of) spaces, tabs, line-feeds, carriage returns, or NULL characters. Avoid to send NULL characters, but be prepared for them and interpret them as white space. INTEGER is the data type for non-negative integral numbers that must fit within 32 bits. They are represented as text in decimal notation. HOLLERITH is the data type for text strings and sequences of binary bytes. First, the length of the string is sent in the shape of an INTEGER, then comes the upper-case letter H, immediately followed (with separating white space!) by the text. Bytes in HOLLERITH strings can have any value from 0 to 255. BITSTRING is the data type for sequences of binary bits or bit-logic flags. These are represented in text as integral numbers in binary notation. All bits, also leading zeroes, must be sent. Bit value 1 represents a true logic value and 0 represents false. Bits are sent in order as listed in the abstract syntax. An example: shape-of-world : BITSTRING ( is-flat; is-round; is-3d; is-2d; ! e.g. "0110" ) ARRAY is the data type for a list of elements all having the same type. The data type of the elements is written immediately after the word ARRAY. In protocol representation, an INTEGER comes first, telling the number of elements in this array, then comes an opening curly brace {, then all the elements according to their type, finally a closing curly brace }. The curly braces really have no function, their only purpose is to make it easier to read the raw protocol. An example: hackers : ARRAY HOLLERITH; ! e.g. 5 { 8Haronsson 7Hbellman 5Hceder 4Hinge 7Hwillför } SELECTION is the data type that cannot decide what it is. It is represented by an INTEGER and an optional trailer. The existence and data type of the trailer depends on the leading integer. The legal integral values for a certain selection is written number=name in the abstract syntax. An example: phrase : SELECTION ( 1=hello name:HOLLERITH; ! e.g. "1 4HJohn" 2=howdy ; ! e.g. "2" ) RPC is a very special data type used for remote procedure calls, that is protocol entities making up calls and return values. The notation for RPC is similar to that for SELECTION, but each branch has two trailers: the data field for the call and the data field for the return value. The selection number is only sent together with the call, not together with the return value. An example: phrases : RPC ( 1=cost inventory:INTEGER; price:INTEGER; 2=time timezone:INTEGER; hours:INTEGER; 3=name ; name:HOLLERITH; ) ! e.g. call "1 23" returns "498" ! call "3" returns "4HLars" ! call "2 1" returns "1430" The data type for structs or records has no reserved word in the abstract syntax notation. Structs are written as surrounding opening and closing parenthesis ( ). Structs themselves do not add to the data sent in the protocol. Dialog A LysKOM session always starts with connection and protocol negotiation. The client selects a protocol by sending a connection-request : ( "A"; login-name : HOLLERITH; ) ! e.g. "A8Hsand_man" which should be answered by the server by a connection-acknowledgement : "LysKOM\n" Note that only protocol A can be selected. Hopefully, someone will specify and implement the B protocol in the future. The login name given together with the client's host name will show up in the "who-is-on" list. After this negotiation, the protocol consists of the RPC protocol called commands. The client is allowed to send several RPC calls before receiving the return value from the first call. In order to keep track of which return value belongs to which call, the calling client picks a small number to accompany each call. The same small number is found in the return value. It is the task of the client to pick and keep track of these small numbers. call : ( reference-no : INTEGER; commands-call; ) If all goes well, the above client call results in the servers ok-return : ( "="; reference-no : INTEGER; commands-return; ) otherwise, that is if something fails, the server responds error-return : ( "%"; reference-no : INTEGER; error-no : Error-No; error-status : INTEGER; ) There will be no white space between = or % and the following small reference number. Note that even for calls where the commands-return (the return value trailer of the RPC type commands) is empty, the server responds with = or % and the reference number. Security levels and privilege bits Security and privileges in LysKOM are built with two components: Every person has a number of ``bits'' assigned (like the person belongs to the corresponding groups), and every session has a security level (a number). Each privileged operation needs a certain ``bit'' and a minimal security level. The most recent combinations of bits, levels, and operations are found in a file called security-levels.txt. Here is a more readable table: Bit Level Operation ------------------------------------------------------ wheel Not assigned by default 0 Always login, even on crowded server. 6 Give privilege bits to any person 7 Set new password for any person 8 Enter supervisor mode 10 Read all texts in all conferences ------------------------------------------------------ admin Not assigned by default 1 Shutdown the LysKOM server 1 Set motd_of_kom (message of the day) 1 Read last_login 2 Read status for secret conferences and persons 2 Read the protected parts of the status 2 Read all text status information, even for secret recipients 3 Change anybody's name 4 Add and subtract members 4 Add and subtract recipients to texts 5 Define super-conference 5 Erase texts 6 Give away the admin privilege bit ------------------------------------------------------ statistic Not assigned by default 2 Read the statistics parts of the person struct, even if they are protected. ------------------------------------------------------ create_conf Assigned by default 0 Create new conferences ------------------------------------------------------ create_pers Assigned by default 0 Create new persons ------------------------------------------------------ According to the experience of Thomas Bellman, an administrator normally uses only security levels 0 or 255. Rather than the present security levels, each operation should have its own privilege bit. This may find a better solution in future versions of the protocol. Error codes The error codes that may appear as return values to RPC calls are listed below. This table puts them in numeric order. Afterwards is a short cross reference in alphabetic order. Error-No : SELECTION ( 0=no-error; ! No error has occurred 2=not-impl; ! Not implemented yet 3=obsolete; ! No longer implemented 4=pwd; ! Wrong or illegal password 5=long-str; ! String too long 6=login; ! Not logged in. 7=login-disallowed; ! System is in 'single-user mode' 8=conf-zero; ! Attempt to use conference number 0. 9=undef-conf; ! Undefined or secret conference 10=undef-pers; ! Undefined or secret person 11=access; ! No 'read/write permission' 12=perm; ! No permission 13=not-member; ! Not member in conf 14=no-such-text; ! No such global text-no, or no access 15=text-zero; ! Can't use text no 0 16=no-such-local-text;! No such local text-no 17=local-text-zero; ! Can't use local text no 0 18=bad-name; ! Too short or too long ! or contains illegal chars 19=index-out-of-range; 20=conf-exists; ! Already exists 21=pers-exists; ! Already exists 22=secret-public; ! Cannot be secret and !rd-prot 23=letter-box; ! Cannot change letter-box flag 24=ldb-err; ! Should never happen, ! unless Willför makes a mistake. 25=ill-misc; ! Illegal misc field. ! err-stat holds field no 26=illegal-info-type; ! Info-type parameter was illegal. ! This means that there is a ! bug in the client. 27=already-recipient; ! Already recipient to this text. 28=already-comment; ! Already comment to this text. 29=already-footnote; ! Already footnote to this text. 30=not-recipient; ! Not recipient 31=not-comment; ! Not comment to this text. 32=not-footnote; ! Not footnote to this text. 33=recipient-limit; ! Too many recipients 34=comm-limit; ! Too many comments 35=foot-limit; ! Too many footnotes 36=mark-limit; ! Too many marks. 37=not-author; ! Only the author may add footnotes or ! delete texts. 38=no-connect; ! Can't connect to specified server 39=out-of-memory; ! Couldn't get memory for result 40=server-is-crazy; ! Client can't understand server 41=client-is-crazy; ! Client thinks that server says it ! can't understand client. 42=undef-session; ! This session doesn't exist ) Number Message Number Message ------------------------------------------------------ 11 access 28 already-comment 29 already-footnote 27 already-recipient 18 bad-name 41 client-is-crazy 34 comm-limit 20 conf-exists 8 conf-zero 35 foot-limit 25 ill-misc 26 illegal-info-type 19 index-out-of-range 24 ldb-err 23 letter-box 17 local-text-zero 6 login 7 login-disallowed 5 long-str 36 mark-limit 38 no-connect 0 no-error 16 no-such-local-text 14 no-such-text 37 not-author 31 not-comment 32 not-footnote 2 not-impl 13 not-member 30 not-recipient 3 obsolete 39 out-of-memory 12 perm 21 pers-exists 4 pwd 33 recipient-limit 22 secret-public 40 server-is-crazy 15 text-zero 9 undef-conf 10 undef-pers 42 undef-session ------------------------------------------------------ Asynchronous calls At any time, between return values, the server can issue an asynchronous call. They are called so because they are issued by the server, without synchronization to client activities. A client needs not take notice. It suffices to skip over asynchronous calls when reading a return value. Asynchronous calls are introduced with a colon : and an integral number telling how many arguments will follow. Then follows a SELECTOR number and the trailing arguments. As is the case for ok-return and error-return, there will be no white space between the colon and the first number. Below, the asynchronous calls are listed in numeric order. An alphabetic cross reference follows after that. asynchronous-call ::= ( ":"; no-of-arguments : INTEGER; message : SELECTION ( 0=new-text ( text-no : Text-No; text-stat : Text-stat ) ! A new text has been created 1=logout person : Pers-No; ! Referenced person has left LysKOM. ! This call is also named "i-am-off" (in C source code). ! The Emacs Lisp source code states that the ! asynchronous call number 1 is now obsolete. ! It has been replaced by call 13 that tells the session number. 2=who-info ( person : Pers-No; conference : Conf-No; what-am-i-doing : HOLLERITH; ) ! Emacs Lisp source code states that the ! asynchronous call number 2 is called login, but that ! it is now obsolete, anyhow. ! It has been replaced by call 9. 3=conf-deleted ! Not used by the Emacs Lisp client ??? 4=conf-created ! Not used by the Emacs Lisp client ??? 5=conf-changed-name ( conf-no : Conf-No; old-name : HOLLERITH; new-name : HOLLERITH; ) ! Also named "new-name" (in C source code). 6=i-am-on info : Who-Info; 7=database-is-syncing ; 8=forced-leave-conf ! Not used by the Emacs Lisp client ??? 9=login ( pers-no : Pers-No; session-no : Session-No; ) ! Note that one person can have several active sessions 10=broadcast-message ( sender : Pers-No; message : HOLLERITH; ) ! It would be a cleaner design if the server would ! avoid issuing call 10, and instead use call 12. 11=crowded ; ! The asynchronous call number 11 means that someone ! has failed login. This will happen when the server ! cannot open more sockets for incoming TCP connections. ! The responsible user, upon seeing this message, can ! leave LysKOM to make way for others. 12=directed-message ( recipient : Pers-No; sender : Pers-No; message : HOLLERITH; ) ! This means a message was sent to sessions owned by the ! indicated recipient. If the recipient given is zero (0), ! that means this is a broadcast message. ! It is not yet possible to direct messages to individual ! sessions. 13=new-logout ( pers-no : Pers-No; session-no : Session-No; ) ) ) An asterisk * following a number in the below table indicates that the particular asynchronous call is obsolete and has been replaced by something else. See comments in the above presentation for details. No Asynchronous call No Asynchronous call ------------------------------------------------------ 10 broadcast-message 5 conf-changed-name 4 conf-created 3 conf-deleted 11 crowded 7 database-is-syncing 12 directed-message 8 forced-leave-conf 6 i-am-on 9 login 1* logout 13 new-logout 0 new-text 2* who-info ------------------------------------------------------ RPC calls The client will send RPC calls with arguments to the server. The server will respond either by error codes (see above sections Dialog and Error codes) or by return values. Below is a BNF-like grammar for the data types used as call arguments and return values. The RPC calls are listed here in alphabetic order. A numerically ordered cross reference follows immediately after that. commands : RPC ( ! Call number and name ! Data type for call argument ! Data type for return value 32=add-comment params : ( comment : Text-No; comment-to : Text-No; ) ; 37=add-footnote params : ( footnote : Text-No; footnote-to : Text-No; ) ; 14=add-member params : ( conf-no : Conf-No; pers-no : Pers-No; priority : INTEGER; where : INTEGER; ) ; ! Add this person as a new member to this conference. ! The priority and where is the intended priority and place ! of the new membership on person's list of conferences ! and decides the reading order. ! This call is also used to alter priority and/or place of ! existing memberships. 30=add-recipient ! The sequence "conf-no, type" is a reversed Misc-Info. ! Type is recpt or cc_recpt. add-recipient-params : ( text-no : Text-No; conf-no : Conf-No; type : INTEGER; ) ; 45=broadcast message : HOLLERITH; ; ! This is a privileged call. ! The same effect is achieved through a magic argument ! to call number 53. ! An old, erroneous comment states that the argument ! shall be a text-no, but that is not the case. 3=change-name change-name-params : ( conf-no : Conf-No; new-name : HOLLERITH; ) ; ! This call sets a new name for a conference or a person. 4=change-what-i-am-doing what-am-i-doing : HOLLERITH; ; ! The text string will appear in the who-is-on list. ! See also call number 51. 10=create-conf params : ( name : HOLLERITH; type : Conf-Type; ) result : Conf-No; 5=create-person create-person-params : ( name : HOLLERITH; passwd : HOLLERITH; ) Pers-No; ! A new person is created with this name and password. ! The person number of the new person is returned. 28=create-text ! create-text-return returns text number zero on error ! NB! Only Misc-Infos 0,1,2,4 can be sent here. params : ( text : HOLLERITH; misc-info : ARRAY Misc-Info ) result : Text-No; 11=delete-conf conf : Conf-No; ; ! Erase a conference or person 29=delete-text Text-No; ; 55=disconnect session-no : Session-No; ; ! Disconnect a session. You can disconnect your own session ! (even if you are not logged in) and any session where you ! are supervisor of the user that is logged in on that ! session. 42=enable ena-level : INTEGER; ; ! This is a privileged call. ! Set security level of this session. ! Zero means don't use any privileges. 50=get-conf-stat conf-no : Conf-No; result : Conference; ! Return this conference's status information. 13=get-conf-stat-old params : ( conf-no : Conf-No; mask : INTEGER; ) result : Conference ! Since the mask given in this call is ignored by the server, ! this call has been obsoleted by call number 50. ! The status information for the referenced conference ! is returned. ! If the mask is an even number, an empty string (0H) ! will be used in the name field in the return value. ! The original intention was this equotion (just use 255): ! mask = name + members + texts + list-sizes 47=get-created-texts params : ( person : Pers-No; first : Local-Text-No; no-of-texts : INTEGER; ) created-texts : Text-List; ! NB! first is a text number local to the person who wrote it. ! It is not a Local-Text-No in his mailbox. 34=get-map params : ( conf-no : Conf-No; first-local-no : Local-Text-No; no-of-texts : INTEGER; ) result : Text-List; 23=get-marks ; Mark-List; 48=get-members params : ( conf : Conf-No; first : INTEGER; no-of-members : INTEGER; ) members : Member-List; ! first should perhaps be Local-Conf-No... 46=get-membership params : ( person : Pers-No; first : INTEGER; no-of-confs : INTEGER; mask : BITSTRING (want-read-texts); ) memberships : Membership-List; ! first should perhaps be Local-Conf-No... 49=get-person-stat person : Pers-No; result : Person; ! This person's status information is returned. 6=get-person-stat-old params : ( person : Pers-No; mask : INTEGER; ) result : Person; ! Since the mask is ignored by the server, ! this call is obsoleted by call number 49. ! This person's status information is returned. ! If the mask is an even number, an empty string (0H) ! will be used in the username field in the return value. 36=get-server-info ; result : Info; ! Return various information about the server. ! This call number 36 was previously called get-info. 54=get-session-info session-no : Session-No; result : Session-Info; 25=get-text params : ( text : Text-No; start-char : INTEGER; end-char : INTEGER; ) result : HOLLERITH; 26=get-text-stat params : Text-No; result : Text-Stat; 35=get-time ; Time; 52=get-unread-confs pers-no : Pers-No; conf-no-list : ARRAY Conf-No; 0=login login-params : ( person : Pers-No; passwd : HOLLERITH; ) ; 1=logout ; ; ! Call number 1 will never fail. 12=lookup-name name : HOLLERITH; result : Conf-List-Old; ! Expand an abbreviated name and return a list of ! numbers with matching conferences and persons. ! See comment at definition of Conf-List. 27=mark-as-read params : ( conference : Conf-No; texts : ARRAY Local-Text-No; ) ; 24=mark-text params : ( text : Text-No; mark-type : INTEGER; ) ! mark-type = permanently-marked -- just use 255 (?) ! The server only stores (does not act upon) this value. ; 2=pepsi Conf-No; ; ! Call number 2 is used to move to the referenced conference. ! The correct English name is change-conference. ! This name Pepsi is one of the more cryptic puns in LysKOM. 9=query-read-texts params : ( pers-no : Pers-No; conf-no : Conf-No; ) result : Membership; ! You can issue this call before login. 53=send-message params : ( recipient : Pers-No; message : HOLLERITH; ) ; ! A privileged call. ! If the recipient is zero, the message will be sent to ! all active sessions. This can replace call number 45. 17=set-conf-motd params : ( conf-no : Conf-No; text-no : Text-No; ) ; ! Set an existing text to be message-of-the-day for ! the referenced conference or person. ! The text will get be marked against destruction, ! the old m-o-t-d for the conference or person will ! lose its mark. ! This call number 17 was earlier called set-etc-motd. 21=set-conf-type params : ( conf-no : Conf-No; type : Conf-Type ) ; ! Make this conference or person one of this type. 22=set-garb-nice params : ( conf-no : Conf-No; nice : Garb-Nice; ) ; ! Texts in this conference conf-no will be kept for nice days ! before being automatically erased. ! Any marks will of course keep texts past this date. 41=set-motd-of-lyskom motd : Text-No; ; ! This is a privileged call. ! The text indicated by the parameter is set to be the message ! of the day of LysKOM. 8=set-passwd params : ( person : Pers-No; old-pwd : HOLLERITH; new-pwd : HOLLERITH; ) ; ! Give this person a new password. The old password is ! the password of the person owning this session. That is ! not necessarily the person in the first argument. 19=set-permitted-submitters params : ( conf-no : Conf-No; perm-sub : Conf-No; ) ; ! Make the conference or person conf-no write-protected. ! Only members of the perm-sub conference may ! create texts with recipient conf-no. ! If perm-sub is zero (0), then conf-no is no longer ! write-protected. 16=set-presentation params : ( conf-no : Conf-No; text-no : Text-No; ) ; ! Alter presentation for referenced conference or person. ! If text-no is zero, the old presentation is removed ! and no text put in its place. ! Just as set-conf-motd, this call puts a mark against ! deletion on the text used as presentation. 7=set-priv-bits params : ( person : Pers-No; privileges : Priv-Bits ) ; ! Give or take privilege bits for this person. 20=set-super-conf params : ( conf-no : Conf-No; super-conf : Conf-No; ) ; ! Set a new super conference for a conference. ! If conf-no is write-protected (see call 19), any texts sent ! to it will instead appear in the super conference. 18=set-supervisor params : ( conf-no : Conf-No; admin : Conf-No; ) ; ! Define all members in the conference admin as administrators ! (or owners) of the conference conf-no. ! Admin is typically one person. 40=set-unread params : ( conference : Conf-No; no-of-unread : INTEGER; ) ; ! Skip (mark as read) all but the no-of-unread latest texts ! in this conference. 57=set-user-area params : ( pers-no : Pers-No; user-area : Text-No; ) ; ! This text will be used to store this persons personal ! variables. These variables are described elsewhere. 44=shutdown exit-val : INTEGER; ; ! This is a privileged call. ! Shutdown server. ! An old comment says exit-val is not used by the server. ! The same effect is achieved by sending UNIX signal HUP to ! the server process. 33=sub-comment params : ( comment : Text-No; comment-to : Text-No; ) ; 38=sub-footnote params : ( footnote : Text-No; footnote-to : Text-No; ) ; 15=sub-member params : ( conf-no : Conf-No; pers-no : Pers-No; ) ; ! This person shall not be a member of this conference. 31=sub-recipient params : ( text-no : Text-No; conf-no : Conf-No; ) ; 43=sync ; ; ! Make LysKOM sync its files. This is a privileged call. ! The same effect is achieved by sending UNIX signal USR1 ! to the server process. 56=who-am-i ; session-no : Session-No; 39=who-is-on-old ; result : Who-Info-List-Old; ! Call number 39 has been obsoleted by call number 51, ! the return value of which contains more information. 51=who-is-on ; result : Who-Info-List; ! The return value is a list of information about ! active sessions. ) The RPC calls, where their number is followed by an asterisk *, are obsolete and have been replaced by other calls in the present version (0.33) of the Emacs Lisp client. Number RPC call Number RPC call ------------------------------------------------------ 0 login 1 logout 2 pepsi 3 change-name 4 change-what-i-am-doing 5 create-person 6* get-person-stat-old 7 set-priv-bits 8 set-passwd 9 query-read-texts 10 create-conf 11 delete-conf 12 lookup-name 13* get-conf-stat-old 14 add-member 15 sub-member 16 set-presentation 17 set-conf-motd 18 set-supervisor 19 set-permitted-submitters 20 set-super-conf 21 set-conf-type 22 set-garb-nice 23 get-marks 24 mark-text 25 get-text 26 get-text-stat 27 mark-as-read 28 create-text 29 delete-text 30 add-recipient 31 sub-recipient 32 add-comment 33 sub-comment 34 get-map 35 get-time 36 get-server-info 37 add-footnote 38 sub-footnote 39* who-is-on-old 40 set-unread 41 set-motd-of-lyskom 42 enable 43 sync 44 shutdown 45* broadcast 46 get-membership 47 get-created-texts 48 get-members 49 get-person-stat 50 get-conf-stat 51 who-is-on 52 get-unread-confs 53 send-message 54 get-session-info 55 disconnect 56 who-am-i 57 set-user-area ------------------------------------------------------ Composite data types Here the data types, used in RPC calls from client to server and in asynchronous calls from server to client, are defined. They are presented in alphabetic order. ! Pers-no and Conf-no are unsigned short ints in the same domain. Conf-No ::= INTEGER; Conf-No-List ::= ARRAY Conf-No; ! Used where? Conf-List ::= ARRAY ( conference : Conf-No; type : Conf-Type; ) ! The return value to RPC call 12 has type Conf-List-Old, that can ! not be correctly defined in the grammar used here. The call should ! return a Conf-List, but then we would break compatibility. ! Conf-List-Old: "3 { 3 45 62 } { 1001 0000 1001 }" ! Conf-List: "3 { 3 1001 45 0000 62 1001 }" Conf-Type ::= BITSTRING ( rd_prot; ! Can anyone become a member? original; ! Comments forbidden? secret; ! Secret mailboxes cannot easily login by name letterbox; ! Mailbox ) Conference ::= ( name : HOLLERITH; type : Conf-Type; creation-time : Time; last-written : Time; creator : Pers-No; presentation : Text-No; supervisor : Conf-No; permitted-submitters : Conf-No; ! Zero means anybody super-conf : Conf-No; ! Zero means author msg-of-day : Text-No; ! Every conf has one nice : Garb-Nice; no-of-members : INTEGER; first-local-no : Local-Text-No; ! Oldest text still stored no-of-texts : INTEGER; ! How many texts stored ) Garb-Nice ::= INTEGER; ! Number of days Info ::= ( version : INTEGER; conf-pres-conf : Conf-No; ! Conf. presenting new conferences pers-pres-conf : Conf-No; ! Conf. presenting new persons motd-conf : Conf-No; ! Conf. with all messages of the day kom-news-conf : Conf-No; ! Conf. with news about LysKOM motd-of-lyskom : Text-No; ! Text shown at login ) ! kom-types.h defines Info-Datum as the tail in Misc-Info ! kom-types.h defines Info-Type as the selector in Misc-Info Local-Text-No ::= INTEGER; Mark ::= ( text-no : Text-No; type : INTEGER ) ! The server ignores the type of the mark, ! this is left to the client. Mark-List ::= ARRAY Mark; Member ::= Pers-No; Member-List ::= ARRAY Member; Membership ::= ( last-time-read : Time; conference : Conf-No; priority : INTEGER; last-text-read : Local-Text-No; read-texts : ARRAY Local-Text-No; ) Membership-List ::= ARRAY Membership; Misc-Info ::= SELECTION ( 0=recpt recipient : Conf-No; ! Real recipient 1=cc-recpt cc-recipient : Conf-No; ! Won't receive further comments 2=comm-to comment-to : Text-No; ! We are commenting this text 3=comm-in commented-in: Text-No; ! This text comments us 4=footn-to footnote-to : Text-No; ! We are a footnote to this 5=footn-in footnoted-in : Text-No; ! This is a footnote to us 6=loc-no local-no : Local-Text-No; ! Text No within conference 7=rec-time received-at : Time; ! Time stamp 8=sent-by sender : Pers-No; ! Who added new recipient 9=sent-at sent-at : Time; ! When was new recipient added ! 10=...-recpt ??? ! For Your Information ) Pers-List ::= ARRAY Pers-No; Pers-No ::= Conf-no; Person ::= ( username : HOLLERITH; ! E-mail address privileges : Priv-Bits; flags : Personal-Flags; last-login : Time; ! Or maybe last logout time? user-area : Text-No; total-time-present : INTEGER; ! In seconds sessions : INTEGER; created-lines : INTEGER; created-bytes : INTEGER; read-texts : INTEGER; no-of-text-fetches : INTEGER; created-persons : INTEGER; created-confs : INTEGER; first-created-local-no : INTEGER; ! Well, local isn't really true but... no-of-created-texts : INTEGER; ! Numbers of texts in the ARRAY, ! i.e. not erased ones. no-of-marks : INTEGER; no-of-confs : INTEGER; ) ! /mo Personal-Flags ::= BITSTRING ( unread-is-secret; ! Value 1 means No of unread is secret flg2; flg3; flg4; flg5; flg6; flg7; flg8; ! A lot of unused positions ) ! See section above about security levels and privilege bits Priv-Bits ::= BITSTRING ( wheel; admin; statistic; create_pers; create_conf; change_name; flg7; flg8; flg9; flg10; flg11; flg12; flg13; flg14; flg15; flg16; ! A lot of unused positions ) ! Session-Info is very similar to Who-Info. Session-Info ::= ( person : Pers-No; working-conference : Conf-No; session : Session-No; what-am-i-doing : HOLLERITH; username : HOLLERITH; ! user@host idle-time : INTEGER; ! Seconds since last RPC call connection-time : Time; ! Time and date for connection ! This is not the same as login time ) ! Session numbers are unique to each session. A person can have ! more than one session running at the same time. Session numbers ! are assigned starting from 1 up. Session numbers are not reused ! during the lifetime of the server. See Who-Info-List Session-No ::= INTEGER; Text-List ::= ( first-local-no : Local-Text-No; texts : ARRAY Text-No; ) ! Text-No is a u_long. Text-No ::= INTEGER; Text-Stat ::= ( creation-time : Time; author : Pers-No; no-of-lines : INTEGER; no-of-chars : String-Size; no-of-marks : INTEGER; misc-info : ARRAY Misc-Info; ) ! UNIX struct tm. No time zone. Time ::= ( seconds : INTEGER; ! 0 ... 59 minutes : INTEGER; ! 0 ... 59 hours : INTEGER; ! 0 ... 23 mday : INTEGER; ! 1 ... 31 month : INTEGER; ! Jan = 0 ... Dec = 11 year : INTEGER; ! Since year 1900 weekday : INTEGER; ! Sun = 0 ... Sat = 6 yearday : INTEGER; ! 0 ... 365 isdst : INTEGER; ! positive = DST, 0 = normal time zone ) Who-Info-Old ::= ( person : Pers-No; what-am-i-doing : HOLLERITH; working-conference : Conf-No; ) Who-Info-List-Old ::= ARRAY Who-Info-Old; Who-Info ::= ( person : Pers-No; working-conference : Conf-No; session : Session-No; what-am-i-doing : HOLLERITH; username : HOLLERITH; ! user@hostname ) Who-Info-List ::= ARRAY Who-Info; Example Below is one example from a real LysKOM session. Comments have been added between ! and end of line, as in the grammar above. This example is old and contains some obsolete details. Never the less, it should give an insight into the ``raw'' protocol A. $ telnet kom.lysator.liu.se 4894 Trying 130.236.254.1 ... Connected to lysator.liu.se. Escape character is '^]'. A8Haronsson ! I use protocol A LysKOM ! LysKOM responds 1 12 13HLars Aronsson ! lookup-name =1 2 { 8 110 } { 1001 1001 } ! Person 8 or Person 110 :3 2 21 7 0H ! Person 21 changed to conf 7 :1 1 56 ! Person 56 left LysKOM 2 0 8 8H******** ! login Person 8 with password :3 2 8 0 0H ! Person 8 arrived in LysKOM =2 ! login OK 3 10 23HAntikommunistiskt Forum 0000 ! I create a new conference =3 57 ! OK, conf 57 created 4 1 ! I leave :1 1 8 ! Person 8 left LysKOM =4 ! logout OK Here is a second example, that will prove really useful. The current (October 1992) GNU Emacs Lisp client does not support these operations. Suppose you have a special-purpose LysKOM client that receives e-mail and sends it to a LysKOM conference. At Lysator, we have such a beast. When we send e-mail to <4711@lyskom.lysator.liu.se>, the automated LysKOM person "Postmaster" will enter LysKOM and enter the message with recipient 4711, whoever that might be, a person or a conference. It has become very popular to "import" mailing lists to LysKOM this way. If the mailing list is called "foo-list", then we find it useful to create two conferences, one for the mailing list messages (Foo List) and another one for local discussion (Foo Debate). The first conference is of type "original", so that comments aren't allowed. All comments will appear in the super-conference, which will be the Foo Debate. Suppose you have created Foo List as conference 4711 and Foo Debate as conference 4712 and that Postmaster is person 911. $ telnet kom.lysator.liu.se Trying 130.236.254.1 Connected to lysator.liu.se. Escape character is '^]'. A11HSanta Claus ! I use protocol A LysKOM ! LysKOM responds 0 0 110 8H******** ! login person 110, password =0 ! ok 19 19 4711 911 ! Only Postmaster submits =19 ! to conf 4711 20 20 4711 4712 ! Super conf is conf 4712 =20 ! ok 21 21 4711 0100 ! No comments here, please =21 ! ok 1 1 ! logout =1 ! ok