OIF - Object Interchange Format spec ------------------------------------ The OIF protocol is intended to be as extensible and simple as possible. OIF consists of two levels, level one deals solely with the definition of single objects, and level two specifies the protocol used to transfer objects between MUDs. Level one OIF can also be used to implement object storage and retrieval. OIF Level 1 - object definition ------------------------------- An object encoded in OIF consists of an object beginning header, a list of object attributes, and an object ending trailer. EG: object /* attribute list */ endobj Individual attributes are stored in printable ascii characters, each ended with a newline. The attribute is preceeded with a type-specifier which can be any number of characters of any type except spaces. Following the type-specifier is the attribute name, also variable-length, ended with an equals sign '='. The attribute name may NOT contain a slash '/' character under any circumstances. The remainder of the line after the equals sign is the attribute data, and is undefined, except that it cannot contain newlines in it. There is no length limit specified on attribute lines, though it is acceptable for an implementation to impose one. An attribute looks like: str name=Jerry Cornelius Where "str" is the attribute's data type, "name" is the attribute's name, and "Jerry Cornelius" is the attributes data. Note that the ending newline is NOT part of the attribute data. Attribute names must be all alpha or numeric characters, with case-sensitivity preserved. Attribute types must also be all alpha or numeric characters, with case-sensitivity preserved. Each named attribute in an OIF object must be unique, IE: there may be only one "name" attribute in an object, regardless of its type. There is no specified limit to the number of attributes an object may have, though a given implementation may impose limits. Since it would be possible to create an OIF-compliant object that would use all the memory available on a given machine, implementations should consider checking for number and size of attributes in some manner. An example OIF object would look like the following: object str name=Jerry Cornelius obj owner=726@someMUD str desc=You see a snobby-looking object, gazing aloofly back at you. cmd peer=@emote "peers down his nose at $1" endobj Object-IDs are encoded in one of 2 forms: local and fully-qualified. Locally-named objects are represented with just a string of numbers that represents the integer ID of the object, EG: 81263 Fully-qualified object-IDs are locally named IDs followed by an '@' character and the name of the object's home MUD. The name of the home MUD MUST be a single alphanumeric string with no spaces, tabs, newlines, etc. The combined length of an object-ID is limited in an implementation dependent manner, but all OIF implementations are expected to correctly handle at least 64-character object-IDs. MUD names should be restricted to 20 characters, maximum. Discussion of OIF Level 1: -------------------------- One important and obvious aspect of OIF-encoded objects is that there is no encoding of the object's ID in the object itself. This is a design decision that has advantages and disadvantages, but the advantages outweigh the disadvantages significantly, as they allow a higher level of object portability by not hardcoding the object ID into the object. There is still the issue of hardcoded object IDs in lists that an object may contain, but within an individual MUD leaving the object ID out of the object makes it somewhat easier to clone objects within a local MUD. Another important consideration in OIF level 1 was the decision to make attributes unique. It would be quite feasible to permit having several attributes with different types share the same name, to permit MUDs to have a variety of different operators tied to a name. This is not ruled out of future versions, but is not permitted in OIF 1.0 because it only serves to further complicate the code that figures out what to do when an objects "ofail" attribute (for example) is invoked. In the initial 1.0 case, there will be only one "ofail" attribute per object, so once it is invoked, figuring out what to do is a matter of examining the type. If there are not only multiple types, but multiple attributes, the decision criteria become more messy. This is open to change. To allow some room for eventual future growth of the protocol, note the specification that attribute names cannot contain a slash character. This is to support eventual further encoding information that may someday be required in attributes - possible uses encompass mode bits, permissions, etc. IE: str foo/readonly=This is a readonly string Note that at present there is no existing code that uses this capability, nor is there server support for it. It's simply there in case it is someday needed. OIF Level 2 - object transport ------------------------------ When a server desires to communicate with another, it opens a connection to the other server in a mode that will cause a timeout if the connection hangs for a significant time. If the connection hangs, the entire transaction is considered to be a failure. Further, at any point during the transaction, either server may sever the connection, which results in a transaction failure. The level 2 OIF transport is even more general purpose, and consists of 3 parts: (each will be discussed in detail) Introduction - The servers establish a connection and identify themselves to eachother's satisfaction. Exchange - The calling server server exchanges a sequence of operations it desires to have executed on the remote server. These operations are stored in internal memory on the remote server and are not executed immediately, until the entire transaction is completed and agreed upon. There is no specified limit to the number of sub-commands that may be ordered in th transaction, but either side can sever the transaction in the middle, if it desires. Sign-Off - The calling server notifies the called server that it is done. This indicates to the called server that it should now "commit" the transaction. The called server may then do any amount of checking on the commands sent, and determine if it is willing to accept the commands. If it is, it performs the requested operations and sends the calling server an OK, otherwise it sends an error code, and an optional line of error text that may explain more about why the transaction failed. Introduction: ------------- When the calling server contacts the server it desires to do business, it connects to a predefined address (it must know it from internal data) and subaddress, and sends a message in the form of: UnterMUD mymudname mymudversion mypassword followed by a newline. The "UnterMUD" string is always the same, and "mymudname" is the name of the calling MUD, "mymudversion" is a string consisting of a numeric value, and an optional '.' and another numeric value (EG: "1.3") encoding the version of the software. The last value "mypassword" occupies the rest of the line and is the password of the local MUD, encrypted with the password of the MUD that is being called. At this point the called MUD may check the port-of-origin, password, version, and may optionally sever the connection without any further explanation at all. If the called MUD is satisfied, it will reply to the calling MUD with an identical line, except where its password is the inverse. The calling MUD may opt to disconnect. If neither MUD has disconnected, the introduction is over. Exchange: --------- The calling MUD now sends a sequence of requests to to the called MUD. At any point the called MUD can simply drop the connection. If the called MUD does not drop connection, it will read a sequence of requests until it gets an "ENDTRANS" message. The length of requests is limited to 1024 bytes. Some of the requests are as follows: OBJECT objectid The OBJECT transaction request indicates that the called server should read a Level 1 OIF encoded object and store it in temporary memory on a transaction list. The object is NOT entered into the permanent database at this point, but is saved until the signoff. The read object should have the given ID. LINKTO toobjectid fromobjectid The LINKTO request indicates that the called server should check permissions to see if an entrance can be linked from toobjectid from fromobjectid. The actual request should be stored for execution during the signoff. Actual use of the fromobjectid is not necessary, but it is included in case it is useful. ADDTO newobjectid oldobjectid Add the new object to the given old object. This is how object movement is implemented. First the object and its contents are sent across, then finally an order to link it into the destination's contents list. ENDTRANS The transaction list is completed. It should now be validated and if it is all valid, executed. Sign-Off: --------- The sign-off phase is pretty straightforward. The called server has completed executing (or failed to validate and execute) the transaction and now returns a message to the caller, and shuts down the connection. The returned message is in the form of a single line, no longer than 1024 bytes, consisting of a single return code, and a leftover string that occupies the rest of the line. The return code is separated with a single space, and no interpretation is performed on the remainder of the line. The possible returned messages are as follows: OK The transaction succeeded and all is well. ERR There is an unspecified error message. EPERM Permission denied. Discussion of OIF Level 2: -------------------------- The main issues in developing the level 2 OIF protocol was to make it as simple as possible, and to prevent the servers from blocking. The commit protocol actually admits the possibility of objects becoming duplicated through a network error. This is life. To make the best use of buffering inherent in TCP/IP, there is no attempt to validate each part of the transaction as it is sent - a simple stream of commands is sent, and if the whole stream is OK, it is executed. The protocol is designed to make it as easy as possible to add new commands, and the inclusion of a version number is intended to help with this. mjr. '91