idnits 2.17.1 draft-ietf-alto-incr-update-sse-07.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. -- The document has examples using IPv4 documentation addresses according to RFC6890, but does not use any IPv6 documentation addresses. Maybe there should be IPv6 examples, too? Miscellaneous warnings: ---------------------------------------------------------------------------- == The copyright year in the IETF Trust and authors Copyright Line does not match the current year == Line 643 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: As described below, each control request adds resources to the set of monitored resources, or removes previously added resources, or does both. Each control request is a separate HTTP request; the client MAY NOT stream multiple control requests in one HTTP request. However, if the client and server support HTTP Keep-Alive ([RFC7230]), the client MAY send multiple HTTP requests on the same TCP/IP connection. -- The document date (July 3, 2017) is 2479 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 314, but not defined == Unused Reference: 'RFC7232' is defined on line 1788, but no explicit reference was found in the text == Unused Reference: 'RFC7233' is defined on line 1791, but no explicit reference was found in the text == Unused Reference: 'RFC7234' is defined on line 1794, but no explicit reference was found in the text == Unused Reference: 'RFC7235' is defined on line 1798, but no explicit reference was found in the text ** 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 7232 (Obsoleted by RFC 9110) ** Obsolete normative reference: RFC 7233 (Obsoleted by RFC 9110) ** Obsolete normative reference: RFC 7234 (Obsoleted by RFC 9111) ** Obsolete normative reference: RFC 7235 (Obsoleted by RFC 9110) ** Obsolete normative reference: RFC 7540 (Obsoleted by RFC 9113) -- Possible downref: Non-RFC (?) normative reference: ref. 'SSE' Summary: 10 errors (**), 0 flaws (~~), 8 warnings (==), 5 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 4, 2018 Tongji/Yale University 6 July 3, 2017 8 ALTO Incremental Updates Using Server-Sent Events (SSE) 9 draft-ietf-alto-incr-update-sse-07 11 Abstract 13 The Application-Layer Traffic Optimization (ALTO) [RFC7285] protocol 14 provides network related information, called network information 15 resources, to client applications so that clients can make informed 16 decisions in utilizing network resources. For example, an ALTO 17 server can provide network and cost maps so that an ALTO client can 18 use the maps to determine the costs between endpoints when choosing 19 communicating endpoints. 21 However, the ALTO protocol does not define a mechanism to allow an 22 ALTO client to obtain updates to the information resources, other 23 than by periodically re-fetching them. Because some information 24 resources (e.g., the aforementioned maps) may be large (potentially 25 tens of megabytes), and because only parts of the information 26 resources may change frequently (e.g., only some entries in a cost 27 map), complete re-fetching can be extremely inefficient. 29 This document presents a mechanism to allow an ALTO server to push 30 updates to ALTO clients, to achieve two benefits: (1) Updates can be 31 immediate, in that the server can send updates as soon as they are 32 available; and (2) Updates are incremental, in that if only a small 33 section of an information resource changes, the server can send just 34 the changes. 36 Requirements Language 38 The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", 39 "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this 40 document are to be interpreted as described in RFC 2119 [RFC2119]. 42 Status of This Memo 44 This Internet-Draft is submitted in full conformance with the 45 provisions of BCP 78 and BCP 79. 47 Internet-Drafts are working documents of the Internet Engineering 48 Task Force (IETF). Note that other groups may also distribute 49 working documents as Internet-Drafts. The list of current Internet- 50 Drafts is at http://datatracker.ietf.org/drafts/current/. 52 Internet-Drafts are draft documents valid for a maximum of six months 53 and may be updated, replaced, or obsoleted by other documents at any 54 time. It is inappropriate to use Internet-Drafts as reference 55 material or to cite them other than as "work in progress." 57 This Internet-Draft will expire on January 4, 2018. 59 Copyright Notice 61 Copyright (c) 2017 IETF Trust and the persons identified as the 62 document authors. All rights reserved. 64 This document is subject to BCP 78 and the IETF Trust's Legal 65 Provisions Relating to IETF Documents 66 (http://trustee.ietf.org/license-info) in effect on the date of 67 publication of this document. Please review these documents 68 carefully, as they describe your rights and restrictions with respect 69 to this document. Code Components extracted from this document must 70 include Simplified BSD License text as described in Section 4.e of 71 the Trust Legal Provisions and are provided without warranty as 72 described in the Simplified BSD License. 74 Table of Contents 76 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3 77 2. Major Changes Since Version -01 . . . . . . . . . . . . . . . 4 78 3. Terms . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 79 4. Background . . . . . . . . . . . . . . . . . . . . . . . . . 5 80 4.1. Server-Sent Events (SSEs) . . . . . . . . . . . . . . . . 5 81 4.2. JSON Merge Patch . . . . . . . . . . . . . . . . . . . . 6 82 4.2.1. JSON Merge Patch Encoding . . . . . . . . . . . . . . 6 83 4.2.2. Merge Patch ALTO Messages . . . . . . . . . . . . . . 7 84 4.3. JSON Patch . . . . . . . . . . . . . . . . . . . . . . . 10 85 4.3.1. JSON Patch Encoding . . . . . . . . . . . . . . . . . 10 86 4.3.2. JSON Patch ALTO Messages . . . . . . . . . . . . . . 10 87 5. Overview of Approach . . . . . . . . . . . . . . . . . . . . 11 88 6. Update Stream Messages: Update and Control Events . . . . . . 12 89 6.1. ALTO Event Format . . . . . . . . . . . . . . . . . . . . 12 90 6.2. ALTO Update Events . . . . . . . . . . . . . . . . . . . 13 91 6.3. ALTO Control Events . . . . . . . . . . . . . . . . . . . 13 92 7. Update Stream . . . . . . . . . . . . . . . . . . . . . . . . 14 93 7.1. Media Type . . . . . . . . . . . . . . . . . . . . . . . 14 94 7.2. HTTP Method . . . . . . . . . . . . . . . . . . . . . . . 14 95 7.3. Accept Input Parameters . . . . . . . . . . . . . . . . . 14 96 7.4. Capabilities . . . . . . . . . . . . . . . . . . . . . . 16 97 7.5. Uses . . . . . . . . . . . . . . . . . . . . . . . . . . 16 98 7.6. Response . . . . . . . . . . . . . . . . . . . . . . . . 17 99 7.6.1. Keep-Alive Messages . . . . . . . . . . . . . . . . . 17 100 7.6.2. Event Sequence Requirements . . . . . . . . . . . . . 17 101 7.6.3. Cross-Stream Consistency Requirements . . . . . . . . 18 102 8. Update Stream Control . . . . . . . . . . . . . . . . . . . . 18 103 8.1. URI . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 104 8.2. Media Type . . . . . . . . . . . . . . . . . . . . . . . 19 105 8.3. HTTP Method . . . . . . . . . . . . . . . . . . . . . . . 19 106 8.4. Accept Input Parameters . . . . . . . . . . . . . . . . . 19 107 8.5. Capabilities & Uses . . . . . . . . . . . . . . . . . . . 20 108 8.6. Response . . . . . . . . . . . . . . . . . . . . . . . . 20 109 9. Examples . . . . . . . . . . . . . . . . . . . . . . . . . . 21 110 9.1. Example: Simple Network and Cost Map Updates . . . . . . 21 111 9.2. Example: Advanced Network and Cost Map Updates . . . . . 22 112 9.3. Example: Endpoint Property Updates . . . . . . . . . . . 25 113 9.4. IRD Example . . . . . . . . . . . . . . . . . . . . . . . 28 114 10. Client Actions When Receiving Update Messages . . . . . . . . 30 115 11. Design Decisions and Discussions . . . . . . . . . . . . . . 31 116 11.1. HTTP/2 Server-Push . . . . . . . . . . . . . . . . . . . 31 117 11.2. Not Allowing Stream Restart . . . . . . . . . . . . . . 32 118 11.3. Is Incremental Update Useful for Network Maps? . . . . . 33 119 11.4. Other Incremental Update Message Types . . . . . . . . . 34 120 11.5. Requirements on Future ALTO Services to Use this Design 34 121 12. Miscellaneous Considerations . . . . . . . . . . . . . . . . 34 122 12.1. Considerations for Updates to Filtered Cost Maps . . . . 34 123 12.2. Considerations for Incremental Updates to Ordinal Mode 124 Costs . . . . . . . . . . . . . . . . . . . . . . . . . 35 125 12.3. Considerations Related to SSE Line Lengths . . . . . . . 35 126 13. Security Considerations . . . . . . . . . . . . . . . . . . . 35 127 13.1. Denial-of-Service Attacks . . . . . . . . . . . . . . . 35 128 13.2. Spoofed Control Requests . . . . . . . . . . . . . . . . 36 129 13.3. Privacy . . . . . . . . . . . . . . . . . . . . . . . . 36 130 14. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 36 131 15. References . . . . . . . . . . . . . . . . . . . . . . . . . 38 132 Appendix A. Acknowledgments . . . . . . . . . . . . . . . . . . 39 133 Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 39 135 1. Introduction 137 The Application-Layer Traffic Optimization (ALTO) [RFC7285] protocol 138 provides network related information called network information 139 resources to client applications so that clients may make informed 140 decisions in utilizing network resources. For example, an ALTO 141 server provides network and cost maps, where a network map partitions 142 the set of endpoints into a manageable number of sets each defined by 143 a Provider-Defined Identifier (PID), and a cost map provides directed 144 costs between PIDs. Given network and cost maps, an ALTO client can 145 obtain costs between endpoints by using the network map to get the 146 PID for each endpoint, and then using the cost map to get the costs 147 between those PIDs. Such costs can be used by the client to choose 148 communicating endpoints with low network costs. 150 However, the ALTO protocol does not define a mechanism to allow a 151 client to obtain updates to network information resources, other than 152 by periodically re-fetching them. In settings where an information 153 resource may be large but only parts of it may change frequently 154 (e.g., some entries of a cost map), complete re-fetching can be 155 extremely inefficient. 157 This document presents a mechanism to allow an ALTO server to push 158 incremental updates to ALTO clients. Integrating server-push and 159 incremental updates provides two benefits: (1) updates can be 160 immediate, in that the server can send updates as soon as they are 161 available; and (2) updates can be small, in that if only a small 162 section of an information resource changes, the server can send just 163 the changes. 165 While primarily intended to provide updates to GET-mode network and 166 cost maps, the mechanism defined in this document can also provide 167 updates to POST-mode ALTO services such as the endpoint property and 168 endpoint cost services. We intend that the mechanism can also 169 support new ALTO services to be defined by future extensions. We 170 discuss the requirements in Section 11.5. 172 The rest of this document is organized as follows. Section 4 gives 173 background on the basic techniques used in this design: Server-Sent 174 Events to allow server push; JSON merge patch and JSON patch to allow 175 incremental updates. With the background, Section 5 gives a non- 176 normative overview of the design. Section 6 defines individual 177 messages in an update stream, and Section 7 defines the overall 178 update stream service. Section 8 defines the update stream control 179 service. Section 9 gives several examples. Section 10 describes how 180 a client should handle incoming updates. Section 11 and Section 12 181 discuss the design decisions behind this update mechanism and other 182 considerations. The remaining sections review the security and IANA 183 considerations. 185 2. Major Changes Since Version -01 187 To RFC editor: This will be removed in the final version. 189 o Added JSON Patch as an alternative incremental delta encoding. 191 o Defined a new "stream control" resource (Section 8) to allow 192 clients to add or remove resources from a previously created 193 update stream. The ALTO server creates a new stream control 194 resource for each update stream instance, assigns a unique URI to 195 it, and sends the URI to the client as the first event in the 196 stream. 198 o The client now assigns a unique client-id to each resource in an 199 update stream. The server puts the client-id in each update event 200 for that resource (before, the server used the server's resource- 201 id). This allows a client to use one stream to get updates to two 202 different endpoint cost requests (before, that required two 203 separate streams). 205 3. Terms 207 4. Background 209 The design requires two basic techniques: server push and encoding of 210 incremental changes. Using existing techniques whenever possible, 211 this design uses SSE for server push and JSON merge patch to encode 212 incremental changes. Below we give a non-normative summary of these 213 two techniques. 215 4.1. Server-Sent Events (SSEs) 217 The following is a non-normative summary of Server-Sent Events 218 (SSEs); see [SSE] for its normative definition. 220 Server-Sent Events enable a server to send new data to a client by 221 "server-push". The client establishes an HTTP ([RFC7230], [RFC7231]) 222 connection to the server, and keeps the connection open. The server 223 continually sends messages. Each message has one or more lines, 224 where a line is terminated by a carriage-return immediately followed 225 by a new-line, a carriage-return not immediately followed by a new- 226 line, or a new-line not immediately preceded by a carriage-return. A 227 message is terminated by a blank line (two line terminators in a 228 row). 230 Each line in a message is of the form "field-name: string value". 231 Lines with a blank field-name (that is, lines which start with a 232 colon) are ignored, as are lines which do not have a colon. The 233 protocol defines three field names: event, id, and data. If a 234 message has more than one "data" line, the value of the data field is 235 the concatenation of the values on those lines. There can be only 236 one "event" or "id" line per message. The "data" field is required; 237 the others are optional. 239 Figure 1 is a sample SSE stream, starting with the client request. 240 The server sends three events and then closes the stream. 242 (Client request) 243 GET /stream HTTP/1.1 244 Host: example.com 245 Accept: text/event-stream 247 (Server response) 248 HTTP/1.1 200 OK 249 Connection: keep-alive 250 Content-Type: text/event-stream 252 event: start 253 id: 1 254 data: hello there 256 event: middle 257 id: 2 258 data: let's chat some more ... 259 data: and more and more and ... 261 event: end 262 id: 3 263 data: good bye 265 Figure 1: A Sample SSE stream. 267 4.2. JSON Merge Patch 269 4.2.1. JSON Merge Patch Encoding 271 To avoid always sending complete data, a server needs a mechanism to 272 encode incremental changes. This design uses JSON merge patch as the 273 mechanism. Below is a non-normative summary of JSON merge patch; see 274 [RFC7396] for the normative definition. 276 JSON merge patch is intended to allow applications to update server 277 resources via the HTTP PATCH method [RFC5789]. This document adopts 278 the JSON merge patch message format to encode the changes, but uses a 279 different transport mechanism. 281 Informally, a merge patch object is a JSON data structure that 282 defines how to transform one JSON value into another. Specifically, 283 JSON merge patch treats the two JSON values as trees of nested JSON 284 objects (dictionaries of name-value pairs), where the leaves are 285 values other than JSON objects (e.g., JSON arrays, strings, numbers, 286 etc.), and the path for each leaf is the sequence of keys leading to 287 that leaf. When the second tree has a different value for a leaf at 288 a path, or adds a new leaf, the merge patch tree has a leaf, at that 289 path, with the new value. When a leaf in the first tree does not 290 exist in the second tree, the merge patch tree has a leaf with a JSON 291 "null" value. The merge patch tree does not have an entry for any 292 leaf that has the same value in both versions. 294 As a result, if all leaf values are simple scalars, JSON merge patch 295 is a quite efficient representation of the change. It is less 296 efficient when leaf values are arrays, because JSON merge patch 297 replaces arrays in their entirety, even if only one entry changes. 299 Formally, the process of applying a merge patch is defined by the 300 following recursive algorithm, as specified in [RFC7396]: 302 define MergePatch(Target, Patch) { 303 if Patch is an Object { 304 if Target is not an Object { 305 Target = {} # Ignore the contents and 306 # set it to an empty Object 307 } 308 for each Name/Value pair in Patch { 309 if Value is null { 310 if Name exists in Target { 311 remove the Name/Value pair from Target 312 } 313 } else { 314 Target[Name] = MergePatch(Target[Name], Value) 315 } 316 } 317 return Target 318 } else { 319 return Patch 320 } 321 } 323 Note that null as the value of a name/value pair will delete the 324 element with "name" in the original JSON value. 326 4.2.2. Merge Patch ALTO Messages 328 Both as examples of JSON merge patch and demonstration of feasibility 329 to apply JSON merge patch to ALTO, we look at application of JSON 330 merge patch to two key ALTO messages. 332 4.2.2.1. Merge Patch Network Map Messages 334 Section 11.2.1.6 of [RFC7285] defines the format of a network map 335 message. Here is a simple example: 337 { 338 "meta" : { 339 "vtag": { 340 "resource-id" : "my-network-map", 341 "tag" : "da65eca2eb7a10ce8b059740b0b2e3f8eb1d4785" 342 } 343 }, 344 "network-map" : { 345 "PID1" : { 346 "ipv4" : [ "192.0.2.0/24", "198.51.100.0/25" ] 347 }, 348 "PID2" : { 349 "ipv4" : [ "198.51.100.128/25" ] 350 }, 351 "PID3" : { 352 "ipv4" : [ "0.0.0.0/0" ], 353 "ipv6" : [ "::/0" ] 354 } 355 } 356 } 358 When applied to that message, the following merge patch update 359 message adds the ipv6 prefix "2001:db8:8000::/33" to "PID1", deletes 360 "PID2", and assigns a new "tag" to the network map: 362 { 363 "meta" : { 364 "vtag" : { 365 "tag" : "a10ce8b059740b0b2e3f8eb1d4785acd42231bfe" 366 } 367 }, 368 "network-map": { 369 "PID1" : { 370 "ipv6" : [ "2001:db8:8000::/33" ] 371 }, 372 "PID2" : null 373 } 374 } 376 Here is the updated network map: 378 { 379 "meta" : { 380 "vtag": { 381 "resource-id" : "my-network-map", 382 "tag" : "a10ce8b059740b0b2e3f8eb1d4785acd42231bfe" 383 } 384 }, 385 "network-map" : { 386 "PID1" : { 387 "ipv4" : [ "192.0.2.0/24", "198.51.100.0/25" ], 388 "ipv6" : [ "2001:db8:8000::/33" ] 389 }, 390 "PID3" : { 391 "ipv4" : [ "0.0.0.0/0" ], 392 "ipv6" : [ "::/0" ] 393 } 394 } 395 } 397 4.2.2.2. Merge Patch Cost Map Messages 399 Section 11.2.3.6 of [RFC7285] defines the format of a cost map 400 message. Here is a simple example: 402 { 403 "meta" : { 404 "dependent-vtags" : [ 405 {"resource-id": "my-network-map", 406 "tag": "a10ce8b059740b0b2e3f8eb1d4785acd42231bfe" 407 } 408 ], 409 "cost-type" : { 410 "cost-mode" : "numerical", 411 "cost-metric": "routingcost" 412 } 413 }, 414 "cost-map" : { 415 "PID1": { "PID1": 1, "PID2": 5, "PID3": 10 }, 416 "PID2": { "PID1": 5, "PID2": 1, "PID3": 15 }, 417 "PID3": { "PID1": 20, "PID2": 15 } 418 } 419 } 421 The following merge patch message updates the example cost map so 422 that PID1->PID2 is 9 instead of 5, PID3->PID1 is no longer available, 423 and PID3->PID3 is now defined as 1: 425 { 426 "cost-map" : { 427 "PID1" : { "PID2" : 9 }, 428 "PID3" : { "PID1" : null, "PID3" : 1 } 429 } 430 } 432 Here is the updated cost map: 434 { 435 "meta" : { 436 "dependent-vtags" : [ 437 {"resource-id": "my-network-map", 438 "tag": "a10ce8b059740b0b2e3f8eb1d4785acd42231bfe" 439 } 440 ], 441 "cost-type" : { 442 "cost-mode" : "numerical", 443 "cost-metric": "routingcost" 444 } 445 }, 446 "cost-map" : { 447 "PID1": { "PID1": 1, "PID2": 9, "PID3": 10 }, 448 "PID2": { "PID1": 5, "PID2": 1, "PID3": 15 }, 449 "PID3": { "PID2": 15, "PID3": 1 } 450 } 451 } 453 4.3. JSON Patch 455 4.3.1. JSON Patch Encoding 457 An issue of JSON merge patch is that it does not handle array changes 458 well. JSON Patch [RFC6902] defines a set of operators to modify a 459 JSON object. Below is a non-normative description of JSON patch; see 460 [RFC6902] for the normative definition. 462 4.3.2. JSON Patch ALTO Messages 464 Consider the original network map example in Section 4.2.2.1. Assume 465 that the incremental change is that 192.0.2.0/24 is removed from 466 PID1. Using JSON patch, the patch will be: 468 [ 469 {"op": "replace", 470 "path": "/meta/vtag/tag", 471 "value" : "a10ce8b059740b0b2e3f8eb1d4785acd42231bfe"}, 472 {"op": "remove", 473 "path": "/network-map/PID1/ipv4/1"} 474 ] 476 5. Overview of Approach 478 With the background, we now gives a non-normative overview of the 479 update mechanism to be defined in this document. 481 The building block of the update mechanism defined in this document 482 is update stream resources (defined in Section 7), where each update 483 stream resource (or update stream for short) is a POST-mode service 484 through which an ALTO server returns a continuous sequence of update 485 messages (defined in Section 6) to an ALTO client. An update stream 486 can provide updates to both GET-mode resources, such as ALTO network 487 and cost maps, and POST-mode resources, such as ALTO endpoint 488 property services. 490 Although an update stream may update one or more ALTO resources, each 491 update message updates only one resource, and is sent as a Server- 492 Sent Event (SSE), as defined by [SSE]. An update message is either a 493 full replacement or an incremental change. A full-replacement update 494 uses the JSON message format defined by the ALTO protocol. There can 495 be multiple incremental update mechanisms. The current design 496 achieves incremental-update using JSON merge patch ([RFC7396]) or 497 JSON patch ([RFC6902]) to describe the changes to the resource. 498 Future documents may define additional mechanisms for delta encoding. 499 The ALTO server decides when to send update messages, and whether to 500 send full replacements or incremental updates. These decisions can 501 vary from resource to resource and from update to update. 503 An ALTO server may offer any number of update stream resources, for 504 any subset of the server's resources. An ALTO server's Information 505 Resource Directory (IRD) defines the update stream resources, and 506 declares the set of resources for which each update stream provides 507 updates. The server selects the resource set for each stream. It is 508 recommended that if a resource depends on one or more other 509 resource(s) (indicated with the "uses" attribute defined in 510 [RFC7285]), these other resource(s) should also be part of that 511 stream. Thus the update stream for a cost map should also provide 512 updates for the network map on which that cost map depends. 514 When an ALTO client requests an update stream resource, the client 515 establishes a new persistent connection to the server. The server 516 responds by sending an event with the URI of a stream-control 517 resource for this update stream. The control URI allows a client to 518 modify the newly-created update stream. For example, the client can 519 ask the server to send update events for additional resources, to 520 stop sending update events for previously requested resources, or to 521 gracefully stop and close the update stream altogether. 523 A client may request any number of update streams simultaneously. 524 Because each update stream consumes resources on the server, a server 525 may require client authorization/authentication, limit the number of 526 open update streams, close inactive streams, or redirect a client to 527 another server. 529 6. Update Stream Messages: Update and Control Events 531 We now define the details of ALTO incremental update. Specifically, 532 an update stream consists of a stream of update events (Section 6.2) 533 and control events (Section 6.3). 535 6.1. ALTO Event Format 537 Update and control events have the same basic structure. The data 538 field is a JSON object, and the event field contains the media type 539 of the data field, and an optional client id. Update events use the 540 client id to identify the ALTO resource to which the update message 541 applies. Client ids MUST follow the rules for ALTO ResourceIds (see 542 {10.2} of [RFC7285]. Client ids MUST be unique within an update 543 stream, but need not be globally unique. For example, if a client 544 requests updates for both a cost map and its network map, the client 545 might assign id "1" to the network map and "2" to the cost map. 546 Alternatively, the client could use the ALTO resource ids for those 547 two maps. 549 JSON specifications use the type ClientId for a client-id. 551 The two sub-fields of the event field are encoded as comma-separated 552 strings: 554 media-type [ ',' client-id ] 556 Note that media type names may not contain a comma (character code 557 0x2c). 559 Note that an update stream does not use the SSE "id" field. 561 6.2. ALTO Update Events 563 An update event is sent when a monitored resource changes. The data 564 is either a complete specification of the resource, or else a patch 565 object (either JSON merge patch or JSON patch) describing the changes 566 from the last version. We will refer to these as full-replacement 567 and patch messages, respectively. The data objects in full- 568 replacement messages are defined by [RFC7285]; examples are network 569 and cost map messages. They have the media types defined in that 570 document. The data objects in merge patch messages are defined by 571 [RFC7396], and they have the media type "application/merge- 572 patch+json", as defined by [RFC7396]. The data objects in patch 573 messages are defined by [RFC6902], and they have the media type 574 "application/json-patch+json", as defined by [RFC6902]. 576 Figure 2 shows some examples of ALTO update events: 578 event: application/alto-networkmap+json,1 579 data: { ... full network map message ... } 581 event: application/alto-costmap+json,2 582 data: { ... full cost map message ... } 584 event: application/merge-patch+json,2 585 data: { ... merge patch update for the cost map ... } 587 Figure 2: Examples of ALTO update events. 589 6.3. ALTO Control Events 591 Control events have the media type "application/alto- 592 updatestreamcontrol+json", and the data is of type 593 UpdateStreamControlEvent: 595 object { 596 [String control-uri;] 597 [String remove<1..*>;] 598 } UpdateStreamControlEvent; 600 The "control-uri" field is the URI of the stream control resource for 601 this update stream (see Section 8). The ALTO server MUST send a 602 control event with that URI as the first event in an update stream. 604 The "remove" field is a list of client-ids of resources for which the 605 server will no longer send updates. The server sends this event 606 after processing a stream control request to remove those resources 607 (Section 7.6.2). 609 7. Update Stream 611 An update stream returns a stream of SSE messages, as defined in 612 Section 6. An ALTO server's IRD (Information Resource Directory) MAY 613 define one or more update stream resources, which clients use to 614 request new update stream instances. 616 When a server creates a new update stream, it also creates a new 617 stream control service for that update stream. A client uses the 618 stream control service to remove resources from the update stream 619 instance, or to request updates for additional resources. A client 620 cannot obtain the stream control service through the IRD. Instead, 621 the first event that the server sends to the client has the URI for 622 the associated control service (see Section 6.3. 624 Section 8 describes the stream control service. 626 7.1. Media Type 628 The media type of an ALTO update stream resource is "text/event- 629 stream", as defined by [SSE]. 631 7.2. HTTP Method 633 An ALTO update stream is requested using the HTTP POST method. 635 7.3. Accept Input Parameters 637 An ALTO client specifies the parameters for the new update stream by 638 sending an HTTP POST body with the media type "application/alto- 639 updatestreamparams+json". That body contains a JSON Object of type 640 UpdateStreamReq, where: 642 object { 643 [AddUpdatesReq add;] 644 [ClientId remove<0..*>;] 645 } UpdateStreamReq; 647 object-map { 648 ClientId -> AddUpdateReq; 649 } AddUpdatesReq; 651 object { 652 String resource-id; 653 [String tag;] 654 [Boolean incremental-updates;] 655 [Object input;] 656 } AddUpdateReq; 658 The "add" field specifies the resources for which the client wants 659 updates, and has one entry for each resource. The client creates a 660 unique client-id (Section 6.1) for each such resource, and uses those 661 client-ids as the keys in the "add" field. 663 An update stream request MUST have an "add" field specifying one or 664 more resources. If it does not, the server MUST return an 665 E_INVALID_FIELD_VALUE error response (see Section 8.5.2 of 666 [RFC7285]), and MUST close the stream without sending any events. 668 The "resource-id" field is the resource-id of an ALTO resource, and 669 MUST be in the update stream's "uses" list (see Section 7.5). If any 670 resource-id is invalid, or is not associated with this update stream, 671 the server MUST return an E_INVALID_FIELD_VALUE error response (see 672 Section 8.5.2 of [RFC7285]), and MUST close the stream without 673 sending any events. 675 If the resource-id is a GET-mode resource with a version tag (or 676 "vtag"), as defined in Sections 6.3 and 10.3 of [RFC7285], and if the 677 client has previously retrieved a version of that resource from the 678 server, the client MAY set the "tag" field to the tag part of the 679 client's version of that resource. If that version is not current, 680 the server MUST send a full-replacement update before sending any 681 incremental updates, as described in Section 7.6.2. If that version 682 is still current, the ALTO server MAY omit the initial full- 683 replacement update. 685 If the "incremental-updates" field for a resource-id is "true", the 686 server MAY send incremental update events for this resource-id 687 (assuming the server supports incremental updates for that resource; 688 see Section 7.4). If the "incremental-updates" field is "false", the 689 ALTO server MUST NOT send incremental update events for that 690 resource. In this case, whenever a change occurs, the server MUST 691 send a full-replacement update instead of an incremental update. The 692 server MAY wait until more changes are available, and send a single 693 full-replacement update with those changes. Thus an ALTO client 694 which declines to accept incremental updates may not get updates as 695 quickly as a client which does. 697 The default for "incremental-updates" is "true", so to suppress 698 incremental updates, the client MUST explicitly set "incremental- 699 updates" to "false". Note that the client cannot suppress full- 700 replacement update events. 702 If the resource is a POST-mode service which requires input, the 703 client MUST set the "input" field to a JSON Object with the 704 parameters that resource expects. If the "input" field is missing or 705 invalid, the ALTO server MUST return the same error response that 706 that resource would return for missing or invalid input (see 707 [RFC7285]). In this case, the server MUST close the update stream 708 without sending any events. If the inputs for several POST-mode 709 resources are missing or invalid, the server MUST pick one error 710 response and return it. 712 The "remove" field is used in stream control requests (see 713 Section 8), and is not allowed in the update stream request. If the 714 "remove" field exists, the server MUST return an 715 E_INVALID_FIELD_VALUE error response (see Section 8.5.2 of 716 [RFC7285]), and MUST close the stream without sending any events. 718 7.4. Capabilities 720 The capabilities are defined by an object of type 721 UpdateStreamCapabilities: 723 object { 724 IncrementalUpdateMediaTypes incremental-update-media-types; 725 } UpdateStreamCapabilities; 727 object-map { 728 ResourceID -> String; 729 } IncrementalUpdateMediaTypes; 731 If this update stream can provide incremental update events for a 732 resource, the "incremental-update-media-types" field has an entry for 733 that resource-id, and the value is the media-type of the incremental 734 update message. Normally this will be "application/merge- 735 patch+json", "application/json-patch+json", or "application/merge- 736 patch+json,application/json-patch+json", because, as described in 737 Section 6, they are the only incremental update event types defined 738 by this document. However future extensions may define other types 739 of incremental updates. 741 7.5. Uses 743 The "uses" attribute MUST be an array with the resource-ids of every 744 resource for which this stream can provide updates. 746 This set may be any subset of the ALTO server's resources, and may 747 include resources defined in linked IRDs. However, it is RECOMMENDED 748 that the ALTO server select a set that is closed under the resource 749 dependency relationship. That is, if an update stream's "uses" set 750 includes resource R1, and resource R1 depends on ("uses") resource 751 R0, then the Update Stream's "uses" set should include R0 as well as 752 R1. For example, an update stream for a cost map SHOULD also provide 753 updates for the network map upon which that cost map depends. 755 7.6. Response 757 The response is a stream of SSE update events. Section 6 defines the 758 events, and [SSE] defines how they are encoded into a stream. 760 An ALTO server SHOULD send updates only when the underlying values 761 change. However, it may be difficult for a server to guarantee that 762 in all circumstances. Therefore a client MUST NOT assume that an SSE 763 update event represents an actual change. 765 There are additional requirements on the server's response, as 766 described below. 768 7.6.1. Keep-Alive Messages 770 In an SSE stream, any line which starts with a colon (U+003A) 771 character is a comment, and an ALTO client MUST ignore that line 772 ([SSE]). As recommended in [SSE], an ALTO server SHOULD send a 773 comment line (or an event) every 15 seconds to prevent clients and 774 proxy servers from dropping the HTTP connection. 776 7.6.2. Event Sequence Requirements 778 o The first event MUST be a control event with the URI of the stream 779 control service (Section 8) for this update stream (Section 6.3). 781 o As soon as possible after the client initiates the connection, the 782 ALTO server MUST send a full-replacement update event for each 783 resource-id requested by the client. The only exception is for a 784 GET-mode resource with a version tag. In this case the server MAY 785 omit the initial full-replacement event for that resource if the 786 "tag" field the client provided for that resource-id matches the 787 tag of the server's current version. 789 o If this stream provides updates for resource-ids R0 and R1, and if 790 R1 depends on R0, then the ALTO server MUST send the update for R0 791 before sending the related update for R1. For example, suppose a 792 stream provides updates to a network map and its dependent cost 793 maps. When the network map changes, the ALTO server MUST send the 794 network map update before sending the cost map updates. 796 o If this stream provides updates for resource-ids R0 and R1, and if 797 R1 depends on R0, then the ALTO server SHOULD send an update for 798 R1 as soon as possible after sending the update for R0. For 799 example, when a network map changes, the ALTO server SHOULD send 800 update events for the dependent cost maps as soon as possible 801 after the update event for the network map. 803 o When the client uses the stream control service to stop updates 804 for one or more resources (Section 8), the ALTO server MUST send a 805 control event (Section 6.3) whose "remove" field has the client- 806 ids of those resources. If the client uses the stream control 807 service to terminate all active resources and close the stream, 808 the server MUST send a control event whose "remove" field has the 809 client-ids of all active resources. 811 7.6.3. Cross-Stream Consistency Requirements 813 If several clients create multiple update streams for updates to the 814 same resource, the server MUST send the same updates to all of them. 815 However, the server MAY pack data items into different patch events, 816 as long as the net result of applying those updates is the same. 818 For example, suppose two different clients create update streams for 819 the same cost map, and suppose the ALTO server processes three 820 separate cost point updates with a brief pause between each update. 821 The server MUST send all three new cost points to both clients. But 822 the server MAY send a single patch event (with all three cost points) 823 to one client, while sending three separate patch events (with one 824 cost point per event) to the other client. 826 A server MAY offer several different update stream resources that 827 provide updates to the same underlying resource (that is, a resource- 828 id may appear in the "uses" field of more than one update stream 829 resource). In this case, those update stream resources MUST return 830 the same update data. 832 8. Update Stream Control 834 An update stream control service allows a client to remove resources 835 from the set of resources that are monitored by an update stream, or 836 add additional resources to that set. The service also allows a 837 client to gracefully shutdown an update stream. 839 The stream control service is not obtained from the ALTO server's 840 IRD. Instead, when a client requests a new update stream, the server 841 creates a new control service for that stream, and sends its URI to 842 the client as the first event in the update stream (Section 7.6.2). 844 As described below, each control request adds resources to the set of 845 monitored resources, or removes previously added resources, or does 846 both. Each control request is a separate HTTP request; the client 847 MAY NOT stream multiple control requests in one HTTP request. 848 However, if the client and server support HTTP Keep-Alive 849 ([RFC7230]), the client MAY send multiple HTTP requests on the same 850 TCP/IP connection. 852 8.1. URI 854 The URI for a stream control service, by itself, MUST uniquely 855 specify the update stream instance which it controls. The server 856 MUST NOT use other properties of an HTTP request, such as cookies or 857 the client's IP address, to determine the update stream. 858 Furthermore, a server MUST NOT re-use a control service URI once the 859 associated update stream has been closed. 861 The client MUST evaluate a non-absolute control URI (for example, a 862 URI without a host, or with a relative path) in the context of the 863 URI used to create the update stream. The controller's host MAY be 864 different from the update stream's host. 866 It is expected that the server will assign a unique stream id to each 867 update stream instance, and will embed that id in the associated 868 stream control URI. However, the exact mechanism is left to the 869 server. Clients MUST NOT attempt to deduce a stream id from the 870 control URI. 872 To prevent an attacker from forging a stream control URI and sending 873 bogus requests to disrupt other update streams, stream control URIs 874 SHOULD contain sufficient random redundancy to make it difficult to 875 guess valid URIs. 877 8.2. Media Type 879 An ALTO stream control response does not have a specific media type. 880 If a request is successful, the server returns an HTTP "204 No 881 Content" response. If a request is unsuccessful, the server returns 882 an ALTO error response (Section 8.5.2 of [RFC7285]) 884 8.3. HTTP Method 886 An ALTO update stream control request uses the POST method. 888 8.4. Accept Input Parameters 890 A stream control service accepts the same input media type and input 891 parameters as the update stream service (Section 7.3). The only 892 difference is that a stream control service also accepts the "remove" 893 field. 895 If specified, the "remove" field is an array of client-ids the client 896 previously added to this update stream. An empty "remove" array is 897 equivalent to a list of all currently active resources; the server 898 responds by removing all resources and closing the stream. 900 A client MAY use the "add" field to add additional resources. 901 However, the client MUST assign a unique client-id to each resource. 902 Client-ids MUST be unique over the lifetime of this update stream: a 903 client MUST NOT re-use a previously removed client-id. 905 If a request has any error, the server MUST NOT add or remove any 906 resources from the associated update stream. In particular, 908 o Each "add" request must satisfy the requirements in Section 7.3. 909 If not, the server MUST return the error response defined in 910 Section 7.3. 912 o As described in Section 7.6.2, for each "add" request, the ALTO 913 server MUST send a full-replacement update event for that resource 914 before sending any incremental updates. The only exception is for 915 a GET-mode resource with a version tag. In this case the server 916 MAY omit the full-replacement event for that resource if the "tag" 917 field the client provided matches the server's current version. 919 o The server MUST return an E_INVALID_FIELD_VALUE error if a client- 920 id in the "remove" field was not added in a prior request. Thus 921 it is illegal to "add" and "remove" the same client-id in the same 922 request. However, it is legal to remove a client-id twice. 924 o The server MUST return an E_INVALID_FIELD_VALUE error if a client- 925 id in the "add" field has been used before in this stream. 927 o The server MUST return an E_INVALID_FIELD_VALUE error if the 928 request has a non-empty "add" field and a "remove" field with an 929 empty list of client-ids (to replace all active resources with a 930 new set, the client MUST explicitly enumerate the client-ids to be 931 removed). 933 o If the associated update stream has been closed, the server MUST 934 return either an ALTO E_INVALID_FIELD_VALUE error, or else an HTTP 935 error, such as "404 Not Found". 937 8.5. Capabilities & Uses 939 None (Stream control services do not appear in the IRD). 941 8.6. Response 943 If a request is successful, the server returns an HTTP "204 No 944 Content" response with no data. If there are any errors, the server 945 MUST return the appropriate error code, and MUST NOT add or remove 946 any resources from the update stream. Thus control requests are 947 atomic: they cannot partially succeed. 949 The server MUST process the "add" field before the "remove" field. 950 If the request removes all active resources without adding any 951 additional resources, the server MUST close the update stream. Thus 952 an update stream cannot have zero resources. 954 Whenever a server removes resources as a result of a stream control 955 request, the server MUST send the corresponding "remove" Control 956 Events (Section 6.3) on the update stream. If one control request 957 removes several resources, the server MAY send one Control Event for 958 all those resources, or a separate event for each removed resource, 959 or any combination thereof. 961 9. Examples 963 9.1. Example: Simple Network and Cost Map Updates 965 Here is an example of a client's request and the server's immediate 966 response, using the update stream resource "update-my-costs" defined 967 in the IRD in Section 9.4. The client requests updates for the 968 network map and "routingcost" cost map, but not for the "hopcount" 969 cost map. The client uses the server's resource-ids as the client- 970 ids. Because the client does not provide a "tag" for the network 971 map, the server must send a full update for the network map as well 972 as for the cost map. The client does not set "incremental-updates" 973 to "false", so it defaults to "true". Thus server will send patch 974 updates for the cost map, but not for the network map, because this 975 update stream resource does not provide incremental updates for the 976 network map. 978 POST /updates/costs HTTP/1.1 979 Host: alto.example.com 980 Accept: text/event-stream,application/alto-error+json 981 Content-Type: application/alto-updatestreamparams+json 982 Content-Length: ### 984 { "add": { 985 "my-network-map": { 986 "resource-id": "my-network-map" 987 }, 988 "my-routingcost-map": { 989 "resource-id": "my-routingcost-map" 990 } 991 } 992 } 993 HTTP/1.1 200 OK 994 Connection: keep-alive 995 Content-Type: text/event-stream 997 event: application/alto-updatestreamcontrol+json 998 data: {"control-uri": 999 data: "http://alto.example.com/updates/streams/3141592653589"} 1001 event: application/alto-networkmap+json,my-network-map 1002 data: { ... full network map message ... } 1004 event: application/alto-costmap+json,my-routingcost-map 1005 data: { ... full routingcost cost map message ... } 1007 After sending those events immediately, the ALTO server will send 1008 additional events as the maps change. For example, the following 1009 represents a small change to the cost map: 1011 event: application/merge-patch+json,my-routingcost-map 1012 data: {"cost-map": {"PID1" : {"PID2" : 9}}} 1014 If a major change to the network map occurs, the ALTO server MAY 1015 choose to send full network and cost map messages rather than patch 1016 messages: 1018 event: application/alto-networkmap+json,my-network-map 1019 data: { ... full network map message ... } 1021 event: application/alto-costmap+json,my-routingcost-map 1022 data: { ... full cost map message ... } 1024 9.2. Example: Advanced Network and Cost Map Updates 1026 This example is similar to the previous one, except that the client 1027 requests updates for the "hopcount" cost map as well as the 1028 "routingcost" cost map, and provides the current version tag of the 1029 network map, so the server is not required to send the full network 1030 map update event at the beginning of the stream. In this example, 1031 the client uses the client-ids "net", "routing" and "hops" for those 1032 resources. The ALTO server sends the stream id and the full cost 1033 maps, followed by updates for the network map and cost maps as they 1034 become available: 1036 POST /updates/costs HTTP/1.1 1037 Host: alto.example.com 1038 Accept: text/event-stream,application/alto-error+json 1039 Content-Type: application/alto-updatestreamparams+json 1040 Content-Length: ### 1042 { "add": { 1043 "net": { 1044 "resource-id": "my-network-map". 1045 "tag": "a10ce8b059740b0b2e3f8eb1d4785acd42231bfe" 1046 }, 1047 "routing": { 1048 "resource-id": "my-routingcost-map" 1049 }, 1050 "hops": { 1051 "resource-id": "my-hopcount-map" 1052 } 1053 } 1054 } 1056 HTTP/1.1 200 OK 1057 Connection: keep-alive 1058 Content-Type: text/event-stream 1060 event: application/alto-updatestreamcontrol+json 1061 data: {"control-uri": 1062 data: "http://alto.example.com/updates/streams/2718281828459"} 1064 event: application/alto-costmap+json,routing 1065 data: { ... full routingcost cost map message ... } 1067 event: application/alto-costmap+json,hops 1068 data: { ... full hopcount cost map message ... } 1070 (pause) 1072 event: application/merge-patch+json,routing 1073 data: {"cost-map": {"PID2" : {"PID3" : 31}}} 1075 event: application/merge-patch+json,hops 1076 data: {"cost-map": {"PID2" : {"PID3" : 4}}} 1078 If the client wishes to stop receiving updates for the "hopcount" 1079 cost map, the client can send a "remove" request on the stream 1080 control URI: 1082 POST /updates/streams/2718281828459" HTTP/1.1 1083 Host: alto.example.com 1084 Accept: text/plain,application/alto-error+json 1085 Content-Type: application/alto-updatestreamparams+json 1086 Content-Length: ### 1088 { 1089 "remove": [ "hops" ] 1090 } 1092 HTTP/1.1 204 No Content 1093 Content-Length: 0 1095 (stream closed without sending data content) 1097 The ALTO server sends a "remove" control event on the original 1098 request stream to inform the client that updates are stopped for that 1099 resource: 1101 event: application/alto-updatestreamcontrol+json 1102 data: { "remove": ["hops"] } 1104 If the client no longer needs any updates, and wishes to shut the 1105 update stream down gracefully, the client can send a "remove" request 1106 with an empty array: 1108 POST /updates/streams/2718281828459" HTTP/1.1 1109 Host: alto.example.com 1110 Accept: text/plain,application/alto-error+json 1111 Content-Type: application/alto-updatestreamparams+json 1112 Content-Length: ### 1114 { 1115 "remove": [ ] 1116 } 1118 HTTP/1.1 204 No Content 1119 Content-Length: 0 1121 (stream closed without sending data content) 1123 The ALTO server sends a final "remove" control event on the original 1124 request stream to inform the client that all updates are stopped, and 1125 then closes the stream: 1127 event: application/alto-updatestreamcontrol+json 1128 data: { "remove": ["net", "routing"] } 1130 (server closes stream) 1132 9.3. Example: Endpoint Property Updates 1134 As another example, here is how a client can request updates for the 1135 property "priv:ietf-bandwidth" for one set of endpoints, and 1136 "priv:ietf-load" for another. The ALTO server immediately sends 1137 full-replacement messages with the property values for all endpoints. 1138 After that, the server sends update events for the individual 1139 endpoints as their property values change. 1141 POST /updates/properties HTTP/1.1 1142 Host: alto.example.com 1143 Accept: text/event-stream 1144 Content-Type: application/alto-updatestreamparams+json 1145 Content-Length: ### 1147 { "add": { 1148 "props-1": { 1149 "resource-id": "my-props", 1150 "input": { 1151 "properties" : [ "priv:ietf-bandwidth" ], 1152 "endpoints" : [ 1153 "ipv4:198.51.100.1", 1154 "ipv4:198.51.100.2", 1155 "ipv4:198.51.100.3" 1156 ] 1157 } 1158 }, 1159 "props-2": { 1160 "resource-id": "my-props", 1161 "input": { 1162 "properties" : [ "priv:ietf-load" ], 1163 "endpoints" : [ 1164 "ipv6:2001:db8:100::1", 1165 "ipv6:2001:db8:100::2", 1166 "ipv6:2001:db8:100::3", 1167 ] 1168 } 1169 }, 1170 } 1171 } 1172 HTTP/1.1 200 OK 1173 Connection: keep-alive 1174 Content-Type: text/event-stream 1176 event: application/alto-updatestreamcontrol+json 1177 data: {"control-uri": 1178 data: "http://alto.example.com/updates/streams/1414213562373"} 1180 event: application/alto-endpointprops+json,props-1 1181 data: { "endpoint-properties": { 1182 data: "ipv4:198.51.100.1" : { "priv:ietf-bandwidth": "13" }, 1183 data: "ipv4:198.51.100.2" : { "priv:ietf-bandwidth": "42" }, 1184 data: "ipv4:198.51.100.3" : { "priv:ietf-bandwidth": "27" } 1185 data: } } 1187 event: application/alto-endpointprops+json,props-2 1188 data: { "endpoint-properties": { 1189 data: "ipv6:2001:db8:100::1" : { "priv:ietf-load": "8" }, 1190 data: "ipv6:2001:db8:100::2" : { "priv:ietf-load": "2" }, 1191 data: "ipv6:2001:db8:100::3" : { "priv:ietf-load": "9" } 1192 data: } } 1194 (pause) 1196 event: application/merge-patch+json,props-1 1197 data: { "endpoint-properties": 1198 data: {"ipv4:198.51.100.1" : {"priv:ietf-bandwidth": "3"}} 1199 data: } 1201 (pause) 1203 event: application/merge-patch+json,props-2 1204 data: { "endpoint-properties": 1205 data: {"ipv6:2001:db8:100::3" : {"priv:ietf-load": "7"}} 1206 data: } 1208 If the client needs the "bandwidth" property for additional 1209 endpoints, the client can send a "add" request on the stream control 1210 URI: 1212 POST /updates/streams/1414213562373" HTTP/1.1 1213 Host: alto.example.com 1214 Accept: text/plain,application/alto-error+json 1215 Content-Type: application/alto-updatestreamparams+json 1216 Content-Length: ### 1218 { "add": { 1219 "props-3": { 1220 "resource-id": "my-props", 1221 "input": { 1222 "properties" : [ "priv:ietf-bandwidth" ], 1223 "endpoints" : [ 1224 "ipv4:198.51.100.4", 1225 "ipv4:198.51.100.5", 1226 ] 1227 } 1228 }, 1229 "props-4": { 1230 "resource-id": "my-props", 1231 "input": { 1232 "properties" : [ "priv:ietf-load" ], 1233 "endpoints" : [ 1234 "ipv6:2001:db8:100::4", 1235 "ipv6:2001:db8:100::5", 1236 ] 1237 } 1238 }, 1239 } 1240 } 1242 HTTP/1.1 204 No Content 1243 Content-Length: 0 1245 (stream closed without sending data content) 1247 The ALTO server sends full replacement events for the two new 1248 resources, followed by incremental updates for all four requests as 1249 they arrive: 1251 event: application/alto-endpointprops+json,props-3 1252 data: { "endpoint-properties": { 1253 data: "ipv4:198.51.100.4" : { "priv:ietf-bandwidth": "25" }, 1254 data: "ipv4:198.51.100.5" : { "priv:ietf-bandwidth": "31" }, 1255 data: } } 1257 event: application/alto-endpointprops+json,props-4 1258 data: { "endpoint-properties": { 1259 data: "ipv6:2001:db8:100::4" : { "priv:ietf-load": "6" }, 1260 data: "ipv6:2001:db8:100::5" : { "priv:ietf-load": "4" }, 1261 data: } } 1263 (pause) 1265 event: application/merge-patch+json,props-3 1266 data: { "endpoint-properties": 1267 data: {"ipv4:198.51.100.5" : {"priv:ietf-bandwidth": "15"}} 1268 data: } 1270 (pause) 1272 event: application/merge-patch+json,props-2 1273 data: { "endpoint-properties": 1274 data: {"ipv6:2001:db8:100::2" : {"priv:ietf-load": "9"}} 1275 data: } 1277 (pause) 1279 event: application/merge-patch+json,props-4 1280 data: { "endpoint-properties": 1281 data: {"ipv6:2001:db8:100::4" : {"priv:ietf-load": "3"}} 1282 data: } 1284 9.4. IRD Example 1286 Here is an example of an IRD that offers two update stream services. 1287 The first provides updates for the network map, the "routingcost" and 1288 "hopcount" cost maps, and a filtered cost map resource. The second 1289 update stream provides updates to the endpoint properties service. 1291 Note that this IRD defines two filtered cost map resources. They use 1292 the same cost types, but "my-filtered-cost-map" accepts cost 1293 constraint tests, while "my-simple-filtered-cost-map" does not. To 1294 avoid the issues discussed in Section 12.1, the update stream 1295 provides updates for the second, but not the first. 1297 "my-network-map": { 1298 "uri": "http://alto.example.com/networkmap", 1299 "media-type": "application/alto-networkmap+json", 1300 }, 1301 "my-routingcost-map": { 1302 "uri": "http://alto.example.com/costmap/routingcost", 1303 "media-type": "application/alto-costmap+json", 1304 "uses": ["my-networkmap"], 1305 "capabilities": { 1306 "cost-type-names": ["num-routingcost"] 1307 } 1308 }, 1309 "my-hopcount-map": { 1310 "uri": "http://alto.example.com/costmap/hopcount", 1311 "media-type": "application/alto-costmap+json", 1312 "uses": ["my-networkmap"], 1313 "capabilities": { 1314 "cost-type-names": ["num-hopcount"] 1315 } 1316 }, 1317 "my-filtered-cost-map": { 1318 "uri": "http://alto.example.com/costmap/filtered/constraints", 1319 "media-type": "application/alto-costmap+json", 1320 "accepts": "application/alto-costmapfilter+json", 1321 "uses": ["my-networkmap"], 1322 "capabilities": { 1323 "cost-type-names": ["num-routingcost", "num-hopcount"], 1324 "cost-constraints": true 1325 } 1326 }, 1327 "my-simple-filtered-cost-map": { 1328 "uri": "http://alto.example.com/costmap/filtered/simple", 1329 "media-type": "application/alto-costmap+json", 1330 "accepts": "application/alto-costmapfilter+json", 1331 "uses": ["my-networkmap"], 1332 "capabilities": { 1333 "cost-type-names": ["num-routingcost", "num-hopcount"], 1334 "cost-constraints": false 1335 } 1336 }, 1337 "my-props": { 1338 "uri": "http://alto.example.com/properties", 1339 "media-type": "application/alto-endpointprops+json", 1340 "accepts": "application/alto-endpointpropparams+json", 1341 "capabilities": { 1342 "prop-types": ["priv:ietf-bandwidth"] 1343 } 1344 }, 1345 "update-my-costs": { 1346 "uri": "http://alto.example.com/updates/costs", 1347 "media-type": "text/event-stream", 1348 "accepts": "application/alto-updatestreamparams+json", 1349 "uses": [ 1350 "my-network-map", 1351 "my-routingcost-map", 1352 "my-hopcount-map", 1353 "my-simple-filtered-cost-map" 1354 ], 1355 "capabilities": { 1356 "incremental-update-media-types": { 1357 "my-routingcost-map": application/merge-patch+json", 1358 "my-hopcount-map": "application/merge-patch+json" 1359 } 1360 } 1361 }, 1362 "update-my-props": { 1363 "uri": "http://alto.example.com/updates/properties", 1364 "media-type": "text/event-stream", 1365 "uses": [ "my-props" ], 1366 "accepts": "application/alto-updatestreamparams+json", 1367 "capabilities": { 1368 "incremental-update-media-types": { 1369 "my-props": "application/merge-patch+json" 1370 } 1371 } 1372 } 1374 10. Client Actions When Receiving Update Messages 1376 In general, when a client receives a full-replacement update message 1377 for a resource, the client should replace the current version with 1378 the new version. When a client receives a patch update message for a 1379 resource, the client should apply those patches to the current 1380 version of the resource. 1382 However, because resources can depend on other resources (e.g., cost 1383 maps depend on network maps), an ALTO client MUST NOT use a dependent 1384 resource if the resource on which it depends has changed. There are 1385 at least two ways a client can do that. We will illustrate these 1386 techniques by referring to Network and cost map messages, although 1387 these techniques apply to any dependent resources. 1389 Note that when a network map changes, the ALTO server MUST send the 1390 network map update message before sending the updates for the 1391 dependent cost maps (see Section 7.6.2). 1393 One approach is for the ALTO client to save the network map update 1394 message in a buffer, and continue to use the previous network map, 1395 and the associated cost maps, until the client receives the update 1396 messages for all dependent cost maps. The client then applies all 1397 network and cost map updates atomically. 1399 Alternatively, the client MAY update the network map immediately. In 1400 this case, the client MUST mark each dependent cost map as 1401 temporarily invalid, and MUST NOT use that map until the client 1402 receives a cost map update message with the new network map version 1403 tag. Note that the client MUST NOT delete the cost maps, because the 1404 server may send patch update messages. 1406 The ALTO server SHOULD send updates for dependent resources in a 1407 timely fashion. However, if the client does not receive the expected 1408 updates, the client MUST close the update stream connection, discard 1409 the dependent resources, and reestablish the update stream. The 1410 client MAY retain the version tag of the last version of any tagged 1411 resources, and give those version tags when requesting the new update 1412 stream. In this case, if a version is still current, the ALTO server 1413 will not re-send that resource. 1415 Although not as efficient as possible, this recovery method is simple 1416 and reliable. 1418 11. Design Decisions and Discussions 1420 11.1. HTTP/2 Server-Push 1422 HTTP/2 ([RFC7540]) provides a Server Push facility. Although the 1423 name implies that it might be useful for sending asynchronous updates 1424 from the server to the client, in reality Server Push is not well 1425 suited for that task. To see why it is not, here is a quick summary 1426 of HTTP/2. 1428 HTTP/2 allows a client and server to multiplex many HTTP requests and 1429 responses over a single TCP connection. The requests and responses 1430 can be interleaved on a block by block basis, avoiding the head-of- 1431 line blocking problem encountered with the Keep-Alive mechanism in 1432 HTTP/1.1. Server Push allows the server to send a resource (an 1433 image, a CSS file, a javascript file, etc.) to the client before the 1434 client explicitly requests it. A server can only push cacheable GET- 1435 mode resources. By pushing a resource, the server implicitly tells 1436 the client, "Add this resource to your cache, because a resource you 1437 have requested needs it." 1439 One approach for using Server Push for ALTO updates is for the server 1440 to send each update event as a separate Server Push item, and let the 1441 client apply those updates as they arrive. Unfortunately there are 1442 several problems with that approach. 1444 First, HTTP/2 does not guarantee that pushed resources are delivered 1445 to the client in the order they were sent by the client, so each 1446 update event would need a sequence number, and the client would have 1447 to re-sequence them. 1449 Second, an HTTP/2-aware client library will not necessarily inform a 1450 client application when the server pushes a resource. Instead, the 1451 library might cache the pushed resource, and only deliver it to the 1452 client when the client explicitly requests that URI. 1454 But the third problem is the most significant: Server Push is 1455 optional, and can be disabled by any proxy between the client and the 1456 server. This is not a problem for the intended use of Server Push: 1457 eventually the client will request those resources, so disabling 1458 Server Push just adds a delay. But this means that Server Push is 1459 not suitable for resources which the client does not know to request. 1461 Thus we do not believe HTTP/2 Server Push is suitable for delivering 1462 asynchronous updates. Hence we have chosen to base ALTO updates on 1463 HTTP/1.1 and SSE. 1465 11.2. Not Allowing Stream Restart 1467 If an update stream is closed accidentally, when the client 1468 reconnects, the server must resend the full maps. This is clearly 1469 inefficient. To avoid that inefficiency, the SSE specification 1470 allows a server to assign an id to each event. When a client 1471 reconnects, the client can present the id of the last successfully 1472 received event, and the server restarts with the next event. 1474 However, that mechanism adds additional complexity. The server must 1475 save SSE messages in a buffer, in case clients reconnect. But that 1476 mechanism will never be perfect: if the client waits too long to 1477 reconnect, or if the client sends an invalid id, then the server will 1478 have to resend the complete maps anyway. 1480 Furthermore, this is unlikely to be a problem in practice. Clients 1481 who want continuous updates for large resources, such as full Network 1482 and cost maps, are likely to be things like P2P trackers. These 1483 clients will be well connected to the network; they will rarely drop 1484 connections. 1486 Mobile devices certainly can and do drop connections, and will have 1487 to reconnect. But mobile devices will not need continuous updates 1488 for multi-megabyte cost maps. If mobile devices need continuous 1489 updates at all, they will need them for small queries, such as the 1490 costs from a small set of media servers from which the device can 1491 stream the currently playing movie. If the mobile device drops the 1492 connection and reestablishes the update stream, the ALTO server will 1493 have to retransmit only a small amount of redundant data. 1495 In short, using event ids to avoid resending the full map adds a 1496 considerable amount of complexity to avoid a situation which we 1497 expect is very rare. We believe that complexity is not worth the 1498 benefit. 1500 The Update Stream service does allow the client to specify the tag of 1501 the last received version of any tagged resource, and if that is 1502 still current, the server need not retransmit the full resource. 1503 Hence clients can use this to avoid retransmitting full network maps. 1504 cost maps are not tagged, so this will not work for them. Of course, 1505 the ALTO protocol could be extended by adding version tags to cost 1506 maps, which would solve the retransmission-on-reconnect problem. 1507 However, adding tags to cost maps might add a new set of 1508 complications. 1510 11.3. Is Incremental Update Useful for Network Maps? 1512 It is not clear whether incremental updates (that is, patch updates) 1513 are useful for network maps. For minor changes, such as moving a 1514 prefix from one PID to another, they can be useful. But more 1515 involved changes to the network map are likely to be "flag days": 1516 they represent a completely new network map, rather than a simple, 1517 well-defined change. 1519 At this point we do not have sufficient experience with ALTO 1520 deployments to know how frequently network maps will change, or how 1521 extensive those changes will be. For example, suppose a link goes 1522 down and the network uses an alternative route. This is a frequent 1523 occurrence. If an ALTO server models that by moving prefixes from 1524 one PID to another, then network maps will change frequently. 1525 However, an ALTO server might model that as a change in costs between 1526 PIDs, rather than a change in the PID definitions. If a server takes 1527 that approach, simple routing changes will affect cost maps, but not 1528 network maps. 1530 So while we allow a server to use patch on network maps, we do not 1531 require the server to do so. Each server may decide on its own 1532 whether to use patch for network maps. 1534 This is not to say that network map updates are not useful. Clearly 1535 network maps will change, and update events are necessary to inform 1536 clients of the new map. Further, there maybe another incremental 1537 update encoding that is better suited for updating Networks Maps; see 1538 the discussions in the next section. 1540 11.4. Other Incremental Update Message Types 1542 Other JSON-based incremental update formats may be introduced in the 1543 future. The update events defined in this document have the media- 1544 type of the update data. Hence, this update mechanism could easily 1545 be extended to allow servers to use additional encoding for 1546 incremental updates. 1548 Although we allow both JSON patch and JSON merge patch, we think that 1549 JSON merge patch is clearly superior to JSON Patch for describing 1550 incremental updates to cost maps, Endpoint Costs, and Endpoint 1551 Properties. For these data structures, JSON merge patch is more 1552 space-efficient, as well as simpler to apply; we see no advantage to 1553 allowing a server to use JSON Patch for those resources. 1555 The case is not as clear for incremental updates to network maps. 1556 For example, suppose a prefix moves from one PID to another. JSON 1557 Patch could encode that as a simple insertion and deletion, while 1558 merge patch would have to replace the entire array of prefixes for 1559 both PIDs. On the other hand, to process a JSON Patch update, the 1560 client would have to retain the indexes of the prefixes for each PID. 1561 Logically, the prefixes in a PID are an unordered set, not an array; 1562 aside from handling updates, a client has no need to retain the array 1563 indexes of the prefixes. Hence to take advantage of JSON Patch for 1564 network maps, clients would have to retain additional, otherwise 1565 unnecessary, data. 1567 11.5. Requirements on Future ALTO Services to Use this Design 1569 12. Miscellaneous Considerations 1571 12.1. Considerations for Updates to Filtered Cost Maps 1573 If an update stream provides updates to a Filtered cost map which 1574 allows constraint tests, then a client MAY request updates to a 1575 Filtered cost map request with a constraint test. In this case, when 1576 a cost changes, the server MUST send an update if the new value 1577 satisfies the test. If the new value does not, whether the server 1578 sends an update depends on whether the previous value satisfied the 1579 test. If it did not, the server SHOULD NOT send an update to the 1580 client. But if the previous value did, then the server MUST send an 1581 update with a "null" value, to inform the client that this cost no 1582 longer satisfies the criteria. 1584 An ALTO server can avoid such issues by offering update streams only 1585 for filtered cost maps which do not allow constraint tests. 1587 12.2. Considerations for Incremental Updates to Ordinal Mode Costs 1589 For an ordinal mode cost map, a change to a single cost point may 1590 require updating many other costs. As an extreme example, suppose 1591 the lowest cost changes to the highest cost. For a numerical mode 1592 cost map, only that one cost changes. But for an ordinal mode cost 1593 map, every cost might change. While this document allows a server to 1594 offer incremental updates for ordinal mode cost maps, server 1595 implementors should be aware that incremental updates for ordinal 1596 costs are more complicated than for numerical costs, and clients 1597 should be aware that small changes may result in large updates. 1599 An ALTO server can avoid this complication by only offering full 1600 replacement updates for ordinal cost maps. 1602 12.3. Considerations Related to SSE Line Lengths 1604 SSE was designed for events that consist of relatively small amounts 1605 of line-oriented text data, and SSE clients frequently read input one 1606 line-at-a-time. However, an update stream sends full cost maps as 1607 single events, and a cost map may involve megabytes, if not tens of 1608 megabytes, of text. This has implications for both the ALTO server 1609 and Client. 1611 First, SSE clients might not be able to handle a multi-megabyte data 1612 "line". Hence it is RECOMMENDED that an ALTO server limit data lines 1613 to at most 2,000 characters. 1615 Second, some SSE client packages read all the data for an event into 1616 memory, and then present it to the client as a single character 1617 array. However, a client computer may not have enough memory to hold 1618 the entire JSON text for a large cost map. Hence an ALTO client 1619 SHOULD consider using an SSE library which presents the event data in 1620 manageable chunks, so the client can parse the cost map incrementally 1621 and store the underlying data in a more compact format. 1623 13. Security Considerations 1625 13.1. Denial-of-Service Attacks 1627 Allowing persistent update stream connections enables a new class of 1628 Denial-of-Service attacks. A client might create an unreasonable 1629 number of update stream connections, or add an unreasonable number of 1630 client-ids to one update stream. To avoid those attacks, an ALTO 1631 server MAY choose to limit the number of active streams, and reject 1632 new requests when that threshold is reached. A server MAY also chose 1633 to limit the number of active client-ids on any given stream, or 1634 limit the total number of client-ids used over the lifetime of a 1635 stream, and reject any stream control request which would exceed 1636 those limits. In these cases, the server SHOULD return the HTTP 1637 status "503 Service Unavailable". 1639 While this technique prevents update stream DoS attacks from 1640 disrupting an ALTO server's other services, it does make it easier 1641 for a DoS attack to disrupt the update stream service. Therefore a 1642 server may prefer to restrict update stream services to authorized 1643 clients, as discussed in Section 15 of [RFC7285]. 1645 Alternatively an ALTO server MAY return the HTTP status "307 1646 Temporary Redirect" to redirect the client to another ALTO server 1647 which can better handle a large number of update streams. 1649 13.2. Spoofed Control Requests 1651 An outside party which can read the update stream response, or which 1652 can observe stream control requests, can obtain the control URI and 1653 use that to send a fraudulent "remove" requests, thus disabling 1654 updates for the valid client. This can be avoided by encrypting the 1655 update stream and stream control requests (see Section 15 of 1656 [RFC7285]). Also, the ALTO server echoes the "remove" requests on 1657 the update stream, so the valid client can detect unauthorized 1658 requests. 1660 13.3. Privacy 1662 This extension does not introduce any privacy issues not already 1663 present in the ALTO protocol. 1665 14. IANA Considerations 1667 This document defines two new media-types, "application/alto- 1668 updatestreamparams+json", as described in Section 7.3, and 1669 "application/alto-updatestreamcontrol+json", as described in 1670 Section 6.3. All other media-types used in this document have 1671 already been registered, either for ALTO, JSON merge patch, or JSON 1672 patch. 1674 Type name: application 1676 Subtype name: alto-updatestreamparams+json 1678 Required parameters: n/a 1679 Optional parameters: n/a 1681 Encoding considerations: Encoding considerations are identical to 1682 those specified for the "application/json" media type. See 1683 [RFC7159]. 1685 Security considerations: Security considerations relating to the 1686 generation and consumption of ALTO Protocol messages are discussed 1687 in Section 13 of this document and Section 15 of [RFC7285]. 1689 Interoperability considerations: This document specifies format of 1690 conforming messages and the interpretation thereof. 1692 Published specification: Section 7.3 of this document. 1694 Applications that use this media type: ALTO servers and ALTO clients 1695 either stand alone or are embedded within other applications. 1697 Additional information: 1699 Magic number(s): n/a 1701 File extension(s): This document uses the mime type to refer to 1702 protocol messages and thus does not require a file extension. 1704 Macintosh file type code(s): n/a 1706 Person & email address to contact for further information: See 1707 Authors' Addresses section. 1709 Intended usage: COMMON 1711 Restrictions on usage: n/a 1713 Author: See Authors' Addresses section. 1715 Change controller: Internet Engineering Task Force 1716 (mailto:iesg@ietf.org). 1718 Type name: application 1720 Subtype name: alto-updatestreamcontrol+json 1722 Required parameters: n/a 1724 Optional parameters: n/a 1725 Encoding considerations: Encoding considerations are identical to 1726 those specified for the "application/json" media type. See 1727 [RFC7159]. 1729 Security considerations: Security considerations relating to the 1730 generation and consumption of ALTO Protocol messages are discussed 1731 in Section 13 of this document and Section 15 of [RFC7285]. 1733 Interoperability considerations: This document specifies format of 1734 conforming messages and the interpretation thereof. 1736 Published specification: Section 6.3 of this document. 1738 Applications that use this media type: ALTO servers and ALTO clients 1739 either stand alone or are embedded within other applications. 1741 Additional information: 1743 Magic number(s): n/a 1745 File extension(s): This document uses the mime type to refer to 1746 protocol messages and thus does not require a file extension. 1748 Macintosh file type code(s): n/a 1750 Person & email address to contact for further information: See 1751 Authors' Addresses section. 1753 Intended usage: COMMON 1755 Restrictions on usage: n/a 1757 Author: See Authors' Addresses section. 1759 Change controller: Internet Engineering Task Force 1760 (mailto:iesg@ietf.org). 1762 15. References 1764 [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate 1765 Requirement Levels", RFC 2119, BCP 14, March 1997. 1767 [RFC5789] Dusseault, L. and J. Snell, "PATCH Method for HTTP", 1768 RFC 5789, March 2010. 1770 [RFC6902] Bryan, P. and M. Nottingham, "JavaScript Object Notation 1771 (JSON) Patch", RFC 6902, April 2013. 1773 [RFC7159] Bray, T., "The JavaScript Object Notation (JSON) Data 1774 Interchange Format", RFC 7159, March 2014. 1776 [RFC7285] Almi, R., Penno, R., Yang, Y., Kiesel, S., Previdi, S., 1777 Roome, W., Shalunov, S., and R. Woundy, "Application-Layer 1778 Traffic Optimization (ALTO) Protocol", RFC 7285, September 1779 2014. 1781 [RFC7230] Fielding, R. and J. Reschke, "Hypertext Transfer Protocol 1782 (HTTP/1.1): Message Syntax and Routing", RFC 7230, June 1783 2014. 1785 [RFC7231] Fielding, R. and J. Reschke, "Hypertext Transfer Protocol 1786 (HTTP/1.1): Semantics and Content", RFC 7231, June 2014. 1788 [RFC7232] Fielding, R. and J. Reschke, "Hypertext Transfer Protocol 1789 (HTTP/1.1): Conditional Requests", RFC 7232, June 2014. 1791 [RFC7233] Fielding, R. and J. Reschke, "Hypertext Transfer Protocol 1792 (HTTP/1.1): Range Requests", RFC 7233, June 2014. 1794 [RFC7234] Fielding, R., Nottingham, M., and J. Reschke, "Hypertext 1795 Transfer Protocol (HTTP/1.1): Caching", RFC 7234, June 1796 2014. 1798 [RFC7235] Fielding, R. and J. Reschke, "Hypertext Transfer Protocol 1799 (HTTP/1.1): Authentication", RFC 7235, June 2014. 1801 [RFC7396] Hoffman, P. and J. Snell, "JSON Merge Patch", RFC 7396, 1802 October 2014. 1804 [RFC7540] Belshe, M., Peon, R., and M. Thomson, "Hypertext Transfer 1805 Protocol Version 2 (HTTP/2)", RFC 7540, May 2015. 1807 [SSE] Hickson, I., "Server-Sent Events (W3C)", W3C 1808 Recommendation 03 February 2015, February 2015. 1810 Appendix A. Acknowledgments 1812 Thank you to Xiao Shi (Yale University) for his contributions to an 1813 earlier version of this document. 1815 Authors' Addresses 1816 Wendy Roome 1817 Nokia Bell Labs 1818 600 Mountain Ave, Rm 3B-324 1819 Murray Hill, NJ 07974 1820 USA 1822 Phone: +1-908-582-7974 1823 Email: wendy@wdroome.com 1825 Y. Richard Yang 1826 Tongji/Yale University 1827 51 Prospect St 1828 New Haven CT 1829 USA 1831 Email: yang.r.yang@gmail.com