Skip to content

Euphoria Packet Format

jeremyredhead edited this page Mar 27, 2022 · 25 revisions
Table Of Contents
Packets
Common Components
Client Commands
Asynchronous Packets

Packets

The heim API is transmitted via websocket in units called packets. Each packet is serialized to JSON with UTF-8 encoding for transmission.

Packets originating from the client will always receive a packet from the server in response. If a client sends packets A and B, then the server will always send the response to A before it sends the response to B.

The server may also send packets to the client asynchronously. For example, when a user says something in a room, a packet is broadcast to each other session connected to that room. An asynchronous packet could be transmitted before the response to a client packet is transmitted.

Every packet shares a common top-level structure. Here is a sample ping, sent from the the server to the client on connect.

{
  type: "ping-event",
  data: {
    time: 1428979816,
    next: 1428979846
  }
}

The type, and data fields are common to all packets. The type field specifies the command or event being communicated, and this determines the expected structure of the data field. This packet is an example of an asynchronous packet.

Non-asynchronous packets use an id field:

{
  id: "1",
  type: "send",
  data: {
    content: "hello ezzie!"
  }
}

The id should be given in any packet sent by the client, and its value should be unique in the lifetime of the connection. The server must include the same id when it sends the corresponding response packet, if an id was given.

Common Packet Components

Some common definitions used across many packets.

timestamps

The heim API uses timestamps to synchronize clients and server. These timestamps are long integers containing the number of seconds since the Unix Epoch in the GMT time zone. When sending the server timestamps, the same format is expected.

user

Field Type Description
id string Global id of the user. Will be the same across rooms regardless of display name. Always begins with the string 'agent:'.
name string Name that should be displayed in the user interface.
server_id string Identity of the heim server this user is connected to.
server_era string Internal heim API data.
session_id string Unique id of the users session. Combination of the users id and a per-session-nonce

Sample:

{
  id: "agent:8ed8e41c4771ca4f", 
  name: "Max", 
  server_id: "heim.4", 
  server_era: "00g5fg7f12ww0", 
  session_id: "8ed8e41c4771ca4f-00000210"
}

message

Field Type Description
time timestamp Time when server received the clients' send packet.
id string Id unique to the room that identifies this message.
parent string Id of message this send is a reply to.
sender user User that sent this send.
content string Content of send to display in room.
edited boolean If true, this message has been edited (not implemented).
deleted boolean If true, this message has been deleted (not implemented).

Sample:

{
  time: 1418585715,
  id: "00gd7wc0qgjcw",
  parent: ""
  sender: {
    id: "agent:8ed8e41c4771ca4f", 
    name: "Max", 
    server_id: "heim.4", 
    server_era: "00g5fg7f12ww0", 
    session_id: "8ed8e41c4771ca4f-00000210"
  }, 
  content: "hi!", 
  edited: null, 
  deleted: null
}

Client Commands

The following commands are available to the client:

Type Purpose
ping-reply Respond to a ping from the server.
nick Modify the user's display name for this session.
who Receive a listing of live users in the room.
log Receive the most recent chat history.
send Send a message to the room's chat.
register-account coming soon Create a new account.
login coming soon Log into an account.

ping-reply

Euphoria implements a second layer of pings & ping-replies on top of the system built into websockets. Clients will occasionally receive a [ping-event](#ping-event) and *must* reply with a `ping-reply` or the server will close the connection.
data field Type Description
time timestamp Current time for the client.

Request:

{id: "1", type: "ping-reply", data: {time: 1431519995}}

nick

Use the nick command to change the user's display name, for subsequent messages sent from the user and for subsequent listings of the room. The user will not be allowed to send messages to a room before sending a nick packet.

Request:

{id: "1", type: "nick", data: {name: "Ezzie"}}

Response:

{
  id: "1", 
  type: "nick-reply", 
  data: {
    id: "agent:61ea7b275e1248f5", 
    name: "Ezzie", 
    server_id:"heim.3", 
    server_era:"00g5femcgk0lc", 
    session_id:"373f7e9af9f00b71-00000236"
  }
}

Other users in the room will be notified of your name change. For a detailed description, see nick-event.

who

Use the who command to fetch the current list of live users in the room.

Request:

{id: "2", type: "who"}

Response:

{
  id: "2", 
  type: "who-reply", 
  data: [
    {
      id: "agent:61ea7b275e1248f5",
      name: "Logan", 
      server_id: "heim.3", 
      server_era: "00g5femcgk0lc", 
      session_id: "61ea7b275e1248f5-00000236"
    },
    {
      id: "agent:8ed8e41c4771ca4f", 
      name: "Max", 
      server_id: "heim.4", 
      server_era: "00g5fg7f12ww0", 
      session_id: "8ed8e41c4771ca4f-00000210"
    }
  ]
}

log

Use the log command to fetch the latest n messages from the room's chat.

Request:

{id: "1", type: "log", data: {n: 50, before:"00c97lmxzgq9s"}}

Response:

{
  id: "1",
  type: "log-reply",
  data: [
    {
      time: 1418585715,
      id: "00gd7wc0qgjcw",
      parent: "",
      sender: {
        id: "agent:8ed8e41c4771ca4f", 
        name: "Max", 
        server_id: "heim.4", 
        server_era: "00g5fg7f12ww0", 
        session_id: "8ed8e41c4771ca4f-00000210"
      }, 
      content: "hi!", 
      edited: null, 
      deleted: null
    },
    {
      time: 1418585515,
      id: "00gd7wc7m7z7k",
      parent: "00gd7wc0qgjcw",
      sender: {
        id: "agent:8a55576975ce6e47", 
        name: "Logan", 
        server_id: "heim.3", 
        server_era: "00g5femcgk0lc", 
        session_id: "61ea7b275e1248f5-00000236"
      }, 
      content: "j0!", 
      edited: null, 
      deleted: null
    }]
}

send

Use the send command to send a message to the room's chat.

Request:

Data Field Type Description
content string Content of the send.
parent string If blank, this send will appear at the bottom of the chat. Otherwise, is the id of the send you are replying to.
{id: "1", type: "send", data: {content: "hello ezzie", parent:""}}

Response: See message for field descriptions.

{
  id: "1",
  type: "send-reply",
  data: {
    time: 1418585715,
    id: "00gd6yy9hvksg",
    parent: ""
    sender: {
      id: "agent:4da8fa7375215589",
      name: "Ezzie",
      server_id: "heim.1", 
      server_era: "00g5fdwjzl91c", 
      session_id: "4da8fa7375215589-00000246"},
    content: "hello ezzie",
    edited: null,
    deleted: null
  }
}

The response will also be broadcast to all other users in the room. For details, see send-event

register-account

Coming soon! This section describes a command that isn't available yet.

The register-account command creates a new account. This command can only be used in a session that is not logged in.

To register an account, you must provide a contact address and a password. The contact address is a combination of namespace and id, which taken together provide a unique, verified, secret identity for the account.

Request
Data Field Type Description
namespace string The type of the new account's primary contact address. See the table of supported namespaces below.
id string The new account's primary contact address.
password string A password for the account.
Supported Namespaces
Namespace ID
email An email address. We may contact this address to verify it, send notifications, etc.
{
  id: "1",
  type: "register-account",
  data: {
    namespace: "email",
    id: "[email protected]",
    password: "hunter2"
  }
}
Failure Response (already logged in)
{
  id: "1",
  type: "register-account-reply",
  data: {
    success: false,
    failure_reason: "already logged in"
  }
}
Success Response
{
  id: "1",
  type: "register-account-reply",
  data: {
    success: true,
    account_id: "00khznsawxo1s"
  }
}
{
  type: "bounce-event",
  data: {
    reason: "authentication changed"
  }
}

Notice that you will receive a bounce-event upon successful login. This means that you must reconnect. If you reconnect with the same cookie, your new session will be logged in.

login

Coming soon! This section describes a command that isn't available yet.

The login command logs into an account. This command can only be used in a session that is not logged in.

Request

The request data is the same as for the register-account command (see above).

Data Field Type Description
namespace string The type of the new account's primary contact address. See the table of supported namespaces below.
id string The new account's primary contact address.
password string A password for the account.
{
  id: "1",
  type: "login",
  data: {
    namespace: "email",
    id: "[email protected]",
    password: "123456"
  }
}
Failure response (invalid password)
{
  id: "1",
  type: "login-reply",
  data: {
    success: false,
    reason: "access denied"
  }
}
Success response
{
  id: "1",
  type: "login-reply",
  data: {
    success: true,
    account_id: "00khznsawxo1s"
  }
}
{
  type: "bounce-event",
  data: {
    reason: "authentication changed"
  }
}

Notice that you will receive a bounce-event upon successful registration. This means that you must reconnect. If you reconnect with the same cookie, your new session will be logged into the account just created.

Asynchronous Packets

Type Purpose
ping-event Ping from the server.
snapshot-event History of current room and list of current users.
send-event Message from another user in the room.
nick-event Name change for another user in the room.
join-event A new user joins the room.
part-event A user leaves the room.

These packets are sent by the server, sometimes in response to packets from other clients or packets from your client.

ping-event

Ping events are used by the server to detect clients that have frozen or timed out. They can also be used by clients to detect connection or server failures.
Data Field Type Description
time timestamp Time when this ping was generated.
next timestamp Scheduled time for next ping-event.

Sample:

{
  type: "ping-event",
  data: {
    time: 1428979816,
    next: 1428979846
  }
}

snapshot-event

A snapshot event is sent when a client first connects and acts as a combination log-reply and who-reply packet.

Data Field Type Description
identity string Your clients unique id. This is the same value as id in user.
session_id string Same data as session_id in user.
version string Git hash of the current server build.
listing list of user Current users in this room.
log list of message Up to 50 messages of backlog. Equivalent to calling log.

Sample:

{
  type: "snapshot-event",
  data: {
    identity: "agent:4da8fa7375215589",
    session_id: "4da8fa7375215589-00000246",
    version: "801ea89a4e410b11410eb61c91971439904e66c0",
    listing: [
      {
        id: "agent:61ea7b275e1248f5",
        name: "Logan", 
        server_id: "heim.3", 
        server_era: "00g5femcgk0lc", 
        session_id: "61ea7b275e1248f5-00000236"
      },
      {
        id: "agent:8ed8e41c4771ca4f", 
        name: "Max", 
        server_id: "heim.4", 
        server_era: "00g5fg7f12ww0", 
        session_id: "8ed8e41c4771ca4f-00000210"
      }],
    log:[
      {
        time: 1418585715,
        id: "00gd7wc0qgjcw",
        parent: "",
        sender: {
          id: "agent:8ed8e41c4771ca4f", 
          name: "Max", 
          server_id: "heim.4", 
          server_era: "00g5fg7f12ww0", 
          session_id: "8ed8e41c4771ca4f-00000210"
        }, 
        content: "hi!", 
        edited: null, 
        deleted: null
      },
      {
        time: 1418585515,
        id: "00gd7wc7m7z7k",
        parent: "00gd7wc0qgjcw",
        sender: {
          id: "agent:8a55576975ce6e47", 
          name: "Logan", 
          server_id: "heim.3", 
          server_era: "00g5femcgk0lc", 
          session_id: "61ea7b275e1248f5-00000236"
        }, 
        content: "j0!", 
        edited: null, 
        deleted: null
      }]
  }
}

send-event

For each message sent by a client, Heim will send a send-event packet to the other clients. The sending client will receive a send-reply, which has an identical format. Both these events are a single message with a type field to indicate its context.

{
  type: "send-event",
  data: {
    time: 1418585715,
    id: "00gd6yy9hvksg",
    parent: ""
    sender: {
      id: "agent:4da8fa7375215589",
      name: "Ezzie",
      server_id: "heim.1", 
      server_era: "00g5fdwjzl91c", 
      session_id: "4da8fa7375215589-00000246"},
    content: "hello ezzie",
    edited: null,
    deleted: null
  }
}

nick-event

The server sends a nick-event to all clients in the same room as a user who changes their name. The sending client will receive a nick-reply.

Data Field Type Description
to string New display name for user.
from string Previous display name for user.
id string See user.
server_id string See user.
server_era string See user.
session_id string See user.
{
  type: "nick-event",
  data: {
    id: "agent:61ea7b275e1248f5", 
    to: "Ezzie", 
    from: "Logan", 
    server_id: "heim.3", 
    server_era: "00g5femcgk0lc", 
    session_id: "373f7e9af9f00b71-00000236"
  }
}

join-event

A join-event is sent when a client joins a room. The data field contains the user who has entered the room.

The client does not have to choose a name before joining a room, so the name field may be empty.

Sample:

{
  type: "join-event",
  data: {
    id: "agent:61ea7b275e1248f5", 
    name: "Logan", 
    server_id: "heim.3", 
    server_era: "00g5femcgk0lc", 
    session_id: "373f7e9af9f00b71-00000236"
  }
}

part-event

A part-event is sent when a client leaves a room or times out. The data field contains the user who has left the room.

Sample:

{
  type: "part-event",
  data: {
    id: "agent:61ea7b275e1248f5", 
    name: "Logan", 
    server_id: "heim.3", 
    server_era: "00g5femcgk0lc", 
    session_id: "373f7e9af9f00b71-00000236"
  }
}