User Tools

Site Tools


pawsd:protocol

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
pawsd:protocol [2026/03/30 14:29] – [Verb 4096 (0x1000): Start authentication] winterpawsd:protocol [2026/04/07 17:50] (current) – Verb 2: Query services winter
Line 104: Line 104:
 ^ Field   ^ Length ^ Type    ^ ^ Field   ^ Length ^ Type    ^
 | service | varies | service | | service | varies | service |
 +
 +
 +===== Verb 2: Query services =====
 +
 +The client sends a structured search query to the server, which it performs recursively (up to the specified maximum depth, or until its own depth limit) against all zones it has cached locally. Generally the server shouldn't perform lookups as part of this process unless it can be sure they will complete quickly. The list of matching services returned to the client may therefore be incomplete.
 +
 +Request payload:
 +^ Field               ^ Length    ^ Type                                                       ^
 +| starting zone       | varies >4 | key type, length, key (as in first three fields of verb 1) |
 +| max recursion depth | 1 byte    | u8                                                         |
 +| query               | varies    | service-condition (see below)                              |
 +
 +Recursion starts at the "starting zone" and continues by following edge pointer records (found on service 0 of each zone). If the max recursion depth is 0, it won't follow any edges, and will just check the starting zone itself. At each zone, the query is evaluated against each service of the zone, and matching services (for which the overall result of the query condition is true) are included in the response.
 +
 +The query itself is a tree-like expression, representing a logical combination of comparisons against properties of the service or its records. The <wrap important>**VERY NON-FINAL AND SUBJECT TO CHANGE**</wrap> encoding of query expressions is defined according to the following pseudo-ABNF:
 +
 +<code bnf>
 +service-condition = service-logical / service-comparative
 +                  / all-records / any-records
 +
 +;; boolean operators (T is service, record, or tag)
 +T-logical = T-not / T-and / T-or
 +T-not = %x00 T-condition
 +T-and = %x01 T-condition T-condition
 +T-or = %x02 T-condition T-condition
 +
 +;; numeric operators (=, <, >) (T as above)
 +T-comparative = T-equals / T-lt / T-gt
 +;; for all T-lt and T-gt, the specified value is the
 +;; RHS and the value in the T is the LHS
 +
 +u8 = OCTET
 +u16 = u8 u8
 +u32 = u16 u16
 +u64 = u32 u32
 +tag = u64 u64
 +string = u32 *(u8) ;; length prefixed string, *=u32
 +
 +;; returns true iff service index = 'u16'
 +service-equals = %x03 service-index
 +service-index = u16
 +;; comparisons for the number of records in a service
 +service-lt = %x04 record-count
 +service-gt = %x05 record-count
 +record-count = u16
 +
 +;; both map a condition over all elements of the parent
 +;; returns true iff all matched
 +all-Ts = %x06 T-condition
 +;; returns false iff none matched
 +any-Ts = %x07 T-condition
 +
 +record-condition = record-logical / record-comparative
 +                 / all-tags / any-tags
 +
 +record-lt = %x08 tag-count
 +record-gt = %x09 tag-count
 +tag-count = u16
 +
 +tag-condition = tag-logical / tag-comparative
 +
 +tag-equals = %x0A tag ;; tag ID = ?
 +           / %x0B string ;; tag value = ?
 +           / %x0C string ;; tag value substring match
 +           / %x0D string ;; tag value fuzzy match
 +
 +;; compare tag value as an unsigned int
 +tag-lt = %x0E tag-xt
 +tag-gt = %x0F tag-xt
 +tag-xt = %x01 u8 / %x02 u16 / %x04 u32 / %x08 u64 / %x10 u64 u64
 +</code>
 +
 +The response is a list of matching services grouped by zone:
 +
 +^ Field                                    ^ Length    ^ Type    ^
 +| zone count                               | 2 bytes   | u16     |
 +| zone<sub>1</sub> service count           | 2 bytes   | u16     |
 +| zone<sub>1</sub> service indices         | varies    | [_]u16  |
 +| //zone<sub>2</sub> service count, etc.// |                   |
 +
 +==== Examples ====
 +
 +To fuzzy-search for the string "winter", you would:
 +  * construct a logical query something like ''match any record where [match any tag where [the value fuzzy-matches "winter"]]''
 +    * in a lisp-like syntax you might write that as ''<nowiki>(match-any (match-any (tag-eq 'fuzzy "winter")))</nowiki>''
 +  * encode it accordingly:
 +    * the top-level "parent" is the service, whose elements are records
 +    * so to match against any record, use ''07 <condition>'' (nonterminal "any-Ts")
 +    * inside that condition, the parent is a record, whose elements are tags
 +    * so we use the same again to match against any tag
 +    * inside the sub-condition we want to fuzzy match the tag's value: ''0D <string>'' (part of nonterminal "tag-equals")
 +    * the string itself will just be length-prefixed UTF-8: ''00000006 77696e746572'' in hex
 +  * which results in the final encoded query ''07 07 0D 00000006 77696e746572'' in hex
  
  
pawsd/protocol.txt · Last modified: by winter