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:
- Determine the IP address and port at which to connect based on resolution of a DNS service record.
- Open a TCP connection to the selected IP address and port.
- Negotiate an IMPP protocol version.
- Negotiate the features for the IMPP stream, including TLS and compression.
- Authenticate using a domain-specific IM address and password.
- Bind a device to the stream and retrieve presence lists, group chats, and offline messages.
- Activate incoming and outgoing presence for the device.
- Exchange messages with other entities on the network.
- Unbind the device from the stream.
- 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:
- Request, response, error. The client sends a request to the server and the server responds with success or error.
- 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 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
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:
- A 16-bit flags field.
- A 16-bit message family, most significant bit reserved.
- A 16-bit message type, most significant bit reserved.
- A 32-bit sequence number.
- A 32-bit TLV block size.
- 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 . . . | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
The TLV block is REQUIRED to contain a sequence of TLVs in the following format:
- A 16-bit TLV type.
- 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.
- 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:
- LISTS::CONTACT_ADD with sequence 100.
- LISTS::CONTACT_REMOVE with sequence 101.
- 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:
- 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.
- 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.
- 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.
- 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:
- 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".
- 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