<?xml version="1.0" encoding="utf-8"?>
<html>
<head>
<title>KGS Protocol Description</title>
<!--
    Copyright (C) 2003      Marc Lehmannn &lt;pcg@goof.com&gt;
 
    You can redistribute and/or modify this document under the terms of
    the GNU General Public License as published by the Free Software
    Foundation; either version 2 of the License, or (at your option) any
    later version.

    This document is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-->
</head>
<body>

<h1>KGS Protocol Description</h1>

   <p>This XML document describes the KGS protocol. It is also used
   to automatically generate the perl parser for all the messages and
   structures in the protocol. Adapting it to other languages should be
   trivial.</p>

<h2>Structure and conventions of this document and the protocol</h2>

   <p>"Send" means messages send from the client to the server, while
   "received" means messages send by the server to the client.</p>

   <p>Everything on the wire are in little-endian format (what a shame).</p>

   <p>Primitive types are mostly integers (signed "I&lt;bits&gt;",
   unsigned "I&lt;bits&gt;"), ascii strings ("username"), or
   zero-terminated UCS2-Strings ("STRING"). Yes, I know java is supposed
   to do UTF-16, but no implementation seems to care...</p>

   <p>For the rest, go figure or bug me, Marc Lehmann &lt;pcg@goof.com&gt;</p>

<h2>Stream and message structure.</h2>

   <p>After connecting to the server, a handshake byte is exchanged. It's the
   major version number of the protocol the client uses. Version 3 and 4 are
   mostly the same, except that Version 4 clients expect server messages to
   be compressed, version 3 clients not.</p>

   <p>After that, the server sends back his version number, which is
   always 3 in the current protocol. Most of the protocol variation is
   determined by the server using the client version that is used in the
   initial login message.</p>

   <p>After the initial handshake, the client sends uncompressed
   messages, while the server sends back a zlib-compressed
   stream (<a href="http://rfc1950.x42.com/">rfc1950</a> and <a
   href="http://rfc1950.x42.com/">rfc1951</a>).</p>

   <p>All messages have the same header:</p>

   <struct name="message_header" send="yes" recv="yes">
      <member name="_unknown" type="U16"/>
      <member name="length" type="U16"/>
      The length is the length of the full message including the header.
      <member name="type" type="U16"/>
      If the type is &gt;= 0x4000 this is a message for a specific channel. The channel
      number is always the next U16.
   </struct>

<h2>Primitive types used in the protocol.</h2>

   <p>Baaah... not much yet.</p>

   <type name="username" type="A" length="12"/>
   <type name="roomname" type="S" length="25"/><!-- argh, how horribly broken -->
   <type name="locale" type="A" length="5"/>
   <type name="flag" type="U8" multiplier="1"/>
   <type name="komi" type="I32" multiplier="2"/>
   <type name="result" type="I32" multiplier="2"/>
   <type name="score" type="I32" multiplier="4"/>
   <type name="time" type="U32" multiplier="100"/>

<h2>Constants, enumeration and set types used in the protocol.</h2>

   <p>Baaah... not yet.</p>

<h2>Structs used in send &amp; receive messages</h2>

   <struct name="user" class="KGS::User">
      <member name="name" type="username"/>
      <member name="flags" type="U32" default="1"/>
   </struct>

<h2>Structs used in send messages</h2>

   <message type="0000" name="login" send="yes">
      <member name="ver_major" type="U32" default="2"/>
      <member name="ver_minor" type="U32" default="4"/>
      <member name="ver_micro" type="U32" default="67"/>
      <member name="name" type="username"/>
      <member name="password " type="U64" default="0"/>
      Password is a number calculated as follows (VERY insecure, basically plaintext!):
      password = 0; for (characters) { password = password * 1055 + ascii (char) }
      <member name="guest" type="flag" default="1"/>
      <member name="_unknown3" type="U16" default="0"/>
      <member name="locale" type="locale" default='"en_US"'/>
      <member name="clientver" type="DATA" default='"1.4.1_01:Swing app:Sun Microsystems Inc."'/>
   </message>

   <message type="0014" name="server_stats" send="yes">
      Request server statistics.
   </message>

   <message type="0021" name="pic_req" send="yes">
      Request a user picture from the server.
      <member name="name" type="username"/>
   </message>

   <message type="0021" name="pic_upload" send="yes">
      Same code as pic_req, but with an additional data section that
      should contain a JPEG image that is &lt;=7KB. It must have 141×200 Pixels.
      <member name="name" type="username"/>
      <member name="data" type="DATA"/>
   </message>

   <message type="0100" name="gnotice" send="yes">
      Send a global message. Maybe. Never tried, for obvious reasons :/
      <member name="notice" type="STRING"/>
   </message>

   <message type="0318" name="list_rooms" send="yes">
      List the rooms in a specific group/category.
      <member name="group" type="U8"/>
   </message>

   <message type="031a" name="new_room" send="yes">
      Create a new room. Not verified.
      <member name="name" type="username"/>
      <member name="i1" type="U32" default="0"/>
      <member name="b1" type="U8" default="0"/>
      <member name="b2" type="U8" default="255"/>
      <member name="b3" type="U8" default="255"/>
      <member name="group" type="U8" default="1"/>
      <member name="name" type="STRING"/>
      <member name="description" type="STRING"/>
      <member name="flags" type="U8"/>
      0x10 .. private room etc.. see code
   </message>

   <message type="4300" name="join_room" send="yes">
      <member name="channel" type="U16"/>
      <member name="user" type="user"/>
   </message>

   <message type="4301" name="msg_room" send="yes">
      <member name="channel" type="U16"/>
      <member name="name" type="username"/>
      <member name="message" type="STRING"/>
   </message>

   <message type="4302" name="part_room" send="yes">
      <member name="channel" type="U16"/>
      <member name="name" type="username"/>
   </message>

   <message type="4305" name="new_game" send="yes">
      <member name="channel" type="U16"/>
      <member name="id" type="U16"/>
      <member name="gametype" type="U32"/>
      <member name="rules" type="rules"/>
      <member name="notes" type="STRING"/>
   </message>

   <message type="430b" name="req_games" send="yes">
      request to update room game list (send once per minute)
      <member name="channel" type="U16"/>
   </message>

   <message type="4319" name="req_desc" send="yes">
      Request room description.
      <member name="channel" type="U16"/>
   </message>

   <message type="4400" name="send_chal" send="yes">
      No idea.
      <member name="channel" type="U16"/>
      <member name="black" type="username"/>
      <member name="white" type="username"/>
      More following... TREE or challenge.
   </message>

   <message type="4403" name="join_game" send="yes">
      <member name="user" type="user"/>
      <member name="channel" type="U16"/>
   </message>

   <message type="4404" name="part_game" send="yes">
      <member name="channel" type="U16"/>
      <member name="name" type="username"/>
   </message>

   <message type="4405" name="set_tree" send="yes">
      <member name="channel" type="U16"/>
      <member name="tree" type="TREE"/>
   </message>

   <message type="4408" name="get_tree" send="yes">
      <member name="channel" type="U16"/>
      <member name="node" type="U32"/>
   </message>

   <message type="440c" name="claim_win" send="yes">
      <member name="channel" type="U16"/>
      <member name="_byte" type="U8 "/>
      Player colour maybe? Unclear.
   </message>

   <message type="440d" name="add_time" send="yes">
      <member name="channel" type="U16"/>
      <member name="time" type="U32"/>
      <member name="player" type="U8"/>
   </message>

   <message type="440f" name="grant_undo" send="yes">
      <member name="channel" type="U16"/>
   </message>

   <message type="4410" name="resign_game" send="yes">
      <member name="channel" type="U16"/>
      <member name="player" type="U8"/>
   </message>

   <message type="441a" name="set_teacher" send="yes">
      <member name="channel" type="U16"/>
      <member name="name" type="username"/>
   </message>

   <message type="4422" name="add_user" send="yes">
      <member name="channel" type="U16"/>
      <member name="othername" type="username"/>
      <member name="name" type="username"/>; # gives user access to the game (to what? ;)
   </message>

   <message type="4423" name="set_privacy" send="yes">
      <member name="channel" type="U16"/>
      <member name="private" type="U8"/>
   </message>

   <message type="4429" name="reject_chal" send="yes">
      <member name="channel" type="U16"/>
      <member name="name" type="username"/>
   </message>

   <message type="4433" name="req_result" send="yes">
      <member name="channel" type="U16"/>
   </message>

<h2>Structs mainly used in receive messages</h2>

   <struct name="challenge_defaults">
      <member name="gametype" type="U32"/>
      <member name="size" type="U32"/>
      <member name="timesys" type="U32"/>
      <member name="time" type="U32"/>
      <member name="byo_time" type="U32"/>
      <member name="byo_periods" type="U32"/>
      <member name="can_time" type="U32"/>
      <member name="can_stones" type="U32"/>
   </struct>

   <struct name="rules" class="KGS::Rules">
      <member name="ruleset" type="U8"/>
      <member name="size" type="U8"/>
      <member name="handicap" type="U8"/>
      <member name="komi" type="komi"/>
      <member name="timesys" type="U8"/>
      <member name="time" type="U32"/>
      <member name="interval" type="U32"/>
      byo-yomi time / canadian time
      <member name="count" type="U16"/>
      periods / moves
   </struct>

   <struct name="challenge" class="KGS::Challenge">
      <member name="user1" type="user"/>
      <member name="user2" type="user"/>
      <member name="gametype" type="U32"/>
      <member name="rules" type="rules"/>
      Maybe the rules" are in TREE format. I forgot.
   </struct>

   <struct name="game" class="KGS::Game">
      <member name="channel" type="U16"/>
      <member name="type" type="U32"/>
      <member name="user1" type="user"/>
      White
      <member name="user2" type="user"/>
      Black
      <member name="user3" type="user"/>
      Owner
      <member name="size" type="U32"/>
      <member name="handicap" type="I32"/>
      &lt; 0 not fully setup
      <member name="komi" type="komi"/>
      <member name="moves" type="U16"/>
      <member name="flags" type="U16"/>
      <member name="observers" type="U32"/>
      <member name="saved" type="flag"/>
      <member name="notes" type="STRING" guard-member="handicap" guard-cond="&lt; 0"/>
   </struct>

   <struct name="room_obs">
      <member name="name" type="roomname"/>
      <member name="channel" type="U16"/>
      <member name="flags" type="U32"/>
      <member name="users" type="U32"/>)
   </struct>

   <struct name="room" class="KGS::Room">
      <member name="channel" type="U16"/>
      <member name="flags" type="U8"/>
      <member name="group" type="U8"/>
      <member name="users" type="U16"/>
      <member name="games" type="U16"/>
      <member name="name" type="STRING"/>)
   </struct>

   <struct name="score" class="KGS::Score">
      <member name="score" type="score"/>
      <member name="territory" type="U32"/>
      <member name="captures" type="U32"/>
      <member name="i3" type="U32"/>
      <member name="f2" type="U32"/>
      <member name="komi" type="komi"/>
      <member name="i4" type="U32"/>)
      Apparently the i3, f2, i4 are zero.
   </struct>

<h2>Receive messages</h2>

   <message type="0001" name="login" recv="yes">
      <member name="result" type="CONSTANT" default='"login ok"'/>
      <member name="success" type="CONSTANT" default="1"/>
   </message>

   <message type="0002" name="login" recv="yes">
      <member name="result" type="CONSTANT" default='"guest login ok"'/>
      <member name="success" type="CONSTANT" default="1"/>
   </message>

   <message type="0003" name="login" recv="yes">
      <member name="result" type="CONSTANT" default='"login error 3"'/>
      ** maybe more following? **
   </message>

   <message type="0004" name="login" recv="yes">
      <member name="result" type="CONSTANT" default='"wrong password"'/>
      ** maybe more following? **
   </message>

   <message type="0005" name="login" recv="yes">
      <member name="result" type="CONSTANT" default='"user unknown"'/>
      ** maybe more following? **
   </message>

   <message type="0006" name="login" recv="yes">
      <member name="result" type="CONSTANT" default='"user exists"'/>
      ** maybe more following? **
   </message>

   <message type="0018" name="login" recv="yes">
      <member name="result" type="CONSTANT" default='"login error 18"'/>
      ** maybe more following? **
   </message>

   <message type="0022" name="login" recv="yes">
      <!-- "thanks" to jylem for blocking me ;)-->
      <member name="result" type="CONSTANT" default='"user or ip blocked"'/>
      <member name="reason" type="STRING"/>
   </message>

   <message type="0013" name="msg_chat" recv="yes">
      <member name="user1" type="username"/>
      <member name="user2" type="username"/>
      <member name="message" type="STRING"/>
   </message>

   <message type="0015" name="stats" recv="yes">
      <member name="ver_major" type="U16"/>
      <member name="ver_minor" type="U16"/>
      <member name="ver_micro" type="U16"/>
      <member name="boot_time" type="U64"/>
      <member name="users_cur" type="U32"/>
      <member name="users_max" type="U32"/>
      <member name="users_lim" type="U32"/>
      <member name="accts_cur" type="U32"/>
      <member name="accts_max" type="U32"/>
      <member name="unknown1" type="U32"/>
      <member name="work_max" type="U32"/>
      <member name="rooms_cur" type="U32"/>
      <member name="rooms_max" type="U32"/>
      <member name="rooms_lim" type="U32"/>
      <member name="games_cur" type="U32"/>
      <member name="games_max" type="U32"/>
      <member name="games_lim" type="U32"/>
      <member name="results_cur" type="U32"/>
      <member name="results_max" type="U32"/>
      <member name="unknown2" type="U32"/>
      <member name="params_cur" type="U32"/>
      <member name="params_max" type="U32"/>
      <member name="bytes_in" type="U64"/>
      <member name="packets_in" type="U64"/>
      <member name="bytes_out" type="U64"/>
      <member name="packets_out" type="U64"/>)
   </message>

   <message type="0016" name="idle_warn" recv="yes">
      idle warning, autologout soon (10 minutes...)
   </message>

   <message type="001b" name="timewarning_default" recv="yes">
      WILD guess
      <member name="channel" type="U16"/>
      <member name="time" type="U16"/>
   </message>

   <message type="001c" name="idle_err" recv="yes">
      autologout
   </message>

   <message type="001d" name="ping" recv="yes">
   </message>

   <message type="0021" name="userpic" recv="yes">
      <member name="name" type="username"/>
      Reply to pic_req, contains an image in jpeg format.
      <member name="data" type="DATA"/>
   </message>

   <message type="0100" name="gnotice" recv="yes">
      global notice, sent to everybody
      <member name="notice" type="STRING"/>
   </message>


   <message type="0310" name="priv_room" recv="yes">
      "permission denied" when joining a room
      <member name="name" type="STRING"/>
   </message>

   <message type="0318" name="upd_rooms" recv="yes">
      <member name="rooms" type="room" array="yes"/>
   </message>

   <message type="041c" name="upd_game2" recv="yes">
      <member name="channel_junk" type="U16"/>
      <member name="game" type="game"/>
   </message>

   <message type="0202" name="upd_user" recv="yes">
      # loc 0" type="chat(?) loc 1 => gameinfo?, loc 2 => game result (more data)
      <member name="location" type="U32"/>
      <member name="user" type="user"/>
      <member name="lotsofinfo" type="DATA" guard-member="location" guard-cond="== 2"/>
   </message>

<h3>Room messages</h3>

   <p>Not all room messages are for rooms only, and rooms need to parse
   not only these messages. Orthogonality, what for?</p>

   <message type="4300" name="join_room" recv="yes">
      <member name="channel" type="U16"/>
      <member name="users" type="user" array="yes"/>
   </message>

   <message type="4301" name="msg_room" recv="yes">
      <member name="channel" type="U16"/>
      <member name="name" type="username"/>
      <member name="message" type="STRING"/>
   </message>

   <message type="4302" name="part_room" recv="yes">
      <member name="channel" type="U16"/>
      <member name="user" type="user"/>
   </message>

   <message type="4303" name="del_room" recv="yes">
      <member name="channel" type="U16"/>

   </message>

   <message type="4304" name="upd_games" recv="yes">
      <member name="channel" type="U16"/>
      <member name="games" type="game" array="yes"/>
   </message>

   <message type="4319" name="desc_room" recv="yes">
      <member name="channel" type="U16"/>
      <member name="owner" type="username"/>
      <member name="description" type="STRING"/>
   </message>


   <message type="0411" name="chal_defaults" recv="yes">
      <member name="channel" type="U16"/>
      <member name="defaults" type="challenge_defaults"/>
   </message>

<h3>Game messages</h3>

   <message type="4400" name="upd_chal" recv="yes">
      Unclear.
      <member name="channel" type="U16"/>
      <member name="challenge" type="challenge"/>
   </message>

   <message type="4401" name="upd_game" recv="yes">
      <member name="channel" type="U16"/>
      <member name="game" type="game"/>
   </message>

   <message type="4402" name="del_game" recv="yes">
      <member name="channel" type="U16"/>
   </message>

   <message type="4403" name="upd_observers" recv="yes">
      <member name="channel" type="U16"/>
      <member name="users" type="user" array="yes"/>
   </message>

   <message type="4404" name="del_observer" recv="yes">
      <member name="channel" type="U16"/>
      <member name="name" type="username"/>
   </message>

   <message type="4405" name="set_tree" recv="yes">
      <member name="channel" type="U16"/>
      <member name="tree" type="TREE"/>
   </message>

   <message type="4406" name="upd_tree" recv="yes">
      <member name="channel" type="U16"/>
      <member name="tree" type="TREE"/>
   </message>

   <message type="4407" name="set_node" recv="yes">
      <member name="channel" type="U16"/>
      <member name="node" type="U32"/>
   </message>

   <message type="4409" name="superko" recv="yes">
      Superko-warning.
      <member name="channel" type="U16"/>
   </message>

   <message type="440b" name="final_result" recv="yes">
      <member name="channel" type="U16"/>
      <member name="blackscore" type="score"/>
      <member name="whitescore" type="score"/>
   </message>

   <message type="440e" name="req_undo" recv="yes">
      <member name="channel" type="U16"/>

   </message>

   <message type="4410" name="resign_game" recv="yes">
      <member name="channel" type="U16"/>
      <member name="player" type="U8"/>
   </message>

   <message type="441a" name="set_teacher" recv="yes">
      <member name="channel" type="U16"/>
      <member name="name" type="username"/>
   </message>

   <message type="441d" name="owner_left" recv="yes">
      Unclear.
      <member name="channel" type="U16"/>
   </message>

   <message type="441e" name="teacher_left" recv="yes">
      Unclear.
      <member name="channel" type="U16"/>
   </message>

   <message type="4422" name="unknown4422" recv="yes">
      change teacher? something to do with editing?
      <member name="channel" type="U16"/>
      <member name="name1" type="username"/>
      <member name="name2" type="username"/>
   </message>

   <message type="4433" name="req_result" recv="yes">
       Unclear.
       <member name="channel" type="U16"/>
       # # recv_result(?)
   </message>

   <message type="4434" name="unknown4434" recv="yes">
      <member name="channel" type="U16"/>
      <member name="b1" type="U8"/>
      ?? !demonstration game??
   </message>

</body>
</html>

