idnits 2.17.1 draft-ietf-alto-incr-update-sse-13.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 833 has weird spacing: '...atesReq add;...' -- The exact meaning of the all-uppercase expression 'MAY NOT' is not defined in RFC 2119. If it is intended as a requirements expression, it should be rewritten using one of the combinations defined in RFC 2119; otherwise it should not be all-uppercase. == The expression 'MAY NOT', while looking like RFC 2119 requirements text, is not defined in RFC 2119, and should not be used. Consider using 'MUST NOT' instead (if that is what you mean). Found 'MAY NOT' in this paragraph: Note that media-type names may not contain a comma (character code 0x2c). [Dawn: may not or MAY NOT] -- The document date (July 23, 2018) is 2103 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 374, but not defined == Missing Reference: 'TBD' is mentioned on line 1547, but not defined ** Obsolete normative reference: RFC 7159 (Obsoleted by RFC 8259) ** Obsolete normative reference: RFC 7230 (Obsoleted by RFC 9110, RFC 9112) ** Obsolete normative reference: RFC 7231 (Obsoleted by RFC 9110) ** Obsolete normative reference: RFC 7540 (Obsoleted by RFC 9113) -- Possible downref: Non-RFC (?) normative reference: ref. 'SSE' Summary: 6 errors (**), 0 flaws (~~), 5 warnings (==), 4 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: January 24, 2019 Tongji/Yale University 6 S. Chen 7 Tongji University 8 July 23, 2018 10 ALTO Incremental Updates Using Server-Sent Events (SSE) 11 draft-ietf-alto-incr-update-sse-13 13 Abstract 15 The Application-Layer Traffic Optimization (ALTO) [RFC7285] protocol 16 provides network related information, called network information 17 resources, to client applications so that clients can make informed 18 decisions in utilizing network resources. For example, an ALTO 19 server can provide network and cost maps so that an ALTO client can 20 use the maps to determine the costs between endpoints when choosing 21 communicating endpoints. 23 However, the ALTO protocol does not define a mechanism to allow an 24 ALTO client to obtain updates to the information resources, other 25 than by periodically re-fetching them. Because some information 26 resources (e.g., the aforementioned maps) may be large (potentially 27 tens of megabytes), and because only parts of the information 28 resources may change frequently (e.g., only some entries in a cost 29 map), complete re-fetching can be extremely inefficient. 31 This document presents a mechanism to allow an ALTO server to push 32 updates to ALTO clients, to achieve two benefits: (1) Updates can be 33 immediate, in that the ALTO server can send updates as soon as they 34 are available; and (2) updates can be incremental, in that if only a 35 small section of an information resource changes, the ALTO server can 36 send just the changes. 38 Requirements Language 40 The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", 41 "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this 42 document are to be interpreted as described in RFC 2119 [RFC2119]. 44 Status of This Memo 46 This Internet-Draft is submitted in full conformance with the 47 provisions of BCP 78 and BCP 79. 49 Internet-Drafts are working documents of the Internet Engineering 50 Task Force (IETF). Note that other groups may also distribute 51 working documents as Internet-Drafts. The list of current Internet- 52 Drafts is at http://datatracker.ietf.org/drafts/current/. 54 Internet-Drafts are draft documents valid for a maximum of six months 55 and may be updated, replaced, or obsoleted by other documents at any 56 time. It is inappropriate to use Internet-Drafts as reference 57 material or to cite them other than as "work in progress." 59 This Internet-Draft will expire on January 24, 2019. 61 Copyright Notice 63 Copyright (c) 2018 IETF Trust and the persons identified as the 64 document authors. All rights reserved. 66 This document is subject to BCP 78 and the IETF Trust's Legal 67 Provisions Relating to IETF Documents 68 (http://trustee.ietf.org/license-info) in effect on the date of 69 publication of this document. Please review these documents 70 carefully, as they describe your rights and restrictions with respect 71 to this document. Code Components extracted from this document must 72 include Simplified BSD License text as described in Section 4.e of 73 the Trust Legal Provisions and are provided without warranty as 74 described in the Simplified BSD License. 76 Table of Contents 78 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3 79 2. Major Changes Since Version -01 . . . . . . . . . . . . . . . 5 80 3. Terms . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 81 4. Background . . . . . . . . . . . . . . . . . . . . . . . . . 6 82 4.1. Server-Sent Events (SSEs) . . . . . . . . . . . . . . . . 6 83 4.2. JSON Merge Patch . . . . . . . . . . . . . . . . . . . . 7 84 4.2.1. JSON Merge Patch Encoding . . . . . . . . . . . . . . 8 85 4.2.2. JSON Merge Patch ALTO Messages . . . . . . . . . . . 9 86 4.3. JSON Patch . . . . . . . . . . . . . . . . . . . . . . . 12 87 4.3.1. JSON Patch Encoding . . . . . . . . . . . . . . . . . 13 88 4.3.2. JSON Patch ALTO Messages . . . . . . . . . . . . . . 13 89 5. Overview of Approach . . . . . . . . . . . . . . . . . . . . 15 90 6. Update Messages: Data Update and Control Update Messages . . 17 91 6.1. ALTO Update Message Format . . . . . . . . . . . . . . . 17 92 6.2. ALTO Data Update Message . . . . . . . . . . . . . . . . 18 93 6.3. ALTO Control Update Message . . . . . . . . . . . . . . . 18 94 7. Update Stream Service . . . . . . . . . . . . . . . . . . . . 19 95 7.1. Media Type . . . . . . . . . . . . . . . . . . . . . . . 19 96 7.2. HTTP Method . . . . . . . . . . . . . . . . . . . . . . . 20 97 7.3. Accept Input Parameters . . . . . . . . . . . . . . . . . 20 98 7.4. Capabilities . . . . . . . . . . . . . . . . . . . . . . 21 99 7.5. Uses . . . . . . . . . . . . . . . . . . . . . . . . . . 22 100 7.6. Response . . . . . . . . . . . . . . . . . . . . . . . . 22 101 7.7. Additional Requirements on Update Messages . . . . . . . 24 102 7.7.1. Event Sequence Requirements . . . . . . . . . . . . . 24 103 7.7.2. Cross-Stream Consistency Requirements . . . . . . . . 24 104 7.8. Keep-Alive Messages . . . . . . . . . . . . . . . . . . . 25 105 8. Stream Control Service . . . . . . . . . . . . . . . . . . . 25 106 8.1. URI . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 107 8.2. Media Type . . . . . . . . . . . . . . . . . . . . . . . 26 108 8.3. HTTP Method . . . . . . . . . . . . . . . . . . . . . . . 26 109 8.4. Accept Input Parameters . . . . . . . . . . . . . . . . . 26 110 8.5. Capabilities & Uses . . . . . . . . . . . . . . . . . . . 27 111 8.6. Response . . . . . . . . . . . . . . . . . . . . . . . . 27 112 9. Examples . . . . . . . . . . . . . . . . . . . . . . . . . . 28 113 9.1. Example: IRD Announcing Update Stream Services . . . . . 28 114 9.2. Example: Simple Network and Cost Map Updates . . . . . . 30 115 9.3. Example: Advanced Network and Cost Map Updates . . . . . 33 116 9.4. Example: Endpoint Property Updates . . . . . . . . . . . 37 117 10. Client Actions When Receiving Update Messages . . . . . . . . 40 118 11. Design Decisions and Discussions . . . . . . . . . . . . . . 41 119 11.1. HTTP/2 Server-Push . . . . . . . . . . . . . . . . . . . 41 120 11.2. Not Allowing Stream Restart . . . . . . . . . . . . . . 42 121 11.3. Data Update Choices . . . . . . . . . . . . . . . . . . 43 122 11.3.1. Full Replacement or Incremental Change . . . . . . . 43 123 11.3.2. JSON Merge Patch or JSON Patch . . . . . . . . . . . 43 124 11.4. Requirements on Future ALTO Services to Use this Design 44 125 12. Miscellaneous Considerations . . . . . . . . . . . . . . . . 44 126 12.1. Considerations for Updates to Filtered Cost Maps . . . . 45 127 12.2. Considerations for Incremental Updates to Ordinal Mode 128 Costs . . . . . . . . . . . . . . . . . . . . . . . . . 45 129 12.3. Considerations Related to SSE Line Lengths . . . . . . . 45 130 13. Security Considerations . . . . . . . . . . . . . . . . . . . 46 131 13.1. Denial-of-Service Attacks . . . . . . . . . . . . . . . 46 132 13.2. Spoofed Control Requests . . . . . . . . . . . . . . . . 46 133 13.3. Privacy . . . . . . . . . . . . . . . . . . . . . . . . 47 134 14. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 47 135 15. Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . 49 136 16. References . . . . . . . . . . . . . . . . . . . . . . . . . 49 137 Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 50 139 1. Introduction 141 The Application-Layer Traffic Optimization (ALTO) [RFC7285] protocol 142 provides network related information called network information 143 resources to client applications so that clients may make informed 144 decisions in utilizing network resources. For example, an ALTO 145 server provides network and cost maps, where a network map partitions 146 the set of endpoints into a manageable number of sets each defined by 147 a Provider-Defined Identifier (PID), and a cost map provides directed 148 costs between PIDs. Given network and cost maps, an ALTO client can 149 obtain costs between endpoints by first using the network map to get 150 the PID for each endpoint, and then using the cost map to get the 151 costs between those PIDs. Such costs can be used by the client to 152 choose communicating endpoints with low network costs. 154 The ALTO protocol defines only an ALTO client pull model, without 155 defining a mechanism to allow an ALTO client to obtain updates to 156 network information resources, other than by periodically re-fetching 157 them. In settings where an information resource may be large but 158 only parts of it may change frequently (e.g., some entries of a cost 159 map), complete re-fetching can be inefficient. 161 This document presents a mechanism to allow an ALTO server to push 162 incremental updates to ALTO clients. Integrating server-push and 163 incremental updates provides two benefits: (1) Updates can be 164 immediate, in that the ALTO server can send updates as soon as they 165 are available; and (2) updates can be small, in that if only a small 166 section of an information resource changes, the ALTO server can send 167 just the changes. 169 While primarily intended to provide updates to GET-mode network and 170 cost maps, the mechanism defined in this document can also provide 171 updates to POST-mode ALTO services, such as the endpoint property and 172 endpoint cost services. We intend that the mechanism can also 173 support new ALTO services to be defined by future extensions, but a 174 future service needs to satisfy requirements specified in 175 Section 11.4. 177 The rest of this document is organized as follows. Section 4 gives 178 background on the basic techniques used in this design: (1) Server- 179 Sent Events to allow server push; (2) JSON merge patch and JSON patch 180 to allow incremental update. With the background, Section 5 gives a 181 non-normative overview of the design. Section 6 defines individual 182 messages in an update stream, and Section 7 defines the overall 183 update stream service. Section 8 defines the stream control service. 184 Section 9 gives several examples. Section 10 describes how an ALTO 185 client should handle incoming updates. Section 11 and Section 12 186 discusses the design decisions behind this update mechanism and other 187 considerations. The next two sections review the security and IANA 188 considerations. 190 2. Major Changes Since Version -01 192 To RFC editor: This will be removed in the final version. We keep 193 this section to make clear major changes in the technical content. 195 o Incremental encoding: Added JSON patch as an alternative 196 incremental delta encoding. 198 o Update concurrent requests of the same resource: The client now 199 assigns a unique client-id to each resource in an update stream. 200 The server puts the client-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 get updates to two 203 different requests with the same server resource-id; before, that 204 required two separate update streams. 206 o Control: Defined a new "stream control" resource (Section 8) to 207 allow clients to add or remove resources from a previously created 208 update stream. The ALTO server creates a new stream control 209 resource for each update stream instance, assigns a unique URI to 210 it, and sends the URI to the client as the first event in the 211 stream. 213 3. Terms 215 This document uses the following terms: Update Stream, Update 216 Message, Data Update Message, Full Replacement, Incremental Change, 217 Update Stream Server, Update Stream Control Service, Update Stream 218 Control, Control Update Message, Stream Control Service. 220 Update Stream: An update stream is an HTTP connection between an ALTO 221 client and an ALTO server so that the server can push a sequence of 222 update messages using SSE to the client. 224 Update Message: An update message is either a data update message or 225 a control update message. 227 Data Update Message: A data update message is for a single ALTO 228 information resource and sent from the update stream server to the 229 ALTO client when the resource changes. A data update message can be 230 either a full-replacement message or an incremental-change message. 231 Full replacement is a shorthand for a full-replacement message, and 232 incremental change is a shorthand for an incremental-change message. 234 Full Replacement: A full replacement for a resource encodes the 235 content of the resource in its original ALTO encoding. 237 Incremental Change: An incremental change specifies only the 238 difference between the new content and the previous version. An 239 incremental change can be encoded using either JSON merge patch or 240 JSON patch in this document. 242 Update Stream Server: An update stream server is an ALTO server that 243 provides update stream service. 245 Stream Control Service: An stream control service provides an HTTP 246 URI so that the ALTO client of an update stream can use it to request 247 the addition or removal of resources receiving update messages. 249 Stream Control: A shorthand for stream control service. 251 Control Update Message: A control update message of an update stream 252 is for the update stream server to notify the ALTO client of related 253 control information of the update stream. The first control update 254 message provides the URI using which the ALTO client can send stream 255 control requests to the stream control server. Additional control 256 update messages allow the update stream server to notify the ALTO 257 client of status changes (e.g., the server will no longer send 258 updates for an information resource). 260 Stream Contorl Server: An stream control server is an ALTO server 261 that receives the addition or removal requests from the ALTO client. 263 Note that the ALTO server mentioned in this document refers to a 264 general sever that provides various kinds of services, it can be an 265 update stream server or stream control server, it can also be a 266 server providing ALTO IRD information. 268 4. Background 270 The design requires two basic techniques: server push and encoding of 271 incremental changes. Using existing techniques whenever possible, 272 this design uses Server-Sent Events (SSEs) for server push; JSON 273 merge patch and JSON patch to encode incremental changes. Below we 274 give a non-normative summary of these two techniques. 276 4.1. Server-Sent Events (SSEs) 278 The following is a non-normative summary of SSE; see [SSE] for its 279 normative definition. 281 Server-Sent Events enable a server to send new data to a client by 282 "server-push". The client establishes an HTTP ([RFC7230], [RFC7231]) 283 connection to the server and keeps the connection open. The server 284 continually sends messages. Each message has one or more lines, 285 where a line is terminated by a carriage-return immediately followed 286 by a new-line, a carriage-return not immediately followed by a new- 287 line, or a new-line not immediately preceded by a carriage-return. A 288 message is terminated by a blank line (two line terminators in a 289 row). 291 Each line in a message is of the form "field-name: string value". 292 Lines with a blank field-name (that is, lines which start with a 293 colon) are ignored, as are lines which do not have a colon. The 294 protocol defines three field names: event, id, and data. If a 295 message has more than one "data" line, the value of the data field is 296 the concatenation of the values on those lines. There can be only 297 one "event" and "id" line per message. The "data" field is required; 298 the others are optional. 300 Figure 1 is a sample SSE stream, starting with the client request. 301 The server sends three events and then closes the stream. 303 (Client request) 304 GET /stream HTTP/1.1 305 Host: example.com 306 Accept: text/event-stream 308 (Server response) 309 HTTP/1.1 200 OK 310 Connection: keep-alive 311 Content-Type: text/event-stream 313 event: start 314 id: 1 315 data: hello there 317 event: middle 318 id: 2 319 data: let's chat some more ... 320 data: and more and more and ... 322 event: end 323 id: 3 324 data: goodbye 326 Figure 1: A Sample SSE stream. 328 4.2. JSON Merge Patch 329 4.2.1. JSON Merge Patch Encoding 331 To avoid always sending complete data, a server needs mechanisms to 332 encode incremental changes. This design uses JSON merge patch as one 333 mechanism. Below is a non-normative summary of JSON merge patch; see 334 [RFC7396] for the normative definition. 336 JSON merge patch is intended to allow applications to update server 337 resources via the HTTP patch method [RFC5789]. This document adopts 338 the JSON merge patch message format to encode incremental changes, 339 but uses a different transport mechanism. 341 Informally, a JSON merge patch object is a JSON data structure that 342 defines how to transform one JSON value into another. Specifically, 343 JSON merge patch treats the two JSON values as trees of nested JSON 344 objects (dictionaries of name-value pairs), where the leaves are 345 values (e.g., JSON arrays, strings, numbers) other than JSON objects 346 and the path for each leaf is the sequence of keys leading to that 347 leaf. When the second tree has a different value for a leaf at a 348 path, or adds a new leaf, the JSON merge patch tree has a leaf, at 349 that path, with the new value. When a leaf in the first tree does 350 not exist in the second tree, the JSON merge patch tree has a leaf 351 with a JSON "null" value. The JSON merge patch tree does not have an 352 entry for any leaf that has the same value in both versions. 354 As a result, if all leaf values are simple scalars, JSON merge patch 355 is a quite efficient representation of incremental changes. It is 356 less efficient when leaf values are arrays, because JSON merge patch 357 replaces arrays in their entirety, even if only one entry changes. 359 Formally, the process of applying a JSON merge patch is defined by 360 the following recursive algorithm, as specified in [RFC7396]: 362 define MergePatch(Target, Patch) { 363 if Patch is an Object { 364 if Target is not an Object { 365 Target = {} # Ignore the contents and 366 # set it to an empty Object 367 } 368 for each Name/Value pair in Patch { 369 if Value is null { 370 if Name exists in Target { 371 remove the Name/Value pair from Target 372 } 373 } else { 374 Target[Name] = MergePatch(Target[Name], Value) 375 } 376 } 377 return Target 378 } else { 379 return Patch 380 } 381 } 383 Note that null as the value of a name/value pair will delete the 384 element with "name" in the original JSON value. 386 4.2.2. JSON Merge Patch ALTO Messages 388 Both as examples of JSON merge patch and as a demonstration of the 389 feasibility of applying JSON merge patch to ALTO, we look at the 390 application of JSON merge patch to two key ALTO messages. 392 4.2.2.1. JSON Merge Patch Network Map Messages 394 Section 11.2.1.6 of [RFC7285] defines the format of a network map 395 message. Assume a simple example ALTO message sending an initial 396 network map: 398 { 399 "meta" : { 400 "vtag": { 401 "resource-id" : "my-network-map", 402 "tag" : "da65eca2eb7a10ce8b059740b0b2e3f8eb1d4785" 403 } 404 }, 405 "network-map" : { 406 "PID1" : { 407 "ipv4" : [ "192.0.2.0/24", "198.51.100.0/25" ] 408 }, 409 "PID2" : { 410 "ipv4" : [ "198.51.100.128/25" ] 411 }, 412 "PID3" : { 413 "ipv4" : [ "0.0.0.0/0" ], 414 "ipv6" : [ "::/0" ] 415 } 416 } 417 } 419 Consider the following JSON merge patch update message, which (1) 420 adds an ipv4 prefix "193.51.100.0/25" and an ipv6 prefix 421 "2001:db8:8000::/33" to "PID1", (2) deletes "PID2", and (3) assigns a 422 new "tag" to the network map: 424 { 425 "meta" : { 426 "vtag" : { 427 "tag" : "a10ce8b059740b0b2e3f8eb1d4785acd42231bfe" 428 } 429 }, 430 "network-map": { 431 "PID1" : { 432 "ipv4" : [ "192.0.2.0/24", "198.51.100.0/25", 433 "193.51.100.0/25" ], 434 "ipv6" : [ "2001:db8:8000::/33" ] 435 }, 436 "PID2" : null 437 } 438 } 440 Applying the JSON merge patch update to the initial network map is 441 equivalent to the following ALTO network map: 443 { 444 "meta" : { 445 "vtag": { 446 "resource-id" : "my-network-map", 447 "tag" : "a10ce8b059740b0b2e3f8eb1d4785acd42231bfe" 448 } 449 }, 450 "network-map" : { 451 "PID1" : { 452 "ipv4" : [ "192.0.2.0/24", "198.51.100.0/25", 453 "193.51.100.0/25" ], 454 "ipv6" : [ "2001:db8:8000::/33" ] 455 }, 456 "PID3" : { 457 "ipv4" : [ "0.0.0.0/0" ], 458 "ipv6" : [ "::/0" ] 459 } 460 } 461 } 463 4.2.2.2. JSON Merge Patch Cost Map Messages 465 Section 11.2.3.6 of [RFC7285] defines the format of a cost map 466 message. Assume a simple example ALTO message for an initial cost 467 map: 469 { 470 "meta" : { 471 "dependent-vtags" : [ 472 {"resource-id": "my-network-map", 473 "tag": "a10ce8b059740b0b2e3f8eb1d4785acd42231bfe" 474 } 475 ], 476 "cost-type" : { 477 "cost-mode" : "numerical", 478 "cost-metric": "routingcost" 479 }, 480 "vtag": { 481 "resource-id" : "my-cost-map", 482 "tag" : "3ee2cb7e8d63d9fab71b9b34cbf764436315542e" 483 } 484 }, 485 "cost-map" : { 486 "PID1": { "PID1": 1, "PID2": 5, "PID3": 10 }, 487 "PID2": { "PID1": 5, "PID2": 1, "PID3": 15 }, 488 "PID3": { "PID1": 20, "PID2": 15 } 489 } 490 } 492 The following JSON merge patch message updates the example cost map 493 so that (1) the "tag" field of the cost map is updated, (2) the cost 494 of PID1->PID2 is 9 instead of 5, (3) the cost of PID3->PID1 is no 495 longer available, (4) the cost of PID3->PID3 is defined as 1. 497 { 498 "meta" : { 499 "vtag": { 500 "tag": "c0ce023b8678a7b9ec00324673b98e54656d1f6d" 501 } 502 } 503 "cost-map" : { 504 "PID1" : { "PID2" : 9 }, 505 "PID3" : { "PID1" : null, "PID3" : 1 } 506 } 507 } 509 Hence applying the JSON merge patch to the initial cost map is 510 equivalent to the following ALTO cost map: 512 { 513 "meta" : { 514 "dependent-vtags" : [ 515 {"resource-id": "my-network-map", 516 "tag": "a10ce8b059740b0b2e3f8eb1d4785acd42231bfe" 517 } 518 ], 519 "cost-type" : { 520 "cost-mode" : "numerical", 521 "cost-metric": "routingcost" 522 }, 523 "vtag": { 524 "resource-id": "my-cost-map", 525 "tag": "c0ce023b8678a7b9ec00324673b98e54656d1f6d" 526 } 527 }, 528 "cost-map" : { 529 "PID1": { "PID1": 1, "PID2": 9, "PID3": 10 }, 530 "PID2": { "PID1": 5, "PID2": 1, "PID3": 15 }, 531 "PID3": { "PID2": 15, "PID3": 1 } 532 } 533 } 535 4.3. JSON Patch 536 4.3.1. JSON Patch Encoding 538 One issue of JSON merge patch is that it does not handle array 539 changes well. In particular, JSON merge patch considers an array as 540 a single object and hence can only replace an array in its entirety. 541 When the change is to make a small change to an array such as the 542 deletion of an element from a large array, whole-array replacement is 543 inefficient. Consider the example in Section 4.2.2.1. To add a new 544 entry to the ipv4 array for PID1, the server needs to send a whole 545 new array. Another issue is that JSON merge patch cannot change a 546 value to be null, as the JSON merge patch processing algorithm 547 (MergePatch in Section 4.2.1) interprets a null as a removal 548 instruction. On the other hand, some ALTO resources can have null 549 values, and it is possible that the update will want to change the 550 new value to be null. 552 JSON patch [RFC6902] can address the preceding issues. It defines a 553 set of operators to modify a JSON object. Below is a non-normative 554 description of JSON patch; see [RFC6902] for the normative 555 definition. 557 4.3.2. JSON Patch ALTO Messages 559 Both as examples of JSON patch and as a demonstration of the 560 difference between JSON patch and JSON merge patch, we take a look at 561 the application of JSON patch to the same updates shown in 562 Section 4.2.2. 564 4.3.2.1. JSON Patch Network Map Messages 566 First consider the same update as in Section 4.2.2.1 for the network 567 map. Below is the encoding using JSON patch: 569 [ 570 { 571 "op": "replace", 572 "path": "/meta/vtag/tag", 573 "value": "a10ce8b059740b0b2e3f8eb1d4785acd42231bfe" 574 }, 575 { 576 "op": "add", 577 "path": "/network-map/PID1/ipv4/2", 578 "value": "193.51.100.0/25" 579 } 580 { 581 "op": "add", 582 "path": "/network-map/PID1/ipv6", 583 "value": ["2001:db8:8000::/33"] 584 }, 585 { 586 "op": "remove", 587 "path": "/network-map/PID2" 588 } 589 ] 591 4.3.2.2. JSON Patch Cost Map Messages 593 Compared with JSON merge patch, JSON patch does not encode cost map 594 updates efficiently. Consider the cost map update shown in 595 Section 4.2.2.2, the encoding using JSON patch is: 597 [ 598 { 599 "op": "replace", 600 "path": "/meta/vtag/tag", 601 "value": "c0ce023b8678a7b9ec00324673b98e54656d1f6d" 602 }, 603 { 604 "op": "replace", 605 "path": "/cost-map/PID1/PID2", 606 "value": 9 607 }, 608 { 609 "op": "remove", 610 "path": "/cost-map/PID3/PID1" 611 }, 612 { 613 "op": "replace", 614 "path": "/cost-map/PID3/PID3", 615 "value": 1 616 } 617 ] 619 5. Overview of Approach 621 With the preceding background, we now give a non-normative overview 622 of the update mechanism to be defined in later sections of this 623 document. 625 The building block of the update mechanism defined in this document 626 is the update stream service (defined in Section 7), where each 627 update stream service is a POST-mode service that provides update 628 streams. When an ALTO client requests an update stream service, the 629 ALTO client establishes a persistent connection to the update stream 630 server, creating an update stream. The update stream server uses the 631 update stream to continuously send a sequence of update messages 632 (defined in Section 6) to the ALTO client. An update stream can 633 provide updates to both GET-mode resources, such as ALTO network and 634 cost maps, and POST-mode resources, such as ALTO endpoint property 635 service. 637 An ALTO server may provide any number of update stream services, 638 where each update stream may provide updates for a given subset of 639 the ALTO server's resources. An ALTO server's Information Resource 640 Directory (IRD) defines the update stream services and declares the 641 set of resources for which each update stream service provides 642 updates. The ALTO server selects the resource set for each update 643 stream service. It is recommended that if a resource depends on one 644 or more other resource(s) (indicated with the "uses" attribute 645 defined in [RFC7285]), these other resource(s) should also be part of 646 that update stream. Thus the update stream for a cost map should 647 also provide updates for the network map on which that cost map 648 depends. 650 An ALTO client may request any number of update streams 651 simultaneously. Because each update stream consumes resources on the 652 update stream server, an update stream server may require client 653 authorization/authentication, limit the number of open update 654 streams, close inactive streams, or redirect an ALTO client to 655 another update stream server. 657 The key objective of an update stream is to update the ALTO client on 658 data value changes to ALTO resources. We refer to messages sending 659 such updates as data update messages. Although an update stream may 660 update one or more ALTO resources, each data update message updates 661 only one resource and is sent as a Server-Sent Event (SSE), as 662 defined by [SSE]. A data update message is encoded either as a full 663 replacement or as an incremental change. A full replacement uses the 664 JSON message format defined by the ALTO protocol. There can be 665 multiple encodings for incremental changes. The current design 666 supports incremental changes using JSON merge patch ([RFC7396]) or 667 JSON patch ([RFC6902]) to describe the changes of the resource. 668 Future documents may define additional mechanisms for incremental 669 changes. The update stream server decides when to send data update 670 messages, and whether to send full replacements or incremental 671 changes. These decisions can vary from resource to resource and from 672 update to update. 674 An update stream can run for a long time, and hence there can be 675 status changes at the update stream server side during the lifetime 676 of an update stream; for example, the update stream server may 677 encounter an error or need to shut down for maintenance. To support 678 robust, flexible protocol design, this design allows the update 679 stream server to send server state updates to the ALTO client as 680 well, showing as control update messages from the update stream 681 server to the ALTO client. 683 +-------+ +-------+ init request +-------+ 684 | | | | <---------- | | 685 add/remove | | | | | | 686 resource |Update | |Update | data update | | 687 ----------> |Stream | private |Stream | messages |Client | 688 |Control|<------->|Server | -----------> | | 689 <---------- |Server | | | | | 690 response | | | | -----------> | | 691 | | | | control update| | 692 +-------+ +-------+ messages +-------+ 694 Figure 2: ALTO SSE Overview 696 In addition to state changes triggered from the update stream server 697 side, in a flexible design, an ALTO client may initiate changes as 698 well, in particular, by adding or removing ALTO resources receiving 699 updates. An ALTO client initiates such changes using the stream 700 control service. For an update stream service supporting update 701 stream control, the update stream server responds by sending an event 702 (a control update message) with the URI of the stream control 703 service. The ALTO client can then use the URI to ask the update 704 stream server to (1) send data update messages for additional 705 resources, (2) stop sending data update messages for previously 706 requested resources, or (3) gracefully stop and close the update 707 stream altogether. 709 6. Update Messages: Data Update and Control Update Messages 711 We now define the details of ALTO incremental update. Specifically, 712 an update stream consists of a stream of data update messages 713 (Section 6.2) and control update messages (Section 6.3). 715 6.1. ALTO Update Message Format 717 Data update and control update messages have the same basic 718 structure. The data field is a JSON object, and the event field 719 contains the media type of the data field and an optional client-id. 720 Data update messages use the client-id to identify the ALTO resource 721 to which the update message applies. Client-ids MUST follow the 722 rules for ALTO ResourceIds (Section 10.2 of [RFC7285]). Client-ids 723 MUST be unique within an update stream, but need not be globally 724 unique. For example, if an ALTO client requests updates for both a 725 cost map and its dependent network map, the ALTO client might assign 726 client-id "1" to the network map and client-id "2" to the cost map. 727 Alternatively, the ALTO client could use the client-ids for those two 728 maps. 730 JSON specifications use the type ClientId for a client-id, and the 731 type ClientId conforms to the specification of ResourceId as defined 732 in Section 10.2 of [RFC7285]. 734 The two sub-fields (media-type and client-id) of the event field are 735 encoded as comma-separated strings: 737 media-type [ ',' client-id ] 739 Note that media-type names may not contain a comma (character code 740 0x2c). [Dawn: may not or MAY NOT] 742 Note that an update message does not use the SSE "id" field. 744 6.2. ALTO Data Update Message 746 A data update message is sent when a monitored resource changes. The 747 data is either a complete specification of the resource, or else a 748 patch (either JSON merge patch or JSON patch) describing the changes 749 from the last version. We will refer to these as full replacement 750 and incremental change, respectively. The encoding of full 751 replacement is defined by [RFC7285]; examples are network and cost 752 map messages. They have the media types defined in that document. 753 The encoding of JSON merge patch is defined by [RFC7396], with media 754 type "application/merge-patch+json"; the encoding of JSON patch is 755 defined by [RFC6902], with media type "application/json-patch+json". 757 Figure 3 shows some examples of ALTO data update messages: 759 event: application/alto-networkmap+json,1 760 data: { ... full network map message ... } 762 event: application/alto-costmap+json,2 763 data: { ... full cost map message ... } 765 event: application/merge-patch+json,2 766 data: { ... JSON merge patch update for the cost map ... } 768 Figure 3: Examples of ALTO data update messages. 770 6.3. ALTO Control Update Message 772 Control update messages have the media type "application/alto- 773 updatestreamcontrol+json", and the data is of type 774 UpdateStreamControlEvent: 776 object { 777 [String control-uri;] 778 [ClientId started<1..*>;] 779 [ClientId stopped<1..*>;] 780 [String description;] 781 } UpdateStreamControlEvent; 783 control-uri: the URI providing stream control for this update stream 784 (see Section 8). The server MUST send a control update message 785 with an URI as the first event in an update stream. If the URI 786 is NULL, the update stream server does not support stream 787 control for this update stream; otherwise, the update stream 788 server provides stream control through the given URI. 790 started: a list of client-ids of resources. It notifies the ALTO 791 client that the update stream server will start sending data 792 update messages for each resource listed. 794 stopped: a list of client-ids of resources. It notifies the ALTO 795 client that the update stream server will no longer send data 796 update messages for the listed resources. There can be multiple 797 reasons for an update stream server to stop sending data update 798 messages for a resource, including a request from the ALTO 799 client using stream control (Section 7.7.1) or an internal 800 server event. 802 description: a non-normative text providing an explanation for the 803 control event. When an update stream server stops sending data 804 update messages for a resource, it is RECOMMENDED that the 805 update stream server provides a short reason text, providing 806 details. 808 7. Update Stream Service 810 An update stream service returns a stream of update messages, as 811 defined in Section 6. An ALTO server's IRD (Information Resource 812 Directory) MAY define one or more update stream services, which ALTO 813 clients use to request new update stream instances. 815 7.1. Media Type 817 The media type of an ALTO update stream service is "text/event- 818 stream", as defined by [SSE]. 820 7.2. HTTP Method 822 An ALTO update stream service is requested using the HTTP POST 823 method. 825 7.3. Accept Input Parameters 827 An ALTO client specifies the parameters for the new update stream by 828 sending an HTTP POST body with the media type "application/alto- 829 updatestreamparams+json". That body contains a JSON Object of type 830 UpdateStreamReq, where: 832 object { 833 [AddUpdatesReq add;] 834 [ClientId remove<0..*>;] 835 } UpdateStreamReq; 837 object-map { 838 ClientId -> AddUpdateReq; 839 } AddUpdatesReq; 841 object { 842 String resource-id; 843 [String tag;] 844 [Boolean incremental-changes;] 845 [Object input;] 846 } AddUpdateReq; 848 add: specifies the resources for which the ALTO client wants updates, 849 and has one entry for each resource. An ALTO client creates a 850 unique client-id (Section 6.1) for each such resource, and uses 851 those client-ids as the keys in the "add" field. 853 resource-id: the resource-id of an ALTO resource, and MUST be in the 854 update stream's "uses" list (Section 8.5.2 of Section 7.5). If 855 the resource-id is a GET-mode resource with a version tag (or 856 "vtag"), as defined in Section 6.3 and Section 10.3 of 857 [RFC7285], and the ALTO client has previously retrieved a 858 version of that resource from the update stream server, the ALTO 859 client MAY set the "tag" field to the tag part of the client's 860 version of that resource. If that version is not current, the 861 update stream server MUST send a full replacement before sending 862 any incremental changes, as described in Section 7.7.1. If that 863 version is still current, the update stream server MAY omit the 864 initial full replacement. 866 incremental-changes: the ALTO client specify whether it is willing 867 to receive incremental changes from the update stream server for 868 a specific resource-id. If the "incremental-changes" field for 869 a resource-id is "true", the update stream server MAY send 870 incremental changes for that resource (assuming the update 871 stream server supports incremental changes for) that resource; 872 see Section Section 7.4). If the "incremental-changes" field is 873 "false", the update stream server MUST NOT send incremental 874 changes for that resource. The default value for "incremental- 875 changes" is "true", so to suppress incremental changes, the ALTO 876 client MUST explicitly set "incremental-changes" to "false". 877 Note that the ALTO client cannot suppress full replacement. 878 When the ALTO client sets "incremental-changes" to "false", the 879 update stream server MUST send a full replacement instead of an 880 incremental change to the ALTO client. The update stream server 881 MAY wait until more changes are available, and send a single 882 full replacement with those changes. Thus an ALTO client which 883 declines to accept incremental changes may not get updates as 884 quickly as an ALTO client which does. 886 input: If the resource is a POST-mode service which requires input, 887 the ALTO client MUST set the "input" field to a JSON Object with 888 the parameters that resource expects. 890 remove: it is used in update stream control requests (Section 8), 891 and is not allowed in the update stream request. The update 892 stream server SHOULD ignore this field if it is included in the 893 request. 895 If a request has any errors, the update stream server MUST NOT create 896 an update stream. Also, the update stream server will send error 897 response to the ALTO client as specified in Section 7.6. 899 7.4. Capabilities 901 The capabilities are defined as an object of type 902 UpdateStreamCapabilities: 904 object { 905 IncrementalUpdateMediaTypes incremental-change-media-types; 906 Boolean support-stream-control; 907 } UpdateStreamCapabilities; 909 object-map { 910 ResourceID -> String; 911 } IncrementalUpdateMediaTypes; 913 If this update stream can provide data update messages with 914 incremental changes for a resource, the "incremental-change-media- 915 types" field has an entry for that resource-id, and the value is the 916 media-type of the incremental change. Normally this will be 917 "application/merge-patch+json", "application/json-patch+json", or 918 "application/merge-patch+json,application/json-patch+json", because, 919 as described in Section 6, they are the only incremental change types 920 defined by this document. However future extensions may define other 921 types of incremental changes. 923 When choosing the media-type to encode incremental changes for a 924 resource, the update stream server SHOULD consider the limitations of 925 the encoding. For example, when a JSON merge patch specifies that 926 the value of a field is null, its semantics is that the field is 927 removed from the target, and hence the field is no longer defined 928 (i.e., undefined); see the MergePatch algorithm in Section 4.2.1 on 929 how null value is processed. This, however, may not be the intended 930 result for the resource, when null and undefined have different 931 semantics for the resource. In such a case, the update stream server 932 SHOULD choose JSON patch over JSON merge patch. 934 The "support-stream-control" field specifies whether the given update 935 stream supports stream control. If "support-stream-control" field is 936 "true", the update stream server will uses the stream control 937 specified in this document; else, the update stream server may use 938 other mechanisms to provide the same functionality as stream control. 940 7.5. Uses 942 The "uses" attribute MUST be an array with the resource-ids of every 943 resource for which this update stream can provide updates. Each 944 resource specified in the "uses" MUST support full replacement: the 945 update stream server can always send full replacement, and the ALTO 946 client MUST accept full replacement. 948 This set may be any subset of the ALTO server's resources, and may 949 include resources defined in linked IRDs. However, it is RECOMMENDED 950 that the ALTO server selects a set that is closed under the resource 951 dependency relationship. That is, if an update stream's "uses" set 952 includes resource R1, and resource R1 depends on ("uses") resource 953 R0, then the update stream's "uses" set SHOULD include R0 as well as 954 R1. For example, an update stream for a cost map SHOULD also provide 955 updates for the network map upon which that cost map depends. 957 7.6. Response 959 If the update stream request has any errors, the update stream server 960 MUST return an HTTP "400 Bad Request" to the ALTO client. The body 961 part of the HTTP response is the JSON object defined in Section 8.5.2 962 in [RFC7285]. Hence, an ALTO error response has the format: 964 HTTP/1.1 400 Bad Request 965 Content-Length: [TBD] 966 Content-Type: application/alto-error+json 967 Connection: close 969 { 970 "meta":{ 971 "code": "***", 972 "field": "***", 973 "value": "***" 974 } 975 } 977 Note that "field" and "value" are optional fields. If the "value" 978 field exists, the "field" field MUST exist. 980 o If an update stream request does not have an "add" field 981 specifying one or more resources, the error code of the error 982 message MUST be E_MISSING_FIELD and the "field" field SHOULD be 983 "add". The update stream server MUST close the stream without 984 sending any events. 986 o If the "resource-id" field is invalid, or is not associated with 987 the update stream, the error code of the error message MUST be 988 E_INVALID_FIELD_VALUE; the "field" field SHOULD be "resource-id" 989 and the "value" field SHOULD be the invalid resource-id. If there 990 are more than one invalid resource-ids, the update stream server 991 SHOULD pick one and return it. The update stream server MUST 992 close the stream without sending any events. 994 o If the resource is a POST-mode service which requires input, the 995 client MUST set the "input" field to a JSON Object with the 996 parameters that that resource expects. If the "input" field is 997 missing or invalid, the update stream server MUST return the same 998 error response that that resource would return for missing or 999 invalid input (see [RFC7285]). In this case, the update stream 1000 server MUST close the update stream without sending any events. 1001 If the input for several POST-mode resources are missing or 1002 invalid, the update stream server MUST pick one and return it. 1004 The response to a valid request is a stream of update messages. 1005 Section 6 defines the update messages, and [SSE] defines how they are 1006 encoded into a stream. 1008 An update stream server SHOULD send updates only when the underlying 1009 values change. However, it may be difficult for an update stream 1010 server to guarantee that in all circumstances. Therefore a client 1011 MUST NOT assume that an update message represents an actual change. 1013 7.7. Additional Requirements on Update Messages 1015 7.7.1. Event Sequence Requirements 1017 o The first event MUST be a control update message with the URI of 1018 the update stream control service Section 8 for this update 1019 stream. 1021 o As soon as possible after the ALTO client initiates the 1022 connection, the update stream server MUST send a full replacement 1023 for each resource-id requested with a version tag. In this case 1024 the update stream server MAY omit the initial full replacement for 1025 that resource, if the "tag" field the ALTO client provided for 1026 that resource-id matches the tag of the update stream's current 1027 version. 1029 o If this update stream provides update for resource-ids and R0 and 1030 R1, and if R1 depends on R0, then the update stream server MUST 1031 send the update for R0 before sending the related updates for R1. 1032 For example, suppose an update stream provides updates to a 1033 network map and its dependent cost maps. When the network map 1034 changes, the update stream server MUST send the network map update 1035 before sending the cost map updates. 1037 o When the ALTO client uses the stream control service to stop 1038 updates for one or more resources Section 8, the ALTO client MUST 1039 send a stream control request. The update stream server MUST send 1040 a control update message whose "stopped" field has the client-ids 1041 of all active resources. 1043 7.7.2. Cross-Stream Consistency Requirements 1045 If several ALTO clients create multiple update streams for updates to 1046 the same resource, the update stream server MUST send the same 1047 updates to all of them. However, the update stream server MAY pack 1048 data items into different patch events, as long as the net result of 1049 applying those updates is the same. 1051 For example, suppose two different ALTO clients create update streams 1052 for the same cost map, and suppose the update stream server processes 1053 three separate cost point updates with a brief pause between each 1054 update. The server MUST send all three new cost points to both 1055 clients. But the update stream server MAY send a single patch event 1056 (with all three cost points) to one ALTO client, while sending three 1057 separate patch events (with one cost point per event) to the other 1058 ALTO client. 1060 A update stream server MAY offer several different update stream 1061 resources that provide updates to the same underlying resource (that 1062 is, a resource-id may appear in the "uses" field of more than one 1063 update stream resource). In this case, those update stream resources 1064 MUST return the same update data. 1066 7.8. Keep-Alive Messages 1068 In an SSE stream, any line which starts with a colon (U+003A) 1069 character is a comment, and an ALTO client MUST ignore that line 1070 ([SSE]). As recommended in [SSE], an update stream server SHOULD 1071 send a comment line (or an event) every 15 seconds to prevent ALTO 1072 clients and proxy servers from dropping the HTTP connection. 1074 8. Stream Control Service 1076 An stream control service allows an ALTO client to remove resources 1077 from the set of resources that are monitored by an update stream, or 1078 add additional resources to that set. The service also allows an 1079 ALTO client to gracefully shut down an update stream. 1081 When an update stream server creates a new update stream, and if the 1082 update stream server supports stream control for the update stream, 1083 the update stream server creates a stream control service for that 1084 update stream. An ALTO client uses the stream control service to 1085 remove resources from the update stream instance, or to request 1086 updates for additional resources. An ALTO client cannot obtain the 1087 stream control service through the IRD. Instead, the first event 1088 that the update stream server sends to the ALTO client has the URI 1089 for the associated stream control service (see Section 6.3). 1091 Each stream control request is an individual HTTP request. If the 1092 ALTO client and the stream control server the ALTO client MAY send 1093 multiple stream control requests to the stream control server using 1094 the same HTTP connection. 1096 8.1. URI 1098 The URI for an stream control service, by itself, MUST uniquely 1099 specify the update stream instance which it controls. The stream 1100 control server MUST NOT use other properties of an HTTP request, such 1101 as cookies or the client's IP address, to determine the update 1102 stream. Furthermore, an update stream server MUST NOT reuse a 1103 control service URI once the associated update stream has been 1104 closed. 1106 The ALTO client MUST evaluate a non-absolute control URI (for 1107 example, a URI without a host, or with a relative path) in the 1108 context of the URI used to create the update stream. The stream 1109 control service's host MAY be different from the update stream's 1110 host. 1112 It is expected that the update stream server will assign a unique 1113 stream id to each update stream instance and will embed that id in 1114 the associated stream control URI. However, the exact mechanism is 1115 left to the update stream server. ALTO clients MUST NOT attempt to 1116 deduce a stream id from the control URI. 1118 To prevent an attacker from forging a stream control URI and sending 1119 bogus requests to disrupt other update streams, stream control URIs 1120 SHOULD contain sufficient random redundancy to make it difficult to 1121 guess valid URIs. 1123 8.2. Media Type 1125 An ALTO stream control response does not have a specific media type. 1127 8.3. HTTP Method 1129 An ALTO update stream control resource is requested using the HTTP 1130 POST method. 1132 8.4. Accept Input Parameters 1134 An stream control service accepts the same input media type and input 1135 parameters as the update stream service (Section 7.3). The only 1136 difference is that a stream control service also accepts the "remove" 1137 field. 1139 If specified, the "remove" field is an array of client-ids the ALTO 1140 client previously added to this update stream. An empty "remove" 1141 array is equivalent to a list of all currently active resources; the 1142 update stream server responds by removing all resources and closing 1143 the stream. 1145 An ALTO client MAY use the "add" field to add additional resources. 1146 However, the ALTO client MUST assign a unique client-id to each 1147 resource. Client-ids MUST be unique over the lifetime of this update 1148 stream: an ALTO client MUST NOT reuse a previously removed client-id. 1150 If a request has any errors, the update stream server MUST NOT add or 1151 remove any resources from the associated update stream. Also, the 1152 stream control server will return an error response to the client as 1153 specified in Section 8.6. 1155 8.5. Capabilities & Uses 1157 None (Stream control services do not appear in the IRD). 1159 8.6. Response 1161 The stream control server MUST process the "add" field before the 1162 "remove" field. If the request removes all active resources without 1163 adding any additional resources, the update stream server MUST close 1164 the update stream. Thus an update stream cannot have zero resources. 1166 If the request has any errors, the stream control server MUST return 1167 an HTTP "400 Bad Request" to the ALTO client. The body part of the 1168 HTTP response is the JSON object defined in Section 8.5.2 in 1169 [RFC7285]. An error response has the same format as specified in 1170 Section 7.6. Detailed error code and error information are specified 1171 as below. 1173 o If the "add" request does not satisfy the requirements in 1174 Section 7.3, the stream control server MUST return the ALTO error 1175 message defined in Section 7.6. 1177 o If any client-id in the "remove" field was not added in a prior 1178 request, the error code of the error message MUST be 1179 E_INVALID_FIELD_VALUE; the "field" field SHOULD be "remove" and 1180 the "value" field SHOULD be the array of the invalid client-ids. 1181 Thus it is illegal to "add" and "remove" the same client-id in the 1182 same request. However, it is legal to remove a client-id twice. 1184 o If any client-id in the "add" field has been used before in this 1185 stream, the error code of the error message MUST be 1186 E_INVALID_FIELD_VALUE, the "field" field SHOULD be "add" and the 1187 "value" field SHOULD be the array of invalid client-ids. 1189 o If the request has a non-empty "add" field and a "remove" field 1190 with an empty list of client-ids (to replace all active resources 1191 with a new set, the client MUST explicitly enumerate the client- 1192 ids to be removed), the error code of the error message MUST be 1193 E_INVALID_FIELD_VALUE; the "field" field SHOULD be "remove" and 1194 the "value" field SHOULD be an empty array. 1196 If the request is valid but the associated update stream has been 1197 closed. The stream control server MUST return an HTTP "404 Not 1198 Found". 1200 If the request is valid and the stream control server successfully 1201 processes the request without error, the stream control server should 1202 return either an HTTP "202 Accepted" response or an HTTP "204 No 1203 Content" response. The difference is that for the latter case, the 1204 stream control server is sure that the update stream server has also 1205 processed the request. Regardless of 202 or 204 HTTP response, the 1206 final updates of related resources will be notified by the update 1207 stream server using its control update message(s), due to our modular 1208 design. 1210 9. Examples 1212 9.1. Example: IRD Announcing Update Stream Services 1214 Below is an example IRD announcing two update stream services. The 1215 first, which is named "update-my-costs", provides updates for the 1216 network map, the "routingcost" and "hopcount" cost maps, and a 1217 filtered cost map resource. The second, which is named "update-my- 1218 prop", provides updates to the endpoint propertie service. 1220 Note that in the "update-my-costs" update stream shown in the example 1221 IRD, the update stream server uses JSON patch for network map, and it 1222 uses JSON merge patch to update the other resources. Also, the 1223 update stream will only provide full replacements for "my-simple- 1224 filtered-cost-map". 1226 Also, note that this IRD defines two filtered cost map resources. 1227 They use the same cost types, but "my-filtered-cost-map" accepts cost 1228 constraint tests, while "my-simple-filtered-cost-map" does not. To 1229 avoid the issues discussed in Section 12.1, the update stream 1230 provides updates for the second, but not the first. 1232 "my-network-map": { 1233 "uri": "http://alto.example.com/networkmap", 1234 "media-type": "application/alto-networkmap+json", 1235 }, 1236 "my-routingcost-map": { 1237 "uri": "http://alto.example.com/costmap/routingcost", 1238 "media-type": "application/alto-costmap+json", 1239 "uses": ["my-networkmap"], 1240 "capabilities": { 1241 "cost-type-names": ["num-routingcost"] 1242 } 1243 }, 1244 "my-hopcount-map": { 1245 "uri": "http://alto.example.com/costmap/hopcount", 1246 "media-type": "application/alto-costmap+json", 1247 "uses": ["my-networkmap"], 1248 "capabilities": { 1249 "cost-type-names": ["num-hopcount"] 1250 } 1252 }, 1253 "my-filtered-cost-map": { 1254 "uri": "http://alto.example.com/costmap/filtered/constraints", 1255 "media-type": "application/alto-costmap+json", 1256 "accepts": "application/alto-costmapfilter+json", 1257 "uses": ["my-networkmap"], 1258 "capabilities": { 1259 "cost-type-names": ["num-routingcost", "num-hopcount"], 1260 "cost-constraints": true 1261 } 1262 }, 1263 "my-simple-filtered-cost-map": { 1264 "uri": "http://alto.example.com/costmap/filtered/simple", 1265 "media-type": "application/alto-costmap+json", 1266 "accepts": "application/alto-costmapfilter+json", 1267 "uses": ["my-networkmap"], 1268 "capabilities": { 1269 "cost-type-names": ["num-routingcost", "num-hopcount"], 1270 "cost-constraints": false 1271 } 1272 }, 1273 "my-props": { 1274 "uri": "http://alto.example.com/properties", 1275 "media-type": "application/alto-endpointprops+json", 1276 "accepts": "application/alto-endpointpropparams+json", 1277 "capabilities": { 1278 "prop-types": ["priv:ietf-bandwidth"] 1279 } 1280 }, 1281 "update-my-costs": { 1282 "uri": "http://alto.example.com/updates/costs", 1283 "media-type": "text/event-stream", 1284 "accepts": "application/alto-updatestreamparams+json", 1285 "uses": [ 1286 "my-network-map", 1287 "my-routingcost-map", 1288 "my-hopcount-map", 1289 "my-simple-filtered-cost-map" 1290 ], 1291 "capabilities": { 1292 "incremental-change-media-types": { 1293 "my-network-map": "application/json-patch+json", 1294 "my-routingcost-map": "application/merge-patch+json", 1295 "my-hopcount-map": "application/merge-patch+json" 1296 }, 1297 "support-stream-control": true 1298 } 1299 }, 1300 "update-my-props": { 1301 "uri": "http://alto.example.com/updates/properties", 1302 "media-type": "text/event-stream", 1303 "uses": [ "my-props" ], 1304 "accepts": "application/alto-updatestreamparams+json", 1305 "capabilities": { 1306 "incremental-change-media-types": { 1307 "my-props": "application/merge-patch+json" 1308 }, 1309 "support-stream-control": true 1310 } 1311 } 1313 9.2. Example: Simple Network and Cost Map Updates 1315 Given the update streams announced in the preceding example IRD, 1316 below we show an example of an ALTO client's request and the update 1317 stream server's immediate response, using the update stream resource 1318 "update-my-costs". In the example, the ALTO client requests updates 1319 for the network map and "routingcost" cost map, but not for the 1320 "hopcount" cost map. The ALTO client uses the ALTO server's 1321 resource-ids as the client-ids. Because the client does not provide 1322 a "tag" for the network map, the update stream server must send a 1323 full replacement for the network map as well as for the cost map. 1324 The ALTO client does not set "incremental-changes" to "false", so it 1325 defaults to "true". Thus, the update stream server will send patch 1326 updates for the cost map and the network map. 1328 POST /updates/costs HTTP/1.1 1329 Host: alto.example.com 1330 Accept: text/event-stream,application/alto-error+json 1331 Content-Type: application/alto-updatestreamparams+json 1332 Content-Length: ### 1334 { "add": { 1335 "my-network-map": { 1336 "resource-id": "my-network-map" 1337 }, 1338 "my-routingcost-map": { 1339 "resource-id": "my-routingcost-map" 1340 } 1341 } 1342 } 1344 HTTP/1.1 200 OK 1345 Connection: keep-alive 1346 Content-Type: text/event-stream 1347 event: application/alto-updatestreamcontrol+json 1348 data: {"control-uri": 1349 data: "http://alto.example.com/updates/streams/3141592653589"} 1351 event: application/alto-networkmap+json,my-network-map 1352 data: { 1353 data: "meta" : { 1354 data: "vtag": { 1355 data: "resource-id" : "my-network-map", 1356 data: "tag" : "da65eca2eb7a10ce8b059740b0b2e3f8eb1d4785" 1357 data: } 1358 data: }, 1359 data: "network-map" : { 1360 data: "PID1" : { 1361 data: "ipv4" : [ "192.0.2.0/24", "198.51.100.0/25" ] 1362 data: }, 1363 data: "PID2" : { 1364 data: "ipv4" : [ "198.51.100.128/25" ] 1365 data: }, 1366 data: "PID3" : { 1367 data: "ipv4" : [ "0.0.0.0/0" ], 1368 data: "ipv6" : [ "::/0" ] 1369 data: } 1370 data: } 1371 data: } 1372 data: } 1374 event: application/alto-costmap+json,my-routingcost-map 1375 data: { 1376 data: "meta" : { 1377 data: "dependent-vtags" : [{ 1378 data: "resource-id": "my-network-map", 1379 data: "tag": "da65eca2eb7a10ce8b059740b0b2e3f8eb1d4785" 1380 data: }], 1381 data: "cost-type" : { 1382 data: "cost-mode" : "numerical", 1383 data: "cost-metric": "routingcost" 1384 data: }, 1385 data: "vtag": { 1386 data: "resource-id" : "my-routingcost-map", 1387 data: "tag" : "3ee2cb7e8d63d9fab71b9b34cbf764436315542e" 1388 data: } 1389 data: }, 1390 data: "cost-map" : { 1391 data: "PID1": { "PID1": 1, "PID2": 5, "PID3": 10 }, 1392 data: "PID2": { "PID1": 5, "PID2": 1, "PID3": 15 }, 1393 data: "PID3": { "PID1": 20, "PID2": 15 } 1394 data: } 1395 data: } 1397 After sending those events immediately, the update stream server will 1398 send additional events as the maps change. For example, the 1399 following represents a small change to the cost map. PID1->PID2 is 1400 changed to 9 from 5, PID3->PID1 is no longer available and PID3->PID3 1401 is now defined as 1: 1403 event: application/merge-patch+json,my-routingcost-map 1404 data: { 1405 data: "meta" : { 1406 data: "vtag": { 1407 data: "tag": "c0ce023b8678a7b9ec00324673b98e54656d1f6d" 1408 data: } 1409 data: }, 1410 data: "cost-map": { 1411 data: "PID1" : { "PID2" : 9 }, 1412 data: "PID3" : { "PID1" : null, "PID3" : 1 } 1413 data: } 1414 data: } 1416 As another example, the following represents a change to the network 1417 map: an ipv4 prefix "193.51.100.0/25" is added to PID1. It triggers 1418 changes to the cost map. The update stream server chooses to send an 1419 incremental change for the network map and send a full replacement 1420 instead of an incremental change for the cost map: 1422 event: application/json-patch+json,my-network-map 1423 data: { 1424 data: { 1425 data: "op": "replace", 1426 data: "path": "/meta/vtag/tag", 1427 data: "value" :"a10ce8b059740b0b2e3f8eb1d4785acd42231bfe" 1428 data: }, 1429 data: { 1430 data: "op": "add", 1431 data: "path": "/network-map/PID1/ipv4/2", 1432 data: "value": "193.51.100.0/25" 1433 data: } 1434 data: } 1436 event: application/alto-costmap+json,my-routingcost-map 1437 data: { 1438 data: "meta" : { 1439 data: "vtag": { 1440 data: "tag": "c0ce023b8678a7b9ec00324673b98e54656d1f6d" 1441 data: } 1442 data: }, 1443 data: "cost-map" : { 1444 data: "PID1": { "PID1": 1, "PID2": 3, "PID3": 7 }, 1445 data: "PID2": { "PID1": 12, "PID2": 1, "PID3": 9 }, 1446 data: "PID3": { "PID1": 14, "PID2": 8 } 1447 data: } 1448 data: } 1450 9.3. Example: Advanced Network and Cost Map Updates 1452 This example is similar to the previous one, except that the ALTO 1453 client requests updates for the "hopcount" cost map as well as the 1454 "routingcost" cost map and provides the current version tag of the 1455 network map, so the update stream server is not required to send the 1456 full network map data update message at the beginning of the stream. 1457 In this example, the client uses the client-ids "net", "routing" and 1458 "hops" for those resources. The update stream server sends the 1459 stream control URI and the full cost maps, followed by updates for 1460 the network map and cost maps as they become available: 1462 POST /updates/costs HTTP/1.1 1463 Host: alto.example.com 1464 Accept: text/event-stream,application/alto-error+json 1465 Content-Type: application/alto-updatestreamparams+json 1466 Content-Length: ### 1468 { "add": { 1469 "net": { 1470 "resource-id": "my-network-map". 1471 "tag": "a10ce8b059740b0b2e3f8eb1d4785acd42231bfe" 1472 }, 1473 "routing": { 1474 "resource-id": "my-routingcost-map" 1475 }, 1476 "hops": { 1477 "resource-id": "my-hopcount-map" 1478 } 1479 } 1480 } 1482 HTTP/1.1 200 OK 1483 Connection: keep-alive 1484 Content-Type: text/event-stream 1486 event: application/alto-updatestreamcontrol+json 1487 data: {"control-uri": 1488 data: "http://alto.example.com/updates/streams/2718281828459"} 1490 event: application/alto-costmap+json,routing 1491 data: { ... full routingcost cost map message ... } 1493 event: application/alto-costmap+json,hops 1494 data: { ... full hopcount cost map message ... } 1496 (pause) 1498 event: application/merge-patch+json,routing 1499 data: {"cost-map": {"PID2" : {"PID3" : 31}}} 1501 event: application/merge-patch+json,hops 1502 data: {"cost-map": {"PID2" : {"PID3" : 4}}} 1504 If the ALTO client wishes to stop receiving updates for the 1505 "hopcount" cost map, the ALTO client can send a "remove" request on 1506 the stream control URI: 1508 POST /updates/streams/2718281828459" HTTP/1.1 1509 Host: alto.example.com 1510 Accept: text/plain,application/alto-error+json 1511 Content-Type: application/alto-updatestreamparams+json 1512 Content-Length: ### 1514 { 1515 "remove": [ "hops" ] 1516 } 1518 HTTP/1.1 204 No Content 1519 Content-Length: 0 1521 (stream closed without sending data content) 1523 The update stream server sends a "stopped" control update message on 1524 the original request stream to inform the ALTO client that updates 1525 are stopped for that resource: 1527 event: application/alto-updatestreamcontrol+json 1528 data: { 1529 data: "stopped": ["hops"] 1530 data: } 1532 Below is an example of an invalid stream control request. The 1533 "remove" field of the request includes an undefined client-id and the 1534 stream control server will return an error response to the ALTO 1535 client. 1537 POST /updates/streams/2718281828459 HTTP/1.1 1538 Host: alto.example.com 1539 Accept: text/plain,application/alto-error+json 1540 Content-Type: application/alto-updatestreamparams+json 1541 Content-Length: ### 1542 { 1543 "remove": [ "properties" ] 1544 } 1546 HTTP/1.1 400 Bad Request 1547 Content-Length: [TBD] 1548 Content-Type: application/alto-error+json 1550 { 1551 "meta":{ 1552 "code": "E_INVALID_FIELD_VALUE", 1553 "field": "remove", 1554 "value": "properties" 1555 } 1557 If the ALTO client no longer needs any updates, and wishes to shut 1558 the update stream down gracefully, the client can send a "remove" 1559 request with an empty array: 1561 POST /updates/streams/2718281828459 HTTP/1.1 1562 Host: alto.example.com 1563 Accept: text/plain,application/alto-error+json 1564 Content-Type: application/alto-updatestreamparams+json 1565 Content-Length: ### 1567 { 1568 "remove": [ ] 1569 } 1571 HTTP/1.1 204 No Content 1572 Content-Length: 0 1574 (stream closed without sending data content) 1576 The update stream server sends a final control update message on the 1577 original request stream to inform the ALTO client that all updates 1578 are stopped and then closes the stream: 1580 event: application/alto-updatestreamcontrol+json 1581 data: { 1582 data: "stopped": ["net", "routing"] 1583 data: } 1585 (server closes stream) 1587 9.4. Example: Endpoint Property Updates 1589 As another example, here is how an ALTO client can request updates 1590 for the property "priv:ietf-bandwidth" for one set of endpoints and 1591 "priv:ietf-load" for another. The update stream server immediately 1592 sends full replacements with the property values for all endpoints. 1593 After that, the update stream server sends data update messages for 1594 the individual endpoints as their property values change. 1596 POST /updates/properties HTTP/1.1 1597 Host: alto.example.com 1598 Accept: text/event-stream 1599 Content-Type: application/alto-updatestreamparams+json 1600 Content-Length: ### 1602 { "add": { 1603 "props-1": { 1604 "resource-id": "my-props", 1605 "input": { 1606 "properties" : [ "priv:ietf-bandwidth" ], 1607 "endpoints" : [ 1608 "ipv4:198.51.100.1", 1609 "ipv4:198.51.100.2", 1610 "ipv4:198.51.100.3" 1611 ] 1612 } 1613 }, 1614 "props-2": { 1615 "resource-id": "my-props", 1616 "input": { 1617 "properties" : [ "priv:ietf-load" ], 1618 "endpoints" : [ 1619 "ipv6:2001:db8:100::1", 1620 "ipv6:2001:db8:100::2", 1621 "ipv6:2001:db8:100::3", 1622 ] 1623 } 1624 }, 1625 } 1626 } 1627 HTTP/1.1 200 OK 1628 Connection: keep-alive 1629 Content-Type: text/event-stream 1631 event: application/alto-updatestreamcontrol+json 1632 data: {"control-uri": 1633 data: "http://alto.example.com/updates/streams/1414213562373"} 1635 event: application/alto-endpointprops+json,props-1 1636 data: { "endpoint-properties": { 1637 data: "ipv4:198.51.100.1" : { "priv:ietf-bandwidth": "13" }, 1638 data: "ipv4:198.51.100.2" : { "priv:ietf-bandwidth": "42" }, 1639 data: "ipv4:198.51.100.3" : { "priv:ietf-bandwidth": "27" } 1640 data: } } 1642 event: application/alto-endpointprops+json,props-2 1643 data: { "endpoint-properties": { 1644 data: "ipv6:2001:db8:100::1" : { "priv:ietf-load": "8" }, 1645 data: "ipv6:2001:db8:100::2" : { "priv:ietf-load": "2" }, 1646 data: "ipv6:2001:db8:100::3" : { "priv:ietf-load": "9" } 1647 data: } } 1649 (pause) 1651 event: application/merge-patch+json,props-1 1652 data: { "endpoint-properties": 1653 data: {"ipv4:198.51.100.1" : {"priv:ietf-bandwidth": "3"}} 1654 data: } 1656 (pause) 1658 event: application/merge-patch+json,props-2 1659 data: { "endpoint-properties": 1660 data: {"ipv6:2001:db8:100::3" : {"priv:ietf-load": "7"}} 1661 data: } 1663 If the ALTO client needs the "bandwidth" property for additional 1664 endpoints, the ALTO client can send an "add" request on the stream 1665 control URI: 1667 POST /updates/streams/1414213562373" HTTP/1.1 1668 Host: alto.example.com 1669 Accept: text/plain,application/alto-error+json 1670 Content-Type: application/alto-updatestreamparams+json 1671 Content-Length: ### 1673 { "add": { 1674 "props-3": { 1675 "resource-id": "my-props", 1676 "input": { 1677 "properties" : [ "priv:ietf-bandwidth" ], 1678 "endpoints" : [ 1679 "ipv4:198.51.100.4", 1680 "ipv4:198.51.100.5", 1681 ] 1682 } 1683 }, 1684 "props-4": { 1685 "resource-id": "my-props", 1686 "input": { 1687 "properties" : [ "priv:ietf-load" ], 1688 "endpoints" : [ 1689 "ipv6:2001:db8:100::4", 1690 "ipv6:2001:db8:100::5", 1691 ] 1692 } 1693 }, 1694 } 1695 } 1697 HTTP/1.1 204 No Content 1698 Content-Length: 0 1700 (stream closed without sending data content) 1702 The update stream server sends full replacements for the two new 1703 resources, followed by incremental changes for all four requests as 1704 they arrive: 1706 event: application/alto-endpointprops+json,props-3 1707 data: { "endpoint-properties": { 1708 data: "ipv4:198.51.100.4" : { "priv:ietf-bandwidth": "25" }, 1709 data: "ipv4:198.51.100.5" : { "priv:ietf-bandwidth": "31" }, 1710 data: } } 1712 event: application/alto-endpointprops+json,props-4 1713 data: { "endpoint-properties": { 1714 data: "ipv6:2001:db8:100::4" : { "priv:ietf-load": "6" }, 1715 data: "ipv6:2001:db8:100::5" : { "priv:ietf-load": "4" }, 1716 data: } } 1718 (pause) 1720 event: application/merge-patch+json,props-3 1721 data: { "endpoint-properties": 1722 data: {"ipv4:198.51.100.5" : {"priv:ietf-bandwidth": "15"}} 1723 data: } 1725 (pause) 1727 event: application/merge-patch+json,props-2 1728 data: { "endpoint-properties": 1729 data: {"ipv6:2001:db8:100::2" : {"priv:ietf-load": "9"}} 1730 data: } 1732 (pause) 1734 event: application/merge-patch+json,props-4 1735 data: { "endpoint-properties": 1736 data: {"ipv6:2001:db8:100::4" : {"priv:ietf-load": "3"}} 1737 data: } 1739 10. Client Actions When Receiving Update Messages 1741 In general, when an ALTO client receives a full replacement for a 1742 resource, the ALTO client should replace the current version with the 1743 new version. When an ALTO client receives an incremental change for 1744 a resource, the ALTO client should apply those patches to the current 1745 version of the resource. 1747 However, because resources can depend on other resources (e.g., cost 1748 maps depend on network maps), an ALTO client MUST NOT use a dependent 1749 resource if the resource on which it depends has changed. There are 1750 at least two ways an ALTO client can do that. We will illustrate 1751 these techniques by referring to network and cost map messages, 1752 although these techniques apply to any dependent resources. 1754 Note that when a network map changes, the update stream server MUST 1755 send the network map update message before sending the updates for 1756 the dependent cost maps (see Section 7.7.1). 1758 One approach is for the ALTO client to save the network map update 1759 message in a buffer and continue to use the previous network map, and 1760 the associated cost maps, until the ALTO client receives the update 1761 messages for all dependent cost maps. The ALTO client then applies 1762 all network and cost map updates atomically. 1764 Alternatively, the ALTO client MAY update the network map 1765 immediately. In this case, the ALTO client MUST mark each dependent 1766 cost map as temporarily invalid and MUST NOT use that map until the 1767 ALTO client receives a cost map update message with the new network 1768 map version tag. Note that the ALTO client MUST NOT delete the cost 1769 maps, because the update stream server may send incremental changes. 1771 The update stream server SHOULD send updates for dependent resources 1772 in a timely fashion. However, if the ALTO client does not receive 1773 the expected updates, the ALTO client MUST close the update stream 1774 connection, discard the dependent resources, and reestablish the 1775 update stream. The ALTO client MAY retain the version tag of the 1776 last version of any tagged resources and give those version tags when 1777 requesting the new update stream. In this case, if a version is 1778 still current, the update stream server will not re-send that 1779 resource. 1781 Although not as efficient as possible, this recovery method is simple 1782 and reliable. 1784 11. Design Decisions and Discussions 1786 11.1. HTTP/2 Server-Push 1788 HTTP/2 ([RFC7540]) provides a Server Push facility. Although the 1789 name implies that it might be useful for sending asynchronous updates 1790 from the update stream server to the client, in reality Server Push 1791 is not well suited for that task. To see why it is not, here is a 1792 quick summary of HTTP/2. 1794 HTTP/2 allows an client and a server to multiplex many HTTP requests 1795 and responses over a single TCP connection. The requests and 1796 responses can be interleaved on a block by block basis, avoiding the 1797 head-of-line blocking problem encountered with the Keep-Alive 1798 mechanism in HTTP/1.1. Server Push allows a server to send a 1799 resource (an image, a CSS file, a javascript file, etc.) to the 1800 client before the client explicitly requests it. A server can only 1801 push cacheable GET-mode resources. By pushing a resource, the server 1802 implicitly tells the client, "Add this resource to your cache, 1803 because a resource you have requested needs it." 1805 One approach for using Server Push for updates is for the update 1806 stream server to send each data update message as a separate Server 1807 Push item and let the client apply those updates as they arrive. 1808 Unfortunately, there are several problems with that approach. 1810 First, HTTP/2 does not guarantee that pushed resources are delivered 1811 to the client in the order they were sent by the client, so each data 1812 update message would need a sequence number, and the client would 1813 have to re-sequence them. 1815 Second, an HTTP/2-aware client library will not necessarily inform a 1816 client application when the server pushes a resource. Instead, the 1817 library might cache the pushed resource, and only deliver it to the 1818 client when the client explicitly requests that URI. 1820 But the third problem is the most significant: Server Push is 1821 optional and can be disabled by any proxy between the client and the 1822 server. This is not a problem for the intended use of Server Push: 1823 eventually the client will request those resources, so disabling 1824 Server Push just adds a delay. But this means that Server Push is 1825 not suitable for resources which the client does not know to request. 1827 Thus we do not believe HTTP/2 Server Push is suitable for delivering 1828 asynchronous updates. Hence we have chosen to base ALTO updates on 1829 HTTP/1.1 and SSE. 1831 11.2. Not Allowing Stream Restart 1833 If an update stream is closed accidentally, when the ALTO client 1834 reconnects, the update stream server must resend the full maps. This 1835 is clearly inefficient. To avoid that inefficiency, the SSE 1836 specification allows an update stream server to assign an id to each 1837 event. When an ALTO client reconnects, the ALTO client can present 1838 the id of the last successfully received event, and the update stream 1839 server restarts with the next event. 1841 However, that mechanism adds additional complexity. The update 1842 stream server must save SSE messages in a buffer, in case ALTO 1843 clients reconnect. But that mechanism will never be perfect: if the 1844 ALTO client waits too long to reconnect, or if the ALTO client sends 1845 an invalid id, then the update stream server will have to resend the 1846 complete maps anyway. 1848 Furthermore, this is unlikely to be a problem in practice. ALTO 1849 clients who want continuous updates for large resources, such as full 1850 Network and cost maps, are likely to be things like P2P trackers. 1851 These ALTO clients will be well connected to the network; they will 1852 rarely drop connections. 1854 Mobile devices certainly can and do drop connections and will have to 1855 reconnect. But mobile devices will not need continuous updates for 1856 multi-megabyte cost maps. If mobile devices need continuous updates 1857 at all, they will need them for small queries, such as the costs from 1858 a small set of media servers from which the device can stream the 1859 currently playing movie. If the mobile device drops the connection 1860 and reestablishes the update stream, the update stream server will 1861 have to retransmit only a small amount of redundant data. 1863 In short, using event ids to avoid resending the full map adds a 1864 considerable amount of complexity to avoid a situation which we 1865 expect is very rare. We believe that complexity is not worth the 1866 benefit. 1868 The Update Stream service does allow the ALTO client to specify the 1869 tag of the last received version of any tagged resource, and if that 1870 is still current, the update stream server need not retransmit the 1871 full resource. Hence ALTO clients can use this to avoid 1872 retransmitting full network maps. cost maps are not tagged, so this 1873 will not work for them. Of course, the ALTO protocol could be 1874 extended by adding version tags to cost maps, which would solve the 1875 retransmission-on-reconnect problem. However, adding tags to cost 1876 maps might add a new set of complications. 1878 11.3. Data Update Choices 1880 11.3.1. Full Replacement or Incremental Change 1882 At this point we do not have sufficient experience with ALTO 1883 deployments to know how frequently the resources will change, or how 1884 extensive those changes will be. For stable resources with minor 1885 changes, the update stream server may choose to send incremental 1886 changes; for resources that frequently change, the update stream 1887 server may choose to send a full replacement after a while. Whether 1888 to send full replacement or incremental change depends on the update 1889 stream server. 1891 11.3.2. JSON Merge Patch or JSON Patch 1893 We allow both JSON patch and JSON merge patch for incremental 1894 changes. JSON merge patch is clearly superior to JSON patch for 1895 describing incremental changes to Cost Maps, Endpoint Costs, and 1896 Endpoint Properties. For these data structures, JSON merge patch is 1897 more space-efficient, as well as simpler to apply; we see no 1898 advantage to allowing a server to use JSON patch for those resources. 1900 The case is not as clear for incremental changes to network maps. 1901 First, consider small changes such as moving a prefix from one PID to 1902 another. JSON patch could encode that as a simple insertion and 1903 deletion, while JSON merge patch would have to replace the entire 1904 array of prefixes for both PIDs. On the other hand, to process a 1905 JSON patch update, the ALTO client would have to retain the indexes 1906 of the prefixes for each PID. Logically, the prefixes in a PID are 1907 an unordered set, not an array; aside from handling updates, a client 1908 has no need to retain the array indexes of the prefixes. Hence to 1909 take advantage of JSON patch for network maps, ALTO clients would 1910 have to retain additional, otherwise unnecessary, data. 1912 Second, consider more involved changes such as removing half of the 1913 prefixes from a PID. JSON merge patch would send a new array for 1914 that PID, while JSON patch would have to send a list of remove 1915 operations and delete the prefix one by one. 1917 Therefore, each update stream server may decide on its own whether to 1918 use JSON merge patch or JSON patch according to the changes in 1919 network maps. 1921 Other JSON-based incremental change formats may be introduced in the 1922 future. 1924 11.4. Requirements on Future ALTO Services to Use this Design 1926 Although this design is quite flexible, it has underlying 1927 requirements. In particular, the key requirements are that (1) each 1928 update message is for a single resource; (2) incremental changes can 1929 be applied only to a resource that is a single JSON object, as both 1930 JSON merge patch and JSON patch can apply only to a single JSON 1931 object. Hence, if a future ALTO resource can contain multiple 1932 objects, then either each individual object also has a resource-id or 1933 an extension to this design is made. 1935 If an update stream provides updates to a filtered cost map that 1936 allows constraint tests, the requirements for such services are 1937 stated in Section 12.1. 1939 12. Miscellaneous Considerations 1940 12.1. Considerations for Updates to Filtered Cost Maps 1942 If an update stream provides updates to a Filtered cost map which 1943 allows constraint tests, then an ALTO client MAY request updates to a 1944 Filtered cost map request with a constraint test. In this case, when 1945 a cost changes, the update stream server MUST send an update if the 1946 new value satisfies the test. If the new value does not, whether the 1947 update stream server sends an update depends on whether the previous 1948 value satisfied the test. If it did not, the update stream server 1949 SHOULD NOT send an update to the ALTO client. But if the previous 1950 value did, then the update stream server MUST send an update with a 1951 "null" value, to inform the ALTO client that this cost no longer 1952 satisfies the criteria. 1954 An update stream server can avoid such issues by offering update 1955 streams only for filtered cost maps which do not allow constraint 1956 tests. 1958 12.2. Considerations for Incremental Updates to Ordinal Mode Costs 1960 For an ordinal mode cost map, a change to a single cost point may 1961 require updating many other costs. As an extreme example, suppose 1962 the lowest cost changes to the highest cost. For a numerical mode 1963 cost map, only that one cost changes. But for an ordinal mode cost 1964 map, every cost might change. While this document allows an update 1965 stream server to offer incremental updates for ordinal mode cost 1966 maps, update stream server implementors should be aware that 1967 incremental updates for ordinal costs are more complicated than for 1968 numerical costs, and ALTO clients should be aware that small changes 1969 may result in large updates. 1971 An update stream server can avoid this complication by only offering 1972 full replacements for ordinal cost maps. 1974 12.3. Considerations Related to SSE Line Lengths 1976 SSE was designed for events that consist of relatively small amounts 1977 of line-oriented text data, and SSE clients frequently read input one 1978 line-at-a-time. However, an update stream sends full cost maps as 1979 single events, and a cost map may involve megabytes, if not tens of 1980 megabytes, of text. This has implications for both the update stream 1981 server and the ALTO Client. 1983 First, SSE clients might not be able to handle a multi-megabyte data 1984 "line". Hence it is RECOMMENDED that an update stream server limit 1985 data lines to at most 2,000 characters. 1987 Second, some SSE client packages read all the data for an event into 1988 memory, and then present it to the client as a single character 1989 array. However, a client computer may not have enough memory to hold 1990 the entire JSON text for a large cost map. Hence an ALTO client 1991 SHOULD consider using an SSE library which presents the event data in 1992 manageable chunks, so the ALTO client can parse the cost map 1993 incrementally and store the underlying data in a more compact format. 1995 13. Security Considerations 1997 13.1. Denial-of-Service Attacks 1999 Allowing persistent update stream connections enables a new class of 2000 Denial-of-Service attacks. An ALTO client might create an 2001 unreasonable number of update stream connections, or add an 2002 unreasonable number of client-ids to one update stream. To avoid 2003 those attacks, an update stream server MAY choose to limit the number 2004 of active streams and reject new requests when that threshold is 2005 reached. An update stream server MAY also choose to limit the number 2006 of active client-ids on any given stream, or limit the total number 2007 of client-ids used over the lifetime of a stream, and reject any 2008 stream control request which would exceed those limits. In these 2009 cases, the update stream server SHOULD return the HTTP status "503 2010 Service Unavailable". 2012 While this technique prevents update stream DoS attacks from 2013 disrupting an update stream server's other services, it does make it 2014 easier for a DoS attack to disrupt the update stream service. 2015 Therefore an update stream server may prefer to restrict update 2016 stream services to authorized clients, as discussed in Section 15 of 2017 [RFC7285]. 2019 Alternatively, an update stream server MAY return the HTTP status 2020 "307 Temporary Redirect" to redirect the client to another ALTO 2021 server which can better handle a large number of update streams. 2023 13.2. Spoofed Control Requests 2025 An outside party which can read the update stream response, or which 2026 can observe stream control requests, can obtain the control URI and 2027 use that to send a fraudulent "remove" requests, thus disabling 2028 updates for the valid ALTO client. This can be avoided by encrypting 2029 the update stream and stream control requests (see Section 15 of 2030 [RFC7285]). Also, the update stream server echoes the "remove" 2031 requests on the update stream, so the valid ALTO client can detect 2032 unauthorized requests. 2034 13.3. Privacy 2036 This extension does not introduce any privacy issues not already 2037 present in the ALTO protocol. 2039 14. IANA Considerations 2041 This document defines two new media-types, "application/alto- 2042 updatestreamparams+json", as described in Section 7.3, and 2043 "application/alto-updatestreamcontrol+json", as described in 2044 Section 6.3. All other media-types used in this document have 2045 already been registered, either for ALTO, JSON merge patch, or JSON 2046 patch. 2048 Type name: application 2050 Subtype name: alto-updatestreamparams+json 2052 Required parameters: n/a 2054 Optional parameters: n/a 2056 Encoding considerations: Encoding considerations are identical to 2057 those specified for the "application/json" media type. See 2058 [RFC7159]. 2060 Security considerations: Security considerations relating to the 2061 generation and consumption of ALTO Protocol messages are discussed 2062 in Section 13 of this document and Section 15 of [RFC7285]. 2064 Interoperability considerations: This document specifies format of 2065 conforming messages and the interpretation thereof. 2067 Published specification: Section 7.3 of this document. 2069 Applications that use this media type: ALTO servers and ALTO clients 2070 either stand alone or are embedded within other applications. 2072 Additional information: 2074 Magic number(s): n/a 2076 File extension(s): This document uses the mime type to refer to 2077 protocol messages and thus does not require a file extension. 2079 Macintosh file type code(s): n/a 2081 Person & email address to contact for further information: See 2082 Authors' Addresses section. 2084 Intended usage: COMMON 2086 Restrictions on usage: n/a 2088 Author: See Authors' Addresses section. 2090 Change controller: Internet Engineering Task Force 2091 (mailto:iesg@ietf.org). 2093 Type name: application 2095 Subtype name: alto-updatestreamcontrol+json 2097 Required parameters: n/a 2099 Optional parameters: n/a 2101 Encoding considerations: Encoding considerations are identical to 2102 those specified for the "application/json" media type. See 2103 [RFC7159]. 2105 Security considerations: Security considerations relating to the 2106 generation and consumption of ALTO Protocol messages are discussed 2107 in Section 13 of this document and Section 15 of [RFC7285]. 2109 Interoperability considerations: This document specifies format of 2110 conforming messages and the interpretation thereof. 2112 Published specification: Section 6.3 of this document. 2114 Applications that use this media type: ALTO servers and ALTO clients 2115 either stand alone or are embedded within other applications. 2117 Additional information: 2119 Magic number(s): n/a 2121 File extension(s): This document uses the mime type to refer to 2122 protocol messages and thus does not require a file extension. 2124 Macintosh file type code(s): n/a 2126 Person & email address to contact for further information: See 2127 Authors' Addresses section. 2129 Intended usage: COMMON 2131 Restrictions on usage: n/a 2133 Author: See Authors' Addresses section. 2135 Change controller: Internet Engineering Task Force 2136 (mailto:iesg@ietf.org). 2138 15. Acknowledgments 2140 Thank you to Xiao Shi (Yale University) for his contributions to an 2141 earlier version of this document. 2143 16. References 2145 [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate 2146 Requirement Levels", RFC 2119, BCP 14, March 1997. 2148 [RFC5789] Dusseault, L. and J. Snell, "PATCH Method for HTTP", 2149 RFC 5789, March 2010. 2151 [RFC6902] Bryan, P. and M. Nottingham, "JavaScript Object Notation 2152 (JSON) Patch", RFC 6902, April 2013. 2154 [RFC7159] Bray, T., "The JavaScript Object Notation (JSON) Data 2155 Interchange Format", RFC 7159, March 2014. 2157 [RFC7230] Fielding, R. and J. Reschke, "Hypertext Transfer Protocol 2158 (HTTP/1.1): Message Syntax and Routing", RFC 7230, June 2159 2014. 2161 [RFC7231] Fielding, R. and J. Reschke, "Hypertext Transfer Protocol 2162 (HTTP/1.1): Semantics and Content", RFC 7231, June 2014. 2164 [RFC7285] Almi, R., Penno, R., Yang, Y., Kiesel, S., Previdi, S., 2165 Roome, W., Shalunov, S., and R. Woundy, "Application-Layer 2166 Traffic Optimization (ALTO) Protocol", RFC 7285, September 2167 2014. 2169 [RFC7396] Hoffman, P. and J. Snell, "JSON Merge Patch", RFC 7396, 2170 October 2014. 2172 [RFC7540] Belshe, M., Peon, R., and M. Thomson, "Hypertext Transfer 2173 Protocol Version 2 (HTTP/2)", RFC 7540, May 2015. 2175 [SSE] Hickson, I., "Server-Sent Events (W3C)", W3C 2176 Recommendation 03 February 2015, February 2015. 2178 Authors' Addresses 2180 Wendy Roome 2181 Nokia Bell Labs (Retired) 2182 124 Burlington Rd 2183 Murray Hill, NJ 07974 2184 USA 2186 Phone: +1-908-464-6975 2187 Email: wendy@wdroome.com 2189 Y. Richard Yang 2190 Tongji/Yale University 2191 51 Prospect St 2192 New Haven CT 2193 USA 2195 Email: yang.r.yang@gmail.com 2197 Shiwei Dawn Chen 2198 Tongji University 2199 4800 Caoan Road 2200 Shanghai 201804 2201 China 2203 Email: dawn_chen_f@hotmail.com