Inimeg - Reverse Gemini

Speculative specification

v0.1.2, December 29th 2020

reflecting v0.14.3 of the Project Gemini spec

This is document is a very rough sketch of an actual spec for "Inimeg", a.k.a "reverse Gemini". It is by no means finalized and likely to undergo anything from significant changes to outright abandonment in response to feedback. For now, I would not recommend putting anything I've drafted here into code.

Contact

Discussions about this proposal are likely to happen on the Gemini mailing list. I'm happy to take suggestions and corrections by direct email as well.

Gemini mailing list

Contact me directly at <benthor@posteo.de>

Overview

Inimeg is an entirely optional extension of the client-server protocol Gemini, which itself is broadly similar to gopher or HTTP. Inimeg is only meaningful when understood in concert with Gemini.

Project Gemini spec

The Inimeg protocol extension for Gemini is intended as a way for Gemini clients to upload content to Gemini servers in-band, i.e., without reliance on other protocols like FTP, SSH or even dedicated HTML forms.

The Inimeg mechanism allows a Gemini client to temporarily act as a Gemini server, with the Gemini server briefly playing the part of a Gemini client. Entirely within an otherwise standard Gemini transaction, a server and client can agree to swap roles, with the server then waiting for any content that the client may send (i.e., "upload") to the server.

Inimeg strictly follows the Gemini spec and only extends it in three respects.

Inimeg is careful not break or be in conflict with the current Gemini spec. (See top of this document for notes on the Gemini spec version that was taken into consideration when drafting this version of the Inimeg spec.)

Gemini and Inimeg transactions

Vanilla Gemini transactions

Recall that there is just one kind of Gemini transaction, roughly equivalent to a gopher request or a HTTP "GET" request. Per the Gemini spec, transactions in vanilla Gemini happen as follows:

C:   Opens connection
S:   Accepts connection
C/S: Complete TLS handshake
C:   Validates server certificate
C:   Sends Gemini request
S:   Sends Gemini response header, closes connection under non-success conditions
S:   Sends Gemini response body (text or binary data)
S:   Closes connection
C:   Handles response

Project Gemini spec

Successful Inimeg transaction

A successful Inimeg transaction departs from a vanilla Gemini

transaction after Client and Server have indicated their support for

the Inimeg mechanism through usage of the "inimeg://" scheme by the

client and a 7x status code response by the server. It looks like

this:

C:   Opens connection
S:   Accepts connection
C/S: Complete TLS handshake
C:   Validates server certificate
C:   Sends Inimeg client request (a valid Gemini request but using the "inimeg://" scheme)
S:   Sends Inimeg server response (a Gemini request preceded by 7x status code)
C:   Sends Gemini response header, closes connection for non-success headers
C:   Sends Gemini response body (text or binary data, optional)
C:   Closes connection
S:   Handles uploaded content/header

Note that the client is always expected to respond with a Gemini response header like a vanilla Gemini server would before sending any content.

The Inimeg mechanism

Inimeg requests

Inimeg requests are equivalent to Gemini requests, replacing the

gemini:// scheme with the inimeg:// scheme:

<URL><CR><LF>

Inimeg requests MUST include the inimeg:// scheme. Given no explicit scheme, the gemini:// scheme is implied (as per Gemini spec)

Inimeg server responses

Inimeg server responses use the same format as Gemini responses:

<STATUS><SPACE><META><CR><LF>

Inimeg server responses are distinguished from Gemini responses through the status codes. The first digit of Inimeg status codes is an 7. Server implementations SHOULD anticipate that clients MAY immediately close the connection after reading this single byte (or at any later point).

To indicate non-success in response to an Inimeg request, a Gemini server MUST respond with a standard Gemini response-header, for example "61 Certificate Not Authorized".

Generally speaking, a Gemini server MAY respond with an Inimeg status code to a valid Inimeg request. However, a Gemini server MUST NOT respond with an Inimeg status code to any other kind of request.

Inimeg status codes

Any 7x status code indicates ROLE REVERSE. Only the semantics of the <META> line differ. Clients MAY disregard the contents of <META> entirely. <META> can however contain useful information, such as the expected future URL of the uploaded resource.

The second digit in the status code is meant to roughly mirror the

semantics of the corresponding Gemini status code groups. Example: The

<META> part of the 72 status header specifies a desired MIME type for the upload and follows the format of a Gemini "20 SUCCESS" header.

70 GENERIC

<META> is optional and has no defined meaning. Basic implementations need only support this status code. Exact server behaviour is undefined. The uploaded resource may or may not be immediately accessible and may or may not be eventually accessible under the exact URL in the request.

71 META

This status code signals that <META> carries special semantics that require dedicated client support to correctly interpret. In an attempt to mirror the nature of the "1x INPUT" Gemini status code, this spec places no further restrictions on the contents of <META>.

72 SUCCESS

<META> contains the expected MIME media type for the upload. The Inimeg 72 response header corresponds exactly to the Gemini "20 SUCCESS" response header. The server MAY indicate acceptance of generic files for upload by specifying 'application/octet-stream' in accordance with RFC 2045 and RFC 2046

RFC 2045

RFC 2046

73 REDIRECT

<META> contains the expected future gemini:// URL where successfully uploaded content will later be found. The client SHOULD NOT automatically assume Inimeg-accessibility of the resource given in <META>. Instead, the client SHOULD simply proceed with the upload.

74 PROCESSING REQUIRED

This status reflects some of the semantics of the "4x TEMPORARY FAILURE" Gemini status code. It indicates that the uploaded resource will not be immediately made available and needs to be processed first. One typical example for this is user-solicited content that might need moderator approval before publication. <META> can be a user-facing explanation about the exact nature of the delay.

75 DUMMY

This status reflects some of the semantics of the "5x PERMANENT FAILURE" Gemini status code. The server signals that it does not actually implement the Inimeg mechanism but likes to indicate general awareness of Inimegs existence in response to an inimeg:// request. <META> can have arbitrary content, references to teapots are appreciated.

77 REFLECT

<META> SHOULD contain the inimeg:// request rewritten as a gemini:// URL. This status code can be seen as a subset of 73 Redirect, whereby the server signals its readiness to place the incoming file at exactly the requested location.

Optional Gemini status codes

Regular Gemini should not be impacted by the Inimeg mechanism. However, since a "2x SUCCESS" status indicates, well, success, the second digit MAY be used to indicate Inimeg support.

27 UPLOAD ALLOWED

Using this status code, the server signals that it understands the Inimeg mechanism and allows replacing the current resource with one that is uploaded via Inimeg. The server MAY decide to issue this status code only to authenticated clients.

47 CREATION ALLOWED

Using this status code, the server could indicate the absence of a resource that can be added via Inimeg. This error falls within the "4x TEMPORARY FAILURE" rather than the "5x PERMANENT FAILURE" realm, because there is a real chance that the resouce will exist in future, following a successful Inimeg upload.

Notes about Gemini compatibility

Reasonably well-implemented vanilla Gemini servers and clients should

never experience any issues in case one party does have support for

the Inimeg mechanism and the other does not.

Non-successful Inimeg transaction

Generally, a non-successful Inimeg transaction is equivalent to a non-successful vanilla Gemini transaction. The server should respond with a non-success header and close the connection.

Inimeg support only on client-side

No Inimeg-supporting Gemini client should be able to disrupt any vanilla Gemini server: Any attempt of a client to use Inimeg with a Gemini server that does not support the Inimeg mechanism should fail in a backwards-compatible manner.

In case the Gemini server verifies the request URL scheme, this is trivially the case:

C:   Opens connection
S:   Accepts connection
C/S: Complete TLS handshake
C:   Validates server certificate
C:   Sends Inimeg client request (a valid Gemini request but using "inimeg://" as scheme)
S:   Sends Gemini non-success response header (5x, probably 53 or 59) and closes connection

In case the Gemini server response is a success-indicating (2x) header, the server ignored the "inimeg://" scheme. In this case, the client SHOULD just read (and discard) all returned content from the connection until it has been closed by the server. In other words, any vanilla Gemini server implementation that already fails to respond with e.g., "59 BAD REQUEST" to a query with the "inimeg://" scheme should be treated exactly to Gemini spec for the rest of the transaction:

(handshake and validation omitted)
C:   Sends Inimeg client request (a valid Gemini request but using "inimeg://" as scheme)
S:   Sends Gemini success response header
S:   Sends Gemini response body
S:   Closes connection
C:   Discards response

The Gemini spec does not explicitly allow a client to unilaterally close a connection in the middle of a transaction, so the client SHOULD read the entire server response before discarding it.

Inimeg support only on server-side

No Inimeg-supporting Gemini server should negatively affect any Gemini client. The Gemini spec does not specify client behavior in response to 7x codes. For this reason a server MUST NOT send an 7x Inimeg status code in response to any request that does not include the "inimeg://" scheme.

In general, by issuing an "inimeg://" request, a client signals Inimeg support. Sometimes, a buggy client without Inimeg support may still end up issuing an "inimeg://" request to a supporting server (e.g., when following an inimeg:// link). This can cause the server to respond with an Inimeg header and wait for further input from the client. However, even if a client normally has graceful error handling in response to unknown (i.e., Inimeg-) status codes, many Gemini client implementations only start processing server responses once the connection has been terminated by the server. This can easily lead to a dead-lock, where both sides wait for the other side to close the connection. For this reason, the Inimeg-supporting server MUST close the connection after at most 5 seconds of client silence. (Upon parsing a valid Gemini response header from the client, i.e., when a valid Inimeg transaction appears to be under way, the server SHOULD no longer enforce this timeout and wait for the client to finish the transmission and close the connection.)