Chirp Version 1 INTRODUCTION Chirp is a simple and lightweight remote I/O protocol. Each Chirp operation is a remote procedure call from a client to a server. A Chirp operation is initiated by a client, which sends a formatted request. The server acts upon the request and sends a response. For example, in this interaction, a client creates a file for reading and writing, and the server responds with a file descriptor: client: open /tmp/file rwct 511 server: 5 AUTHENTICATION It is assumed that Chirp is carried over a stream protocol such as TCP. The stream itself may uniquely identify the client to the server, in which case authentication is performed before Chirp comes into play. For example, the server might identify the client based upon its IP address or credentials determined by SSL. If desired, client authentication may be done within the context of Chirp itself. Two commands are available for authentication within the protocol, "cookie" and "login". The exact syntax of these commands is given below. The "cookie" command is used to pass a magic string discovered by the client through a covert channel. If the cookie present is what the server expects, then authentication succeeds. The "login" command is a traditional cleartext username and password. Exactly what authentication the server requires is different in every setting. If the user fails to satisfy the server's authentication requirements, then the server is free to return NO_AUTHENTICATION in response to the authentication attempt or any other I/O request. SYNTAX A request consists of an LF-terminated line possibly followed by binary data. At a minimum, a Chirp server must accept requests of 1024 characters. It may accept longer lines. If a line exceeds a server's internal maximum, it must gracefully consume the excess characters and return a TOO_BIG error code, defined below. Certain requests are immediately followed by binary data. The number of bytes is dependent on the semantics of the request, also described below. A request is parsed into words separated by any amount of white space consisting of spaces and tabs. The first word of the request is called the "command" and the rest are called "arguments." Words fall into two categories: strings and decimals. A string is any sequence of non-white-space characters. A string may include a white-space character if it is escaped by a backslash. A single backslash may be represented by a double backslash. A decimal is any sequence of the digits 0-9, optionally prefixed by a single + or -. At the protocol level, words ave no maximum size. They may stretch on to fill any number of bytes. Of course, each implementation has limits on concepts such a file name lengths and integer sizes. If a receiver cannot parse, store, or execute a word contained in a request, it must gracefully consume the excess characters and return a TOO_BIG error response, defined below. A response consists of an LF-terminated line, bearing an ASCII integer. If greater than or equal to zero, the response indicates the operation succeeded. If negative, the operation failed, and the exact value tells why: -1 NOT_AUTHENTICATED The client has not authenticated its identity. -2 NOT_AUTHORIZED The client is not authorized to perform that action. -3 DOESNT_EXIST There is no object by that name. -4 ALREADY_EXISTS There is already an object by that name. -5 TOO_BIG That request is too big to execute. -6 NO_SPACE There is not enough space to store that. -7 NO_MEMORY The server is out of memory. -8 INVALID_REQUEST The form of the request is invalid. -9 TOO_MANY_OPEN There are too many resources in use. -10 BUSY That object is in use by someone else. -11 TRY_AGAIN A temporary condition prevented the request. -12 UNKNOWN An unknown error occurred. Negative values greater than -12 are reserved for future expansion. The receipt of such a values should be interpreted in the same way as UNKNOWN. Error values between -1000 and -1999 inclusive are reserved for site-specific and experimental errors codes. COMMANDS Here are the available commands. Each argument to a command is specified with a type and a name. The valid types are: close Complete access to this file. cookie Authenticate to the server with the given cookie string. fsync Block until all uncommitted changes to this file descriptor have been written to stable storage. login Authenticate to the server with this name and password. lseek Move the current seek pointer of "fd" by "offset" bytes from the base given by "whence." "whence" may be: 0 - from the beginning of the file 1 - from the current seek position 2 - from the end of the file. Returns the current seek position. mkdir Create a new directory by this name. "mode" is interpreted in the same manner as a POSIX file mode. open Open the file named "name." "mode" is interpreted in the same manner as a POSIX file mode. Note that the mode is printed in decimal representation, although the UNIX custom is to use octal. For example, the octal mode 0755, representing readable and executable by everyone would be printed as 493. "flags" may contain any of these characters which affect the nature of the call: r - open for reading w - open for writing a - force all writes to append t - truncate before use c - create if it doesn't exist x - fail if 'c' is given and the file already exists Returns an integer file descriptor which may be used with later calls referring to open files. read Read "length" bytes from the file descriptor "fd." If successful, the server may respond with any value between zero and "length." Immediately following the response will be binary data of exactly as many bytes indicated in the response. If zero, the end of the file has been reached. If any other value is given, no assumptions about the file size may be made. rename Cause the file "oldpath" to be renamed to "newpath". rmdir Delete a directory by this name. unlink Delete the file named "path". version Return the protocol version number implemented by this server. Clients may assume that higher protocol numbers are backwards- compatible with lower protocol numbers. write Write "length" bytes to the file descriptor "fd." This request should be immediately followed by "length" binary bytes. If successful, may return any value between 0 and "length," indicating the number of bytes actually accepted for writing. An efficient server should avoid accepting fewer bytes than requested, by the client must be prepared for this possibility.