1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633
5634
5635
5636
5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682
5683
5684
5685
5686
5687
5688
5689
5690
5691
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861
5862
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882
5883
5884
5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938
5939
5940
5941
5942
5943
5944
5945
5946
5947
5948
5949
5950
5951
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980
5981
5982
5983
5984
5985
5986
5987
5988
5989
5990
5991
5992
5993
5994
5995
5996
5997
5998
5999
6000
6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023
6024
6025
6026
6027
6028
6029
6030
6031
6032
6033
6034
6035
6036
6037
6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048
6049
6050
6051
6052
6053
6054
6055
6056
6057
6058
6059
6060
6061
6062
6063
6064
6065
6066
6067
6068
6069
6070
6071
6072
6073
6074
6075
6076
6077
6078
6079
6080
6081
6082
6083
6084
6085
6086
6087
6088
6089
6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
6105
6106
6107
6108
6109
6110
6111
6112
6113
6114
6115
6116
6117
6118
6119
6120
6121
6122
6123
6124
6125
6126
6127
6128
6129
6130
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140
6141
6142
6143
6144
6145
6146
6147
6148
6149
6150
6151
6152
6153
6154
6155
6156
6157
6158
6159
6160
6161
6162
6163
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173
6174
6175
6176
6177
6178
6179
6180
6181
6182
6183
6184
6185
6186
6187
6188
6189
6190
6191
6192
6193
6194
6195
6196
6197
6198
6199
6200
6201
6202
6203
6204
6205
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
|
Internet Engineering Task Force (IETF) M. Thornburgh
Request for Comments: 7016 Adobe
Category: Informational November 2013
ISSN: 2070-1721
Adobe's Secure Real-Time Media Flow Protocol
Abstract
This memo describes Adobe's Secure Real-Time Media Flow Protocol
(RTMFP), an endpoint-to-endpoint communication protocol designed to
securely transport parallel flows of real-time video, audio, and data
messages, as well as bulk data, over IP networks. RTMFP has features
that make it effective for peer-to-peer (P2P) as well as client-
server communications, even when Network Address Translators (NATs)
are used.
Status of This Memo
This document is not an Internet Standards Track specification; it is
published for informational purposes.
This document is a product of the Internet Engineering Task Force
(IETF). It has been approved for publication by the Internet
Engineering Steering Group (IESG). Not all documents approved by the
IESG are a candidate for any level of Internet Standard; see Section
2 of RFC 5741.
Information about the current status of this document, any errata,
and how to provide feedback on it may be obtained at
http://www.rfc-editor.org/info/rfc7016.
IESG Note
This document represents technology developed outside the processes
of the IETF and the IETF community has determined that it is useful
to publish it as an RFC in its current form. It is a product of the
IETF only in that it has received public review and has been approved
for publication by the Internet Engineering Steering Group (IESG),
but the content of the document does not represent a consensus of the
IETF.
Thornburgh Informational [Page 1]
^L
RFC 7016 Adobe RTMFP November 2013
Copyright Notice
Copyright (c) 2013 IETF Trust and the persons identified as the
document authors. All rights reserved.
This document is subject to BCP 78 and the IETF Trust's Legal
Provisions Relating to IETF Documents
(http://trustee.ietf.org/license-info) in effect on the date of
publication of this document. Please review these documents
carefully, as they describe your rights and restrictions with respect
to this document. Code Components extracted from this document must
include Simplified BSD License text as described in Section 4.e of
the Trust Legal Provisions and are provided without warranty as
described in the Simplified BSD License.
This document may not be modified, and derivative works of it may not
be created, except to format it for publication as an RFC or to
translate it into languages other than English.
Table of Contents
1. Introduction ....................................................5
1.1. Design Highlights of RTMFP .................................6
1.2. Terminology ................................................7
2. Syntax ..........................................................8
2.1. Common Elements ............................................8
2.1.1. Elementary Types and Constructs .....................8
2.1.2. Variable Length Unsigned Integer (VLU) .............10
2.1.3. Option .............................................10
2.1.4. Option List ........................................11
2.1.5. Internet Socket Address (Address) ..................12
2.2. Network Layer .............................................13
2.2.1. Encapsulation ......................................13
2.2.2. Multiplex ..........................................13
2.2.3. Encryption .........................................14
2.2.4. Packet .............................................15
2.3. Chunks ....................................................18
2.3.1. Packet Fragment Chunk ..............................20
2.3.2. Initiator Hello Chunk (IHello) .....................21
2.3.3. Forwarded Initiator Hello Chunk (FIHello) ..........22
2.3.4. Responder Hello Chunk (RHello) .....................23
2.3.5. Responder Redirect Chunk (Redirect) ................24
2.3.6. RHello Cookie Change Chunk .........................26
2.3.7. Initiator Initial Keying Chunk (IIKeying) ..........27
2.3.8. Responder Initial Keying Chunk (RIKeying) ..........29
2.3.9. Ping Chunk .........................................31
2.3.10. Ping Reply Chunk ..................................32
Thornburgh Informational [Page 2]
^L
RFC 7016 Adobe RTMFP November 2013
2.3.11. User Data Chunk ...................................33
2.3.11.1. Options for User Data ....................35
2.3.11.1.1. User's Per-Flow Metadata ......35
2.3.11.1.2. Return Flow Association .......36
2.3.12. Next User Data Chunk ..............................37
2.3.13. Data Acknowledgement Bitmap Chunk (Bitmap Ack) ....39
2.3.14. Data Acknowledgement Ranges Chunk (Range Ack) .....41
2.3.15. Buffer Probe Chunk ................................43
2.3.16. Flow Exception Report Chunk .......................43
2.3.17. Session Close Request Chunk (Close) ...............44
2.3.18. Session Close Acknowledgement Chunk (Close Ack) ...44
3. Operation ......................................................45
3.1. Overview ..................................................45
3.2. Endpoint Identity .........................................46
3.3. Packet Multiplex ..........................................48
3.4. Packet Fragmentation ......................................48
3.5. Sessions ..................................................50
3.5.1. Startup ............................................53
3.5.1.1. Normal Handshake ..........................53
3.5.1.1.1. Initiator ......................54
3.5.1.1.2. Responder ......................55
3.5.1.2. Cookie Change .............................57
3.5.1.3. Glare .....................................59
3.5.1.4. Redirector ................................60
3.5.1.5. Forwarder .................................61
3.5.1.6. Redirector and Forwarder with NAT .........63
3.5.1.7. Load Distribution and Fault Tolerance .....66
3.5.2. Congestion Control .................................67
3.5.2.1. Time Critical Reverse Notification ........68
3.5.2.2. Retransmission Timeout ....................68
3.5.2.3. Burst Avoidance ...........................71
3.5.3. Address Mobility ...................................71
3.5.4. Ping ...............................................72
3.5.4.1. Keepalive .................................72
3.5.4.2. Address Mobility ..........................73
3.5.4.3. Path MTU Discovery ........................74
3.5.5. Close ..............................................74
3.6. Flows .....................................................75
3.6.1. Overview ...........................................75
3.6.1.1. Identity ..................................75
3.6.1.2. Messages and Sequencing ...................76
3.6.1.3. Lifetime ..................................77
Thornburgh Informational [Page 3]
^L
RFC 7016 Adobe RTMFP November 2013
3.6.2. Sender .............................................78
3.6.2.1. Startup ...................................80
3.6.2.2. Queuing Data ..............................80
3.6.2.3. Sending Data ..............................81
3.6.2.3.1. Startup Options ................83
3.6.2.3.2. Send Next Data .................83
3.6.2.4. Processing Acknowledgements ...............83
3.6.2.5. Negative Acknowledgement and Loss .........84
3.6.2.6. Timeout ...................................85
3.6.2.7. Abandoning Data ...........................86
3.6.2.7.1. Forward Sequence Number
Update .........................86
3.6.2.8. Examples ..................................87
3.6.2.9. Flow Control ..............................89
3.6.2.9.1. Buffer Probe ...................89
3.6.2.10. Exception ................................89
3.6.2.11. Close ....................................90
3.6.3. Receiver ...........................................90
3.6.3.1. Startup ...................................93
3.6.3.2. Receiving Data ............................94
3.6.3.3. Buffering and Delivering Data .............95
3.6.3.4. Acknowledging Data ........................97
3.6.3.4.1. Timing .........................98
3.6.3.4.2. Size and Truncation ............99
3.6.3.4.3. Constructing ...................99
3.6.3.4.4. Delayed Acknowledgement .......100
3.6.3.4.5. Obligatory Acknowledgement ....100
3.6.3.4.6. Opportunistic
Acknowledgement ...............100
3.6.3.4.7. Example .......................101
3.6.3.5. Flow Control .............................102
3.6.3.6. Receiving a Buffer Probe .................103
3.6.3.7. Rejecting a Flow .........................103
3.6.3.8. Close ....................................104
4. IANA Considerations ...........................................104
5. Security Considerations .......................................105
6. Acknowledgements ..............................................106
7. References ....................................................107
7.1. Normative References .....................................107
7.2. Informative References ...................................107
Appendix A. Example Congestion Control Algorithm .................108
A.1. Discussion ................................................108
A.2. Algorithm .................................................110
Thornburgh Informational [Page 4]
^L
RFC 7016 Adobe RTMFP November 2013
1. Introduction
Adobe's Secure Real-Time Media Flow Protocol (RTMFP) is intended for
use as a general purpose endpoint-to-endpoint data transport service
in IP networks. It has features that make it well suited to the
transport of real-time media (such as low-delay video, audio, and
data) as well as bulk data, and for client-server as well as peer-to-
peer (P2P) communication. These features include independent
parallel message flows that may have different delivery priorities,
variable message reliability (from TCP-like full reliability to
UDP-like best effort), multi-point congestion control, and built-in
security. Session multiplexing and facilities to support UDP
hole-punching simplify Network Address Translator (NAT) traversal in
peer-to-peer systems.
RTMFP is implemented in Flash Player, Adobe Integrated Runtime (AIR),
and Adobe Media Server (AMS, formerly Flash Media Server or FMS), all
from Adobe Systems Incorporated, and is used as the foundation
transport protocol for real-time video, audio, and data
communication, both client-server and P2P, in those products. At the
time of writing, the Adobe Flash Player runtime is installed on more
than one billion end-user desktop computers.
RTMFP was developed by Adobe Systems Incorporated and is not the
product of an IETF activity.
This memo describes the syntax and operation of the Secure Real-Time
Media Flow Protocol.
This memo describes a general security framework that, when combined
with an application-specific Cryptography Profile, can be used to
establish a confidential and authenticated session between endpoints.
The application-specific Cryptography Profile, not defined herein,
would detail the specific cryptographic algorithms, data formats, and
semantics to be used within this framework. Interoperation between
applications of RTMFP requires common or compatible Cryptography
Profiles.
Note to implementers: at the time of writing, the Cryptography
Profile used by the above-mentioned Adobe products is not publicly
described by Adobe. Implementers should investigate the availability
of documentation of that Cryptography Profile prior to implementing
RTMFP for the purpose of interoperation with the above-mentioned
Adobe products.
Thornburgh Informational [Page 5]
^L
RFC 7016 Adobe RTMFP November 2013
1.1. Design Highlights of RTMFP
Between any pair of communicating endpoints is a single,
bidirectional, secured, congestion controlled session.
Unidirectional flows convey messages from one end to the other within
the session. An endpoint can have concurrent sessions with multiple
other far endpoints.
Design highlights of RTMFP include the following:
o The security framework is an inherent part of the basic protocol.
The application designer chooses the cryptographic formats and
algorithms to suit the needs of the application, and may update
them as the state of the security arts progresses.
o Cryptographic Endpoint Discriminators can resist port scanning.
o All header, control, and framing information, except for network
addressing information and a session identifier, is encrypted
according to the Cryptography Profile.
o There is a single session and associated congestion control state
between a pair of endpoints.
o Each session may have zero or more unidirectional message-oriented
flows in each direction. All of a session's sending flows share
the session's congestion control state.
o Return Flow Association (Section 2.3.11.1.2) generalizes
bidirectional communication to arbitrarily complex trees of flows.
o Messages in flows can be arbitrarily large and are fragmented for
transmission.
o Messages of any size may be sent with full, partial, or no
reliability (sender's choice). Messages may be delivered to the
receiving user in original queuing order or network arrival order
(receiver's choice).
o Flows are named with arbitrary, user-defined metadata
(Section 2.3.11.1.1) rather than port or stream numbers.
o The sequence numbers of each flow are independent of all other
flows and are not permanently bound to a session-wide transmission
ordering. This allows real-time priority decisions to be made at
transmission or retransmission time.
Thornburgh Informational [Page 6]
^L
RFC 7016 Adobe RTMFP November 2013
o Each flow has its own receive window and, therefore, independent
flow control.
o Round trips are expensive and are minimized or eliminated when
possible.
o After a session is established, flows begin by sending the flow's
messages with no additional handshake (and associated round
trips).
o Transmitting bytes on the network is much more expensive than
moving bytes in a CPU or memory. Wasted bytes are minimized or
eliminated when possible and practical, and variable length
encodings are used, even at the expense of breaking 32-bit
alignment and making the text diagrams in this specification look
awkward.
o P2P lookup and peer introduction (including UDP hole-punching for
NAT and firewall traversal) are supported directly by the session
startup handshake.
o Session identifiers allow an endpoint to multiplex many sessions
over a single local transport address while allowing sessions to
survive changes in transport address (as may happen in mobile or
wireless deployments).
The syntax of the protocol is detailed in Section 2. The operation
of the protocol is detailed in Section 3.
1.2. Terminology
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
"SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and
"OPTIONAL" in this document are to be interpreted as described in
[RFC2119].
Thornburgh Informational [Page 7]
^L
RFC 7016 Adobe RTMFP November 2013
2. Syntax
Definitions of types and structures in this specification use
traditional text diagrams paired with procedural descriptions using a
C-like syntax. The C-like procedural descriptions SHALL be construed
as definitive.
Structures are packed to take only as many bytes as explicitly
indicated. There is no 32-bit alignment constraint, and fields are
not padded for alignment unless explicitly indicated or described.
Text diagrams may include a bit ruler across the top; this is a
convenience for counting bits in individual fields and does not
necessarily imply field alignment on a multiple of the ruler width.
Unless specified otherwise, reserved fields SHOULD be set to 0 by a
sender and MUST be ignored by a receiver.
The procedural syntax of this specification defines correct and
error-free encoded inputs to a parser. The procedural syntax does
not describe a fully featured parser, including error detection and
handling. Implementations MUST include means to identify error
circumstances, including truncations causing elementary or composed
types to not fit inside containing structures, fields, or elements.
Unless specified otherwise, an error circumstance SHALL abort the
parsing and processing of an element and its enclosing elements, up
to the containing packet.
2.1. Common Elements
This section lists types and structures that are used throughout this
specification.
2.1.1. Elementary Types and Constructs
This section lists the elementary types and constructs out of which
all of the following sections' definitions are built.
uint8_t var;
An unsigned integer 8 bits (one byte) in length and byte aligned.
uint16_t var;
An unsigned integer 16 bits in length, in network byte order ("big
endian") and byte aligned.
Thornburgh Informational [Page 8]
^L
RFC 7016 Adobe RTMFP November 2013
uint32_t var;
An unsigned integer 32 bits in length, in network byte order and
byte aligned.
uint128_t var;
An unsigned integer 128 bits in length, in network byte order and
byte aligned.
uintn_t var :bitsize;
An unsigned integer of any other size, potentially not byte
aligned. Its size in bits is specified explicitly by bitsize.
bool_t var :1;
A boolean flag having the value true (1 or set) or false (0 or
clear) and being one bit in length.
type var[num];
A packed array of type with length num*sizeof(type)*8 bits.
struct name_t { ... } name :bitsize;
A packed structure. Its size in bits is specified by bitsize.
remainder();
The number of bytes from the current offset to the end of the
enclosing structure.
type var[remainder()];
A packed array of type, its size extending to the end of the
enclosing structure.
Note that a bitsize of "variable" indicates that the size of the
structure is determined by the sizes of its interior components. A
bitsize of "n*8" indicates that the size of the structure is a whole
number of bytes and is byte aligned.
Thornburgh Informational [Page 9]
^L
RFC 7016 Adobe RTMFP November 2013
2.1.2. Variable Length Unsigned Integer (VLU)
A VLU encodes any finite non-negative integer into one or more bytes.
For each encoded byte, if the high bit is set, the next byte is also
part of the VLU. If the high bit is clear, this is the final byte of
the VLU. The remaining bits encode the number, seven bits at a time,
from most significant to least significant.
0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+~+~+~+~+~+~+~+~+ +-+-+-+-+-+-+-+-+
|1| digit |...............|0| digit |
+~+~+~+~+~+~+~+~+ +-+-+-+-+-+-+-+-+
^ ^
+--------- zero or more --------+
struct vlu_t
{
value = 0;
do {
bool_t more :1;
uintn_t digit :7;
value = (value * 128) + digit;
} while(more);
} :variable*8;
+-------------/-+
| \ |
+-------------/-+
Figure 1: VLU Depiction in Following Diagrams
Unless stated otherwise in this specification, implementations SHOULD
handle VLUs encoding unsigned integers at least 64 bits in length
(that is, encoding a maximum value of at least 2^64 - 1).
2.1.3. Option
An Option is a Length-Type-Value triplet. Length and Type are
encoded in VLU format. Length is the number of bytes of payload
following the Length field. The payload comprises the Type and Value
fields. Type identifies the kind of option this is. The syntax of
the Value field is determined by the type of option.
Thornburgh Informational [Page 10]
^L
RFC 7016 Adobe RTMFP November 2013
An Option can have a length of zero, in which case it has no type and
no value and is empty. An empty Option is called a "Marker".
+-------------/-+~~~~~~~~~~~~~/~+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
| length \ | type \ | value |
+-------------/-+~~~~~~~~~~~~~/~+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/
^ ^
+-------- length bytes long (may be 0) ---------+
struct option_t
{
vlu_t length :variable*8; // "L"
if(length > 0)
{
struct {
vlu_t type :variable*8; // "T"
uint8_t value[remainder()]; // "V"
} payload :length*8;
}
} :variable*8;
+---/---/-------+
| L \ T \ V |
+---/---/-------+
Figure 2: Option Depiction in Following Diagrams
2.1.4. Option List
An Option List is a sequence of zero or more non-empty Options
terminated by a Marker.
+~~~/~~~/~~~~~~~+ +~~~/~~~/~~~~~~~+-------------/-+
| L \ T \ V |...............| L \ T \ V | 0 \ |
+~~~/~~~/~~~~~~~+ +~~~/~~~/~~~~~~~+-------------/-+
^ ^ Marker
+------- zero or more non-empty Options --------+ (empty Option)
struct optionList_t
{
do
{
option_t option :variable*8;
} while(option.length > 0);
} :variable*8;
Thornburgh Informational [Page 11]
^L
RFC 7016 Adobe RTMFP November 2013
2.1.5. Internet Socket Address (Address)
When communicating an Internet socket address (a combination of a
32-bit IPv4 [RFC0791] or 128-bit IPv6 [RFC2460] address and a 16-bit
port number) to another RTMFP, this encoding is used. This encoding
additionally allows an address to be tagged with an origin type,
which an RTMFP MAY use to modify the use or disposition of the
address.
1
0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7|8 9 0 1 2 3 4 5
+-+-+-+-+-+-+-+-+-----/.../-----+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|I| | O | Internet | |
|P|0 0 0 0 0| R | address | port |
|6| rsv | I |32 or 128 bits | |
+-+-+-+-+-+-+-+-+-----/.../-----+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
struct address_t
{
bool_t inet6 :1; // "IP6"
uintn_t reserved :5 = 0; // "rsv"
uintn_t origin :2; // "ORI"
if(inet6)
uint128_t ipAddress;
else
uint32_t ipAddress;
uint16_t port;
} :variable*8;
inet6: If set, the Internet address is a 128-bit IPv6 address. If
clear, the Internet address is a 32-bit IPv4 address.
origin: The origin tag of this address. Possible values are:
0: Unknown, unspecified, or "other"
1: Address was reported by the origin as a local, directly
attached interface address
2: Address was observed to be the source address from which a
packet was received (a "reflexive transport address" in the
terminology of [RFC5389])
3: Address is a relay, proxy, or introducer (a Redirector
and/or Forwarder)
Thornburgh Informational [Page 12]
^L
RFC 7016 Adobe RTMFP November 2013
ipAddress: The Internet address, in network byte order.
port: The 16-bit port number, in network byte order.
2.2. Network Layer
2.2.1. Encapsulation
RTMFP Multiplex packets are usually carried in UDP [RFC0768]
datagrams so that they may transit commonly deployed NATs and
firewalls, and so that RTMFP may be implemented on commonly deployed
operating systems without special privileges or permissions.
RTMFP Multiplex packets MAY be carried by any suitable datagram
transport or encapsulation where endpoints are addressed by an
Internet socket address (that is, an IPv4 or IPv6 address and a
16-bit port number).
The choice of port numbers is not mandated by this specification.
Higher protocol layers or the application define the port
numbers used.
2.2.2. Multiplex
0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Scrambled Session ID (SSID) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| e first32[0] |
|- - - - - - n - - - - - - - - - - - - - - - - - - - - - - - -|
| c first32[1] |
+- - - - - - r - - - - - - - - - - - - - - - - - - - - - - - -+
| y |
| pted packet |
+---------------------------------------------------------------/
struct multiplex_t
{
uint32_t scrambledSessionID; // "SSID"
union {
uint32_t first32[2]; // see note
uint8_t encryptedPacket[remainder()];
} :(encapsulation.length - 4)*8;
// if encryptedPacket is less than 8 bytes long, treat it
// as if it were end-padded with 0s for the following:
sessionID = scrambledSessionID XOR first32[0] XOR first32[1];
} :encapsulation.length*8;
Thornburgh Informational [Page 13]
^L
RFC 7016 Adobe RTMFP November 2013
The 32-bit Scrambled Session ID is the 32-bit session ID modified by
performing a bitwise exclusive-or with the bitwise exclusive-or of
the first two 32-bit words of the encrypted packet.
The session ID is a 32-bit value that the receiver has requested to
be used by the sender when sending packets to this receiver
(Sections 2.3.7 and 2.3.8). The session ID identifies the session to
which this packet belongs and the decryption key to be used to
decrypt the encrypted packet.
Note: Session ID 0 (prior to scrambling) denotes the startup pseudo-
session and implies the Default Session Key.
Note: If the encrypted packet is less than 8 bytes long, then for the
scrambling operation, perform the exclusive-or as though the
encrypted packet were end-padded with enough 0-bytes to bring its
length to 8.
2.2.3. Encryption
RTMFP packets are encrypted according to a Cryptography Profile.
This specification doesn't define a Cryptography Profile or mandate a
particular choice of cryptography. The application defines the
cryptographic syntax and algorithms.
Packet encryption is RECOMMENDED to be a block cipher operating in
Cipher Block Chaining [CBC] or similar mode. Encrypted packets MUST
be decipherable without inter-packet dependency, since packets may be
lost, duplicated, or reordered in the network.
The packet encryption layer is responsible for data integrity and
authenticity of packets, for example by means of a checksum or
cryptographic message authentication code. To mitigate replay
attacks, data integrity SHOULD comprise duplicate packet detection,
for example by means of a session-wide packet sequence number. The
packet encryption layer SHALL discard a received packet that does not
pass integrity or authenticity tests.
Note that the structures described below are of plain, unencrypted
packets. Encrypted packets MUST be decrypted according to the
Session Key associated with the Multiplex Session ID before being
interpreted according to this specification.
The Cryptography Profile defines a well-known Default Session Key
that is used at session startup, during which per-session key(s) are
negotiated by the two endpoints. A session ID of zero denotes use of
the Default Session Key. The Default Session Key is also used with
Thornburgh Informational [Page 14]
^L
RFC 7016 Adobe RTMFP November 2013
non-zero session IDs during the latter phases of session startup
(Sections 2.3.6 and 2.3.8). See Security Considerations (Section 5)
for more about the Default Session Key.
2.2.4. Packet
An (unencrypted, plain) RTMFP packet consists of a variable sized
common header, zero or more chunks, and padding. Padding can be
inserted by the encryption layer of the sender to meet cipher block
size constraints and is ignored by the receiver. A sender's
encryption layer MAY pad the end of a packet with bytes with value
0xff such that the resulting packet is a natural and appropriate size
for the cipher. Alternatively, the Cryptography Profile MAY define
its own framing and padding scheme, if needed, such that decrypted
packets are compatible with the syntax defined in this section.
Thornburgh Informational [Page 15]
^L
RFC 7016 Adobe RTMFP November 2013
0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+
|T|T| r |T|T| M |
|C|C| s |S|S| O |
| |R| v | |E| D |
+-+-+-+-+-+-+-+-+
+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+
| if(TS) timestamp | if(TSE) timestampEcho |
+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
| Chunk |
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/
:
:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
| Chunk |
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
| padding |
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/
struct packet_t
{
bool_t timeCritical :1; // "TC"
bool_t timeCriticalReverse :1; // "TCR"
uintn_t reserved :2; // "rsv"
bool_t timestampPresent :1; // "TS"
bool_t timestampEchoPresent :1; // "TSE"
uintn_t mode :2; // "MOD"
if(0 != mode)
{
if(timestampPresent)
uint16_t timestamp;
if(timestampEchoPresent)
uint16_t timestampEcho;
while(remainder() > 2)
{
uint8_t chunkType;
uint16_t chunkLength;
if(remainder() < chunkLength)
break;
uint8_t chunkPayload[chunkLength];
} // chunks
uint8_t padding[remainder()];
}
} :plainPacket.length*8;
Thornburgh Informational [Page 16]
^L
RFC 7016 Adobe RTMFP November 2013
timeCritical: Time Critical Forward Notification. If set, indicates
that this packet contains real-time user data.
timeCriticalReverse: Time Critical Reverse Notification. If set,
indicates that the sender is currently receiving packets on other
sessions that have the timeCritical flag set.
timestampPresent: If set, indicates that the timestamp field is
present. If clear, there is no timestamp field.
timestampEchoPresent: If set, indicates that the timestamp echo
field is present. If clear, there is no timestamp echo field.
mode: The mode of this packet. See below for additional discussion
of packet modes. Possible values are:
0: Forbidden value
1: Initiator Mark
2: Responder Mark
3: Startup
timestamp: If the timestampPresent flag is set, this field is
present and contains the low 16 bits of the sender's 250 Hz clock
(4 milliseconds per tick) at transmit time. The sender's clock
MAY have its origin at any time in the past.
timestampEcho: If the timestampEchoPresent flag is set, this field
is present and contains the sender's estimate of what the
timestamp field of a packet received from the other end would be
at the time this packet was transmitted, using the method
described in Section 3.5.2.2.
chunks: Zero or more chunks follow the header. It is RECOMMENDED
that a packet contain at least one chunk.
padding: Zero or more bytes of padding follow the chunks. The
following conditions indicate padding:
* Fewer than three bytes (the size of a chunk header) remain in
the packet.
* The chunkLength field of what would be the current chunk header
indicates that the hypothetical chunk payload wouldn't fit in
the remaining bytes of the packet.
Thornburgh Informational [Page 17]
^L
RFC 7016 Adobe RTMFP November 2013
Packet mode 0 is not allowed. Packets marked with this mode are
invalid and MUST be discarded.
The original initiator of a session MUST mark all non-startup packets
it sends in that session with packet mode 1 ("Initiator Mark"). It
SHOULD ignore any packet received in that session with packet mode 1.
The original responder of a session MUST mark all non-startup packets
it sends in that session with packet mode 2 ("Responder Mark"). It
SHOULD ignore any packet received in that session with packet mode 2.
Packet mode 3 is for session startup. Session startup chunks are
only allowed in packets with this mode.
Chunks that are not for session startup are only allowed in packets
with modes 1 or 2.
2.3. Chunks
0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| chunkType | chunkLength |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
| chunkPayload (chunkLength bytes, may be zero) |
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/
struct chunk_t
{
uint8_t chunkType;
uint16_t chunkLength;
uint8_t chunkPayload[chunkLength];
} :variable*8;
chunkType: The chunk type code.
chunkLength: The size, in bytes, of the chunk payload.
chunkPayload: The type-specific payload of this chunk,
chunkLength bytes in length (may be empty).
Thornburgh Informational [Page 18]
^L
RFC 7016 Adobe RTMFP November 2013
Defined chunk types are enumerated here in the order they might be
encountered in the course of a typical session. The following chunk
type codes are defined:
0x7f: Packet Fragment (Section 2.3.1)
0x30: Initiator Hello (Section 2.3.2)
0x0f: Forwarded Initiator Hello (Section 2.3.3)
0x70: Responder Hello (Section 2.3.4)
0x71: Responder Redirect (Section 2.3.5)
0x79: RHello Cookie Change (Section 2.3.6)
0x38: Initiator Initial Keying (Section 2.3.7)
0x78: Responder Initial Keying (Section 2.3.8)
0x01: Ping (Section 2.3.9)
0x41: Ping Reply (Section 2.3.10)
0x10: User Data (Section 2.3.11)
0x11: Next User Data (Section 2.3.12)
0x50: Data Acknowledgement Bitmap (Section 2.3.13)
0x51: Data Acknowledgement Ranges (Section 2.3.14)
0x18: Buffer Probe (Section 2.3.15)
0x5e: Flow Exception Report (Section 2.3.16)
0x0c: Session Close Request (Section 2.3.17)
0x4c: Session Close Acknowledgement (Section 2.3.18)
0x00: Ignore/Padding
0xff: Ignore/Padding
A receiver MUST ignore a chunk having an unrecognized chunk type
code. A receiver MUST ignore a chunk appearing in a packet having a
mode inappropriate to that chunk type.
Thornburgh Informational [Page 19]
^L
RFC 7016 Adobe RTMFP November 2013
Unless specified otherwise, if a chunk has a syntax or processing
error (for example, the chunk's payload field is not long enough to
contain the specified syntax elements), the chunk SHALL be ignored as
though it was not present in the packet, and parsing and processing
SHALL commence with the next chunk in the packet, if any.
2.3.1. Packet Fragment Chunk
This chunk is used to divide a plain RTMFP packet (Section 2.2.4)
that is unavoidably larger than the path MTU (such as session startup
packets containing Responder Hello (Section 2.3.4) or Initiator
Initial Keying (Section 2.3.7) chunks with large certificates) into
segments that do not exceed the path MTU, and to allow the segments
to be sent through the network at a moderated rate to avoid jamming
interfaces, links, or paths.
0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x7f | chunkLength |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-+-+-+-+-+-+-+-+-------------/-+-------------/-+
|M| reserved | packetID \ | fragmentNum \ |
+-+-+-+-+-+-+-+-+-------------/-+-------------/-+
+---------------------------------------------------------------+
| packetFragment |
+---------------------------------------------------------------/
struct fragmentChunkPayload_t
{
bool_t moreFragments :1; // M
uintn_t reserved :7;
vlu_t packetID :variable*8;
vlu_t fragmentNum :variable*8;
uint8_t packetFragment[remainder()];
} :chunkLength*8;
moreFragments: If set, the indicated packet comprises additional
fragments. If clear, this fragment is the final fragment of the
packet.
reserved: Reserved for future use.
packetID: VLU, the identifier of this segmented packet. All
fragments of the same packet have the same packetID.
fragmentNum: VLU, the index of this fragment of the indicated
packet. The first fragment of the packet MUST be index 0.
Fragments are numbered consecutively.
Thornburgh Informational [Page 20]
^L
RFC 7016 Adobe RTMFP November 2013
packetFragment: The bytes of the indicated segment of the indicated
original plain RTMFP packet. A packetFragment MUST NOT be empty.
The use of this mechanism is detailed in Section 3.4.
2.3.2. Initiator Hello Chunk (IHello)
This chunk is sent by the initiator of a new session to begin the
startup handshake. This chunk is only allowed in a packet with
Session ID 0, encrypted with the Default Session Key, and having
packet mode 3 (Startup).
0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x30 | chunkLength |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-------------/-+-----------------------------------------------+
| epdLength \ | endpointDiscriminator (epdLength bytes) |
+-------------/-+-----------------------------------------------/
+---------------------------------------------------------------+
| tag |
+---------------------------------------------------------------/
struct ihelloChunkPayload_t
{
vlu_t epdLength :variable*8;
uint8_t endpointDiscriminator[epdLength];
uint8_t tag[remainder()];
} :chunkLength*8;
epdLength: VLU, the length of the following endpointDiscriminator
field in bytes.
endpointDiscriminator: The Endpoint Discriminator for the identity
with which the initiator wants to communicate.
tag: Initiator-provided data to be returned in a Responder Hello's
tagEcho field. The tag/tagEcho is used to match Responder Hellos
to the initiator's session startup state independent of the
responder's address.
The use of IHello is detailed in Section 3.5.1.
Thornburgh Informational [Page 21]
^L
RFC 7016 Adobe RTMFP November 2013
2.3.3. Forwarded Initiator Hello Chunk (FIHello)
This chunk is sent on behalf of an initiator by a Forwarder. It is
only allowed in packets of an established session having packet
mode 1 or 2. A receiver MAY treat this chunk as though it was an
Initiator Hello received directly from replyAddress. Alternatively,
if the receiver is selected by the Endpoint Discriminator, it MAY
respond to replyAddress with an Implied Redirect (Section 2.3.5).
0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x0f | chunkLength |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-------------/-+-----------------------------------------------+
| epdLength \ | endpointDiscriminator (epdLength bytes) |
+-------------/-+-----------------------------------------------/
+---------------------------------------------------------------+
| replyAddress |
+---------------------------------------------------------------/
+---------------------------------------------------------------+
| tag |
+---------------------------------------------------------------/
struct fihelloChunkPayload_t
{
vlu_t epdLength :variable*8;
uint8_t endpointDiscriminator[epdLength];
address_t replyAddress :variable*8;
uint8_t tag[remainder()];
} :chunkLength*8;
epdLength: VLU, the length of the following endpointDiscriminator
field in bytes.
endpointDiscriminator: The Endpoint Discriminator for the identity
with which the original initiator wants to communicate, copied
from the original Initiator Hello.
replyAddress: Address format (Section 2.1.5), the address that the
forwarding node derived from the received Initiator Hello, to
which the receiver should respond.
tag: Copied from the original Initiator Hello.
The use of FIHello is detailed in Section 3.5.1.5.
Thornburgh Informational [Page 22]
^L
RFC 7016 Adobe RTMFP November 2013
2.3.4. Responder Hello Chunk (RHello)
This chunk is sent by a responder in response to an Initiator Hello
or Forwarded Initiator Hello if the Endpoint Discriminator indicates
the responder's identity. This chunk is only allowed in a packet
with Session ID 0, encrypted with the Default Session Key, and having
packet mode 3 (Startup).
0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x70 | chunkLength |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-------------/-+-----------------------------------------------+
| tagLength \ | tagEcho (tagLength bytes) |
+-------------/-+-----------------------------------------------/
+-------------/-+-----------------------------------------------+
| cookieLength\ | cookie (cookieLength bytes) |
+-------------/-+-----------------------------------------------/
+---------------------------------------------------------------+
| responderCertificate |
+---------------------------------------------------------------/
struct rhelloChunkPayload_t
{
vlu_t tagLength :variable*8;
uint8_t tagEcho[tagLength];
vlu_t cookieLength :variable*8;
uint8_t cookie[cookieLength];
uint8_t responderCertificate[remainder()];
} :chunkLength*8;
tagLength: VLU, the length of the following tagEcho field in bytes.
tagEcho: The tag from the Initiator Hello, unaltered.
cookieLength: VLU, the length of the following cookie field
in bytes.
cookie: Responder-created state data to authenticate a future
Initiator Initial Keying message (in order to prevent denial-of-
service attacks).
responderCertificate: The responder's cryptographic credentials.
Thornburgh Informational [Page 23]
^L
RFC 7016 Adobe RTMFP November 2013
Note: This specification doesn't mandate a specific choice of
certificate format. The Cryptography Profile determines the syntax,
algorithms, and interpretation of the responderCertificate.
The use of RHello is detailed in Section 3.5.1.
2.3.5. Responder Redirect Chunk (Redirect)
This chunk is sent in response to an Initiator Hello or Forwarded
Initiator Hello to indicate that the requested endpoint can be
reached at one or more of the indicated addresses. A receiver can
add none, some, or all of the indicated addresses to the set of
addresses to which it is sending Initiator Hello messages for the
opening session associated with tagEcho. This chunk is only allowed
in a packet with Session ID 0, encrypted with the Default Session
Key, and having packet mode 3 (Startup).
Thornburgh Informational [Page 24]
^L
RFC 7016 Adobe RTMFP November 2013
0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x71 | chunkLength |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-------------/-+-----------------------------------------------+
| tagLength \ | tagEcho (tagLength bytes) |
+-------------/-+-----------------------------------------------/
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
| redirectDestination 1 |
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/
:
:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
| redirectDestination N |
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/
struct responderRedirectChunkPayload_t
{
vlu_t tagLength :variable*8;
uint8_t tagEcho[tagLength];
addressCount = 0;
while(remainder() > 0)
{
address_t redirectDestination :variable*8;
addressCount++;
}
if(0 == addressCount)
redirectDestination = packetSourceAddress();
} :chunkLength*8;
tagLength: VLU, the length of the following tagEcho field in bytes.
tagEcho: The tag from the Initiator Hello, unaltered.
redirectDestination: (Zero or more) Address format (Section 2.1.5)
addresses to add to the opening set for the indicated session.
If this chunk lists zero redirectDestination addresses, then this is
an Implied Redirect, and the indicated address is the address from
which the packet containing this chunk was received.
The use of Redirect is detailed in Sections 3.5.1.1.1, 3.5.1.1.2,
and 3.5.1.4.
Thornburgh Informational [Page 25]
^L
RFC 7016 Adobe RTMFP November 2013
2.3.6. RHello Cookie Change Chunk
This chunk SHOULD be sent by a responder to an initiator in response
to an Initiator Initial Keying if that chunk's cookie appears to have
been created by the responder but the cookie is incorrect (for
example, it includes a hash of the initiator's address, but the
initiator's address is different than the one that elicited the
Responder Hello containing the original cookie).
This chunk is only allowed in a packet encrypted with the Default
Session Key and having packet mode 3, and with the session ID
indicated in the initiatorSessionID field of the Initiator Initial
Keying to which this is a response.
0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x79 | chunkLength |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-------------/-+-----------------------------------------------+
| oldCookieLen\ | oldCookie (oldCookieLen bytes) |
+-------------/-+-----------------------------------------------/
+---------------------------------------------------------------+
| newCookie |
+---------------------------------------------------------------/
struct rhelloCookieChangeChunkPayload_t
{
vlu_t oldCookieLen :variable*8;
uint8_t oldCookie[oldCookieLen];
uint8_t newCookie[remainder()];
} :chunkLength*8;
oldCookieLen: VLU, the length of the following oldCookie field
in bytes.
oldCookie: The cookie that was sent in a previous Responder Hello
and Initiator Initial Keying.
newCookie: The new cookie that the responder would like sent (and
signed) in a replacement Initiator Initial Keying. The old and
new cookies need not have the same lengths.
On receipt of this chunk, the initiator SHOULD compute, sign, and
send a new Initiator Initial Keying having newCookie in place of
oldCookie. The use of this chunk is detailed in Section 3.5.1.2.
Thornburgh Informational [Page 26]
^L
RFC 7016 Adobe RTMFP November 2013
2.3.7. Initiator Initial Keying Chunk (IIKeying)
This chunk is sent by an initiator to establish a session with a
responder. The initiator MUST have obtained a valid cookie to use
with the responder, typically by receiving a Responder Hello from it.
This chunk is only allowed in a packet with Session ID 0, encrypted
with the Default Session Key, and having packet mode 3 (Startup).
0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x38 | chunkLength |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| initiatorSessionID |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-------------/-+-----------------------------------------------+
| cookieLength\ | cookieEcho |
+-------------/-+-----------------------------------------------/
+-------------/-+-----------------------------------------------+
| certLength \ | initiatorCertificate |
+-------------/-+-----------------------------------------------/
+-------------/-+-----------------------------------------------+
| skicLength \ | sessionKeyInitiatorComponent |
+-------------/-+-----------------------------------------------/
+---------------------------------------------------------------+
| signature |
+---------------------------------------------------------------/
struct iikeyingChunkPayload_t
{
struct
{
uint32_t initiatorSessionID;
vlu_t cookieLength :variable*8;
uint8_t cookieEcho[cookieLength];
vlu_t certLength :variable*8;
uint8_t initiatorCertificate[certLength];
vlu_t skicLength :variable*8;
uint8_t sessionKeyInitiatorComponent[skicLength];
} initiatorSignedParameters :variable*8;
uint8_t signature[remainder()];
} :chunkLength*8;
initiatorSessionID: The session ID to be used by the responder when
sending packets to the initiator.
Thornburgh Informational [Page 27]
^L
RFC 7016 Adobe RTMFP November 2013
cookieLength: VLU, the length of the following cookieEcho field
in bytes.
cookieEcho: The cookie from the Responder Hello, unaltered.
certLength: VLU, the length of the following initiatorCertificate
field in bytes.
initiatorCertificate: The initiator's identity credentials.
skicLength: VLU, the length of the following
sessionKeyInitiatorComponent field in bytes.
sessionKeyInitiatorComponent: The initiator's portion of the session
key negotiation according to the Cryptography Profile.
initiatorSignedParameters: The payload portion of this chunk up to
the signature field.
signature: The initiator's digital signature of the
initiatorSignedParameters according to the Cryptography Profile.
Note: This specification doesn't mandate a specific choice of
cryptography. The Cryptography Profile determines the syntax,
algorithms, and interpretation of the initiatorCertificate,
responderCertificate, sessionKeyInitiatorComponent,
sessionKeyResponderComponent, and signature, and how the
sessionKeyInitiatorComponent and sessionKeyResponderComponent are
combined to derive the session keys.
The use of IIKeying is detailed in Section 3.5.1.
Thornburgh Informational [Page 28]
^L
RFC 7016 Adobe RTMFP November 2013
2.3.8. Responder Initial Keying Chunk (RIKeying)
This chunk is sent by a responder in response to an Initiator Initial
Keying as the final phase of session startup. This chunk is only
allowed in a packet encrypted with the Default Session Key, having
packet mode 3 (Startup), and sent to the initiator with the
session ID specified by the initiatorSessionID field from the
Initiator Initial Keying.
0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x78 | chunkLength |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| responderSessionID |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-------------/-+-----------------------------------------------+
| skrcLength \ | sessionKeyResponderComponent |
+-------------/-+-----------------------------------------------/
+---------------------------------------------------------------+
| signature |
+---------------------------------------------------------------/
struct rikeyingChunkPayload_t
{
struct
{
uint32_t responderSessionID;
vlu_t skrcLength :variable*8;
uint8_t sessionKeyResponderComponent[skrcLength];
} responderSignedParametersPortion :variable*8;
uint8_t signature[remainder()];
} :chunkLength*8;
struct
{
responderSignedParametersPortion;
sessionKeyInitiatorComponent;
} responderSignedParameters;
responderSessionID: The session ID to be used by the initiator when
sending packets to the responder.
skrcLength: VLU, the length of the following
sessionKeyResponderComponent field in bytes.
sessionKeyResponderComponent: The responder's portion of the session
key negotiation according to the Cryptography Profile.
Thornburgh Informational [Page 29]
^L
RFC 7016 Adobe RTMFP November 2013
responderSignedParametersPortion: The payload portion of this chunk
up to the signature field.
signature: The responder's digital signature of the
responderSignedParameters (see below) according to the
Cryptography Profile.
responderSignedParameters: The concatenation of the
responderSignedParametersPortion (the payload portion of this
chunk up to the signature field) and the
sessionKeyInitiatorComponent from the Initiator Initial Keying to
which this chunk is a response.
Note: This specification doesn't mandate a specific choice of
cryptography. The Cryptography Profile determines the syntax,
algorithms, and interpretation of the initiatorCertificate,
responderCertificate, sessionKeyInitiatorComponent,
sessionKeyResponderComponent, and signature, and how the
sessionKeyInitiatorComponent and sessionKeyResponderComponent are
combined to derive the session keys.
Once the responder has computed the sessionKeyResponderComponent, it
has all of the information and state necessary for an established
session with the initiator. Once the responder has sent this chunk
to the initiator, the session is established and ready to carry flows
of user data.
Once the initiator receives, verifies, and processes this chunk, it
has all of the information and state necessary for an established
session with the responder. The session is established and ready to
carry flows of user data.
The use of RIKeying is detailed in Section 3.5.1.
Thornburgh Informational [Page 30]
^L
RFC 7016 Adobe RTMFP November 2013
2.3.9. Ping Chunk
This chunk is sent in order to elicit a Ping Reply from the receiver.
It is only allowed in a packet belonging to an established session
and having packet mode 1 or 2.
0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x01 | chunkLength |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
| message |
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/
struct pingChunkPayload_t
{
uint8_t message[chunkLength];
} :chunkLength*8;
message: The (potentially empty) message that is expected to be
returned by the other end of the session in a Ping Reply.
The receiver of this chunk SHOULD reply as immediately as is
practical with a Ping Reply.
Ping and the expected Ping Reply are typically used for session
keepalive, endpoint address change verification, and path MTU
discovery. See Section 3.5.4 for details.
Thornburgh Informational [Page 31]
^L
RFC 7016 Adobe RTMFP November 2013
2.3.10. Ping Reply Chunk
This chunk is sent in response to a Ping chunk. It is only allowed
in a packet belonging to an established session and having packet
mode 1 or 2.
0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x41 | chunkLength |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
| messageEcho |
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/
struct pingReplyChunkPayload_t
{
uint8_t messageEcho[chunkLength];
} :chunkLength*8;
messageEcho: The message from the Ping to which this is a response,
unaltered.
Thornburgh Informational [Page 32]
^L
RFC 7016 Adobe RTMFP November 2013
2.3.11. User Data Chunk
This chunk is the basic unit of transmission for the user messages of
a flow. A user message comprises one or more fragments. Each
fragment is carried in its own chunk and has a unique sequence number
in its flow. It is only allowed in a packet belonging to an
established session and having packet mode 1 or 2.
0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x10 | chunkLength |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-+-+-+-+-+-+-+-+
|O|r| F | r |A|F|
|P|s| R | s |B|I|
|T|v| A | v |N|N|
+-+-+-+-+-+-+-+-+
+-------------/-+-------------/-+-------------/-+
| flowID \ | seq# \ | fsnOffset \ |
+-------------/-+-------------/-+-------------/-+
+~~~/~~~/~~~~~~~+ +~~~/~~~/~~~~~~~+-------------/-+
| L \ T \ V |... options ...| L \ T \ V | 0 \ |
\~~~/~~~/~~~~~~~+ [if(OPT)] +~~~/~~~/~~~~~~~+-------------/-/
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
| userData |
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/
struct userDataChunkPayload_t
{
bool_t optionsPresent :1; // "OPT"
uintn_t reserved1 :1; // "rsv"
uintn_t fragmentControl :2; // "FRA"
// 0=whole, 1=begin, 2=end, 3=middle
uintn_t reserved2 :2; // "rsv"
bool_t abandon :1; // "ABN"
bool_t final :1; // "FIN"
vlu_t flowID :variable*8;
vlu_t sequenceNumber :variable*8; // "seq#"
vlu_t fsnOffset :variable*8;
forwardSequenceNumber = sequenceNumber - fsnOffset;
if(optionsPresent)
optionList_t options :variable*8;
uint8_t userData[remainder()];
} :chunkLength*8;
optionsPresent: If set, indicates the presence of an option list
before the user data. If clear, there is no option list in this
chunk.
Thornburgh Informational [Page 33]
^L
RFC 7016 Adobe RTMFP November 2013
fragmentControl: Indicates how this fragment is assembled,
potentially with others, into a complete user message. Possible
values:
0: This fragment is a complete message.
1: This fragment is the first of a multi-fragment message.
2: This fragment is the last of a multi-fragment message.
3: This fragment is in the middle of a multi-fragment message.
A single-fragment user message has a fragment control of
"0-whole". When a message has more than one fragment, the first
fragment has a fragment control of "1-begin", then zero or more
"3-middle" fragments, and finally a "2-end" fragment. The
sequence numbers of a multi-fragment message MUST be contiguous.
abandon: If set, this sequence number has been abandoned by the
sender. The userData, if any, MUST be ignored.
final: If set, this is the last sequence number of the flow.
flowID: VLU, the flow identifier.
sequenceNumber: VLU, the sequence number of this fragment.
Fragments are assigned contiguous increasing sequence numbers in a
flow. The first sequence number of a flow SHOULD be 1. The first
sequence number of a flow MUST be greater than zero. Sequence
numbers are unbounded and do not wrap.
fsnOffset: VLU, the difference between the sequence number and the
Forward Sequence Number. This field MUST NOT be zero if the
abandon flag is not set. This field MUST NOT be greater than
sequenceNumber.
forwardSequenceNumber: The flow sender will not send (or resend) any
fragment with a sequence number less than or equal to the Forward
Sequence Number.
options: If the optionsPresent flag is set, a list of zero or more
Options terminated by a Marker is present. See Section 2.3.11.1
for defined options.
userData: The actual user data for this fragment.
The use of User Data is detailed in Section 3.6.2.
Thornburgh Informational [Page 34]
^L
RFC 7016 Adobe RTMFP November 2013
2.3.11.1. Options for User Data
This section lists options that may appear in User Data option lists.
A conforming implementation MUST support the options in this section.
A flow receiver MUST reject a flow containing a flow option that is
not understood if the option type is less than 8192 (0x2000). A flow
receiver MUST ignore any flow option that is not understood if the
option type is 8192 or greater.
The following option type codes are defined for User Data:
0x00: User's Per-Flow Metadata (Section 2.3.11.1.1)
0x0a: Return Flow Association (Section 2.3.11.1.2)
2.3.11.1.1. User's Per-Flow Metadata
This option conveys the user's per-flow metadata for the flow to
which it's attached.
+-------------/-+-------------/-+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
| length \ | 0x00 \ | userMetadata |
+-------------/-+-------------/-+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/
struct userMetadataOptionValue_t
{
uint8_t userMetadata[remainder()];
} :remainder()*8;
The user associates application-defined metadata with each flow. The
metadata does not change over the life of the flow. Every flow MUST
have metadata. A flow sender MUST send this option with the first
User Data chunk for this flow in each packet until an acknowledgement
for this flow is received. A flow sender SHOULD NOT send this option
more than once for each flow in any one packet. A flow sender SHOULD
NOT send this option for a flow once the flow has been acknowledged.
This specification doesn't mandate the encoding, syntax, or
interpretation of the user's per-flow metadata; this is determined by
the application.
The userMetadata SHOULD NOT exceed 512 bytes. The userMetadata MAY
be 0 bytes in length.
Thornburgh Informational [Page 35]
^L
RFC 7016 Adobe RTMFP November 2013
2.3.11.1.2. Return Flow Association
A new flow can be considered to be in return (or response) to a flow
sent by the other endpoint. This option encodes the receive flow
identifier to which this new sending flow is a response.
+-------------/-+-------------/-+-------------/-+
| length \ | 0x0a \ | flowID \ |
+-------------/-+-------------/-+-------------/-+
struct returnFlowAssociationOptionValue_t
{
vlu_t flowID :variable*8;
} :variable*8;
Consider endpoints A and B. Endpoint A begins a flow with
identifier 5 to endpoint B. A is the flow sender for A's flowID=5,
and B is the flow receiver for A's flowID=5. B begins a return flow
with identifier 7 to A in response to A's flowID=5. B is the flow
sender for B's flowID=7, and A is the flow receiver for B's flowID=7.
B sends this option with flowID set to 5 to indicate that B's
flowID=7 is in response to and associated with A's flowID=5.
If there is a return association, the flow sender MUST send this
option with the first User Data chunk for this flow in each packet
until an acknowledgement for this flow is received. A flow sender
SHOULD NOT send this option more than once for each flow in any one
packet. A flow sender SHOULD NOT send this option for a flow once
the flow has been acknowledged.
A flow MUST NOT indicate more than one return association.
A flow MUST indicate its return association, if any, upon its first
transmission of a User Data chunk. A return association can't be
added to a sending flow after it begins.
A flow receiver MUST reject a new receiving flow having a return flow
association that does not indicate an F_OPEN sending flow.
Thornburgh Informational [Page 36]
^L
RFC 7016 Adobe RTMFP November 2013
2.3.12. Next User Data Chunk
This chunk is equivalent to the User Data chunk for purposes of
sending the user messages of a flow. When used, it MUST follow a
User Data chunk or another Next User Data chunk in the same packet.
0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x11 | chunkLength |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-+-+-+-+-+-+-+-+
|O|r| F | r |A|F|
|P|s| R | s |B|I|
|T|v| A | v |N|N|
+-+-+-+-+-+-+-+-+
+~~~/~~~/~~~~~~~+ +~~~/~~~/~~~~~~~+-------------/-+
| L \ T \ V |... options ...| L \ T \ V | 0 \ |
\~~~/~~~/~~~~~~~+ [if(OPT)] +~~~/~~~/~~~~~~~+-------------/-/
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
| userData |
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/
struct nextUserDataChunkPayload_t
{
bool_t optionsPresent :1; // "OPT"
uintn_t reserved1 :1; // "rsv"
uintn_t fragmentControl :2; // "FRA"
// 0=whole, 1=begin, 2=end, 3=middle
uintn_t reserved2 :2; // "rsv"
bool_t abandon :1; // "ABN"
bool_t final :1; // "FIN"
if(optionsPresent)
optionList_t options :variable*8;
uint8_t userData[remainder()];
} :chunkLength*8;
This chunk is considered to be for the same flowID as the most
recently preceding User Data or Next User Data chunk in the same
packet, having the same Forward Sequence Number, and having the next
sequence number. The optionsPresent, fragmentControl, abandon, and
final flags, and the options (if present), have the same
interpretation as for the User Data chunk.
Thornburgh Informational [Page 37]
^L
RFC 7016 Adobe RTMFP November 2013
...
----------+------------------------------------
10 00 07 | User Data chunk, length=7
00 | OPT=0, FRA=0 "whole", ABN=0, FIN=0
02 05 03 | flowID=2, seq#=5, fsn=(5-3)=2
00 01 02 | data 3 bytes: 00, 01, 02
----------+------------------------------------
11 00 04 | Next User Data chunk,length=4
00 | OPT=0, FRA=0 "whole", ABN=0, FIN=0
| flowID=2, seq#=6, fsn=2
03 04 05 | data 3 bytes: 03, 04, 05
----------+------------------------------------
11 00 04 | Next User Data chunk, length=4
00 | OPT=0, FRA=0 "whole", ABN=0, FIN=0
| flowID=2, seq#=7, fsn=2
06 07 08 | data 3 bytes: 06, 07, 08
----------+------------------------------------
Figure 3: Sequential Messages in One Packet Using Next User Data
The use of Next User Data is detailed in Section 3.6.2.3.2.
Thornburgh Informational [Page 38]
^L
RFC 7016 Adobe RTMFP November 2013
2.3.13. Data Acknowledgement Bitmap Chunk (Bitmap Ack)
This chunk is sent by the flow receiver to indicate to the flow
sender the User Data fragment sequence numbers that have been
received for one flow. It is only allowed in a packet belonging to
an established session and having packet mode 1 or 2.
The flow receiver can choose to acknowledge User Data with this chunk
or with a Range Ack. It SHOULD choose whichever format has the most
compact encoding of the sequence numbers received.
0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x50 | chunkLength |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-------------/-+-------------/-+-------------/-+
| flowID \ | bufAvail \ | cumAck \ |
+-------------/-+-------------/-+-------------/-+
+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+
|C|C|C|C|C|C|C|C|C|C|C|C|C|C|C|C|C|C|C|C|C|C|C|C|
|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|
|9|8|7|6|5|4|3|2|1|1|1|1|1|1|1|1|2|2|2|2|2|2|1|1| ....
| | | | | | | | |7|6|5|4|3|2|1|0|5|4|3|2|1|0|9|8|
+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+
struct dataAckBitmapChunkPayload_t
{
vlu_t flowID :variable*8;
vlu_t bufferBlocksAvailable :variable*8; // "bufAvail"
vlu_t cumulativeAck :variable*8; // "cumAck"
bufferBytesAvailable = bufferBlocksAvailable * 1024;
acknowledge(0 through cumulativeAck);
ackCursor = cumulativeAck + 1;
while(remainder() > 0)
{
for(bitPosition = 8; bitPosition > 0; bitPosition--)
{
bool_t bit :1;
if(bit)
acknowledge(ackCursor + bitPosition);
}
ackCursor += 8;
}
} :chunkLength*8;
Thornburgh Informational [Page 39]
^L
RFC 7016 Adobe RTMFP November 2013
flowID: VLU, the flow identifier.
bufferBlocksAvailable: VLU, the number of 1024-byte blocks of User
Data that the receiver is currently able to accept.
Section 3.6.3.5 describes how to calculate this value.
cumulativeAck: VLU, the acknowledgement of every fragment sequence
number in this flow that is less than or equal to this value.
This MUST NOT be less than the highest Forward Sequence Number
received in this flow.
bit field: A sequence of zero or more bytes representing a bit field
of received fragment sequence numbers after the cumulative
acknowledgement, least significant bit first. A set bit indicates
receipt of a sequence number. A clear bit indicates that sequence
number was not received. The least significant bit of the first
byte is the second sequence number following the cumulative
acknowledgement, the next bit is the third sequence number
following, and so on.
Figure 4 shows an example Bitmap Ack indicating acknowledgement of
fragment sequence numbers 0 through 16, 18, 21 through 24, 27,
and 28.
50 00 05 | Bitmap Ack, length=5 bytes
05 7f 10 | flowID=5, bufAvail=127*1024 bytes, cumAck=0..16
79 06 | 01111001 00000110 = 18, 21, 22, 23, 24, 27, 28
Figure 4: Example Bitmap Ack
Thornburgh Informational [Page 40]
^L
RFC 7016 Adobe RTMFP November 2013
2.3.14. Data Acknowledgement Ranges Chunk (Range Ack)
This chunk is sent by the flow receiver to indicate to the flow
sender the User Data fragment sequence numbers that have been
received for one flow. It is only allowed in a packet belonging to
an established session and having packet mode 1 or 2.
The flow receiver can choose to acknowledge User Data with this chunk
or with a Bitmap Ack. It SHOULD choose whichever format has the most
compact encoding of the sequence numbers received.
0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x51 | chunkLength |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-------------/-+-------------/-+-------------/-+
| flowID \ | bufAvail \ | cumAck \ |
+-------------/-+-------------/-+-------------/-+
+~~~~~~~~~~~~~/~+~~~~~~~~~~~~~/~+
| #holes-1 \ | #recv-1 \ |
+~~~~~~~~~~~~~/~+~~~~~~~~~~~~~/~+
:
:
+~~~~~~~~~~~~~/~+~~~~~~~~~~~~~/~+
| #holes-1 \ | #recv-1 \ |
+~~~~~~~~~~~~~/~+~~~~~~~~~~~~~/~+
struct dataAckRangesChunkPayload_t
{
vlu_t flowID :variable*8;
vlu_t bufferBlocksAvailable :variable*8; // "bufAvail"
vlu_t cumulativeAck :variable*8; // "cumAck"
bufferBytesAvailable = bufferBlocksAvailable * 1024;
acknowledge(0 through cumulativeAck);
ackCursor = cumulativeAck;
while(remainder() > 0)
{
vlu_t holesMinusOne :variable*8; // "#holes-1"
vlu_t receivedMinusOne :variable*8; // "#recv-1"
ackCursor++;
rangeFrom = ackCursor + holesMinusOne + 1;
rangeTo = rangeFrom + receivedMinusOne;
acknowledge(rangeFrom through rangeTo);
ackCursor = rangeTo;
}
} :chunkLength*8;
Thornburgh Informational [Page 41]
^L
RFC 7016 Adobe RTMFP November 2013
flowID: VLU, the flow identifier.
bufferBlocksAvailable: VLU, the number of 1024-byte blocks of User
Data that the receiver is currently able to accept.
Section 3.6.3.5 describes how to calculate this value.
cumulativeAck: VLU, the acknowledgement of every fragment sequence
number in this flow that is less than or equal to this value.
This MUST NOT be less than the highest Forward Sequence Number
received in this flow.
holesMinusOne / receivedMinusOne: Zero or more acknowledgement
ranges, run-length encoded. Runs are encoded as zero or more
pairs of VLUs indicating the number (minus one) of missing
sequence numbers followed by the number (minus one) of received
sequence numbers, starting at the cumulative acknowledgement.
NOTE: If a parser syntax error is encountered here (that is, if
the chunk is truncated such that not enough bytes remain to
completely encode both VLUs of the acknowledgement range), then
treat and process this chunk as though it was properly formed up
to the last completely encoded range.
Figure 5 shows an example Range Ack indicating acknowledgement of
fragment sequence numbers 0 through 16, 18, 21, 22, 23, and 24.
51 00 07 | Range Ack, length=7
05 7f 10 | flowID=5, bufAvail=127*1024 bytes, cumAck=0..16
00 00 | holes=1, received=1 -- missing 17, received 18
01 03 | holes=2, received=4 -- missing 19..20, received 21..24
Figure 5: Example Range Ack
Figure 6 shows an example Range Ack indicating acknowledgement of
fragment sequence numbers 0 through 16 and 18, with a truncated
last range. Note that the truncation and parse error does not
abort the entire chunk in this case.
51 00 07 | Range Ack, length=9
05 7f 10 | flowID=5, bufAvail=127*1024 bytes, cumAck=0..16
00 00 | holes=1, received=1 -- missing 17, received 18
01 83 | holes=2, received=VLU parse error, ignore this range
Figure 6: Example Truncated Range Ack
Thornburgh Informational [Page 42]
^L
RFC 7016 Adobe RTMFP November 2013
2.3.15. Buffer Probe Chunk
This chunk is sent by the flow sender in order to request the current
available receive buffer (in the form of a Data Acknowledgement) for
a flow. It is only allowed in a packet belonging to an established
session and having packet mode 1 or 2.
0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x18 | chunkLength |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-------------/-+
| flowID \ |
+-------------/-+
struct bufferProbeChunkPayload_t
{
vlu_t flowID :variable*8;
} :chunkLength*8;
flowID: VLU, the flow identifier.
The receiver of this chunk SHOULD reply as immediately as is
practical with a Data Acknowledgement.
2.3.16. Flow Exception Report Chunk
This chunk is sent by the flow receiver to indicate that it is not
(or is no longer) interested in the flow and would like the flow
sender to close the flow. This chunk SHOULD precede every Data
Acknowledgement chunk for the same flow in this condition.
This chunk is only allowed in a packet belonging to an established
session and having packet mode 1 or 2.
0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x5e | chunkLength |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-------------/-+-------------/-+
| flowID \ | exception \ |
+-------------/-+-------------/-+
struct flowExceptionReportChunkPayload_t
{
vlu_t flowID :variable*8;
vlu_t exception :variable*8;
} :chunkLength*8;
Thornburgh Informational [Page 43]
^L
RFC 7016 Adobe RTMFP November 2013
flowID: VLU, the flow identifier.
exception: VLU, the application-defined exception code being
reported.
A receiving RTMFP might reject a flow automatically, for example if
it is missing metadata, or if an invalid return association is
specified. In circumstances where an RTMFP rejects a flow
automatically, the exception code MUST be 0. The application can
specify any exception code, including 0, when rejecting a flow. All
non-zero exception codes are reserved for the application.
2.3.17. Session Close Request Chunk (Close)
This chunk is sent to cleanly terminate a session. It is only
allowed in a packet belonging to an established or closing session
and having packet mode 1 or 2.
0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x0c | 0 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
This chunk has no payload.
The use of Close is detailed in Section 3.5.5.
2.3.18. Session Close Acknowledgement Chunk (Close Ack)
This chunk is sent in response to a Session Close Request to indicate
that the sender has terminated the session. It is only allowed in a
packet belonging to an established or closing session and having
packet mode 1 or 2.
0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x4c | 0 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
This chunk has no payload.
The use of Close Ack is detailed in Section 3.5.5.
Thornburgh Informational [Page 44]
^L
RFC 7016 Adobe RTMFP November 2013
3. Operation
3.1. Overview
+--------+ +--------+
| Peer A | S E S S I O N | Peer B |
| /=============================\ |
| || Flows || |
| ||---------------------------->|| |
| ||---------------------------->|| |
| ||<----------------------------|| |
| ||<----------------------------|| |
| ||<----------------------------|| |
| \=============================/ |
| | | |
| | +--------+
| |
| | +--------+
| | S E S S I O N | Peer C |
| /=============================\ |
| || Flows || |
| ||---------------------------->|| |
| ||<----------------------------|| |
| ||<----------------------------|| |
| \=============================/ |
| | | |
+--------+ +--------+
Figure 7: Sessions between Pairs of Communicating Endpoints
Between any pair of communicating endpoints is a single,
bidirectional, secured, congestion controlled session.
Unidirectional flows convey messages from one end to the other within
the session.
An endpoint initiates a session to a far end when communication is
desired. An initiator begins with one or more candidate destination
socket addresses, and it may learn and try more candidate addresses
during startup handshaking. Eventually, a first suitable response is
received, and that endpoint is selected. Startup proceeds to the
selected endpoint. In the case of session startup glare, one
endpoint is the prevailing initiator and the other assumes the role
of responder. Encryption keys and session identifiers are negotiated
between the endpoints, and the session is established.
Each endpoint may begin sending message flows to the other end. For
each flow, the far end may accept it and deliver its messages to the
user, or it may reject the flow and transmit an exception to the
Thornburgh Informational [Page 45]
^L
RFC 7016 Adobe RTMFP November 2013
sender. The flow receiver may close and reject a flow at a later
time, after first accepting it. The flow receiver acknowledges all
data sent to it, regardless of whether the flow was accepted.
Acknowledgements drive a congestion control mechanism.
An endpoint may have concurrent sessions with other far endpoints.
The multiple sessions are distinguished by a session identifier
rather than by socket address. This allows an endpoint's address to
change mid-session without having to tear down and re-establish a
session. The existing cryptographic state for a session can be used
to verify a change of address while protecting against session
hijacking or denial of service.
A sender may indicate to a receiver that some user messages are of a
time critical or real-time nature. A receiver may indicate to
senders on concurrent sessions that it is receiving time critical
messages from another endpoint. The other senders SHOULD modify
their congestion control parameters to yield capacity to the session
carrying time critical messages.
A sender may close a flow. The flow is completed when the receiver
has no outstanding gaps before the final fragment of the flow. The
sender and receiver reserve a completed flow's identifier for a time
to allow in-flight messages to drain from the network.
Eventually, neither end will have any flows open to the other. The
session will be idle and quiescent. Either end may reliably close
the session to recover its resources.
In certain circumstances, an endpoint may be ceasing operation and
not have time to wait for acknowledgement of a reliable session
close. In this case, the halting endpoint may send an abrupt session
close to advise the far end that it is halting immediately.
3.2. Endpoint Identity
Each RTMFP endpoint has an identity. The identity is encoded in a
certificate. This specification doesn't mandate any particular
certificate format, cryptographic algorithms, or cryptographic
properties for certificates.
An endpoint is named by an Endpoint Discriminator. This
specification doesn't mandate any particular format for Endpoint
Discriminators.
An Endpoint Discriminator MAY select more than one identity and MAY
match more than one distinct certificate.
Thornburgh Informational [Page 46]
^L
RFC 7016 Adobe RTMFP November 2013
Multiple distinct Endpoint Discriminators MAY match one certificate.
It is RECOMMENDED that multiple endpoints not have the same identity.
Entities with the same identity are indistinguishable during session
startup; this situation could be undesirable in some applications.
An endpoint MAY have more than one address.
The Cryptography Profile implements the following functions for
identities, certificates, and Endpoint Discriminators, whose
operation MUST be deterministic:
o Test whether a given certificate is authentic. Authenticity can
comprise verifying an issuer signature chain in a public key
infrastructure.
o Test whether a given Endpoint Discriminator selects a given
certificate.
o Test whether a given Endpoint Discriminator selects the local
endpoint.
o Generate a Canonical Endpoint Discriminator for a given
certificate. Canonical Endpoint Discriminators for distinct
identities SHOULD be distinct. If two distinct identities have
the same Canonical Endpoint Discriminator, an initiator might
abort a new opening session to the second identity
(Section 3.5.1.1.1); this behavior might not be desirable.
o Given a certificate, a message, and a digital signature over the
message, test whether the signature is valid and generated by the
owner of the certificate.
o Generate a digital signature for a given message corresponding to
the near identity.
o Given the near identity and a far certificate, determine which one
shall prevail as Initiator and which shall assume the Responder
role in the case of startup glare. The far end MUST arrive at the
same conclusion. A comparison function can comprise performing a
lexicographic ordering of the binary certificates, declaring the
far identity the prevailing endpoint if the far certificate is
ordered before the near certificate, and otherwise declaring the
near identity to be the prevailing endpoint.
Thornburgh Informational [Page 47]
^L
RFC 7016 Adobe RTMFP November 2013
o Given a first certificate and a second certificate, test whether a
new incoming session from the second shall override an existing
session with the first. It is RECOMMENDED that the test comprise
testing whether the certificates are bitwise identical.
All other semantics for certificates and Endpoint Discriminators are
determined by the Cryptography Profile and the application.
3.3. Packet Multiplex
An RTMFP typically has one or more interfaces through which it
communicates with other RTMFP endpoints. RTMFP can communicate with
multiple distinct other RTMFP endpoints through each local interface.
Session multiplexing over a shared interface can facilitate peer-to-
peer communications through a NAT, by enabling third-party endpoints
such as Forwarders (Section 3.5.1.5) and Redirectors
(Section 3.5.1.4) to observe the translated public address and inform
peers of the translation.
An interface is typically a UDP socket (Section 2.2.1) but MAY be any
suitable datagram transport service where endpoints can be addressed
by IPv4 or IPv6 socket addresses.
RTMFP uses a session ID to multiplex and demultiplex communications
with distinct endpoints (Section 2.2.2), in addition to the endpoint
socket address. This allows an RTMFP to detect a far-end address
change (as might happen, for example, in mobile and wireless
scenarios) and allows communication sessions to survive address
changes. This also allows an RTMFP to act as a Forwarder or
Redirector for an endpoint with which it has an active session, by
distinguishing startup packets from those of the active session.
On receiving a packet, an RTMFP decodes the session ID to look up the
corresponding session information context and decryption key.
Session ID 0 is reserved for session startup and MUST NOT be used for
an active session. A packet for Session ID 0 uses the Default
Session Key as defined by the Cryptography Profile.
3.4. Packet Fragmentation
When an RTMFP packet (Section 2.2.4) is unavoidably larger than the
path MTU (such as a startup packet containing an RHello
(Section 2.3.4) or IIKeying (Section 2.3.7) chunk with a large
certificate), it can be fragmented into segments that do not exceed
the path MTU by using the Packet Fragment chunk (Section 2.3.1).
Thornburgh Informational [Page 48]
^L
RFC 7016 Adobe RTMFP November 2013
The packet fragmentation mechanism SHOULD be used only to segment
unavoidably large packets. Accordingly, this mechanism SHOULD be
employed only during session startup with Session ID 0. This
mechanism MUST NOT be used instead of the natural fragmentation
mechanism of the User Data (Section 2.3.11) and Next User Data
(Section 2.3.12) chunks for dividing the messages of the user's data
flows into segments that do not exceed the path MTU.
A fragmented plain RTMFP packet is reassembled by concatenating the
packetFragment fields of the fragments for the packet in contiguous
ascending order, starting from index 0 through and including the
final fragment.
When reassembling packets for Session ID 0, a receiver SHOULD
identify the packets by the socket address from which the packet
containing the fragment was received, as well as the indicated
packetID.
A receiver SHOULD allow up to 60 seconds to completely receive a
fragmented packet for which progress is being made. A packet is
progressing if at least one new fragment for it was received in the
last second.
A receiver MUST discard a Packet Fragment chunk having an empty
packetFragment field.
The mode of each packet containing Packet Fragments for the same
fragmented packet MUST match the mode of the fragmented packet. A
receiver MUST discard any new Packet Fragment chunk received in a
packet with a mode different from the mode of the packet containing
the first received fragment. A receiver MUST discard any reassembled
packet with a mode different than the packets containing its
fragments.
In order to avoid jamming the network, the sender MUST rate limit
packet transmission. In the absence of specific path capacity
information (for instance, during session startup), a sender SHOULD
NOT send more than 4380 bytes nor more than four packets per distinct
endpoint every 200 ms.
To avoid resource exhaustion, a receiver SHOULD limit the number of
concurrent packet reassembly buffers and the size of each buffer.
Limits can depend, for example, on the expected size of reassembled
packets, on the rate at which fragmented packets are expected to be
received, on the expected degree of interleaving, and on the expected
function of the receiver. Limits can depend on the available
resources of the receiver. There can be different limits for packets
with Session ID 0 and packets for established sessions. For example,
Thornburgh Informational [Page 49]
^L
RFC 7016 Adobe RTMFP November 2013
a busy server might need to allow for several hundred concurrent
packet reassembly buffers to accommodate hundreds of connection
requests per second with potentially interleaved fragments, but a
client device with constrained resources could allow just a few
reassembly buffers. In the absence of specific information regarding
the expected size of reassembled packets, a receiver should set the
limit for each packet reassembly buffer to 65536 bytes.
3.5. Sessions
A session is the protocol relationship between a pair of
communicating endpoints, comprising the shared and endpoint-specific
information context necessary to carry out the communication. The
session context at each end includes at least:
o TS_RX: the last timestamp received from the far end;
o TS_RX_TIME: the time at which TS_RX was first observed to be
different than its previous value;
o TS_ECHO_TX: the last timestamp echo sent to the far end;
o MRTO: the measured retransmission timeout;
o ERTO: the effective retransmission timeout;
o Cryptographic keys for encrypting and decrypting packets, and for
verifying the validity of packets, according to the Cryptography
Profile;
o Cryptographic near and far nonces according to the Cryptography
Profile, where the near nonce is the far end's far nonce, and vice
versa;
o The certificate of the far end;
o The receive session identifier, used by the far end when sending
packets to this end;
o The send session identifier to use when sending packets to the far
end;
o DESTADDR: the destination socket address to use when sending
packets to the far end;
o The set of all sending flow contexts (Section 3.6.2);
o The set of all receiving flow contexts (Section 3.6.3);
Thornburgh Informational [Page 50]
^L
RFC 7016 Adobe RTMFP November 2013
o The transmission budget, which controls the rate at which data is
sent into the network (for example, a congestion window);
o S_OUTSTANDING_BYTES: the total amount of user message data
outstanding, or in flight, in the network -- that is, the sum of
the F_OUTSTANDING_BYTES of each sending flow in the session;
o RX_DATA_PACKETS: a count of the number of received packets
containing at least one User Data chunk since the last
acknowledgement was sent, initially 0;
o ACK_NOW: a boolean flag indicating whether an acknowledgement
should be sent immediately, initially false;
o DELACK_ALARM: an alarm to trigger an acknowledgement after a
delay, initially unset;
o The state, at any time being one of the following values: the
opening states S_IHELLO_SENT and S_KEYING_SENT, the open state
S_OPEN, the closing states S_NEARCLOSE and S_FARCLOSE_LINGER, and
the closed states S_CLOSED and S_OPEN_FAILED; and
o The role -- either Initiator or Responder -- of this end of the
session.
Thornburgh Informational [Page 51]
^L
RFC 7016 Adobe RTMFP November 2013
Note: The following diagram is only a summary of state transitions
and their causing events, and is not a complete operational
specification.
rcv IIKeying Glare
far prevails +-------------+ ultimate open timeout
+--------------|S_IHELLO_SENT|-------------+
| +-------------+ |
| |rcv RHello |
| | v
| v +-------------+
|<-----------(duplicate session?) |S_OPEN_FAILED|
| yes |no +-------------+
| | ^
| rcv IIKeying Glare v |
| far prevails +-------------+ |
|<-------------|S_KEYING_SENT|-------------+
| +-------------+ ultimate open timeout
| |rcv RIKeying
| |
| rcv v
| +-+ IIKeying +--------+ rcv Close Request
| |X|---------->| S_OPEN |--------------------+
| +-+ +--------+ |
| | |ABRUPT CLOSE |
| ORDERLY CLOSE| |or rcv Close Ack |
| | |or rcv IIKeying |
| | | session override |
| | +-------+ |
| v | v
| +-----------+ | +-----------------+
| |S_NEARCLOSE| | |S_FARCLOSE_LINGER|
| +-----------+ | +-----------------+
| rcv Close Ack| | |rcv Close Ack
| or 90 seconds| v |or 19 seconds
| | +--------+ |
| +------>|S_CLOSED|<---------+
+-------------------------->| |
+--------+
Figure 8: Session State Diagram
Thornburgh Informational [Page 52]
^L
RFC 7016 Adobe RTMFP November 2013
3.5.1. Startup
3.5.1.1. Normal Handshake
RTMFP sessions are established with a 4-way handshake in two round
trips. The initiator begins by sending an IHello to one or more
candidate addresses for the desired destination endpoint. A
responder statelessly sends an RHello in response. The first correct
RHello received at the initiator is selected; all others are ignored.
The initiator computes its half of the session keying and sends an
IIKeying. The responder receives the IIKeying and, if it is
acceptable, computes its half of the session keying, at which point
it can also compute the shared session keying and session nonces.
The responder creates a new S_OPEN session with the initiator and
sends an RIKeying. The initiator receives the RIKeying and, if it is
acceptable, computes the shared session keying and session nonces.
The initiator's session is now S_OPEN.
. Initiator Responder .
| IHello |
|(EPD,Tag) |
S_IHELLO_SENT |(SID=0) |
|------------------------------->|
| |
| RHello |
| (Tag,Cookie,RCert)|
| (SID=0)|
|<-------------------------------|
S_KEYING_SENT | |
| IIKeying |
|(ISID,Cookie,ICert,SKIC,ISig) |
|(SID=0) |
|------------------------------->|
| |
| RIKeying |
| (RSID,SKRC,RSig)|
| (SID=ISID,Key=Default)| S_OPEN
|<-------------------------------|
S_OPEN | |
| S E S S I O N |
|<-------------------(SID=ISID)--|
|--(SID=RSID)------------------->|
Figure 9: Normal Handshake
In the following sections, the handshake is detailed from the
perspectives of the initiator and responder.
Thornburgh Informational [Page 53]
^L
RFC 7016 Adobe RTMFP November 2013
3.5.1.1.1. Initiator
The initiator determines that a session is needed for an Endpoint
Discriminator. The initiator creates state for a new opening session
and begins with a candidate endpoint address set containing at least
one address. The new session is placed in the S_IHELLO_SENT state.
If the session does not move to the S_OPEN state before an ultimate
open timeout, the session has failed and moves to the S_OPEN_FAILED
state. The RECOMMENDED ultimate open timeout is 95 seconds.
The initiator chooses a new, unique tag not used by any currently
opening session. It is RECOMMENDED that the tag be cryptographically
pseudorandom and be at least 8 bytes in length, so that it is hard to
guess. The initiator constructs an IHello chunk (Section 2.3.2) with
the Endpoint Discriminator and the tag.
While the initiator is in the S_IHELLO_SENT state, it sends the
IHello to each candidate endpoint address in the set, on a backoff
schedule. The backoff SHOULD NOT be less than multiplicative, with
not less than 1.5 seconds added to the interval between each attempt.
The backoff SHOULD be scheduled separately for each candidate
address, since new candidates can be added over time.
If the initiator receives a Redirect chunk (Section 2.3.5) with a tag
echo matching this session, AND this session is in the S_IHELLO_SENT
state, then for each redirect destination indicated in the Redirect:
if the candidate endpoint address set contains fewer than
REDIRECT_THRESHOLD addresses, add the indicated redirect destination
to the candidate endpoint address set. REDIRECT_THRESHOLD SHOULD NOT
be more than 24.
If the initiator receives an RHello chunk (Section 2.3.4) with a tag
echo matching this session, AND this session is in the S_IHELLO_SENT
state, AND the responder certificate matches the desired Endpoint
Discriminator, AND the certificate is authentic according to the
Cryptography Profile, then:
1. If the Canonical Endpoint Discriminator for the responder
certificate matches the Canonical Endpoint Discriminator of
another existing session in the S_KEYING_SENT or S_OPEN states,
AND the certificate of the other opening session matches the
desired Endpoint Discriminator, then this session is a duplicate
and SHOULD be aborted in favor of the other existing session;
otherwise,
Thornburgh Informational [Page 54]
^L
RFC 7016 Adobe RTMFP November 2013
2. Move to the S_KEYING_SENT state. Set DESTADDR, the far-end
address for the session, to the address from which this RHello
was received. The initiator chooses a new, unique receive
session ID, not used by any other session, for the responder to
use when sending packets to the initiator. It computes a Session
Key Initiator Component appropriate to the responder's
certificate according to the Cryptography Profile. Using this
data and the cookie from the RHello, the initiator constructs and
signs an IIKeying chunk (Section 2.3.7).
While the initiator is in the S_KEYING_SENT state, it sends the
IIKeying to DESTADDR on a backoff schedule. The backoff SHOULD NOT
be less than multiplicative, with not less than 1.5 seconds added to
the interval between each attempt.
If the initiator receives an RIKeying chunk (Section 2.3.8) in a
packet with this session's receive session identifier, AND this
session is in the S_KEYING_SENT state, AND the signature in the chunk
is authentic according to the far end's certificate (from the
RHello), AND the Session Key Responder Component successfully
combines with the Session Key Initiator Component and the near and
far certificates to form the shared session keys and nonces according
to the Cryptography Profile, then the session has opened
successfully. The session moves to the S_OPEN state. The send
session identifier is set from the RIKeying. Packet encryption,
decryption, and verification now use the newly computed shared
session keys, and the session nonces are available for application-
layer cryptographic challenges.
3.5.1.1.2. Responder
On receipt of an IHello chunk (Section 2.3.2) with an Endpoint
Discriminator that selects its identity, an endpoint SHOULD construct
an RHello chunk (Section 2.3.4) and send it to the address from which
the IHello was received. To avoid a potential resource exhaustion
denial of service, the endpoint SHOULD NOT create any persistent
state associated with the IHello. The endpoint MUST generate the
cookie for the RHello in such a way that it can be recognized as
authentic and valid when echoed in an IIKeying. The endpoint SHOULD
use the address from which the IHello was received as part of the
cookie generation formula. Cookies SHOULD be valid only for a
limited time; that lifetime SHOULD NOT be less than 95 seconds (the
recommended ultimate session open timeout).
Thornburgh Informational [Page 55]
^L
RFC 7016 Adobe RTMFP November 2013
On receipt of an FIHello chunk (Section 2.3.3) from a Forwarder
(Section 3.5.1.5) where the Endpoint Discriminator selects its
identity, an endpoint SHOULD do one of the following:
1. Compute, construct, and send an RHello as though the FIHello was
an IHello received from the indicated reply address; or
2. Construct and send an Implied Redirect (Section 2.3.5) to the
FIHello's reply address; or
3. Ignore this FIHello.
On receipt of an IIKeying chunk (Section 2.3.7), if the cookie is not
authentic or if it has expired, ignore this IIKeying; otherwise,
On receipt of an IIKeying chunk, if the cookie appears authentic but
does not match the address from which the IIKeying's packet was
received, perform the special processing at Cookie Change
(Section 3.5.1.2); otherwise,
On receipt of an IIKeying with an authentic and valid cookie, if the
certificate is authentic according to the Cryptography Profile, AND
the signature in the chunk is authentic according to the far end's
certificate and the Cryptography Profile, AND the Session Key
Initiator Component is acceptable, then:
1. If the address from which this IIKeying was received corresponds
to an opening session in the S_IHELLO_SENT or S_KEYING_SENT
state, perform the special processing at Glare (Section 3.5.1.3);
otherwise,
2. If the address from which this IIKeying was received corresponds
to a session in the S_OPEN state, then:
1. If the receiver was the Responder for the S_OPEN session and
the session identifier, certificate, and Session Key
Initiator Component are identical to those of the S_OPEN
session, this IIKeying is a retransmission, so resend the
S_OPEN session's RIKeying using the Default Session Key as
specified below; otherwise,
2. If the certificate from this IIKeying does not override the
certificate of the S_OPEN session, ignore this IIKeying;
otherwise,
Thornburgh Informational [Page 56]
^L
RFC 7016 Adobe RTMFP November 2013
3. The certificate from this IIKeying overrides the certificate
of the S_OPEN session; this is a new opening session from the
same identity, and the existing S_OPEN session is stale.
Move the existing S_OPEN session to S_CLOSED and abort all of
its flows (signaling exceptions to the user), then continue
processing this IIKeying.
Otherwise,
3. Compute a Session Key Responder Component and choose a new,
unique receive session ID not used by any other session for the
initiator to use when sending packets to the responder. Using
this data, construct and, with the Session Key Initiator
Component, sign an RIKeying chunk (Section 2.3.8). Using the
Session Key Initiator and Responder Components and the near and
far certificates, the responder combines and computes the shared
session keys and nonces according to the Cryptography Profile.
The responder creates a new session in the S_OPEN state, with the
far-endpoint address DESTADDR taken from the source address of
the packet containing the IIKeying and the send session
identifier taken from the IIKeying. The responder sends the
RIKeying to the initiator using the Default Session Key and the
requested send session identifier. Packet encryption,
decryption, and verification of all future packets for this
session use the newly computed keys, and the session nonces are
available for application-layer cryptographic challenges.
3.5.1.2. Cookie Change
In some circumstances, the responder may generate an RHello cookie
for an initiator's address that isn't the address the initiator would
use when sending packets directly to the responder. This can happen,
for example, when the initiator has multiple local addresses and uses
one address to reach a Forwarder (Section 3.5.1.5) but another to
reach the responder.
Thornburgh Informational [Page 57]
^L
RFC 7016 Adobe RTMFP November 2013
Consider the following example:
Initiator Forwarder Responder
| IHello | |
|(Src=Ix) | |
|------------------------------->| |
| | FIHello |
| |(RA=Ix) |
| |-------------------------------->|
| |
| RHello |
| (Cookie:Ix)|
|<-----------------------------------------------------------------|
| |
| IIKeying |
|(Cookie:Ix,Src=Iy) |
|----------------------------------------------------------------->|
| |
| RHello Cookie Change |
| (Cookie:Ix,Cookie:Iy)|
|<-----------------------------------------------------------------|
| |
| IIKeying |
|(Cookie:Iy) |
|----------------------------------------------------------------->|
| |
| RIKeying |
|<-----------------------------------------------------------------|
| |
|<======================== S E S S I O N =========================>|
Figure 10: Handshake with Cookie Change
The initiator has two network interfaces: a first preferred interface
with address Ix = 192.0.2.100:50000, and a second with address Iy =
198.51.100.101:50001. The responder has one interface with address
Ry = 198.51.100.200:51000, on the same network as the initiator's
second interface. The initiator uses its first interface to reach a
Forwarder. The Forwarder observes the initiator's address of Ix and
sends a Forwarded IHello (Section 2.3.3) to the responder. The
responder treats this as if it were an IHello from Ix, calculates a
corresponding cookie, and sends an RHello to Ix. The initiator
receives this RHello from Ry and selects that address as the
destination for the session. It then sends an IIKeying, copying the
cookie from the RHello. However, since the source of the RHello is
Ry, on a network to which the initiator is directly connected, the
initiator uses its second interface Iy to send the IIKeying. The
responder, on receiving the IIKeying, will compare the cookie to the
Thornburgh Informational [Page 58]
^L
RFC 7016 Adobe RTMFP November 2013
expected value based on the source address of the packet, and since
the IIKeying source doesn't match the IHello source used to generate
the cookie, the responder will reject the IIKeying.
If the responder determines that it generated the cookie in the
IIKeying but the cookie doesn't match the sender's address (for
example, if the cookie is in two parts, with a first part generated
independently of the initiator's address and a second part dependent
on the address), the responder SHOULD generate a new cookie based on
the address from which the IIKeying was received and send an RHello
Cookie Change chunk (Section 2.3.6) to the source of the IIKeying,
using the session ID from the IIKeying and the Default Session Key.
If the initiator receives an RHello Cookie Change chunk for a session
in the S_KEYING_SENT state, AND the old cookie matches the one
originally sent to the responder, then the initiator adopts the new
cookie, constructs and signs a new IIKeying chunk, and sends the new
IIKeying to the responder. The initiator SHOULD NOT change the
cookie for a session more than once.
3.5.1.3. Glare
Glare occurs when two endpoints attempt to initiate sessions to each
other concurrently. Glare is detected by receipt of a valid and
authentic IIKeying from an endpoint address that is a destination for
an opening session. Only one session is allowed between a pair of
endpoints.
Glare is resolved by comparing the certificate in the received
IIKeying with the near end's certificate. The Cryptography Profile
defines a certificate comparison function to determine the prevailing
endpoint when there is glare.
If the near end prevails, discard and ignore the received IIKeying.
The far end will abort its opening session on receipt of IIKeying
from the near end.
Otherwise, the far end prevails:
1. If the certificate in the IIKeying overrides the certificate
associated with the near opening session according to the
Cryptography Profile, then abort and destroy the near opening
session. Then,
2. Continue with normal Responder IIKeying processing
(Section 3.5.1.1.2).
Thornburgh Informational [Page 59]
^L
RFC 7016 Adobe RTMFP November 2013
3.5.1.4. Redirector
+-----------+ +------------+ +-----------+
| Initiator |---------->| Redirector | | Responder |
| |<----------| | | |
| | +------------+ | |
| |<=================================>| |
+-----------+ +-----------+
Figure 11: Redirector
A Redirector acts like a name server for Endpoint Discriminators.
An initiator MAY use a Redirector to discover additional candidate
endpoint addresses for a desired endpoint.
On receipt of an IHello chunk with an Endpoint Discriminator that
does not select the Redirector's identity, the Redirector constructs
and sends back to the initiator a Responder Redirect chunk
(Section 2.3.5) containing one or more additional candidate addresses
for the indicated endpoint.
Initiator Redirector Responder
| IHello | |
|------------------------------->| |
| | |
| Redirect | |
|<-------------------------------| |
| |
| IHello |
|----------------------------------------------------------------->|
| |
| RHello |
|<-----------------------------------------------------------------|
| |
| IIKeying |
|----------------------------------------------------------------->|
| |
| RIKeying |
|<-----------------------------------------------------------------|
| |
|<======================== S E S S I O N =========================>|
Figure 12: Handshake Using a Redirector
Thornburgh Informational [Page 60]
^L
RFC 7016 Adobe RTMFP November 2013
Deployment Design Note: Redirectors SHOULD NOT initiate new sessions
to endpoints that might use the Redirector's address as a candidate
for another endpoint, since the far end might interpret the
Redirector's IIKeying as glare for the far end's initiation to the
other endpoint.
3.5.1.5. Forwarder
+-----------+ +-----------+ +---+ +-----------+
| Initiator |---->| Forwarder |<===>| N |<===>| Responder |
| | +-----------+ | A | | |
| |<=====================>| T |<===>| |
+-----------+ +---+ +-----------+
Figure 13: Forwarder
A responder might be behind a NAT or firewall that doesn't allow
inbound packets to reach the endpoint until it first sends an
outbound packet for a particular far-endpoint address.
A Forwarder's endpoint address MAY be a candidate address for another
endpoint. A responder MAY use a Forwarder to receive FIHello chunks
sent on behalf of an initiator.
On receipt of an IHello chunk with an Endpoint Discriminator that
does not select the Forwarder's identity, if the Forwarder has an
S_OPEN session with an endpoint whose certificate matches the desired
Endpoint Discriminator, the Forwarder constructs and sends an FIHello
chunk (Section 2.3.3) to the selected endpoint over the S_OPEN
session, using the tag and Endpoint Discriminator from the IHello
chunk and the source address of the packet containing the IHello for
the corresponding fields of the FIHello.
Thornburgh Informational [Page 61]
^L
RFC 7016 Adobe RTMFP November 2013
On receipt of an FIHello chunk, a responder might send an RHello or
Implied Redirect to the original source of the IHello
(Section 3.5.1.1.2), potentially allowing future packets to flow
directly between the initiator and responder through the NAT or
firewall.
Initiator Forwarder NAT Responder
| IHello | | |
|------------------------------->| | |
| | FIHello | |
| |--------------->|--------------->|
| | |
| | RHello |
| :<---------------|
|<------------------------------------------------: |
| : |
| IIKeying : |
|-------------------------------------------------:--------------->|
| : |
| : RIKeying |
| :<---------------|
|<------------------------------------------------: |
| : |
|<======================== S E S S I O N ========>:<==============>|
Figure 14: Forwarder Handshake where Responder Sends an RHello
Thornburgh Informational [Page 62]
^L
RFC 7016 Adobe RTMFP November 2013
Initiator Forwarder NAT Responder
| IHello | | |
|------------------------------->| | |
| | FIHello | |
| |--------------->|--------------->|
| | |
| | Redirect |
| | (Implied,RD={})|
| :<---------------|
|<------------------------------------------------: |
| : |
| IHello : |
|------------------------------------------------>:--------------->|
| : |
| : RHello |
| :<---------------|
|<------------------------------------------------: |
| : |
| IIKeying : |
|------------------------------------------------>:--------------->|
| : |
| : RIKeying |
| :<---------------|
|<------------------------------------------------: |
| : |
|<======================== S E S S I O N ========>:<==============>|
Figure 15: Forwarder Handshake where Responder Sends an
Implied Redirect
3.5.1.6. Redirector and Forwarder with NAT
+---+ +---+ +---+ +---+ +---+
| I | | N | | I | | N | | R |
| n |------>| A |------>| n | | A | | e |
| i | | T | | t |<====>| T |<====>| s |
| t |<------| |<------| r | | | | p |
| i | | | | o | | | | o |
| a | | | +---+ | | | n |
| t | | | | | | d |
| o |<=====>| |<================>| |<====>| e |
| r | | | | | | r |
+---+ +---+ +---+ +---+
Figure 16: Introduction Service for Initiator and Responder
behind NATs
Thornburgh Informational [Page 63]
^L
RFC 7016 Adobe RTMFP November 2013
An initiator and responder might each be behind distinct NATs or
firewalls that don't allow inbound packets to reach the respective
endpoints until each first sends an outbound packet for a particular
far-endpoint address.
An introduction service comprising Redirector and Forwarder functions
may facilitate direct communication between endpoints each behind
a NAT.
The responder is registered with the introduction service via an
S_OPEN session to it. The service observes and records the
responder's public NAT address as the DESTADDR of the S_OPEN session.
The service MAY record other addresses for the responder, for example
addresses that the responder self-reports as being directly attached.
The initiator begins with an address of the introduction service as
an initial candidate. The Redirector portion of the service sends to
the initiator a Responder Redirect containing at least the
responder's public NAT address as previously recorded. The Forwarder
portion of the service sends to the responder a Forwarded IHello
containing the initiator's public NAT address as observed to be the
source of the IHello.
The responder sends an RHello to the initiator's public NAT address
in response to the FIHello. This will allow inbound packets to the
responder through its NAT from the initiator's public NAT address.
The initiator sends an IHello to the responder's public NAT address
in response to the Responder Redirect. This will allow inbound
packets to the initiator through its NAT from the responder's public
NAT address.
With transit paths created in both NATs, normal session startup can
proceed.
Thornburgh Informational [Page 64]
^L
RFC 7016 Adobe RTMFP November 2013
Initiator NAT-I Redirector+Forwarder NAT-R Responder
| | | | |
| IHello | | | |
|(Dst=Intro) | | | |
|-------------->| | | |
| |--------------->| | |
| | | FIHello | |
| | |(RA=NAT-I-Pub) | |
| | |--------------->|--------------->|
| | Redirect | | |
| | (RD={NAT-R-Pub,| | |
| | ...})| | |
|<--------------|<---------------| | |
| | | RHello |
| | | (Dst=NAT-I-Pub)|
| | :<---------------|
| | (*) <--------------------------: |
| IHello | : |
|(Dst=NAT-R-Pub)| : |
|-------------->: : |
| :-------------------------------->:--------------->|
| : : |
| : : RHello |
| : :<---------------|
|<--------------:<--------------------------------: |
| : : |
| IIKeying : : |
|-------------->: : |
| :-------------------------------->:--------------->|
| : : |
| : : RIKeying |
| : :<---------------|
|<--------------:<--------------------------------: |
| : : |
|<=============>:<======== S E S S I O N ========>:<==============>|
Figure 17: Handshake with Redirector and Forwarder
At the point in Figure 17 marked (*), the responder's RHello from the
FIHello might arrive at the initiator's NAT before or after the
initiator's IHello is sent outbound to the responder's public NAT
address. If it arrives before, it may be dropped by the NAT. If it
arrives after, it will transit the NAT and trigger keying without
waiting for another round-trip time. The timing of this race
depends, among other factors, on the relative distances of the
initiator and responder from each other and from the introduction
service.
Thornburgh Informational [Page 65]
^L
RFC 7016 Adobe RTMFP November 2013
3.5.1.7. Load Distribution and Fault Tolerance
+---+ IHello/RHello +-------------+
| I |<------------------->| Responder 1 |
| n | +-------------+
| i | SESSION +-------------+
| t |<=========>| Responder 2 |
| i | +-------------+
| a | IHello... +----------------+
| t |-------------------------> X | Dead Responder |
| o | +----------------+
| r | IHello/RHello +-------------+
| |<---------------->| Responder N |
+---+ +-------------+
Figure 18: Parallel Open to Multiple Endpoints
As specified in Section 3.2, more than one endpoint is allowed to be
selected by one Endpoint Discriminator. This will typically be the
case for a set of servers, any of which could accommodate a
connecting client.
As specified in Section 3.5.1.1.1, an initiator is allowed to use
multiple candidate endpoint addresses when starting a session, and
the sender of the first acceptable RHello chunk to be received is
selected to complete the session, with later responses ignored. An
initiator can start with the multiple candidate endpoint addresses,
or it may learn them during startup from one or more Redirectors
(Section 3.5.1.4).
Parallel open to multiple endpoints for the same Endpoint
Discriminator, combined with selection by earliest RHello, can be
used for load distribution and fault tolerance. The cost at each
endpoint that is not selected is limited to receiving and processing
an IHello, and generating and sending an RHello.
In one circumstance, multiple servers of similar processing and
networking capacity may be located in near proximity to each other,
such as in a data center. In this circumstance, a less heavily
loaded server can respond to an IHello more quickly than more heavily
loaded servers and will tend to be selected by a client.
In another circumstance, multiple servers may be located in different
physical locations, such as different data centers. In this
circumstance, a server that is located nearer (in terms of network
distance) to the client can respond earlier than more distant servers
and will tend to be selected by the client.
Thornburgh Informational [Page 66]
^L
RFC 7016 Adobe RTMFP November 2013
Multiple servers, in proximity or distant from one another, can form
a redundant pool of servers. A client can perform a parallel open to
the multiple servers. In normal operation, the multiple servers will
all respond, and the client will select one of them as described
above. If one of the multiple servers fails, other servers in the
pool can still respond to the client, allowing the client to succeed
to an S_OPEN session with one of them.
3.5.2. Congestion Control
An RTMFP MUST implement congestion control and avoidance algorithms
that are "TCP compatible", in accordance with Internet best current
practice [RFC2914]. The algorithms SHOULD NOT be more aggressive in
sending data than those described in "TCP Congestion Control"
[RFC5681] and MUST NOT be more aggressive in sending data than the
"slow start algorithm" described in Section 3.1 of RFC 5681.
An endpoint maintains a transmission budget in the session
information context of each S_OPEN session (Section 3.5), controlling
the rate at which the endpoint sends data into the network.
For window-based congestion control and avoidance algorithms, the
transmission budget is the congestion window, which is the amount of
user data that is allowed to be outstanding, or in flight, in the
network. Transmission is allowed when S_OUTSTANDING_BYTES
(Section 3.5) is less than the congestion window (Section 3.6.2.3).
See Appendix A for an experimental window-based congestion control
algorithm for real-time and bulk data.
An endpoint avoids sending large bursts of data or packets into the
network (Section 3.5.2.3).
A sending endpoint increases and decreases its transmission budget in
response to acknowledgements (Section 3.6.2.4) and loss according to
the congestion control and avoidance algorithms. Loss is detected by
negative acknowledgement (Section 3.6.2.5) and timeout
(Section 3.6.2.6).
Timeout is determined by the Effective Retransmission Timeout (ERTO)
(Section 3.5.2.2). The ERTO is measured using the Timestamp and
Timestamp Echo packet header fields (Section 2.2.4).
A receiving endpoint acknowledges all received data (Section 3.6.3.4)
to enable the sender to measure receipt of data, or lack thereof.
A receiving endpoint may be receiving time critical (or real-time)
data from a first sender while receiving data from other senders.
The receiving endpoint can signal its other senders (Section 2.2.4)
Thornburgh Informational [Page 67]
^L
RFC 7016 Adobe RTMFP November 2013
to cause them to decrease the aggressiveness of their congestion
control and avoidance algorithms, in order to yield network capacity
to the time critical data (Section 3.5.2.1).
3.5.2.1. Time Critical Reverse Notification
A sender can increase its transmission budget at a rate compatible
with (but not exceeding) the "slow start algorithm" specified in
RFC 5681 (with which the transmission rate is doubled every round
trip when beginning or restarting transmission, until loss is
detected). However, a sender MUST behave as though the slow start
threshold SSTHRESH is clamped to 0 (disabling the slow start
algorithm's exponential increase behavior) on a session where a Time
Critical Reverse Notification (Section 2.2.4) indication has been
received from the far end within the last 800 milliseconds, unless
the sender is itself currently sending time critical data to the
far end.
During each round trip, a sender SHOULD NOT increase the transmission
budget by more than 0.5% or by 384 bytes per round trip (whichever is
greater) on a session where a Time Critical Reverse Notification
indication has been received from the far end within the last 800
milliseconds, unless the sender is itself currently sending time
critical data to the far end.
3.5.2.2. Retransmission Timeout
RTMFP uses the ERTO to detect when a user data fragment has been lost
in the network. The ERTO is typically calculated in a manner similar
to that specified in "Requirements for Internet Hosts - Communication
Layers" [RFC1122] and is a function of round-trip time measurements
and persistent timeout behavior.
The ERTO SHOULD be at least 250 milliseconds and SHOULD allow for the
receiver to delay sending an acknowledgement for up to 200
milliseconds (Section 3.6.3.4.4). The ERTO MUST NOT be less than the
round-trip time.
To facilitate round-trip time measurement, an endpoint MUST implement
the Timestamp Echo facility:
o On a session entering the S_OPEN state, initialize TS_RX_TIME to
negative infinity, and initialize TS_RX and TS_ECHO_TX to have no
value.
Thornburgh Informational [Page 68]
^L
RFC 7016 Adobe RTMFP November 2013
o On receipt of a packet in an S_OPEN session with the
timestampPresent (Section 2.2.4) flag set, if the timestamp field
in the packet is different than TS_RX, set TS_RX to the value of
the timestamp field in the packet, and set TS_RX_TIME to the
current time.
o When sending a packet to the far end in an S_OPEN session:
1. Calculate TS_RX_ELAPSED = current time - TS_RX_TIME. If
TS_RX_ELAPSED is more than 128 seconds, then set TS_RX and
TS_ECHO_TX to have no value, and do not include a timestamp
echo; otherwise,
2. Calculate TS_RX_ELAPSED_TICKS to be the number of whole
4-millisecond periods in TS_RX_ELAPSED; then
3. Calculate TS_ECHO = (TS_RX + TS_RX_ELAPSED_TICKS) MODULO
65536; then
4. If TS_ECHO is not equal to TS_ECHO_TX, then set TS_ECHO_TX to
TS_ECHO, set the timestampEchoPresent flag, and set the
timestampEcho field to TS_ECHO_TX.
The remainder of this section describes an OPTIONAL method for
calculating the ERTO. Real-time applications and P2P mesh
applications often require knowing the round-trip time and RTT
variance. This section additionally describes a method for measuring
the round-trip time and RTT variance, and calculating a smoothed
round-trip time.
Let the session information context contain additional variables:
o TS_TX: the last timestamp sent to the far end, initialized to have
no value;
o TS_ECHO_RX: the last timestamp echo received from the far end,
initialized to have no value;
o SRTT: the smoothed round-trip time, initialized to have no value;
o RTTVAR: the round-trip time variance, initialized to 0.
Initialize MRTO to 250 milliseconds.
Initialize ERTO to 3 seconds.
Thornburgh Informational [Page 69]
^L
RFC 7016 Adobe RTMFP November 2013
On sending a packet to the far end of an S_OPEN session, if the
current send timestamp is not equal to TS_TX, then set TS_TX to the
current send timestamp, set the timestampPresent flag in the packet
header, and set the timestamp field to TS_TX.
On receipt of a packet from the far end of an S_OPEN session, if the
timestampEchoPresent flag is set in the packet header, AND the
timestampEcho field is not equal to TS_ECHO_RX, then:
1. Set TS_ECHO_RX to timestampEcho;
2. Calculate RTT_TICKS = (current send timestamp - timestampEcho)
MODULO 65536;
3. If RTT_TICKS is greater than 32767, the measurement is invalid,
so discard this measurement; otherwise,
4. Calculate RTT = RTT_TICKS * 4 milliseconds;
5. If SRTT has a value, then calculate new values of RTTVAR
and SRTT:
1. RTT_DELTA = | SRTT - RTT |;
2. RTTVAR = ((3 * RTTVAR) + RTT_DELTA) / 4;
3. SRTT = ((7 * SRTT) + RTT) / 8.
6. If SRTT has no value, then set SRTT = RTT and RTTVAR = RTT / 2;
7. Set MRTO = SRTT + 4 * RTTVAR + 200 milliseconds;
8. Set ERTO to MRTO or 250 milliseconds, whichever is greater.
A retransmission timeout occurs when the most recently transmitted
user data fragment has remained outstanding in the network for ERTO.
When this timeout occurs, increase ERTO on an exponential backoff
with an ultimate backoff cap of 10 seconds:
1. Calculate ERTO_BACKOFF = ERTO * 1.4142;
2. Calculate ERTO_CAPPED to be ERTO_BACKOFF or 10 seconds, whichever
is less;
3. Set ERTO to ERTO_CAPPED or MRTO, whichever is greater.
Thornburgh Informational [Page 70]
^L
RFC 7016 Adobe RTMFP November 2013
3.5.2.3. Burst Avoidance
An application's sending patterns may cause the transmission budget
to grow to a large value, but at times its sending patterns will
result in a comparatively small amount of data outstanding in the
network. In this circumstance, especially with a window-based
congestion avoidance algorithm, if the application then has a large
amount of new data to send (for example, a new bulk data transfer),
it could send data into the network all at once to fill the window.
This kind of transmission burst is undesirable, however, because it
can jam interfaces, links, and buffers.
Accordingly, in any session, an endpoint SHOULD NOT send more than
six packets containing user data between receiving any
acknowledgements or retransmission timeouts.
The following describes an OPTIONAL method to avoid bursting large
numbers of packets into the network:
Let the session information context contain an additional variable
DATA_PACKET_COUNT, initialized to 0.
Transmission of a user data fragment on this session is not allowed
if DATA_PACKET_COUNT is greater than or equal to 6, regardless of any
other allowance of the congestion control algorithm.
On transmission of a packet containing at least one User Data chunk
(Section 2.3.11), set DATA_PACKET_COUNT = DATA_PACKET_COUNT + 1.
On receipt of an acknowledgement chunk (Sections 2.3.13 and 2.3.14),
set DATA_PACKET_COUNT to 0.
On a retransmission timeout, set DATA_PACKET_COUNT to 0.
3.5.3. Address Mobility
Sessions are demultiplexed with a 32-bit session ID, rather than by
endpoint address. This allows an endpoint's address to change during
an S_OPEN session. This can happen, for example, when switching from
a wireless to a wired network, or when moving from one wireless base
station to another, or when a NAT restarts.
If the near end receives a valid packet for an S_OPEN session from a
source address that doesn't match DESTADDR, the far end might have
changed addresses. The near end SHOULD verify that the far end is
definitively at the new address before changing DESTADDR. A
suggested verification method is described in Section 3.5.4.2.
Thornburgh Informational [Page 71]
^L
RFC 7016 Adobe RTMFP November 2013
3.5.4. Ping
If an endpoint receives a Ping chunk (Section 2.3.9) in a session in
the S_OPEN state, it SHOULD construct and send a Ping Reply chunk
(Section 2.3.10) in response if possible, copying the message
unaltered. The Ping Reply SHOULD be sent as quickly as possible
following receipt of a Ping. The semantics of a Ping's message is
reserved for the sender; a receiver SHOULD NOT interpret the Ping's
message.
Endpoints can use the mechanism of the Ping chunk and the expected
Ping Reply for any purpose. This specification doesn't mandate any
specific constraints on the format or semantics of a Ping message. A
Ping Reply MUST be sent only as a response to a Ping.
Receipt of a Ping Reply implies live bidirectional connectivity.
This specification doesn't mandate any other semantics for a
Ping Reply.
3.5.4.1. Keepalive
An endpoint can use a Ping to test for live bidirectional
connectivity, to test that the far end of a session is still in the
S_OPEN state, to keep NAT translations alive, and to keep firewall
holes open.
An endpoint can use a Ping to hasten detection of a near-end address
change by the far end.
An endpoint may declare a session to be defunct and dead after a
persistent failure by the far end to return Ping Replies in response
to Pings.
If used for these purposes, a Keepalive Ping SHOULD have an empty
message.
A Keepalive Ping SHOULD NOT be sent more often than once per ERTO.
If a corresponding Ping Reply is not received within ERTO of sending
the Ping, ERTO SHOULD be increased according to Section 3.5.2
("Congestion Control").
Thornburgh Informational [Page 72]
^L
RFC 7016 Adobe RTMFP November 2013
3.5.4.2. Address Mobility
This section describes an OPTIONAL but suggested method for
processing and verifying a far-end address change.
Let the session context contain additional variables MOB_TX_TS,
MOB_RX_TS, and MOB_SECRET. MOB_TX_TS and MOB_RX_TS have initial
values of negative infinity. MOB_SECRET should be a
cryptographically pseudorandom value not less than 128 bits in length
and known only to this end.
On receipt of a packet for an S_OPEN session, after processing all
chunks in the packet: if the session is still in the S_OPEN state,
AND the source address of the packet does not match DESTADDR, AND
MOB_TX_TS is at least one second in the past, then:
1. Set MOB_TX_TS to the current time;
2. Construct a Ping message comprising the following: a marking to
indicate (to this end when returned in a Ping Reply) that it is a
mobility check (for example, the first byte being ASCII 'M' for
"Mobility"), a timestamp set to MOB_TX_TS, and a cryptographic
hash over the following: the preceding items, the address from
which the packet was received, and MOB_SECRET; and
3. Send this Ping to the address from which the packet was received,
instead of DESTADDR.
On receipt of a Ping Reply in an S_OPEN session, if the Ping Reply's
message satisfies all of these conditions:
o it has this end's expected marking to indicate that it is a
mobility check, and
o the timestamp in the message is not more than 120 seconds in the
past, and
o the timestamp in the message is greater than MOB_RX_TS, and
o the cryptographic hash matches the expected value according to the
contents of the message plus the source address of the packet
containing this Ping Reply and MOB_SECRET,
Thornburgh Informational [Page 73]
^L
RFC 7016 Adobe RTMFP November 2013
then:
1. Set MOB_RX_TS to the timestamp in the message; and
2. Set DESTADDR to the source address of the packet containing this
Ping Reply.
3.5.4.3. Path MTU Discovery
"Packetization Layer Path MTU Discovery" [RFC4821] describes a method
for measuring the path MTU between communicating endpoints.
An RTMFP SHOULD perform path MTU discovery.
The method described in RFC 4821 can be adapted for use in RTMFP by
sending a probe packet comprising one of the Padding chunk types
(type 0x00 or 0xff) and a Ping. The Ping chunk SHOULD come after the
Padding chunk, to guard against a false positive response in case the
probe packet is truncated.
3.5.5. Close
An endpoint may close a session at any time. Typically, an endpoint
will close a session when there have been no open flows in either
direction for a time. In another circumstance, an endpoint may be
ceasing operation and will close all of its sessions even if they
have open flows.
To close an S_OPEN session in a reliable and orderly fashion, an
endpoint moves the session to the S_NEARCLOSE state.
On a session transitioning from S_OPEN to S_NEARCLOSE and every
5 seconds thereafter while still in the S_NEARCLOSE state, send a
Session Close Request chunk (Section 2.3.17).
A session that has been in the S_NEARCLOSE state for at least
90 seconds (allowing time to retransmit the Session Close Request
multiple times) SHOULD move to the S_CLOSED state.
On a session transitioning from S_OPEN to the S_NEARCLOSE,
S_FARCLOSE_LINGER or S_CLOSED state, immediately abort and terminate
all open or closing flows. Flows only exist in S_OPEN sessions.
To close an S_OPEN session abruptly, send a Session Close
Acknowledgement chunk (Section 2.3.18), then move to the S_CLOSED
state.
Thornburgh Informational [Page 74]
^L
RFC 7016 Adobe RTMFP November 2013
On receipt of a Session Close Request chunk for a session in the
S_OPEN, S_NEARCLOSE, or S_FARCLOSE_LINGER states, send a Session
Close Acknowledgement chunk; then, if the session is in the S_OPEN
state, move to the S_FARCLOSE_LINGER state.
A session that has been in the S_FARCLOSE_LINGER state for at least
19 seconds (allowing time to answer 3 retransmissions of a Session
Close Request) SHOULD move to the S_CLOSED state.
On receipt of a Session Close Acknowledgement chunk for a session in
the S_OPEN, S_NEARCLOSE, or S_FARCLOSE_LINGER states, move to the
S_CLOSED state.
3.6. Flows
A flow is a unidirectional communication channel in a session for
transporting a correlated series of user messages from a sender to a
receiver. Each end of a session may have zero or more sending flows
to the other end. Each sending flow at one end has a corresponding
receiving flow at the other end.
3.6.1. Overview
3.6.1.1. Identity
Flows are multiplexed in a session by a flow identifier. Each end of
a session chooses its sending flow identifiers independently of the
other end. The choice of similar flow identifiers by both ends does
not imply an association. A sender MAY choose any identifier for any
flow; therefore, a flow receiver MUST NOT ascribe any semantic
meaning, role, or name to a flow based only on its identifier. There
are no "well known" or reserved flow identifiers.
Bidirectional flow association is indicated at flow startup with the
Return Flow Association option (Section 2.3.11.1.2). An endpoint can
indicate that a new sending flow is in return (or response) to a
receiving flow from the other end. A sending flow MUST NOT indicate
more than one return association. A receiving flow can be specified
as the return association for any number of sending flows. The
return flow association, if any, is fixed for the lifetime of the
sending flow. Note: Closure of one flow in an association does not
automatically close other flows in the association, except as
specified in Section 3.6.3.1.
Thornburgh Informational [Page 75]
^L
RFC 7016 Adobe RTMFP November 2013
Flows are named with arbitrary user metadata. This specification
doesn't mandate any particular encoding, syntax, or semantics for the
user metadata, except for the encoded size (Section 2.3.11.1.1); the
user metadata is entirely reserved for the application. The user
metadata is fixed for the lifetime of the flow.
3.6.1.2. Messages and Sequencing
Flows provide message-oriented framing. Large messages are
fragmented for transport in the network. Receivers reassemble
fragmented messages and only present complete messages to the user.
A sender queues messages on a sending flow one after another. A
receiver can recover the original queuing order of the messages, even
when they are reordered in transit by the network or as a result of
loss and retransmission, by means of the messages' fragment sequence
numbers. Flows are the basic units of message sequencing; each flow
is sequenced independently of all other flows; inter-flow message
arrival and delivery sequencing are not guaranteed.
Independent flow sequencing allows a sender to prioritize the
transmission or retransmission of the messages of one flow over those
of other flows in a session, allocating capacity from the
transmission budget according to priority. RTMFP is designed for
flows to be the basic unit of prioritization. In any flow, fragment
sequence numbers are unique and monotonically increasing; that is,
the fragment sequence numbers for any message MUST be greater than
the fragment sequence numbers of all messages previously queued in
that flow. Receipt of fragments out of sequence number order within
a flow creates discontiguous gaps at the receiver, causing it to send
an acknowledgement for every packet and also causing the size of the
encoded acknowledgements to grow. Therefore, for any flow, the
sender SHOULD send lower sequence numbers first.
A sender can abandon a queued message at any time, even if some
fragments of that message have been received by the other end. A
receiver MUST be able to detect a gap in the flow when a message is
abandoned; therefore, each message SHOULD take at least one sequence
number from the sequence space even if no fragments for that message
are ever sent. The sender will transmit the fragments of all
messages not abandoned, and retransmit any lost fragments of all
messages not abandoned, until all the fragments of all messages not
abandoned are acknowledged by the receiver. A sender indicates a
Forward Sequence Number (FSN) to instruct the receiver that sequence
numbers less than or equal to the FSN will not be transmitted or
retransmitted. This allows the receiver to move forward over gaps
and continue sequenced delivery of completely received messages to
the user. Any incomplete messages missing fragments with sequence
Thornburgh Informational [Page 76]
^L
RFC 7016 Adobe RTMFP November 2013
numbers less than or equal to the FSN were abandoned by the sender
and will never be completed. A gap indication MUST be communicated
to the receiving user.
3.6.1.3. Lifetime
A sender begins a flow by sending user message fragments to the other
end, and including the user metadata and, if any, the return flow
association. The sender continues to include the user metadata and
return flow association until the flow is acknowledged by the far
end, at which point the sender knows that the receiver has received
the user metadata and, if any, the return flow association. After
that point, the flow identifier alone is sufficient.
Flow receivers SHOULD acknowledge all sequence numbers received for
any flow, whether the flow is accepted or rejected. Flow receivers
MUST NOT acknowledge sequence numbers higher than the FSN that were
not received. Acknowledgements drive the congestion control and
avoidance algorithms and therefore must be accurate.
An endpoint can reject a receiving flow at any time in the flow's
lifetime. To reject the flow, the receiving endpoint sends a Flow
Exception Report chunk (Section 2.3.16) immediately preceding every
acknowledgement chunk for the rejected receiving flow.
An endpoint may eventually conclude and close a sending flow. The
last sequence number of the flow is marked with the Final flag. The
sending flow is complete when all sequence numbers of the flow,
including the final sequence number, have been cumulatively
acknowledged by the receiver. The receiving flow is complete when
every sequence number from the FSN to the final sequence number has
been received. The sending flow and corresponding receiving flow at
the respective ends hold the flow identifier of a completed flow in
reserve for a time to allow delayed or duplicated fragments and
acknowledgements to drain from the network without erroneously
initiating a new receiving flow or erroneously acknowledging a new
sending flow.
If a flow sender receives a Flow Exception indication from the other
end, the flow sender SHOULD close the flow and abandon all of the
undelivered queued messages. The flow sender SHOULD indicate an
exception to the user.
Thornburgh Informational [Page 77]
^L
RFC 7016 Adobe RTMFP November 2013
3.6.2. Sender
Each sending flow comprises the flow-specific information context
necessary to transfer that flow's messages to the other end. Each
sending flow context includes at least:
o F_FLOW_ID: this flow's identifier;
o STARTUP_OPTIONS: the set of options to send to the receiver until
this flow is acknowledged, including the User's Per-Flow Metadata
and, if set, the Return Flow Association;
o SEND_QUEUE: the unacknowledged message fragments queued in this
flow, initially empty; each message fragment entry comprising the
following:
* SEQUENCE_NUMBER: the sequence number of this fragment;
* DATA: this fragment's user data;
* FRA: the fragment control value for this message fragment,
having one of the values enumerated for that purpose in
Section 2.3.11 ("User Data Chunk");
* ABANDONED: a boolean flag indicating whether this fragment has
been abandoned;
* SENT_ABANDONED: a boolean flag indicating whether this fragment
was abandoned when sent;
* EVER_SENT: a boolean flag indicating whether this fragment has
been sent at least once, initially false;
* NAK_COUNT: a count of the number of negative acknowledgements
detected for this fragment, initially 0;
* IN_FLIGHT: a boolean flag indicating whether this fragment is
currently outstanding, or in flight, in the network, initially
false;
* TRANSMIT_SIZE: the size, in bytes, of the encoded User Data
chunk (including the chunk header) for this fragment when it
was transmitted into the network.
o F_OUTSTANDING_BYTES: the sum of the TRANSMIT_SIZE of each entry in
SEND_QUEUE where entry.IN_FLIGHT is true;
Thornburgh Informational [Page 78]
^L
RFC 7016 Adobe RTMFP November 2013
o RX_BUFFER_SIZE: the most recent available buffer advertisement
from the other end (Sections 2.3.13 and 2.3.14), initially
65536 bytes;
o NEXT_SN: the next sequence number to assign to a message fragment,
initially 1;
o F_FINAL_SN: the sequence number assigned to the final message
fragment of the flow, initially having no value;
o EXCEPTION: a boolean flag indicating whether an exception has been
reported by the receiver, initially false;
o The state, at any time being one of the following values: the open
state F_OPEN; the closing states F_CLOSING and F_COMPLETE_LINGER;
and the closed state F_CLOSED.
Note: The following diagram is only a summary of state transitions
and their causing events, and is not a complete operational
specification.
+--------+
| F_OPEN |
+--------+
|CLOSE or
|rcv Flow Exception
|
v
+---------+
|F_CLOSING|
+---------+
|rcv Data Ack
| 0..F_FINAL_SN
v
+-----------------+
|F_COMPLETE_LINGER|
+-----------------+
| 130 seconds
v
+--------+
|F_CLOSED|
+--------+
Figure 19: Sending Flow State Diagram
Thornburgh Informational [Page 79]
^L
RFC 7016 Adobe RTMFP November 2013
3.6.2.1. Startup
The application opens a new sending flow to the other end in an
S_OPEN session. The implementation chooses a new flow ID that is not
assigned to any other sending flow in that session in the F_OPEN,
F_CLOSING, or F_COMPLETE_LINGER states. The flow starts in the
F_OPEN state. The STARTUP_OPTIONS for the new flow is set with the
User's Per-Flow Metadata (Section 2.3.11.1.1). If this flow is in
return (or response) to a receiving flow from the other end, that
flow's ID is encoded in a Return Flow Association
(Section 2.3.11.1.2) option and added to STARTUP_OPTIONS. A new
sending flow SHOULD NOT be opened in response to a receiving flow
from the other end that is not in the RF_OPEN state when the sending
flow is opened.
At this point, the flow exists in the sender but not in the receiver.
The flow begins when user data fragments are transmitted to the
receiver. A sender can begin a flow in the absence of immediate user
data by sending a Forward Sequence Number Update (Section 3.6.2.7.1),
by queuing and transmitting a user data fragment that is already
abandoned.
3.6.2.2. Queuing Data
The application queues messages in an F_OPEN sending flow for
transmission to the far end. The implementation divides each message
into one or more fragments for transmission in User Data chunks
(Section 2.3.11). Each fragment MUST be small enough so that, if
assembled into a packet (Section 2.2.4) with a maximum-size common
header, User Data chunk header, and, if not empty, this flow's
STARTUP_OPTIONS, the packet will not exceed the path MTU
(Section 3.5.4.3).
For each fragment, create a fragment entry and set
fragmentEntry.SEQUENCE_NUMBER to flow.NEXT_SN, and increment
flow.NEXT_SN by one. Set fragmentEntry.FRA according to the encoding
in User Data chunks:
0: This fragment is a complete message.
1: This fragment is the first of a multi-fragment message.
2: This fragment is the last of a multi-fragment message.
3: This fragment is in the middle of a multi-fragment message.
Append fragmentEntry to flow.SEND_QUEUE.
Thornburgh Informational [Page 80]
^L
RFC 7016 Adobe RTMFP November 2013
3.6.2.3. Sending Data
A sending flow is ready to transmit if the SEND_QUEUE contains at
least one entry that is eligible to send, and if either
RX_BUFFER_SIZE is greater than F_OUTSTANDING_BYTES or EXCEPTION is
set to true.
A SEND_QUEUE entry is eligible to send if it is not IN_FLIGHT, AND at
least one of the following conditions holds:
o The entry is not ABANDONED; or
o The entry is the first one in the SEND_QUEUE; or
o The entry's SEQUENCE_NUMBER is equal to flow.F_FINAL_SN.
If the session's transmission budget allows, a flow that is ready to
transmit is selected for transmission according to the
implementation's prioritization scheme. The manner of flow
prioritization is not mandated by this specification.
Trim abandoned messages from the front of the queue, and find the
Forward Sequence Number (FSN):
1. While the SEND_QUEUE contains at least two entries, AND the first
entry is not IN_FLIGHT, AND the first entry is ABANDONED, remove
and discard the first entry from the SEND_QUEUE;
2. If the first entry in the SEND_QUEUE is not abandoned, set FSN to
entry.SEQUENCE_NUMBER - 1; otherwise,
3. If the first entry in the SEND_QUEUE is IN_FLIGHT, AND
entry.SENT_ABANDONED is false, set FSN to
entry.SEQUENCE_NUMBER - 1; otherwise,
4. The first entry in the SEND_QUEUE is abandoned and either is not
IN_FLIGHT or was already abandoned when sent; set FSN to
entry.SEQUENCE_NUMBER.
The FSN MUST NOT be greater than any sequence number currently
outstanding. The FSN MUST NOT be equal to any sequence number
currently outstanding that was not abandoned when sent.
Thornburgh Informational [Page 81]
^L
RFC 7016 Adobe RTMFP November 2013
Assemble user data chunks for this flow into a packet to send to the
receiver. While enough space remains in the packet and the flow is
ready to transmit:
1. Starting at the head of the SEND_QUEUE, find the first eligible
fragment entry;
2. Encode the entry into a User Data chunk (Section 2.3.11) or, if
possible (Section 3.6.2.3.2), a Next User Data chunk
(Section 2.3.12);
3. If present, set chunk.flowID to flow.F_FLOW_ID;
4. If present, set chunk.sequenceNumber to entry.SEQUENCE_NUMBER;
5. If present, set chunk.fsnOffset to entry.SEQUENCE_NUMBER - FSN;
6. Set chunk.fragmentControl to entry.FRA;
7. Set chunk.abandon to entry.ABANDONED;
8. If entry.SEQUENCE_NUMBER equals flow.F_FINAL_SN, set chunk.final
to true; else set chunk.final to false;
9. If any options are being sent with this chunk, set
chunk.optionsPresent to true, assemble the options into the
chunk, and assemble a Marker to terminate the option list;
10. If entry.ABANDONED is true, set chunk.userData to empty;
otherwise, set chunk.userData to entry.DATA;
11. If adding the assembled chunk to the packet would cause the
packet to exceed the path MTU, do not assemble this chunk into
the packet; enough space no longer remains in the packet; stop.
Otherwise, continue:
12. Set entry.IN_FLIGHT to true;
13. Set entry.EVER_SENT to true;
14. Set entry.NAK_COUNT to 0;
15. Set entry.SENT_ABANDONED to entry.ABANDONED;
16. Set entry.TRANSMIT_SIZE to the size of the assembled chunk,
including the chunk header;
Thornburgh Informational [Page 82]
^L
RFC 7016 Adobe RTMFP November 2013
17. Assemble this chunk into the packet; and
18. If this flow or entry is considered Time Critical (real-time),
set the timeCritical flag in the packet header (Section 2.2.4).
Complete any other appropriate packet processing, and transmit the
packet to the far end.
3.6.2.3.1. Startup Options
If STARTUP_OPTIONS is not empty, then when assembling the FIRST User
Data chunk for this flow into a packet, add the encoded
STARTUP_OPTIONS to that chunk's option list.
3.6.2.3.2. Send Next Data
The Next User Data chunk (Section 2.3.12) is a compact encoding for a
user message fragment when multiple contiguous fragments are
assembled into one packet. Using this chunk where possible can
conserve space in a packet, potentially reducing transmission
overhead or allowing additional information to be sent in a packet.
If, after assembling a user message fragment of a flow into a packet
(Section 3.6.2.3), the next eligible fragment to be selected for
assembly into that packet belongs to the same flow, AND its sequence
number is one greater than that of the fragment just assembled, it is
RECOMMENDED that an implementation encode a Next User Data chunk
instead of a User Data chunk.
The FIRST fragment of a flow assembled into a packet MUST be encoded
as a User Data chunk.
3.6.2.4. Processing Acknowledgements
A Data Acknowledgement Bitmap chunk (Section 2.3.13) or a Data
Acknowledgement Ranges chunk (Section 2.3.14) encodes the
acknowledgement of receipt of one or more sequence numbers of a flow,
as well as the receiver's current receive window advertisement.
On receipt of an acknowledgement chunk for a sending flow:
1. Set PRE_ACK_OUTSTANDING_BYTES to flow.F_OUTSTANDING_BYTES;
2. Set flow.STARTUP_OPTIONS to empty;
3. Set flow.RX_BUFFER_SIZE to chunk.bufferBytesAvailable;
Thornburgh Informational [Page 83]
^L
RFC 7016 Adobe RTMFP November 2013
4. For each sequence number encoded in the acknowledgement, if
there is an entry in flow.SEND_QUEUE with that sequence number
and its IN_FLIGHT is true, then remove the entry from
flow.SEND_QUEUE; and
5. Notify the congestion control and avoidance algorithms that
PRE_ACK_OUTSTANDING_BYTES - flow.F_OUTSTANDING_BYTES were
acknowledged. Note that negative acknowledgements
(Section 3.6.2.5) affect "TCP friendly" congestion control.
3.6.2.5. Negative Acknowledgement and Loss
A negative acknowledgement is inferred for an outstanding fragment if
an acknowledgement is received for any other fragments sent after it
in the same session.
An implementation SHOULD consider a fragment to be lost once that
fragment receives three negative acknowledgements. A lost fragment
is no longer outstanding in the network.
The following describes an OPTIONAL method for detecting negative
acknowledgements.
Let the session track the order in which fragments are transmitted
across all its sending flows by way of a monotonically increasing
Transmission Sequence Number (TSN) recorded with each fragment queue
entry each time that fragment is transmitted.
Let the session information context contain additional variables:
o NEXT_TSN: the next TSN to record with a fragment's queue entry
when it is transmitted, initially 1;
o MAX_TSN_ACK: the highest acknowledged TSN, initially 0.
Let each fragment queue entry contain an additional variable TSN,
initially 0, to track its transmission order.
On transmission of a message fragment into the network, set its
entry.TSN to session.NEXT_TSN, and increment session.NEXT_TSN.
On acknowledgement of an outstanding fragment, if its entry.TSN is
greater than session.MAX_TSN_ACK, set session.MAX_TSN_ACK to
entry.TSN.
After processing all acknowledgements in a packet containing at least
one acknowledgement, then for each sending flow in that session, for
each entry in that flow's SEND_QUEUE, if entry.IN_FLIGHT is true and
Thornburgh Informational [Page 84]
^L
RFC 7016 Adobe RTMFP November 2013
entry.TSN is less than session.MAX_TSN_ACK, increment entry.NAK_COUNT
and notify the congestion control and avoidance algorithms that a
negative acknowledgement was detected in this packet.
For each sending flow in that session, for each entry in that flow's
SEND_QUEUE, if entry.IN_FLIGHT is true and entry.NAK_COUNT is at
least 3, that fragment was lost in the network and is no longer
considered to be in flight. Set entry.IN_FLIGHT to false. Notify
the congestion control and avoidance algorithms of the loss.
3.6.2.6. Timeout
A fragment is considered lost and no longer in flight in the network
if it has remained outstanding for at least ERTO.
The following describes an OPTIONAL method to manage transmission
timeouts. This method REQUIRES that either burst avoidance
(Section 3.5.2.3) is implemented or the implementation's congestion
control and avoidance algorithms will eventually stop sending new
fragments into the network if acknowledgements are persistently not
received.
Let the session information context contain an alarm TIMEOUT_ALARM,
initially unset.
On sending a packet containing at least one User Data chunk, set or
reset TIMEOUT_ALARM to fire in ERTO.
On receiving a packet containing at least one acknowledgement, reset
TIMEOUT_ALARM (if already set) to fire in ERTO.
When TIMEOUT_ALARM fires:
1. Set WAS_LOSS = false;
2. For each sending flow in the session, and for each entry in that
flow's SEND_QUEUE:
1. If entry.IN_FLIGHT is true, set WAS_LOSS = true; and
2. Set entry.IN_FLIGHT to false.
3. If WAS_LOSS is true, perform ERTO backoff (Section 3.5.2.2); and
4. Notify the congestion control and avoidance algorithms of the
timeout and, if WAS_LOSS is true, that there was loss.
Thornburgh Informational [Page 85]
^L
RFC 7016 Adobe RTMFP November 2013
3.6.2.7. Abandoning Data
The application can abandon queued messages at any time and for any
reason. Example reasons include (but are not limited to) the
following: one or more fragments of a message have remained in the
SEND_QUEUE for longer than a specified message lifetime; a fragment
has been retransmitted more than a specified retransmission limit; a
prior message on which this message depends (such as a key frame in a
prediction chain) was abandoned and not delivered.
To abandon a message fragment, set its SEND_QUEUE entry's ABANDON
flag to true. When abandoning a message fragment, abandon all
fragments of the message to which it belongs.
An abandoned fragment MUST NOT be un-abandoned.
3.6.2.7.1. Forward Sequence Number Update
Abandoned data may leave gaps in the sequence number space of a flow.
Gaps may cause the receiver to hold completely received messages for
ordered delivery to allow for retransmission of the missing
fragments. User Data chunks (Section 2.3.11) encode a Forward
Sequence Number (FSN) to instruct the receiver that fragments with
sequence numbers less than or equal to the FSN will not be
transmitted or retransmitted.
When the receiver has gaps in the received sequence number space and
no non-abandoned message fragments remain in the SEND_QUEUE, the
sender SHOULD transmit a Forward Sequence Number Update (FSN Update)
comprising a User Data chunk marked abandoned, whose sequence number
is the FSN and whose fsnOffset is 0. An FSN Update allows the
receiver to skip gaps that will not be repaired and deliver received
messages to the user. An FSN Update may be thought of as a
transmission or retransmission of abandoned sequence numbers without
actually sending the data.
The method described in Section 3.6.2.3 ("Sending Data") generates
FSN Updates when appropriate.
Thornburgh Informational [Page 86]
^L
RFC 7016 Adobe RTMFP November 2013
3.6.2.8. Examples
Sender
| :
1 |<--- Ack ID=2, seq:0-16
2 |---> Data ID=2, seq#=25, fsnOff=9 (fsn=16)
3 |---> Data ID=2, seq#=26, fsnOff=10 (fsn=16)
4 |<--- Ack ID=2, seq:0-18
5 |---> Data ID=2, seq#=27, fsnOff=9 (fsn=18)
6 |---> Data ID=2, seq#=28, fsnOff=10 (fsn=18)
| :
There are 9 sequence numbers in flight with delayed acknowledgements.
Figure 20: Normal Flow with No Loss
Thornburgh Informational [Page 87]
^L
RFC 7016 Adobe RTMFP November 2013
Sender
| :
1 |<--- Ack ID=3, seq:0-30
2 |---> Data ID=3, seq#=45, fsnOff=15 (fsn=30)
3 |<--- Ack ID=3, seq:0-30, 32 (nack 31:1)
4 |---> Data ID=3, seq#=46, fsnOff=16 (fsn=30)
5 |<--- Ack ID=3, seq:0-30, 32, 34 (nack 31:2, 33:1)
6 |<--- Ack ID=3, seq:0-30, 32, 34-35 (nack 31:3=lost, 33:2)
7 |---> Data ID=3, seq#=47, fsnOff=15 (fsn=32, abandon 31)
8 |<--- Ack ID=3, seq:0-30, 32, 34-36 (nack 33:3=lost)
9 |---> Data ID=3, seq#=33, fsnOff=1 (fsn=32, retransmit 33)
10 |<--- Ack ID=3, seq:0-30, 32, 34-37
11 |---> Data ID=3, seq#=48, fsnOff=16 (fsn=32)
| :
| (continues through seq#=59)
| :
12 |---> Data ID=3, seq#=60, fsnOff=28(fsn=32)
13 |<--- Ack ID=3, seq:0-30, 34-46
14 |---> Data ID=3, seq#=61, fsnOff=29 (fsn=32)
15 |<--- Ack ID=3, seq:0-32, 34-47
16 |---> Data ID=3, seq#=62, fsnOff=30 (fsn=32)
17 |<--- Ack ID=3, seq:0-47
18 |---> Data ID=3, seq#=63, fsnOff=16 (fsn=47)
19 |<--- Ack ID=3, seq:0-49
20 |---> Data ID=3, seq#=64, fsnOff=15 (fsn=49)
| :
21 |<--- Ack ID=3, seq:0-59
22 |<--- Ack ID=3, seq:0-59, 61 (nack 60:1)
23 |<--- Ack ID=3, seq:0-59, 61-62 (nack 60:2)
24 |<--- Ack ID=3, seq:0-59, 61-63 (nack 60:3=lost)
25 |---> Data ID=3, ABN=1, seq#=60, fsnOff=0 (fsn=60, abandon 60)
26 |<--- Ack ID=3, seq:0-59, 61-64
| :
27 |<--- Ack ID=3, seq:0-64
Flow with sequence numbers 31, 33, and 60 lost in transit, and a
pause at 64. 33 is retransmitted; 31 and 60 are abandoned. Note
that line 25 is a Forward Sequence Number Update (Section 3.6.2.7.1).
Figure 21: Flow with Loss
Thornburgh Informational [Page 88]
^L
RFC 7016 Adobe RTMFP November 2013
3.6.2.9. Flow Control
The flow receiver advertises the amount of new data it's willing to
accept from the flow sender with the bufferBytesAvailable derived
field of an acknowledgement (Sections 2.3.13 and 2.3.14).
The flow sender MUST NOT send new data into the network if
flow.F_OUTSTANDING_BYTES is greater than or equal to the most
recently received buffer advertisement, unless flow.EXCEPTION is true
(Section 3.6.2.3).
3.6.2.9.1. Buffer Probe
The flow sender is suspended if the most recently received buffer
advertisement is zero and the flow hasn't been rejected by the
receiver -- that is, while RX_BUFFER_SIZE is zero AND EXCEPTION is
false. To guard against potentially lost acknowledgements that might
reopen the receive window, a suspended flow sender SHOULD send a
packet comprising a Buffer Probe chunk (Section 2.3.15) for this flow
from time to time.
If the receive window advertisement transitions from non-zero to
zero, the flow sender MAY send a Buffer Probe immediately and SHOULD
send a probe within one second.
The initial period between Buffer Probes SHOULD be at least
one second or ERTO, whichever is greater. The period between probes
SHOULD increase over time, but the period between probes SHOULD NOT
be more than one minute or ERTO, whichever is greater.
The flow sender SHOULD stop sending Buffer Probes if it is no longer
suspended.
3.6.2.10. Exception
The flow receiver can reject the flow at any time and for any reason.
The flow receiver sends a Flow Exception Report (Section 2.3.16) when
it has rejected a flow.
On receiving a Flow Exception Report for a sending flow:
1. If the flow is F_OPEN, close the flow (Section 3.6.2.11) and
notify the user that the far end reported an exception with the
encoded exception code;
2. Set the EXCEPTION flag to true; and
3. For each entry in SEND_QUEUE, set entry.ABANDONED = true.
Thornburgh Informational [Page 89]
^L
RFC 7016 Adobe RTMFP November 2013
3.6.2.11. Close
A sending flow is closed by the user or as a result of an exception.
To close an F_OPEN flow:
1. Move to the F_CLOSING state;
2. If the SEND_QUEUE is not empty, AND the tail entry of the
SEND_QUEUE has a sequence number of NEXT_SN - 1, AND the
tail entry.EVER_SENT is false, set F_FINAL_SN to
entry.SEQUENCE_NUMBER; else
3. The SEND_QUEUE is empty, OR the tail entry does not have a
sequence number of NEXT_SN - 1, OR the tail entry.EVER_SENT is
true: enqueue a new SEND_QUEUE entry with entry.SEQUENCE_NUMBER =
flow.NEXT_SN, entry.FRA = 0, and entry.ABANDONED = true, and set
flow.F_FINAL_SN to entry.SEQUENCE_NUMBER.
An F_CLOSING sending flow is complete when its SEND_QUEUE transitions
to empty, indicating that all sequence numbers, including the
FINAL_SN, have been acknowledged by the other end.
When an F_CLOSING sending flow becomes complete, move to the
F_COMPLETE_LINGER state.
A sending flow MUST remain in the F_COMPLETE_LINGER state for at
least 130 seconds. After at least 130 seconds, move to the F_CLOSED
state. The sending flow is now closed, its resources can be
reclaimed, and its F_FLOW_ID MAY be used for a new sending flow.
3.6.3. Receiver
Each receiving flow comprises the flow-specific information context
necessary to receive that flow's messages from the sending end and
deliver completed messages to the user. Each receiving flow context
includes at least:
o RF_FLOW_ID: this flow's identifier;
o SEQUENCE_SET: the set of all fragment sequence numbers seen in
this receiving flow, whether received or abandoned, initially
empty;
o RF_FINAL_SN: the final fragment sequence number of the flow,
initially having no value;
Thornburgh Informational [Page 90]
^L
RFC 7016 Adobe RTMFP November 2013
o RECV_BUFFER: the message fragments waiting to be delivered to the
user, sorted by sequence number in ascending order, initially
empty; each message fragment entry comprising the following:
* SEQUENCE_NUMBER: the sequence number of this fragment;
* DATA: this fragment's user data; and
* FRA: the fragment control value for this message fragment,
having one of the values enumerated for that purpose in
Section 2.3.11 ("User Data Chunk").
o BUFFERED_SIZE: the sum of the lengths of each fragment in
RECV_BUFFER plus any additional storage overhead for the fragments
incurred by the implementation, in bytes;
o BUFFER_CAPACITY: the desired maximum size for the receive buffer,
in bytes;
o PREV_RWND: the most recent receive window advertisement sent in an
acknowledgement, in 1024-byte blocks, initially having no value;
o SHOULD_ACK: whether or not an acknowledgement should be sent for
this flow, initially false;
o EXCEPTION_CODE: the exception code to report to the sender when
the flow has been rejected, initially 0;
o The state, at any time being one of the following values: the open
state RF_OPEN; the closing states RF_REJECTED and
RF_COMPLETE_LINGER; and the closed state RF_CLOSED.
Thornburgh Informational [Page 91]
^L
RFC 7016 Adobe RTMFP November 2013
Note: The following diagram is only a summary of state transitions
and their causing events, and is not a complete operational
specification.
+-+
|X|
+-+
|rcv User Data for
| no existing flow
v
+---------+
| RF_OPEN |
+---------+
rcv all sequence numbers| |user reject,
0..RF_FINAL_SN | |rcv bad option,
| |no metadata at open,
| |association specified
| | but not F_OPEN at open
+---+ |
| v
| +-----------+
| |RF_REJECTED|
| +-----------+
| |rcv all sequence numbers
| | 0..RF_FINAL_SN
v v
+------------------+
|RF_COMPLETE_LINGER|
+------------------+
| 120 seconds
v
+---------+
|RF_CLOSED|
+---------+
Figure 22: Receiving Flow State Diagram
Thornburgh Informational [Page 92]
^L
RFC 7016 Adobe RTMFP November 2013
3.6.3.1. Startup
A new receiving flow starts on receipt of a User Data chunk
(Section 2.3.11) encoding a flow ID not belonging to any other
receiving flow in the same session in the RF_OPEN, RF_REJECTED, or
RF_COMPLETE_LINGER states.
On receipt of such a User Data chunk:
1. Set temporary variables METADATA, ASSOCIATED_FLOWID, and
ASSOCIATION to each have no value;
2. Create a new receiving flow context in this session, setting its
RF_FLOW_ID to the flow ID encoded in the opening User Data
chunk, and set to the RF_OPEN state;
3. If the opening User Data chunk encodes a User's Per-Flow
Metadata option (Section 2.3.11.1.1), set METADATA to
option.userMetadata;
4. If the opening User Data chunk encodes a Return Flow Association
option (Section 2.3.11.1.2), set ASSOCIATED_FLOWID to
option.flowID;
5. If METADATA has no value, the receiver MUST reject the flow
(Section 3.6.3.7), moving it to the RF_REJECTED state;
6. If ASSOCIATED_FLOWID has a value, then if there is no sending
flow in the same session with a flow ID of ASSOCIATED_FLOWID,
the receiver MUST reject the flow, moving it to the RF_REJECTED
state; otherwise, set ASSOCIATION to the indicated sending flow;
7. If ASSOCIATION indicates a sending flow, AND that sending flow's
state is not F_OPEN, the receiver MUST reject this receiving
flow, moving it to the RF_REJECTED state;
8. If the opening User Data chunk encodes any unrecognized option
with a type code less than 8192 (Section 2.3.11.1), the receiver
MUST reject the flow, moving it to the RF_REJECTED state;
9. If this new receiving flow is still RF_OPEN, then notify the
user that a new receiving flow has opened, including the
METADATA and, if present, the ASSOCIATION, and set
flow.BUFFER_CAPACITY according to the user;
Thornburgh Informational [Page 93]
^L
RFC 7016 Adobe RTMFP November 2013
10. Perform the normal data processing (Section 3.6.3.2) for the
opening User Data chunk; and
11. Set this session's ACK_NOW to true.
3.6.3.2. Receiving Data
A User Data chunk (Section 2.3.11) or a Next User Data chunk
(Section 2.3.12) encodes one fragment of a user data message of a
flow, as well as the flow's Forward Sequence Number and potentially
optional parameters (Section 2.3.11.1).
On receipt of a User Data or Next User Data chunk:
1. If chunk.flowID doesn't indicate an existing receiving flow in
the same session in the RF_OPEN, RF_REJECTED, or
RF_COMPLETE_LINGER state, perform the steps of Section 3.6.3.1
("Startup") to start a new receiving flow;
2. Retrieve the receiving flow context for the flow indicated by
chunk.flowID;
3. Set flow.SHOULD_ACK to true;
4. If the flow is RF_OPEN, AND the chunk encodes any unrecognized
option with a type code less than 8192 (Section 2.3.11.1), the
flow MUST be rejected: notify the user of an exception, and
reject the flow (Section 3.6.3.7), moving it to the RF_REJECTED
state;
5. If the flow is not in the RF_OPEN state, set session.ACK_NOW
to true;
6. If flow.PREV_RWND has a value and that value is less than
2 blocks, set session.ACK_NOW to true;
7. If chunk.abandon is true, set session.ACK_NOW to true;
8. If flow.SEQUENCE_SET has any gaps (that is, if it doesn't
contain every sequence number from 0 through and including the
highest sequence number in the set), set session.ACK_NOW
to true;
9. If flow.SEQUENCE_SET contains chunk.sequenceNumber, then this
chunk is a duplicate: set session.ACK_NOW to true;
Thornburgh Informational [Page 94]
^L
RFC 7016 Adobe RTMFP November 2013
10. If flow.SEQUENCE_SET doesn't contain chunk.sequenceNumber, AND
chunk.final is true, AND flow.RF_FINAL_SN has no value, then set
flow.RF_FINAL_SN to chunk.sequenceNumber, and set
session.ACK_NOW to true;
11. If the flow is in the RF_OPEN state, AND flow.SEQUENCE_SET
doesn't contain chunk.sequenceNumber, AND chunk.abandon is
false, then create a new RECV_BUFFER entry for this chunk's data
and set entry.SEQUENCE_NUMBER to chunk.sequenceNumber,
entry.DATA to chunk.userData, and entry.FRA to
chunk.fragmentControl, and insert this new entry into
flow.RECV_BUFFER;
12. Add to flow.SEQUENCE_SET the range of sequence numbers from 0
through and including the chunk.forwardSequenceNumber derived
field;
13. Add chunk.sequenceNumber to flow.SEQUENCE_SET;
14. If flow.SEQUENCE_SET now has any gaps, set session.ACK_NOW
to true;
15. If session.ACK_NOW is false and session.DELACK_ALARM is not set,
set session.DELACK_ALARM to fire in 200 milliseconds; and
16. Attempt delivery of completed messages in this flow's
RECV_BUFFER to the user (Section 3.6.3.3).
After processing all chunks in a packet containing at least one User
Data chunk, increment session.RX_DATA_PACKETS by one. If
session.RX_DATA_PACKETS is at least two, set session.ACK_NOW to true.
A receiving flow that is not in the RF_CLOSED state is ready to send
an acknowledgement if its SHOULD_ACK flag is set. Acknowledgements
for receiving flows that are ready are sent either opportunistically
by piggybacking on a packet that's already sending user data or an
acknowledgement (Section 3.6.3.4.6), or when the session's ACK_NOW
flag is set (Section 3.6.3.4.5).
3.6.3.3. Buffering and Delivering Data
A receiving flow's information context contains a RECV_BUFFER for
reordering, reassembling, and holding the user data messages of the
flow. Only complete messages are delivered to the user; an
implementation MUST NOT deliver partially received messages, except
by special arrangement with the user.
Thornburgh Informational [Page 95]
^L
RFC 7016 Adobe RTMFP November 2013
Let the Cumulative Acknowledgement Sequence Number (CSN) be the
highest number in the contiguous range of numbers in SEQUENCE_SET
starting with 0. For example, if SEQUENCE_SET contains {0, 1, 2, 3,
5, 6}, the contiguous range starting with 0 is 0..3, so the CSN is 3.
A message is complete if all of its fragments are present in the
RECV_BUFFER. The fragments of one message have contiguous sequence
numbers. A message can be either a single fragment, whose fragment
control value is 0-whole, or two or more fragments where the first's
fragment control value is 1-begin, followed by zero or more fragments
with control value 3-middle, and terminated by a last fragment with
control value 2-end.
An incomplete message segment is a contiguous sequence of one or more
fragments that do not form a complete message -- that is, a 1-begin
followed by zero or more 3-middle fragments but with no 2-end, or
zero or more 3-middle fragments followed by a 2-end but with no
1-begin, or one or more 3-middle fragments with neither a 1-begin nor
a 2-end.
Incomplete message segments can either be in progress or abandoned.
An incomplete segment is abandoned in the following cases:
o The sequence number of the segment's first fragment is less than
or equal to the CSN, AND that fragment's control value is not
1-begin; or
o The sequence number of the segment's last fragment is less than
the CSN.
Abandoned message segments will never be completed, so they SHOULD be
removed from the RECV_BUFFER to make room in the advertised receive
window and the receiver's memory for messages that can be completed.
The user can suspend delivery of a flow's messages. A suspended
receiving flow holds completed messages in its RECV_BUFFER until the
user resumes delivery. A suspended flow can cause the receive window
advertisement to go to zero even when the BUFFER_CAPACITY is
non-zero; this is described in detail in Section 3.6.3.5
("Flow Control").
When the receiving flow is not suspended, the original queuing order
of the messages is recovered by delivering, in ascending sequence
number order, complete messages in the RECV_BUFFER whose sequence
numbers are less than or equal to the CSN.
Thornburgh Informational [Page 96]
^L
RFC 7016 Adobe RTMFP November 2013
The following describes a method for discarding abandoned message
segments and delivering complete messages in original queuing order
when the receiving flow is not suspended.
While the first fragment entry in the RECV_BUFFER has a sequence
number less than or equal to the CSN and delivery is still possible:
1. If entry.FRA is 0-whole, deliver entry.DATA to the user, and
remove this entry from RECV_BUFFER; otherwise,
2. If entry.FRA is 2-end or 3-middle, this entry belongs to an
abandoned segment, so remove and discard this entry from
RECV_BUFFER; otherwise,
3. Entry.FRA is 1-begin. Let LAST_ENTRY be the last RECV_BUFFER
entry that is part of this message segment (LAST_ENTRY can be
entry if the segment has only one fragment so far). Then:
1. If LAST_ENTRY.FRA is 2-end, this segment is a complete
message, so concatenate the DATA fields of each fragment
entry of this segment in ascending sequence number order and
deliver the complete message to the user, then remove the
entries for this complete message from RECV_BUFFER;
otherwise,
2. If LAST_ENTRY.SEQUENCE_NUMBER is less than CSN, this segment
is incomplete and abandoned, so remove and discard the
entries for this segment from RECV_BUFFER; otherwise,
3. LAST_ENTRY.SEQUENCE_NUMBER is equal to CSN and LAST_ENTRY.FRA
is not 2-end: this segment is incomplete but still in
progress. Ordered delivery is no longer possible until at
least one more fragment is received. Stop.
If flow.RF_FINAL_SN has a value and is equal to the CSN, AND
RECV_BUFFER is empty, all complete messages have been delivered to
the user, so notify the user that the flow is complete.
3.6.3.4. Acknowledging Data
A flow receiver SHOULD acknowledge all user data fragment sequence
numbers seen in that flow. Acknowledgements drive the sender's
congestion control and avoidance algorithms, clear data from the
sender's buffers, and in some sender implementations clock new data
into the network; therefore, the acknowledgements must be accurate
and timely.
Thornburgh Informational [Page 97]
^L
RFC 7016 Adobe RTMFP November 2013
3.6.3.4.1. Timing
For reasons similar to those discussed in Section 4.2.3.2 of RFC 1122
[RFC1122], it is advantageous to delay sending acknowledgements for a
short time, so that multiple data fragments can be acknowledged in a
single transmission. However, it is also advantageous for a sender
to receive timely notification about the receiver's disposition of
the flow, particularly in unusual or exceptional circumstances, so
that the circumstances can be addressed if possible.
Therefore, a flow receiver SHOULD send an acknowledgement for a flow
as soon as is practical in any of the following circumstances:
o On receipt of a User Data chunk that starts a new flow;
o On receipt of a User Data or Next User Data chunk if the flow is
not in the RF_OPEN state;
o On receipt of a User Data chunk where, before processing the
chunk, the SEQUENCE_SET of the indicated flow does not contain
every sequence number between 0 and the highest sequence number in
the set (that is, if there was a sequence number gap before
processing the chunk);
o On receipt of a User Data chunk where, after processing the chunk,
the flow's SEQUENCE_SET does not contain every sequence number
between 0 and the highest sequence number in the set (that is, if
this chunk causes a sequence number gap);
o On receipt of a Buffer Probe for the flow;
o On receipt of a User Data chunk if the last acknowledgement sent
for the flow indicated fewer than two bufferBlocksAvailable;
o On receipt of a User Data or Next User Data chunk for the flow if,
after processing the chunk, the flow's BUFFER_CAPACITY is not at
least 1024 bytes greater than BUFFERED_SIZE;
o On receipt of a User Data or Next User Data chunk for any sequence
number that was already seen (that is, on receipt of a duplicate);
o On the first receipt of the final sequence number of the flow;
o On receipt of two packets in the session that contain user data
for any flows since an acknowledgement was last sent, the new
acknowledgements being for the flows having any User Data chunks
in the received packets (that is, for every second packet
containing user data);
Thornburgh Informational [Page 98]
^L
RFC 7016 Adobe RTMFP November 2013
o After receipt of a User Data chunk for the flow, if an
acknowledgement for any other flow is being sent (that is,
consolidate acknowledgements);
o After receipt of a User Data chunk for the flow, if any user data
for a sending flow is being sent in a packet and if there is space
available in the same packet (that is, attempt to piggyback an
acknowledgement with user data if possible);
o No longer than 200 milliseconds after receipt of a User Data chunk
for the flow.
3.6.3.4.2. Size and Truncation
Including an encoded acknowledgement in a packet might cause the
packet to exceed the path MTU. In that case:
o If the packet is being sent primarily to send an acknowledgement,
AND this is the first acknowledgement in the packet, truncate the
acknowledgement so that the packet does not exceed the path MTU;
otherwise,
o The acknowledgement is being piggybacked in a packet with user
data or with an acknowledgement for another flow: do not include
this acknowledgement in the packet, and send it later.
3.6.3.4.3. Constructing
The Data Acknowledgement Bitmap chunk (Section 2.3.13) and Data
Acknowledgement Ranges chunk (Section 2.3.14) encode a receiving
flow's SEQUENCE_SET and its receive window advertisement. The two
chunks are semantically equivalent; implementations SHOULD send
whichever provides the most compact encoding of the SEQUENCE_SET.
When assembling an acknowledgement for a receiving flow:
1. If the flow's state is RF_REJECTED, first assemble a Flow
Exception Report chunk (Section 2.3.16) for flow.flowID;
2. Choose the acknowledgement chunk type that most compactly encodes
flow.SEQUENCE_SET;
3. Use the method described in Section 3.6.3.5 ("Flow Control") to
determine the value for the acknowledgement chunk's
bufferBlocksAvailable field.
Thornburgh Informational [Page 99]
^L
RFC 7016 Adobe RTMFP November 2013
3.6.3.4.4. Delayed Acknowledgement
As discussed in Section 3.6.3.4.1 ("Timing"), a flow receiver can
delay sending an acknowledgement for up to 200 milliseconds after
receiving user data. The method described in Section 3.6.3.2
("Receiving Data") sets the session's DELACK_ALARM.
When DELACK_ALARM fires, set ACK_NOW to true.
3.6.3.4.5. Obligatory Acknowledgement
One or more acknowledgements should be sent as soon as is practical
when the session's ACK_NOW flag is set. While the ACK_NOW flag
is set:
1. Choose a receiving flow that is ready to send an acknowledgement;
2. If there is no such flow, there is no work to do, set ACK_NOW to
false, set RX_DATA_PACKETS to 0, clear the DELACK_ALARM, and
stop; otherwise,
3. Start a new packet;
4. Assemble an acknowledgement for the flow and include it in the
packet, truncating it if necessary so that the packet doesn't
exceed the path MTU;
5. Set flow.SHOULD_ACK to false;
6. Set flow.PREV_RWND to the bufferBlocksAvailable field of the
included acknowledgement chunk;
7. Attempt to piggyback acknowledgements for any other flows that
are ready to send an acknowledgement into the packet, as
described below; and
8. Send the packet.
3.6.3.4.6. Opportunistic Acknowledgement
When sending a packet with user data or an acknowledgement, any other
receiving flows that are ready to send an acknowledgement should
include their acknowledgements in the packet if possible.
Thornburgh Informational [Page 100]
^L
RFC 7016 Adobe RTMFP November 2013
To piggyback acknowledgements in a packet that is already being sent,
where the packet contains user data or an acknowledgement, while
there is at least one receiving flow that is ready to send an
acknowledgement:
1. Assemble an acknowledgement for the flow;
2. If the acknowledgement cannot be included in the packet without
exceeding the path MTU, the packet is full; stop. Otherwise,
3. Include the acknowledgement in the packet;
4. Set flow.SHOULD_ACK to false;
5. Set flow.PREV_RWND to the bufferBlocksAvailable field of the
included acknowledgement chunk; and
6. If there are no longer any receiving flows in the session that
are ready to send an acknowledgement, set session.ACK_NOW to
false, set session.RX_DATA_PACKETS to 0, and clear
session.DELACK_ALARM.
3.6.3.4.7. Example
Figure 23 shows an example flow with sequence numbers 31 and 33 lost
in transit; 31 is abandoned, and 33 is retransmitted.
Receiver
1 |<--- Data ID=3, seq#=29, fsnOff=11 (fsn=18)
2 |<--- Data ID=3, seq#=30, fsnOff=12 (fsn=18)
3 |---> Ack ID=3, seq:0-30
4 |<--- Data ID=3, seq#=32, fsnOff=12 (fsn=20)
5 |---> Ack ID=3, seq:0-30, 32
6 |<--- Data ID=3, seq#=34, fsnOff=12 (fsn=22)
7 |---> Ack ID=3, seq:0-30, 32, 34
| :
8 |<--- Data ID=3, seq#=46, fsnOff=16 (fsn=30)
9 |---> Ack ID=3, seq:0-30, 32, 34-46
10 |<--- Data ID=3, seq#=47, fsnOff=15 (fsn=32)
11 |---> Ack ID=3, seq:0-32, 34-47
12 |<--- Data ID=3, seq#=33, fsnOff=1 (fsn=32)
13 |---> Ack ID=3, seq#=0-47
14 |<--- Data ID=3, seq#=48, fsnOff=16 (fsn=32)
15 |<--- Data ID=3, seq#=49, fsnOff=17 (fsn=32)
16 |---> Ack ID=3, seq#=0-49
| :
Figure 23: Flow Example with Loss
Thornburgh Informational [Page 101]
^L
RFC 7016 Adobe RTMFP November 2013
3.6.3.5. Flow Control
The flow receiver maintains a buffer for reassembling and reordering
messages for delivery to the user (Section 3.6.3.3). The
implementation and the user may wish to limit the amount of resources
(including buffer memory) that a flow is allowed to use.
RTMFP provides a means for each receiving flow to govern the amount
of data sent by the sender, by way of the bufferBytesAvailable
derived field of acknowledgement chunks (Sections 2.3.13 and 2.3.14).
This derived field indicates the amount of data that the sender is
allowed to have outstanding in the network, until instructed
otherwise. This amount is also called the receive window.
The flow receiver can suspend the sender by advertising a closed
(zero length) receive window.
The user can suspend delivery of messages from the receiving flow
(Section 3.6.3.3). This can cause the receive buffer to fill.
In order for progress to be made on completing a fragmented message
or repairing a gap for sequenced delivery in a flow, the flow
receiver MUST advertise at least one buffer block in an
acknowledgement if it is not suspended, even if the amount of data in
the buffer exceeds the buffer capacity, unless the buffer capacity is
0. Otherwise, deadlock can occur, as the receive buffer will stay
full and won't drain because of a gap or incomplete message, and the
gap or incomplete message can't be repaired or completed because the
sender is suspended.
The receive window is advertised in units of 1024-byte blocks. For
example, advertisements for 1 byte, 1023 bytes, and 1024 bytes each
require one block. An advertisement for 1025 bytes requires
two blocks.
The following describes the RECOMMENDED method of calculating the
bufferBlocksAvailable field of an acknowledgement chunk for a
receiving flow:
1. If BUFFERED_SIZE is greater than or equal to BUFFER_CAPACITY, set
ADVERTISE_BYTES to 0;
2. If BUFFERED_SIZE is less than BUFFER_CAPACITY, set
ADVERTISE_BYTES to BUFFER_CAPACITY - BUFFERED_SIZE;
3. Set ADVERTISE_BLOCKS to CEIL(ADVERTISE_BYTES / 1024);
Thornburgh Informational [Page 102]
^L
RFC 7016 Adobe RTMFP November 2013
4. If ADVERTISE_BLOCKS is 0, AND BUFFER_CAPACITY is greater than 0,
AND delivery to the user is not suspended, set ADVERTISE_BLOCKS
to 1; and
5. Set the acknowledgement's bufferBlocksAvailable field to
ADVERTISE_BLOCKS.
3.6.3.6. Receiving a Buffer Probe
A Buffer Probe chunk (Section 2.3.15) is sent by the flow sender
(Section 3.6.2.9.1) to request the current receive window
advertisement (in the form of an acknowledgement) from the flow
receiver.
On receipt of a Buffer Probe chunk:
1. If chunk.flowID doesn't belong to a receiving flow in the same
session in the RF_OPEN, RF_REJECTED, or RF_COMPLETE_LINGER state,
ignore this Buffer Probe; otherwise,
2. Retrieve the receiving flow context for the flow indicated by
chunk.flowID; then
3. Set flow.SHOULD_ACK to true; and
4. Set session.ACK_NOW to true.
3.6.3.7. Rejecting a Flow
A receiver can reject an RF_OPEN flow at any time and for any reason.
To reject a receiving flow in the RF_OPEN state:
1. Move to the RF_REJECTED state;
2. Discard all entries in flow.RECV_BUFFER, as they are no longer
relevant;
3. If the user rejected the flow, set flow.EXCEPTION_CODE to the
exception code indicated by the user; otherwise, the flow was
rejected automatically by the implementation, so the exception
code is 0;
4. Set flow.SHOULD_ACK to true; and
5. Set session.ACK_NOW to true.
Thornburgh Informational [Page 103]
^L
RFC 7016 Adobe RTMFP November 2013
The receiver indicates that it has rejected a flow by sending a Flow
Exception Report chunk (Section 2.3.16) with every acknowledgement
(Section 3.6.3.4.3) for a flow in the RF_REJECTED state.
3.6.3.8. Close
A receiving flow is complete when every sequence number from 0
through and including the final sequence number has been received --
that is, when flow.RF_FINAL_SN has a value and flow.SEQUENCE_SET
contains every sequence number from 0 through flow.RF_FINAL_SN,
inclusive.
When an RF_OPEN or RF_REJECTED receiving flow becomes complete, move
to the RF_COMPLETE_LINGER state, set flow.SHOULD_ACK to true, and set
session.ACK_NOW to true.
A receiving flow SHOULD remain in the RF_COMPLETE_LINGER state for
120 seconds. After 120 seconds, move to the RF_CLOSED state. The
receiving flow is now closed, and its resources can be reclaimed once
all complete messages in flow.RECV_BUFFER have been delivered to the
user (Section 3.6.3.3). The same flow ID might be used for a new
flow by the sender after this point.
Discussion: The flow sender detects that the flow is complete on
receiving an acknowledgement of all fragment sequence numbers of the
flow. This can't happen until after the receiver has detected that
the flow is complete and acknowledged all of the sequence numbers.
The receiver's RF_COMPLETE_LINGER period is two minutes (one Maximum
Segment Lifetime (MSL)); this period allows any in-flight packets to
drain from the network without being misidentified and gives the
sender an opportunity to retransmit any sequence numbers if the
completing acknowledgement is lost. The sender's F_COMPLETE_LINGER
period is at least two minutes plus 10 seconds and doesn't begin
until the completing acknowledgement is received; therefore, the same
flow identifier won't be reused by the flow sender for a new sending
flow for at least 10 seconds after the flow receiver has closed the
receiving flow context. This ensures correct operation independent
of network delay, even when the sender's clock runs up to 8 percent
faster than the receiver's.
4. IANA Considerations
This memo specifies chunk type code values (Section 2.3) and User
Data option type code values (Section 2.3.11.1). These type code
values are assigned and maintained by Adobe. Therefore, this memo
has no IANA actions.
Thornburgh Informational [Page 104]
^L
RFC 7016 Adobe RTMFP November 2013
5. Security Considerations
This memo specifies a general framework that can be used to establish
a confidential and authenticated session between endpoints. A
Cryptography Profile, not specified herein, defines the cryptographic
algorithms, data formats, and semantics as used within this
framework. Designing a Cryptography Profile to ensure that
communications are protected to the degree required by the
application-specific threat model is outside the scope of this
specification.
A block cipher in CBC mode is RECOMMENDED for packet encryption
(Section 2.2.3). An attacker can predict the values of some fields
from one plain RTMFP packet to the next or predict that some fields
may be the same from one packet to the next. This SHOULD be
considered in choosing and implementing a packet encryption cipher
and mode.
The well-known Default Session Key of a Cryptography Profile serves
multiple purposes, including the scrambling of session startup
packets to protect interior fields from undesirable modification by
middleboxes such as NATs, increasing the effort required for casual
passive observation of startup packets, and allowing different
applications of RTMFP using different Default Session Keys to
(intentionally or not) share network transport addresses without
interference. The Default Session Key, being well known, MUST NOT be
construed to contribute to the security of session startup; session
startup is essentially in the clear.
Section 3.5.4.2 describes an OPTIONAL method for processing a change
of network address of a communicating peer. Securely processing
address mobility using that method, or any substantially similar
method, REQUIRES at least that the packet encryption function of the
Cryptography Profile (Section 2.2.3) employs a cryptographic
verification mechanism comprising secret information known only to
the two endpoints. Without this constraint, that method, or any
substantially similar method, becomes "session hijacking support".
Flows and packet fragmentation imply semantics that could cause
unbounded resource utilization in receivers, causing a denial of
service. Implementations SHOULD guard against unbounded or excessive
resource use and abort sessions that appear abusive.
A rogue but popular Redirector (Section 3.5.1.4) could direct session
initiators to flood a victim address or network with Initiator Hello
packets, potentially causing a denial of service.
Thornburgh Informational [Page 105]
^L
RFC 7016 Adobe RTMFP November 2013
An attacker that can passively observe an IHello and that possesses a
certificate matching the Endpoint Discriminator (without having to
know the private key, if any, associated with it) can deny the
initiator access to the desired responder by sending an RHello before
the desired responder does, since only the first received RHello is
selected by the initiator. The attacker needn't forge the desired
responder's source address, since the RHello is selected based on the
tag echo and not the packet's source address. This can simplify the
attack in some network or host configurations.
An attacker that can passively observe and record the packets of an
established session can use traffic analysis techniques to infer the
start and completion of flows without decrypting the packets. The
User Data fragments of flows have unique sequence numbers, so flows
are immune to replay while they are open. However, once a flow has
completed and the linger period has concluded, the attacker could
replay the recorded packets, opening a new flow in the receiver and
duplicating the flow's data; this replay might have undesirable
effects on the receiver's application. The attacker could also infer
that a new flow has begun reusing the recorded flow's identifier and
replay the final sequence number or any of the other fragments in the
flow, potentially denying or interfering with legitimate traffic to
the receiver. Therefore, the data integrity aspect of packet
encryption SHOULD comprise anti-replay measures.
6. Acknowledgements
Special thanks go to Matthew Kaufman for his contributions to the
creation and design of RTMFP.
Thanks to Jari Arkko, Ben Campbell, Wesley Eddy, Stephen Farrell,
Philipp Hancke, Bela Lubkin, Hilarie Orman, Richard Scheffenegger,
and Martin Stiemerling for their detailed reviews of this memo.
Thornburgh Informational [Page 106]
^L
RFC 7016 Adobe RTMFP November 2013
7. References
7.1. Normative References
[CBC] Dworkin, M., "Recommendation for Block Cipher Modes of
Operation", NIST Special Publication 800-38A,
December 2001, <http://csrc.nist.gov/publications/
nistpubs/800-38a/sp800-38a.pdf>.
[RFC0768] Postel, J., "User Datagram Protocol", STD 6, RFC 768,
August 1980.
[RFC0791] Postel, J., "Internet Protocol", STD 5, RFC 791,
September 1981.
[RFC1122] Braden, R., "Requirements for Internet Hosts -
Communication Layers", STD 3, RFC 1122, October 1989.
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119, March 1997.
[RFC2460] Deering, S. and R. Hinden, "Internet Protocol, Version 6
(IPv6) Specification", RFC 2460, December 1998.
[RFC2914] Floyd, S., "Congestion Control Principles", BCP 41,
RFC 2914, September 2000.
[RFC4821] Mathis, M. and J. Heffner, "Packetization Layer Path MTU
Discovery", RFC 4821, March 2007.
[RFC5681] Allman, M., Paxson, V., and E. Blanton, "TCP Congestion
Control", RFC 5681, September 2009.
7.2. Informative References
[RFC5389] Rosenberg, J., Mahy, R., Matthews, P., and D. Wing,
"Session Traversal Utilities for NAT (STUN)", RFC 5389,
October 2008.
[ScalableTCP]
Kelly, T., "Scalable TCP: Improving Performance in
Highspeed Wide Area Networks", December 2002,
<http://datatag.web.cern.ch/datatag/papers/
pfldnet2003-ctk.pdf>.
Thornburgh Informational [Page 107]
^L
RFC 7016 Adobe RTMFP November 2013
Appendix A. Example Congestion Control Algorithm
As mandated in Section 3.5.2, an RTMFP is required to use TCP-
compatible congestion control, but flexibility in exact
implementation is allowed, within certain limits. This section
describes an experimental window-based congestion control algorithm
that is appropriate for real-time and bulk data transport in RTMFP.
The algorithm includes slow start and congestion avoidance phases,
including modified increase and decrease parameters. These
parameters are further adjusted according to whether real-time data
is being sent and whether Time Critical Reverse Notifications are
received.
A.1. Discussion
RFC 5681 defines the standard window-based congestion control
algorithms for TCP. These algorithms are appropriate for delay-
insensitive bulk data transport but have undesirable behaviors for
delay- and loss-sensitive applications. Among the undesirable
behaviors are the cutting of the congestion window in half during a
loss event, and the rapidity of the slow start algorithm's
exponential growth. Cutting the congestion window in half requires a
large channel headroom to support a real-time application and can
cause a large amount of jitter from sender-side buffering. Doubling
the congestion window during the slow start phase can lead to the
congestion window temporarily growing to twice the size it should be,
causing a period of excessive loss in the path.
We found that a number of deployed TCP implementations use the method
of equation (3) from Section 3.1 of RFC 5681; this method, when
combined with the recommended behavior of acknowledging every other
packet, causes the congestion window to grow at approximately half
the rate that the recommended method specifies. In order to compete
fairly with these deployed TCPs, we choose 768 bytes per round trip
as the increment during the normal congestion avoidance phase; this
is approximately half of the typical maximum segment size of
1500 bytes and is also easily subdivided.
The sender may be sending real-time data to the far end. When
sending real-time data, a smoother response to congestion is desired
while still competing with reasonable fairness to other flows in the
Internet. In order to scale the sending rate quickly, the slow start
algorithm is desired, but slow start's normal rate of increase can
cause excessive loss in the last round trip. Accordingly, slow
start's exponential increase rate is adjusted to double approximately
every 3 round trips instead of every round trip. The multiplicative
decrease cuts the congestion window by one eighth on loss to maintain
a smoother sending rate. The additive increase is done at half the
Thornburgh Informational [Page 108]
^L
RFC 7016 Adobe RTMFP November 2013
normal rate (incrementing at 384 bytes per round trip), to both
compensate for the less aggressive loss response and probe the path
capacity more gently.
The far end may report that it is receiving real-time data from other
peers, or the sender may be sending real-time data to other far ends.
In these circumstances (if not sending real-time data to this far
end), it is desirable to respond differently than the standard TCP
algorithms specify, to both yield capacity to the real-time flows and
avoid excessive losses while probing the path capacity. Slow start's
exponential increase is disabled, and the additive increase is done
at half the normal rate (incrementing at 384 bytes per round trip).
Multiplicative decrease is left at the normal rate (cutting by half)
to yield to other flows.
Since real-time messages may be small, and sent regularly, it is
advantageous to spread congestion window increases out across the
round-trip time instead of doing them all at once. We divide the
round trip into 16 segments with an additive increase of a useful
size (48 bytes) per segment.
Scalable TCP [ScalableTCP] describes experimental methods of
modifying the additive increase and multiplicative decrease of the
congestion window in large delay-bandwidth scenarios. The congestion
window is increased by 1% each round trip and decreased by one eighth
on loss in the congestion avoidance phase in certain circumstances
(specifically, when a 1% increase is larger than the normal additive-
increase amount). Those methods are adapted here. The scalable
increase amount is 48 bytes for every 4800 bytes acknowledged, to
spread the increase out over the round trip. The congestion window
is decreased by one eighth on loss when it is at least 67200 bytes
per round trip, which is seven eighths of 76800 (the point at which
1% is greater than 768 bytes per round trip). When sending real-time
data to the far end, the scalable increase is 1% or 384 bytes per
round trip, whichever is greater. Otherwise, when notified that the
far end is receiving real-time data from other peers, the scaled
increase is adjusted to 0.5% or 384 bytes per round trip, whichever
is greater.
Thornburgh Informational [Page 109]
^L
RFC 7016 Adobe RTMFP November 2013
A.2. Algorithm
Let SMSS denote the Sender Maximum Segment Size [RFC5681], for
example 1460 bytes. Let CWND_INIT denote the Initial Congestion
Window (IW) according to Section 3.1 of RFC 5681, for example
4380 bytes. Let CWND_TIMEDOUT denote the congestion window after a
timeout indicating lost data, being 1*SMSS (for example, 1460 bytes).
Let the session information context contain additional variables:
o CWND: the congestion window, initialized to CWND_INIT;
o SSTHRESH: the slow start threshold, initialized to positive
infinity;
o ACKED_BYTES_ACCUMULATOR: a count of acknowledged bytes,
initialized to 0;
o ACKED_BYTES_THIS_PACKET: a count of acknowledged bytes observed in
the current packet;
o PRE_ACK_OUTSTANDING: the number of bytes outstanding in the
network before processing any acknowledgements in the current
packet;
o ANY_LOSS: an indication of whether any loss has been detected in
the current packet;
o ANY_NAKS: an indication of whether any negative acknowledgements
have been detected in the current packet;
o ANY_ACKS: an indication of whether any acknowledgement chunks have
been received in the current packet.
Let FASTGROW_ALLOWED indicate whether the congestion window is
allowed to grow at the normal rate versus a slower rate, being false
if a Time Critical Reverse Notification has been received on this
session within the last 800 milliseconds (Sections 2.2.4 and 3.5.2.1)
or if a Time Critical Forward Notification has been sent on ANY
session in the last 800 milliseconds, and otherwise being true.
Let TC_SENT indicate whether a Time Critical Forward Notification has
been sent on this session within the last 800 milliseconds.
Implement the method described in Section 3.6.2.6 to manage
transmission timeouts, including setting the TIMEOUT_ALARM.
Thornburgh Informational [Page 110]
^L
RFC 7016 Adobe RTMFP November 2013
On being notified that the TIMEOUT_ALARM has fired, perform the
function shown in Figure 24:
on TimeoutNotification(WAS_LOSS):
set SSTHRESH to MAX(SSTHRESH, CWND * 3/4).
set ACKED_BYTES_ACCUMULATOR to 0.
if WAS_LOSS is true:
set CWND to CWND_TIMEDOUT.
else:
set CWND to CWND_INIT.
Figure 24: Pseudocode for Handling a Timeout Notification
Before processing each received packet in this session:
1. Set ANY_LOSS to false;
2. Set ANY_NAKS to false;
3. Set ACKED_BYTES_THIS_PACKET to 0; and
4. Set PRE_ACK_OUTSTANDING to S_OUTSTANDING_BYTES.
On notification of loss (Section 3.6.2.5), set ANY_LOSS to true.
On notification of negative acknowledgement (Section 3.6.2.5), set
ANY_NAKS to true.
On notification of acknowledgement of data (Section 3.6.2.4), set
ANY_ACKS to true, and add the count of acknowledged bytes to
ACKED_BYTES_THIS_PACKET.
Thornburgh Informational [Page 111]
^L
RFC 7016 Adobe RTMFP November 2013
After processing all chunks in each received packet for this session,
perform the function shown in Figure 25:
if ANY_LOSS is true:
if (TC_SENT is true) OR (PRE_ACK_OUTSTANDING > 67200 AND \
FASTGROW_ALLOWED is true):
set SSTHRESH to MAX(PRE_ACK_OUTSTANDING * 7/8, CWND_INIT).
else:
set SSTHRESH to MAX(PRE_ACK_OUTSTANDING * 1/2, CWND_INIT).
set CWND to SSTHRESH.
set ACKED_BYTES_ACCUMULATOR to 0.
else if (ANY_ACKS is true) AND (ANY_NAKS is false) AND \
(PRE_ACK_OUTSTANDING >= CWND):
set var INCREASE to 0.
var AITHRESH.
if FASTGROW_ALLOWED is true:
if CWND < SSTHRESH:
set INCREASE to ACKED_BYTES_THIS_PACKET.
else:
add ACKED_BYTES_THIS_PACKET to ACKED_BYTES_ACCUMULATOR.
set AITHRESH to MIN(MAX(CWND / 16, 64), 4800).
while ACKED_BYTES_ACCUMULATOR >= AITHRESH:
subtract AITHRESH from ACKED_BYTES_ACCUMULATOR.
add 48 to INCREASE.
else FASTGROW_ALLOWED is false:
if CWND < SSTHRESH AND TC_SENT is true:
set INCREASE to CEIL(ACKED_BYTES_THIS_PACKET / 4).
else:
var AITHRESH_CAP.
if TC_SENT is true:
set AITHRESH_CAP to 2400.
else:
set AITHRESH_CAP to 4800.
add ACKED_BYTES_THIS_PACKET to ACKED_BYTES_ACCUMULATOR.
set AITHRESH to MIN(MAX(CWND / 16, 64), AITHRESH_CAP).
while ACKED_BYTES_ACCUMULATOR >= AITHRESH:
subtract AITHRESH from ACKED_BYTES_ACCUMULATOR.
add 24 to INCREASE.
set CWND to MAX(CWND + MIN(INCREASE, SMSS), CWND_INIT).
Figure 25: Pseudocode for Congestion Window Adjustment
after Processing a Packet
Thornburgh Informational [Page 112]
^L
RFC 7016 Adobe RTMFP November 2013
Author's Address
Michael C. Thornburgh
Adobe Systems Incorporated
345 Park Avenue
San Jose, CA 95110-2704
US
Phone: +1 408 536 6000
EMail: mthornbu@adobe.com
URI: http://www.adobe.com/
Thornburgh Informational [Page 113]
^L
|