idnits 2.17.1 draft-ietf-alto-incr-update-sse-18.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 913 has weird spacing: '...atesReq add;...' -- The document date (January 23, 2020) is 1555 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 404, but not defined == Missing Reference: 'TBD' is mentioned on line 1684, but not defined ** Obsolete normative reference: RFC 4960 (Obsoleted by RFC 9260) ** 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: 7 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: July 26, 2020 Yale University 6 January 23, 2020 8 ALTO Incremental Updates Using Server-Sent Events (SSE) 9 draft-ietf-alto-incr-update-sse-18 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 https://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 July 26, 2020. 59 Copyright Notice 61 Copyright (c) 2020 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 (https://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 . . . . . . . . . . . . . . . 5 78 3. Terms . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 79 4. Background . . . . . . . . . . . . . . . . . . . . . . . . . 7 80 4.1. Server-Sent Events (SSEs) . . . . . . . . . . . . . . . . 7 81 4.2. JSON Merge Patch . . . . . . . . . . . . . . . . . . . . 8 82 4.2.1. JSON Merge Patch Encoding . . . . . . . . . . . . . . 8 83 4.2.2. JSON Merge Patch ALTO Messages . . . . . . . . . . . 9 84 4.3. JSON Patch . . . . . . . . . . . . . . . . . . . . . . . 12 85 4.3.1. JSON Patch Encoding . . . . . . . . . . . . . . . . . 13 86 4.3.2. JSON Patch ALTO Messages . . . . . . . . . . . . . . 13 87 5. Overview of Approach . . . . . . . . . . . . . . . . . . . . 15 88 6. Update Messages: Data Update and Control Update Messages . . 17 89 6.1. ALTO Update Message Format . . . . . . . . . . . . . . . 17 90 6.2. ALTO Data Update Message . . . . . . . . . . . . . . . . 18 91 6.3. ALTO Control Update Message . . . . . . . . . . . . . . . 19 92 7. Update Stream Service . . . . . . . . . . . . . . . . . . . . 20 93 7.1. Media Type . . . . . . . . . . . . . . . . . . . . . . . 20 94 7.2. HTTP Method . . . . . . . . . . . . . . . . . . . . . . . 20 95 7.3. Accept Input Parameters . . . . . . . . . . . . . . . . . 20 96 7.4. Capabilities . . . . . . . . . . . . . . . . . . . . . . 22 97 7.5. Uses . . . . . . . . . . . . . . . . . . . . . . . . . . 23 98 7.6. Response . . . . . . . . . . . . . . . . . . . . . . . . 23 99 7.7. Additional Requirements on Update Messages . . . . . . . 25 100 7.7.1. Event Sequence Requirements . . . . . . . . . . . . . 25 101 7.7.2. Cross-Stream Consistency Requirements . . . . . . . . 25 102 7.7.3. Multipart Update Requirements . . . . . . . . . . . . 26 103 7.8. Keep-Alive Messages . . . . . . . . . . . . . . . . . . . 26 104 8. Stream Control Service . . . . . . . . . . . . . . . . . . . 26 105 8.1. URI . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 106 8.2. Media Type . . . . . . . . . . . . . . . . . . . . . . . 27 107 8.3. HTTP Method . . . . . . . . . . . . . . . . . . . . . . . 27 108 8.4. Accept Input Parameters . . . . . . . . . . . . . . . . . 28 109 8.5. Capabilities & Uses . . . . . . . . . . . . . . . . . . . 28 110 8.6. Response . . . . . . . . . . . . . . . . . . . . . . . . 28 111 9. Examples . . . . . . . . . . . . . . . . . . . . . . . . . . 29 112 9.1. Example: IRD Announcing Update Stream Services . . . . . 29 113 9.2. Example: Simple Network and Cost Map Updates . . . . . . 32 114 9.3. Example: Advanced Network and Cost Map Updates . . . . . 35 115 9.4. Example: Endpoint Property Updates . . . . . . . . . . . 39 116 9.5. Example: Multipart Message Updates . . . . . . . . . . . 42 117 10. Operation and Processing Considerations . . . . . . . . . . . 44 118 10.1. Considerations for Choosing Data Update Messages . . . . 44 119 10.2. Considerations for Client Processing Data Update 120 Messages . . . . . . . . . . . . . . . . . . . . . . . . 45 121 10.3. Considerations for Updates to Filtered Cost Maps . . . . 46 122 10.4. Considerations for Updates to Ordinal Mode Costs . . . . 46 123 10.5. Considerations for SSE Text Formatting and Processing . 46 124 11. Security Considerations . . . . . . . . . . . . . . . . . . . 47 125 11.1. Update Stream Server: Denial-of-Service Attacks . . . . 47 126 11.2. ALTO Client: Update Overloading or Instability . . . . . 48 127 11.3. Stream Control: Spoofed Control Requests . . . . . . . . 48 128 12. Requirements on Future ALTO Services to Use this Design . . . 48 129 13. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 49 130 14. Alternative Designs Not Supported . . . . . . . . . . . . . . 51 131 14.1. Why Not HTTP/2 Server-Push . . . . . . . . . . . . . . . 51 132 14.2. Why Not Allowing Stream Restart . . . . . . . . . . . . 52 133 15. Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . 53 134 16. Contributors . . . . . . . . . . . . . . . . . . . . . . . . 53 135 17. References . . . . . . . . . . . . . . . . . . . . . . . . . 53 136 Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 54 138 1. Introduction 140 The Application-Layer Traffic Optimization (ALTO) [RFC7285] protocol 141 provides network related information called network information 142 resources to client applications so that clients may make informed 143 decisions in utilizing network resources. For example, an ALTO 144 server provides network and cost maps, where a network map partitions 145 the set of endpoints into a manageable number of sets each defined by 146 a Provider-Defined Identifier (PID), and a cost map provides directed 147 costs between PIDs. Given network and cost maps, an ALTO client can 148 obtain costs between endpoints by first using the network map to get 149 the PID for each endpoint, and then using the cost map to get the 150 costs between those PIDs. Such costs can be used by the client to 151 choose communicating endpoints with low network costs. 153 The ALTO protocol defines only an ALTO client pull model, without 154 defining a mechanism to allow an ALTO client to obtain updates to 155 network information resources, other than by periodically re-fetching 156 them. In settings where an information resource may be large but 157 only parts of it may change frequently (e.g., some entries of a cost 158 map), complete re-fetching can be inefficient. 160 This document presents a mechanism to allow an ALTO server to push 161 incremental updates to ALTO clients. Integrating server-push and 162 incremental updates provides two benefits: (1) updates can be 163 immediate, in that the ALTO server can send updates as soon as they 164 are available; and (2) updates can be small, in that if only a small 165 section of an information resource changes, the ALTO server can send 166 just the changes. 168 While primarily intended to provide updates to GET-mode network and 169 cost maps, the mechanism defined in this document can also provide 170 updates to POST-mode ALTO services, such as the endpoint property and 171 endpoint cost services. We intend that the mechanism can also 172 support new ALTO services to be defined by future extensions, but a 173 future service needs to satisfy requirements specified in Section 12. 175 The rest of this document is organized as follows. Section 4 gives 176 background on the basic techniques used in this design: (1) Server- 177 Sent Events to allow server push; (2) JSON merge patch and JSON patch 178 to allow incremental update. With the background, Section 5 gives a 179 non-normative overview of the design. Section 6 defines individual 180 messages in an update stream, and Section 7 defines the overall 181 update stream service; Section 8 defines the stream control service; 182 Section 9 gives several examples; Section 10 describes operation and 183 processing considerations by both ALTO servers and clients; 184 Section 14 discusses two design features that are not supported; 185 Section 11 discusses security issues; The last two sections review 186 the requirements for future ALTO services to use SSE and IANA 187 considerations, respectively. 189 2. Major Changes Since Version -01 191 To RFC editor: This will be removed in the final version. We keep 192 this section to make clear major changes in the technical content. 194 o Incremental encoding using JSON patch: Added JSON patch as an 195 alternative incremental delta encoding than Merge patch. 197 o Substream-id to allow concurrent updates of the same server 198 resource: This design allows an ALTO client to assign a unique 199 substream-id when requesting a resource in an update stream. The 200 server puts the substream-id in each update event for that 201 resource (before, the server used the server's resource-id). This 202 allows a client to use one update stream to receive updates to 203 multiple requests for the same server resource, for example, for a 204 POST-mode resource with different input parameters; before, that 205 required separate update streams. 207 o Multipart resources: Use generic `data-id` subfield of the `event` 208 field to identify the data to be updated. For all major existing 209 data, data-id is the substream-id, but it allows support of 210 multipart as well, by adding content-id. 212 o Flexible control: Defined a new "stream control" resource 213 (Section 8) to allow a client to add or remove resources from a 214 previously created update stream. The ALTO server creates a new 215 stream control resource for each update stream instance, assigns a 216 unique URI to it, and sends the URI to the client as the first 217 event in the stream. 219 3. Terms 221 This document uses the following terms: Update Stream, Update Stream 222 Server, Update Message, Data Update Message, Full Replacement, 223 Incremental Change, Stream Control Service, Stream Control, Stream 224 Control Server, Substream-ID, Data-ID, Control Update Message. 226 Update Stream: An update stream is an HTTP connection between an ALTO 227 client and an ALTO server so that the server can push a sequence of 228 update messages using SSE to the client. 230 Update Stream Server: We refer to an ALTO server providing an update 231 stream as an ALTO update stream server, or update stream server for 232 short. Note that the ALTO server mentioned in this document refers 233 to a general server that provides various kinds of services; it can 234 be an update stream server or stream control server (see below); it 235 can also be a server providing ALTO IRD information. 237 Update Message: An update message is either a data update message or 238 a control update message. 240 Data Update Message: A data update message is for a single ALTO 241 information resource and sent from the update stream server to the 242 ALTO client when the resource changes. A data update message can be 243 either a full-replacement message or an incremental-change message. 244 Full replacement is a shorthand for a full-replacement message, and 245 incremental change is a shorthand for an incremental-change message. 247 Full Replacement: A full replacement for a resource encodes the 248 content of the resource in its original ALTO encoding. 250 Incremental Change: An incremental change specifies only the 251 difference between the new content and the previous version. An 252 incremental change can be encoded using either JSON merge patch or 253 JSON patch in this document. 255 Stream Control Service: An stream control service provides an HTTP 256 URI so that the ALTO client of an update stream can use it to send 257 stream control requests to the ALTO server on the addition or removal 258 of resources receiving update messages from the update stream. The 259 ALTO server creates a new stream control resource for each update 260 stream instance, assigns a unique URI to it, and sends the URI to the 261 client as the first event in the stream. (Note that the Stream 262 Control Service in ALTO has no association with the similarly named 263 Stream Control Transmission Protocol [RFC4960].) 265 Stream Control: A shorthand for stream control service. 267 Stream Control Server: An stream control server providing the stream 268 control service. 270 Substream-ID: An ALTO client can assign a unique substream-id when 271 requesting the addition of a resource receiving update messages from 272 an update stream. The server puts the substream-id in each update 273 event for that resource. Substream-id allows a client to use one 274 update stream to receive updates to multiple requests for the same 275 resource (i.e., with the same resource-id in an ALTO IRD), for 276 example, for a POST-mode resource with different input parameters. 278 Data-ID: It is a subfield of the `event` field of SSE to identify the 279 ALTO data (object) to be updated. For an ALTO resource returning a 280 multipart response, the data-id to identify the data (object) is the 281 substream-id, in addition to the content-id of the object in the 282 multipart response. The data-id of a single part response is just 283 the substream-id. 285 Control Update Message: A control update message is a message in an 286 update stream for the update stream server to notify the ALTO client 287 of related control information of the update stream. The first 288 message of an update stream is a control update message and provides 289 the URI using which the ALTO client can send stream control requests 290 to the stream control server. Additional control update messages in 291 an update stream allow the update stream server to notify the ALTO 292 client of status changes (e.g., the server will no longer send 293 updates for an information resource). 295 4. Background 297 The design requires two basic techniques: server push and encoding of 298 incremental changes. Using existing techniques whenever possible 299 (e.g., WebSocket, HTTP/2), this design uses Server-Sent Events (SSEs) 300 for server push; JSON merge patch and JSON patch to encode 301 incremental changes. Below we give a non-normative summary of these 302 two techniques. 304 4.1. Server-Sent Events (SSEs) 306 The following is a non-normative summary of SSE; see [SSE] for its 307 normative definition. 309 Server-Sent Events enable a server to send new data to a client by 310 "server-push". The client establishes an HTTP ([RFC7230], [RFC7231]) 311 connection to the server and keeps the connection open. The server 312 continually sends messages. Each message has one or more lines, 313 where a line is terminated by a carriage-return immediately followed 314 by a new-line, a carriage-return not immediately followed by a new- 315 line, or a new-line not immediately preceded by a carriage-return. A 316 message is terminated by a blank line (two line terminators in a 317 row). 319 Each line in a message is of the form "field-name: string value". 320 Lines with a blank field-name (that is, lines which start with a 321 colon) are ignored, as are lines which do not have a colon. The 322 protocol defines three field names: event, id, and data. If a 323 message has more than one "data" line, the value of the data field is 324 the concatenation of the values on those lines. There can be only 325 one "event" and "id" line per message. The "data" field is required; 326 the others are optional. 328 Figure 1 is a sample SSE stream, starting with the client request. 329 The server sends three events and then closes the stream. 331 (Client request) 332 GET /stream HTTP/1.1 333 Host: example.com 334 Accept: text/event-stream 336 (Server response) 337 HTTP/1.1 200 OK 338 Connection: keep-alive 339 Content-Type: text/event-stream 341 event: start 342 id: 1 343 data: hello there 345 event: middle 346 id: 2 347 data: let's chat some more ... 348 data: and more and more and ... 350 event: end 351 id: 3 352 data: goodbye 354 Figure 1: A Sample SSE stream. 356 4.2. JSON Merge Patch 358 4.2.1. JSON Merge Patch Encoding 360 To avoid always sending complete data, a server needs mechanisms to 361 encode incremental changes. This design uses JSON merge patch as one 362 mechanism. Below is a non-normative summary of JSON merge patch; see 363 [RFC7396] for the normative definition. 365 JSON merge patch is intended to allow applications to update server 366 resources via the HTTP patch method [RFC5789]. This document adopts 367 the JSON merge patch message format to encode incremental changes, 368 but uses a different HTTP method, i.e., it uses POST instead of 369 PATCH. 371 Informally, a JSON merge patch object is a JSON data structure that 372 defines how to transform one JSON value into another. Specifically, 373 JSON merge patch treats the two JSON values as trees of nested JSON 374 objects (dictionaries of name-value pairs), where the leaves are 375 values (e.g., JSON arrays, strings, numbers) other than JSON objects 376 and the path for each leaf is the sequence of keys leading to that 377 leaf. When the second tree has a different value for a leaf at a 378 path, or adds a new leaf, the JSON merge patch tree has a leaf, at 379 that path, with the new value. When a leaf in the first tree does 380 not exist in the second tree, the JSON merge patch tree has a leaf 381 with a JSON "null" value. The JSON merge patch tree does not have an 382 entry for any leaf that has the same value in both versions. 384 As a result, if all leaf values are simple scalars, JSON merge patch 385 is a quite efficient representation of incremental changes. It is 386 less efficient when leaf values are arrays, because JSON merge patch 387 replaces arrays in their entirety, even if only one entry changes. 389 Formally, the process of applying a JSON merge patch is defined by 390 the following recursive algorithm, as specified in [RFC7396]: 392 define MergePatch(Target, Patch) { 393 if Patch is an Object { 394 if Target is not an Object { 395 Target = {} # Ignore the contents and 396 # set it to an empty Object 397 } 398 for each Name/Value pair in Patch { 399 if Value is null { 400 if Name exists in Target { 401 remove the Name/Value pair from Target 402 } 403 } else { 404 Target[Name] = MergePatch(Target[Name], Value) 405 } 406 } 407 return Target 408 } else { 409 return Patch 410 } 411 } 413 Note that null as the value of a name/value pair will delete the 414 element with "name" in the original JSON value. 416 4.2.2. JSON Merge Patch ALTO Messages 418 To provide both examples of JSON merge patch and a demonstration of 419 the feasibility of applying JSON merge patch to ALTO, we look at the 420 application of JSON merge patch to two key ALTO messages. 422 4.2.2.1. JSON Merge Patch Network Map Messages 424 Section 11.2.1.6 of [RFC7285] defines the format of an ALTO network 425 map message. Assume a simple example ALTO message sending an initial 426 network map: 428 { 429 "meta" : { 430 "vtag": { 431 "resource-id" : "my-network-map", 432 "tag" : "da65eca2eb7a10ce8b059740b0b2e3f8eb1d4785" 433 } 434 }, 435 "network-map" : { 436 "PID1" : { 437 "ipv4" : [ "192.0.2.0/24", "198.51.100.0/25" ] 438 }, 439 "PID2" : { 440 "ipv4" : [ "198.51.100.128/25" ] 441 }, 442 "PID3" : { 443 "ipv4" : [ "0.0.0.0/0" ], 444 "ipv6" : [ "::/0" ] 445 } 446 } 447 } 449 Consider the following JSON merge patch update message, which (1) 450 adds an ipv4 prefix "193.51.100.0/25" and an ipv6 prefix 451 "2001:db8:8000::/33" to "PID1", (2) deletes "PID2", and (3) assigns a 452 new "tag" to the network map: 454 { 455 "meta" : { 456 "vtag" : { 457 "tag" : "a10ce8b059740b0b2e3f8eb1d4785acd42231bfe" 458 } 459 }, 460 "network-map": { 461 "PID1" : { 462 "ipv4" : [ "192.0.2.0/24", "198.51.100.0/25", 463 "193.51.100.0/25" ], 464 "ipv6" : [ "2001:db8:8000::/33" ] 465 }, 466 "PID2" : null 467 } 468 } 470 Applying the JSON merge patch update to the initial network map is 471 equivalent to the following ALTO network map: 473 { 474 "meta" : { 475 "vtag": { 476 "resource-id" : "my-network-map", 477 "tag" : "a10ce8b059740b0b2e3f8eb1d4785acd42231bfe" 478 } 479 }, 480 "network-map" : { 481 "PID1" : { 482 "ipv4" : [ "192.0.2.0/24", "198.51.100.0/25", 483 "193.51.100.0/25" ], 484 "ipv6" : [ "2001:db8:8000::/33" ] 485 }, 486 "PID3" : { 487 "ipv4" : [ "0.0.0.0/0" ], 488 "ipv6" : [ "::/0" ] 489 } 490 } 491 } 493 4.2.2.2. JSON Merge Patch Cost Map Messages 495 Section 11.2.3.6 of [RFC7285] defines the format of an ALTO cost map 496 message. Assume a simple example ALTO message for an initial cost 497 map: 499 { 500 "meta" : { 501 "dependent-vtags" : [ 502 {"resource-id": "my-network-map", 503 "tag": "a10ce8b059740b0b2e3f8eb1d4785acd42231bfe" 504 } 505 ], 506 "cost-type" : { 507 "cost-mode" : "numerical", 508 "cost-metric": "routingcost" 509 }, 510 "vtag": { 511 "resource-id" : "my-cost-map", 512 "tag" : "3ee2cb7e8d63d9fab71b9b34cbf764436315542e" 513 } 514 }, 515 "cost-map" : { 516 "PID1": { "PID1": 1, "PID2": 5, "PID3": 10 }, 517 "PID2": { "PID1": 5, "PID2": 1, "PID3": 15 }, 518 "PID3": { "PID1": 20, "PID2": 15 } 519 } 520 } 522 The following JSON merge patch message updates the example cost map 523 so that (1) the "tag" field of the cost map is updated, (2) the cost 524 of PID1->PID2 is 9 instead of 5, (3) the cost of PID3->PID1 is no 525 longer available, and (4) the cost of PID3->PID3 is defined as 1. 527 { 528 "meta" : { 529 "vtag": { 530 "tag": "c0ce023b8678a7b9ec00324673b98e54656d1f6d" 531 } 532 } 533 "cost-map" : { 534 "PID1" : { "PID2" : 9 }, 535 "PID3" : { "PID1" : null, "PID3" : 1 } 536 } 537 } 539 Hence applying the JSON merge patch to the initial cost map is 540 equivalent to the following ALTO cost map: 542 { 543 "meta" : { 544 "dependent-vtags" : [ 545 {"resource-id": "my-network-map", 546 "tag": "a10ce8b059740b0b2e3f8eb1d4785acd42231bfe" 547 } 548 ], 549 "cost-type" : { 550 "cost-mode" : "numerical", 551 "cost-metric": "routingcost" 552 }, 553 "vtag": { 554 "resource-id": "my-cost-map", 555 "tag": "c0ce023b8678a7b9ec00324673b98e54656d1f6d" 556 } 557 }, 558 "cost-map" : { 559 "PID1": { "PID1": 1, "PID2": 9, "PID3": 10 }, 560 "PID2": { "PID1": 5, "PID2": 1, "PID3": 15 }, 561 "PID3": { "PID2": 15, "PID3": 1 } 562 } 563 } 565 4.3. JSON Patch 566 4.3.1. JSON Patch Encoding 568 One issue of JSON merge patch is that it does not handle array 569 changes well. In particular, JSON merge patch considers an array as 570 a single object and hence can only replace an array in its entirety. 571 When the change is to make a small change to an array such as the 572 deletion of an element from a large array, whole-array replacement is 573 inefficient. Consider the example in Section 4.2.2.1. To add a new 574 entry to the ipv4 array for PID1, the server needs to send a whole 575 new array. Another issue is that JSON merge patch cannot change a 576 value to be null, as the JSON merge patch processing algorithm 577 (MergePatch in Section 4.2.1) interprets a null as a removal 578 instruction. On the other hand, some ALTO resources can have null 579 values, and it is possible that the update will want to change the 580 new value to be null. 582 JSON patch [RFC6902] can address the preceding issues. It defines a 583 set of operators to modify a JSON object. Below is a non-normative 584 description of JSON patch; see [RFC6902] for the normative 585 definition. 587 4.3.2. JSON Patch ALTO Messages 589 To provide both examples of JSON patch and a demonstration of the 590 difference between JSON patch and JSON merge patch, we take a look at 591 the application of JSON patch to the same updates shown in 592 Section 4.2.2. 594 4.3.2.1. JSON Patch Network Map Messages 596 First consider the same update as in Section 4.2.2.1 for the network 597 map. Below is the encoding using JSON patch: 599 [ 600 { 601 "op": "replace", 602 "path": "/meta/vtag/tag", 603 "value": "a10ce8b059740b0b2e3f8eb1d4785acd42231bfe" 604 }, 605 { 606 "op": "add", 607 "path": "/network-map/PID1/ipv4/2", 608 "value": "193.51.100.0/25" 609 } 610 { 611 "op": "add", 612 "path": "/network-map/PID1/ipv6", 613 "value": ["2001:db8:8000::/33"] 614 }, 615 { 616 "op": "remove", 617 "path": "/network-map/PID2" 618 } 619 ] 621 4.3.2.2. JSON Patch Cost Map Messages 623 Compared with JSON merge patch, JSON patch does not encode cost map 624 updates efficiently. Consider the cost map update shown in 625 Section 4.2.2.2, the encoding using JSON patch is: 627 [ 628 { 629 "op": "replace", 630 "path": "/meta/vtag/tag", 631 "value": "c0ce023b8678a7b9ec00324673b98e54656d1f6d" 632 }, 633 { 634 "op": "replace", 635 "path": "/cost-map/PID1/PID2", 636 "value": 9 637 }, 638 { 639 "op": "remove", 640 "path": "/cost-map/PID3/PID1" 641 }, 642 { 643 "op": "replace", 644 "path": "/cost-map/PID3/PID3", 645 "value": 1 646 } 647 ] 649 5. Overview of Approach 651 With the preceding background, we now give a non-normative overview 652 of the update mechanism to be defined in later sections of this 653 document. 655 The building block of the update mechanism defined in this document 656 is the update stream service (defined in Section 7), where each 657 update stream service is a POST-mode service that provides update 658 streams. When an ALTO client requests an update stream service, the 659 ALTO client establishes a persistent connection to the update stream 660 server, creating an update stream. The update stream server uses the 661 update stream to continuously send a sequence of update messages 662 (defined in Section 6) to the ALTO client. An update stream can 663 provide updates to both GET-mode resources, such as ALTO network and 664 cost maps, and POST-mode resources, such as ALTO endpoint property 665 service. 667 An ALTO server may provide any number of update stream services, 668 where each update stream may provide updates for a given subset of 669 the ALTO server's resources. An ALTO server's Information Resource 670 Directory (IRD) defines the update stream services and declares the 671 set of resources for which each update stream service provides 672 updates. The ALTO server selects the resource set for each update 673 stream service. It is recommended that if a resource depends on one 674 or more other resource(s) (indicated with the "uses" attribute 675 defined in [RFC7285]), these other resource(s) should also be part of 676 that update stream. Thus the update stream for a cost map should 677 also provide updates for the network map on which that cost map 678 depends. 680 An ALTO client may request any number of update streams 681 simultaneously. Because each update stream consumes resources on the 682 update stream server, an update stream server may require client 683 authorization and/or authentication, limit the number of open update 684 streams, close inactive streams, or redirect an ALTO client to 685 another update stream server. 687 An ALTO client may use one update stream to receive updates to 688 multiple requests. In particular, the client may request to receive 689 updates for the same resource but with different parameters for a 690 POST-mode resource. Hence, the ALTO server needs an identifier to 691 indicate the specific request among these multiple requests for an 692 update event. To achieve this goal, the client assigns a unique 693 substream-id when requesting a resource in an update stream, and the 694 server puts the substream-id in each update event to distinguish the 695 updates. 697 The key objective of an update stream is to update the ALTO client on 698 data value changes to ALTO resources. This document refers to 699 messages sending such updates as data update messages. Although an 700 update stream may update one or more ALTO resources, each data update 701 message updates only one resource and is sent as a Server-Sent Event 702 (SSE), as defined by [SSE]. A data update message is encoded either 703 as a full replacement or as an incremental change. A full 704 replacement uses the JSON message format defined by the ALTO 705 protocol. There can be multiple encodings for incremental changes. 706 The current design supports incremental changes using JSON merge 707 patch ([RFC7396]) or JSON patch ([RFC6902]) to describe the changes 708 of the resource. Future documents may define additional mechanisms 709 for incremental changes. The update stream server decides when to 710 send data update messages, and whether to send full replacements or 711 incremental changes. These decisions can vary from resource to 712 resource and from update to update. 714 An update stream can run for a long time, and hence there can be 715 status changes at the update stream server side during the lifetime 716 of an update stream; for example, the update stream server may 717 encounter an error or need to shut down for maintenance. To support 718 robust, flexible protocol design, this document allows the update 719 stream server to send server control updates (vs data updates) to the 720 ALTO client as well, showing as control update messages from the 721 update stream server to the ALTO client. 723 ------------------------------------------------------------------ 724 | | 725 | +-------+ +-------+ init request +-------+ | 726 | | | | | <---------- | | | 727 | add/remove | | | | | | | 728 | resource |Stream | |Update | data update | | | 729 ---------> |Control| private |Stream | messages |Client | -- 730 |Server |<------->|Server | -----------> | | 731 ---------- | | | | | | <- 732 | response | | | | -----------> | | | 733 | | | | | control update| | | 734 | +-------+ +-------+ messages +-------+ | 735 | | 736 ------------------------------------------------------------------ 738 Figure 2: ALTO SSE Architecture. 740 In addition to control changes triggered from the update stream 741 server side, in a flexible design, an ALTO client may initiate 742 control changes as well, in particular, by adding or removing ALTO 743 resources receiving updates. An ALTO client initiates such changes 744 using the stream control service. Although one may use a design that 745 the client uses the same HTTP connection to send the control 746 requests, it requires stronger server support such as HTTP pipeline. 747 For more flexibility, this document introduces stream control 748 service. In particular, the update stream server of an update stream 749 uses the first message to provide the URI of the stream control 750 service. The ALTO client can then use the URI to ask the update 751 stream server to (1) send data update messages for additional 752 resources, (2) stop sending data update messages for previously 753 requested resources, or (3) gracefully stop and close the update 754 stream altogether. Figure 2 shows the complete ALTO SSE 755 architecture. 757 6. Update Messages: Data Update and Control Update Messages 759 We now define the details of ALTO SSE. Specifically, an update 760 stream consists of a stream of data update messages (Section 6.2) and 761 control update messages (Section 6.3). 763 6.1. ALTO Update Message Format 765 Data update and control update messages have the same basic 766 structure: each message includes a data field to provide data 767 information, which is typically a JSON object; and an event field 768 preceding the data field, to specify the media type indicating the 769 encoding of the data field. 771 A data update message needs additional information to identify the 772 ALTO data (object) to which the update message applies. For example, 773 an ALTO client can request updates for both a cost map and its 774 dependent network map in the same update stream. The ALTO client 775 assigns substream-id "1" in its request to receive updates to the 776 network map; and substream-id "2" to the cost map. For this example, 777 the substream-id defines the data to be updated and need to be 778 indicated in a data update message. As another example, an ALTO 779 client can request updates for an ALTO resource returning a multipart 780 response. Each part of this multipart response is an HTTP message 781 including a Content-ID header and a JSON object body. The ALTO 782 client assigns substream-id "mp" in its request to recieve updates to 783 each part of the multipart response. For this example, the 784 combination of the substream-id and the Content-ID defines the data 785 to be updated and need to be indicated in a data update message. To 786 be generic, this document use a data-id to identify the ALTO data 787 (object) to be updated. 789 Hence, the event field of ALTO update message can include two sub- 790 fields (media-type and data-id), where the two sub-fields are 791 separated by a comma (',', U+002C): 793 media-type [ ',' data-id ] 795 According to Section 4.2 of [RFC6838], the comma character is not 796 allowed in a media-type name. So there is no ambiguous decoding of 797 the two sub-fields. 799 Note that an update message does not use the SSE "id" field. 801 6.2. ALTO Data Update Message 803 A data update message is sent when a monitored resource changes. In 804 [RFC7285], each resource is encoded as a single JSON object. In the 805 general case, a resource may include multiple JSON objects. This 806 document considers the case that a resource may contain multiple 807 components (parts) and they are encoded using multipart/related 808 [RFC2387]. Each component requiring the service of this document 809 MUST be identified by a unique Content-ID to be defined in its 810 defining document. 812 The `data-id` sub-field identifies the ALTO data to which a data 813 update message applies. For a resource containing only a single JSON 814 object, the substream-id assigned by the client when requesting the 815 SSE service is enough to identify the data. Substream-ids MUST be 816 unique within an update stream, but need not be globally unique. For 817 a resource using multipart/related, the `data-id` sub-field MUST be 818 the concatenation of the substream-id, the '.' separator (U+002E) and 819 the unique Content-ID in order. 821 A substream-id is encoded as a JSON string with the same format as 822 that of the type ResourceID (Section 10.2 of [RFC7285]). The type 823 SubstreamID is used in this document to indicate a string of this 824 format. 826 A data update is either a complete specification of the identified 827 data, or else an incremental patch (e.g., a JSON merge patch or JSON 828 patch), if possible, describing the changes from the last version of 829 the data. This document refers to these as full replacement and 830 incremental change, respectively. The encoding of a full replacement 831 is defined its defining document (e.g., network and cost map messages 832 by [RFC7285], and uses media type defined in that document. The 833 encoding of JSON merge patch is defined by [RFC7396], with media type 834 "application/merge-patch+json"; the encoding of JSON patch is defined 835 by [RFC6902], with media type "application/json-patch+json". 837 Figure 3 shows some examples of ALTO data update messages: 839 event: application/alto-networkmap+json,1 840 data: { ... full network map message ... } 842 event: application/alto-costmap+json,2 843 data: { ... full cost map message ... } 845 event: application/merge-patch+json,2 846 data: { ... JSON merge patch update for the cost map ... } 848 Figure 3: Examples of ALTO data update messages. 850 6.3. ALTO Control Update Message 852 Control update messages have the media type "application/alto- 853 updatestreamcontrol+json", and the data is of type 854 UpdateStreamControlEvent: 856 object { 857 [String control-uri;] 858 [SubstreamID started<1..*>;] 859 [SubstreamID stopped<1..*>;] 860 [String description;] 861 } UpdateStreamControlEvent; 863 control-uri: the URI providing stream control for this update stream 864 (see Section 8). The server MUST send a control update message 865 with an URI as the first event in an update stream. If the URI 866 is NULL, the update stream server does not support stream 867 control for this update stream; otherwise, the update stream 868 server provides stream control through the given URI. 870 started: a list of substream-ids of resources. It notifies the ALTO 871 client that the update stream server will start sending data 872 update messages for each resource listed. 874 stopped: a list of substream-ids of resources. It notifies the ALTO 875 client that the update stream server will no longer send data 876 update messages for the listed resources. There can be multiple 877 reasons for an update stream server to stop sending data update 878 messages for a resource, including a request from the ALTO 879 client using stream control (Section 7.7.1) or an internal 880 server event. 882 description: a non-normative text providing an explanation for the 883 control event. When an update stream server stops sending data 884 update messages for a resource, it is RECOMMENDED that the 885 update stream server use the description field to provide 886 details. 888 7. Update Stream Service 890 An update stream service returns a stream of update messages, as 891 defined in Section 6. An ALTO server's IRD (Information Resource 892 Directory) MAY define one or more update stream services, which ALTO 893 clients use to request new update stream instances. 895 7.1. Media Type 897 The media type of an ALTO update stream service is "text/event- 898 stream", as defined by [SSE]. 900 7.2. HTTP Method 902 An ALTO update stream service is requested using the HTTP POST 903 method. 905 7.3. Accept Input Parameters 907 An ALTO client specifies the parameters for the new update stream by 908 sending an HTTP POST body with the media type "application/alto- 909 updatestreamparams+json". That body contains a JSON Object of type 910 UpdateStreamReq, where: 912 object { 913 [AddUpdatesReq add;] 914 [SubstreamID remove<0..*>;] 915 } UpdateStreamReq; 917 object-map { 918 SubstreamID -> AddUpdateReq; 919 } AddUpdatesReq; 921 object { 922 String resource-id; 923 [String tag;] 924 [Boolean incremental-changes;] 925 [Object input;] 926 } AddUpdateReq; 928 add: specifies the resources (and the parameters for the resources) 929 for which the ALTO client wants updates. We say that the add- 930 request creates a substream. The ALTO client MUST assign a 931 unique substream-id (Section 6.2) for each entry, and uses those 932 substream-ids as the keys in the "add" field. 934 resource-id: the resource-id of an ALTO resource, and MUST be in the 935 update stream's "uses" list (Section 8.5.2 of Section 7.5). If 936 the resource-id is a GET-mode resource with a version tag (or 937 "vtag"), as defined in Section 6.3 and Section 10.3 of 938 [RFC7285], and the ALTO client has previously retrieved a 939 version of that resource from the update stream server, the ALTO 940 client MAY set the "tag" field to the tag part of the client's 941 version of that resource. If that version is not current, the 942 update stream server MUST send a full replacement before sending 943 any incremental changes, as described in Section 7.7.1. If that 944 version is still current, the update stream server MAY omit the 945 initial full replacement. 947 incremental-changes: the ALTO client specifies whether it is willing 948 to receive incremental changes from the update stream server for 949 this substream. If the "incremental-changes" field is "true", 950 the update stream server MAY send incremental changes for this 951 substream (assuming the update stream server supports 952 incremental changes for) that resource; see 953 Section Section 7.4). If the "incremental-changes" field is 954 "false", the update stream server MUST NOT send incremental 955 changes for that substream. The default value for "incremental- 956 changes" is "true", so to suppress incremental changes, the ALTO 957 client MUST explicitly set "incremental-changes" to "false". An 958 alternative design of incremental-changes control is a more 959 fine-grained control, by allowing a client to select the subset 960 of incremental methods from the set announced in the server's 961 capabilities (see Section Section 7.4). But this adds 962 complexity to server, which is more likely to be the bottleneck. 963 Note that the ALTO client cannot suppress full replacement. 964 When the ALTO client sets "incremental-changes" to "false", the 965 update stream server MUST send a full replacement instead of an 966 incremental change to the ALTO client. The update stream server 967 MAY wait until more changes are available, and send a single 968 full replacement with those changes. Thus an ALTO client which 969 declines to accept incremental changes may not get updates as 970 quickly as an ALTO client which does. 972 input: If the resource is a POST-mode service which requires input, 973 the ALTO client MUST set the "input" field to a JSON Object with 974 the parameters that the resource expects. 976 remove: it is used in update stream control requests (Section 8), 977 and is not allowed in the update stream request. The update 978 stream server SHOULD ignore this field if it is included in the 979 request. 981 If a request has any errors, the update stream server MUST NOT create 982 an update stream. Also, the update stream server will send an error 983 response to the ALTO client as specified in Section 7.6. 985 7.4. Capabilities 987 The capabilities are defined as an object of type 988 UpdateStreamCapabilities: 990 object { 991 IncrementalUpdateMediaTypes incremental-change-media-types; 992 Boolean support-stream-control; 993 } UpdateStreamCapabilities; 995 object-map { 996 ResourceID -> String; 997 } IncrementalUpdateMediaTypes; 999 If this update stream can provide data update messages with 1000 incremental changes for a resource, the "incremental-change-media- 1001 types" field has an entry for that resource-id, and the value is the 1002 media-type of the incremental change. Normally this will be 1003 "application/merge-patch+json", "application/json-patch+json", or 1004 "application/merge-patch+json,application/json-patch+json", because, 1005 as described in Section 6, they are the only incremental change types 1006 defined by this document. However future extensions may define other 1007 types of incremental changes. 1009 When choosing the media-type to encode incremental changes for a 1010 resource, the update stream server SHOULD consider the limitations of 1011 the encoding. For example, when a JSON merge patch specifies that 1012 the value of a field is null, its semantics is that the field is 1013 removed from the target, and hence the field is no longer defined 1014 (i.e., undefined); see the MergePatch algorithm in Section 4.2.1 on 1015 how null value is processed. This, however, may not be the intended 1016 result for the resource, when null and undefined have different 1017 semantics for the resource. In such a case, the update stream server 1018 SHOULD choose JSON patch over JSON merge patch. 1020 The "support-stream-control" field specifies whether the given update 1021 stream supports stream control. If "support-stream-control" field is 1022 "true", the update stream server will uses the stream control 1023 specified in this document; else, the update stream server may use 1024 other mechanisms to provide the same functionality as stream control. 1026 7.5. Uses 1028 The "uses" attribute MUST be an array with the resource-ids of every 1029 resource for which this update stream can provide updates. Each 1030 resource specified in the "uses" MUST support full replacement: the 1031 update stream server can always send full replacement, and the ALTO 1032 client MUST accept full replacement. 1034 This set may be any subset of the ALTO server's resources, and may 1035 include resources defined in linked IRDs. However, it is RECOMMENDED 1036 that the ALTO server selects a set that is closed under the resource 1037 dependency relationship. That is, if an update stream's "uses" set 1038 includes resource R1, and resource R1 depends on ("uses") resource 1039 R0, then the update stream's "uses" set SHOULD include R0 as well as 1040 R1. For example, an update stream for a cost map SHOULD also provide 1041 updates for the network map upon which that cost map depends. 1043 7.6. Response 1045 If the update stream request has any errors, the update stream server 1046 MUST return an HTTP "400 Bad Request" to the ALTO client. The body 1047 part of the HTTP response is the JSON object defined in Section 8.5.2 1048 in [RFC7285]. Hence, an ALTO error response has the format: 1050 HTTP/1.1 400 Bad Request 1051 Content-Length: [TBD] 1052 Content-Type: application/alto-error+json 1053 Connection: Closed 1055 { 1056 "meta":{ 1057 "code": "***", 1058 "field": "***", 1059 "value": "***" 1060 } 1061 } 1063 Note that "field" and "value" are optional fields. If the "value" 1064 field exists, the "field" field MUST exist. 1066 o If an update stream request does not have an "add" field 1067 specifying one or more resources, the error code of the error 1068 message MUST be E_MISSING_FIELD and the "field" field SHOULD be 1069 "add". The update stream server MUST close the stream without 1070 sending any events. 1072 o If the "resource-id" field is invalid, or is not associated with 1073 the update stream, the error code of the error message MUST be 1074 E_INVALID_FIELD_VALUE; the "field" field SHOULD be "resource-id" 1075 and the "value" field SHOULD be the invalid resource-id. If there 1076 are more than one invalid resource-ids, the update stream server 1077 SHOULD pick one and return it. The update stream server MUST 1078 close the stream without sending any events. 1080 o If the resource is a POST-mode service which requires input, the 1081 client MUST set the "input" field to a JSON Object with the 1082 parameters that that resource expects. If the "input" field is 1083 missing or invalid, the update stream server MUST return the same 1084 error response that that resource would return for missing or 1085 invalid input (see [RFC7285]). In this case, the update stream 1086 server MUST close the update stream without sending any events. 1087 If the input for several POST-mode resources are missing or 1088 invalid, the update stream server MUST pick one and return it. 1090 The response to a valid request is a stream of update messages. 1091 Section 6 defines the update messages, and [SSE] defines how they are 1092 encoded into a stream. 1094 An update stream server SHOULD send updates only when the underlying 1095 values change. However, it may be difficult for an update stream 1096 server to guarantee that in all circumstances. Therefore a client 1097 MUST NOT assume that an update message represents an actual change. 1099 7.7. Additional Requirements on Update Messages 1101 7.7.1. Event Sequence Requirements 1103 o The first event MUST be a control update message with the URI of 1104 the update stream control service Section 8 for this update 1105 stream. 1107 o As soon as possible after the ALTO client initiates the 1108 connection, the update stream server MUST send a full replacement 1109 for each resource-id requested with a version tag. In this case 1110 the update stream server MAY omit the initial full replacement for 1111 that resource, if the "tag" field the ALTO client provided for 1112 that resource-id matches the tag of the update stream's current 1113 version. 1115 o If this update stream provides update for resource-ids and R0 and 1116 R1, and if R1 depends on R0, then the update stream server MUST 1117 send the update for R0 before sending the related updates for R1. 1118 For example, suppose an update stream provides updates to a 1119 network map and its dependent cost maps. When the network map 1120 changes, the update stream server MUST send the network map update 1121 before sending the cost map updates. 1123 o When the ALTO client uses the stream control service to stop 1124 updates for one or more resources Section 8, the ALTO client MUST 1125 send a stream control request. The update stream server MUST send 1126 a control update message whose "stopped" field has the substream- 1127 ids of all active resources. 1129 7.7.2. Cross-Stream Consistency Requirements 1131 If several ALTO clients create multiple update streams for updates to 1132 the same resource, the update stream server MUST send the same 1133 updates to all of them. However, the update stream server MAY pack 1134 data items into different patch events, as long as the net result of 1135 applying those updates is the same. 1137 For example, suppose two different ALTO clients create update streams 1138 for the same cost map, and suppose the update stream server processes 1139 three separate cost point updates with a brief pause between each 1140 update. The server MUST send all three new cost points to both 1141 clients. But the update stream server MAY send a single patch event 1142 (with all three cost points) to one ALTO client, while sending three 1143 separate patch events (with one cost point per event) to the other 1144 ALTO client. 1146 A update stream server MAY offer several different update stream 1147 resources that provide updates to the same underlying resource (that 1148 is, a resource-id may appear in the "uses" field of more than one 1149 update stream resource). In this case, those update stream resources 1150 MUST return the same update data. 1152 7.7.3. Multipart Update Requirements 1154 This design allows any valid media type for full replacement. Hence, 1155 it supports ALTO resources using multipart to contain multiple JSON 1156 objects. This realizes the push benefit, but not the incremental 1157 encoding benefit of SSE. 1159 JSON Patch and Merge Patch provide the incremental encoding benefit 1160 but can be applied to only a single JSON object. If an update stream 1161 service (1) supports a resource providing a multipart media type and 1162 (2) specifies an incremental media type for the resource in its 1163 capabilities, the server MUST (1) use substream-id.content-id in its 1164 `event` field, (2) include the content-id in the multipart message, 1165 and (3) the content identified by the content-id must be a single 1166 JSON object. 1168 7.8. Keep-Alive Messages 1170 In an SSE stream, any line which starts with a colon (U+003A) 1171 character is a comment, and an ALTO client MUST ignore that line 1172 ([SSE]). As recommended in [SSE], an update stream server SHOULD 1173 send a comment line (or an event) every 15 seconds to prevent ALTO 1174 clients and proxy servers from dropping the HTTP connection. 1176 8. Stream Control Service 1178 An stream control service allows an ALTO client to remove resources 1179 from the set of resources that are monitored by an update stream, or 1180 add additional resources to that set. The service also allows an 1181 ALTO client to gracefully shut down an update stream. 1183 When an update stream server creates a new update stream, and if the 1184 update stream server supports stream control for the update stream, 1185 the update stream server creates a stream control service for that 1186 update stream. An ALTO client uses the stream control service to 1187 remove resources from the update stream instance, or to request 1188 updates for additional resources. An ALTO client cannot obtain the 1189 stream control service through the IRD. Instead, the first event 1190 that the update stream server sends to the ALTO client has the URI 1191 for the associated stream control service (see Section 6.3). 1193 Each stream control request is an individual HTTP request. If the 1194 ALTO client and the stream control server the ALTO client MAY send 1195 multiple stream control requests to the stream control server using 1196 the same HTTP connection. 1198 8.1. URI 1200 The URI for an stream control service, by itself, MUST uniquely 1201 specify the update stream instance which it controls. The stream 1202 control server MUST NOT use other properties of an HTTP request, such 1203 as cookies or the client's IP address, to determine the update 1204 stream. Furthermore, an update stream server MUST NOT reuse a 1205 control service URI once the associated update stream has been 1206 closed. 1208 The ALTO client MUST evaluate a non-absolute control URI (for 1209 example, a URI without a host, or with a relative path) in the 1210 context of the URI used to create the update stream. The stream 1211 control service's host MAY be different from the update stream's 1212 host. 1214 It is expected that the update stream server will assign a unique 1215 stream id to each update stream instance and will embed that id in 1216 the associated stream control URI. However, the exact mechanism is 1217 left to the update stream server. ALTO clients MUST NOT attempt to 1218 deduce a stream id from the control URI. 1220 To prevent an attacker from forging a stream control URI and sending 1221 bogus requests to disrupt other update streams, stream control URIs 1222 SHOULD contain sufficient random redundancy to make it difficult to 1223 guess valid URIs. 1225 8.2. Media Type 1227 An ALTO stream control response does not have a specific media type. 1229 8.3. HTTP Method 1231 An ALTO update stream control resource is requested using the HTTP 1232 POST method. 1234 8.4. Accept Input Parameters 1236 An stream control service accepts the same input media type and input 1237 parameters as the update stream service (Section 7.3). The only 1238 difference is that a stream control service also accepts the "remove" 1239 field. 1241 If specified, the "remove" field is an array of substream-ids the 1242 ALTO client previously added to this update stream. An empty 1243 "remove" array is equivalent to a list of all currently active 1244 resources; the update stream server responds by removing all 1245 resources and closing the stream. 1247 An ALTO client MAY use the "add" field to add additional resources. 1248 However, the ALTO client MUST assign a unique substream-id to each 1249 resource. Substream-ids MUST be unique over the lifetime of this 1250 update stream: an ALTO client MUST NOT reuse a previously removed 1251 substream-id. 1253 If a request has any errors, the update stream server MUST NOT add or 1254 remove any resources from the associated update stream. Also, the 1255 stream control server will return an error response to the client as 1256 specified in Section 8.6. 1258 8.5. Capabilities & Uses 1260 None (Stream control services do not appear in the IRD). 1262 8.6. Response 1264 The stream control server MUST process the "add" field before the 1265 "remove" field. If the request removes all active resources without 1266 adding any additional resources, the update stream server MUST close 1267 the update stream. Thus an update stream cannot have zero resources. 1269 If the request has any errors, the stream control server MUST return 1270 an HTTP "400 Bad Request" to the ALTO client. The body part of the 1271 HTTP response is the JSON object defined in Section 8.5.2 in 1272 [RFC7285]. An error response has the same format as specified in 1273 Section 7.6. Detailed error code and error information are specified 1274 as below. 1276 o If the "add" request does not satisfy the requirements in 1277 Section 7.3, the stream control server MUST return the ALTO error 1278 message defined in Section 7.6. 1280 o If any substream-id in the "remove" field was not added in a prior 1281 request, the error code of the error message MUST be 1282 E_INVALID_FIELD_VALUE; the "field" field SHOULD be "remove" and 1283 the "value" field SHOULD be the array of the invalid substream- 1284 ids. Thus it is illegal to "add" and "remove" the same substream- 1285 id in the same request. However, it is legal to remove a 1286 substream-id twice. 1288 o If any substream-id in the "add" field has been used before in 1289 this stream, the error code of the error message MUST be 1290 E_INVALID_FIELD_VALUE, the "field" field SHOULD be "add" and the 1291 "value" field SHOULD be the array of invalid substream-ids. 1293 o If the request has a non-empty "add" field and a "remove" field 1294 with an empty list of substream-ids (to replace all active 1295 resources with a new set, the client MUST explicitly enumerate the 1296 substream-ids to be removed), the error code of the error message 1297 MUST be E_INVALID_FIELD_VALUE; the "field" field SHOULD be 1298 "remove" and the "value" field SHOULD be an empty array. 1300 If the request is valid but the associated update stream has been 1301 closed. The stream control server MUST return an HTTP "404 Not 1302 Found". 1304 If the request is valid and the stream control server successfully 1305 processes the request without error, the stream control server should 1306 return either an HTTP "202 Accepted" response or an HTTP "204 No 1307 Content" response. The difference is that for the latter case, the 1308 stream control server is sure that the update stream server has also 1309 processed the request. Regardless of 202 or 204 HTTP response, the 1310 final updates of related resources will be notified by the update 1311 stream server using its control update message(s), due to our modular 1312 design. 1314 9. Examples 1316 9.1. Example: IRD Announcing Update Stream Services 1318 Below is an example IRD announcing three update stream services. The 1319 first, which is named "update-my-costs", provides updates for the 1320 network map, the "routingcost" and "hopcount" cost maps, and a 1321 filtered cost map resource. The second, which is named "update-my- 1322 prop", provides updates to the endpoint properties service. The 1323 third, which is named "update-my-pv", provides updates to a non- 1324 standard ALTO service returning a multipart response. 1326 Note that in the "update-my-costs" update stream shown in the example 1327 IRD, the update stream server uses JSON patch for network map, and it 1328 uses JSON merge patch to update the other resources. Also, the 1329 update stream will only provide full replacements for "my-simple- 1330 filtered-cost-map". 1332 Also, note that this IRD defines two filtered cost map resources. 1333 They use the same cost types, but "my-filtered-cost-map" accepts cost 1334 constraint tests, while "my-simple-filtered-cost-map" does not. To 1335 avoid the issues discussed in Section 10.3, the update stream 1336 provides updates for the second, but not the first. 1338 This IRD also announces a non-standard ALTO service, which is named 1339 "my-pv". This service accepts an extended endpoint cost request as 1340 an input and returns a multipart response including an endpoint cost 1341 resource and a property map resource. This document does not rely on 1342 any other design details of this new service. In this document, the 1343 "my-pv" service is only used to illustrate how the update stream 1344 service provides updates to an ALTO resource returning a multipart 1345 response. 1347 "my-network-map": { 1348 "uri": "http://alto.example.com/networkmap", 1349 "media-type": "application/alto-networkmap+json", 1350 }, 1351 "my-routingcost-map": { 1352 "uri": "http://alto.example.com/costmap/routingcost", 1353 "media-type": "application/alto-costmap+json", 1354 "uses": ["my-networkmap"], 1355 "capabilities": { 1356 "cost-type-names": ["num-routingcost"] 1357 } 1358 }, 1359 "my-hopcount-map": { 1360 "uri": "http://alto.example.com/costmap/hopcount", 1361 "media-type": "application/alto-costmap+json", 1362 "uses": ["my-networkmap"], 1363 "capabilities": { 1364 "cost-type-names": ["num-hopcount"] 1365 } 1366 }, 1367 "my-filtered-cost-map": { 1368 "uri": "http://alto.example.com/costmap/filtered/constraints", 1369 "media-type": "application/alto-costmap+json", 1370 "accepts": "application/alto-costmapfilter+json", 1371 "uses": ["my-networkmap"], 1372 "capabilities": { 1373 "cost-type-names": ["num-routingcost", "num-hopcount"], 1374 "cost-constraints": true 1375 } 1376 }, 1377 "my-simple-filtered-cost-map": { 1378 "uri": "http://alto.example.com/costmap/filtered/simple", 1379 "media-type": "application/alto-costmap+json", 1380 "accepts": "application/alto-costmapfilter+json", 1381 "uses": ["my-networkmap"], 1382 "capabilities": { 1383 "cost-type-names": ["num-routingcost", "num-hopcount"], 1384 "cost-constraints": false 1385 } 1386 }, 1387 "my-props": { 1388 "uri": "http://alto.example.com/properties", 1389 "media-type": "application/alto-endpointprops+json", 1390 "accepts": "application/alto-endpointpropparams+json", 1391 "capabilities": { 1392 "prop-types": ["priv:ietf-bandwidth"] 1393 } 1394 }, 1395 "my-pv": { 1396 "uri": "http://alto.example.com/endpointcost/pv", 1397 "media-type": "multipart/related; 1398 type=application/alto-endpointcost+json", 1399 "accepts": "application/alto-endpointcostparams+json", 1400 "capabilities": { 1401 "cost-type-names": [ "path-vector" ], 1402 "ane-properties": [ "maxresbw", "persistent-entities" ] 1403 } 1404 }, 1405 "update-my-costs": { 1406 "uri": "http://alto.example.com/updates/costs", 1407 "media-type": "text/event-stream", 1408 "accepts": "application/alto-updatestreamparams+json", 1409 "uses": [ 1410 "my-network-map", 1411 "my-routingcost-map", 1412 "my-hopcount-map", 1413 "my-simple-filtered-cost-map" 1414 ], 1415 "capabilities": { 1416 "incremental-change-media-types": { 1417 "my-network-map": "application/json-patch+json", 1418 "my-routingcost-map": "application/merge-patch+json", 1419 "my-hopcount-map": "application/merge-patch+json" 1420 }, 1421 "support-stream-control": true 1422 } 1423 }, 1424 "update-my-props": { 1425 "uri": "http://alto.example.com/updates/properties", 1426 "media-type": "text/event-stream", 1427 "uses": [ "my-props" ], 1428 "accepts": "application/alto-updatestreamparams+json", 1429 "capabilities": { 1430 "incremental-change-media-types": { 1431 "my-props": "application/merge-patch+json" 1432 }, 1433 "support-stream-control": true 1434 } 1435 }, 1436 "update-my-pv": { 1437 "uri": "http://alto.example.com/updates/pv", 1438 "media-type": "text/event-stream", 1439 "uses": [ "my-pv" ], 1440 "accepts": "application/alto-updatestreamparams+json", 1441 "capabilities": { 1442 "incremental-change-media-types": { 1443 "my-pv": "application/merge-patch+json" 1444 }, 1445 "support-stream-control": true 1446 } 1447 } 1449 9.2. Example: Simple Network and Cost Map Updates 1451 Given the update streams announced in the preceding example IRD, 1452 below we show an example of an ALTO client's request and the update 1453 stream server's immediate response, using the update stream resource 1454 "update-my-costs". In the example, the ALTO client requests updates 1455 for the network map and "routingcost" cost map, but not for the 1456 "hopcount" cost map. The ALTO client uses the ALTO server's 1457 resource-ids as the substream-ids. Because the client does not 1458 provide a "tag" for the network map, the update stream server must 1459 send a full replacement for the network map as well as for the cost 1460 map. The ALTO client does not set "incremental-changes" to "false", 1461 so it defaults to "true". Thus, the update stream server will send 1462 patch updates for the cost map and the network map. 1464 POST /updates/costs HTTP/1.1 1465 Host: alto.example.com 1466 Accept: text/event-stream,application/alto-error+json 1467 Content-Type: application/alto-updatestreamparams+json 1468 Content-Length: ### 1470 { "add": { 1471 "my-network-map": { 1472 "resource-id": "my-network-map" 1473 }, 1474 "my-routingcost-map": { 1475 "resource-id": "my-routingcost-map" 1476 } 1477 } 1478 } 1480 HTTP/1.1 200 OK 1481 Connection: keep-alive 1482 Content-Type: text/event-stream 1484 event: application/alto-updatestreamcontrol+json 1485 data: {"control-uri": 1486 data: "http://alto.example.com/updates/streams/3141592653589"} 1488 event: application/alto-networkmap+json,my-network-map 1489 data: { 1490 data: "meta" : { 1491 data: "vtag": { 1492 data: "resource-id" : "my-network-map", 1493 data: "tag" : "da65eca2eb7a10ce8b059740b0b2e3f8eb1d4785" 1494 data: } 1495 data: }, 1496 data: "network-map" : { 1497 data: "PID1" : { 1498 data: "ipv4" : [ "192.0.2.0/24", "198.51.100.0/25" ] 1499 data: }, 1500 data: "PID2" : { 1501 data: "ipv4" : [ "198.51.100.128/25" ] 1502 data: }, 1503 data: "PID3" : { 1504 data: "ipv4" : [ "0.0.0.0/0" ], 1505 data: "ipv6" : [ "::/0" ] 1506 data: } 1507 data: } 1508 data: } 1509 data: } 1511 event: application/alto-costmap+json,my-routingcost-map 1512 data: { 1513 data: "meta" : { 1514 data: "dependent-vtags" : [{ 1515 data: "resource-id": "my-network-map", 1516 data: "tag": "da65eca2eb7a10ce8b059740b0b2e3f8eb1d4785" 1517 data: }], 1518 data: "cost-type" : { 1519 data: "cost-mode" : "numerical", 1520 data: "cost-metric": "routingcost" 1521 data: }, 1522 data: "vtag": { 1523 data: "resource-id" : "my-routingcost-map", 1524 data: "tag" : "3ee2cb7e8d63d9fab71b9b34cbf764436315542e" 1525 data: } 1526 data: }, 1527 data: "cost-map" : { 1528 data: "PID1": { "PID1": 1, "PID2": 5, "PID3": 10 }, 1529 data: "PID2": { "PID1": 5, "PID2": 1, "PID3": 15 }, 1530 data: "PID3": { "PID1": 20, "PID2": 15 } 1531 data: } 1532 data: } 1534 After sending those events immediately, the update stream server will 1535 send additional events as the maps change. For example, the 1536 following represents a small change to the cost map. PID1->PID2 is 1537 changed to 9 from 5, PID3->PID1 is no longer available and PID3->PID3 1538 is now defined as 1: 1540 event: application/merge-patch+json,my-routingcost-map 1541 data: { 1542 data: "meta" : { 1543 data: "vtag": { 1544 data: "tag": "c0ce023b8678a7b9ec00324673b98e54656d1f6d" 1545 data: } 1546 data: }, 1547 data: "cost-map": { 1548 data: "PID1" : { "PID2" : 9 }, 1549 data: "PID3" : { "PID1" : null, "PID3" : 1 } 1550 data: } 1551 data: } 1553 As another example, the following represents a change to the network 1554 map: an ipv4 prefix "193.51.100.0/25" is added to PID1. It triggers 1555 changes to the cost map. The update stream server chooses to send an 1556 incremental change for the network map and send a full replacement 1557 instead of an incremental change for the cost map: 1559 event: application/json-patch+json,my-network-map 1560 data: { 1561 data: { 1562 data: "op": "replace", 1563 data: "path": "/meta/vtag/tag", 1564 data: "value" :"a10ce8b059740b0b2e3f8eb1d4785acd42231bfe" 1565 data: }, 1566 data: { 1567 data: "op": "add", 1568 data: "path": "/network-map/PID1/ipv4/2", 1569 data: "value": "193.51.100.0/25" 1570 data: } 1571 data: } 1573 event: application/alto-costmap+json,my-routingcost-map 1574 data: { 1575 data: "meta" : { 1576 data: "vtag": { 1577 data: "tag": "c0ce023b8678a7b9ec00324673b98e54656d1f6d" 1578 data: } 1579 data: }, 1580 data: "cost-map" : { 1581 data: "PID1": { "PID1": 1, "PID2": 3, "PID3": 7 }, 1582 data: "PID2": { "PID1": 12, "PID2": 1, "PID3": 9 }, 1583 data: "PID3": { "PID1": 14, "PID2": 8 } 1584 data: } 1585 data: } 1587 9.3. Example: Advanced Network and Cost Map Updates 1589 This example is similar to the previous one, except that the ALTO 1590 client requests updates for the "hopcount" cost map as well as the 1591 "routingcost" cost map and provides the current version tag of the 1592 network map, so the update stream server is not required to send the 1593 full network map data update message at the beginning of the stream. 1594 In this example, the client uses the substream-ids "net", "routing" 1595 and "hops" for those resources. The update stream server sends the 1596 stream control URI and the full cost maps, followed by updates for 1597 the network map and cost maps as they become available: 1599 POST /updates/costs HTTP/1.1 1600 Host: alto.example.com 1601 Accept: text/event-stream,application/alto-error+json 1602 Content-Type: application/alto-updatestreamparams+json 1603 Content-Length: ### 1605 { "add": { 1606 "net": { 1607 "resource-id": "my-network-map". 1608 "tag": "a10ce8b059740b0b2e3f8eb1d4785acd42231bfe" 1609 }, 1610 "routing": { 1611 "resource-id": "my-routingcost-map" 1612 }, 1613 "hops": { 1614 "resource-id": "my-hopcount-map" 1615 } 1616 } 1617 } 1619 HTTP/1.1 200 OK 1620 Connection: keep-alive 1621 Content-Type: text/event-stream 1623 event: application/alto-updatestreamcontrol+json 1624 data: {"control-uri": 1625 data: "http://alto.example.com/updates/streams/2718281828459"} 1627 event: application/alto-costmap+json,routing 1628 data: { ... full routingcost cost map message ... } 1630 event: application/alto-costmap+json,hops 1631 data: { ... full hopcount cost map message ... } 1633 (pause) 1635 event: application/merge-patch+json,routing 1636 data: {"cost-map": {"PID2" : {"PID3" : 31}}} 1638 event: application/merge-patch+json,hops 1639 data: {"cost-map": {"PID2" : {"PID3" : 4}}} 1641 If the ALTO client wishes to stop receiving updates for the 1642 "hopcount" cost map, the ALTO client can send a "remove" request on 1643 the stream control URI: 1645 POST /updates/streams/2718281828459" HTTP/1.1 1646 Host: alto.example.com 1647 Accept: text/plain,application/alto-error+json 1648 Content-Type: application/alto-updatestreamparams+json 1649 Content-Length: ### 1651 { 1652 "remove": [ "hops" ] 1653 } 1655 HTTP/1.1 204 No Content 1656 Content-Length: 0 1658 (stream closed without sending data content) 1660 The update stream server sends a "stopped" control update message on 1661 the original request stream to inform the ALTO client that updates 1662 are stopped for that resource: 1664 event: application/alto-updatestreamcontrol+json 1665 data: { 1666 data: "stopped": ["hops"] 1667 data: } 1669 Below is an example of an invalid stream control request. The 1670 "remove" field of the request includes an undefined substream-id and 1671 the stream control server will return an error response to the ALTO 1672 client. 1674 POST /updates/streams/2718281828459 HTTP/1.1 1675 Host: alto.example.com 1676 Accept: text/plain,application/alto-error+json 1677 Content-Type: application/alto-updatestreamparams+json 1678 Content-Length: ### 1679 { 1680 "remove": [ "properties" ] 1681 } 1683 HTTP/1.1 400 Bad Request 1684 Content-Length: [TBD] 1685 Content-Type: application/alto-error+json 1687 { 1688 "meta":{ 1689 "code": "E_INVALID_FIELD_VALUE", 1690 "field": "remove", 1691 "value": "properties" 1692 } 1694 If the ALTO client no longer needs any updates, and wishes to shut 1695 the update stream down gracefully, the client can send a "remove" 1696 request with an empty array: 1698 POST /updates/streams/2718281828459 HTTP/1.1 1699 Host: alto.example.com 1700 Accept: text/plain,application/alto-error+json 1701 Content-Type: application/alto-updatestreamparams+json 1702 Content-Length: ### 1704 { 1705 "remove": [ ] 1706 } 1708 HTTP/1.1 204 No Content 1709 Content-Length: 0 1711 (stream closed without sending data content) 1713 The update stream server sends a final control update message on the 1714 original request stream to inform the ALTO client that all updates 1715 are stopped and then closes the stream: 1717 event: application/alto-updatestreamcontrol+json 1718 data: { 1719 data: "stopped": ["net", "routing"] 1720 data: } 1722 (server closes stream) 1724 9.4. Example: Endpoint Property Updates 1726 As another example, here is how an ALTO client can request updates 1727 for the property "priv:ietf-bandwidth" for one set of endpoints and 1728 "priv:ietf-load" for another. The update stream server immediately 1729 sends full replacements with the property values for all endpoints. 1730 After that, the update stream server sends data update messages for 1731 the individual endpoints as their property values change. 1733 POST /updates/properties HTTP/1.1 1734 Host: alto.example.com 1735 Accept: text/event-stream 1736 Content-Type: application/alto-updatestreamparams+json 1737 Content-Length: ### 1739 { "add": { 1740 "props-1": { 1741 "resource-id": "my-props", 1742 "input": { 1743 "properties" : [ "priv:ietf-bandwidth" ], 1744 "endpoints" : [ 1745 "ipv4:198.51.100.1", 1746 "ipv4:198.51.100.2", 1747 "ipv4:198.51.100.3" 1748 ] 1749 } 1750 }, 1751 "props-2": { 1752 "resource-id": "my-props", 1753 "input": { 1754 "properties" : [ "priv:ietf-load" ], 1755 "endpoints" : [ 1756 "ipv6:2001:db8:100::1", 1757 "ipv6:2001:db8:100::2", 1758 "ipv6:2001:db8:100::3", 1759 ] 1760 } 1761 }, 1762 } 1763 } 1764 HTTP/1.1 200 OK 1765 Connection: keep-alive 1766 Content-Type: text/event-stream 1768 event: application/alto-updatestreamcontrol+json 1769 data: {"control-uri": 1770 data: "http://alto.example.com/updates/streams/1414213562373"} 1772 event: application/alto-endpointprops+json,props-1 1773 data: { "endpoint-properties": { 1774 data: "ipv4:198.51.100.1" : { "priv:ietf-bandwidth": "13" }, 1775 data: "ipv4:198.51.100.2" : { "priv:ietf-bandwidth": "42" }, 1776 data: "ipv4:198.51.100.3" : { "priv:ietf-bandwidth": "27" } 1777 data: } } 1779 event: application/alto-endpointprops+json,props-2 1780 data: { "endpoint-properties": { 1781 data: "ipv6:2001:db8:100::1" : { "priv:ietf-load": "8" }, 1782 data: "ipv6:2001:db8:100::2" : { "priv:ietf-load": "2" }, 1783 data: "ipv6:2001:db8:100::3" : { "priv:ietf-load": "9" } 1784 data: } } 1786 (pause) 1788 event: application/merge-patch+json,props-1 1789 data: { "endpoint-properties": 1790 data: {"ipv4:198.51.100.1" : {"priv:ietf-bandwidth": "3"}} 1791 data: } 1793 (pause) 1795 event: application/merge-patch+json,props-2 1796 data: { "endpoint-properties": 1797 data: {"ipv6:2001:db8:100::3" : {"priv:ietf-load": "7"}} 1798 data: } 1800 If the ALTO client needs the "bandwidth" property for additional 1801 endpoints, the ALTO client can send an "add" request on the stream 1802 control URI: 1804 POST /updates/streams/1414213562373" HTTP/1.1 1805 Host: alto.example.com 1806 Accept: text/plain,application/alto-error+json 1807 Content-Type: application/alto-updatestreamparams+json 1808 Content-Length: ### 1810 { "add": { 1811 "props-3": { 1812 "resource-id": "my-props", 1813 "input": { 1814 "properties" : [ "priv:ietf-bandwidth" ], 1815 "endpoints" : [ 1816 "ipv4:198.51.100.4", 1817 "ipv4:198.51.100.5", 1818 ] 1819 } 1820 }, 1821 "props-4": { 1822 "resource-id": "my-props", 1823 "input": { 1824 "properties" : [ "priv:ietf-load" ], 1825 "endpoints" : [ 1826 "ipv6:2001:db8:100::4", 1827 "ipv6:2001:db8:100::5", 1828 ] 1829 } 1830 }, 1831 } 1832 } 1834 HTTP/1.1 204 No Content 1835 Content-Length: 0 1837 (stream closed without sending data content) 1839 The update stream server sends full replacements for the two new 1840 resources, followed by incremental changes for all four requests as 1841 they arrive: 1843 event: application/alto-endpointprops+json,props-3 1844 data: { "endpoint-properties": { 1845 data: "ipv4:198.51.100.4" : { "priv:ietf-bandwidth": "25" }, 1846 data: "ipv4:198.51.100.5" : { "priv:ietf-bandwidth": "31" }, 1847 data: } } 1849 event: application/alto-endpointprops+json,props-4 1850 data: { "endpoint-properties": { 1851 data: "ipv6:2001:db8:100::4" : { "priv:ietf-load": "6" }, 1852 data: "ipv6:2001:db8:100::5" : { "priv:ietf-load": "4" }, 1853 data: } } 1855 (pause) 1857 event: application/merge-patch+json,props-3 1858 data: { "endpoint-properties": 1859 data: {"ipv4:198.51.100.5" : {"priv:ietf-bandwidth": "15"}} 1860 data: } 1862 (pause) 1864 event: application/merge-patch+json,props-2 1865 data: { "endpoint-properties": 1866 data: {"ipv6:2001:db8:100::2" : {"priv:ietf-load": "9"}} 1867 data: } 1869 (pause) 1871 event: application/merge-patch+json,props-4 1872 data: { "endpoint-properties": 1873 data: {"ipv6:2001:db8:100::4" : {"priv:ietf-load": "3"}} 1874 data: } 1876 9.5. Example: Multipart Message Updates 1878 This example shows how an ALTO client can request a non-standard ALTO 1879 service returning a multipart response. The update stream server 1880 immediately sends full replacements of the multipart response. After 1881 that, the update stream server sends data update messages for the 1882 individual parts of the response as the ALTO data (object) in each 1883 part changes. 1885 POST /updates/pv HTTP/1.1 1886 Host: alto.example.com 1887 Accept: text/event-stream 1888 Content-Type: application/alto-updatestreamparams+json 1889 Content-Length: ### 1891 { 1892 "add": { 1893 "ecspvsub1": { 1894 "resource-id": "endpoint-cost-pv", 1895 "input": { ... input of an endpoit cost ... } 1896 } 1897 } 1898 } 1900 HTTP/1.1 200 OK 1901 Connection: keep-alive 1902 Content-Type: text/event-stream 1904 event: application/alto-updatestreamcontrol+json 1905 data: {"control-uri": "http://alto.example.com/updates/streams/1414"} 1907 event: multipart/related;boundary=example-pv; 1908 type=application/alto-endpointcost+json,ecspvsub1 1909 data: --example-pv 1910 data: Content-ID: ecsmap 1911 data: Content-Type: application/alto-endpointcost+json 1912 data: 1913 data: { ... data (object) of an endpoint cost map ... } 1914 data: --example-pv 1915 data: Content-ID: propmap 1916 data: Content-Type: application/alto-propmap+json 1917 data: 1918 data: { ... data (object) of a property map ... } 1919 data: --example-pv-- 1921 (pause) 1923 event: application/merge-patch+json,ecspvsub1.ecsmap 1924 data: { ... merge patch for updates of ecspvsub1.ecsmap ... } 1926 event: application/merge-patch+json,ecspvsub1.propmap 1927 data: { ... merge patch for updates of ecspvsub1.propmap ... } 1929 10. Operation and Processing Considerations 1931 10.1. Considerations for Choosing Data Update Messages 1933 The choice on data update messages depends on both how frequently the 1934 resources will change, and how extensive those changes will be. For 1935 stable resources with minor changes, the update stream server may 1936 choose to send incremental changes; for resources that frequently 1937 change, the update stream server may choose to send a full 1938 replacement after a while. Whether to send full replacement or 1939 incremental change depends on the update stream server. 1941 For incremental updates, this design allows both JSON patch and JSON 1942 merge patch for incremental changes. JSON merge patch is clearly 1943 superior to JSON patch for describing incremental changes to Cost 1944 Maps, Endpoint Costs, and Endpoint Properties. For these data 1945 structures, JSON merge patch is more space-efficient, as well as 1946 simpler to apply; we see no advantage to allowing a server to use 1947 JSON patch for those resources. 1949 The case is not as clear for incremental changes to network maps. 1951 First, consider small changes such as moving a prefix from one PID to 1952 another. JSON patch could encode that as a simple insertion and 1953 deletion, while JSON merge patch would have to replace the entire 1954 array of prefixes for both PIDs. On the other hand, to process a 1955 JSON patch update, the ALTO client would have to retain the indexes 1956 of the prefixes for each PID. Logically, the prefixes in a PID are 1957 an unordered set, not an array; aside from handling updates, a client 1958 has no need to retain the array indexes of the prefixes. Hence to 1959 take advantage of JSON patch for network maps, ALTO clients would 1960 have to retain additional, otherwise unnecessary, data. 1962 Second, consider more involved changes such as removing half of the 1963 prefixes from a PID. JSON merge patch would send a new array for 1964 that PID, while JSON patch would have to send a list of remove 1965 operations and delete the prefix one by one. 1967 Therefore, each update stream server may decide on its own whether to 1968 use JSON merge patch or JSON patch according to the changes in 1969 network maps. 1971 Other JSON-based incremental change formats may be introduced in the 1972 future. 1974 10.2. Considerations for Client Processing Data Update Messages 1976 In general, when an ALTO client receives a full replacement for a 1977 resource, the ALTO client should replace the current version with the 1978 new version. When an ALTO client receives an incremental change for 1979 a resource, the ALTO client should apply those patches to the current 1980 version of the resource. 1982 However, because resources can depend on other resources (e.g., cost 1983 maps depend on network maps), an ALTO client MUST NOT use a dependent 1984 resource if the resource on which it depends has changed. There are 1985 at least two ways an ALTO client can do that. We will illustrate 1986 these techniques by referring to network and cost map messages, 1987 although these techniques apply to any dependent resources. 1989 Note that when a network map changes, the update stream server MUST 1990 send the network map update message before sending the updates for 1991 the dependent cost maps (see Section 7.7.1). 1993 One approach is for the ALTO client to save the network map update 1994 message in a buffer and continue to use the previous network map, and 1995 the associated cost maps, until the ALTO client receives the update 1996 messages for all dependent cost maps. The ALTO client then applies 1997 all network and cost map updates atomically. 1999 Alternatively, the ALTO client MAY update the network map 2000 immediately. In this case, the ALTO client MUST mark each dependent 2001 cost map as temporarily invalid and MUST NOT use that map until the 2002 ALTO client receives a cost map update message with the new network 2003 map version tag. Note that the ALTO client MUST NOT delete the cost 2004 maps, because the update stream server may send incremental changes. 2006 The update stream server SHOULD send updates for dependent resources 2007 in a timely fashion. However, if the ALTO client does not receive 2008 the expected updates, the ALTO client MUST close the update stream 2009 connection, discard the dependent resources, and reestablish the 2010 update stream. The ALTO client MAY retain the version tag of the 2011 last version of any tagged resources and give those version tags when 2012 requesting the new update stream. In this case, if a version is 2013 still current, the update stream server will not re-send that 2014 resource. 2016 Although not as efficient as possible, this recovery method is simple 2017 and reliable. 2019 10.3. Considerations for Updates to Filtered Cost Maps 2021 If an update stream provides updates to a Filtered cost map which 2022 allows constraint tests, then an ALTO client MAY request updates to a 2023 Filtered cost map request with a constraint test. In this case, when 2024 a cost changes, the update stream server MUST send an update if the 2025 new value satisfies the test. If the new value does not, whether the 2026 update stream server sends an update depends on whether the previous 2027 value satisfied the test. If it did not, the update stream server 2028 SHOULD NOT send an update to the ALTO client. But if the previous 2029 value did, then the update stream server MUST send an update with a 2030 "null" value, to inform the ALTO client that this cost no longer 2031 satisfies the criteria. 2033 An update stream server can avoid such issues by offering update 2034 streams only for filtered cost maps which do not allow constraint 2035 tests. 2037 10.4. Considerations for Updates to Ordinal Mode Costs 2039 For an ordinal mode cost map, a change to a single cost point may 2040 require updating many other costs. As an extreme example, suppose 2041 the lowest cost changes to the highest cost. For a numerical mode 2042 cost map, only that one cost changes. But for an ordinal mode cost 2043 map, every cost might change. While this document allows an update 2044 stream server to offer incremental updates for ordinal mode cost 2045 maps, update stream server implementors should be aware that 2046 incremental updates for ordinal costs are more complicated than for 2047 numerical costs, and ALTO clients should be aware that small changes 2048 may result in large updates. 2050 An update stream server can avoid this complication by only offering 2051 full replacements for ordinal cost maps. 2053 10.5. Considerations for SSE Text Formatting and Processing 2055 SSE was designed for events that consist of relatively small amounts 2056 of line-oriented text data, and SSE clients frequently read input one 2057 line-at-a-time. However, an update stream sends a full cost map as a 2058 single events, and a cost map may involve megabytes, if not tens of 2059 megabytes, of text. This has implications that the ALTO client and 2060 the update stream server may consider. 2062 First, some SSE client libraries read all data for an event into 2063 memory, and then present it to the client as a character array. 2064 However, a client may not have enough memory to hold the entire JSON 2065 text for a large cost map. Hence an ALTO client SHOULD consider 2066 using an SSE library which presents the event data in manageable 2067 chunks, so the ALTO client can parse the cost map incrementally and 2068 store the underlying data in a more compact format. 2070 Second, an SSE client library may use a low level, generic socket 2071 read library that stores each line of an event data, just in case the 2072 higher level parser may need the line delimiters as part of the 2073 protocol formatting. A server sending a complete cost map as a 2074 single line may then generate a multi-megabyte data "line", and such 2075 a long line may then require complex memory management at the client. 2076 It is RECOMMENDED that an update stream server limit the lengths of 2077 data lines. 2079 11. Security Considerations 2081 As an extension of the base ALTO protocol [RFC7285], this document 2082 fits into the architecture of the base protocol, and hence the 2083 Security Considerations (Section 15) of the base protocol fully apply 2084 when this extension is provided by an ALTO server. For example, the 2085 same authenticity and integrity considerations (Section 15.1 of 2086 [RFC7285]) still fully apply; the same considerations for the privacy 2087 of ALTO users (Section 15.4 of [RFC7285]) also still fully apply. 2089 The addition of update streams and stream control can introduce 2090 additional risks which we discuss below. 2092 11.1. Update Stream Server: Denial-of-Service Attacks 2094 Allowing persistent update stream connections enables a new class of 2095 Denial-of-Service attacks. 2097 For the update stream server, an ALTO client might create an 2098 unreasonable number of update stream connections, or add an 2099 unreasonable number of substream-ids to one update stream. 2101 To avoid these attacks on the update stream server, the server MAY 2102 choose to limit the number of active streams and reject new requests 2103 when that threshold is reached. An update stream server MAY also 2104 choose to limit the number of active substream-ids on any given 2105 stream, or limit the total number of substream-ids used over the 2106 lifetime of a stream, and reject any stream control request which 2107 would exceed those limits. In these cases, the update stream server 2108 SHOULD return the HTTP status "503 Service Unavailable". 2110 While the preceding techniques prevent update stream DoS attacks from 2111 disrupting an update stream server's other services, it does make it 2112 easier for a DoS attack to disrupt the update stream service. 2113 Therefore an update stream server may prefer to restrict update 2114 stream services to authorized clients, as discussed in Section 15 of 2115 [RFC7285]. 2117 Alternatively, an update stream server MAY return the HTTP status 2118 "307 Temporary Redirect" to redirect the client to another ALTO 2119 server which can better handle a large number of update streams. 2121 11.2. ALTO Client: Update Overloading or Instability 2123 The availability of continuous updates can also cause overload for an 2124 ALTO client, in particular an ALTO client with limited processing 2125 capabilities. The current design does not include any flow control 2126 mechanisms for the client to reduce the update rates from the server. 2127 Under overloading, the client may choose to remove the information 2128 resources with high update rates. 2130 Also, under overloading, the client may no longer be able to detect 2131 whether an information is still fresh or has become stale. In such a 2132 case, the client should be careful in how it uses the information to 2133 avoid stability or efficiency issues. 2135 11.3. Stream Control: Spoofed Control Requests 2137 An outside party which can read the update stream response, or which 2138 can observe stream control requests, can obtain the control URI and 2139 use that to send a fraudulent "remove" requests, thus disabling 2140 updates for the valid ALTO client. This can be avoided by encrypting 2141 the update stream and stream control requests (see Section 15 of 2142 [RFC7285]). Also, the update stream server echoes the "remove" 2143 requests on the update stream, so the valid ALTO client can detect 2144 unauthorized requests. 2146 12. Requirements on Future ALTO Services to Use this Design 2148 Although this design is quite flexible, it has underlying 2149 requirements. 2151 The key requirements are that (1) each data update message is for a 2152 single resource; (2) an incremental change can be applied only to a 2153 resource that is a single JSON object, as both JSON merge patch and 2154 JSON patch can apply only to a single JSON object. Hence, if a 2155 future ALTO resource can contain multiple objects, then either each 2156 individual object also has a resource-id or an extension to this 2157 design is made. 2159 At the low level encoding level, new line in SSE has its own 2160 semantics. Hence, this design requires that resource encoding does 2161 not include new lines that can confuse with SSE encoding. In 2162 particular, the data update message MUST NOT include "event: " or 2163 "data: " at a new line as part of data message. 2165 If an update stream provides updates to a filtered cost map that 2166 allows constraint tests, the requirements for such services are 2167 stated in Section 10.3. 2169 13. IANA Considerations 2171 This document defines two new media-types, "application/alto- 2172 updatestreamparams+json", as described in Section 7.3, and 2173 "application/alto-updatestreamcontrol+json", as described in 2174 Section 6.3. All other media-types used in this document have 2175 already been registered, either for ALTO, JSON merge patch, or JSON 2176 patch. 2178 Type name: application 2180 Subtype name: alto-updatestreamparams+json 2182 Required parameters: n/a 2184 Optional parameters: n/a 2186 Encoding considerations: Encoding considerations are identical to 2187 those specified for the "application/json" media type. See 2188 [RFC7159]. 2190 Security considerations: Security considerations relating to the 2191 generation and consumption of ALTO Protocol messages are discussed 2192 in Section 11 of this document and Section 15 of [RFC7285]. 2194 Interoperability considerations: This document specifies format of 2195 conforming messages and the interpretation thereof. 2197 Published specification: Section 7.3 of this document. 2199 Applications that use this media type: ALTO servers and ALTO clients 2200 either stand alone or are embedded within other applications. 2202 Additional information: 2204 Magic number(s): n/a 2206 File extension(s): This document uses the mime type to refer to 2207 protocol messages and thus does not require a file extension. 2209 Macintosh file type code(s): n/a 2211 Person & email address to contact for further information: See 2212 Authors' Addresses section. 2214 Intended usage: COMMON 2216 Restrictions on usage: n/a 2218 Author: See Authors' Addresses section. 2220 Change controller: Internet Engineering Task Force 2221 (mailto:iesg@ietf.org). 2223 Type name: application 2225 Subtype name: alto-updatestreamcontrol+json 2227 Required parameters: n/a 2229 Optional parameters: n/a 2231 Encoding considerations: Encoding considerations are identical to 2232 those specified for the "application/json" media type. See 2233 [RFC7159]. 2235 Security considerations: Security considerations relating to the 2236 generation and consumption of ALTO Protocol messages are discussed 2237 in Section 11 of this document and Section 15 of [RFC7285]. 2239 Interoperability considerations: This document specifies format of 2240 conforming messages and the interpretation thereof. 2242 Published specification: Section 6.3 of this document. 2244 Applications that use this media type: ALTO servers and ALTO clients 2245 either stand alone or are embedded within other applications. 2247 Additional information: 2249 Magic number(s): n/a 2251 File extension(s): This document uses the mime type to refer to 2252 protocol messages and thus does not require a file extension. 2254 Macintosh file type code(s): n/a 2256 Person & email address to contact for further information: See 2257 Authors' Addresses section. 2259 Intended usage: COMMON 2261 Restrictions on usage: n/a 2263 Author: See Authors' Addresses section. 2265 Change controller: Internet Engineering Task Force 2266 (mailto:iesg@ietf.org). 2268 14. Alternative Designs Not Supported 2270 14.1. Why Not HTTP/2 Server-Push 2272 HTTP/2 ([RFC7540]) provides a Server Push facility. Although the 2273 name implies that it might be useful for sending asynchronous updates 2274 from the update stream server to the client, in reality Server Push 2275 is not well suited for that task. To see why it is not, here is a 2276 quick summary of HTTP/2. 2278 HTTP/2 allows an client and a server to multiplex many HTTP requests 2279 and responses over a single TCP connection. The requests and 2280 responses can be interleaved on a block by block basis, avoiding the 2281 head-of-line blocking problem encountered with the Keep-Alive 2282 mechanism in HTTP/1.1. Server Push allows a server to send a 2283 resource (an image, a CSS file, a javascript file, etc.) to the 2284 client before the client explicitly requests it. A server can only 2285 push cacheable GET-mode resources. By pushing a resource, the server 2286 implicitly tells the client, "Add this resource to your cache, 2287 because a resource you have requested needs it." 2289 One approach for using Server Push for updates is for the update 2290 stream server to send each data update message as a separate Server 2291 Push item and let the client apply those updates as they arrive. 2292 Unfortunately, there are several problems with that approach. 2294 First, HTTP/2 does not guarantee that pushed resources are delivered 2295 to the client in the order they were sent by the client, so each data 2296 update message would need a sequence number, and the client would 2297 have to re-sequence them. 2299 Second, an HTTP/2-aware client library will not necessarily inform a 2300 client application when the server pushes a resource. Instead, the 2301 library might cache the pushed resource, and only deliver it to the 2302 client when the client explicitly requests that URI. 2304 But the third problem is the most significant: Server Push is 2305 optional and can be disabled by any proxy between the client and the 2306 server. This is not a problem for the intended use of Server Push: 2308 eventually the client will request those resources, so disabling 2309 Server Push just adds a delay. But this means that Server Push is 2310 not suitable for resources which the client does not know to request. 2312 Thus we do not believe HTTP/2 Server Push is suitable for delivering 2313 asynchronous updates. Hence we have chosen to base ALTO updates on 2314 HTTP/1.1 and SSE. 2316 14.2. Why Not Allowing Stream Restart 2318 If an update stream is closed accidentally, when the ALTO client 2319 reconnects, the update stream server must resend the full maps. This 2320 is clearly inefficient. To avoid that inefficiency, the SSE 2321 specification allows an update stream server to assign an id to each 2322 event. When an ALTO client reconnects, the ALTO client can present 2323 the id of the last successfully received event, and the update stream 2324 server restarts with the next event. 2326 However, that mechanism adds additional complexity. The update 2327 stream server must save SSE messages in a buffer, in case ALTO 2328 clients reconnect. But that mechanism will never be perfect: if the 2329 ALTO client waits too long to reconnect, or if the ALTO client sends 2330 an invalid id, then the update stream server will have to resend the 2331 complete maps anyway. 2333 Furthermore, this is unlikely to be a problem in practice. ALTO 2334 clients who want continuous updates for large resources, such as full 2335 Network and cost maps, are likely to be things like P2P trackers. 2336 These ALTO clients will be well connected to the network; they will 2337 rarely drop connections. 2339 Mobile devices certainly can and do drop connections and will have to 2340 reconnect. But mobile devices will not need continuous updates for 2341 multi-megabyte cost maps. If mobile devices need continuous updates 2342 at all, they will need them for small queries, such as the costs from 2343 a small set of media servers from which the device can stream the 2344 currently playing movie. If the mobile device drops the connection 2345 and reestablishes the update stream, the update stream server will 2346 have to retransmit only a small amount of redundant data. 2348 In short, using event ids to avoid resending the full map adds a 2349 considerable amount of complexity to avoid a situation which we 2350 expect is very rare. We believe that complexity is not worth the 2351 benefit. 2353 The Update Stream service does allow the ALTO client to specify the 2354 tag of the last received version of any tagged resource, and if that 2355 is still current, the update stream server need not retransmit the 2356 full resource. Hence ALTO clients can use this to avoid 2357 retransmitting full network maps. cost maps are not tagged, so this 2358 will not work for them. Of course, the ALTO protocol could be 2359 extended by adding version tags to cost maps, which would solve the 2360 retransmission-on-reconnect problem. However, adding tags to cost 2361 maps might add a new set of complications. 2363 15. Acknowledgments 2365 Thank you to Dawn Chen (Tongji University), Shawn Lin (Tongji 2366 University) and Xiao Shi (Yale University) for their contributions to 2367 an earlier version of this document. 2369 16. Contributors 2371 Section 3, Section 6 and Section 9 of this document are based on 2372 contributions from Jingxuan Jensen Zhang. 2374 17. References 2376 [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate 2377 Requirement Levels", RFC 2119, BCP 14, March 1997. 2379 [RFC2387] Levinson, E., "The MIME Multipart/Related Content-type", 2380 RFC 2387, BCP 14, August 1998. 2382 [RFC4960] Stewart, R., "Stream Control Transmission Protocol", 2383 RFC 4960, September 2007. 2385 [RFC5789] Dusseault, L. and J. Snell, "PATCH Method for HTTP", 2386 RFC 5789, March 2010. 2388 [RFC6838] Freed, N., Klensin, J., and T. Hansen, "Media Type 2389 Specifications and Registration Procedures", RFC 6838, 2390 January 2013. 2392 [RFC6902] Bryan, P. and M. Nottingham, "JavaScript Object Notation 2393 (JSON) Patch", RFC 6902, April 2013. 2395 [RFC7159] Bray, T., "The JavaScript Object Notation (JSON) Data 2396 Interchange Format", RFC 7159, March 2014. 2398 [RFC7230] Fielding, R. and J. Reschke, "Hypertext Transfer Protocol 2399 (HTTP/1.1): Message Syntax and Routing", RFC 7230, June 2400 2014. 2402 [RFC7231] Fielding, R. and J. Reschke, "Hypertext Transfer Protocol 2403 (HTTP/1.1): Semantics and Content", RFC 7231, June 2014. 2405 [RFC7285] Almi, R., Penno, R., Yang, Y., Kiesel, S., Previdi, S., 2406 Roome, W., Shalunov, S., and R. Woundy, "Application-Layer 2407 Traffic Optimization (ALTO) Protocol", RFC 7285, September 2408 2014. 2410 [RFC7396] Hoffman, P. and J. Snell, "JSON Merge Patch", RFC 7396, 2411 October 2014. 2413 [RFC7540] Belshe, M., Peon, R., and M. Thomson, "Hypertext Transfer 2414 Protocol Version 2 (HTTP/2)", RFC 7540, May 2015. 2416 [SSE] Hickson, I., "Server-Sent Events (W3C)", W3C 2417 Recommendation 03 February 2015, February 2015. 2419 Authors' Addresses 2421 Wendy Roome 2422 Nokia Bell Labs (Retired) 2423 124 Burlington Rd 2424 Murray Hill, NJ 07974 2425 USA 2427 Phone: +1-908-464-6975 2428 Email: wendy@wdroome.com 2430 Y. Richard Yang 2431 Yale University 2432 51 Prospect St 2433 New Haven CT 2434 USA 2436 Email: yry@cs.yale.edu