Instant Messaging and Presence Protocol

Table of Contents

1.   Introduction
2.   Protocol Summary
2.1.   Overview
2.2.   Server Discovery
3.   Message Structure
3.1.   Overview
3.2.   Start Byte
3.3.   Channels
   3.3.1.   Version
   3.3.2.   TLV
   3.3.2.1.   Message Sequencing
   3.3.2.2.   Message Flags
   3.3.2.3.   Message Families
   3.3.2.4.   Message Types
   3.3.2.5.   TLV Types
   3.3.2.6.   Errorcodes
4.   TLV Messages
4.1.   STREAM
   4.1.1.   FEATURES_SET
   4.1.1.1.   Request
   4.1.1.2.   Response
   4.1.1.3.   Error
   4.1.2.   AUTHENTICATE
   4.1.2.1.   Request
   4.1.2.2.   Response
   4.1.2.3.   Error
   4.1.3.   PING
   4.1.3.1.   Request
   4.1.3.2.   Response
   4.1.3.3.   Error
4.2.   DEVICE
   4.2.1.   BIND
   4.2.1.1.   Request
   4.2.1.2.   Response
   4.2.1.3.   Error
   4.2.2.   UPDATE
   4.2.2.1.   Request
   4.2.2.2.   Response
   4.2.2.3.   Indication
   4.2.2.4.   Error
   4.2.3.   UNBIND
   4.2.3.1.   Request
   4.2.3.2.   Response
   4.2.3.3.   Indication
   4.2.3.4.   Error
4.3.   LISTS
   4.3.1.   GET
   4.3.1.1.   Request
   4.3.1.2.   Response
   4.3.1.3.   Error
   4.3.2.   CONTACT_ADD
   4.3.2.1.   Request
   4.3.2.2.   Response
   4.3.2.3.   Indication
   4.3.2.4.   Error
   4.3.3.   CONTACT_REMOVE
   4.3.3.1.   Request
   4.3.3.2.   Response
   4.3.3.3.   Indication
   4.3.3.4.   Error
   4.3.4.   CONTACT_AUTH_REQUEST
   4.3.4.1.   Request
   4.3.4.2.   Response
   4.3.4.3.   Error
   4.3.5.   CONTACT_APPROVE
   4.3.5.1.   Request
   4.3.5.2.   Response
   4.3.5.3.   Indication
   4.3.5.4.   Error
   4.3.6.   CONTACT_APPROVED
   4.3.6.1.   Indication
   4.3.7.   CONTACT_DENY
   4.3.7.1.   Request
   4.3.7.2.   Response
   4.3.7.3.   Indication
   4.3.7.4.   Error
   4.3.8.   ALLOW_ADD
   4.3.8.1.   Request
   4.3.8.2.   Response
   4.3.8.3.   Indication
   4.3.8.4.   Error
   4.3.9.   ALLOW_REMOVE
   4.3.9.1.   Request
   4.3.9.2.   Response
   4.3.9.3.   Indication
   4.3.9.4.   Error
   4.3.10.   BLOCK_ADD
   4.3.10.1.   Request
   4.3.10.2.   Response
   4.3.10.3.   Indication
   4.3.10.4.   Error
   4.3.11.   BLOCK_REMOVE
   4.3.11.1.   Request
   4.3.11.2.   Response
   4.3.11.3.   Indication
   4.3.11.4.   Error
4.4.   GROUP_CHATS
   4.4.1.   SET
   4.4.1.1.   Request
   4.4.1.2.   Response
   4.4.1.3.   Indication
   4.4.1.4.   Error
   4.4.2.   GET
   4.4.2.1.   Request
   4.4.2.2.   Response
   4.4.2.3.   Error
   4.4.3.   MEMBER_ADD
   4.4.3.1.   Request
   4.4.3.2.   Response
   4.4.3.3.   Indication
   4.4.3.4.   Error
   4.4.4.   MEMBER_REMOVE
   4.4.4.1.   Request
   4.4.4.2.   Response
   4.4.4.3.   Indication
   4.4.4.4.   Error
   4.4.5.   MESSAGE_SEND
   4.4.5.1.   Request
   4.4.5.2.   Response
   4.4.5.3.   Indication
   4.4.5.4.   Error
4.5.   IM
   4.5.1.   OFFLINE_MESSAGES_GET
   4.5.1.1.   Request
   4.5.1.2.   Response
   4.5.1.3.   Error
   4.5.2.   OFFLINE_MESSAGE_DELETE
   4.5.2.1.   Request
   4.5.2.2.   Response
   4.5.2.3.   Error
   4.5.3.   MESSAGE_SEND
   4.5.3.1.   Request
   4.5.3.2.   Response
   4.5.3.3.   Indication
   4.5.3.4.   Error
4.6.   PRESENCE
   4.6.1.   SET
   4.6.1.1.   Request
   4.6.1.2.   Response
   4.6.1.3.   Indication
   4.6.1.4.   Error
   4.6.2.   GET
   4.6.2.1.   Request
   4.6.2.2.   Response
   4.6.2.3.   Error
   4.6.3.   UPDATE
   4.6.3.1.   Indication
4.7.   AVATAR
   4.7.1.   SET
   4.7.1.1.   Request
   4.7.1.2.   Response
   4.7.1.3.   Indication
   4.7.1.4.   Error
   4.7.2.   GET
   4.7.2.1.   Request
   4.7.2.2.   Response
   4.7.2.3.   Error
   4.7.3.   UPLOAD
   4.7.3.1.   Request
   4.7.3.2.   Response
   4.7.3.3.   Error
Appendix A.   TLV Message Reference
   A.1.   General
   A.2.   STREAM
   A.3.   DEVICE
   A.4.   LISTS
   A.5.   GROUP_CHATS
   A.6.   IM
   A.7.   PRESENCE
   A.8.   AVATAR

1. Introduction

We started building our own IM protocol at Cerulean Studios back in 2001. At the time, our ambitions were twofold: we wanted a way to protect ourselves against being blocked by other IM providers while also opening the door to in-house innovations like Trillian's "continuous client" feature. Today, what we creatively refer to as our "instant messaging and presence protocol", or IMPP, is used by Trillian customers as the protocol that powers our fully-featured IM network. In an effort to promote interoperability between instant messaging providers, we've decided to open the protocol to the public. Some of IMPP's strong points include:

  • A TLV-based binary protocol.
  • Authorization-based contact lists: only users you approve can track your presence.
  • Capability-based messaging: devices can be shielded from unsupported message types.
  • Capability-based offline messaging: devices will only retrieve messages of supported message types.
  • Clients are required to use TLS and may optionally utilize DEFLATE-based compression.
  • Extendable: Trillian-specific extensions for continuous client, cloud history, and more.
  • Leverage of existing standards when applicable: TLS, SIP, ICE, TURN, RTP, etc.
  • Invisibility with allow and block lists.
  • Intelligent presence: idle and mobile devices are tracked to determine the best status to advertise.
  • Multi-device awareness: state and messages are shared between all connected devices.
  • Server-backed, persistent group chats.
  • User avatars.

2. Protocol Summary

2.1. Overview

IMPP is a binary protocol that works by establishing a TCP connection to an IMPP server, authenticating with that server, and then exchanging messages with that server in order to reach other clients. Over the years, best efforts have been made to keep the protocol flow reasonably compatible with XMPP with the long term idea of enabling federation between IMPP and XMPP servers. As such, the general flow of an IMPP session somewhat mirrors that of XMPP:

  1. Determine the IP address and port at which to connect based on resolution of a DNS service record.
  2. Open a TCP connection to the selected IP address and port.
  3. Negotiate an IMPP protocol version.
  4. Negotiate the features for the IMPP stream, including TLS and compression.
  5. Authenticate using a domain-specific IM address and password.
  6. Bind a device to the stream and retrieve presence lists, group chats, and offline messages.
  7. Activate incoming and outgoing presence for the device.
  8. Exchange messages with other entities on the network.
  9. Unbind the device from the stream.
  10. Close the TCP connection.

2.2. Server Discovery

Server discovery is done via DNS SRV lookups. For example, to find the server associated with the IM address tricia@trillian.im, a client MUST construct a DNS SRV query with a service of "impp", a protocol of "tcp", and a name that corresponds to the domain of the IMPP service to be connected to; for example, "_impp._tcp.trillian.im". The standard IMPP port is 3158, but servers SHOULD also listen on ports 80 and 443. For compatibility with firewalls and proxies, connections over port 443 MUST be treated like pure HTTPS connections, meaning that clients MUST immediately begin - and complete - a TLS negotiation before any IMPP-specific communication occurs.

3. Message Structure

3.1. Overview

IMPP messages consist of an 8-bit start byte, an 8-bit channel, and channel-specific data. All integers sent over IMPP are unsigned and sent in network byte (big endian) order. The normal flow of messages between clients and servers can be defined in one of two ways:

  1. Request, response, error. The client sends a request to the server and the server responds with success or error.
  2. Indication. The server sends a stateless "indication" to the client when it has information to send; the client does not reply.

3.2. Start Byte

All messages MUST begin with the IMPP start byte 0x6f.

3.3. Channels

There are two possible channels that messages can be sent over: the version channel (0x01) and the TLV channel (0x02).

3.3.1. Version

The version channel is used to negotiate an acceptable protocol version between the client and server. Version messages contain a 16-bit version value and nothing else. The current protocol version is 8.

 0             7 0             7 0             7 0             7
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|   Start Byte  |    Channel    |            Version            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 1: Version Channel

3.3.2. TLV

The TLV (type, length, value) channel is the main channel for IMPP communication. TLV messages begin with a 14 byte header followed by an arbitrarily-sized TLV block. Headers consist of:

  1. A 16-bit flags field.
  2. A 16-bit message family, most significant bit reserved.
  3. A 16-bit message type, most significant bit reserved.
  4. A 32-bit sequence number.
  5. A 32-bit TLV block size.
  6. A (block-size) TLV block.
 0             7 0             7 0             7 0             7                
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|               |               |                       |E|E|I|R|
|   Start Byte  |    Channel    |          Flags        |X|R|N|S|
|               |               |                       |T|R|D|P|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|R|            Family           |R|            Type             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                           Sequence                            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                         TLV Block Size                        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                                                               |
.                                                               .
.                           TLV Block                           .
.                                                               .
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 2: TLV Channel

The TLV block is REQUIRED to contain a sequence of TLVs in the following format:

  1. A 16-bit TLV type.
  2. A variably-sized length field, either 16 or 32 bits. The method of determining the size of the length field is defined under Section 3.3.2.5.
  3. A (length) sized value field.

3.3.2.1. Message Sequencing

TLV messages are sequenced and MUST be sent in sequenced order. Messages received by the server are processed in per-family FIFO order. The sequence value itself starts at a random value and is incremented by one for every message regardless of family. For example, a client may send three messages:

  1. LISTS::CONTACT_ADD with sequence 100.
  2. LISTS::CONTACT_REMOVE with sequence 101.
  3. PRESENCE::SET with sequence 102.

In this example, the server will process the first request, hold the second request until it's finished with the first, and process the third request immediately. Once the server responds to request 100, (which may involve backend communication with a database, thereby requiring a wait period) it is then allowed to continue processing messages within the LISTS family. Responses from the server can therefore come out-of-order. Clients MUST store the sequence associated with a message and be prepard to act on its response at any time.

3.3.2.2. Message Flags

The 16-bit flags field determines what type of message is being sent and whether or not the message is a domain-specific extension. There are four types of messages:

  1. A request. If the response, indication, and error bits are all set to 0, the message is a request. Requests are the only type of messages sent by clients to servers.
  2. A response. Responses are sent from server to client and are always tied to a particular request. The sequence number of a response will correspond to the request the response belongs to.
  3. An indication. Indications are "server-initiated" messages not tied to any particular client request. The sequence number of an indication will always be set to 0.
  4. An error. Errors are typically tied to a particular request but MAY be stateless. The sequence number will either be 0 or the sequence number of the request that resulted in an error.

3.3.2.3. Message Families

The most significant bit of a message family value is reserved. The allowable range of values for families is therefore 0-32767. Within that range:

  • The values from 0-16383 are reserved for the core IMPP protocol.
  • The values from 16384-32767 are reserved for extensions and are not defined as a part of the core IMPP protocol. Clients and servers MUST mark all messages from extended families with the extension bit.

3.3.2.4. Message Types

The most significant bit of a message type value is reserved. The allowable range of values for types is therefore 0-32767. Within that range:

  • The values from 0-16383 are reserved for the core IMPP protocol.
  • The values from 16384-32767 are reserved for extensions and are not defined as a part of the core IMPP protocol. Clients and servers MUST mark all messages of extended types with the extension bit.

3.3.2.5. TLV Types

TLV types are defined within the scope of a family. Types will therefore exist across families and can only be understood in conjunction with their family. This helps keep the type values from growing indefinitely and keeps similar types clumped together as the protocol matures.

The most significant bit of a TLV type determines whether or not the length field to follow is 16 or 32 bits in length. When the most significant bit is set to 0, the length field to follow will be 16 bits in size. When the most significant bit is set to 1, the length field to follow will be 32 bits in size. Because the most significant bit of a TLV type is reserved, the allowable range of values for TLV types is 0-32767. Within that range:

  • The values from 0-16383 are reserved for the core IMPP protocol.
  • The values 16384-32767 are reserved for extensions and are not defined as a part of the core IMPP protocol.

3.3.2.6. Errorcodes

When a client sends a request and that request fails, the server MUST respond with an error. All errors sent by the server MUST include the special errorcode TLV with type 0x0000 and a 16-bit errorcode value. There are two types of errorcodes in IMPP:

  1. Global errorcodes. A global errorcode is typically indicative of something fundamentally wrong with the stream, user, or server itself. Global errorcodes can be sent in response to any type of request from any family. An example of a global errorcode is "internal error".
  2. Local errorcodes. A local errorcode is similar to a TLV type in that it exists within the scope of a particular family and is specific to that family only. An example of a local errorcode is "contact already exists".

The most significant bit of an errorcode value is used to mark errorcodes as global or local. When the most significant bit is set to 1, the errorcode is local. Because the most significant bit of an errorcode is reserved, the allowable range of values for errorcodes is 0-32767. Within that range:

  • The values from 0-16383 are reserved for the core IMPP protocol.
  • The values 16384-32767 are reserved for extensions and are not defined as a part of the core IMPP protocol.

4. TLV Messages

4.1. STREAM

The stream family facilitates stream feature negotiation, authentication, and optional "keepalive" pings. After connecting to a server and negotiating an IMPP protocol version, a client MUST begin by negotiating stream features. All Trillian clients and servers MUST use TLS and MAY use compression.

4.1.1. FEATURES_SET

4.1.1.1. Request

0000    6f 02 00 00 00 01 00 01     00 00 00 01 00 00 00 06
0010    00 01 00 02 00 03

4.1.1.2. Response

If the server agrees with the requested features, it MUST respond with the agreed upon features for the stream. Clients MUST NOT assume that the features they've requested will be enabled; rather, they MUST parse the response from the server to know what features will be enabled for the stream.

4.1.1.3. Error

4.1.2. AUTHENTICATE

4.1.2.1. Request

Once the stream features have been negotiated, a client MUST authenticate itself with the server. This document defines the MECHANISM_PASSWORD mechanism as used by Trillian. In this case, the password is sent after securing the stream with TLS.

0000    6f 02 00 00 00 01 00 02     00 00 00 01 00 00 00 1c
0010    00 02 00 02 00 01 00 03     00 06 74 72 69 63 69 61
0020    00 03 00 08 70 61 73 73     77 6f 72 64

4.1.2.2. Response

4.1.2.3. Error

4.1.3. PING

4.1.3.1. Request

Periodically, but not more than once every 60 seconds, clients MAY send ping requests to the server.

0000    6f 02 00 00 00 01 00 03     00 00 00 01 00 00 00 00

4.1.3.2. Response

4.1.3.3. Error

4.2. DEVICE

After stream negotiation and authentication, clients begin the process of "device negotiation". The first step in negotiating a device is to attempt to "bind" it to the newly-negotiated stream. Device binding allows the client to send its client software information, capabilities, statistics about the device name and type, and desired initial presence status (for example, when signing on as invisible) to the server. The device properties can be updated later. Clients can unbind their devices when they are ready to disconnect from the server, and can also use the unbind request to disconnect other connected devices.

4.2.1. BIND

4.2.1.1. Request

0000    6f 02 00 00 00 02 00 01     00 00 00 01 00 00 00 78
0010    00 01 00 08 54 72 69 6c     6c 69 61 6e 00 02 00 07
0020    57 69 6e 64 6f 77 73 00     04 00 04 69 33 38 36 00
0030    05 00 03 35 2e 33 00 06     00 02 31 31 00 08 00 0a
0040    53 54 41 52 53 43 52 45     41 4d 00 0b 00 02 00 01
0050    00 10 00 01 00 00 0d 00     12 00 01 42 04 00 02 42
0060    09 42 03 42 06 42 05 42     07 42 08 00 07 00 19 54
0070    72 69 6c 6c 69 61 6e 2f     57 69 6e 64 6f 77 73 20
0080    35 2e 33 2e 30 2e 31 31

4.2.1.2. Response

The server MUST respond to a bind request upon success. Device names MAY be changed by the server for any or no reason. Whether a device name is changed by the server or not, the server MUST send the assigned device name in its response to the client. In the event that the client software reported by the client is outdated, the server MAY suggest an alternate version and/or build for the client to use. The method in which a client chooses to utilize this information to optionally update itself is outside the scope of this document.

4.2.1.3. Error

In the event that the server cannot bind the client device to the stream, it MUST return an error and disconnect the client. The most common error cases are when the server needs to redirect the client to another server or when the client software is unsupported by the server. If the the client is being redirected to another server, it MUST immediately disconnect from the current server and begin the connection process over again (starting with an IMPP version exchange and so on) with the server address supplied in the error message.

4.2.2. UPDATE

4.2.2.1. Request

Clients MAY wish to periodically update the server with new device properties. For example, device capabilities, idle status, and mobile status may change during the course of a session.

0000    6f 02 00 00 00 02 00 02     00 00 00 01 00 00 00 1d
0010    00 0d 00 12 00 01 42 04     00 02 42 09 42 03 42 06
0020    42 05 42 07 42 08 00 0e     01 00 0f 00 01

4.2.2.2. Response

4.2.2.3. Indication

In the event that a device updates one or more properties, the server MUST send an indication to any other connected devices with the latest properties for the newly-updated device. In this way, a mobile device can know that another non-idle desktop device exists and can choose to suppress push notifications, as one example. Indications of this type will contain information for ALL connected devices, not just the device being updated.

4.2.2.4. Error

4.2.3. UNBIND

4.2.3.1. Request

If a client wishes to disconnect itself or another device under its control, it MUST send an unbind request to do so. Unbind requests may be targetted to a specific device by including the device name in the request. The lack of a device name in the unbind request means the client wishes to disconnect all OTHER devices but itself.

0000    6f 02 00 00 00 02 00 03     00 00 00 01 00 00 00 00

4.2.3.2. Response

If a client is unbinding itself, the server MUST send a response and disconnect the client.

4.2.3.3. Indication

If a client is unbinding another connected device, the server MUST send an indication to the device being unbound and disconnect the device.

4.2.3.4. Error

4.3. LISTS

The lists family controls the addition and removal of list objects, including the management of authorization requests, authorization approvals, and authorization denials. The four types of list objects currently supported are contact, pending contact, allow, and block.

4.3.1. GET

4.3.1.1. Request

After successfully binding a device to the stream, the client MUST request its lists from the server.

0000    6f 02 00 00 00 03 00 01     00 00 00 01 00 00 00 00

4.3.1.2. Response

Upon success, the server MUST send a response containing all of the client's list objects. List objects are currently sent in the following order: contact, pending, allow, block. Note: After the server sends list objects to the client, the server MUST send any pending incoming authorization requests to the user. These authorization requests will come in as CONTACT_AUTH_REQUEST indications.

0000    6f 02 00 01 00 03 00 01     00 00 00 01 00 00 00 18
0010    00 03 00 07 63 6f 6e 74     61 63 74 00 04 00 07 70
0020    65 6e 64 69 6e 67 00 05     00 05 61 6c 6c 6f 77 00
0030    06 00 05 62 6c 6f 63 6b

4.3.1.3. Error

4.3.2. CONTACT_ADD

4.3.2.1. Request

0000    6f 02 00 00 00 03 00 02     00 00 00 01 00 00 00 20
0010    00 01 00 06 74 72 69 63     69 61 00 02 00 06 7a 61
0020    70 68 6f 64 00 08 00 08     4e 69 63 6b 6e 61 6d 65

4.3.2.2. Response

Upon success, the server MUST send a response containing the TO and FROM TLVs. Success means that the contact is now on the client's pending contact list. Presence will NOT be delivered for this contact until the contact approves the add request. The server MUST deliver an authorization request to the newly-added contact after sending a success response to the client.

4.3.2.3. Indication

If a contact is successfully added, servers MUST send indications to other connected devices informing them of the change to their list.

4.3.2.4. Error

4.3.3. CONTACT_REMOVE

4.3.3.1. Request

0000    6f 02 00 00 00 03 00 03     00 00 00 01 00 00 00 14
0010    00 01 00 06 74 72 69 63     69 61 00 02 00 06 7a 61
0020    70 68 6f 64

4.3.3.2. Response

4.3.3.3. Indication

If a contact is successfully removed, servers MUST send indications to other connected devices informing them of the change to their list.

4.3.3.4. Error

4.3.4. CONTACT_AUTH_REQUEST

4.3.4.1. Request

In the event that an add request has not been responded to, clients MAY choose to resend their requests to the contact they are attempting to add.

0000    6f 02 00 00 00 03 00 04     00 00 00 01 00 00 00 14
0010    00 01 00 06 74 72 69 63     69 61 00 02 00 06 7a 61
0020    70 68 6f 64

4.3.4.2. Response

4.3.4.3. Error

4.3.5. CONTACT_APPROVE

4.3.5.1. Request

0000    6f 02 00 00 00 03 00 04     00 00 00 01 00 00 00 14
0010    00 01 00 06 7a 61 70 68     6f 64 00 02 00 06 74 72
0020    69 63 69 61

4.3.5.2. Response

4.3.5.3. Indication

If a contact is successfully approved, servers MUST send indications to other connected devices informing them of the approval. Clients can use this indication to remove any user interface elements relating to the incoming authorization request.

4.3.5.4. Error

4.3.6. CONTACT_APPROVED

4.3.6.1. Indication

After a client approves an incoming add request, the approved indication is sent to the user whose request was just approved.

4.3.7. CONTACT_DENY

4.3.7.1. Request

0000    6f 02 00 00 00 03 00 07     00 00 00 01 00 00 00 14
0010    00 01 00 06 7a 61 70 68     6f 64 00 02 00 06 74 72
0020    69 63 69 61

4.3.7.2. Response

4.3.7.3. Indication

If a contact add request is successfully denied, servers MUST send indications to other connected devices informing them of the denial.

4.3.7.4. Error

4.3.8. ALLOW_ADD

4.3.8.1. Request

The addition of a user to the allow list means that the user will be able to see the client when it goes invisible to others.

0000    6f 02 00 00 00 03 00 08     00 00 00 01 00 00 00 14
0010    00 01 00 06 7a 61 70 68     6f 64 00 02 00 06 74 72
0020    69 63 69 61

4.3.8.2. Response

4.3.8.3. Indication

If an allow add request is successful, servers MUST send indications to other connected devices informing them of the change to their list.

4.3.8.4. Error

4.3.9. ALLOW_REMOVE

4.3.9.1. Request

0000    6f 02 00 00 00 03 00 09     00 00 00 01 00 00 00 14
0010    00 01 00 06 7a 61 70 68     6f 64 00 02 00 06 74 72
0020    69 63 69 61

4.3.9.2. Response

4.3.9.3. Indication

If an allow remove request is successful, servers MUST send indications to other connected devices informing them of the change to their list.

4.3.9.4. Error

4.3.10. BLOCK_ADD

4.3.10.1. Request

The addition of a user to the block list means that the user will no longer be able to see the presence of the client. In addition, the client will no longer be able to see the presence of the user it is blocking.

0000    6f 02 00 00 00 03 00 0a     00 00 00 01 00 00 00 14
0010    00 01 00 06 7a 61 70 68     6f 64 00 02 00 06 74 72
0020    69 63 69 61

4.3.10.2. Response

4.3.10.3. Indication

If an block add request is successful, servers MUST send indications to other connected devices informing them of the change to their list.

4.3.10.4. Error

4.3.11. BLOCK_REMOVE

4.3.11.1. Request

0000    6f 02 00 00 00 03 00 0b     00 00 00 01 00 00 00 14
0010    00 01 00 06 7a 61 70 68     6f 64 00 02 00 06 74 72
0020    69 63 69 61

4.3.11.2. Response

4.3.11.3. Indication

If an block remove request is successful, servers MUST send indications to other connected devices informing them of the change to their list.

4.3.11.4. Error

4.4. GROUP_CHATS

Group chats are server-stored and persist between connections. A member of a group chat is therefore a permanent member until it chooses to leave the chat. As a result, both online and offline contacts can be added to group chats.

4.4.1. SET

4.4.1.1. Request

A client wishing to start a new group chat must first request a new chat from the server.

0000    6f 02 00 00 00 07 00 01     00 00 00 01 00 00 00 00

4.4.1.2. Response

On success, the response to a set request will contain the newly-assigned group chat name. Clients can now add members to the new chat.

4.4.1.3. Indication

If the group chat set request is successful, servers MUST send indications to other connected devices informing them of the new chat.

4.4.1.4. Error

4.4.2. GET

4.4.2.1. Request

0000    6f 02 00 00 00 07 00 02     00 00 00 01 00 00 00 00

4.4.2.2. Response

4.4.2.3. Error

4.4.3. MEMBER_ADD

4.4.3.1. Request

0000    6f 02 00 00 00 07 00 03     00 00 00 01 00 00 00 41
0010    00 01 00 06 7a 61 70 68     6f 64 00 02 00 29 23 33
0020    35 30 64 34 38 33 65 61     61 63 34 31 38 66 31 66
0030    37 64 66 38 38 66 39 34     37 35 63 64 61 39 31 62
0040    34 30 66 36 63 37 63 00     03 00 06 74 72 69 63 69
0050    61

4.4.3.2. Response

4.4.3.3. Indication

4.4.3.4. Error

4.4.4. MEMBER_REMOVE

4.4.4.1. Request

0000    6f 02 00 00 00 07 00 04     00 00 00 01 00 00 00 41
0010    00 01 00 06 7a 61 70 68     6f 64 00 02 00 29 23 33
0020    35 30 64 34 38 33 65 61     61 63 34 31 38 66 31 66
0030    37 64 66 38 38 66 39 34     37 35 63 64 61 39 31 62
0040    34 30 66 36 63 37 63 00     03 00 06 7a 61 70 68 6f
0050    64

4.4.4.2. Response

4.4.4.3. Indication

4.4.4.4. Error

4.4.5. MESSAGE_SEND

4.4.5.1. Request

0000    6f 02 00 00 00 07 00 05     00 00 00 01 00 00 00 82
0010    00 01 00 06 7a 61 70 68     6f 64 00 02 00 29 23 33
0020    35 30 64 34 38 33 65 61     61 63 34 31 38 66 31 66
0030    37 64 66 38 38 66 39 34     37 35 63 64 61 39 31 62
0040    34 30 66 36 63 37 63 00     05 00 3f 3c 48 54 4d 4c
0050    3e 3c 42 4f 44 59 20 42     47 43 4f 4c 4f 52 3d 22
0060    23 66 66 66 66 66 66 22     3e 3c 66 6f 6e 74 20 6c
0070    61 6e 67 3d 22 45 4e 22     3e 68 65 79 3c 2f 42 4f
0080    44 59 3e 3c 2f 48 54 4d     4c 3e

4.4.5.2. Response

When a group chat message is successfully delivered to all members, the server MUST send a response to the client.

4.4.5.3. Indication

Indications will be sent to ALL members of a group chat, including the client that sends the message. The reason for this is to allow the server to assign an authoritative timestamp to the message before sending it to group chat members. Clients must therefore be prepared to receive messages from themselves and avoid rendering the message twice.

4.4.5.4. Error

4.5. IM

The IM family exposes basic instant messaging, including the management of offline messages. All messages are tied to a 16-bit capability value. The idea behind capabilities is to allow clients to extend basic instant messaging to new forms (for example, handwriting messages) without worrying about confusing or breaking older clients. The IMPP protocol spec defines two core capability blocks: 0x0001 for IMs and 0x0002 for typing notifications.

4.5.1. OFFLINE_MESSAGES_GET

4.5.1.1. Request

0000    6f 02 00 00 00 04 00 01     00 00 00 01 00 00 00 00

4.5.1.2. Response

If offline messages exist, one or more will be returned in the response. In addition, a timestamp value representing the most recent message will be included in the response. Clients MUST delete offline messages by sending this timestamp back to the server. Because the server may utilize offline messaging in ways that are hidden to clients, this timestamp value may not be related to any of the actual offline messages returned to the client and should therefore be stored separately.

4.5.1.3. Error

4.5.2. OFFLINE_MESSAGES_DELETE

4.5.2.1. Request

0000    6f 02 00 00 00 04 00 02     00 00 00 01 00 00 00 0c
0010    00 08 00 08 00 00 00 00     00 00 00 00

4.5.2.2. Response

4.5.2.3. Error

4.5.3. MESSAGE_SEND

4.5.3.1. Request

0000    6f 02 00 00 00 04 00 03     00 00 00 01 00 00 00 89
0010    00 01 00 06 7a 61 70 68     6f 64 00 02 00 06 74 72
0020    69 63 69 61 00 04 00 04     00 00 00 00 00 05 00 04
0030    00 00 00 3f 00 06 00 3f     3c 48 54 4d 4c 3e 3c 42
0040    4f 44 59 20 42 47 43 4f     4c 4f 52 3d 22 23 66 66
0050    66 66 66 66 22 3e 3c 66     6f 6e 74 20 6c 61 6e 67
0060    3d 22 45 4e 22 3e 68 65     79 3c 2f 42 4f 44 59 3e
0070    3c 2f 48 54 4d 4c 3e 00     03 00 02 00 01 00 07 00
0080    08 00 00 01 3c 1a df 2b     23

4.5.3.2. Response

If the server was able to deliver the message to at least one recipient device, it MUST send a response to the client.

4.5.3.3. Indication

Incoming instant messages will arrive as indications from the sender to the receiver. As of this writing, the servers are NOT sending indications of outgoing messages to other connected devices. Trillian clients are currently using an internal continuous client extension to relay outgoing messages to other devices; this will be amended in a future version of the protocol.

0000    6f 02 00 02 00 04 00 03     00 00 00 00 00 00 00 32
0010    00 01 00 03 6b 77 6b 00     03 00 02 00 01 00 06 00
0020    05 68 65 6c 6c 6f 00 05     00 04 00 00 00 05 00 04
0030    00 04 00 00 00 00 00 07     00 08 00 00 01 3f 3e 55
0040    60 30

4.5.3.4. Error

If the server was unable to deliver the message to ANY recipient devices, it MUST send an error to the client.

4.6. PRESENCE

The presence family controls device presence, including the nuances of synchronizing presence between devices.

4.6.1. SET

4.6.1.1. Request

Presence set requests include status, status message, and whether or not the status is considered "automatic". Most IM clients offer the option to set you away after a period of inactivity; however, this only makes sense in a single device environment. To help solve this, IMPP requires that all presence be tagged as automatic or non-automatic. Automatic presence statuses are confined to the device that sets them, while non-automatic presence statuses are propagated to other devices. If a user requests the status "Away" with the message "Out To Lunch", for example, it will propagate everywhere. If a computer automatically requests the status "Away" with the message "Away Since 9:06 AM", for example, it will only be applied to the device that sets it. In addition, the server will intelligently determine what status and status message to export based on a number of additional factors, including the idle and mobile states of other connected devices.

0000    6f 02 00 00 00 05 00 01     00 00 00 01 00 00 00 14
0010    00 03 00 02 00 01 00 04     00 05 4c 75 6e 63 68 00
0020    05 00 01 00

4.6.1.2. Response

4.6.1.3. Indication

If a non-automatic status is set by a client, the server MUST send an indication to other connected devices informing them of their new presence status. Note that SET indications are NOT used to inform clients of the presence of their contacts; UPDATE indications are used for this purpose.

4.6.1.4. Error

4.6.2. GET

4.6.1.1. Request

0000    6f 02 00 00 00 05 00 02     00 00 00 01 00 00 00 00

4.6.1.2. Response

4.6.1.3. Error

4.6.3. UPDATE

4.6.3.1. Indication

When the status of a user changes, the server MUST send an update indication to all other users who currently have the changed user on their contact lists. Presence update indications can therefore come at any time.

0000    6f 02 00 02 00 05 00 03     00 00 00 00 00 00 00 1d
0010    00 06 00 14 ec 41 e5 64     49 0b 4c ad 5a 5c 2e b2
0020    ce 07 04 f0 34 4c 7f 07     00 07 00 03 73 6d 77 00
0030    03 00 02 00 01 00 08 00     04 00 01 00 02

4.7. AVATAR

The avatar family allows clients to set, get, and upload avatars for display to other clients. Avatars are identified by their SHA-1 hash, which is included in all outgoing presence indications once successfully set. Clients are expected to set new avatars first by sending the SHA-1 hash of the avatar to the server; if the server needs the avatar, it will send a "not found" error to the client. The client should then upload the avatar to the server. The server will automatically set the avatar for the client after a successful upload.

4.7.1. SET

4.7.1.1. Request

4.7.1.2. Response

4.7.1.3. Indication

4.7.1.4. Error

4.7.2. GET

4.7.2.1. Request

4.7.2.2. Response

4.7.2.3. Error

4.7.3. UPLOAD

4.7.3.1. Request

4.7.3.2. Response

4.7.3.3. Error

A. TLV Message Reference

A.1. General

/* Message flags.
 */

#define MF_REQUEST          0x0000
#define MF_RESPONSE         0x0001
#define MF_INDICATION       0x0002
#define MF_ERROR            0x0004
#define MF_EXTENSION        0x0008

/* Global error codes.
 */

enum TErrorcode
{
    SUCCESS                 = 0x0000,
    SERVICE_UNAVAILABLE     = 0x0001,
    INVALID_CONNECTION      = 0x0002,
    INVALID_STATE           = 0x0003,
    INVALID_TLV_FAMILY      = 0x0004,
    INVALID_TLV_LENGTH      = 0x0005,
    INVALID_TLV_VALUE       = 0x0006
};

/* User statuses.
 */

#define USER_STATUS_OFFLINE     0
#define USER_STATUS_ONLINE      1
#define USER_STATUS_AWAY        2

/* DND doesn't work yet.
 */

#define USER_STATUS_DND         3
#define USER_STATUS_INVISIBLE   4

/*
 * Mobile can't be set by clients; the server exports it automatically when a
 * mobile device is considered "most available".
 */

#define USER_STATUS_MOBILE      5

A.2. STREAM

namespace StreamTypes
{

#define FEATURE_NONE        0x00
#define FEATURE_TLS         0x01
#define FEATURE_COMPRESSION 0x02

#define MECHANISM_PASSWORD  0x01

enum TFamily
{
    STREAM                  = 0x0001
};

enum TType
{
    FEATURES_SET            = 0x0001,
    AUTHENTICATE            = 0x0002,
    PING                    = 0x0003
};

enum TErrorcode
{
    FEATURE_INVALID         = 0x8001,
    MECHANISM_INVALID       = 0x8002,
    AUTHENTICATION_INVALID  = 0x8003
};

enum TTupleType
{
    ERRORCODE               = 0x0000,
    FEATURES                = 0x0001,
    MECHANISM               = 0x0002,
    NAME                    = 0x0003,
    TIMESTAMP               = 0x0004
};

}

A.3. DEVICE

namespace DeviceTypes
{

enum TFamily
{
    DEVICE                  = 0x0002
};

enum TType
{
    BIND                    = 0x0001,
    UPDATE                  = 0x0002,
    UNBIND                  = 0x0003
};

enum TErrorcode
{
    CLIENT_INVALID          = 0x8001,
    DEVICE_COLLISION        = 0x8002,
    TOO_MANY_DEVICES        = 0x8003,
    DEVICE_BOUND_ELSEWHERE  = 0x8004
};

enum TTupleType
{
    ERRORCODE               = 0x0000,
    CLIENT_NAME             = 0x0001,
    CLIENT_PLATFORM         = 0x0002,
    CLIENT_MODEL            = 0x0003,
    CLIENT_ARCH             = 0x0004,
    CLIENT_VERSION          = 0x0005,
    CLIENT_BUILD            = 0x0006,
    CLIENT_DESCRIPTION      = 0x0007,
    DEVICE_NAME             = 0x0008,
    IP_ADDRESS              = 0x0009,
    CONNECTED_AT            = 0x000a,
    STATUS                  = 0x000b,
    STATUS_MESSAGE          = 0x000c,
    CAPABILITIES            = 0x000d,
    IS_IDLE                 = 0x000e,
    IS_MOBILE               = 0x000f,
    IS_STATUS_AUTOMATIC     = 0x0010,
    SERVER                  = 0x0012,
    DEVICE_TUPLE            = 0x0013
};

}

A.4. LISTS

namespace ListsTypes
{

#define MAX_OBJECTS         1000

enum TFamily
{
    LISTS                   = 0x0003
};

enum TType
{
    GET                     = 0x0001,
    CONTACT_ADD             = 0x0002,
    CONTACT_REMOVE          = 0x0003,
    CONTACT_AUTH_REQUEST    = 0x0004,
    CONTACT_APPROVE         = 0x0005,
    CONTACT_APPROVED        = 0x0006,
    CONTACT_DENY            = 0x0007,
    ALLOW_ADD               = 0x0008,
    ALLOW_REMOVE            = 0x0009,
    BLOCK_ADD               = 0x000a,
    BLOCK_REMOVE            = 0x000b
};

enum TErrorcode
{
    LIST_LIMIT_EXCEEDED     = 0x8001,
    ADDRESS_EXISTS          = 0x8002,
    ADDRESS_DOES_NOT_EXIST  = 0x8003,
    ADDRESS_CONFLICT        = 0x8004,
    ADDRESS_INVALID         = 0x8005
};

enum TTupleType
{
    ERRORCODE               = 0x0000,
    FROM                    = 0x0001,
    TO                      = 0x0002,
    CONTACT_ADDRESS         = 0x0003,
    PENDING_ADDRESS         = 0x0004,
    ALLOW_ADDRESS           = 0x0005,
    BLOCK_ADDRESS           = 0x0006,
    AVATAR_SHA1             = 0x0007,
    NICKNAME                = 0x0008
};

}

A.5. GROUP_CHATS

namespace GroupChatsTypes
{

enum TFamily
{
    GROUP_CHATS             = 0x0007
};

enum TType
{
    SET                     = 0x0001,
    GET                     = 0x0002,
    MEMBER_ADD              = 0x0003,
    MEMBER_REMOVE           = 0x0004,
    MESSAGE_SEND            = 0x0005
};

enum TErrorcode
{
    MEMBER_NOT_CONTACT      = 0x8001,
    MEMBER_ALREADY_EXISTS   = 0x8002
};

enum TTupleType
{
    ERRORCODE               = 0x0000,
    FROM                    = 0x0001,
    NAME                    = 0x0002,
    MEMBER                  = 0x0003,
    INITIAL                 = 0x0004,
    MESSAGE                 = 0x0005,
    TIMESTAMP               = 0x0006,
    GROUP_CHAT_TUPLE        = 0x0007
};

}

A.6. IM

namespace IMTypes
{

/* IMPP capability blocks.
 */

#define CAPABILITY_IM       0x0001
#define CAPABILITY_TYPING   0x0002

enum TFamily
{
    IM                      = 0x0004
};

enum TType
{
    OFFLINE_MESSAGES_GET    = 0x0001,
    OFFLINE_MESSAGES_DELETE = 0x0002,
    MESSAGE_SEND            = 0x0003
};

enum TErrorcode
{
    USERNAME_BLOCKED        = 0x8001,
    USERNAME_NOT_CONTACT    = 0x8002,
    INVALID_CAPABILITY      = 0x8003
};

enum TTupleType
{
    ERRORCODE               = 0x0000,
    FROM                    = 0x0001,
    TO                      = 0x0002,
    CAPABILITY              = 0x0003,
    MESSAGE_ID              = 0x0004,
    MESSAGE_SIZE            = 0x0005,
    MESSAGE_CHUNK           = 0x0006,
    CREATED_AT              = 0x0007,
    TIMESTAMP               = 0x0008,
    OFFLINE_MESSAGE         = 0x0009
};

}

A.7. PRESENCE

namespace PresenceTypes
{

enum TFamily
{
    PRESENCE                = 0x0005
};

enum TType
{
    SET                     = 0x0001,
    GET                     = 0x0002,
    UPDATE                  = 0x0003
};

enum TTupleType
{
    ERRORCODE               = 0x0000,
    FROM                    = 0x0001,
    TO                      = 0x0002,
    STATUS                  = 0x0003,
    STATUS_MESSAGE          = 0x0004,
    IS_STATUS_AUTOMATIC     = 0x0005,
    AVATAR_SHA1             = 0x0006,
    NICKNAME                = 0x0007,
    CAPABILITIES            = 0x0008
};

}

A.8. AVATAR

namespace AvatarTypes
{

#define MAX_AVATAR_SIZE     65535

enum TFamily
{
    AVATAR                  = 0x0006
};

enum TType
{
    SET                     = 0x0001,
    GET                     = 0x0002,
    UPLOAD                  = 0x0003
};

enum TErrorcode
{
    AVATAR_NOT_FOUND        = 0x8001
};

enum TTupleType
{
    ERRORCODE               = 0x0000,
    FROM                    = 0x0001,
    TO                      = 0x0002,
    AVATAR_SHA1             = 0x0003,
    DATA                    = 0x0004
};

}

Last updated: June 13, 2013

Changed: 4.3.1.2, 4.5.3.3, 4.6.3.1, A.1