idnits 2.17.1 draft-ietf-alto-incr-update-sse-16.txt: Checking boilerplate required by RFC 5378 and the IETF Trust (see https://trustee.ietf.org/license-info): ---------------------------------------------------------------------------- No issues found here. Checking nits according to https://www.ietf.org/id-info/1id-guidelines.txt: ---------------------------------------------------------------------------- No issues found here. Checking nits according to https://www.ietf.org/id-info/checklist : ---------------------------------------------------------------------------- ** The document seems to lack separate sections for Informative/Normative References. All references will be assumed normative when checking for downward references. ** The abstract seems to contain references ([RFC7285]), which it shouldn't. Please replace those with straight textual mentions of the documents in question. Miscellaneous warnings: ---------------------------------------------------------------------------- == The copyright year in the IETF Trust and authors Copyright Line does not match the current year == Line 843 has weird spacing: '...atesReq add;...' -- The document date (March 10, 2019) is 1873 days in the past. Is this intentional? -- Found something which looks like a code comment -- if you have code sections in the document, please surround them with '' and '' lines. Checking references for intended status: Proposed Standard ---------------------------------------------------------------------------- (See RFCs 3967 and 4897 for information about using normative references to lower-maturity documents in RFCs) == Missing Reference: 'Name' is mentioned on line 373, but not defined == Missing Reference: 'TBD' is mentioned on line 1557, but not defined ** Obsolete normative reference: RFC 7159 (Obsoleted by RFC 8259) ** Obsolete normative reference: RFC 7230 (Obsoleted by RFC 9110, RFC 9112) ** Obsolete normative reference: RFC 7231 (Obsoleted by RFC 9110) ** Obsolete normative reference: RFC 7540 (Obsoleted by RFC 9113) -- Possible downref: Non-RFC (?) normative reference: ref. 'SSE' Summary: 6 errors (**), 0 flaws (~~), 4 warnings (==), 3 comments (--). Run idnits with the --verbose option for more detailed information about the items above. -------------------------------------------------------------------------------- 2 ALTO WG W. Roome 3 Internet-Draft Nokia Bell Labs 4 Intended status: Standards Track Y. Yang 5 Expires: September 11, 2019 Yale University 6 March 10, 2019 8 ALTO Incremental Updates Using Server-Sent Events (SSE) 9 draft-ietf-alto-incr-update-sse-16 11 Abstract 13 The Application-Layer Traffic Optimization (ALTO) [RFC7285] protocol 14 provides network related information, called network information 15 resources, to client applications so that clients can make informed 16 decisions in utilizing network resources. For example, an ALTO 17 server can provide network and cost maps so that an ALTO client can 18 use the maps to determine the costs between network endpoints when 19 choosing communicating endpoints. 21 However, the ALTO protocol does not define a mechanism to allow an 22 ALTO client to obtain updates to the information resources, other 23 than by periodically re-fetching them. Because some information 24 resources (e.g., the aforementioned maps) may be large (potentially 25 tens of megabytes), and because only parts of the information 26 resources may change frequently (e.g., only some entries in a cost 27 map), complete re-fetching can be extremely inefficient. 29 This document presents a mechanism to allow an ALTO server to push 30 updates to ALTO clients, to achieve two benefits: (1) updates can be 31 immediate, in that the ALTO server can send updates as soon as they 32 are available; and (2) updates can be incremental, in that if only a 33 small section of an information resource changes, the ALTO server can 34 send just the changes. 36 Requirements Language 38 The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", 39 "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this 40 document are to be interpreted as described in RFC 2119 [RFC2119]. 42 Status of This Memo 44 This Internet-Draft is submitted in full conformance with the 45 provisions of BCP 78 and BCP 79. 47 Internet-Drafts are working documents of the Internet Engineering 48 Task Force (IETF). Note that other groups may also distribute 49 working documents as Internet-Drafts. The list of current Internet- 50 Drafts is at http://datatracker.ietf.org/drafts/current/. 52 Internet-Drafts are draft documents valid for a maximum of six months 53 and may be updated, replaced, or obsoleted by other documents at any 54 time. It is inappropriate to use Internet-Drafts as reference 55 material or to cite them other than as "work in progress." 57 This Internet-Draft will expire on September 11, 2019. 59 Copyright Notice 61 Copyright (c) 2019 IETF Trust and the persons identified as the 62 document authors. All rights reserved. 64 This document is subject to BCP 78 and the IETF Trust's Legal 65 Provisions Relating to IETF Documents 66 (http://trustee.ietf.org/license-info) in effect on the date of 67 publication of this document. Please review these documents 68 carefully, as they describe your rights and restrictions with respect 69 to this document. Code Components extracted from this document must 70 include Simplified BSD License text as described in Section 4.e of 71 the Trust Legal Provisions and are provided without warranty as 72 described in the Simplified BSD License. 74 Table of Contents 76 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3 77 2. Major Changes Since Version -01 . . . . . . . . . . . . . . . 4 78 3. Terms . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 79 4. Background . . . . . . . . . . . . . . . . . . . . . . . . . 6 80 4.1. Server-Sent Events (SSEs) . . . . . . . . . . . . . . . . 6 81 4.2. JSON Merge Patch . . . . . . . . . . . . . . . . . . . . 7 82 4.2.1. JSON Merge Patch Encoding . . . . . . . . . . . . . . 7 83 4.2.2. JSON Merge Patch ALTO Messages . . . . . . . . . . . 9 84 4.3. JSON Patch . . . . . . . . . . . . . . . . . . . . . . . 12 85 4.3.1. JSON Patch Encoding . . . . . . . . . . . . . . . . . 12 86 4.3.2. JSON Patch ALTO Messages . . . . . . . . . . . . . . 13 87 5. Overview of Approach . . . . . . . . . . . . . . . . . . . . 14 88 6. Update Messages: Data Update and Control Update Messages . . 16 89 6.1. ALTO Update Message Format . . . . . . . . . . . . . . . 16 90 6.2. ALTO Data Update Message . . . . . . . . . . . . . . . . 17 91 6.3. ALTO Control Update Message . . . . . . . . . . . . . . . 18 92 7. Update Stream Service . . . . . . . . . . . . . . . . . . . . 19 93 7.1. Media Type . . . . . . . . . . . . . . . . . . . . . . . 19 94 7.2. HTTP Method . . . . . . . . . . . . . . . . . . . . . . . 19 95 7.3. Accept Input Parameters . . . . . . . . . . . . . . . . . 19 96 7.4. Capabilities . . . . . . . . . . . . . . . . . . . . . . 20 97 7.5. Uses . . . . . . . . . . . . . . . . . . . . . . . . . . 21 98 7.6. Response . . . . . . . . . . . . . . . . . . . . . . . . 22 99 7.7. Additional Requirements on Update Messages . . . . . . . 23 100 7.7.1. Event Sequence Requirements . . . . . . . . . . . . . 23 101 7.7.2. Cross-Stream Consistency Requirements . . . . . . . . 24 102 7.8. Keep-Alive Messages . . . . . . . . . . . . . . . . . . . 24 103 8. Stream Control Service . . . . . . . . . . . . . . . . . . . 24 104 8.1. URI . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 105 8.2. Media Type . . . . . . . . . . . . . . . . . . . . . . . 25 106 8.3. HTTP Method . . . . . . . . . . . . . . . . . . . . . . . 25 107 8.4. Accept Input Parameters . . . . . . . . . . . . . . . . . 25 108 8.5. Capabilities & Uses . . . . . . . . . . . . . . . . . . . 26 109 8.6. Response . . . . . . . . . . . . . . . . . . . . . . . . 26 110 9. Examples . . . . . . . . . . . . . . . . . . . . . . . . . . 27 111 9.1. Example: IRD Announcing Update Stream Services . . . . . 27 112 9.2. Example: Simple Network and Cost Map Updates . . . . . . 29 113 9.3. Example: Advanced Network and Cost Map Updates . . . . . 32 114 9.4. Example: Endpoint Property Updates . . . . . . . . . . . 36 115 10. Operation and Processing Considerations . . . . . . . . . . . 39 116 10.1. Considerations for Choosing SSE Line Lengths . . . . . . 39 117 10.2. Considerations for Choosing Data Update Messages . . . . 40 118 10.3. Considerations for Client Processing Data Update 119 Messages . . . . . . . . . . . . . . . . . . . . . . . . 41 120 10.4. Considerations for Updates to Filtered Cost Maps . . . . 42 121 10.5. Considerations for Updates to Ordinal Mode Costs . . . . 42 122 11. Security Considerations . . . . . . . . . . . . . . . . . . . 42 123 11.1. Update Stream Server: Denial-of-Service Attacks . . . . 43 124 11.2. ALTO Client: Update Overloading or Instability . . . . . 43 125 11.3. Stream Control: Spoofed Control Requests . . . . . . . . 43 126 12. Requirements on Future ALTO Services to Use this Design . . . 44 127 13. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 44 128 14. Alternative Designs Not Supported . . . . . . . . . . . . . . 46 129 14.1. Why Not HTTP/2 Server-Push . . . . . . . . . . . . . . . 46 130 14.2. Why Not Allowing Stream Restart . . . . . . . . . . . . 47 131 15. Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . 48 132 16. References . . . . . . . . . . . . . . . . . . . . . . . . . 48 133 Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 49 135 1. Introduction 137 The Application-Layer Traffic Optimization (ALTO) [RFC7285] protocol 138 provides network related information called network information 139 resources to client applications so that clients may make informed 140 decisions in utilizing network resources. For example, an ALTO 141 server provides network and cost maps, where a network map partitions 142 the set of endpoints into a manageable number of sets each defined by 143 a Provider-Defined Identifier (PID), and a cost map provides directed 144 costs between PIDs. Given network and cost maps, an ALTO client can 145 obtain costs between endpoints by first using the network map to get 146 the PID for each endpoint, and then using the cost map to get the 147 costs between those PIDs. Such costs can be used by the client to 148 choose communicating endpoints with low network costs. 150 The ALTO protocol defines only an ALTO client pull model, without 151 defining a mechanism to allow an ALTO client to obtain updates to 152 network information resources, other than by periodically re-fetching 153 them. In settings where an information resource may be large but 154 only parts of it may change frequently (e.g., some entries of a cost 155 map), complete re-fetching can be inefficient. 157 This document presents a mechanism to allow an ALTO server to push 158 incremental updates to ALTO clients. Integrating server-push and 159 incremental updates provides two benefits: (1) updates can be 160 immediate, in that the ALTO server can send updates as soon as they 161 are available; and (2) updates can be small, in that if only a small 162 section of an information resource changes, the ALTO server can send 163 just the changes. 165 While primarily intended to provide updates to GET-mode network and 166 cost maps, the mechanism defined in this document can also provide 167 updates to POST-mode ALTO services, such as the endpoint property and 168 endpoint cost services. We intend that the mechanism can also 169 support new ALTO services to be defined by future extensions, but a 170 future service needs to satisfy requirements specified in Section 12. 172 The rest of this document is organized as follows. Section 4 gives 173 background on the basic techniques used in this design: (1) Server- 174 Sent Events to allow server push; (2) JSON merge patch and JSON patch 175 to allow incremental update. With the background, Section 5 gives a 176 non-normative overview of the design. Section 6 defines individual 177 messages in an update stream, and Section 7 defines the overall 178 update stream service; Section 8 defines the stream control service; 179 Section 9 gives several examples; Section 10 describes operation and 180 processing considerations by both ALTO servers and clients; 181 Section 14 discusses two design features that are not supported; 182 Section 11 discusses security issues; The last two sections review 183 the requirements for future ALTO services to use SSE and IANA 184 considerations, respectively. 186 2. Major Changes Since Version -01 188 To RFC editor: This will be removed in the final version. We keep 189 this section to make clear major changes in the technical content. 191 o Incremental encoding: Added JSON patch as an alternative 192 incremental delta encoding. 194 o Client-assigned client-id to allow concurrent updates of the same 195 server resource: The client now assigns a unique client-id to each 196 resource in an update stream. The server puts the client-id in 197 each update event for that resource (before, the server used the 198 server's resource-id). This allows a client to use one update 199 stream to receive updates to multiple requests for the same server 200 resource, for example, for a POST-mode resource; before, that 201 required separate update streams. 203 o Flexible control: Defined a new "stream control" resource 204 (Section 8) to allow a client to add or remove resources from a 205 previously created update stream. The ALTO server creates a new 206 stream control resource for each update stream instance, assigns a 207 unique URI to it, and sends the URI to the client as the first 208 event in the stream. 210 3. Terms 212 This document uses the following terms: Update Stream, Update Stream 213 Server, Update Message, Data Update Message, Full Replacement, 214 Incremental Change, Control Update Message, Stream Control Service, 215 Stream Control. 217 Update Stream: An update stream is an HTTP connection between an ALTO 218 client and an ALTO server so that the server can push a sequence of 219 update messages using SSE to the client. 221 Update Stream Server: We refer to an ALTO server providing an update 222 stream as an ALTO update stream server, or update stream server for 223 short. Note that the ALTO server mentioned in this document refers 224 to a general server that provides various kinds of services; it can 225 be an update stream server or stream control server (see below); it 226 can also be a server providing ALTO IRD information. 228 Update Message: An update message is either a data update message or 229 a control update message. 231 Data Update Message: A data update message is for a single ALTO 232 information resource and sent from the update stream server to the 233 ALTO client when the resource changes. A data update message can be 234 either a full-replacement message or an incremental-change message. 235 Full replacement is a shorthand for a full-replacement message, and 236 incremental change is a shorthand for an incremental-change message. 238 Full Replacement: A full replacement for a resource encodes the 239 content of the resource in its original ALTO encoding. 241 Incremental Change: An incremental change specifies only the 242 difference between the new content and the previous version. An 243 incremental change can be encoded using either JSON merge patch or 244 JSON patch in this document. 246 Stream Control Service: An stream control service provides an HTTP 247 URI so that the ALTO client of an update stream can use it to send 248 stream control requests on the addition or removal of resources 249 receiving update messages from the update stream. 251 Stream Control: A shorthand for stream control service. 253 Stream Control Server: An stream control server providing the stream 254 control service. 256 Control Update Message: A control update message is a message in an 257 update stream for the update stream server to notify the ALTO client 258 of related control information of the update stream. The first 259 message of an update stream is a control update message and provides 260 the URI using which the ALTO client can send stream control requests 261 to the stream control server. Additional control update messages in 262 an update stream allow the update stream server to notify the ALTO 263 client of status changes (e.g., the server will no longer send 264 updates for an information resource). 266 4. Background 268 The design requires two basic techniques: server push and encoding of 269 incremental changes. Using existing techniques whenever possible, 270 this design uses Server-Sent Events (SSEs) for server push; JSON 271 merge patch and JSON patch to encode incremental changes. Below we 272 give a non-normative summary of these two techniques. 274 4.1. Server-Sent Events (SSEs) 276 The following is a non-normative summary of SSE; see [SSE] for its 277 normative definition. 279 Server-Sent Events enable a server to send new data to a client by 280 "server-push". The client establishes an HTTP ([RFC7230], [RFC7231]) 281 connection to the server and keeps the connection open. The server 282 continually sends messages. Each message has one or more lines, 283 where a line is terminated by a carriage-return immediately followed 284 by a new-line, a carriage-return not immediately followed by a new- 285 line, or a new-line not immediately preceded by a carriage-return. A 286 message is terminated by a blank line (two line terminators in a 287 row). 289 Each line in a message is of the form "field-name: string value". 290 Lines with a blank field-name (that is, lines which start with a 291 colon) are ignored, as are lines which do not have a colon. The 292 protocol defines three field names: event, id, and data. If a 293 message has more than one "data" line, the value of the data field is 294 the concatenation of the values on those lines. There can be only 295 one "event" and "id" line per message. The "data" field is required; 296 the others are optional. 298 Figure 1 is a sample SSE stream, starting with the client request. 299 The server sends three events and then closes the stream. 301 (Client request) 302 GET /stream HTTP/1.1 303 Host: example.com 304 Accept: text/event-stream 306 (Server response) 307 HTTP/1.1 200 OK 308 Connection: keep-alive 309 Content-Type: text/event-stream 311 event: start 312 id: 1 313 data: hello there 315 event: middle 316 id: 2 317 data: let's chat some more ... 318 data: and more and more and ... 320 event: end 321 id: 3 322 data: goodbye 324 Figure 1: A Sample SSE stream. 326 4.2. JSON Merge Patch 328 4.2.1. JSON Merge Patch Encoding 330 To avoid always sending complete data, a server needs mechanisms to 331 encode incremental changes. This design uses JSON merge patch as one 332 mechanism. Below is a non-normative summary of JSON merge patch; see 333 [RFC7396] for the normative definition. 335 JSON merge patch is intended to allow applications to update server 336 resources via the HTTP patch method [RFC5789]. This document adopts 337 the JSON merge patch message format to encode incremental changes, 338 but uses a different transport mechanism. 340 Informally, a JSON merge patch object is a JSON data structure that 341 defines how to transform one JSON value into another. Specifically, 342 JSON merge patch treats the two JSON values as trees of nested JSON 343 objects (dictionaries of name-value pairs), where the leaves are 344 values (e.g., JSON arrays, strings, numbers) other than JSON objects 345 and the path for each leaf is the sequence of keys leading to that 346 leaf. When the second tree has a different value for a leaf at a 347 path, or adds a new leaf, the JSON merge patch tree has a leaf, at 348 that path, with the new value. When a leaf in the first tree does 349 not exist in the second tree, the JSON merge patch tree has a leaf 350 with a JSON "null" value. The JSON merge patch tree does not have an 351 entry for any leaf that has the same value in both versions. 353 As a result, if all leaf values are simple scalars, JSON merge patch 354 is a quite efficient representation of incremental changes. It is 355 less efficient when leaf values are arrays, because JSON merge patch 356 replaces arrays in their entirety, even if only one entry changes. 358 Formally, the process of applying a JSON merge patch is defined by 359 the following recursive algorithm, as specified in [RFC7396]: 361 define MergePatch(Target, Patch) { 362 if Patch is an Object { 363 if Target is not an Object { 364 Target = {} # Ignore the contents and 365 # set it to an empty Object 366 } 367 for each Name/Value pair in Patch { 368 if Value is null { 369 if Name exists in Target { 370 remove the Name/Value pair from Target 371 } 372 } else { 373 Target[Name] = MergePatch(Target[Name], Value) 374 } 375 } 376 return Target 377 } else { 378 return Patch 379 } 380 } 382 Note that null as the value of a name/value pair will delete the 383 element with "name" in the original JSON value. 385 4.2.2. JSON Merge Patch ALTO Messages 387 To provide both examples of JSON merge patch and a demonstration of 388 the feasibility of applying JSON merge patch to ALTO, we look at the 389 application of JSON merge patch to two key ALTO messages. 391 4.2.2.1. JSON Merge Patch Network Map Messages 393 Section 11.2.1.6 of [RFC7285] defines the format of an ALTO network 394 map message. Assume a simple example ALTO message sending an initial 395 network map: 397 { 398 "meta" : { 399 "vtag": { 400 "resource-id" : "my-network-map", 401 "tag" : "da65eca2eb7a10ce8b059740b0b2e3f8eb1d4785" 402 } 403 }, 404 "network-map" : { 405 "PID1" : { 406 "ipv4" : [ "192.0.2.0/24", "198.51.100.0/25" ] 407 }, 408 "PID2" : { 409 "ipv4" : [ "198.51.100.128/25" ] 410 }, 411 "PID3" : { 412 "ipv4" : [ "0.0.0.0/0" ], 413 "ipv6" : [ "::/0" ] 414 } 415 } 416 } 418 Consider the following JSON merge patch update message, which (1) 419 adds an ipv4 prefix "193.51.100.0/25" and an ipv6 prefix 420 "2001:db8:8000::/33" to "PID1", (2) deletes "PID2", and (3) assigns a 421 new "tag" to the network map: 423 { 424 "meta" : { 425 "vtag" : { 426 "tag" : "a10ce8b059740b0b2e3f8eb1d4785acd42231bfe" 427 } 428 }, 429 "network-map": { 430 "PID1" : { 431 "ipv4" : [ "192.0.2.0/24", "198.51.100.0/25", 432 "193.51.100.0/25" ], 433 "ipv6" : [ "2001:db8:8000::/33" ] 434 }, 435 "PID2" : null 436 } 437 } 439 Applying the JSON merge patch update to the initial network map is 440 equivalent to the following ALTO network map: 442 { 443 "meta" : { 444 "vtag": { 445 "resource-id" : "my-network-map", 446 "tag" : "a10ce8b059740b0b2e3f8eb1d4785acd42231bfe" 447 } 448 }, 449 "network-map" : { 450 "PID1" : { 451 "ipv4" : [ "192.0.2.0/24", "198.51.100.0/25", 452 "193.51.100.0/25" ], 453 "ipv6" : [ "2001:db8:8000::/33" ] 454 }, 455 "PID3" : { 456 "ipv4" : [ "0.0.0.0/0" ], 457 "ipv6" : [ "::/0" ] 458 } 459 } 460 } 462 4.2.2.2. JSON Merge Patch Cost Map Messages 464 Section 11.2.3.6 of [RFC7285] defines the format of an ALTO cost map 465 message. Assume a simple example ALTO message for an initial cost 466 map: 468 { 469 "meta" : { 470 "dependent-vtags" : [ 471 {"resource-id": "my-network-map", 472 "tag": "a10ce8b059740b0b2e3f8eb1d4785acd42231bfe" 473 } 474 ], 475 "cost-type" : { 476 "cost-mode" : "numerical", 477 "cost-metric": "routingcost" 478 }, 479 "vtag": { 480 "resource-id" : "my-cost-map", 481 "tag" : "3ee2cb7e8d63d9fab71b9b34cbf764436315542e" 482 } 483 }, 484 "cost-map" : { 485 "PID1": { "PID1": 1, "PID2": 5, "PID3": 10 }, 486 "PID2": { "PID1": 5, "PID2": 1, "PID3": 15 }, 487 "PID3": { "PID1": 20, "PID2": 15 } 488 } 489 } 491 The following JSON merge patch message updates the example cost map 492 so that (1) the "tag" field of the cost map is updated, (2) the cost 493 of PID1->PID2 is 9 instead of 5, (3) the cost of PID3->PID1 is no 494 longer available, and (4) the cost of PID3->PID3 is defined as 1. 496 { 497 "meta" : { 498 "vtag": { 499 "tag": "c0ce023b8678a7b9ec00324673b98e54656d1f6d" 500 } 501 } 502 "cost-map" : { 503 "PID1" : { "PID2" : 9 }, 504 "PID3" : { "PID1" : null, "PID3" : 1 } 505 } 506 } 508 Hence applying the JSON merge patch to the initial cost map is 509 equivalent to the following ALTO cost map: 511 { 512 "meta" : { 513 "dependent-vtags" : [ 514 {"resource-id": "my-network-map", 515 "tag": "a10ce8b059740b0b2e3f8eb1d4785acd42231bfe" 516 } 517 ], 518 "cost-type" : { 519 "cost-mode" : "numerical", 520 "cost-metric": "routingcost" 521 }, 522 "vtag": { 523 "resource-id": "my-cost-map", 524 "tag": "c0ce023b8678a7b9ec00324673b98e54656d1f6d" 525 } 526 }, 527 "cost-map" : { 528 "PID1": { "PID1": 1, "PID2": 9, "PID3": 10 }, 529 "PID2": { "PID1": 5, "PID2": 1, "PID3": 15 }, 530 "PID3": { "PID2": 15, "PID3": 1 } 531 } 532 } 534 4.3. JSON Patch 536 4.3.1. JSON Patch Encoding 538 One issue of JSON merge patch is that it does not handle array 539 changes well. In particular, JSON merge patch considers an array as 540 a single object and hence can only replace an array in its entirety. 541 When the change is to make a small change to an array such as the 542 deletion of an element from a large array, whole-array replacement is 543 inefficient. Consider the example in Section 4.2.2.1. To add a new 544 entry to the ipv4 array for PID1, the server needs to send a whole 545 new array. Another issue is that JSON merge patch cannot change a 546 value to be null, as the JSON merge patch processing algorithm 547 (MergePatch in Section 4.2.1) interprets a null as a removal 548 instruction. On the other hand, some ALTO resources can have null 549 values, and it is possible that the update will want to change the 550 new value to be null. 552 JSON patch [RFC6902] can address the preceding issues. It defines a 553 set of operators to modify a JSON object. Below is a non-normative 554 description of JSON patch; see [RFC6902] for the normative 555 definition. 557 4.3.2. JSON Patch ALTO Messages 559 To provide both examples of JSON patch and a demonstration of the 560 difference between JSON patch and JSON merge patch, we take a look at 561 the application of JSON patch to the same updates shown in 562 Section 4.2.2. 564 4.3.2.1. JSON Patch Network Map Messages 566 First consider the same update as in Section 4.2.2.1 for the network 567 map. Below is the encoding using JSON patch: 569 [ 570 { 571 "op": "replace", 572 "path": "/meta/vtag/tag", 573 "value": "a10ce8b059740b0b2e3f8eb1d4785acd42231bfe" 574 }, 575 { 576 "op": "add", 577 "path": "/network-map/PID1/ipv4/2", 578 "value": "193.51.100.0/25" 579 } 580 { 581 "op": "add", 582 "path": "/network-map/PID1/ipv6", 583 "value": ["2001:db8:8000::/33"] 584 }, 585 { 586 "op": "remove", 587 "path": "/network-map/PID2" 588 } 589 ] 591 4.3.2.2. JSON Patch Cost Map Messages 593 Compared with JSON merge patch, JSON patch does not encode cost map 594 updates efficiently. Consider the cost map update shown in 595 Section 4.2.2.2, the encoding using JSON patch is: 597 [ 598 { 599 "op": "replace", 600 "path": "/meta/vtag/tag", 601 "value": "c0ce023b8678a7b9ec00324673b98e54656d1f6d" 602 }, 603 { 604 "op": "replace", 605 "path": "/cost-map/PID1/PID2", 606 "value": 9 607 }, 608 { 609 "op": "remove", 610 "path": "/cost-map/PID3/PID1" 611 }, 612 { 613 "op": "replace", 614 "path": "/cost-map/PID3/PID3", 615 "value": 1 616 } 617 ] 619 5. Overview of Approach 621 With the preceding background, we now give a non-normative overview 622 of the update mechanism to be defined in later sections of this 623 document. 625 The building block of the update mechanism defined in this document 626 is the update stream service (defined in Section 7), where each 627 update stream service is a POST-mode service that provides update 628 streams. When an ALTO client requests an update stream service, the 629 ALTO client establishes a persistent connection to the update stream 630 server, creating an update stream. The update stream server uses the 631 update stream to continuously send a sequence of update messages 632 (defined in Section 6) to the ALTO client. An update stream can 633 provide updates to both GET-mode resources, such as ALTO network and 634 cost maps, and POST-mode resources, such as ALTO endpoint property 635 service. 637 An ALTO server may provide any number of update stream services, 638 where each update stream may provide updates for a given subset of 639 the ALTO server's resources. An ALTO server's Information Resource 640 Directory (IRD) defines the update stream services and declares the 641 set of resources for which each update stream service provides 642 updates. The ALTO server selects the resource set for each update 643 stream service. It is recommended that if a resource depends on one 644 or more other resource(s) (indicated with the "uses" attribute 645 defined in [RFC7285]), these other resource(s) should also be part of 646 that update stream. Thus the update stream for a cost map should 647 also provide updates for the network map on which that cost map 648 depends. 650 An ALTO client may request any number of update streams 651 simultaneously. Because each update stream consumes resources on the 652 update stream server, an update stream server may require client 653 authorization and/or authentication, limit the number of open update 654 streams, close inactive streams, or redirect an ALTO client to 655 another update stream server. 657 The key objective of an update stream is to update the ALTO client on 658 data value changes to ALTO resources. We refer to messages sending 659 such updates as data update messages. Although an update stream may 660 update one or more ALTO resources, each data update message updates 661 only one resource and is sent as a Server-Sent Event (SSE), as 662 defined by [SSE]. A data update message is encoded either as a full 663 replacement or as an incremental change. A full replacement uses the 664 JSON message format defined by the ALTO protocol. There can be 665 multiple encodings for incremental changes. The current design 666 supports incremental changes using JSON merge patch ([RFC7396]) or 667 JSON patch ([RFC6902]) to describe the changes of the resource. 668 Future documents may define additional mechanisms for incremental 669 changes. The update stream server decides when to send data update 670 messages, and whether to send full replacements or incremental 671 changes. These decisions can vary from resource to resource and from 672 update to update. 674 An update stream can run for a long time, and hence there can be 675 status changes at the update stream server side during the lifetime 676 of an update stream; for example, the update stream server may 677 encounter an error or need to shut down for maintenance. To support 678 robust, flexible protocol design, this design allows the update 679 stream server to send server control updates (vs data updates) to the 680 ALTO client as well, showing as control update messages from the 681 update stream server to the ALTO client. 683 ------------------------------------------------------------------ 684 | | 685 | +-------+ +-------+ init request +-------+ | 686 | | | | | <---------- | | | 687 | add/remove | | | | | | | 688 | resource |Stream | |Update | data update | | | 689 ---------> |Control| private |Stream | messages |Client | -- 690 |Server |<------->|Server | -----------> | | 691 ---------- | | | | | | <- 692 | response | | | | -----------> | | | 693 | | | | | control update| | | 694 | +-------+ +-------+ messages +-------+ | 695 | | 696 ------------------------------------------------------------------ 698 Figure 2: ALTO SSE Architecture. 700 In addition to control changes triggered from the update stream 701 server side, in a flexible design, an ALTO client may initiate 702 control changes as well, in particular, by adding or removing ALTO 703 resources receiving updates. An ALTO client initiates such changes 704 using the stream control service. Although one may use a design that 705 the client uses the same HTTP connection to send the control 706 requests, it requires stronger server support such as HTTP pipeline. 707 For more flexibility, this document introduces stream control 708 service. In particular, the update stream server of an update stream 709 uses the first message to provide the URI of the stream control 710 service. The ALTO client can then use the URI to ask the update 711 stream server to (1) send data update messages for additional 712 resources, (2) stop sending data update messages for previously 713 requested resources, or (3) gracefully stop and close the update 714 stream altogether. Figure 2 shows the complete ALTO SSE 715 architecture. 717 6. Update Messages: Data Update and Control Update Messages 719 We now define the details of ALTO SSE. Specifically, an update 720 stream consists of a stream of data update messages (Section 6.2) and 721 control update messages (Section 6.3). 723 6.1. ALTO Update Message Format 725 Data update and control update messages have the same basic 726 structure. The data field is a JSON object, and the event field 727 contains the media type of the data field and an optional client-id. 728 Data update messages use the client-id to identify the ALTO resource 729 to which the update message applies. Client-ids MUST follow the 730 rules for ALTO ResourceIds (Section 10.2 of [RFC7285]). Client-ids 731 MUST be unique within an update stream, but need not be globally 732 unique. For example, if an ALTO client requests updates for both a 733 cost map and its dependent network map, the ALTO client might assign 734 client-id "1" to the network map and client-id "2" to the cost map. 735 Alternatively, the ALTO client could use the client-ids for those two 736 maps. 738 JSON specifications use the type ClientId for a client-id, and the 739 type ClientId conforms to the specification of ResourceId as defined 740 in Section 10.2 of [RFC7285]. 742 The two sub-fields (media-type and client-id) of the event field are 743 encoded as comma-separated strings: 745 media-type [ ',' client-id ] 747 The media-type name used by ALTO SSE MUST NOT contain a comma 748 (character code 0x2c). [TODO: conform to Section 4.2 of [RFC6838]; 749 confirm with IANA.] 751 Note that an update message does not use the SSE "id" field. [TODO: 752 Discuss to move client-id to SSE id?] 754 6.2. ALTO Data Update Message 756 A data update message is sent when a monitored resource changes. The 757 data is either a complete specification of the resource, or else a 758 patch (either JSON merge patch or JSON patch) describing the changes 759 from the last version. We will refer to these as full replacement 760 and incremental change, respectively. The encoding of full 761 replacement is defined by [RFC7285]; examples are network and cost 762 map messages. They have the media types defined in that document. 763 The encoding of JSON merge patch is defined by [RFC7396], with media 764 type "application/merge-patch+json"; the encoding of JSON patch is 765 defined by [RFC6902], with media type "application/json-patch+json". 767 Figure 3 shows some examples of ALTO data update messages: 769 event: application/alto-networkmap+json,1 770 data: { ... full network map message ... } 772 event: application/alto-costmap+json,2 773 data: { ... full cost map message ... } 775 event: application/merge-patch+json,2 776 data: { ... JSON merge patch update for the cost map ... } 778 Figure 3: Examples of ALTO data update messages. 780 6.3. ALTO Control Update Message 782 Control update messages have the media type "application/alto- 783 updatestreamcontrol+json", and the data is of type 784 UpdateStreamControlEvent: 786 object { 787 [String control-uri;] 788 [ClientId started<1..*>;] 789 [ClientId stopped<1..*>;] 790 [String description;] 791 } UpdateStreamControlEvent; 793 control-uri: the URI providing stream control for this update stream 794 (see Section 8). The server MUST send a control update message 795 with an URI as the first event in an update stream. If the URI 796 is NULL, the update stream server does not support stream 797 control for this update stream; otherwise, the update stream 798 server provides stream control through the given URI. 800 started: a list of client-ids of resources. It notifies the ALTO 801 client that the update stream server will start sending data 802 update messages for each resource listed. 804 stopped: a list of client-ids of resources. It notifies the ALTO 805 client that the update stream server will no longer send data 806 update messages for the listed resources. There can be multiple 807 reasons for an update stream server to stop sending data update 808 messages for a resource, including a request from the ALTO 809 client using stream control (Section 7.7.1) or an internal 810 server event. 812 description: a non-normative text providing an explanation for the 813 control event. When an update stream server stops sending data 814 update messages for a resource, it is RECOMMENDED that the 815 update stream server use the description field to provide 816 details. 818 7. Update Stream Service 820 An update stream service returns a stream of update messages, as 821 defined in Section 6. An ALTO server's IRD (Information Resource 822 Directory) MAY define one or more update stream services, which ALTO 823 clients use to request new update stream instances. 825 7.1. Media Type 827 The media type of an ALTO update stream service is "text/event- 828 stream", as defined by [SSE]. 830 7.2. HTTP Method 832 An ALTO update stream service is requested using the HTTP POST 833 method. 835 7.3. Accept Input Parameters 837 An ALTO client specifies the parameters for the new update stream by 838 sending an HTTP POST body with the media type "application/alto- 839 updatestreamparams+json". That body contains a JSON Object of type 840 UpdateStreamReq, where: 842 object { 843 [AddUpdatesReq add;] 844 [ClientId remove<0..*>;] 845 } UpdateStreamReq; 847 object-map { 848 ClientId -> AddUpdateReq; 849 } AddUpdatesReq; 851 object { 852 String resource-id; 853 [String tag;] 854 [Boolean incremental-changes;] 855 [Object input;] 856 } AddUpdateReq; 858 add: specifies the resources for which the ALTO client wants updates, 859 and has one entry for each resource. An ALTO client creates a 860 unique client-id (Section 6.1) for each such resource, and uses 861 those client-ids as the keys in the "add" field. 863 resource-id: the resource-id of an ALTO resource, and MUST be in the 864 update stream's "uses" list (Section 8.5.2 of Section 7.5). If 865 the resource-id is a GET-mode resource with a version tag (or 866 "vtag"), as defined in Section 6.3 and Section 10.3 of 867 [RFC7285], and the ALTO client has previously retrieved a 868 version of that resource from the update stream server, the ALTO 869 client MAY set the "tag" field to the tag part of the client's 870 version of that resource. If that version is not current, the 871 update stream server MUST send a full replacement before sending 872 any incremental changes, as described in Section 7.7.1. If that 873 version is still current, the update stream server MAY omit the 874 initial full replacement. 876 incremental-changes: the ALTO client specifies whether it is willing 877 to receive incremental changes from the update stream server for 878 a specific resource-id. If the "incremental-changes" field for 879 a resource-id is "true", the update stream server MAY send 880 incremental changes for that resource (assuming the update 881 stream server supports incremental changes for) that resource; 882 see Section Section 7.4). If the "incremental-changes" field is 883 "false", the update stream server MUST NOT send incremental 884 changes for that resource. The default value for "incremental- 885 changes" is "true", so to suppress incremental changes, the ALTO 886 client MUST explicitly set "incremental-changes" to "false". 887 Note that the ALTO client cannot suppress full replacement. 888 When the ALTO client sets "incremental-changes" to "false", the 889 update stream server MUST send a full replacement instead of an 890 incremental change to the ALTO client. The update stream server 891 MAY wait until more changes are available, and send a single 892 full replacement with those changes. Thus an ALTO client which 893 declines to accept incremental changes may not get updates as 894 quickly as an ALTO client which does. 896 input: If the resource is a POST-mode service which requires input, 897 the ALTO client MUST set the "input" field to a JSON Object with 898 the parameters that resource expects. 900 remove: it is used in update stream control requests (Section 8), 901 and is not allowed in the update stream request. The update 902 stream server SHOULD ignore this field if it is included in the 903 request. 905 If a request has any errors, the update stream server MUST NOT create 906 an update stream. Also, the update stream server will send an error 907 response to the ALTO client as specified in Section 7.6. 909 7.4. Capabilities 911 The capabilities are defined as an object of type 912 UpdateStreamCapabilities: 914 object { 915 IncrementalUpdateMediaTypes incremental-change-media-types; 916 Boolean support-stream-control; 917 } UpdateStreamCapabilities; 919 object-map { 920 ResourceID -> String; 921 } IncrementalUpdateMediaTypes; 923 If this update stream can provide data update messages with 924 incremental changes for a resource, the "incremental-change-media- 925 types" field has an entry for that resource-id, and the value is the 926 media-type of the incremental change. Normally this will be 927 "application/merge-patch+json", "application/json-patch+json", or 928 "application/merge-patch+json,application/json-patch+json", because, 929 as described in Section 6, they are the only incremental change types 930 defined by this document. However future extensions may define other 931 types of incremental changes. 933 When choosing the media-type to encode incremental changes for a 934 resource, the update stream server SHOULD consider the limitations of 935 the encoding. For example, when a JSON merge patch specifies that 936 the value of a field is null, its semantics is that the field is 937 removed from the target, and hence the field is no longer defined 938 (i.e., undefined); see the MergePatch algorithm in Section 4.2.1 on 939 how null value is processed. This, however, may not be the intended 940 result for the resource, when null and undefined have different 941 semantics for the resource. In such a case, the update stream server 942 SHOULD choose JSON patch over JSON merge patch. 944 The "support-stream-control" field specifies whether the given update 945 stream supports stream control. If "support-stream-control" field is 946 "true", the update stream server will uses the stream control 947 specified in this document; else, the update stream server may use 948 other mechanisms to provide the same functionality as stream control. 950 7.5. Uses 952 The "uses" attribute MUST be an array with the resource-ids of every 953 resource for which this update stream can provide updates. Each 954 resource specified in the "uses" MUST support full replacement: the 955 update stream server can always send full replacement, and the ALTO 956 client MUST accept full replacement. 958 This set may be any subset of the ALTO server's resources, and may 959 include resources defined in linked IRDs. However, it is RECOMMENDED 960 that the ALTO server selects a set that is closed under the resource 961 dependency relationship. That is, if an update stream's "uses" set 962 includes resource R1, and resource R1 depends on ("uses") resource 963 R0, then the update stream's "uses" set SHOULD include R0 as well as 964 R1. For example, an update stream for a cost map SHOULD also provide 965 updates for the network map upon which that cost map depends. 967 7.6. Response 969 If the update stream request has any errors, the update stream server 970 MUST return an HTTP "400 Bad Request" to the ALTO client. The body 971 part of the HTTP response is the JSON object defined in Section 8.5.2 972 in [RFC7285]. Hence, an ALTO error response has the format: 974 HTTP/1.1 400 Bad Request 975 Content-Length: [TBD] 976 Content-Type: application/alto-error+json 977 Connection: Closed 979 { 980 "meta":{ 981 "code": "***", 982 "field": "***", 983 "value": "***" 984 } 985 } 987 Note that "field" and "value" are optional fields. If the "value" 988 field exists, the "field" field MUST exist. 990 o If an update stream request does not have an "add" field 991 specifying one or more resources, the error code of the error 992 message MUST be E_MISSING_FIELD and the "field" field SHOULD be 993 "add". The update stream server MUST close the stream without 994 sending any events. 996 o If the "resource-id" field is invalid, or is not associated with 997 the update stream, the error code of the error message MUST be 998 E_INVALID_FIELD_VALUE; the "field" field SHOULD be "resource-id" 999 and the "value" field SHOULD be the invalid resource-id. If there 1000 are more than one invalid resource-ids, the update stream server 1001 SHOULD pick one and return it. The update stream server MUST 1002 close the stream without sending any events. 1004 o If the resource is a POST-mode service which requires input, the 1005 client MUST set the "input" field to a JSON Object with the 1006 parameters that that resource expects. If the "input" field is 1007 missing or invalid, the update stream server MUST return the same 1008 error response that that resource would return for missing or 1009 invalid input (see [RFC7285]). In this case, the update stream 1010 server MUST close the update stream without sending any events. 1011 If the input for several POST-mode resources are missing or 1012 invalid, the update stream server MUST pick one and return it. 1014 The response to a valid request is a stream of update messages. 1015 Section 6 defines the update messages, and [SSE] defines how they are 1016 encoded into a stream. 1018 An update stream server SHOULD send updates only when the underlying 1019 values change. However, it may be difficult for an update stream 1020 server to guarantee that in all circumstances. Therefore a client 1021 MUST NOT assume that an update message represents an actual change. 1023 7.7. Additional Requirements on Update Messages 1025 7.7.1. Event Sequence Requirements 1027 o The first event MUST be a control update message with the URI of 1028 the update stream control service Section 8 for this update 1029 stream. 1031 o As soon as possible after the ALTO client initiates the 1032 connection, the update stream server MUST send a full replacement 1033 for each resource-id requested with a version tag. In this case 1034 the update stream server MAY omit the initial full replacement for 1035 that resource, if the "tag" field the ALTO client provided for 1036 that resource-id matches the tag of the update stream's current 1037 version. 1039 o If this update stream provides update for resource-ids and R0 and 1040 R1, and if R1 depends on R0, then the update stream server MUST 1041 send the update for R0 before sending the related updates for R1. 1042 For example, suppose an update stream provides updates to a 1043 network map and its dependent cost maps. When the network map 1044 changes, the update stream server MUST send the network map update 1045 before sending the cost map updates. 1047 o When the ALTO client uses the stream control service to stop 1048 updates for one or more resources Section 8, the ALTO client MUST 1049 send a stream control request. The update stream server MUST send 1050 a control update message whose "stopped" field has the client-ids 1051 of all active resources. 1053 7.7.2. Cross-Stream Consistency Requirements 1055 If several ALTO clients create multiple update streams for updates to 1056 the same resource, the update stream server MUST send the same 1057 updates to all of them. However, the update stream server MAY pack 1058 data items into different patch events, as long as the net result of 1059 applying those updates is the same. 1061 For example, suppose two different ALTO clients create update streams 1062 for the same cost map, and suppose the update stream server processes 1063 three separate cost point updates with a brief pause between each 1064 update. The server MUST send all three new cost points to both 1065 clients. But the update stream server MAY send a single patch event 1066 (with all three cost points) to one ALTO client, while sending three 1067 separate patch events (with one cost point per event) to the other 1068 ALTO client. 1070 A update stream server MAY offer several different update stream 1071 resources that provide updates to the same underlying resource (that 1072 is, a resource-id may appear in the "uses" field of more than one 1073 update stream resource). In this case, those update stream resources 1074 MUST return the same update data. 1076 7.8. Keep-Alive Messages 1078 In an SSE stream, any line which starts with a colon (U+003A) 1079 character is a comment, and an ALTO client MUST ignore that line 1080 ([SSE]). As recommended in [SSE], an update stream server SHOULD 1081 send a comment line (or an event) every 15 seconds to prevent ALTO 1082 clients and proxy servers from dropping the HTTP connection. 1084 8. Stream Control Service 1086 An stream control service allows an ALTO client to remove resources 1087 from the set of resources that are monitored by an update stream, or 1088 add additional resources to that set. The service also allows an 1089 ALTO client to gracefully shut down an update stream. 1091 When an update stream server creates a new update stream, and if the 1092 update stream server supports stream control for the update stream, 1093 the update stream server creates a stream control service for that 1094 update stream. An ALTO client uses the stream control service to 1095 remove resources from the update stream instance, or to request 1096 updates for additional resources. An ALTO client cannot obtain the 1097 stream control service through the IRD. Instead, the first event 1098 that the update stream server sends to the ALTO client has the URI 1099 for the associated stream control service (see Section 6.3). 1101 Each stream control request is an individual HTTP request. If the 1102 ALTO client and the stream control server the ALTO client MAY send 1103 multiple stream control requests to the stream control server using 1104 the same HTTP connection. 1106 8.1. URI 1108 The URI for an stream control service, by itself, MUST uniquely 1109 specify the update stream instance which it controls. The stream 1110 control server MUST NOT use other properties of an HTTP request, such 1111 as cookies or the client's IP address, to determine the update 1112 stream. Furthermore, an update stream server MUST NOT reuse a 1113 control service URI once the associated update stream has been 1114 closed. 1116 The ALTO client MUST evaluate a non-absolute control URI (for 1117 example, a URI without a host, or with a relative path) in the 1118 context of the URI used to create the update stream. The stream 1119 control service's host MAY be different from the update stream's 1120 host. 1122 It is expected that the update stream server will assign a unique 1123 stream id to each update stream instance and will embed that id in 1124 the associated stream control URI. However, the exact mechanism is 1125 left to the update stream server. ALTO clients MUST NOT attempt to 1126 deduce a stream id from the control URI. 1128 To prevent an attacker from forging a stream control URI and sending 1129 bogus requests to disrupt other update streams, stream control URIs 1130 SHOULD contain sufficient random redundancy to make it difficult to 1131 guess valid URIs. 1133 8.2. Media Type 1135 An ALTO stream control response does not have a specific media type. 1137 8.3. HTTP Method 1139 An ALTO update stream control resource is requested using the HTTP 1140 POST method. 1142 8.4. Accept Input Parameters 1144 An stream control service accepts the same input media type and input 1145 parameters as the update stream service (Section 7.3). The only 1146 difference is that a stream control service also accepts the "remove" 1147 field. 1149 If specified, the "remove" field is an array of client-ids the ALTO 1150 client previously added to this update stream. An empty "remove" 1151 array is equivalent to a list of all currently active resources; the 1152 update stream server responds by removing all resources and closing 1153 the stream. 1155 An ALTO client MAY use the "add" field to add additional resources. 1156 However, the ALTO client MUST assign a unique client-id to each 1157 resource. Client-ids MUST be unique over the lifetime of this update 1158 stream: an ALTO client MUST NOT reuse a previously removed client-id. 1160 If a request has any errors, the update stream server MUST NOT add or 1161 remove any resources from the associated update stream. Also, the 1162 stream control server will return an error response to the client as 1163 specified in Section 8.6. 1165 8.5. Capabilities & Uses 1167 None (Stream control services do not appear in the IRD). 1169 8.6. Response 1171 The stream control server MUST process the "add" field before the 1172 "remove" field. If the request removes all active resources without 1173 adding any additional resources, the update stream server MUST close 1174 the update stream. Thus an update stream cannot have zero resources. 1176 If the request has any errors, the stream control server MUST return 1177 an HTTP "400 Bad Request" to the ALTO client. The body part of the 1178 HTTP response is the JSON object defined in Section 8.5.2 in 1179 [RFC7285]. An error response has the same format as specified in 1180 Section 7.6. Detailed error code and error information are specified 1181 as below. 1183 o If the "add" request does not satisfy the requirements in 1184 Section 7.3, the stream control server MUST return the ALTO error 1185 message defined in Section 7.6. 1187 o If any client-id in the "remove" field was not added in a prior 1188 request, the error code of the error message MUST be 1189 E_INVALID_FIELD_VALUE; the "field" field SHOULD be "remove" and 1190 the "value" field SHOULD be the array of the invalid client-ids. 1191 Thus it is illegal to "add" and "remove" the same client-id in the 1192 same request. However, it is legal to remove a client-id twice. 1194 o If any client-id in the "add" field has been used before in this 1195 stream, the error code of the error message MUST be 1196 E_INVALID_FIELD_VALUE, the "field" field SHOULD be "add" and the 1197 "value" field SHOULD be the array of invalid client-ids. 1199 o If the request has a non-empty "add" field and a "remove" field 1200 with an empty list of client-ids (to replace all active resources 1201 with a new set, the client MUST explicitly enumerate the client- 1202 ids to be removed), the error code of the error message MUST be 1203 E_INVALID_FIELD_VALUE; the "field" field SHOULD be "remove" and 1204 the "value" field SHOULD be an empty array. 1206 If the request is valid but the associated update stream has been 1207 closed. The stream control server MUST return an HTTP "404 Not 1208 Found". 1210 If the request is valid and the stream control server successfully 1211 processes the request without error, the stream control server should 1212 return either an HTTP "202 Accepted" response or an HTTP "204 No 1213 Content" response. The difference is that for the latter case, the 1214 stream control server is sure that the update stream server has also 1215 processed the request. Regardless of 202 or 204 HTTP response, the 1216 final updates of related resources will be notified by the update 1217 stream server using its control update message(s), due to our modular 1218 design. 1220 9. Examples 1222 9.1. Example: IRD Announcing Update Stream Services 1224 Below is an example IRD announcing two update stream services. The 1225 first, which is named "update-my-costs", provides updates for the 1226 network map, the "routingcost" and "hopcount" cost maps, and a 1227 filtered cost map resource. The second, which is named "update-my- 1228 prop", provides updates to the endpoint properties service. 1230 Note that in the "update-my-costs" update stream shown in the example 1231 IRD, the update stream server uses JSON patch for network map, and it 1232 uses JSON merge patch to update the other resources. Also, the 1233 update stream will only provide full replacements for "my-simple- 1234 filtered-cost-map". 1236 Also, note that this IRD defines two filtered cost map resources. 1237 They use the same cost types, but "my-filtered-cost-map" accepts cost 1238 constraint tests, while "my-simple-filtered-cost-map" does not. To 1239 avoid the issues discussed in Section 10.4, the update stream 1240 provides updates for the second, but not the first. 1242 "my-network-map": { 1243 "uri": "http://alto.example.com/networkmap", 1244 "media-type": "application/alto-networkmap+json", 1245 }, 1246 "my-routingcost-map": { 1247 "uri": "http://alto.example.com/costmap/routingcost", 1248 "media-type": "application/alto-costmap+json", 1249 "uses": ["my-networkmap"], 1250 "capabilities": { 1251 "cost-type-names": ["num-routingcost"] 1252 } 1253 }, 1254 "my-hopcount-map": { 1255 "uri": "http://alto.example.com/costmap/hopcount", 1256 "media-type": "application/alto-costmap+json", 1257 "uses": ["my-networkmap"], 1258 "capabilities": { 1259 "cost-type-names": ["num-hopcount"] 1260 } 1261 }, 1262 "my-filtered-cost-map": { 1263 "uri": "http://alto.example.com/costmap/filtered/constraints", 1264 "media-type": "application/alto-costmap+json", 1265 "accepts": "application/alto-costmapfilter+json", 1266 "uses": ["my-networkmap"], 1267 "capabilities": { 1268 "cost-type-names": ["num-routingcost", "num-hopcount"], 1269 "cost-constraints": true 1270 } 1271 }, 1272 "my-simple-filtered-cost-map": { 1273 "uri": "http://alto.example.com/costmap/filtered/simple", 1274 "media-type": "application/alto-costmap+json", 1275 "accepts": "application/alto-costmapfilter+json", 1276 "uses": ["my-networkmap"], 1277 "capabilities": { 1278 "cost-type-names": ["num-routingcost", "num-hopcount"], 1279 "cost-constraints": false 1280 } 1281 }, 1282 "my-props": { 1283 "uri": "http://alto.example.com/properties", 1284 "media-type": "application/alto-endpointprops+json", 1285 "accepts": "application/alto-endpointpropparams+json", 1286 "capabilities": { 1287 "prop-types": ["priv:ietf-bandwidth"] 1288 } 1289 }, 1290 "update-my-costs": { 1291 "uri": "http://alto.example.com/updates/costs", 1292 "media-type": "text/event-stream", 1293 "accepts": "application/alto-updatestreamparams+json", 1294 "uses": [ 1295 "my-network-map", 1296 "my-routingcost-map", 1297 "my-hopcount-map", 1298 "my-simple-filtered-cost-map" 1299 ], 1300 "capabilities": { 1301 "incremental-change-media-types": { 1302 "my-network-map": "application/json-patch+json", 1303 "my-routingcost-map": "application/merge-patch+json", 1304 "my-hopcount-map": "application/merge-patch+json" 1305 }, 1306 "support-stream-control": true 1307 } 1308 }, 1309 "update-my-props": { 1310 "uri": "http://alto.example.com/updates/properties", 1311 "media-type": "text/event-stream", 1312 "uses": [ "my-props" ], 1313 "accepts": "application/alto-updatestreamparams+json", 1314 "capabilities": { 1315 "incremental-change-media-types": { 1316 "my-props": "application/merge-patch+json" 1317 }, 1318 "support-stream-control": true 1319 } 1320 } 1322 9.2. Example: Simple Network and Cost Map Updates 1324 Given the update streams announced in the preceding example IRD, 1325 below we show an example of an ALTO client's request and the update 1326 stream server's immediate response, using the update stream resource 1327 "update-my-costs". In the example, the ALTO client requests updates 1328 for the network map and "routingcost" cost map, but not for the 1329 "hopcount" cost map. The ALTO client uses the ALTO server's 1330 resource-ids as the client-ids. Because the client does not provide 1331 a "tag" for the network map, the update stream server must send a 1332 full replacement for the network map as well as for the cost map. 1333 The ALTO client does not set "incremental-changes" to "false", so it 1334 defaults to "true". Thus, the update stream server will send patch 1335 updates for the cost map and the network map. 1337 POST /updates/costs HTTP/1.1 1338 Host: alto.example.com 1339 Accept: text/event-stream,application/alto-error+json 1340 Content-Type: application/alto-updatestreamparams+json 1341 Content-Length: ### 1343 { "add": { 1344 "my-network-map": { 1345 "resource-id": "my-network-map" 1346 }, 1347 "my-routingcost-map": { 1348 "resource-id": "my-routingcost-map" 1349 } 1350 } 1351 } 1353 HTTP/1.1 200 OK 1354 Connection: keep-alive 1355 Content-Type: text/event-stream 1357 event: application/alto-updatestreamcontrol+json 1358 data: {"control-uri": 1359 data: "http://alto.example.com/updates/streams/3141592653589"} 1361 event: application/alto-networkmap+json,my-network-map 1362 data: { 1363 data: "meta" : { 1364 data: "vtag": { 1365 data: "resource-id" : "my-network-map", 1366 data: "tag" : "da65eca2eb7a10ce8b059740b0b2e3f8eb1d4785" 1367 data: } 1368 data: }, 1369 data: "network-map" : { 1370 data: "PID1" : { 1371 data: "ipv4" : [ "192.0.2.0/24", "198.51.100.0/25" ] 1372 data: }, 1373 data: "PID2" : { 1374 data: "ipv4" : [ "198.51.100.128/25" ] 1375 data: }, 1376 data: "PID3" : { 1377 data: "ipv4" : [ "0.0.0.0/0" ], 1378 data: "ipv6" : [ "::/0" ] 1379 data: } 1380 data: } 1381 data: } 1382 data: } 1384 event: application/alto-costmap+json,my-routingcost-map 1385 data: { 1386 data: "meta" : { 1387 data: "dependent-vtags" : [{ 1388 data: "resource-id": "my-network-map", 1389 data: "tag": "da65eca2eb7a10ce8b059740b0b2e3f8eb1d4785" 1390 data: }], 1391 data: "cost-type" : { 1392 data: "cost-mode" : "numerical", 1393 data: "cost-metric": "routingcost" 1394 data: }, 1395 data: "vtag": { 1396 data: "resource-id" : "my-routingcost-map", 1397 data: "tag" : "3ee2cb7e8d63d9fab71b9b34cbf764436315542e" 1398 data: } 1399 data: }, 1400 data: "cost-map" : { 1401 data: "PID1": { "PID1": 1, "PID2": 5, "PID3": 10 }, 1402 data: "PID2": { "PID1": 5, "PID2": 1, "PID3": 15 }, 1403 data: "PID3": { "PID1": 20, "PID2": 15 } 1404 data: } 1405 data: } 1407 After sending those events immediately, the update stream server will 1408 send additional events as the maps change. For example, the 1409 following represents a small change to the cost map. PID1->PID2 is 1410 changed to 9 from 5, PID3->PID1 is no longer available and PID3->PID3 1411 is now defined as 1: 1413 event: application/merge-patch+json,my-routingcost-map 1414 data: { 1415 data: "meta" : { 1416 data: "vtag": { 1417 data: "tag": "c0ce023b8678a7b9ec00324673b98e54656d1f6d" 1418 data: } 1419 data: }, 1420 data: "cost-map": { 1421 data: "PID1" : { "PID2" : 9 }, 1422 data: "PID3" : { "PID1" : null, "PID3" : 1 } 1423 data: } 1424 data: } 1426 As another example, the following represents a change to the network 1427 map: an ipv4 prefix "193.51.100.0/25" is added to PID1. It triggers 1428 changes to the cost map. The update stream server chooses to send an 1429 incremental change for the network map and send a full replacement 1430 instead of an incremental change for the cost map: 1432 event: application/json-patch+json,my-network-map 1433 data: { 1434 data: { 1435 data: "op": "replace", 1436 data: "path": "/meta/vtag/tag", 1437 data: "value" :"a10ce8b059740b0b2e3f8eb1d4785acd42231bfe" 1438 data: }, 1439 data: { 1440 data: "op": "add", 1441 data: "path": "/network-map/PID1/ipv4/2", 1442 data: "value": "193.51.100.0/25" 1443 data: } 1444 data: } 1446 event: application/alto-costmap+json,my-routingcost-map 1447 data: { 1448 data: "meta" : { 1449 data: "vtag": { 1450 data: "tag": "c0ce023b8678a7b9ec00324673b98e54656d1f6d" 1451 data: } 1452 data: }, 1453 data: "cost-map" : { 1454 data: "PID1": { "PID1": 1, "PID2": 3, "PID3": 7 }, 1455 data: "PID2": { "PID1": 12, "PID2": 1, "PID3": 9 }, 1456 data: "PID3": { "PID1": 14, "PID2": 8 } 1457 data: } 1458 data: } 1460 9.3. Example: Advanced Network and Cost Map Updates 1462 This example is similar to the previous one, except that the ALTO 1463 client requests updates for the "hopcount" cost map as well as the 1464 "routingcost" cost map and provides the current version tag of the 1465 network map, so the update stream server is not required to send the 1466 full network map data update message at the beginning of the stream. 1467 In this example, the client uses the client-ids "net", "routing" and 1468 "hops" for those resources. The update stream server sends the 1469 stream control URI and the full cost maps, followed by updates for 1470 the network map and cost maps as they become available: 1472 POST /updates/costs HTTP/1.1 1473 Host: alto.example.com 1474 Accept: text/event-stream,application/alto-error+json 1475 Content-Type: application/alto-updatestreamparams+json 1476 Content-Length: ### 1478 { "add": { 1479 "net": { 1480 "resource-id": "my-network-map". 1481 "tag": "a10ce8b059740b0b2e3f8eb1d4785acd42231bfe" 1482 }, 1483 "routing": { 1484 "resource-id": "my-routingcost-map" 1485 }, 1486 "hops": { 1487 "resource-id": "my-hopcount-map" 1488 } 1489 } 1490 } 1492 HTTP/1.1 200 OK 1493 Connection: keep-alive 1494 Content-Type: text/event-stream 1496 event: application/alto-updatestreamcontrol+json 1497 data: {"control-uri": 1498 data: "http://alto.example.com/updates/streams/2718281828459"} 1500 event: application/alto-costmap+json,routing 1501 data: { ... full routingcost cost map message ... } 1503 event: application/alto-costmap+json,hops 1504 data: { ... full hopcount cost map message ... } 1506 (pause) 1508 event: application/merge-patch+json,routing 1509 data: {"cost-map": {"PID2" : {"PID3" : 31}}} 1511 event: application/merge-patch+json,hops 1512 data: {"cost-map": {"PID2" : {"PID3" : 4}}} 1514 If the ALTO client wishes to stop receiving updates for the 1515 "hopcount" cost map, the ALTO client can send a "remove" request on 1516 the stream control URI: 1518 POST /updates/streams/2718281828459" HTTP/1.1 1519 Host: alto.example.com 1520 Accept: text/plain,application/alto-error+json 1521 Content-Type: application/alto-updatestreamparams+json 1522 Content-Length: ### 1524 { 1525 "remove": [ "hops" ] 1526 } 1528 HTTP/1.1 204 No Content 1529 Content-Length: 0 1531 (stream closed without sending data content) 1533 The update stream server sends a "stopped" control update message on 1534 the original request stream to inform the ALTO client that updates 1535 are stopped for that resource: 1537 event: application/alto-updatestreamcontrol+json 1538 data: { 1539 data: "stopped": ["hops"] 1540 data: } 1542 Below is an example of an invalid stream control request. The 1543 "remove" field of the request includes an undefined client-id and the 1544 stream control server will return an error response to the ALTO 1545 client. 1547 POST /updates/streams/2718281828459 HTTP/1.1 1548 Host: alto.example.com 1549 Accept: text/plain,application/alto-error+json 1550 Content-Type: application/alto-updatestreamparams+json 1551 Content-Length: ### 1552 { 1553 "remove": [ "properties" ] 1554 } 1556 HTTP/1.1 400 Bad Request 1557 Content-Length: [TBD] 1558 Content-Type: application/alto-error+json 1560 { 1561 "meta":{ 1562 "code": "E_INVALID_FIELD_VALUE", 1563 "field": "remove", 1564 "value": "properties" 1565 } 1567 If the ALTO client no longer needs any updates, and wishes to shut 1568 the update stream down gracefully, the client can send a "remove" 1569 request with an empty array: 1571 POST /updates/streams/2718281828459 HTTP/1.1 1572 Host: alto.example.com 1573 Accept: text/plain,application/alto-error+json 1574 Content-Type: application/alto-updatestreamparams+json 1575 Content-Length: ### 1577 { 1578 "remove": [ ] 1579 } 1581 HTTP/1.1 204 No Content 1582 Content-Length: 0 1584 (stream closed without sending data content) 1586 The update stream server sends a final control update message on the 1587 original request stream to inform the ALTO client that all updates 1588 are stopped and then closes the stream: 1590 event: application/alto-updatestreamcontrol+json 1591 data: { 1592 data: "stopped": ["net", "routing"] 1593 data: } 1595 (server closes stream) 1597 9.4. Example: Endpoint Property Updates 1599 As another example, here is how an ALTO client can request updates 1600 for the property "priv:ietf-bandwidth" for one set of endpoints and 1601 "priv:ietf-load" for another. The update stream server immediately 1602 sends full replacements with the property values for all endpoints. 1603 After that, the update stream server sends data update messages for 1604 the individual endpoints as their property values change. 1606 POST /updates/properties HTTP/1.1 1607 Host: alto.example.com 1608 Accept: text/event-stream 1609 Content-Type: application/alto-updatestreamparams+json 1610 Content-Length: ### 1612 { "add": { 1613 "props-1": { 1614 "resource-id": "my-props", 1615 "input": { 1616 "properties" : [ "priv:ietf-bandwidth" ], 1617 "endpoints" : [ 1618 "ipv4:198.51.100.1", 1619 "ipv4:198.51.100.2", 1620 "ipv4:198.51.100.3" 1621 ] 1622 } 1623 }, 1624 "props-2": { 1625 "resource-id": "my-props", 1626 "input": { 1627 "properties" : [ "priv:ietf-load" ], 1628 "endpoints" : [ 1629 "ipv6:2001:db8:100::1", 1630 "ipv6:2001:db8:100::2", 1631 "ipv6:2001:db8:100::3", 1632 ] 1633 } 1634 }, 1635 } 1636 } 1637 HTTP/1.1 200 OK 1638 Connection: keep-alive 1639 Content-Type: text/event-stream 1641 event: application/alto-updatestreamcontrol+json 1642 data: {"control-uri": 1643 data: "http://alto.example.com/updates/streams/1414213562373"} 1645 event: application/alto-endpointprops+json,props-1 1646 data: { "endpoint-properties": { 1647 data: "ipv4:198.51.100.1" : { "priv:ietf-bandwidth": "13" }, 1648 data: "ipv4:198.51.100.2" : { "priv:ietf-bandwidth": "42" }, 1649 data: "ipv4:198.51.100.3" : { "priv:ietf-bandwidth": "27" } 1650 data: } } 1652 event: application/alto-endpointprops+json,props-2 1653 data: { "endpoint-properties": { 1654 data: "ipv6:2001:db8:100::1" : { "priv:ietf-load": "8" }, 1655 data: "ipv6:2001:db8:100::2" : { "priv:ietf-load": "2" }, 1656 data: "ipv6:2001:db8:100::3" : { "priv:ietf-load": "9" } 1657 data: } } 1659 (pause) 1661 event: application/merge-patch+json,props-1 1662 data: { "endpoint-properties": 1663 data: {"ipv4:198.51.100.1" : {"priv:ietf-bandwidth": "3"}} 1664 data: } 1666 (pause) 1668 event: application/merge-patch+json,props-2 1669 data: { "endpoint-properties": 1670 data: {"ipv6:2001:db8:100::3" : {"priv:ietf-load": "7"}} 1671 data: } 1673 If the ALTO client needs the "bandwidth" property for additional 1674 endpoints, the ALTO client can send an "add" request on the stream 1675 control URI: 1677 POST /updates/streams/1414213562373" HTTP/1.1 1678 Host: alto.example.com 1679 Accept: text/plain,application/alto-error+json 1680 Content-Type: application/alto-updatestreamparams+json 1681 Content-Length: ### 1683 { "add": { 1684 "props-3": { 1685 "resource-id": "my-props", 1686 "input": { 1687 "properties" : [ "priv:ietf-bandwidth" ], 1688 "endpoints" : [ 1689 "ipv4:198.51.100.4", 1690 "ipv4:198.51.100.5", 1691 ] 1692 } 1693 }, 1694 "props-4": { 1695 "resource-id": "my-props", 1696 "input": { 1697 "properties" : [ "priv:ietf-load" ], 1698 "endpoints" : [ 1699 "ipv6:2001:db8:100::4", 1700 "ipv6:2001:db8:100::5", 1701 ] 1702 } 1703 }, 1704 } 1705 } 1707 HTTP/1.1 204 No Content 1708 Content-Length: 0 1710 (stream closed without sending data content) 1712 The update stream server sends full replacements for the two new 1713 resources, followed by incremental changes for all four requests as 1714 they arrive: 1716 event: application/alto-endpointprops+json,props-3 1717 data: { "endpoint-properties": { 1718 data: "ipv4:198.51.100.4" : { "priv:ietf-bandwidth": "25" }, 1719 data: "ipv4:198.51.100.5" : { "priv:ietf-bandwidth": "31" }, 1720 data: } } 1722 event: application/alto-endpointprops+json,props-4 1723 data: { "endpoint-properties": { 1724 data: "ipv6:2001:db8:100::4" : { "priv:ietf-load": "6" }, 1725 data: "ipv6:2001:db8:100::5" : { "priv:ietf-load": "4" }, 1726 data: } } 1728 (pause) 1730 event: application/merge-patch+json,props-3 1731 data: { "endpoint-properties": 1732 data: {"ipv4:198.51.100.5" : {"priv:ietf-bandwidth": "15"}} 1733 data: } 1735 (pause) 1737 event: application/merge-patch+json,props-2 1738 data: { "endpoint-properties": 1739 data: {"ipv6:2001:db8:100::2" : {"priv:ietf-load": "9"}} 1740 data: } 1742 (pause) 1744 event: application/merge-patch+json,props-4 1745 data: { "endpoint-properties": 1746 data: {"ipv6:2001:db8:100::4" : {"priv:ietf-load": "3"}} 1747 data: } 1749 10. Operation and Processing Considerations 1751 10.1. Considerations for Choosing SSE Line Lengths 1753 SSE was designed for events that consist of relatively small amounts 1754 of line-oriented text data, and SSE clients frequently read input one 1755 line-at-a-time. However, an update stream sends full cost maps as 1756 single events, and a cost map may involve megabytes, if not tens of 1757 megabytes, of text. This has implications for both the update stream 1758 server and the ALTO Client. 1760 First, SSE clients might not be able to handle a multi-megabyte data 1761 "line". Hence it is RECOMMENDED that an update stream server limit 1762 data lines to at most 2,000 characters. 1764 Second, some SSE client packages read all the data for an event into 1765 memory, and then present it to the client as a single character 1766 array. However, a client computer may not have enough memory to hold 1767 the entire JSON text for a large cost map. Hence an ALTO client 1768 SHOULD consider using an SSE library which presents the event data in 1769 manageable chunks, so the ALTO client can parse the cost map 1770 incrementally and store the underlying data in a more compact format. 1772 10.2. Considerations for Choosing Data Update Messages 1774 The choice on data update messages depends on both how frequently the 1775 resources will change, and how extensive those changes will be. For 1776 stable resources with minor changes, the update stream server may 1777 choose to send incremental changes; for resources that frequently 1778 change, the update stream server may choose to send a full 1779 replacement after a while. Whether to send full replacement or 1780 incremental change depends on the update stream server. 1782 For incremental updates, this design allows both JSON patch and JSON 1783 merge patch for incremental changes. JSON merge patch is clearly 1784 superior to JSON patch for describing incremental changes to Cost 1785 Maps, Endpoint Costs, and Endpoint Properties. For these data 1786 structures, JSON merge patch is more space-efficient, as well as 1787 simpler to apply; we see no advantage to allowing a server to use 1788 JSON patch for those resources. 1790 The case is not as clear for incremental changes to network maps. 1792 First, consider small changes such as moving a prefix from one PID to 1793 another. JSON patch could encode that as a simple insertion and 1794 deletion, while JSON merge patch would have to replace the entire 1795 array of prefixes for both PIDs. On the other hand, to process a 1796 JSON patch update, the ALTO client would have to retain the indexes 1797 of the prefixes for each PID. Logically, the prefixes in a PID are 1798 an unordered set, not an array; aside from handling updates, a client 1799 has no need to retain the array indexes of the prefixes. Hence to 1800 take advantage of JSON patch for network maps, ALTO clients would 1801 have to retain additional, otherwise unnecessary, data. 1803 Second, consider more involved changes such as removing half of the 1804 prefixes from a PID. JSON merge patch would send a new array for 1805 that PID, while JSON patch would have to send a list of remove 1806 operations and delete the prefix one by one. 1808 Therefore, each update stream server may decide on its own whether to 1809 use JSON merge patch or JSON patch according to the changes in 1810 network maps. 1812 Other JSON-based incremental change formats may be introduced in the 1813 future. 1815 10.3. Considerations for Client Processing Data Update Messages 1817 In general, when an ALTO client receives a full replacement for a 1818 resource, the ALTO client should replace the current version with the 1819 new version. When an ALTO client receives an incremental change for 1820 a resource, the ALTO client should apply those patches to the current 1821 version of the resource. 1823 However, because resources can depend on other resources (e.g., cost 1824 maps depend on network maps), an ALTO client MUST NOT use a dependent 1825 resource if the resource on which it depends has changed. There are 1826 at least two ways an ALTO client can do that. We will illustrate 1827 these techniques by referring to network and cost map messages, 1828 although these techniques apply to any dependent resources. 1830 Note that when a network map changes, the update stream server MUST 1831 send the network map update message before sending the updates for 1832 the dependent cost maps (see Section 7.7.1). 1834 One approach is for the ALTO client to save the network map update 1835 message in a buffer and continue to use the previous network map, and 1836 the associated cost maps, until the ALTO client receives the update 1837 messages for all dependent cost maps. The ALTO client then applies 1838 all network and cost map updates atomically. 1840 Alternatively, the ALTO client MAY update the network map 1841 immediately. In this case, the ALTO client MUST mark each dependent 1842 cost map as temporarily invalid and MUST NOT use that map until the 1843 ALTO client receives a cost map update message with the new network 1844 map version tag. Note that the ALTO client MUST NOT delete the cost 1845 maps, because the update stream server may send incremental changes. 1847 The update stream server SHOULD send updates for dependent resources 1848 in a timely fashion. However, if the ALTO client does not receive 1849 the expected updates, the ALTO client MUST close the update stream 1850 connection, discard the dependent resources, and reestablish the 1851 update stream. The ALTO client MAY retain the version tag of the 1852 last version of any tagged resources and give those version tags when 1853 requesting the new update stream. In this case, if a version is 1854 still current, the update stream server will not re-send that 1855 resource. 1857 Although not as efficient as possible, this recovery method is simple 1858 and reliable. 1860 10.4. Considerations for Updates to Filtered Cost Maps 1862 If an update stream provides updates to a Filtered cost map which 1863 allows constraint tests, then an ALTO client MAY request updates to a 1864 Filtered cost map request with a constraint test. In this case, when 1865 a cost changes, the update stream server MUST send an update if the 1866 new value satisfies the test. If the new value does not, whether the 1867 update stream server sends an update depends on whether the previous 1868 value satisfied the test. If it did not, the update stream server 1869 SHOULD NOT send an update to the ALTO client. But if the previous 1870 value did, then the update stream server MUST send an update with a 1871 "null" value, to inform the ALTO client that this cost no longer 1872 satisfies the criteria. 1874 An update stream server can avoid such issues by offering update 1875 streams only for filtered cost maps which do not allow constraint 1876 tests. 1878 10.5. Considerations for Updates to Ordinal Mode Costs 1880 For an ordinal mode cost map, a change to a single cost point may 1881 require updating many other costs. As an extreme example, suppose 1882 the lowest cost changes to the highest cost. For a numerical mode 1883 cost map, only that one cost changes. But for an ordinal mode cost 1884 map, every cost might change. While this document allows an update 1885 stream server to offer incremental updates for ordinal mode cost 1886 maps, update stream server implementors should be aware that 1887 incremental updates for ordinal costs are more complicated than for 1888 numerical costs, and ALTO clients should be aware that small changes 1889 may result in large updates. 1891 An update stream server can avoid this complication by only offering 1892 full replacements for ordinal cost maps. 1894 11. Security Considerations 1896 As an extension of the base ALTO protocol [RFC7285], this document 1897 fits into the architecture of the base protocol, and hence the 1898 Security Considerations (Section 15) of the base protocol fully apply 1899 when this extension is provided by an ALTO server. For example, the 1900 same authenticity and integrity considerations (Section 15.1 of 1901 [RFC7285]) still fully apply; the same considerations for the privacy 1902 of ALTO users (Section 15.4 of [RFC7285]) also still fully apply. 1904 The addition of update streams and stream control can introduce 1905 additional risks which we discuss below. 1907 11.1. Update Stream Server: Denial-of-Service Attacks 1909 Allowing persistent update stream connections enables a new class of 1910 Denial-of-Service attacks. 1912 For the update stream server, an ALTO client might create an 1913 unreasonable number of update stream connections, or add an 1914 unreasonable number of client-ids to one update stream. 1916 To avoid these attacks on the update stream server, the server MAY 1917 choose to limit the number of active streams and reject new requests 1918 when that threshold is reached. An update stream server MAY also 1919 choose to limit the number of active client-ids on any given stream, 1920 or limit the total number of client-ids used over the lifetime of a 1921 stream, and reject any stream control request which would exceed 1922 those limits. In these cases, the update stream server SHOULD return 1923 the HTTP status "503 Service Unavailable". 1925 While the preceding techniques prevent update stream DoS attacks from 1926 disrupting an update stream server's other services, it does make it 1927 easier for a DoS attack to disrupt the update stream service. 1928 Therefore an update stream server may prefer to restrict update 1929 stream services to authorized clients, as discussed in Section 15 of 1930 [RFC7285]. 1932 Alternatively, an update stream server MAY return the HTTP status 1933 "307 Temporary Redirect" to redirect the client to another ALTO 1934 server which can better handle a large number of update streams. 1936 11.2. ALTO Client: Update Overloading or Instability 1938 The availability of continuous updates can also cause overload for an 1939 ALTO client, in particular an ALTO client with limited processing 1940 capabilities. The current design does not include any flow control 1941 mechanisms for the client to reduce the update rates from the server. 1942 Under overloading, the client may choose to remove the information 1943 resources with high update rates. 1945 Also, under overloading, the client may no longer be able to detect 1946 whether an information is still fresh or has become stale. In such a 1947 case, the client should be careful in how it uses the information to 1948 avoid stability or efficiency issues. 1950 11.3. Stream Control: Spoofed Control Requests 1952 An outside party which can read the update stream response, or which 1953 can observe stream control requests, can obtain the control URI and 1954 use that to send a fraudulent "remove" requests, thus disabling 1955 updates for the valid ALTO client. This can be avoided by encrypting 1956 the update stream and stream control requests (see Section 15 of 1957 [RFC7285]). Also, the update stream server echoes the "remove" 1958 requests on the update stream, so the valid ALTO client can detect 1959 unauthorized requests. 1961 12. Requirements on Future ALTO Services to Use this Design 1963 Although this design is quite flexible, it has underlying 1964 requirements. 1966 The key requirements are that (1) each data update message is for a 1967 single resource; (2) an incremental change can be applied only to a 1968 resource that is a single JSON object, as both JSON merge patch and 1969 JSON patch can apply only to a single JSON object. Hence, if a 1970 future ALTO resource can contain multiple objects, then either each 1971 individual object also has a resource-id or an extension to this 1972 design is made. 1974 At the low level encoding level, new line in SSE has its own 1975 semantics. Hence, this design requires that resource encoding does 1976 not include new lines that can confuse with SSE encoding. In 1977 particular, the data update message MUST NOT include "event: " or 1978 "data: " at a new line as part of data message. 1980 If an update stream provides updates to a filtered cost map that 1981 allows constraint tests, the requirements for such services are 1982 stated in Section 10.4. 1984 13. IANA Considerations 1986 This document defines two new media-types, "application/alto- 1987 updatestreamparams+json", as described in Section 7.3, and 1988 "application/alto-updatestreamcontrol+json", as described in 1989 Section 6.3. All other media-types used in this document have 1990 already been registered, either for ALTO, JSON merge patch, or JSON 1991 patch. 1993 Type name: application 1995 Subtype name: alto-updatestreamparams+json 1997 Required parameters: n/a 1999 Optional parameters: n/a 2000 Encoding considerations: Encoding considerations are identical to 2001 those specified for the "application/json" media type. See 2002 [RFC7159]. 2004 Security considerations: Security considerations relating to the 2005 generation and consumption of ALTO Protocol messages are discussed 2006 in Section 11 of this document and Section 15 of [RFC7285]. 2008 Interoperability considerations: This document specifies format of 2009 conforming messages and the interpretation thereof. 2011 Published specification: Section 7.3 of this document. 2013 Applications that use this media type: ALTO servers and ALTO clients 2014 either stand alone or are embedded within other applications. 2016 Additional information: 2018 Magic number(s): n/a 2020 File extension(s): This document uses the mime type to refer to 2021 protocol messages and thus does not require a file extension. 2023 Macintosh file type code(s): n/a 2025 Person & email address to contact for further information: See 2026 Authors' Addresses section. 2028 Intended usage: COMMON 2030 Restrictions on usage: n/a 2032 Author: See Authors' Addresses section. 2034 Change controller: Internet Engineering Task Force 2035 (mailto:iesg@ietf.org). 2037 Type name: application 2039 Subtype name: alto-updatestreamcontrol+json 2041 Required parameters: n/a 2043 Optional parameters: n/a 2045 Encoding considerations: Encoding considerations are identical to 2046 those specified for the "application/json" media type. See 2047 [RFC7159]. 2049 Security considerations: Security considerations relating to the 2050 generation and consumption of ALTO Protocol messages are discussed 2051 in Section 11 of this document and Section 15 of [RFC7285]. 2053 Interoperability considerations: This document specifies format of 2054 conforming messages and the interpretation thereof. 2056 Published specification: Section 6.3 of this document. 2058 Applications that use this media type: ALTO servers and ALTO clients 2059 either stand alone or are embedded within other applications. 2061 Additional information: 2063 Magic number(s): n/a 2065 File extension(s): This document uses the mime type to refer to 2066 protocol messages and thus does not require a file extension. 2068 Macintosh file type code(s): n/a 2070 Person & email address to contact for further information: See 2071 Authors' Addresses section. 2073 Intended usage: COMMON 2075 Restrictions on usage: n/a 2077 Author: See Authors' Addresses section. 2079 Change controller: Internet Engineering Task Force 2080 (mailto:iesg@ietf.org). 2082 14. Alternative Designs Not Supported 2084 14.1. Why Not HTTP/2 Server-Push 2086 HTTP/2 ([RFC7540]) provides a Server Push facility. Although the 2087 name implies that it might be useful for sending asynchronous updates 2088 from the update stream server to the client, in reality Server Push 2089 is not well suited for that task. To see why it is not, here is a 2090 quick summary of HTTP/2. 2092 HTTP/2 allows an client and a server to multiplex many HTTP requests 2093 and responses over a single TCP connection. The requests and 2094 responses can be interleaved on a block by block basis, avoiding the 2095 head-of-line blocking problem encountered with the Keep-Alive 2096 mechanism in HTTP/1.1. Server Push allows a server to send a 2097 resource (an image, a CSS file, a javascript file, etc.) to the 2098 client before the client explicitly requests it. A server can only 2099 push cacheable GET-mode resources. By pushing a resource, the server 2100 implicitly tells the client, "Add this resource to your cache, 2101 because a resource you have requested needs it." 2103 One approach for using Server Push for updates is for the update 2104 stream server to send each data update message as a separate Server 2105 Push item and let the client apply those updates as they arrive. 2106 Unfortunately, there are several problems with that approach. 2108 First, HTTP/2 does not guarantee that pushed resources are delivered 2109 to the client in the order they were sent by the client, so each data 2110 update message would need a sequence number, and the client would 2111 have to re-sequence them. 2113 Second, an HTTP/2-aware client library will not necessarily inform a 2114 client application when the server pushes a resource. Instead, the 2115 library might cache the pushed resource, and only deliver it to the 2116 client when the client explicitly requests that URI. 2118 But the third problem is the most significant: Server Push is 2119 optional and can be disabled by any proxy between the client and the 2120 server. This is not a problem for the intended use of Server Push: 2121 eventually the client will request those resources, so disabling 2122 Server Push just adds a delay. But this means that Server Push is 2123 not suitable for resources which the client does not know to request. 2125 Thus we do not believe HTTP/2 Server Push is suitable for delivering 2126 asynchronous updates. Hence we have chosen to base ALTO updates on 2127 HTTP/1.1 and SSE. 2129 14.2. Why Not Allowing Stream Restart 2131 If an update stream is closed accidentally, when the ALTO client 2132 reconnects, the update stream server must resend the full maps. This 2133 is clearly inefficient. To avoid that inefficiency, the SSE 2134 specification allows an update stream server to assign an id to each 2135 event. When an ALTO client reconnects, the ALTO client can present 2136 the id of the last successfully received event, and the update stream 2137 server restarts with the next event. 2139 However, that mechanism adds additional complexity. The update 2140 stream server must save SSE messages in a buffer, in case ALTO 2141 clients reconnect. But that mechanism will never be perfect: if the 2142 ALTO client waits too long to reconnect, or if the ALTO client sends 2143 an invalid id, then the update stream server will have to resend the 2144 complete maps anyway. 2146 Furthermore, this is unlikely to be a problem in practice. ALTO 2147 clients who want continuous updates for large resources, such as full 2148 Network and cost maps, are likely to be things like P2P trackers. 2149 These ALTO clients will be well connected to the network; they will 2150 rarely drop connections. 2152 Mobile devices certainly can and do drop connections and will have to 2153 reconnect. But mobile devices will not need continuous updates for 2154 multi-megabyte cost maps. If mobile devices need continuous updates 2155 at all, they will need them for small queries, such as the costs from 2156 a small set of media servers from which the device can stream the 2157 currently playing movie. If the mobile device drops the connection 2158 and reestablishes the update stream, the update stream server will 2159 have to retransmit only a small amount of redundant data. 2161 In short, using event ids to avoid resending the full map adds a 2162 considerable amount of complexity to avoid a situation which we 2163 expect is very rare. We believe that complexity is not worth the 2164 benefit. 2166 The Update Stream service does allow the ALTO client to specify the 2167 tag of the last received version of any tagged resource, and if that 2168 is still current, the update stream server need not retransmit the 2169 full resource. Hence ALTO clients can use this to avoid 2170 retransmitting full network maps. cost maps are not tagged, so this 2171 will not work for them. Of course, the ALTO protocol could be 2172 extended by adding version tags to cost maps, which would solve the 2173 retransmission-on-reconnect problem. However, adding tags to cost 2174 maps might add a new set of complications. 2176 15. Acknowledgments 2178 Thank you to Dawn Chen (Tongji University), Shawn Lin (Tongji 2179 University) and Xiao Shi (Yale University) for their contributions to 2180 an earlier version of this document. 2182 16. References 2184 [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate 2185 Requirement Levels", RFC 2119, BCP 14, March 1997. 2187 [RFC5789] Dusseault, L. and J. Snell, "PATCH Method for HTTP", RFC 2188 5789, March 2010. 2190 [RFC6838] Freed, N., Klensin, J., and T. Hansen, "Media Type 2191 Specifications and Registration Procedures", RFC 6838, 2192 January 2013. 2194 [RFC6902] Bryan, P. and M. Nottingham, "JavaScript Object Notation 2195 (JSON) Patch", RFC 6902, April 2013. 2197 [RFC7159] Bray, T., "The JavaScript Object Notation (JSON) Data 2198 Interchange Format", RFC 7159, March 2014. 2200 [RFC7285] Almi, R., Penno, R., Yang, Y., Kiesel, S., Previdi, S., 2201 Roome, W., Shalunov, S., and R. Woundy, "Application-Layer 2202 Traffic Optimization (ALTO) Protocol", RFC 7285, September 2203 2014. 2205 [RFC7230] Fielding, R. and J. Reschke, "Hypertext Transfer Protocol 2206 (HTTP/1.1): Message Syntax and Routing", RFC 7230, June 2207 2014. 2209 [RFC7231] Fielding, R. and J. Reschke, "Hypertext Transfer Protocol 2210 (HTTP/1.1): Semantics and Content", RFC 7231, June 2014. 2212 [RFC7396] Hoffman, P. and J. Snell, "JSON Merge Patch", RFC 7396, 2213 October 2014. 2215 [RFC7540] Belshe, M., Peon, R., and M. Thomson, "Hypertext Transfer 2216 Protocol Version 2 (HTTP/2)", RFC 7540, May 2015. 2218 [SSE] Hickson, I., "Server-Sent Events (W3C)", W3C 2219 Recommendation 03 February 2015, February 2015. 2221 Authors' Addresses 2223 Wendy Roome 2224 Nokia Bell Labs (Retired) 2225 124 Burlington Rd 2226 Murray Hill, NJ 07974 2227 USA 2229 Phone: +1-908-464-6975 2230 Email: wendy@wdroome.com 2232 Y. Richard Yang 2233 Yale University 2234 51 Prospect St 2235 New Haven CT 2236 USA 2238 Email: yry@cs.yale.edu