-
Notifications
You must be signed in to change notification settings - Fork 4
/
495.txt
1899 lines (1706 loc) · 90.2 KB
/
495.txt
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
* Data structures
[62] [[要求]]は、次のようなデータ構造です。
[FIG(list members)[
[FIGCAPTION[
[[要求]]
]FIGCAPTION]
:[[要求メソッド]]:バイト列。
:[[要求対象]]:バイト列。
:[[プロトコルの版]]:[CODE[1.1]]。
:[[ヘッダーリスト]]:0個以上の[[ヘッダー]]のリスト。
:[[本体]]:バイト列。初期値は空。
]FIG]
[63] [[応答]]は、次のようなデータ構造です。
[FIG(list members)[
[FIGCAPTION[
[[応答]]
]FIGCAPTION]
:[[プロトコルの版]]:[CODE[0.9]], [CODE[1.0]], [CODE[1.1]] のいずれか。初期値は [CODE[0.9]]。
:[[状態符号]]:[[非負整数]]。初期値は [CODE[200]]。
:[[理由句]]:[[バイト列]]。初期値は [CODE[OK]]。
:[[ヘッダーリスト]]:0個以上の[[ヘッダー]]のリスト。初期値は空。
:[[不完全メッセージ]]フラグ:初期値は未設定。
]FIG]
[38] 終了は、次のようなデータ構造です。
[FIG(list members)[
[FIGCAPTION[
[[Exit status][exit status]]
]FIGCAPTION]
:リセット:[[真]]か[[偽]]。既定値は[[偽]]。
:失敗:[[真]]か[[偽]]。
:[[WebSocket]] cleanly:[[真]]か[[偽]]か null。既定値は null。
:[[WebSocket]] [[状態符号]]:[[整数]]か null。既定値は null。
:[[WebSocket]] 理由:[[文字列]]か null。既定値は null。
:[131] 再試行可能性:[[真]]か[[偽]]。既定値は[[偽]]。
]FIG]
;; [257] 再試行可能性が[[真]]であれば、何も考えずに同じ[[要求]]を他の[[接続]]で再送信して構いません。
* Proxies
[609] A [[client]] has a [F[PAC]], which is initially [[null]].
If the client is configured to use a [[PAC file]], it is set to an object
which represents the file.
Otherwise, if the client is configured to use one or more proxy servers,
it is set to a virtual [[PAC file]] which represents those proxy server configurations.
@@
[610] To [DFN[run a PAC file]] with [VAR[pac]] and [VAR[url]], ...
[611] The steps to [[run a PAC file]] return zero or more [[proxy configurations][proxy configuration]].
[612] A [DFN[proxy configuration]] has [DFN[[F[protocol]]]], which is one of:
[CODE[tcp]],
[CODE[unix]],
[CODE[http]],
[CODE[https]],
[CODE[socks4]], and
[CODE[socks5]].
[613] A [[proxy configuration]] whose [F[protocol]] is
[CODE[http]], [CODE[https]], [CODE[socks4]], or [CODE[socks5]] has
[DFN[[F[host]]]], whose value is a [[host]], and
[DFN[[F[port]]]], whose value is an [[integer]] or [[null]].
[614] A [[proxy configuration]] whose [F[protocol]] is
[CODE[unix]] has [DFN[[F[path]]]], whose value is a [[byte string]].
* Domain names
[615] The [DFN[name resolution steps]] for [VAR[host]] are these steps:
[FIG(steps)[
= [616] If [VAR[host]] is a [[domain]]:
== [617] Return the result of applying [[name resolution]] to [VAR[host]].
= [618] Otherwise:
== [619] Return [VAR[host]].
]FIG]
;; [620] These steps return an [[IPv4 address]], an [[IPv6 address]],
or an [[error]].
* Connections
[640] A [DFN[connection endpoint]] has following states:
[FIG(list members)[
[FIGCAPTION[
[[Connection endpoint][connection endpoint]]
]FIGCAPTION]
: [DFN[[F[protocol]]][connection's protocol]] :
The value is one of
[CODE[tcp]],
[CODE[unix]],
[CODE[http1]],
[CODE[http2]],
[CODE[socks4]], and
[CODE[socks5]].
:[VAR[種別]]:「サーバー」または「クライアント」。
:[VAR[送信閉じ済みフラグ]]:初期状態では未設定。
:[VAR[受信閉じ済みフラグ]]:初期状態では未設定。
:[VAR[送信待ちバッファー]]:初期状態では空のリスト。
: [DFN[[F[request mode]]]] :
The value is either ''default'' or ''HTTP proxy''.
If the [F[request mode]] of a [[connection]] is ''HTTP proxy'',
a [[request]] has to be sent over the [[connection]] as an [[HTTP request]]
whose [[request target]] is an [[absolute URL]].
]FIG]
[542] To [DFN[establish a connection to the HTTP server]] of an [[URL record]] [VAR[url]]
from a client [VAR[client]], optionally with the [VAR[ws]] flag, run these steps:
[FIG(steps)[
= [543] If [VAR[client]]'s [F[PAC]] is not [[null]]:
== [544] Let [VAR[proxies]] be the result of [[running a PAC file][run a PAC file]] with
[VAR[client]]'s [F[PAC]] and [VAR[url]].
= [545] Otherwise:
== [546] Let [VAR[proxies]] be a list whose only member is a [[proxy configuration]]
whose [F[protocol]] is [CODE[tcp]].
= [547] For each [VAR[proxy]] in [VAR[proxies]], in order, run these substeps:
== [548] Set [VAR[request mode]] to ''default''.
== [549] If [VAR[client]] does not support [VAR[proxy]]'s [F[protocol]]:
=== [550] Set [VAR[connection]] to a [[failure]].
== [551] Otherwise, switch by [VAR[proxy]]'s [F[protocol]]:
[FIG(switch)[
: [CODE[tcp]] :
[FIG(steps)[
= [552] Let [VAR[port]] be the [[effective port]] of [VAR[url]].
= [553] Let [VAR[addr]] be the result of applying [[name resolution steps]]
to [VAR[url]]'s [F[host]].
= [554] If [VAR[addr]] is an [[error]]:
== [555] Set [VAR[connection]] to a [[failure]].
= [556] Otherwise:
== [557] If [VAR[ws]] flag is set, [[wait for other connections]]
with [VAR[addr]] and [VAR[url]]'s [F[port]].
== [558] Set [VAR[connection]] to the result of
[[establishing a TCP connection][establish a TCP connection]]
to [VAR[addr]] and [VAR[port]].
]FIG]
: [CODE[unix]] :
[FIG(steps)[
= [559] Set [VAR[connection]] to the result of
[[establishing a UNIX socket domain connection][establish a UNIX socket domain connection]]
with [VAR[protocol]]'s [F[path]].
]FIG]
: [CODE[http]] or [CODE[https]] :
[FIG(steps)[
= [560] If [VAR[ws]] flag is set, [[wait for other connections]]
with [VAR[url]]'s [F[host]] and [VAR[url]]'s [F[port]].
= [561] Let [VAR[proxy port]] be [VAR[proxy]]'s [F[port]].
= [562] If [VAR[proxy port]] is [[null]]:
== [563] If [VAR[proxy]]'s [F[protocol]] is [CODE[http]], set [VAR[proxy port]] to [[80]].
== [564] If [VAR[proxy]]'s [F[protocol]] is [CODE[https]], set [VAR[proxy port]] to [[443]].
= [565] Let [VAR[proxy addr]] be the result of applying [[name resolution steps]]
to [VAR[proxy]]'s [F[host]].
= [566] If [VAR[proxy addr]] is an [[error]]:
== [567] Set [VAR[connection]] to a [[failure]].
= [568] Otherwise:
== [569] Set [VAR[connection]] to the result of
[[establishing a TCP connection][establish a TCP connection]]
to [VAR[proxy addr]] and [VAR[proxy port]].
= [570] If [VAR[connection]] is ''not'' a [[failure]] and
[VAR[proxy]]'s [F[protocol]] is [CODE[https]]:
== [571] Set [VAR[connection]] to the result of running the [[TLS steps]] for
[VAR[connection]] and [VAR[proxy]]'s [F[host]].
= [572] If [VAR[connection]] is ''not'' a [[failure]] and
[VAR[url]]'s [F[scheme][URL scheme]] is [CODE(URI)@en[https]]:
== [573] If [VAR[url]]'s [F[port]] is [[null]]:
=== [574] Let [VAR[target]] be [VAR[url]]'s [F[host]].
== [575] Otherwise:
=== [576] Let [VAR[target]] be [VAR[url]]'s [F[host]], followed by [CODE[:]],
followed by [VAR[url]]'s [F[port]], [[serialized][serialize an integer]].
== [577] Let [VAR[http]] be a new [[HTTP client]] whose
[F[transport]] is [VAR[connection]].
== [578] Set [VAR[connection]] to the result of
[[establishing an HTTP [CODE(HTTP)[CONNECT]] connection][establish an HTTP [CODE(HTTP)@en[CONNECT]] connection]]
with [VAR[http]] and [VAR[target]].
@@ and proxy credentials
== [579] If [VAR[connection]] is a [[failure]] whose HTTP response's [F[status]] is
[CODE[407]]:
===
@@ Show proxy auth dialog
= [580] Otherwise:
== [581] Set [VAR[request mode]] to ''HTTP proxy''.
]FIG]
: [CODE[socks4]] :
[FIG(steps)[
= [582] Let [VAR[port]] be the [[effective port]] of [VAR[url]].
= [583] Let [VAR[addr]] be the result of applying [[name resolution steps]]
to [VAR[url]]'s [F[host]].
= [584] If [VAR[addr]] is ''not'' an [[IPv4 address]]:
== [585] Set [VAR[connection]] to a [[failure]].
= [586] Otherwise:
== [587] If [VAR[ws]] flag is set, [[wait for other connections]]
with [VAR[addr]] and [VAR[url]]'s [F[port]].
== [588] Let [VAR[proxy port]] be [VAR[proxy]]'s [F[port]].
== [589] If [VAR[proxy port]] is [[null]], set [VAR[proxy port]] to [[1080]].
== [590] Let [VAR[proxy addr]] be the result of applying [[name resolution steps]]
to [VAR[proxy]]'s [F[host]].
== [591] Set [VAR[connection]] to the result of
[[establishing a TCP connection][establish a TCP connection]]
to [VAR[proxy addr]] and [VAR[proxy port]].
== [592] Set [VAR[connection]] to the result of
[[establishing a SOCKS4 connection][establish a SOCKS4 connection]]
with [VAR[connection]], [VAR[addr]], and [VAR[port]].
]FIG]
: [CODE[socks5]] :
[FIG(steps)[
= [593] Let [VAR[port]] be the [[effective port]] of [VAR[url]].
= [594] If [VAR[ws]] flag is set, [[wait for other connections]]
with [VAR[url]]'s [F[host]] and [VAR[url]]'s [F[port]].
= [595] Let [VAR[proxy port]] be [VAR[proxy]]'s [F[port]].
= [597] If [VAR[proxy port]] is [[null]], set [VAR[proxy port]] to [[1080]].
= [596] Let [VAR[proxy addr]] be the result of applying [[name resolution steps]]
to [VAR[proxy]]'s [F[host]].
= [598] Set [VAR[connection]] to the result of
[[establishing a TCP connection][establish a TCP connection]]
to [VAR[proxy addr]] and [VAR[proxy port]].
= [599] Set [VAR[connection]] to the result of
[[establishing a SOCKS5 connection][establish a SOCKS5 connection]]
with [VAR[connection]], [VAR[url]]'s [F[host]], and [VAR[port]].
]FIG]
]FIG]
== [600] If [VAR[connection]] is not a [[failure]]:
=== [601] If [VAR[url]]'s [F[scheme][URL scheme]] is [CODE(URI)@en[https]]:
==== [602] Set [VAR[connection]] to the result of running the [[TLS steps]] for
[VAR[connection]] and [VAR[url]]'s [F[host]].
== [603] If [VAR[connection]] is not a [[failure]]:
=== [604] Set [VAR[connection]]'s [F[request mode]] to [VAR[request mode]].
=== [605] Return [VAR[connection]] and abort these steps.
= [606] Return a [[failure]].
]FIG]
@@
[607] To [DFN[wait for other connections]] with [VAR[host]] and [VAR[port]],
run steps in [[WebSocket接続を得る]].
[642] [[アプリケーション]]は、[[接続]]の端点に次の指示を行えます。
[FIG(list)[
- [[バイト]]の送信の指示
- 正常終了の送信の指示
- 中断の指示
- credentials の送信の指示
]FIG]
[643] [[バイト]]の送信の指示は、送信する[[バイト]] (0-255 のいずれかの値)と、
[[緊急データ]]か否かのフラグ (既定値は未設定。)
を[[引数]]とし、次のように処理します。
[FIG(steps)[
= [644] [VAR[送信閉じ済みフラグ]]が設定されていれば、[[例外]]を投げて停止します。
= [645] [VAR[送信待ちバッファー]]が満杯なら、[[例外]]を投げて停止します。
= [646] [[緊急データ]]フラグが設定されていて、
接続の種類が[[緊急データ]]に対応していないものなら、
[[例外]]を投げて停止します。
= [647] [VAR[送信待ちバッファー]]の末尾に、
引数の[[バイト]]、
引数の[[緊急データ]]か否かのフラグ、
[[約束]]の組を追加します。
= [648] 追加した[[約束]]を返します。
]FIG]
;; [649] 返された[[約束]]は、[[バイト]]が送信された際に[[解決]]されます。
[650] [[バイト列]]を送信するとは、当該[[バイト列]]について先頭の[[バイト]]から順に[[バイト]]の送信の指示を行い、最後の[[バイト]]が返した[[約束]]を返す
(空バイト列なら[[解決]]済みの[[約束]]を返す) ことをいいます。
[651] 正常終了の送信の指示は、次のように処理します。
[FIG(steps)[
= [652] [VAR[送信閉じ済みフラグ]]が設定されていれば、[[例外]]を投げて停止します。
= [653] [VAR[送信閉じ済みフラグ]]を設定します。
= [654] [[接続]]の種類に応じた処理を行います。
]FIG]
[655] 中断の指示は、次のように処理します。
[FIG(steps)[
= [656] [VAR[送信閉じ済みフラグ]]と[VAR[受信閉じ済みフラグ]]の両方が設定されていれば、
[[例外]]を投げて停止します。
= [657] [VAR[送信閉じ済みフラグ]]を設定します。
= [658] [VAR[受信閉じ済みフラグ]]を設定します。
= [659] [VAR[送信待ちバッファー]]の先頭の項目から順に、
[[約束]]を[[拒絶]]していきます。
= [660] [[接続]]の種類に応じた処理を行います。
= [661] 中断の通知を行います。リセットフラグを設定します。
]FIG]
[662] [[credentials]] の送信の指示は、
接続の種類に応じた処理を実行します。そのようなものがなければ、
[[例外]]を投げます。
なお引数として、接続の種類に応じた [[credentials]] を受け取ります。
[663] [[接続]]の端点は、[[アプリケーション]]に対して次の通知を行います。
[FIG(list)[
- [664] [[バイト]]の受信の通知
[FIG(list members)[
:[[バイト]]:受信した[[バイト]]。 0-255 のいずれかの値。
:[[緊急データ]]フラグ: [[TCP]] [[緊急データ]]か否か。既定値は[[偽]]。
]FIG]
- [665] 正常終了の受信の通知
- [666] 中断の通知
[FIG(list members)[
:[[リセット]]フラグ:[[TCP]] [CODE[[[RST]]]] 相当のものであるか否か。既定値は[[偽]]。
]FIG]
- [667] 警告の通知
- [668] challenge の受信の通知
[FIG(list members)[
:接続:認証を行う接続の端点。
:[[challenge]]:プロトコル依存の [[challenge]] データ。
]FIG]
]FIG]
[669] [[接続]]の種類に依存した方法で次の[[バイト]]を送信可能であると判断したら、
次のようにします。
[FIG(steps)[
= [670] [VAR[送信待ちバッファー]]が空なら、ここで停止します。
= [671] [VAR[送信待ちバッファー]]の先頭の項目を取得し、バッファーからは削除します。
= [672] [[接続]]の種類に依存した方法で取得した項目の[[バイト]]を送信します。
(あれば) [[緊急データ]]フラグを引渡します。
= [673] 取得した項目の[[約束]]を[[解決]]します。
]FIG]
** TCP
[608] A [[connection endpoint]] whose [F[protocol][connection's protocol]] is
[CODE[tcp]] has following additional states:
[FIG(list members)[
: [F[remote address]] : An [[IPv4 address]] or [[IPv6 address]].
: [F[remote port]] : An [[integer]].
]FIG]
[627] To [DFN[establish a TCP connection]] to [VAR[addr]] and [VAR[port]],
run these steps:
[FIG(steps)[
= [628] Connect to address [VAR[addr]] and port [VAR[port]] using [[TCP]].
= [641] If a [[TCP connection]] has been established:
== [674] Let [VAR[connection]] be a [[connection endpoint]] representing the
[[TCP connection]], with following states:
[FIG(list members)[
: [F[remote address]] : [VAR[addr]]
: [F[remote port]] : [VAR[port]]
]FIG]
== [630] Disable the [CODE[SO_OOBINLINE]] option of [VAR[connection]].
== [631] Enable the [CODE[SO_NODELAY]] option of [VAR[connection]].
== [632] Run the [[TCP keep alive steps]] for [VAR[connection]].
== [818] Return [VAR[connection]].
= [629] Otherwise:
== [819] Return a [[failure]].
]FIG]
[634] The [DFN[TCP keep alive steps]] for [VAR[connection]] is a set of implementation
dependent steps. An example of such steps is:
[FIG(steps)[
= [635] Enable the [CODE[SO_KEEPALIVE]] option of [VAR[connection]].
= [636] Set [CODE[TCP_KEEPIDLE]] option of [VAR[connection]] to 45 (seconds).
= [637] Set [CODE[TCP_KEEPINTVL]] option of [VAR[connection]] to 45 (seconds).
]FIG]
[676] [[TCP]] の[[セグメント]]を受信したら、次のようにします。
[FIG(steps)[
= [677] [[TCP]] に従い処理し、不適切と判断すればここで停止します。
= [678] [CODE[[[RST]]]] フラグが設定されていれば、
== [679] [VAR[送信閉じ済みフラグ]]を設定します。
== [680] [VAR[受信閉じ済みフラグ]]を設定します。
== [681] 中断を通知します。リセットフラグを設定します。
= [682] データの各[[バイト]]について、順に、
== [683] [[バイト]]の受信を通知します。当該[[バイト]]の値を渡します。
[[緊急ポインター]]が本[[バイト]]を指していれば、[[緊急データ]]フラグも設定します。
= [684] [CODE[[[FIN]]]] フラグが設定されていれば、
== [685] [VAR[受信閉じ済みフラグ]]を設定します。
== [686] 正常終了の受信を通知します。
]FIG]
[687] [[タイムアウト]]その他の理由で[[接続]]が利用できないことを検知したら、
次のようにします。
[FIG(steps)[
= [688] [VAR[送信閉じ済みフラグ]]を設定します。
= [689] [VAR[受信閉じ済みフラグ]]を設定します。
= [690] 中断を通知します。
]FIG]
[691] [[バイト]]を送信できるかどうかは、[[フロー制御]]、[[輻輳制御]]その他の状況により決定します。
[692] [[バイト]]の送信は、次のようにします。
[FIG(steps)[
= [693] [[緊急データ]]フラグが設定されていれば、
== [694] 指定された[[バイト]]をデータとして含み、[[緊急ポインター]]が当該[[バイト]]を指す[[セグメント]]を送信することにします。
= [695] それ以外なら、
== [696] 指定された[[バイト]]をデータとして含む[[セグメント]]を送信することにします。
]FIG]
;; [697] 実際の送信時には、前後の[[バイト]]とまとめた[[セグメント]]で送信されたり、
必要に応じて[[再送]]されたりします。
[698] [[緊急データ]]に対応しています。
[699] 正常終了の送信の指示があれば、次のようにします。
[FIG(steps)[
= [700] [CODE[[[FIN]]]] フラグが設定された[[セグメント]]を送信することにします。
]FIG]
[701] 中断の指示があれば、次のようにします。
[FIG(steps)[
= [702] 必要に応じて [CODE[[[FIN]]]] フラグが設定された[[セグメント]]を送信することにします。
= [703] [[TCP]] で受信したデータの処理を以後行わないことにします。
]FIG]
[622] The [DFN[effective port]] of [VAR[url]] is the value returned by these steps:
[FIG(steps)[
= [623] Let [VAR[port]] be [VAR[url]]'s [F[port][URL's port]].
= [624] If [VAR[port]] is [[null]]:
== [625] Set [VAR[port]] to the value determined by the [VAR[url]]'s [F[scheme][URL scheme]]:
[FIG(switch)[
: [CODE(URI)@en[ftp]] : [[21]]
: [CODE(URI)@en[http]] : [[80]]
: [CODE(URI)@en[https]] : [[443]]
]FIG]
= [626] Return [VAR[port]].
]FIG]
** TLS
[638] The [DFN[TLS steps]] for [VAR[connection]] and [VAR[url]] is:
[FIG(steps)[
@@
]FIG]
[704] 接続の確立は、指定された[VAR[下位の[[接続]]]]において、 [[TLS handshake]]
を適切に行い、正常に完了することによります。
;; [705] [[警告]]を受信していれば、アプリケーションにその旨を通知します。
[706] 確立の完了時に、次の情報をアプリケーションに引渡します。
[FIG(list)[
- [[TLS]] の版
- 選択された [[cipher suite]] と引数
- ([VAR[種別]]が「サーバー」の場合) [[SNI]] ホスト名
- 選択された [[ALPN]] プロトコル
- 相手の[[証明書]]と[[中間証明書]] (あれば)
]FIG]
[707] [VAR[下位の接続]]からバイトを受信したら、[[バイト]]と[[緊急データ]]フラグを [[TLS]] に従い処理します。
[708] [[closure alert]] を受信したら、次のようにします。
[FIG(steps)[
= [709] 正常終了の受信を通知します。
]FIG]
[710] [[error alert]] を受信したら、次のようにします。
[FIG(steps)[
= [711] [[alert level]] が[[警告]]なら、
== [712] 警告を通知します。
= [713] それ以外なら、
== [714] [VAR[送信閉じ済みフラグ]]を設定します。
== [715] [VAR[受信閉じ済みフラグ]]を設定します。
== [716] 中断を通知します。リセットフラグを設定します。
]FIG]
[717] [VAR[下位の接続]]から正常終了を受信したら、次のようにします。
[FIG(steps)[
= [718] [VAR[受信閉じ済みフラグ]]が設定されていなければ、
== [719] [VAR[受信閉じ済みフラグ]]を設定します。
== [720] 正常終了の受信を通知します。
]FIG]
[721] [VAR[下位の接続]]から中断を受信したら、次のようにします。
[FIG(steps)[
= [722] [VAR[受信閉じ済みフラグ]]と[VAR[送信閉じ済みフラグ]]のどちらかが未設定なら、
== [723] [VAR[送信閉じ済みフラグ]]を設定します。
== [724] [VAR[受信閉じ済みフラグ]]を設定します。
== [725] 中断を通知します。
]FIG]
[726] バイトの送信は、 [[TLS]] に従い処理します。
[727] バイトを送信できるかどうかは、新たなバイトを入力として [[TLS]]
で処理できるかどうかとします。
[728] 正常終了の送信の指示があれば、次のようにします。
[FIG(steps)[
= [729] [[closure alert]] を送信します。
= [730] [VAR[下位の接続]]に正常終了の送信を指示します。
]FIG]
[731] 中断の指示があれば、[VAR[下位の接続]]に中断を指示します。
[732] [[TLS]] の処理によりバイト列を送信するべきときは、
[VAR[下位の接続]]で指定されたバイト列を送信します。
[733] [[TLS]] の最初の [[handshake]]
または[[再折衝]]により[[クライアント証明書]]を要求された時は、
次のようにします。
[FIG(steps)[
= [734] challenge の受信を通知します。
[FIG(list members)[
:接続:この[[接続]]。
:challenge:(サーバーなら) [CODE(HTTP)@en[[[ClientHello]]]]
や (クライアントなら) [CODE(HTTP)@en[[[CertificateRequest]]]]
に含まれる情報のうち必要なもの。
]FIG]
]FIG]
[735] credentials の送信は、次のようにします。
[FIG(steps)[
= [736] [[TLS]] が [[credentials]] を受け付ける状態でなければ、例外を投げて停止します。
= [737] そうでなければ、与えられた [[credentials]] を [[TLS]] の処理に引渡します。
]FIG]
** HTTP/1 [CODE(HTTP)@en[CONNECT]] の場合
[738] 状態として、次のものを持ちます。
[FIG(list members)[
:[VAR[HTTP]]:[[HTTP接続]]の[[クライアント]]。[[HTTP接続の処理]]参照。
:[VAR[接続確立済みフラグ]]:初期値は未設定。
]FIG]
[739] 接続の確立は、[VAR[target]] について、次のようにします。
[FIG(steps)[
= [740] [VAR[種別]]が「クライアント」の場合、
== [741] [VAR[HTTP]] を、引数として受け取った[[HTTP接続]]の[[クライアント]]に設定します。
== [742] [VAR[HTTP]] に、[[要求]]を送信します。ただし[[クライアント]]が適切な状態になく[[要求]]を送信できないときは、
[[例外]]を投げて停止します。
[FIG(list members)[
: [F[method][request method]] : [CODE[CONNECT]]
: [F[request target]] : [VAR[target]]
: [F[header list]] :
[FIG(list members)[
: [CODE[Host]] : [VAR[target]]
: [CODE[Proxy-Connection]] : [CODE[keep-alive]]
: [CODE[User-Agent]] : [[default `[CODE[User-Agent]]` value]]
]FIG]
]FIG]
== [743] [VAR[HTTP]] からの通知を、次のように処理します。
=== [744] [[要求]]のヘッダー受信完了の通知の場合、
==-= [745] 応答の状態符号が [CODE(HTTP)[[[200]]]] なら、
==-== [746] [VAR[接続確立済みフラグ]]を設定します。
==-== [747] 接続が確立されたとします。
==-= [748] それ以外なら、
==-== [749] 接続の確立は失敗とします。
=== [750] [[要求]]のデータ受信の通知の場合、
==== [751] [VAR[接続確立済みフラグ]]が設定されていれば、
===-= [752] データの各バイトについて、順に、
===-== [753] バイトの受信を通知します。当該バイトの値を渡します。
=== [754] [[要求]]のデータ終了の通知の場合、
==== [755] [VAR[接続確立済みフラグ]]が設定されていれば、
===-= [756] [VAR[受信閉じ済みフラグ]]を設定します。
===-= [757] 正常終了の受信を通知します。
=== [758] [[要求]]の完了の通知の場合、
==-= [759] 終了の失敗フラグが設定されていれば、
==-== [760] [VAR[接続確立済みフラグ]]が設定されていれば、
==-=== [761] [VAR[送信閉じ済みフラグ]]を設定します。
==-=== [762] [VAR[受信閉じ済みフラグ]]を設定します。
==-=== [763] 中断を通知します。
==-== [764] それ以外なら、
==-=== [765] 接続の確立は失敗とします。
= [766] [VAR[種別]]が「サーバー」の場合、
==
@@
]FIG]
[767] バイトは常に送信可能とします。
[768] バイトの送信は、次のようにします。
[FIG(steps)[
= [769] [VAR[HTTP]] でトンネルに指定されたバイトを送信します。
]FIG]
[770] 正常終了の送信の指示があれば、次のようにします。
[FIG(steps)[
= [771] [VAR[HTTP]] に接続の正常終了を指示します。
]FIG]
[772] 中断の指示があれば、次のようにします。
[FIG(steps)[
= [773] [VAR[HTTP]] に中断を指示します。
]FIG]
** HTTP/2 [CODE[CONNECT]]
@@
** SOCKS4 の場合
[774] 接続の確立は、次のようにします。下位層の接続[VAR[接続]]、
宛先[[IPv4アドレス]][VAR[ホスト]]、宛先[[ポート]]番号[VAR[ポート]]を引数として受け取ります。
[FIG(steps)[
= [775] [VAR[種別]]が「クライアント」の場合、
== [776] [VAR[接続]]で 0x04 0x01 [VAR[p[SUB[1]]]] [VAR[p[SUB[2]]]] [VAR[a[SUB[1]]]] [VAR[a[SUB[2]]]]
[VAR[a[SUB[3]]]] [VAR[a[SUB[4]]]] 0x00 を送信します。
==- [VAR[p[SUB[1]]]] [VAR[p[SUB[2]]]] は[VAR[ポート]]を[[16ビット符号無し整数]]
([[ネットワークバイト順]]) としたものです。
==- [VAR[a[SUB[1]]]] [VAR[a[SUB[2]]]] [VAR[a[SUB[3]]]] [VAR[a[SUB[4]]]]
は[VAR[ホスト]]を[[32ビット符号無し整数]] ([[ネットワークバイト順]]) としたものです。
== [777] [VAR[接続]]から8バイト受信するのを最大30s待ちます。
== [778] 受信した最初の2バイトが 0x00 0x5A でなければ、
=== [779] [VAR[接続]]の中断を指示します。
=== [780] 接続の確立を失敗とします。ここで停止します。
== [781] 接続を確立できたとします。
= [782] [VAR[種別]]が「サーバー」の場合、
==
@@
]FIG]
[783] 接続確立後は、指示は[VAR[接続]]への指示とし、
[VAR[接続]]からの通知があればそれを通知します。
** SOCKS5 の場合
[784] 接続の確立は、次のようにします。下位層の接続[VAR[接続]]、
宛先[[ドメイン名]] (長さ255[[以下]]の[[バイト列]]) または
[[IPv4アドレス]]または[[IPv6アドレス]][VAR[ホスト]]、
宛先[[ポート]]番号[VAR[ポート]]を引数として受け取ります。
[FIG(steps)[
= [785] [VAR[種別]]が「クライアント」の場合、
== [786] [VAR[接続]]で 0x05 0x01 0x00 を送信します。
== [787] [VAR[接続]]から2バイト受信するのを最大30s待ちます。
== [788] 受信したのが 0x05 0x00 でなければ、
=== [789] [VAR[接続]]の中断を指示します。
=== [790] 接続の確立を失敗とします。ここで停止します。
== [791] [VAR[接続]]で 0x05 0x01 0x00 [VAR[A]] [VAR[p[SUB[1]]]] [VAR[p[SUB[2]]]]
を送信します。
==- [VAR[A]] は、
==-= [VAR[ホスト]]が[[ドメイン名]]の場合、[VAR[ホスト]]の前に[VAR[ホスト]]のバイト数を[[8ビット符号無し整数]]としたものです。
==-= [VAR[ホスト]]が[[IPv4アドレス]]の場合、[VAR[ホスト]]を[[32ビット符号無し整数]] ([[ネットワークバイト順]]) としたものです。
==-= [VAR[ホスト]]が[[IPv6アドレス]]の場合、[VAR[ホスト]]を16バイトのバイト列としたものです。
==- [VAR[p[SUB[1]]]] [VAR[p[SUB[2]]]] は[VAR[ポート]]を[[16ビット符号無し整数]]
([[ネットワークバイト順]]) としたものです。
== [792] [VAR[接続]]から5バイト受信するのを最大30s待ちます。
== [793] 受信した最初の3バイトが 0x05 0x00 0x00 でないか、
第4バイトが 0x01, 0x03, 0x04 のいずれでもないか、
5バイトに満たなければ、
=== [794] [VAR[接続]]の中断を指示します。
=== [795] 接続の確立を失敗とします。ここで停止します。
== [796] 第4バイトが 0x01 なら、[VAR[接続]]から5バイト受信するのを最大30s待ちます。
== [797] 第4バイトが 0x03 なら、第5バイトを[[8ビット符号無し整数]]として解釈し、
[VAR[接続]]からそのバイト数 + 2 バイト分受信するのを最大30s待ちます。
== [798] 第4バイトが 0x04 なら、[VAR[接続]]から17バイト受信するのを最大30s待ちます。
== [799] 得られたのが指定のバイト数に満たなければ、
=== [800] [VAR[接続]]の中断を指示します。
=== [801] 接続の確立を失敗とします。ここで停止します。
== [802] 接続を確立できたとします。
= [803] [VAR[種別]]が「サーバー」の場合、
==
@@
]FIG]
[804] 接続確立後は、指示は[VAR[接続]]への指示とし、
[VAR[接続]]からの通知があればそれを通知します。
** UNIX domain socket の場合
[805] 接続の確立は、次のようにします。
[FIG(steps)[
= [806] [VAR[種別]]が「クライアント」の場合、
== [807] [[ソケットAPI]]を使って新たに接続します。
[[アドレス族]]は [CODE[[[AF_UNIX]]]]、パス名は引数で指定された[[パス]]、
[[ソケット型]]は [CODE[[[SOCK_STREAM]]]] とします。
== [808] 接続に失敗すれば、確立は失敗とします。そうでなければ、確立できたとします。
= [809] [VAR[種別]]が「サーバー」の場合、
@@
]FIG]
[810] バイトが送信可能かどうかは、 [CODE[[[send]]]] によりバイト列を送信できるかどうかとします。
[811] バイトの送信は、 [CODE[[[send]]]] によります。
[812] 正常終了の送信の指示があれば、 [CODE[[[shutdown]]]] [CODE[[[SHUT_WR]]]] を実行します。
[813] 中断の指示があれば、 [CODE[[[shutdown]]]] [CODE[[[SHUT_RDWR]]]] を実行します。
[814] [CODE[[[recv]]]] によりバイト列を受信したら、
各バイトを順に、バイトの受信を通知します。
[815] [CODE[[[recv]]]] で何も受信しなくなれば、
[VAR[送信閉じ済みフラグ]]を設定し、正常終了の受信を通知します。
[816] [CODE[[[send]]]] や [CODE[[[recv]]]] でエラーが発生したら、
[VAR[送信閉じ済みフラグ]]と[VAR[受信閉じ済みフラグ]]を設定し、
中断を通知します。
* HTTP clients
[34] [[クライアント]]は、次の内部状態を持ちます。
[FIG(list members)[
:[VAR[種別]]:[[クライアント]]。
:[VAR[接続]]:[[下位層の接続]]の端点。
:[VAR[状態]]:後述の状態遷移における状態のいずれか。初期値は「初期」。
:[VAR[要求の送信状態]]: 未送信、送信中、送信済みのいずれか。初期値は未送信。
:[VAR[要求締め切り]]フラグ:初期値は未設定です。
:[VAR[要求]]:[[要求]]か null。初期値は null です。
:[VAR[応答]]:[[応答]]か null。初期値は null です。
:[VAR[一時バッファー]]:バイト列。初期値は空。
:[VAR[最後のヘッダー]]:ヘッダーか null
:[VAR[残り長さ]]:[[非負整数]]か null か「chunked」かエラー。
:[VAR[応答受信済み]]:[[boolean]]。初期値は[[偽]]。
:[VAR[要求の転送済]]:[[非負整数]]。初期値は 0。
:[VAR[要求の処理完了]]:[[Promise]] か null。初期値は null。
:[VAR[WebSocket接続の状態]]:[CODE[CONNECTING]]、[CODE[OPEN]]、
[CODE[CLOSING]]、[CODE[CLOSED]]、null のいずれか。初期値は null。
:[VAR[フレーム]]:[[WebSocketフレーム]]または null。初期値は null。
:[VAR[先頭フレーム]]:[[WebSocketフレーム]]または null。初期値は null。
:[VAR[送信待ちフレーム]]:[[WebSocketフレーム]]または null。初期値は null。
:[VAR[終了]]:終了または null。初期値は null。
:[VAR[切断タイマー]]:タイマー。
]FIG]
[314] タイマーは、初期状態では動作していません。時間と動作が設定されると、
指定時間経過後に指定の動作が実行されます。既に設定された動作は取り消され、実行されません。
** アプリケーションからの指示
[49] [[接続]]に対して[[アプリケーション]]は、
[FIG(list)[
- [[要求]]の送信 (>>42)
- [[WebSocket]] メッセージ送信 (>>259)
- ping 送信 (>>260)
- [[トンネル]]への[[バイト]]送信 (>>107)
- [[接続]]の正常終了 (>>50)
- 接続の中断 (>>52)
]FIG]
... を指示できます。
[42] 要求の送信は、次のようにします。この処理は、[[要求]]である[VAR[送信する要求]]と、
[VAR[WebSocket]] フラグを入力として受け取ります。
[FIG(steps)[
= [90] 前提として、[VAR[送信する要求]]は次の条件を満たす必要があります。
[FIG(list)[
- [93] [[要求メソッド]]が空ではない。
- [94] [[要求メソッド]]に 0x09, 0x0A, 0x0D, 0x20 が含まれない。
- [95] [[要求対象]]が空ではない。
- [96] [[要求対象]]に 0x0A, 0x0D が含まれない。
- [97] [[要求対象]]の先頭と末尾が 0x09, 0x20 でない。
- [99] すべての[[ヘッダー]]について、
-- [100] 名前に 0x3A が含まれない。
-- [101] 名前が空ではない。
-- [103] 名前に 0x0A, 0x0D が含まれない。
-- [102] 名前の先頭と末尾が 0x09, 0x20 でない。
-- [104] 値に 0x0A, 0x0D が含まれない。
-- [105] 値の先頭と末尾が 0x09, 0x20 でない。
- [298] [CODE(HTTP)@en[[[Transfer-Encoding:]]]] [[ヘッダー]]がない。
- [91] [VAR[WebSocket]] フラグが設定されていれば、
-- [92] [[本体]]が空である。
- [261] [[本体]]が空の場合、
-- [262] [CODE(HTTP)@en[[[Content-Length:]]]] [[ヘッダー]]がないか、値が [CODE[0]] である。
- [267] [[本体]]が空でない場合、
-- [263] [CODE(HTTP)@en[[[Content-Length:]]]] [[ヘッダー]]があって、値が[[本体]]のバイト数である。
]FIG]
= [74] [VAR[要求締め切り]]フラグが設定されているなら、
== [75] エラーを返し、ここで停止します。
= [58] [VAR[状態]]が「初期」か「要求待ち」でなければ、
== [35] エラーを返し、ここで停止します。
= [61] [VAR[要求]]を、[VAR[送信する要求]]に設定します。
= [64] [VAR[応答]]を、新しい[[応答]]に設定します。
= [60] [VAR[一時バッファー]]を、空バイト列に設定します。
= [59] [VAR[状態]]を、「応答前」に設定します。
= [77] [VAR[要求]]に [CODE(HTTP)@en[[[Connection:]]]] [[ヘッダー]]があって
[CODE(HTTP)@en[[[close]]]] ([[ASCII大文字・小文字不区別]]) [[接続オプション]]が指定されていれば、
== [78] [VAR[要求締め切り]]フラグを設定します。
= [98] [VAR[WebSocket]] フラグが設定されていれば、
== [258] [VAR[WebSocket接続の状態]]を、 [CODE[[[CONNECTING]]]] に設定します。
== [265] 16バイトの無作為に決定したバイト列を [[RFC 4648]] [[Base64]]
[[符号化]]したものを[VAR[要求]]の [CODE(HTTP)@en[[[Sec-WebSocket-Key:]]]]
[[ヘッダー]]として追加します。
== [266] [VAR[要求]]に [CODE(HTTP)@en[[[Sec-WebSocket-Version:]]]]
[[ヘッダー]]を値 [CODE[[[13]]]] で追加します。
== [264]
@@ 拡張
= [57] [VAR[要求の送信状態]]を、送信中に設定します。
= [45] [VAR[要求の処理完了]]を、新しい [[Promise]] に設定します。
= [48] [VAR[要求の処理完了]]を返します。
= [46] [[並列に]]、[VAR[要求]]の送信を行います。
]FIG]
[25] [VAR[要求]]の送信は、次のようにします。
[FIG(steps)[
= [47] [[HTTP/1.1]] に従い[VAR[要求]]の[[ヘッダー部]] (空行の [CODE[CRLF]] まで)
を表す[[バイト列]]の各[[バイト]]を順に、
== [VAR[接続]]で[[バイト]]の送信を指示します。
== エラーが返されたら、ここで停止します。
= [1] [VAR[要求]]の[[メッセージ本体]]が存在する場合、各[[バイト]]を順に、
== [VAR[接続]]で[[バイト]]の送信を指示します。
== エラーが返されたら、ここで停止します。
== [VAR[要求の転送済]]を、1だけ大きな値に設定します。
== [VAR[要求]]について要求の本体の一部の送信を通知して構いません。
= [VAR[要求の送信状態]]を、送信済みに設定します。
= [VAR[要求]]について要求の送信完了を通知します。
= [520] [VAR[状態]]が「要求送信中」なら、
== [521] 次の要求に進みます。
]FIG]
[259] [[WebSocket]] メッセージ送信は、次のようにします。
この処理は、[[バイト列]]である[VAR[データ]]と、[[テキスト]]または[[バイナリー]]のいずれかの[VAR[種別]]を引数として受け取ります。
[FIG(steps)[
= [278] 前提として、次の条件を満たす必要があります。
[FIG(list)[
- [289] [VAR[データ]]の長さは 2[SUP[63]] [[未満]]かつ実装の扱える範囲内である
]FIG]
= [271] [VAR[WebSocket接続の状態]]が [CODE[[[OPEN]]]] でなければ、
エラーを返して停止します。
= [268] [[WebSocketフレーム]]を作成します。
[FIG(list members)[
:[[FIN]]:1
:[[RSV1]]:0
:[[RSV2]]:0
:[[RSV3]]:0
:[[opcode]]:[VAR[種別]]がテキストなら 1、バイナリーなら 2
:[[mask]]:1
:[[長さ]]:[VAR[データ]]のバイト数
:[[マスクキー]]:無作為に決定した4バイトのバイト列
:データ:[VAR[データ]]
]FIG]
= [269] 作成した [[WebSocketフレーム]]のデータの各[[バイト]]について、
先頭から [VAR[i]] バイト目 (先頭が0バイト) であれば、
[[マスクキー]]の [VAR[i]] [[mod]] 4 バイト目 (先頭が0バイト)
と [[XOR]] した結果に差し替えます。
= [270] [VAR[接続]]で [[WebSocketフレーム]]のバイト列を送信することとします。
]FIG]
[260] ping 送信は、次のようにします。
この処理は、バイト列である[VAR[データ]]と、[VAR[応答]]フラグを受け取ります。
[FIG(steps)[
= [287] 前提として、次の条件を満たす必要があります。
[FIG(list)[
- [288] [VAR[データ]]の長さは 2[SUP[63]] [[未満]]かつ実装の扱える範囲内である
]FIG]
= [272] [VAR[WebSocket接続の状態]]が [CODE[[[OPEN]]]] でなければ、
エラーを返して停止します。
= [273] [[WebSocketフレーム]]を作成します。
[FIG(list members)[
:[[FIN]]:1
:[[RSV1]]:0
:[[RSV2]]:0
:[[RSV3]]:0
:[[opcode]]:[VAR[応答]]フラグが設定されていれば 10、されていなければ 9
:[[mask]]:1
:[[長さ]]:データのバイト数
:[[マスクキー]]:無作為に決定した4バイトのバイト列
:データ:指定されたバイト列
]FIG]
= [274] 作成した [[WebSocketフレーム]]のデータの各[[バイト]]について、
先頭から [VAR[i]] バイト目 (先頭が0バイト) であれば、
[[マスクキー]]の [VAR[i]] [[mod]] 4 バイト目 (先頭が0バイト)
と [[XOR]] した結果に差し替えます。
= [275] [VAR[接続]]で [[WebSocketフレーム]]のバイト列を送信することとします。
]FIG]
[107] [[トンネル]]への[[バイト]]の送信は、次のようにします。
[FIG(steps)[
= [108] [VAR[状態]]が「トンネル」か「トンネル送信中」以外なら、
== [335] エラーを返し、ここで停止します。
= [109] [VAR[接続]]で指定された[[バイト]]の送信を指示します。
= [110] エラーが返されたら、ここで停止します。
]FIG]
[50] [[接続]]の正常終了は、次のようにします。引数として[[非負整数]]または null
である[VAR[状態符号]]と、
[[バイト列]]である[VAR[理由]]を受け取ります。
[FIG(steps)[
= [286] 前提として、次の条件を満たす必要があります。
[FIG(list)[
- [285] [VAR[状態符号]]は2[SUP[16]] [[以下]]
- [283] [VAR[理由]]の長さは 2[SUP[63]] [[未満]]かつ実装の扱える範囲内である
- [276] [VAR[状態符号]]が null なら、[VAR[理由]]は空である
]FIG]
= [279] [VAR[WebSocket接続の状態]]が [CODE[[[OPEN]]]] か [CODE[[[CONNECTING]]]] なら、
== [281] [[WebSocketフレーム]]を作成します。
[FIG(list members)[
:[[FIN]]:1
:[[RSV1]]:0
:[[RSV2]]:0
:[[RSV3]]:0
:[[opcode]]:8
:[[mask]]:1
:[[長さ]]:データのバイト数
:[[マスクキー]]:無作為に決定した4バイトのバイト列
:データ:[VAR[状態符号]]が null なら空、
そうでなければ、[VAR[状態符号]]を表す[[16ビット符号無し整数]] ([[ネットワークバイト順]]) と、
それに続けて[VAR[理由]]
]FIG]
== [282] 作成した [[WebSocketフレーム]]のデータの各[[バイト]]について、
先頭から [VAR[i]] バイト目 (先頭が0バイト) であれば、
[[マスクキー]]の [VAR[i]] [[mod]] 4 バイト目 (先頭が0バイト)
と [[XOR]] した結果に差し替えます。
== [280] [VAR[WebSocket接続の状態]]が [CODE[[[CONNECTING]]]] なら、
=== [277] [VAR[送信待ちフレーム]]が null なら、[VAR[送信待ちフレーム]]を作成した[[WebSocketフレーム]]に設定します。
== [290] それ以外なら、
=== [297] [VAR[WebSocket接続の状態]]を、 [CODE[[[CLOSING]]]] に設定します。
=== [174] [VAR[要求]]について、WebSocket終了開始を通知します。
=== [284] [VAR[接続]]で、作成した [[WebSocketフレーム]]のバイト列を送信することとします。
=== [315] [VAR[切断タイマー]]により20s後に次の要求に進むことにします。
= [72] [VAR[要求締め切り]]フラグを設定します。
= [66] [VAR[状態]]が「初期」か「要求待ち」か「トンネル」か「トンネル送信中」なら、
== [55] [VAR[接続]]で正常終了の送信を指示します。
= [362] [VAR[状態]]が「トンネル」なら、
== [363] [VAR[状態]]を、「トンネル受信中」に設定します。
]FIG]
;; [73] これにより[[要求]]の送信側は閉じられますが、[[応答]]の受信はまだ続くかもしれません。
[52] [[接続]]の中断は、次のようにします。
[FIG(steps)[
= [44] [VAR[要求の締め切り]]フラグを設定します。
= [39] [VAR[要求の送信状態]]を送信済みに設定します。
= [51] [VAR[接続]]を中断します。
]FIG]
** アプリケーションへの通知
[11] [[状態機械]]は、[[要求]]について次の通知を行います。
それぞれ、次に示す[[引数]] (あれば) 付きで通知されます。
[FIG(list)[
- 要求の本体の一部の送信の通知
[FIG(list members)[
:[[転送済]]:[VAR[要求の転送済]]。
]FIG]
- [526] 要求の送信完了の通知
-- [527] [[要求]]全体の送信が完了したことの通知です。
[[WebSocket]] や [CODE(HTTP)@en[[[CONNECT]]]] [[要求]]では、
[[要求ヘッダー]]後の[[空行]]まで送信した時点で発火されます。
- 応答のヘッダー受信完了の通知
[FIG(list members)[
:[[応答]]:[VAR[応答]]。
:[[WebSocket接続確立]]:[[真]]か[[偽]]。既定値は[[偽]]。
]FIG]
- [377] データ開始の通知
-- [535] [[応答本体]]や[[トンネル]]、
[[バイナリー]]の[[WebSocketメッセージ]]の受信開始前に発火されます。
- [528] データ受信の通知
[FIG(list members)[
:データ:[[バイト列]]。
]FIG]
-- [529] [[応答本体]]や[[トンネル]]、
[[バイナリー]]の[[WebSocketメッセージ]]として[[バイト列]]を受信した際に発火されます。
- [378] データ終了の通知
-- [536] [[応答本体]]や[[トンネル]]、
[[バイナリー]]の[[WebSocketメッセージ]]の受信終了後に発火されます。
- [531] 文字列開始の通知
-- [537] [[テキスト]]の[[WebSocketメッセージ]]の受信開始前に発火されます。
- [532] 文字列受信の通知
[FIG(list members)[
:データ:[[文字列]]。
]FIG]
-- [534] [[テキスト]]の[[WebSocketメッセージ]]の[[文字列]]を受信した際に発火されます。
- [533] 文字列終了の通知
-- [538] [[テキスト]]の[[WebSocketメッセージ]]の受信終了後に発火されます。
- [250] ping の通知
[FIG(list members)[
:返答:[[真]]か[[偽]]。既定値は[[偽]]。
:データ:[[バイト列]]。既定値は空。
]FIG]
- [329] WebSocket終了開始の通知
-- [317] [[WebSocket]] で [[Closeフレーム]]を初めに送信または受信したときに発火されます。
- [358] 完了の通知
[FIG(list members)[
:[[応答]]:[VAR[応答]]。
:[[終了]]:終了。
]FIG]
]FIG]
[15] 各[[要求]]について、2種類の送信の通知と3種類の受信の通知をそれぞれこの順序で行うか、
その途中で失敗の通知で中断するかのいずれかです。
送信の通知と受信の通知はどちらもそれぞれ進行し、相互の順序は不定です。
送信の完了は通知されないことがあります (失敗の場合)。
データ受信の通知は、0回以上の任意の回数行います。
データ受信の通知のかわりに 0回以上の ping の通知がある場合があります。
[[トンネル]]では最初にデータ開始の通知、最後にデータ終了の通知があります。
完了の通知の前に、WebSocket終了開始の通知があるかもしれません。
[FIG(flow)[
:initial:要求の送信
:v:
:>>:3
:->:reqbody
:->:reqeof
:->:headers
:->:rerror
:->:reset
:reqbody:本体一部送信
:->:reqbody
:->:reqeof
:v:
:>>:2
:->:rerror
:->:reset
:reqeof:送信完了
:v:
:>>:1
:->:reset
:headers:ヘッダー受信
:v:
:>>:3
:->:body
:->:complete
:->:reset
:body:受信
:v:
:>>:4