<?xml version='1.0' encoding='UTF-8'?><!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.docbook.org/xml/4.4/docbookx.dtd"><article><articleinfo><title>FrontPage</title><revhistory><revision><revnumber>98</revnumber><date>2013-04-23 15:34:37</date><authorinitials>teratorn</authorinitials><revremark>Revert to revision 96.</revremark></revision><revision><revnumber>97</revnumber><date>2013-04-20 20:44:49</date><authorinitials>JoelZOWA</authorinitials></revision><revision><revnumber>96</revnumber><date>2013-03-22 15:53:26</date><authorinitials>teratorn</authorinitials><revremark>Revert to revision 94.</revremark></revision><revision><revnumber>95</revnumber><date>2013-03-21 22:02:21</date><authorinitials>NiamhKins</authorinitials></revision><revision><revnumber>94</revnumber><date>2013-03-21 20:03:57</date><authorinitials>teratorn</authorinitials><revremark>Revert to revision 92.</revremark></revision><revision><revnumber>93</revnumber><date>2013-03-18 20:53:11</date><authorinitials>JoelZOWA</authorinitials></revision><revision><revnumber>92</revnumber><date>2012-09-02 21:25:37</date><authorinitials>teratorn</authorinitials><revremark>note</revremark></revision><revision><revnumber>91</revnumber><date>2012-09-02 19:30:29</date><authorinitials>teratorn</authorinitials><revremark>whitespace</revremark></revision><revision><revnumber>90</revnumber><date>2012-08-31 20:51:38</date><authorinitials>rrcs-50-84-155-27.sw.biz.rr.com</authorinitials><revremark>y it iz so gud</revremark></revision><revision><revnumber>89</revnumber><date>2012-08-31 18:05:55</date><authorinitials>rrcs-50-84-155-27.sw.biz.rr.com</authorinitials><revremark>impl note</revremark></revision><revision><revnumber>88</revnumber><date>2012-08-31 18:05:01</date><authorinitials>rrcs-50-84-155-27.sw.biz.rr.com</authorinitials><revremark>reword</revremark></revision><revision><revnumber>87</revnumber><date>2012-03-14 07:56:51</date><authorinitials>12.191.60.106</authorinitials><revremark>TLS link</revremark></revision><revision><revnumber>86</revnumber><date>2011-08-26 14:15:54</date><authorinitials>teratorn</authorinitials><revremark>Revert to revision 84.</revremark></revision><revision><revnumber>85</revnumber><date>2011-08-26 10:49:11</date><authorinitials>204-242-webenlet.hu</authorinitials></revision><revision><revnumber>84</revnumber><date>2011-07-31 10:12:39</date><authorinitials>rrcs-71-42-153-210.sw.biz.rr.com</authorinitials><revremark>minor tweaks</revremark></revision><revision><revnumber>83</revnumber><date>2011-07-30 04:18:51</date><authorinitials>rrcs-71-42-153-210.sw.biz.rr.com</authorinitials></revision><revision><revnumber>82</revnumber><date>2011-07-12 21:13:17</date><authorinitials>rrcs-71-42-153-210.sw.biz.rr.com</authorinitials><revremark>format tweaks</revremark></revision><revision><revnumber>81</revnumber><date>2011-07-01 22:04:16</date><authorinitials>rrcs-71-42-153-210.sw.biz.rr.com</authorinitials></revision><revision><revnumber>80</revnumber><date>2011-06-13 00:09:39</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>79</revnumber><date>2011-06-06 18:48:24</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>78</revnumber><date>2011-06-06 06:27:22</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>77</revnumber><date>2011-06-06 06:03:49</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>76</revnumber><date>2011-06-06 06:03:28</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>75</revnumber><date>2011-06-06 05:52:18</date><authorinitials>202-7-189-118.static.tpgi.com.au</authorinitials><revremark>Mention size limits.</revremark></revision><revision><revnumber>74</revnumber><date>2011-06-01 16:52:45</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>73</revnumber><date>2011-05-30 21:39:07</date><authorinitials>teratorn</authorinitials><revremark>i laff</revremark></revision><revision><revnumber>72</revnumber><date>2011-05-30 21:36:06</date><authorinitials>teratorn</authorinitials><revremark>clarify desired behavior for error codes</revremark></revision><revision><revnumber>71</revnumber><date>2011-05-30 21:24:06</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>70</revnumber><date>2011-05-24 16:25:55</date><authorinitials>teratorn</authorinitials><revremark>anchor test</revremark></revision><revision><revnumber>69</revnumber><date>2011-05-21 06:04:44</date><authorinitials>109.64.184.254</authorinitials></revision><revision><revnumber>68</revnumber><date>2011-01-13 10:58:46</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>67</revnumber><date>2010-12-15 14:16:47</date><authorinitials>teratorn</authorinitials><revremark>add line break</revremark></revision><revision><revnumber>66</revnumber><date>2010-12-15 14:13:02</date><authorinitials>teratorn</authorinitials><revremark>0x02 instead of 0x03</revremark></revision><revision><revnumber>65</revnumber><date>2010-11-17 03:43:51</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>64</revnumber><date>2010-11-17 00:28:43</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>63</revnumber><date>2010-11-17 00:26:38</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>62</revnumber><date>2010-11-11 20:17:20</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>61</revnumber><date>2010-11-11 20:15:11</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>60</revnumber><date>2010-11-11 20:14:15</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>59</revnumber><date>2010-11-11 17:25:30</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>58</revnumber><date>2010-11-11 17:23:52</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>57</revnumber><date>2010-11-10 23:46:33</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>56</revnumber><date>2010-11-10 23:44:28</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>55</revnumber><date>2010-11-10 23:44:05</date><authorinitials>teratorn</authorinitials><revremark>revert screwup</revremark></revision><revision><revnumber>54</revnumber><date>2010-11-10 23:41:56</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>53</revnumber><date>2010-11-10 17:21:01</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>52</revnumber><date>2010-11-10 17:03:08</date><authorinitials>teratorn</authorinitials><revremark>add section on error handling</revremark></revision><revision><revnumber>51</revnumber><date>2010-11-10 10:42:59</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>50</revnumber><date>2010-11-10 09:33:00</date><authorinitials>121.90.108.75</authorinitials></revision><revision><revnumber>49</revnumber><date>2010-11-10 08:22:23</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>48</revnumber><date>2010-11-09 23:13:13</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>47</revnumber><date>2010-11-09 22:56:51</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>46</revnumber><date>2010-11-09 22:51:36</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>45</revnumber><date>2010-11-09 22:49:15</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>44</revnumber><date>2010-11-09 19:40:42</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>43</revnumber><date>2010-11-09 19:40:21</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>42</revnumber><date>2010-11-09 19:37:31</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>41</revnumber><date>2010-11-09 19:33:08</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>40</revnumber><date>2010-11-09 19:31:33</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>39</revnumber><date>2010-11-09 19:28:50</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>38</revnumber><date>2010-11-09 18:32:38</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>37</revnumber><date>2010-11-09 18:04:17</date><authorinitials>rrcs-71-42-153-210.sw.biz.rr.com</authorinitials></revision><revision><revnumber>36</revnumber><date>2010-11-09 18:01:53</date><authorinitials>rrcs-71-42-153-210.sw.biz.rr.com</authorinitials></revision><revision><revnumber>35</revnumber><date>2010-11-09 17:33:23</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>34</revnumber><date>2010-11-09 17:25:18</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>33</revnumber><date>2010-11-09 17:21:24</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>32</revnumber><date>2010-11-09 17:19:58</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>31</revnumber><date>2010-11-09 17:15:09</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>30</revnumber><date>2010-11-09 17:09:03</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>29</revnumber><date>2010-11-09 17:06:39</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>28</revnumber><date>2010-11-09 17:03:12</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>27</revnumber><date>2010-11-09 15:14:00</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>26</revnumber><date>2010-11-09 13:09:55</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>25</revnumber><date>2010-11-09 13:04:41</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>24</revnumber><date>2010-11-09 13:04:07</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>23</revnumber><date>2010-11-09 03:24:01</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>22</revnumber><date>2010-11-09 03:20:51</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>21</revnumber><date>2010-11-09 03:19:49</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>20</revnumber><date>2010-11-09 03:17:01</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>19</revnumber><date>2010-11-09 03:15:44</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>18</revnumber><date>2010-11-09 03:09:00</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>17</revnumber><date>2010-11-08 15:45:47</date><authorinitials>rrcs-71-42-153-210.sw.biz.rr.com</authorinitials></revision><revision><revnumber>16</revnumber><date>2010-11-08 15:42:25</date><authorinitials>rrcs-71-42-153-210.sw.biz.rr.com</authorinitials></revision><revision><revnumber>15</revnumber><date>2010-11-08 15:40:24</date><authorinitials>rrcs-71-42-153-210.sw.biz.rr.com</authorinitials></revision><revision><revnumber>14</revnumber><date>2010-11-08 15:34:47</date><authorinitials>rrcs-71-42-153-210.sw.biz.rr.com</authorinitials></revision><revision><revnumber>13</revnumber><date>2010-11-08 15:33:47</date><authorinitials>rrcs-71-42-153-210.sw.biz.rr.com</authorinitials></revision><revision><revnumber>12</revnumber><date>2010-11-08 15:32:59</date><authorinitials>rrcs-71-42-153-210.sw.biz.rr.com</authorinitials></revision><revision><revnumber>11</revnumber><date>2010-11-08 15:24:40</date><authorinitials>rrcs-71-42-153-210.sw.biz.rr.com</authorinitials></revision><revision><revnumber>10</revnumber><date>2010-11-08 15:18:04</date><authorinitials>rrcs-71-42-153-210.sw.biz.rr.com</authorinitials></revision><revision><revnumber>9</revnumber><date>2010-11-08 15:15:59</date><authorinitials>rrcs-71-42-153-210.sw.biz.rr.com</authorinitials></revision><revision><revnumber>8</revnumber><date>2010-11-08 15:15:22</date><authorinitials>rrcs-71-42-153-210.sw.biz.rr.com</authorinitials></revision><revision><revnumber>7</revnumber><date>2010-11-08 15:11:03</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>6</revnumber><date>2010-11-08 14:30:25</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>5</revnumber><date>2010-11-08 14:18:20</date><authorinitials>teratorn</authorinitials></revision><revision><revnumber>4</revnumber><date>2010-11-08 14:12:28</date><authorinitials>teratorn</authorinitials><revremark>start of first example</revremark></revision><revision><revnumber>3</revnumber><date>2010-11-08 09:11:40</date><authorinitials>rrcs-71-42-153-210.sw.biz.rr.com</authorinitials></revision><revision><revnumber>2</revnumber><date>2010-11-08 08:20:19</date><authorinitials>rrcs-71-42-153-210.sw.biz.rr.com</authorinitials><revremark>tweak</revremark></revision><revision><revnumber>1</revnumber><date>2010-11-08 08:12:00</date><authorinitials>teratorn</authorinitials><revremark>initial version</revremark></revision></revhistory></articleinfo><section><title>AMP - Asynchronous Messaging Protocol</title><para>AMP is an <ulink url='http://en.wikipedia.org/wiki/Remote_procedure_call'>RPC</ulink> protocol for sending multiple asynchronous request/response pairs over the same</para><para>  connection. Requests and responses are both collections of key/value pairs.  Keys are limited to 255</para><para> bytes in length, and values to 65,535 bytes (<ulink url='http://amp-protocol.net/FrontPage/DontPanic#'>Why?</ulink>). Any number of key/value pairs may be encoded</para><para> in a single AMP packet. </para><para>AMP enables a rich set of Internet applications, from Client-Server "traditional" web-service operations, to highly</para><para> custom and efficient RPC protocols, to distributed peer-to-peer messaging configurations. Once connected, the</para><para> AMP protocol is symmetric, allowing either client or server to initiate an asynchronous request, provided the other</para><para> side implements a handler for it. </para><para>For values, AMP defines a number of <ulink url='http://amp-protocol.net/FrontPage/Types#'>Standard Data Types</ulink>, while keys are always strings. </para><para>AMP originally appeared in <ulink url='http://twistedmatrix.com'>Twisted</ulink>, a Python networking framework, however AMP is <emphasis><emphasis role='strong'>not Python-specific</emphasis></emphasis>. </para><para>Implementation are available for a variety of languages including Python, C, C#, Java, PHP and Erlang.</para><para> See the <ulink url='http://amp-protocol.net/FrontPage/Implementations#'>implementations page</ulink> for details. </para><section><title>Wire-Level Format</title><para>AMP uses a very simple and logical wire-level format, making it easy to implement in your language of choice. </para><para>Lets take a hypothetical <emphasis role='strong'>Sum</emphasis> command which accepts two arguments, <emphasis role='strong'>a</emphasis> and <emphasis role='strong'>b</emphasis>,</para><para> and returns <emphasis role='strong'>a+b</emphasis> as the argument named <emphasis role='strong'>total</emphasis>. </para><para>Sample key/values of a request to the <emphasis role='strong'>Sum</emphasis> command:</para><informaltable><tgroup cols='2'><colspec colname='col_0'/><colspec colname='col_1'/><tbody><row rowsep='1'><entry colsep='1' rowsep='1'><para><emphasis role='strong'>_ask</emphasis> </para></entry><entry colsep='1' rowsep='1'><para>23 </para></entry></row><row rowsep='1'><entry colsep='1' rowsep='1'><para><emphasis role='strong'>_command</emphasis> </para></entry><entry colsep='1' rowsep='1'><para>Sum </para></entry></row><row rowsep='1'><entry colsep='1' rowsep='1'><para><emphasis role='strong'>a</emphasis> </para></entry><entry colsep='1' rowsep='1'><para>13 </para></entry></row><row rowsep='1'><entry colsep='1' rowsep='1'><para><emphasis role='strong'>b</emphasis> </para></entry><entry colsep='1' rowsep='1'><para>81 </para></entry></row></tbody></tgroup></informaltable><para>Key/values of the response:</para><informaltable><tgroup cols='2'><colspec colname='col_0'/><colspec colname='col_1'/><tbody><row rowsep='1'><entry colsep='1' rowsep='1'><para><emphasis role='strong'>_answer</emphasis> </para></entry><entry colsep='1' rowsep='1'><para>23 </para></entry></row><row rowsep='1'><entry colsep='1' rowsep='1'><para><emphasis role='strong'>total</emphasis> </para></entry><entry colsep='1' rowsep='1'><para>94 </para></entry></row></tbody></tgroup></informaltable><para>That's all there is to it for a successful invocation of the <emphasis role='strong'>Sum</emphasis> command!</para><para> (We'll talk about error handling later.) </para><para>The special <emphasis role='strong'>_ask</emphasis> key is a unique-per-connection identifier, which identifies individual requests</para><para> on a particular connection (e.g. a TCP socket). </para><para>Its value is used with the special <emphasis role='strong'>_answer</emphasis> key to indicate the original request that is being answered. </para><para>And obviously the special <emphasis role='strong'>_command</emphasis> key indicates which command-handler should be invoked to process the request. </para><para>AMP is <emphasis><emphasis role='strong'>asynchronous</emphasis></emphasis>, meaning that requests and responses may be interleaved on the wire at will.</para><para> You can happily fire off several requests before receiving any responses... and responses may be returned in <emphasis>any order</emphasis>. </para><para>AMP is <emphasis><emphasis role='strong'>full-duplex</emphasis></emphasis> (or <emphasis><emphasis role='strong'>symmetric</emphasis></emphasis>), meaning that requests may be initiated from either side of the connection. </para><section><title>Sample Code</title><para><ulink url='http://amp-protocol.net/FrontPage/SumClientServer#'>Client and server for a "Sum" command is here.</ulink> You will need Python (2.x) and <ulink url='http://twistedmatrix.com'>Twisted</ulink>. </para><para>Or check out a <ulink url='http://amp-protocol.net/FrontPage/AmpSharp#'>C# example</ulink>. </para></section></section></section><section><title>The Actual Bytes</title><para>Keys and values in AMP are <emphasis><emphasis role='strong'>length-prefixed</emphasis></emphasis>. Keys and values both use a 16-bit (2 byte) prefix value,</para><para> <emphasis><emphasis role='strong'>however</emphasis></emphasis>, key length is restricted to 8 bits (1 byte). This means keys have a maximum length of 255 bytes,</para><para> and values a maximum length of 65,535 bytes. </para><para>Prefix values are in <emphasis><emphasis role='strong'>Network Byte Order</emphasis></emphasis> (big-endian). </para><para>So, the request above (a "packet", in AMP terms) looks like this on the wire:</para><informaltable><tgroup cols='2'><colspec colname='col_0'/><colspec colname='col_1'/><tbody><row rowsep='1'><entry colsep='1' rowsep='1'><para>0x00 0x04 </para></entry><entry colsep='1' rowsep='1'><para> A key name of length 4 follows... </para></entry></row><row rowsep='1'><entry colsep='1' rowsep='1'><para>0x5F 0x61 0x73 0x6B</para></entry><entry colsep='1' rowsep='1'><para> "_ask" </para></entry></row><row rowsep='1'><entry colsep='1' rowsep='1'><para>0x00 0x02</para></entry><entry colsep='1' rowsep='1'><para> A value of length 2 follows... </para></entry></row><row rowsep='1'><entry colsep='1' rowsep='1'><para>0x32 0x33</para></entry><entry colsep='1' rowsep='1'><para> "23" </para></entry></row><row rowsep='1'><entry colsep='1' rowsep='1'><para>0x00 0x08</para></entry><entry colsep='1' rowsep='1'><para> A key name of length 8 follows... </para></entry></row><row rowsep='1'><entry colsep='1' rowsep='1'><para>0x5F 0x63 0x6F 0x6D 0x6D 0x61 0x6E 0x64 </para></entry><entry colsep='1' rowsep='1'><para> "_command" </para></entry></row><row rowsep='1'><entry colsep='1' rowsep='1'><para>0x00 0x03</para></entry><entry colsep='1' rowsep='1'><para> A value of length 3 follows... </para></entry></row><row rowsep='1'><entry colsep='1' rowsep='1'><para>0x53 0x75 0x6D</para></entry><entry colsep='1' rowsep='1'><para> "Sum" </para></entry></row><row rowsep='1'><entry colsep='1' rowsep='1'><para>0x00 0x01</para></entry><entry colsep='1' rowsep='1'><para> A key name of length 1 follows... </para></entry></row><row rowsep='1'><entry colsep='1' rowsep='1'><para>0x61</para></entry><entry colsep='1' rowsep='1'><para> "a" </para></entry></row><row rowsep='1'><entry colsep='1' rowsep='1'><para>0x00 0x02</para></entry><entry colsep='1' rowsep='1'><para> A value of length 2 follows...</para></entry></row><row rowsep='1'><entry colsep='1' rowsep='1'><para>0x31 0x33</para></entry><entry colsep='1' rowsep='1'><para> "13" </para></entry></row><row rowsep='1'><entry colsep='1' rowsep='1'><para>0x00 0x01</para></entry><entry colsep='1' rowsep='1'><para> A key name of length 1 follows... </para></entry></row><row rowsep='1'><entry colsep='1' rowsep='1'><para>0x62</para></entry><entry colsep='1' rowsep='1'><para> "b" </para></entry></row><row rowsep='1'><entry colsep='1' rowsep='1'><para>0x00 0x02</para></entry><entry colsep='1' rowsep='1'><para> A value of length 2 follows...</para></entry></row><row rowsep='1'><entry colsep='1' rowsep='1'><para>0x38 0x31</para></entry><entry colsep='1' rowsep='1'><para> "81" </para></entry></row><row rowsep='1'><entry colsep='1' rowsep='1'><para>0x00 0x00</para></entry><entry colsep='1' rowsep='1'><para> A key of length 0. THIS MARKS THE END OF THE PACKET. </para></entry></row></tbody></tgroup></informaltable><para>Pretty simple, eh? Key names are UTF-8 encoded strings. </para><para>The integer arguments, <emphasis role='strong'>a</emphasis> and <emphasis role='strong'>b</emphasis>, are also UTF-8 strings. </para><para>The response is encoded like so:</para><informaltable><tgroup cols='2'><colspec colname='col_0'/><colspec colname='col_1'/><tbody><row rowsep='1'><entry colsep='1' rowsep='1'><para>0x00 0x07 </para></entry><entry colsep='1' rowsep='1'><para> A key name of length 7 follows... </para></entry></row><row rowsep='1'><entry colsep='1' rowsep='1'><para>0x5F 0x61 0x6E 0x73 0x77 0x65 0x72</para></entry><entry colsep='1' rowsep='1'><para> "_answer" </para></entry></row><row rowsep='1'><entry colsep='1' rowsep='1'><para>0x00 0x02</para></entry><entry colsep='1' rowsep='1'><para> A value of length 2 follows... </para></entry></row><row rowsep='1'><entry colsep='1' rowsep='1'><para>0x32 0x33</para></entry><entry colsep='1' rowsep='1'><para> "23" </para></entry></row><row rowsep='1'><entry colsep='1' rowsep='1'><para>0x00 0x05</para></entry><entry colsep='1' rowsep='1'><para> A key name of length 5 follows... </para></entry></row><row rowsep='1'><entry colsep='1' rowsep='1'><para>0x74 0x6F 0x74 0x61 0x6C </para></entry><entry colsep='1' rowsep='1'><para> "total" </para></entry></row><row rowsep='1'><entry colsep='1' rowsep='1'><para>0x00 0x02</para></entry><entry colsep='1' rowsep='1'><para> A value of length 2 follows... </para></entry></row><row rowsep='1'><entry colsep='1' rowsep='1'><para>0x39 0x34 </para></entry><entry colsep='1' rowsep='1'><para> "94" </para></entry></row><row rowsep='1'><entry colsep='1' rowsep='1'><para>0x00 0x00</para></entry><entry colsep='1' rowsep='1'><para> A key of length 0. THIS MARKS THE END OF THE PACKET. </para></entry></row></tbody></tgroup></informaltable></section><section><title>Fire and Forget Commands</title><para>With AMP it is possible to fire off a request for which <emphasis><emphasis role='strong'>no result is generated</emphasis></emphasis>, or for which you simply <emphasis><emphasis role='strong'>don't care what the result will be</emphasis></emphasis>. </para><para>You do this by omitting the <emphasis role='strong'>_ask</emphasis> key. The only request key that is absolutely required by the wire-protocol is <emphasis role='strong'>_command</emphasis>. </para></section><section><title>Error Handling</title><para>When something goes wrong making an AMP call the response we get back will be quite different</para><para> than the response we saw above. Instead of the <emphasis role='strong'>_answer</emphasis> key, there is an <emphasis role='strong'>_error</emphasis> key instead. </para><para>For example, the first thing you can do wrong is to make a request for an AMP command which doesn't exist:</para><informaltable><tgroup cols='2'><colspec colname='col_0'/><colspec colname='col_1'/><tbody><row rowsep='1'><entry colsep='1' rowsep='1'><para><emphasis role='strong'>_ask</emphasis> </para></entry><entry colsep='1' rowsep='1'><para>1 </para></entry></row><row rowsep='1'><entry colsep='1' rowsep='1'><para><emphasis role='strong'>_command</emphasis> </para></entry><entry colsep='1' rowsep='1'><para>GetSecretFile </para></entry></row><row rowsep='1'><entry colsep='1' rowsep='1'><para><emphasis role='strong'>path</emphasis> </para></entry><entry colsep='1' rowsep='1'><para>/etc/shadow </para></entry></row></tbody></tgroup></informaltable><para>Presumably the other side won't know anything about a <emphasis role='strong'>GetSecretFile</emphasis> command, so you get this:</para><informaltable><tgroup cols='2'><colspec colname='col_0'/><colspec colname='col_1'/><tbody><row rowsep='1'><entry colsep='1' rowsep='1'><para><emphasis role='strong'>_error</emphasis> </para></entry><entry colsep='1' rowsep='1'><para>1 </para></entry></row><row rowsep='1'><entry colsep='1' rowsep='1'><para><emphasis role='strong'>_error_code</emphasis> </para></entry><entry colsep='1' rowsep='1'><para>UNHANDLED </para></entry></row><row rowsep='1'><entry colsep='1' rowsep='1'><para><emphasis role='strong'>_error_description</emphasis> </para></entry><entry colsep='1' rowsep='1'><para>Unhandled Command: 'GetSecretFile' </para></entry></row></tbody></tgroup></informaltable><para>The string "<emphasis role='strong'>UNHANDLED</emphasis>" is a special code that all compliant AMP implementations use. </para></section><section><title>Custom Errors</title><para>Let's imagine a <emphasis role='strong'>Divide</emphasis> command which takes two integers, <emphasis role='strong'>numerator</emphasis> and <emphasis role='strong'>denominator</emphasis>, and returns</para><para> a floating-point value <emphasis role='strong'>result</emphasis> (the result of <emphasis role='strong'>numerator/denominator</emphasis>). </para><para>Clearly, division can fail if you divide by zero, so we need to define what the <emphasis role='strong'>_error_code</emphasis> will be in that case. </para><para>Using the Twisted implementation we would do it something like this:</para><screen startinglinenumber='1' linenumbering='unnumbered' format='linespecific'><!--RAW HTML: <span class="line"><span class="k">class</span> <span class="nc">Divide</span><span class="p">(</span><span class="n">amp</span><span class="o">.</span><span class="n">Command</span><span class="p">):</span>
</span><span class="line">    <span class="n">arguments</span> <span class="o">=</span> <span class="p">[(</span><span class="s">&#39;numerator&#39;</span><span class="p">,</span> <span class="n">amp</span><span class="o">.</span><span class="n">Integer</span><span class="p">()),</span>
</span><span class="line">                 <span class="p">(</span><span class="s">&#39;denominator&#39;</span><span class="p">,</span> <span class="n">amp</span><span class="o">.</span><span class="n">Integer</span><span class="p">())]</span>
</span><span class="line">    <span class="n">response</span> <span class="o">=</span> <span class="p">[(</span><span class="s">&#39;result&#39;</span><span class="p">,</span> <span class="n">amp</span><span class="o">.</span><span class="n">Float</span><span class="p">())]</span>
</span><span class="line">    <span class="n">errors</span> <span class="o">=</span> <span class="p">{</span><span class="ne">ZeroDivisionError</span><span class="p">:</span> <span class="s">&#39;ZERO_DIVISION&#39;</span><span class="p">}</span>
</span>--></screen><para>Then, if the responder for the <emphasis role='strong'>Divide</emphasis> command raises a <emphasis role='strong'>ZeroDivisionError</emphasis> exception, the response will</para><para> look something like this:</para><informaltable><tgroup cols='2'><colspec colname='col_0'/><colspec colname='col_1'/><tbody><row rowsep='1'><entry colsep='1' rowsep='1'><para><emphasis role='strong'>_error</emphasis> </para></entry><entry colsep='1' rowsep='1'><para>1 </para></entry></row><row rowsep='1'><entry colsep='1' rowsep='1'><para><emphasis role='strong'>_error_code</emphasis> </para></entry><entry colsep='1' rowsep='1'><para>ZERO_DIVISION </para></entry></row><row rowsep='1'><entry colsep='1' rowsep='1'><para><emphasis role='strong'>_error_description</emphasis> </para></entry><entry colsep='1' rowsep='1'><para>float division </para></entry></row></tbody></tgroup></informaltable><para>AMP implementations should then raise this same exception on the client (calling) side. In</para><para> languages without exceptions the raw error code should be made available so that special handling</para><para> may be implemented. </para></section><section><title>Unknown Errors</title><para>So what if something happens that wasn't planned for? AMP doesn't just encode information about</para><para> arbitrary exceptions because this could represent a potentially harmful information leak. And because</para><para> it's just better design to make things <emphasis><emphasis role='strong'>explicit</emphasis></emphasis> rather than <emphasis><emphasis role='strong'>implicit</emphasis></emphasis>. </para><para>Lets say the responder for a given command raises a <emphasis role='strong'>WorldExplodedException</emphasis> for which you have</para><para> <emphasis><emphasis role='strong'>not</emphasis></emphasis> defined an <emphasis role='strong'>_error_code</emphasis>. (What would be the point, after all?) </para><para>You will get something like this:</para><informaltable><tgroup cols='2'><colspec colname='col_0'/><colspec colname='col_1'/><tbody><row rowsep='1'><entry colsep='1' rowsep='1'><para><emphasis role='strong'>_error</emphasis> </para></entry><entry colsep='1' rowsep='1'><para>1 </para></entry></row><row rowsep='1'><entry colsep='1' rowsep='1'><para><emphasis role='strong'>_error_code</emphasis> </para></entry><entry colsep='1' rowsep='1'><para>UNKNOWN </para></entry></row><row rowsep='1'><entry colsep='1' rowsep='1'><para><emphasis role='strong'>_error_description</emphasis> </para></entry><entry colsep='1' rowsep='1'><para>Unknown Error </para></entry></row></tbody></tgroup></informaltable><para>The string "<emphasis role='strong'>UNKNOWN</emphasis>" is a special code that all compliant AMP implementations use. </para><para>Well, that's all there is to error handling! </para></section><section><title>Conclusion</title><para>As you've seen, AMP is simple, efficient and flexible. You can build virtually any kind of</para><para> high-level protocol on top of it. </para><para>Security features are achieved by layering AMP on top of <ulink url='http://en.wikipedia.org/wiki/Transport_Layer_Security'>TLS</ulink>. </para><para>A standard set of rich <ulink url='http://amp-protocol.net/FrontPage/Types#'>data types</ulink> are shipped with the <ulink url='http://amp-protocol.net/FrontPage/ReferenceImplementation#'>reference implementation.</ulink> </para><para>Other <ulink url='http://amp-protocol.net/FrontPage/Implementations#'>implementations</ulink> may or may not provide the full set of types out of the box.</para><para> However, adding custom data types with your own serialization format is fairly simple. </para><para>-- </para><para>Happy AMP'ing! </para></section></article>