Naptify Guild Protocol 1.0 (Draft)

This document is a translation. The Japanese version is the authoritative text; where the two differ, the Japanese version prevails. This document is licensed under CC BY-ND 4.0. Anyone is free to implement this specification, and no royalties are charged.

0. About This Document

Item Description
Extension name Naptify Guild Protocol (NGP for short; written “Guild” in English)
Version Document: 1.0 draft (2026-09-26); protocol version: 1
Publisher The Naptify project
Published at https://naptify.net/ (fixed per-version URLs are not yet decided)
Conformance Conforms to the public documentation of the OpenNap protocol [NAP] (§1)
Applicability Can be implemented by any OpenNap-family server that implements the client-facing [NAP] messages whose payloads this document reuses (§1.1). The server needs to implement neither the 8000-series server links nor the OpenNap server-to-server messages (the 10010 series)
Relationship to existing links Independent. It neither uses nor changes the 8000 series (SlavaNap-style links) or the OpenNap server-to-server messages. It can coexist on the same listening port (§6.1). A link and a Guild are not established between the same two servers at the same time

What a Guild is. A Guild is a mechanism by which OpenNap servers run by different owners connect directly, one to one, to peers that they have registered with each other.

  • Relayed: chat, IMs, presence, browsing, searching, the arrangement of file transfers, and wallops.
  • Not shared: registered users, bans, levels, points, and restrictions.
  • Each server is responsible only for the users logged in to that server.

1. What Is Conformed To and What Is Added

1.1 Points of Conformance

  • Framing. Follows the format of [NAP] §2: a 4-byte header consisting of a 2-byte length and a 2-byte type, both little-endian, followed by the payload.
  • String format. Follows [NAP] §2.
  • Fields are separated by a single space (0x20).
  • Values that may contain spaces are enclosed in ".
  • No CR or LF is appended at the end of the line.
  • The meaning of existing messages is not changed. The payloads of the following messages are carried inside messages defined by this document, in their [NAP] format as is.
  • 200, 201 (search request and result)
  • 203, 204, 206 (download request, acknowledgment, and error)
  • 205 (IM, in its server-to-client form)
  • 211, 212, 213 (browse)
  • 403, 406, 407, 410 (channel message, join, part, and topic)
  • 501 (acknowledgment across a firewall)
  • 609 (upload refusal)
  • 627 (wallop, in its server-to-client form)
  • 824 (emote)
  • No new messages are sent to clients. Peer servers’ users are presented to clients using existing messages only.

1.2 Additions Specific to This Extension

  • The allocation of types 9000–9199 and their meanings (§5–§13).
  • Mutual authentication, version and capability negotiation, presence synchronization, display-name rules, request IDs, and reason codes for disconnection and refusal.
  • Specifying UTF-8 as the character encoding of Guild message payloads (§4.2).

1.3 What This Document Does Not Specify

  • The procedures between clients and servers (as in [NAP]).
  • The 8000-series links.
  • The client-to-client transfers themselves (as in [NAP] §5).

2. Terminology and Key Words

Term Meaning
Server A server that accepts OpenNap clients
Peer A server that has been mutually registered as a Guild
Guild connection A single authenticated TCP connection with a peer
Initiator / acceptor The side that opened / accepted that TCP connection
Local users Users logged in to that server as clients
Peer users Local users of a peer server who have been announced through presence (§8). Identified by the pair of user name and origin
Origin The name of the server that created a message
Display name The name under which a peer user is shown to local users (§8.3)
Capability A short word indicating that an optional feature is implemented (§6.5)
Key A secret byte string shared in advance by the operators of the two servers (§6.4)
Request ID A number that ties a search or browse request to its responses (§11)

The key words follow RFC 2119 and RFC 8174 [RFC2119][RFC8174] and correspond to the wording of the Japanese original as follows.

Wording in the Japanese original Key word
しなければならない MUST
してはならない MUST NOT
すべきである SHOULD
すべきでない SHOULD NOT
してもよい MAY

3. Overall Architecture

  1. Direct connections only. Each server connects directly only to the peers it has registered. – A server MUST NOT forward presence, messages, or requests received from a peer to any other peer or to any other server-to-server procedure (such as links). – Because nothing is forwarded, the connections are allowed to form loops. – When A and B, and B and C, are Guilds, nothing is exchanged between A and C. For A and C to communicate, A and C form a Guild directly.
  2. Announce only your own users. Presence MUST announce local users only.
  3. Send events, not commands. – What a message carries is the result of something a local user did (spoke, joined, and so on). – This extension has no commands that change the state of peer users or of servers. – The receiver MUST NOT change its local users or the information it stores on the grounds of a peer’s level.
  4. Rules are applied by the server where the user is. – Muting, flood limits, download conditions, and so on are applied, before sending, by the server the user is logged in to. – The receiver MAY, at its own discretion, stop delivery to its local users.

4. Common Rules for Messages

4.1 Framing

+--------+--------+--------+--------+----------------+
| len lo | len hi | typ lo | typ hi | payload (len)  |
+--------+--------+--------+--------+----------------+
  • len and typ are unsigned 16-bit little-endian integers.
  • The receiver MUST accept payloads of up to 65535 bytes.
  • The big-endian form MUST NOT be used.

4.2 Character Encoding

  • Guild message payloads MUST be UTF-8. A message containing invalid UTF-8 MUST be discarded, and the receiver MAY return 9007 (reason 6).
  • A server that talks to its clients in another encoding (CP932, CP1252, etc.) converts to UTF-8 before sending to the Guild, and converts received data to its clients’ encoding.
  • Names, channel names, and file names containing characters that cannot be represented in the local clients’ encoding MUST NOT be shown with those characters replaced by ? or the like. They are treated as undisplayable (that user or that result is not shown to that client).
  • Note on round-tripping file names (informative). A file name sent by a CP932 client is normally a byte string that Windows produced by converting from Unicode, so converting it to UTF-8 and back to CP932 yields the same byte string. The exception is a file name that contains a character having two encodings (some of the NEC-selected IBM extended characters and NEC special characters) in its non-standard encoding. Such a name turns into a different byte string after the round trip, so a download across the Guild can fail.

4.3 Field Types

Type Format
srv Server name. ASCII letters, digits, ., -, and _ only; 1–63 bytes. Compared after conversion to ASCII lowercase
nick User name. 1–255 bytes in UTF-8. Does not contain a space (U+0020), ", or control characters (U+0000–U+001F, U+007F)
ch Channel name. 1–255 bytes in UTF-8. Does not contain a space (U+0020), ", or control characters (U+0000–U+001F, U+007F)
token Printable ASCII characters, not containing a space. 1–255 bytes
int Non-negative decimal integer. No leading zeros (except for 0 itself). The upper limit is given for each field. In messages after the handshake is complete, a value exceeding its upper limit is treated as a format error (reason 6 in §14). During the handshake (9000–9003), §6.2 applies
hex Lowercase hexadecimal
md5 Same as the md5 field of [NAP] 204 and 501. Carried as is, without changing the value
qstr A string enclosed in ". Does not contain "
abbr Server abbreviation. A short name that each server’s operator configures for their own server. 1–16 characters counted in Unicode code points, and no more than 64 bytes in UTF-8. Does not contain a space, ", (, ), or control characters. If none is configured, - is sent
rest Everything from that position to the end of the payload. May contain spaces. Used only for the last field
body(N) The payload of [NAP] message N, as is. Always placed last
  • User names are compared treating only ASCII uppercase and lowercase letters as equal; everything else is compared byte by byte.
  • If an implementation, under its own rules, treats a broader set of names as equal (such as full-width letters), it MUST also treat names it considers equal in that way as the same name.

4.4 The Origin Field

  • Messages concerning users (9010 and above) carry the origin srv as their first field.
  • In version 1, the origin MUST be the same as the name of the peer on the connection (as authenticated in §6).
  • A message whose origin differs SHOULD be discarded, with 9007 (reason 14) returned. If this recurs, the receiver MAY close the connection with 9006 (12).

4.5 Verifying the Actor

  • When a message contains the name of a peer user as its actor (the speaker, the IM sender, the requester, the downloader, the uploader, or the wallop sender), the receiver MUST verify that the name is present in that peer’s presence.
  • If it is not, the message is discarded (reason 13).

4.6 Ordering and Unknown Messages

  • The receiver MUST process messages in the order received.
  • Unknown types within 9000–9199 MUST be ignored. The receiver MAY return 9007 (reason 8).
  • Types outside that range arriving on a Guild connection MUST also be ignored.
  • Messages of types 9000–9199 arriving on a client connection MUST NOT be treated as Guild messages. The only exception is the first 9000 before login (§6.1).

5. Number Allocation

Range Use
9000–9007 Connection, authentication, keepalive, disconnection (§6, §7)
9010–9012 Presence (§8)
9020–9024 Channels (§9)
9030–9031 IM (§10)
9040–9043 Browsing and cancellation (§11)
9050–9052 Search (§11)
9060–9064 Transfers (§12)
9070 Wallop (§13)
Gaps between the above, 9080–9099 Spare for version 1.x
9100–9189 Reserved for future versions
9190–9199 For implementers’ testing. Never formally allocated. MUST NOT be sent unless the peer has agreed

6. Connection and Handshake

6.1 Distinguishing Connections

  • The initiator opens a TCP connection to the peer’s OpenNap listening port and sends 9000 as the first frame.
  • The acceptor distinguishes connections by the type of the first frame before login.
  • 9000: a Guild handshake.
  • An existing link message (8000, etc.): a link.
  • Anything else: a client.
  • The payload of 9000 MUST begin with the ASCII string GUILD. If it does not, the acceptor closes the connection with 9006 (reason 2).
  • An operator MAY open a separate port dedicated to the Guild.

6.2 Flow

Initiator I                                           Acceptor A
  | 9000 GUILD <vmin> <vmax> <nameI> <nI> <capsI> <abbrI>  --> |  check that I is a registered peer
  |  <-- 9001 <ver> <nameA> <nA> <capsA> <abbrA>               |
  | 9002 <proofI>  -->                                         |  verify proofI
  |  <-- 9003 <proofA>                                         |
  | verify proofA                                              |
  |======= both sides send their presence lists (§8.2) ========|
  • The entire handshake MUST be completed within 30 seconds. If it is exceeded, either side MAY close the connection with reason 2.
  • If any message other than 9000–9003 and 9006 is received before the handshake is complete, the connection is closed with 9006 (reason 2).
  • If a message containing a format error or a value exceeding its upper limit is received during the handshake (9000–9003), the connection is closed with 9006 (reason 2).

6.3 Messages

No. Name Direction Fields and types Behavior on receipt
9000 GUILD_HELLO Initiator→acceptor token "GUILD", int lowest version (max 65535), int highest version (max 65535), srv initiator name, hex nI (32 digits, 128 bits), token capabilities, abbr abbreviation Check in the following order. ① If the format is wrong, 9006 (2). ② If the name is not registered, 9006 (4). ③ If the registration is a link, 9006 (10). ④ If it has been disabled, 9006 (7). ⑤ If there is no common version, 9006 (3). ⑥ If none of the above applies, return 9001
9001 GUILD_CHALLENGE Acceptor→initiator int chosen version (max 65535), srv acceptor name, hex nA (32 digits), token capabilities, abbr abbreviation If the acceptor name differs from the name of the peer as registered locally, 9006 (12). The initiator MUST verify that the chosen version is within the range it sent in 9000. If it is not, 9006 (3). If neither applies, return 9002
9002 GUILD_AUTH Initiator→acceptor hex proofI (64 digits) Compare in constant time. If it does not match, 9006 (5). If it matches, return 9003 and consider the connection established
9003 GUILD_WELCOME Acceptor→initiator hex proofA (64 digits) If it does not match, 9006 (5). If it matches, the connection is established
  • nI and nA MUST be generated from a cryptographically secure random source. The same value MUST NOT be used twice.

6.4 Computing the Proof

input = "GUILD1" SP role SP nameI SP nameA SP nI SP nA SP ver SP capsI SP capsA SP abbrI SP abbrA
proof = hex( HMAC-SHA256( key, input ) )
  • The role is initiator for proofI and acceptor for proofA.
  • Names are converted to ASCII lowercase. Capabilities use the exact spelling that was sent. SP is a single space.
  • Abbreviations are used as the exact byte strings (UTF-8) that were sent.
  • HMAC follows [RFC2104], and SHA-256 follows [FIPS180-4].
  • The key is a byte string of at least 16 bytes (32 bytes recommended), shared by the operators of the two servers outside this extension.
  • It SHOULD be exchanged as a hexadecimal string.
  • The key itself MUST NOT be carried in any message.
  • Because the capabilities are part of the input, tampering that strips capabilities from the list in transit causes the proof to fail.

6.5 Versions and Capabilities

  • A version is an integer. The acceptor chooses the highest version common to both sides’ ranges.
  • Capabilities are written as comma-separated words. If there are none, - is used.
Capability Meaning Required
(none) Presence (§8) and §7 Required
chat §9 Optional
im §10 Optional
browse Browsing in §11 Optional
search Searching in §11 Optional
xfer §12 Optional
wallop §13 Optional
  • The usable capabilities are only those present on both sides.
  • Messages for a feature that is not usable MUST NOT be sent. If received, they are ignored, and the receiver MAY return 9007 (8).
  • Unknown words MUST be ignored. tls is a reserved word and has no meaning in version 1.

6.6 Two Connections to the Same Peer

When there are two established connections to the same peer, both sides apply the same rule and close one of them with 9006 (6).

  • If both were opened by the same side, the newer one is kept.
  • If they were opened in opposite directions, the connection whose initiator name (as a lowercase byte string) is smaller is kept.

6.7 Example (Test Vectors)

Conditions: – key = 000102…1e1f (32 bytes) – I = alpha.example, A = beta.example – nI = 00112233445566778899aabbccddeeff, nA = ffeeddccbbaa99887766554433221100 – capsI = chat,im,search,browse,xfer,wallop, capsA = chat,im,wallop – Abbreviations: A for I, B for A – Version 1

Messages: – The 9000 header is 5c 00 28 23. The payload is GUILD 1 1 alpha.example 00112233445566778899aabbccddeeff chat,im,search,browse,xfer,wallop A (92 bytes). – The 9001 header is 40 00 29 23. The payload is 1 beta.example ffeeddccbbaa99887766554433221100 chat,im,wallop B (64 bytes). – proofI = 3fa063c1f3b56d9bcc22f3dd8bd942f606038d557714597425705abdb3cb7854 – proofA = 4b4c7e994c54f19a840baae11aa721e59669a35c6a3921ab7f70e83c356d2d79

(Values computed with Python’s hmac and hashlib. To be verified again with an independent implementation before publication.)

7. Keepalive, Errors, and Disconnection

No. Name Direction Fields and types Behavior on receipt
9004 GUILD_PING Both rest cookie (ASCII, 32 bytes or less) MUST return 9005 with the same cookie
9005 GUILD_PONG Both rest cookie Record that the peer is alive
9006 GUILD_CLOSE Both int reason (table below; max 255), rest description (optional) Close the TCP connection without replying, and log it. Reconnect according to §7.1
9007 GUILD_ERROR Both int target type (max 65535), int reason (§14; max 255), rest description (optional) Informational only; the connection is kept. Log it
  • If nothing has been sent for 60 seconds, a server SHOULD send 9004.
  • If nothing has been received for 180 seconds, a server MAY close the connection with 9006 (8).

Disconnection reasons

No. Meaning Automatic reconnection
1 Normal termination (operator action, shutdown) Wait at least 30 minutes
2 Protocol violation (format, ordering, handshake timeout) Not until an operator intervenes
3 Version mismatch No
4 Name not registered as a peer No
5 Authentication failure No
6 Duplicate connection (the connection kept under §6.6 is used) No
7 The peer has been disabled by the operator No
8 Keepalive timeout Yes, with increasing intervals
9 Resource limit (send queue overflow, presence count limit) Yes, with increasing intervals
10 Kind mismatch (this peer is registered as a link) No
11 Restart (expected to return shortly) Yes, starting after 30 seconds
12 Name mismatch (peer name, origin) No

7.1 Reconnection

  • “With increasing intervals” means starting at 30 seconds and doubling each time, up to a maximum of 10 minutes.
  • A side disconnected for a reason marked “No” SHOULD NOT reconnect automatically.

7.2 Send Queue Overflow

  • Presence messages and channel join/part messages MUST NOT be dropped. If they cannot be sent, the connection is closed with 9006 (9).
  • Search and browse results MAY be dropped. However, the end message MUST NOT be dropped. Whether it is sent follows the rules in §11.

8. Presence

8.1 Messages

No. Name Direction Fields and types Behavior on receipt
9010 GUILD_USER Both srv origin, nick name, int login time (UNIX seconds, UTC; max 2^63−1), token level (User, Moderator, Admin, Elite, Leech), int share count (max 4294967295), int speed (0–10), qstr client, int flags (max 4294967295) Add the presence entry. If the same name from the same peer already exists, replace its fields. If the login time has changed, treat it as the user having left and come back. Determine the display name according to §8.3
9011 GUILD_USER_QUIT Both srv origin, nick name Remove that presence entry. Also remove all of that user’s channel memberships and send 407 to local users. The hotlist 210 is also sent at this point
9012 GUILD_SYNC_END Both srv origin, int number of 9010 messages sent (max 4294967295) The initial list is considered complete. If the number does not match the number of 9010 messages received, the receiver MAY log it. The connection is kept
  • Levels are for display only. The receiver MUST NOT use levels for authorization decisions.
  • Flags: bit 0 (value 1) means “do not list”. The receiver MUST NOT show this user in lists, channel member lists, or whois. Unknown bits are ignored.
  • If qstr client contains ", the sender removes it.
  • IP addresses and data ports are not included in presence. They appear only in transfers (§12) and search results (the 201 payload).

8.2 The Initial List

Once the connection is established, each side sends the following, in this order.

  1. 9010 for every local user.
  2. If the capability chat has been negotiated, 9020 (joins of all members) and 9024 (topic) for the shared channels.
  3. Finally, 9012.
  • Messages of any other kind MUST NOT be sent before 9012.
  • When the connection is lost, the receiver MUST remove all of that peer’s presence entries and channel memberships.

8.3 How Names Are Displayed

Peer users are identified by the pair of user name and origin. Users with the same user name may be present on different servers at the same time. No user is disconnected or refused login on account of the Guild (except as in item 3 below).

  1. Names that do not collide are displayed as is. If a peer user’s name is not the same as any of the following, it is shown to local users under that name as is. – The name of a local user (currently logged in) – A name registered on the local server (even if that user is offline) – The name of another peer user already being displayed as is
  2. Colliding names are qualified with the origin. If the name is the same as any of the above, it MUST be displayed with the origin attached. – The recommended form is name(origin) (e.g., masa(guild-b.example)). The parentheses are ASCII ( and ), which clients using any character encoding can represent. – A peer user MUST NOT be displayed under the same name as a local user or a registered name, as is. This is to prevent impersonation. – An implementation MAY always display the origin-qualified form, including when there is no collision. – @ SHOULD NOT be used as the separator. Users commonly use @ as part of their names. – Instead of the origin, the implementation MAY use the abbreviation the peer announced in the handshake (abbr in §4.3). Example: masa(B). However, an abbreviation that falls under any of the following MUST NOT be used; the server name is used instead.
    • - (not configured)
    • The same as another peer’s abbreviation or server name
    • The same as the local server name or the local abbreviation
    • Names are compared in the same way as user names in §4.3 (only ASCII uppercase and lowercase letters are treated as equal).
  3. Reservation of display names. Login and registration by local users under the following names MUST be refused. – A name under which a peer user is being displayed as is (using the [NAP] “already logged in” refusal). – A name in the origin-qualified form. In the recommended form, this is a name ending in (peer server name). – An implementation SHOULD reject, as forbidden words, all names that contain a peer’s server name or abbreviation (and the local server name and abbreviation). However, because 1- or 2-character abbreviations readily occur inside ordinary names, only the (abbreviation) form needs to be rejected for them. Because names are rejected regardless of form, this also prevents claiming a name with the parentheses written differently. – When a peer is registered later, existing registered names that contain its name MAY remain usable as they are. However, the operator SHOULD be notified, so that such users are not mistaken for peer users.
  4. Rewriting the destination. When a local user requests an IM, whois, browse, or download addressed to a display name (including the origin-qualified form), the server rewrites it to the peer user (the pair of name and origin) and sends it to that peer. The name in the message sent to the peer is the original name, without the origin.
  5. Even when a display name becomes free because a peer sent 9011 or the connection was lost, there is no need to change the display names of other peer users midway. They MAY be changed. If they are changed, it is presented to local users as if the user left and rejoined, using 407 and 406.

9. Channels (Capability chat)

No. Name Direction Fields and types Behavior on receipt
9020 GUILD_CHAN_JOIN Both srv origin, body(406) = ch nick int share count int speed (share count max 4294967295; speed 0–10) If the local server also shares that channel, add the user to the member list (408, 825) under the display name, and send 406 to the local users in the channel. If it does not share it, ignore the message
9021 GUILD_CHAN_PART Both srv origin, body(407) Remove the user from the member list and send 407
9022 GUILD_CHAN_PUBLIC Both srv origin, body(403) = ch nick rest text Send 403 under the display name to the local users in the channel
9023 GUILD_CHAN_EMOTE Both srv origin, body(824) = ch nick "text" Send 824 to the local users in the channel
9024 GUILD_CHAN_TOPIC Both srv origin, body(410) = ch rest topic The server MAY apply it as the topic of its own channel. If it does, send 410
  • Each server decides which channels to share. The sender MUST NOT send messages for channels it does not share, and the receiver ignores them.
  • Channel names are compared case-insensitively for ASCII letters.
  • The sender applies muting, flood limits, and channel rules to its local users before sending.
  • The receiver MAY decline to deliver a peer user’s messages to its local users on the grounds of its own channel rules.
  • Kicks, bans, operator appointments, and mode changes are not carried.

10. IM (Capability im)

No. Name Direction Fields and types Behavior on receipt
9030 GUILD_PRIVMSG Sender’s server→recipient’s server srv origin, nick recipient, body(205) = nick sender rest text If the recipient is a local user, deliver 205 under the sender’s display name. If not present, return 9031 (1). If the message is not delivered because of the recipient’s settings (such as an ignore list), silently discard it or return 9031 (2)
9031 GUILD_PRIVMSG_FAIL Recipient’s server→sender’s server srv origin, nick original sender, nick original recipient, int reason (max 255) If the original sender is a local user, notify them with 404
  • A request ID is an int from 1 to 4294967295. The requester SHOULD assign it incrementally, starting from 1, per connection and per direction, and MUST NOT reuse an ID whose response has not yet been completed.
No. Name Direction Fields and types Behavior on receipt
9040 GUILD_BROWSE Requester→responder srv origin, int request ID, nick requester, int maximum count (1–4294967295), body(211) = nick target If the target is a local user, send 9041 messages not exceeding the maximum count, and finally send 9042 (0). If not present, 9042 (1). If browsing is disabled, (5). If refused by policy, (3)
9041 GUILD_BROWSE_ITEM Responder→requester srv origin, int request ID, body(212) Deliver 212 to the requester (with the user name converted to the display name)
9042 GUILD_BROWSE_END Responder→requester srv origin, int request ID, int reason (max 255), body(213) Deliver 213 to the requester. If the reason is not 0, the server MAY notify with 404 beforehand
9043 GUILD_QUERY_CANCEL Requester→responder srv origin, int request ID The responder SHOULD abort that request. The end message is handled as described in “Limits and aborting” below
9050 GUILD_SEARCH Requester→responder srv origin, int request ID, nick requester, int maximum count (1–1000), body(200) Search only the shares of local users, with the same semantics as for local clients. The number of results does not exceed the smaller of the maximum count and MAX_RESULTS in the payload. Send the resulting 9051 messages, and finally send 9052 (the end message is handled as described in “Limits and aborting” below)
9051 GUILD_SEARCH_ITEM Responder→requester srv origin, int request ID, body(201) Deliver 201 to the requester (with the user name converted to the display name). Discard any results beyond the server’s own policy limit on the number of results
9052 GUILD_SEARCH_END Responder→requester srv origin, int request ID, int reason (max 255), int number of results sent (max 4294967295) That peer’s part is considered finished

Limits and aborting – For each request received, the responder MUST send an end message (9042 or 9052) exactly once. The only exception is a request cancelled by 9043, for which the responder MAY omit it. – The responder MUST NOT forward a request elsewhere. – The responder SHOULD NOT refuse on the grounds of the requester’s level or share count. Such rules are applied by the requester’s server. – The responder MAY set the number of requests it processes concurrently per peer. Requests beyond that are refused with reason 4 in the end message. – The requester SHOULD NOT have more than 16 concurrent requests outstanding to a single peer. – The responder SHOULD send the end message within 60 seconds. – The requester MAY abort the part of a peer that has not finished after 90 seconds. When aborting, the requester SHOULD send 9043 to the responder. Anything that arrives with that request ID after the abort is discarded. – Once the local results and the end (or abort) of every peer are all in, 202 is sent to the user. – The IP addresses in results (the fields of 201 and 213) are filled in by the responder as “externally reachable addresses”. – When the connection is lost, all requests on that connection are considered finished.

12. Arranging File Transfers (Capability xfer)

The transfer itself is performed directly between the clients ([NAP] §5). The messages in this section carry only the arrangements. The payload is created by the server where the actor is, and that server fills in the IP address and port with the externally reachable values for its local user.

No. Name Direction Fields and types Behavior on receipt
9060 GUILD_XFER_REQUEST Downloader’s server→uploader’s server srv origin, nick downloader, body(203) = nick uploader "file name" If the uploader is a local user, deliver 607 downloader's display name "file name" speed. If not present, 9063
9061 GUILD_XFER_ACCEPT Uploader’s server→downloader’s server srv origin, nick downloader, body(204) = nick uploader int ip int port "file name" md5 int speed (ip max 4294967295; port max 65535; speed 0–10) Deliver 204 to the downloader
9062 GUILD_XFER_REFUSE Same as above srv origin, nick downloader, body(609) Deliver 609
9063 GUILD_XFER_NOTFOUND Same as above srv origin, nick downloader, body(206) = nick peer "file name" Deliver 206
9064 GUILD_XFER_PUSH Downloader’s server→uploader’s server srv origin, nick uploader, body(501) = nick downloader int ip int port "file name" md5 int speed (ip max 4294967295; port max 65535; speed 0–10) Deliver 501 to the uploader. If not present, return 9063 to the origin

Flow (D is a user of S_D; U is a user of S_U) – Normal download: 1. D sends 203 to S_D. 2. S_D checks D under its own rules and sends 9060 to S_U. 3. S_U delivers 607 to U. 4. If U returns 608, S_U sends 9061 to S_D, and S_D delivers 204 to D. If U returns 609, 9062 and 609. – Across a firewall (when the port in 204 is 0): D sends 500 to S_D, S_D sends S_U a 9064 containing D’s externally reachable IP address and port, and S_U delivers 501 to U.

Checks and rules – The receiver verifies the actor’s presence (§4.5). If the delivery target is not a local user, the message is discarded. – Whether a download is allowed (points, sharing conditions, etc.) is decided by the downloader’s server. – The uploader’s server SHOULD NOT apply its own rules to the downloader. However, it MAY apply rate limits on requests. – 218–221 (transfer count notifications) are handled within each server only and are not carried.

13. Wallop (Capability wallop) and Announcements

No. Name Direction Fields and types Behavior on receipt
9070 GUILD_WALLOP Both srv origin, body(627) = nick sender rest text Deliver 627 to those local users who, under the server’s own definition, receive wallops. It MUST NOT be forwarded. The server MAY decline to accept it under its own policy
  • The sender sends only wallops from users who are allowed to send wallops under its own rules.
  • Announcements (628) are not carried. This extension has no message corresponding to 628, and 628 MUST NOT be sent on a Guild connection.

14. Refusal Reason Codes

Used in 9007, 9031, 9042, and 9052.

No. Meaning
0 Success (normal end)
1 The user is not online
2 Refused by the user’s settings
3 Refused by server policy
4 Busy (concurrent request limit)
5 Suspended (searching/browsing disabled)
6 Malformed (contains invalid UTF-8, or a field value exceeds its upper limit)
7 Characters cannot be represented
8 Not supported (capability absent, unknown type)
11 Cannot be handled as a name
12 The channel is not shared
13 Actor mismatch (the name is not in that peer’s presence)
14 Origin mismatch (the origin differs from the name of the peer on the connection)

(9 and 10 are unassigned.)

15. Presentation to Clients (Informative, Not Normative)

  • whois (603): The receiver may build 604 on the spot from presence. An offline peer user is reported as “not online”. Indicating which server the user belongs to is recommended.
  • Lists, channel member lists, and hotlists (830, 408, 825, 209, 210): Peer users may be included under their display names.

16. Compatibility

  1. Connecting to a server that does not know this extension. 9000 is treated as an unknown message from a client before login. Either there is no response or the connection is closed immediately. The initiator SHOULD abandon the handshake after 30 seconds and indicate to the operator that “the peer does not support the Guild”, and SHOULD lengthen the automatic reconnection interval.
  2. Different versions. The highest common version is chosen as in §6.5. If there is none, the connection is closed with reason 3.
  3. Partial implementations. Everything other than presence is negotiated through capabilities, so partial implementations can still connect.
  4. Unknown types. They are ignored as described in §4.6. Messages added in version 1.x rely on this rule.
  5. Clients. New message numbers never reach clients. Clients need not be changed. A display name may have (origin) attached (§8.3).
  6. Coexistence with links. On the same port, connections are distinguished by the first message. A link and a Guild are not established between the same two servers at the same time. Information learned through the Guild MUST NOT be passed to other procedures such as links.

17. Security Considerations

  1. Authentication. Mutual verification by HMAC-SHA256; the key is never carried in messages. 128-bit single-use random nonces and the role word prevent proofs from being reused or reflected. Including the capabilities in the input prevents tampering that forces features to be dropped.
  2. No protection after authentication. Version 1 provides neither encryption nor tamper detection (as with OpenNap itself). When traffic passes over an untrusted path, a VPN or TLS tunnel SHOULD be used. tls is reserved for the future.
  3. Key handling. Use a separate random key for each peer and deliver it outside this extension. Keys SHOULD be encrypted when stored. If a key is leaked, replace it.
  4. No authority over peers. There are no messages that change a peer’s state. Levels are used for display only. Administrative operations, bans, registrations, settings, and announcements are not carried.
  5. Impersonation. As specified in §8.3, a peer user MUST NOT be displayed under the same name as a local user or a registered name, as is.
  6. Personal information. Presence does not include IP addresses. They are included in search results and transfer arrangements (as with OpenNap itself). Operators SHOULD inform their users that joining a Guild can make local users’ IP addresses visible to peer users.
  7. Resource exhaustion attacks. The receiver MAY set per-peer limits on the number of presence entries, the number of concurrent requests, and the number of messages per second. If the presence limit is exceeded, the connection is closed with reason 9. The 30-second handshake timeout and a per-source limit on the number of connections SHOULD be applied.
  8. Connections under unregistered names. Reason 4 reveals whether a name is registered. Operators who are concerned about this MAY return 5 instead of 4.

18. References

  • [NAP] 『Nap プロトコル仕様書』 (Nap Protocol Specification), Japanese translation v1.0 (2002-02-08; revision history through 2003-12-17). The originals are the revised version by CyberAlien (2002-03-19) and the original version by Dr. Scholl (2001-04-07). Sections referenced by this document: §2 (framing and strings); §3 (200–206, 209–213, 218–221, 403, 404, 406–410, 500, 501, 603, 604, 607–609, 627, 628, 824, 825, 830); §5.1 and §5.2 (client-to-client transfers).
  • [RFC2119] Key words for use in RFCs to Indicate Requirement Levels.
  • [RFC8174] Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words.
  • [RFC2104] HMAC: Keyed-Hashing for Message Authentication.
  • [FIPS180-4] Secure Hash Standard.
  • [RFC3629] UTF-8, a transformation format of ISO 10646.

(Before publication, the original English OpenNap documentation will be obtained to verify the message numbers and referenced sections.)

Appendix A. Change Log

  • 1.0 draft (2026-09-26): Initial draft.