PyDECnet uses JSON over HTTPS for its API. It uses the GET method to retrieve information, and POST to make a request, to change something, or to operate on a "connection". Responses and POST request data are encoded using JSON. For fields that contain byte string data (such as packet contents), these are sent as strings, interpreted as Latin-1 text which means each character encodes the corresponding byte value. Node addresses are encoded as an integer. For phase II and III, that is the node number; for Phase IV it is the combined node and area number in the usual form (area number in the upper 6 bits of the 16 bit value). MAC addresses (Ethernet addresses) are encoded as strings, 6 hex byte fields separated by hyphens in the usual representation used by DEC (not colons as is used in some other conventions). For example: "2a-f1-0d-7b-4e-95" or "aa-00-04-00-0b-08". Similarly, Ethernet protocol types are encoded as strings, 2 hex byte fields, for example "60-03". "Connections" are objects that live beyond a single request. The typical example is a DECnet Session Control connection, but MOP Console Carrier client instances are also connections since they have similar properties. Connections live for some time, and represent a full duplex data stream. HTTP is not well adapted to dealing with this. The use pattern in this API is to have separate requests (POST) for the receive and for the transmit streams of the full duplex connnection. Both refer to the connection by a "handle" which is returned when the connection is created. Transmit is a POST with handle and a data argument; the request completes as soon as the data has been buffered (it does not wait for transmission or delivery). Receive is a post with handle but no data argument; the request blocks until data arrives, or after 60 seconds. If you are dealing with a connection that has a request/response or similar "half duplex" data flow, a single stream of API requests, receive or transmit as needed at that point, will work. For applications where data can flow in both directions at the same time, such as a remote terminal application, you will probably need to use two separate API flows, one for the each direction. API requests have to arrive at least once every 120 seconds or the connection will be deleted due to API timeout (this is to compensate for the fact that there is no client connection for the API to which PyDECnet connection liveness can be tied). Note that dictionary fields in the replies are not in any particular order (since that does not affect the meaning). Similarly, unless stated otherwise, lists entries are not in a specific order. The API uses URLs starting with /api, followed by additional path elements to indicate what specifically is to be read or operated on. If a GET is done with a URL consisting only of /api, a dictionary of systems is returned, with the system name as key and a short description of what the system is as the value. For example: { "ERNIE" : [ "Area router", 1026 ], "br-0" : "Bridge" } For any other request, if there are multiple systems in this PyDECnet process (as in the example shown) the system to operate on must be named by a URL argument such as "?system=ERNIE". The system name is case insensitive. The next URL path component after /api indicates which top level component to access. Valid values are: mop, routing, bridge. The requests supported by each component are given below. API for MOP GET request for MOP A GET of /api/mop returns basic information about this MOP, in particular the circuits (data links) it handles. For example: { "circuits" : [ "ETH-102" ] } GET requests for a specific MOP data link GET /api/mop/circuits returns a list of circuit names, for example: [ "ETH-201" ] GET /api/mop/circuits/ returns information about that circuit. For example: { "name" : "ETH-102", "macaddr" : "52-99-bc-a7-67-89", "services" : [ "loop" ] } You can also use * for the circuit name to get a list of items, one for each circuit in this MOP. GET /api/mop/circuits//sysid returns the current contents of the SysID message listener for that circuit. This is only valid for Ethernet circuits. The return value is a list of entries, each of which is a dictionary with keys naming the SysID message fields. For example: [ { "processor" : "Communication Server", "reservation_timer" : 0, "device" : "PCL11-B UNIBUS multiple CPU link", "datalink" : "CSMA-CD", "hwaddr" : "ce-e6-14-13-4f-11", "console_user" : "", "software" : "DECnet/Python", "srcaddr" : "ce-e6-14-13-4f-11" } ] POST requests for MOP MOP allows the following POST requests, addressed to a specific circuit, which must be Ethernet: POST /api/mop/circuits//loop This requests an Ethernet loop operation. The POST data is a JSON encoded dictionary carrying the request parameters: { "dest" : "2e-ca-55-6b-f1-57", "packets" : 3, "timeout" : 3, "fast" : true } All parameters are optional. Dest is either a single destination address, a string in the usual form for Ethernet addresses, or a list of up to three addresses. If omitted, the loopback assistance multicast address CF-00-00-00-00-00 is used. If more than one address is specified, or the destination address is not the loopback assistance address, they must be a unitcast address. The loop packet visits the addresses in the list in that order, so a single address corresponds to a simple loop operation while lists of 2 or 3 entries can be used to implement the "loopback assistant" mechanisms described in the spec, i.e., testing connectivity via some intermediate station. Packets is the number of loop request/response operations to perform, default is 1. Timeout is the response timeout for each request sent, in seconds, default is 3. Fast is a Boolean, default is false. If false, there is a one second delay after each successful loop exchange (not after a timeout because we already waited for the timeout delay); if true, the next request is sent immediately upon receipt of the preceding reply, which should be done with caution because of the added load on the network. The reply is a dictionary containing the overall operation status and a list of round trip delays, in seconds (floating point). Timeout is represented by a value of -1. There is one list entry per loop packet. If the destination address was the loopback assistance multicast address, that is only used for the first request and the address of whichever station replies first is used for subsequent requests; in addition, that address is also returned in the reply. For example: { "status" : "ok", "dest" : "aa-00-04-00-0b-08", "delays" : [ 0.0015108585357666, 0.00301599502563477, 0.00173497200012207, 0.00295305252075195, 0.00289678573608398 ] } POST /api/mop/circuits//console This begins, continues, or terminates a console carrier session. To continue or terminate a session, the session handle returned by the request to begin the session must be included. For the request to begin a session, the POST data is a JSON encoded dictionary carrying the request parameters: "dest" (the destination MAC address) and "verification" (the MOP console carrier verification string, essentially an access password. Both are required. For example: { "verification" : "Plugh", "dest" : "aa-00-04-00-0b-08" } The response is status and, if successful, the session handle: { "handle" : 8246003421459976741, "status" : "ok" } Once the session is created, the API user must issue subsequent requests within 60 seconds, and when the last pending request completes must issue another within 60 seconds. If not, the session times out and is closed. To read or write a console carrier session, the POST data is a JSON encoded dictionary containing the handle returned by the session begin. For a write, it contains a "data" argument with the data to send; a read omits that argument. The return is a dictionary containing status, and in the case of a read, the data. Data may be null if the read timed out (but status is still ok in that case). { "data" : "login: ", "status" : "ok" } To terminate a console carrier session, the POST data is a JSON encoded dictionary with handle and the "close" flag, for example: { "handle" : 8246003421459976741, "close" : 1 } On completion, the console session has been closed, including the release of the console reservation at the destination. POST /api/mop/circuits//counters This operation issues a MOP Request Counters message to a station on the specified Ethernet. The request data is a JSON encoded dictionary specifying the request parameters: { "dest" : "f2-63-1f-8d-f8-94", "timeout" : 2 } Timeout is an optional timeout for the request, in seconds. Default is 3 seconds. The reply is a JSON encoded dictionary reporting the counters obtained from the station, or an error status indicating failure to obtain the information. For example: { "status" : "timeout" } or { "pkts_sent" : 0, "bytes_sent" : 0, "ctr_zero_time" : 65535, "unk_dest" : 0, "bytes_recd" : 0, "mcpkts_recd" : 0, "mcbytes_recd" : 0, "status" : "ok", "pkts_recd" : 0 } API for Routing GET for routing A GET request to routing returns some basic information about the DECnet node, and a list of circuit names. For example: { "version" : "2.0.0", "circuits" : [ "MUL-0", "ETH-102" ], "name" : "ERNIE", "type" : "Area router", "address" : 1026 } GET requests for a specific Routing circuit A GET request addressed to api/routing/circuits returns a list of the circuit names. A GET request addressed to api/routing/circuits/ returns information that circuit. You may use * for to get a list of circuit information for all the circuits in this routing layer. The information returned depends on whether the circuit is point to point (such as DDCMP) or a LAN circuit (Ethernet). Example of point to point circuit response: { "hello_timer" : 60, "listen_timer" : 120, "cost" : 1, "state" : "ru", "blocksize" : 576, "type" : "Area router", "neighbor" : 2049, "version" : "2.0.0", "name" : "MUL-0" } For a LAN circuit on a router, the response includes a list of adjacencies, each of which gives a dictionary of attributes for that particular adjacency. For example: { "name" : "ETH-102", "cost" : 1, "priority" : 64, "is_dr" : true, "designated_router" : 2049 "hello_timer" : 10, "adjacencies" : [ { "priority" : 64, "type" : "Area router", "neighbor" : 2049, "listen_timer" : 30, "version" : "2.0.0", "blocksize" : 591 } ] } For a LAN circuit on an end node, the response shows the current designated router, if known. For example: { "name" : "ETH-102", "hello_timer" : 10, "designated_router" : { "type" : "Area router", "version" : "2.0.0", "blocksize" : 591, "priority" : 64, "neighbor" : 2049, "listen_timer" : 30 } } API for Bridge A GET request for the bridge returns the bridge name and a list of circuits, for example: { "name" : "br-0", "circuits" : [ "ETH-42", "ETH-43" ] } A GET request addressed to api/bridge/circuits returns a list of circuits in this bridge. A GET request addressed to api/bridge/circuits/ returns information about that circuit. You can use * for to get back a list of information for all the circuits in this bridge. The reply for a circuit gives the circuit name and the list of Ethernet protocol types enabled for bridging on that circuit, for example: { "name" : "ETH-43", "protocols" : [ "90-00", "60-04", "60-01", "60-02", "60-03" ] } A GET request to bridge/addrdb returns the address database (forwarding database) of the bridge, in the form of a dictionary keyed by destination MAC address with the circuit to forward to as the value. For example: { "aa-00-04-00-01-08" : "ETH-43", "aa-00-04-00-0b-08" : "ETH-42" } API for Session POST requests to the session layer implement the session control API, allowing DECnet applications to be written as programs that request service from the session layer via the API. Such programs may request outbound connections, or handle inbound ones, or both. A simple example can be found in samples/mirror.py, which implements the standard Mirror protocol via the API. Note that normally Mirror is a built-in object (its code is in decnet/applications/mirror.py) but it is possible to override that by specifying a file to execute instead, using: object --number 25 --file samples/mirror.py