Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

%eyre, %iris: Support Websocket #60

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
123 changes: 123 additions & 0 deletions UIPS/UIP-01XX.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
---
uip: "01XX"
title: "%eyre/%iris: Support Websocket"
description: "Support Websocket connections on Eyre/Iris"
author: ~fidwed-sipwyn
status: Draft
type: Standards Track
category: Kernel
created: 2024-04-27
---

## Abstract

This proposal adds Websocket functionality that works in a similar manner to the currently `%eyre`/`%iris` HTTP interface. Users who wish to receive Websocket connections will use the existing `%eyre`'s `%connect` `$task` to bind a URL path where the websocket handshakes will arrive (since they are technically also HTTP requests, this should be intuitive). To initiate a connection, users should pass a `%websocket-connect` `$task` to `%iris`. Once the connection is established, the client/server vanes interaction with the apps occurs through `%gall` pokes, facts and subscriptions.

## Motivation

Websocket support will allow Urbit to interact with a wider variety of systems/protocols.

## Specification
- **%eyre** will have a new `$gift` and a new `$task`:
```hoon
:: $gift
::
:: websocket-reponse: event to earth
::
[%websocket-response event=websocket-event]
:: $task
::
:: receives websocket event from earth
::
[%websocket-event event=websocket-event]
```
- And the following new types:
```hoon
:: +websocket-connection: connection to be store in eyre state
::
+$ websocket-connection
$: app=term
=inbound-request
==
:: +websocket-message: websocket message content
::
+$ websocket-message
$: opcode=@ud
message=(unit data=octs)
==
:: +websocket-event: inbound/outbound websocket event
::
+$ websocket-event
$% [%accept ~]
[%reject ~]
[%disconnect ~]
[%message message=websocket-message]
==
::
```
- **%iris** will have two new `$gift`s and two new `$task`s:
```hoon
:: $gift
::
:: %websocket-handshake: outbound websocket-handshake to earth
::
[%websocket-handshake id=@ud url=@t]
:: %websocket-response: event to earth
::
[%websocket-response id=@ud websocket-event:eyre]
:: $task
::
:: request to open websocket connection
::
[%websocket-connect app=term url=@t]
:: receives websocket event from earth
::
[%websocket-event id=@ud event=websocket-event:eyre]
```
- And a new type:
```hoon
:: +websocket-connection: websocket connection stored in iris state
::
+$ websocket-connection
$: app=term
=duct
id=@ud
url=@t
status=?(%pending %accepted)
==
```
- %eyre will share the `$websocket-message` and `$websocket-event` types with %iris.
- The only new `$task` that the app devs will utilize is the `%websocket-connect` from iris.
- The existing `%cancel-request` `$task` from iris will be modified to also cancel websocket requests.
- Server user flow:
- The user exposes their app with the `%eyre`'s `%connect` `$task`.
- When a handshake comes from earth, `%eyre` subscribes to the app's `/websocket-server/[eyre-id]` path and sends a `%websocket-handshake` poke with `[eyre-id inbound-request]`. The `eyre-id` will be used to represent that particular connection.
- In response to `%websocket-handshake`, the user gives a fact with the `%accept` or `%reject` mark on `/websocket-server/[eyre-id]`.
- After `%accept`ed the app can give `%message`s facts on `/websocket-server/[eyre-id]` and receives messages that comes as `%websocket-server-message`s pokes, containing `[eyre-id websocket-message]`.
- If the subscription is kicked, then the connection is closed, or the user can give a fact with the `%disconnect` mark to close it.
- Client user flow:
- The user sends a request to initiate the connection by passing the `%websocket-connect` `$task` to `%iris` with `[app=term url=@t]`.
- The user can cancel the request by using the `%cancel-request` `$task`.
- If the connection succeeds `%iris` will subscribe to `/websocket-client/id`, with `id` representing that particular connection.
- The app can give facts with the `%message` mark on `/websocket-client/id` and receives messages that comes as `%websocket-client-message`s pokes, containing `[id websocket-message]`.
- If the subscription is kicked, then the connection is closed, or the user can give a fact with the `%disconnect` mark to close it.

## Rationale

The approach followed here is a way to add the intended feature while reutilizing some of the existing logic and without adding a new vane.

## Backwards Compatibility

Backwards compatibility is only affected if there are developers currently handling Websocket handshakes in the `%handle-http-request` poke.

## Reference Implementation

Incoming

## Security Considerations

Similar considerations as the currently HTTP implementation.

## Copyright

Copyright and related rights waived via [CC0](../LICENSE.md).