mirror of
https://github.com/caddyserver/caddy.git
synced 2025-01-29 05:15:59 +03:00
vendor: Update dependencies
This commit is contained in:
parent
74940af624
commit
a48e4ecb5a
185 changed files with 24095 additions and 13722 deletions
775
vendor/github.com/aead/chacha20/chacha/chachaAVX2_amd64.s
generated
vendored
775
vendor/github.com/aead/chacha20/chacha/chachaAVX2_amd64.s
generated
vendored
|
@ -41,71 +41,71 @@ DATA ·rol8_AVX2<>+0x18(SB)/8, $0x0E0D0C0F0A09080B
|
|||
GLOBL ·rol8_AVX2<>(SB), (NOPTR+RODATA), $32
|
||||
|
||||
#define ROTL(n, t, v) \
|
||||
VPSLLD $n, v, t; \
|
||||
VPSLLD $n, v, t; \
|
||||
VPSRLD $(32-n), v, v; \
|
||||
VPXOR v, t, v
|
||||
VPXOR v, t, v
|
||||
|
||||
#define CHACHA_QROUND(v0, v1, v2, v3, t, c16, c8) \
|
||||
VPADDD v0, v1, v0; \
|
||||
VPXOR v3, v0, v3; \
|
||||
VPADDD v0, v1, v0; \
|
||||
VPXOR v3, v0, v3; \
|
||||
VPSHUFB c16, v3, v3; \
|
||||
VPADDD v2, v3, v2; \
|
||||
VPXOR v1, v2, v1; \
|
||||
ROTL(12, t, v1); \
|
||||
VPADDD v0, v1, v0; \
|
||||
VPXOR v3, v0, v3; \
|
||||
VPSHUFB c8, v3, v3; \
|
||||
VPADDD v2, v3, v2; \
|
||||
VPXOR v1, v2, v1; \
|
||||
VPADDD v2, v3, v2; \
|
||||
VPXOR v1, v2, v1; \
|
||||
ROTL(12, t, v1); \
|
||||
VPADDD v0, v1, v0; \
|
||||
VPXOR v3, v0, v3; \
|
||||
VPSHUFB c8, v3, v3; \
|
||||
VPADDD v2, v3, v2; \
|
||||
VPXOR v1, v2, v1; \
|
||||
ROTL(7, t, v1)
|
||||
|
||||
#define CHACHA_SHUFFLE(v1, v2, v3) \
|
||||
VPSHUFD $0x39, v1, v1; \
|
||||
VPSHUFD $0x39, v1, v1; \
|
||||
VPSHUFD $0x4E, v2, v2; \
|
||||
VPSHUFD $-109, v3, v3
|
||||
|
||||
#define XOR_AVX2(dst, src, off, v0, v1, v2, v3, t0, t1) \
|
||||
VMOVDQU (0+off)(src), t0; \
|
||||
VPERM2I128 $32, v1, v0, t1; \
|
||||
VPXOR t0, t1, t0; \
|
||||
VMOVDQU t0, (0+off)(dst); \
|
||||
VMOVDQU (32+off)(src), t0; \
|
||||
VPERM2I128 $32, v3, v2, t1; \
|
||||
VPXOR t0, t1, t0; \
|
||||
VMOVDQU t0, (32+off)(dst); \
|
||||
VMOVDQU (64+off)(src), t0; \
|
||||
VPERM2I128 $49, v1, v0, t1; \
|
||||
VPXOR t0, t1, t0; \
|
||||
VMOVDQU t0, (64+off)(dst); \
|
||||
VMOVDQU (96+off)(src), t0; \
|
||||
VPERM2I128 $49, v3, v2, t1; \
|
||||
VPXOR t0, t1, t0; \
|
||||
VMOVDQU t0, (96+off)(dst)
|
||||
VMOVDQU (0+off)(src), t0; \
|
||||
VPERM2I128 $32, v1, v0, t1; \
|
||||
VPXOR t0, t1, t0; \
|
||||
VMOVDQU t0, (0+off)(dst); \
|
||||
VMOVDQU (32+off)(src), t0; \
|
||||
VPERM2I128 $32, v3, v2, t1; \
|
||||
VPXOR t0, t1, t0; \
|
||||
VMOVDQU t0, (32+off)(dst); \
|
||||
VMOVDQU (64+off)(src), t0; \
|
||||
VPERM2I128 $49, v1, v0, t1; \
|
||||
VPXOR t0, t1, t0; \
|
||||
VMOVDQU t0, (64+off)(dst); \
|
||||
VMOVDQU (96+off)(src), t0; \
|
||||
VPERM2I128 $49, v3, v2, t1; \
|
||||
VPXOR t0, t1, t0; \
|
||||
VMOVDQU t0, (96+off)(dst)
|
||||
|
||||
#define XOR_UPPER_AVX2(dst, src, off, v0, v1, v2, v3, t0, t1) \
|
||||
VMOVDQU (0+off)(src), t0; \
|
||||
VPERM2I128 $32, v1, v0, t1; \
|
||||
VPXOR t0, t1, t0; \
|
||||
VMOVDQU t0, (0+off)(dst); \
|
||||
VMOVDQU (32+off)(src), t0; \
|
||||
VPERM2I128 $32, v3, v2, t1; \
|
||||
VPXOR t0, t1, t0; \
|
||||
VMOVDQU t0, (32+off)(dst); \
|
||||
|
||||
VMOVDQU (0+off)(src), t0; \
|
||||
VPERM2I128 $32, v1, v0, t1; \
|
||||
VPXOR t0, t1, t0; \
|
||||
VMOVDQU t0, (0+off)(dst); \
|
||||
VMOVDQU (32+off)(src), t0; \
|
||||
VPERM2I128 $32, v3, v2, t1; \
|
||||
VPXOR t0, t1, t0; \
|
||||
VMOVDQU t0, (32+off)(dst); \
|
||||
|
||||
#define EXTRACT_LOWER(dst, v0, v1, v2, v3, t0) \
|
||||
VPERM2I128 $49, v1, v0, t0; \
|
||||
VMOVDQU t0, 0(dst); \
|
||||
VPERM2I128 $49, v3, v2, t0; \
|
||||
VMOVDQU t0, 32(dst)
|
||||
VPERM2I128 $49, v1, v0, t0; \
|
||||
VMOVDQU t0, 0(dst); \
|
||||
VPERM2I128 $49, v3, v2, t0; \
|
||||
VMOVDQU t0, 32(dst)
|
||||
|
||||
#define XOR_AVX(dst, src, off, v0, v1, v2, v3, t0) \
|
||||
VPXOR 0+off(src), v0, t0; \
|
||||
VMOVDQU t0, 0+off(dst); \
|
||||
VPXOR 16+off(src), v1, t0; \
|
||||
VMOVDQU t0, 16+off(dst); \
|
||||
VPXOR 32+off(src), v2, t0; \
|
||||
VMOVDQU t0, 32+off(dst); \
|
||||
VPXOR 48+off(src), v3, t0; \
|
||||
VPXOR 0+off(src), v0, t0; \
|
||||
VMOVDQU t0, 0+off(dst); \
|
||||
VPXOR 16+off(src), v1, t0; \
|
||||
VMOVDQU t0, 16+off(dst); \
|
||||
VPXOR 32+off(src), v2, t0; \
|
||||
VMOVDQU t0, 32+off(dst); \
|
||||
VPXOR 48+off(src), v3, t0; \
|
||||
VMOVDQU t0, 48+off(dst)
|
||||
|
||||
#define TWO 0(SP)
|
||||
|
@ -119,417 +119,424 @@ GLOBL ·rol8_AVX2<>(SB), (NOPTR+RODATA), $32
|
|||
#define TMP_1 256(SP)
|
||||
|
||||
// func xorKeyStreamAVX(dst, src []byte, block, state *[64]byte, rounds int) int
|
||||
TEXT ·xorKeyStreamAVX2(SB),4,$320-80
|
||||
TEXT ·xorKeyStreamAVX2(SB), 4, $320-80
|
||||
MOVQ dst_base+0(FP), DI
|
||||
MOVQ src_base+24(FP), SI
|
||||
MOVQ src_len+32(FP), CX
|
||||
MOVQ block+48(FP), BX
|
||||
MOVQ state+56(FP), AX
|
||||
MOVQ block+48(FP), BX
|
||||
MOVQ state+56(FP), AX
|
||||
MOVQ rounds+64(FP), DX
|
||||
|
||||
MOVQ SP, R8
|
||||
ADDQ $32, SP
|
||||
ANDQ $-32, SP
|
||||
MOVQ SP, R8
|
||||
ADDQ $32, SP
|
||||
ANDQ $-32, SP
|
||||
|
||||
VMOVDQU 0(AX), Y2
|
||||
VMOVDQU 32(AX), Y3
|
||||
VMOVDQU 0(AX), Y2
|
||||
VMOVDQU 32(AX), Y3
|
||||
VPERM2I128 $0x22, Y2, Y0, Y0
|
||||
VPERM2I128 $0x33, Y2, Y1, Y1
|
||||
VPERM2I128 $0x22, Y3, Y2, Y2
|
||||
VPERM2I128 $0x33, Y3, Y3, Y3
|
||||
|
||||
TESTQ CX, CX
|
||||
JZ done
|
||||
TESTQ CX, CX
|
||||
JZ done
|
||||
|
||||
VMOVDQU ·one_AVX2<>(SB), Y4
|
||||
VPADDD Y4, Y3, Y3
|
||||
VMOVDQU ·one_AVX2<>(SB), Y4
|
||||
VPADDD Y4, Y3, Y3
|
||||
|
||||
VMOVDQA Y0, STATE_0
|
||||
VMOVDQA Y1, STATE_1
|
||||
VMOVDQA Y2, STATE_2
|
||||
VMOVDQA Y3, STATE_3
|
||||
VMOVDQA Y0, STATE_0
|
||||
VMOVDQA Y1, STATE_1
|
||||
VMOVDQA Y2, STATE_2
|
||||
VMOVDQA Y3, STATE_3
|
||||
|
||||
VMOVDQU ·rol16_AVX2<>(SB), Y4
|
||||
VMOVDQU ·rol8_AVX2<>(SB), Y5
|
||||
VMOVDQU ·two_AVX2<>(SB), Y6
|
||||
VMOVDQA Y4, Y14
|
||||
VMOVDQA Y5, Y15
|
||||
VMOVDQA Y4, C16
|
||||
VMOVDQA Y5, C8
|
||||
VMOVDQA Y6, TWO
|
||||
VMOVDQU ·rol16_AVX2<>(SB), Y4
|
||||
VMOVDQU ·rol8_AVX2<>(SB), Y5
|
||||
VMOVDQU ·two_AVX2<>(SB), Y6
|
||||
VMOVDQA Y4, Y14
|
||||
VMOVDQA Y5, Y15
|
||||
VMOVDQA Y4, C16
|
||||
VMOVDQA Y5, C8
|
||||
VMOVDQA Y6, TWO
|
||||
|
||||
CMPQ CX, $64
|
||||
JBE between_0_and_64
|
||||
CMPQ CX, $192
|
||||
JBE between_64_and_192
|
||||
CMPQ CX, $320
|
||||
JBE between_192_and_320
|
||||
CMPQ CX, $448
|
||||
JBE between_320_and_448
|
||||
|
||||
CMPQ CX, $64
|
||||
JBE between_0_and_64
|
||||
CMPQ CX, $192
|
||||
JBE between_64_and_192
|
||||
CMPQ CX, $320
|
||||
JBE between_192_and_320
|
||||
CMPQ CX, $448
|
||||
JBE between_320_and_448
|
||||
|
||||
at_least_512:
|
||||
VMOVDQA Y0, Y4
|
||||
VMOVDQA Y1, Y5
|
||||
VMOVDQA Y2, Y6
|
||||
VPADDQ TWO, Y3, Y7
|
||||
VMOVDQA Y0, Y8
|
||||
VMOVDQA Y1, Y9
|
||||
VMOVDQA Y2, Y10
|
||||
VPADDQ TWO, Y7, Y11
|
||||
VMOVDQA Y0, Y12
|
||||
VMOVDQA Y1, Y13
|
||||
VMOVDQA Y2, Y14
|
||||
VPADDQ TWO, Y11, Y15
|
||||
VMOVDQA Y0, Y4
|
||||
VMOVDQA Y1, Y5
|
||||
VMOVDQA Y2, Y6
|
||||
VPADDQ TWO, Y3, Y7
|
||||
VMOVDQA Y0, Y8
|
||||
VMOVDQA Y1, Y9
|
||||
VMOVDQA Y2, Y10
|
||||
VPADDQ TWO, Y7, Y11
|
||||
VMOVDQA Y0, Y12
|
||||
VMOVDQA Y1, Y13
|
||||
VMOVDQA Y2, Y14
|
||||
VPADDQ TWO, Y11, Y15
|
||||
|
||||
MOVQ DX, R9
|
||||
|
||||
MOVQ DX, R9
|
||||
chacha_loop_512:
|
||||
VMOVDQA Y8, TMP_0
|
||||
CHACHA_QROUND(Y0, Y1, Y2, Y3, Y8, C16, C8)
|
||||
CHACHA_QROUND(Y4, Y5, Y6, Y7, Y8, C16, C8)
|
||||
VMOVDQA TMP_0, Y8
|
||||
VMOVDQA Y0, TMP_0
|
||||
CHACHA_QROUND(Y8, Y9, Y10, Y11, Y0, C16, C8)
|
||||
CHACHA_QROUND(Y12, Y13, Y14, Y15, Y0, C16, C8)
|
||||
CHACHA_SHUFFLE(Y1, Y2, Y3)
|
||||
CHACHA_SHUFFLE(Y5, Y6, Y7)
|
||||
CHACHA_SHUFFLE(Y9, Y10, Y11)
|
||||
CHACHA_SHUFFLE(Y13, Y14, Y15)
|
||||
|
||||
CHACHA_QROUND(Y12, Y13, Y14, Y15, Y0, C16, C8)
|
||||
CHACHA_QROUND(Y8, Y9, Y10, Y11, Y0, C16, C8)
|
||||
VMOVDQA TMP_0, Y0
|
||||
VMOVDQA Y8, TMP_0
|
||||
CHACHA_QROUND(Y4, Y5, Y6, Y7, Y8, C16, C8)
|
||||
CHACHA_QROUND(Y0, Y1, Y2, Y3, Y8, C16, C8)
|
||||
VMOVDQA TMP_0, Y8
|
||||
CHACHA_SHUFFLE(Y3, Y2, Y1)
|
||||
CHACHA_SHUFFLE(Y7, Y6, Y5)
|
||||
CHACHA_SHUFFLE(Y11, Y10, Y9)
|
||||
CHACHA_SHUFFLE(Y15, Y14, Y13)
|
||||
SUBQ $2, R9
|
||||
JA chacha_loop_512
|
||||
VMOVDQA Y8, TMP_0
|
||||
CHACHA_QROUND(Y0, Y1, Y2, Y3, Y8, C16, C8)
|
||||
CHACHA_QROUND(Y4, Y5, Y6, Y7, Y8, C16, C8)
|
||||
VMOVDQA TMP_0, Y8
|
||||
VMOVDQA Y0, TMP_0
|
||||
CHACHA_QROUND(Y8, Y9, Y10, Y11, Y0, C16, C8)
|
||||
CHACHA_QROUND(Y12, Y13, Y14, Y15, Y0, C16, C8)
|
||||
CHACHA_SHUFFLE(Y1, Y2, Y3)
|
||||
CHACHA_SHUFFLE(Y5, Y6, Y7)
|
||||
CHACHA_SHUFFLE(Y9, Y10, Y11)
|
||||
CHACHA_SHUFFLE(Y13, Y14, Y15)
|
||||
|
||||
VMOVDQA Y12, TMP_0
|
||||
VMOVDQA Y13, TMP_1
|
||||
VPADDD STATE_0, Y0, Y0
|
||||
VPADDD STATE_1, Y1, Y1
|
||||
VPADDD STATE_2, Y2, Y2
|
||||
VPADDD STATE_3, Y3, Y3
|
||||
XOR_AVX2(DI, SI, 0, Y0, Y1, Y2, Y3, Y12, Y13)
|
||||
VMOVDQA STATE_0, Y0
|
||||
VMOVDQA STATE_1, Y1
|
||||
VMOVDQA STATE_2, Y2
|
||||
VMOVDQA STATE_3, Y3
|
||||
VPADDQ TWO, Y3, Y3
|
||||
CHACHA_QROUND(Y12, Y13, Y14, Y15, Y0, C16, C8)
|
||||
CHACHA_QROUND(Y8, Y9, Y10, Y11, Y0, C16, C8)
|
||||
VMOVDQA TMP_0, Y0
|
||||
VMOVDQA Y8, TMP_0
|
||||
CHACHA_QROUND(Y4, Y5, Y6, Y7, Y8, C16, C8)
|
||||
CHACHA_QROUND(Y0, Y1, Y2, Y3, Y8, C16, C8)
|
||||
VMOVDQA TMP_0, Y8
|
||||
CHACHA_SHUFFLE(Y3, Y2, Y1)
|
||||
CHACHA_SHUFFLE(Y7, Y6, Y5)
|
||||
CHACHA_SHUFFLE(Y11, Y10, Y9)
|
||||
CHACHA_SHUFFLE(Y15, Y14, Y13)
|
||||
SUBQ $2, R9
|
||||
JA chacha_loop_512
|
||||
|
||||
VPADDD Y0, Y4, Y4
|
||||
VPADDD Y1, Y5, Y5
|
||||
VPADDD Y2, Y6, Y6
|
||||
VPADDD Y3, Y7, Y7
|
||||
XOR_AVX2(DI, SI, 128, Y4, Y5, Y6, Y7, Y12, Y13)
|
||||
VPADDQ TWO, Y3, Y3
|
||||
VMOVDQA Y12, TMP_0
|
||||
VMOVDQA Y13, TMP_1
|
||||
VPADDD STATE_0, Y0, Y0
|
||||
VPADDD STATE_1, Y1, Y1
|
||||
VPADDD STATE_2, Y2, Y2
|
||||
VPADDD STATE_3, Y3, Y3
|
||||
XOR_AVX2(DI, SI, 0, Y0, Y1, Y2, Y3, Y12, Y13)
|
||||
VMOVDQA STATE_0, Y0
|
||||
VMOVDQA STATE_1, Y1
|
||||
VMOVDQA STATE_2, Y2
|
||||
VMOVDQA STATE_3, Y3
|
||||
VPADDQ TWO, Y3, Y3
|
||||
|
||||
VPADDD Y0, Y8, Y8
|
||||
VPADDD Y1, Y9, Y9
|
||||
VPADDD Y2, Y10, Y10
|
||||
VPADDD Y3, Y11, Y11
|
||||
XOR_AVX2(DI, SI, 256, Y8, Y9, Y10, Y11, Y12, Y13)
|
||||
VPADDQ TWO, Y3, Y3
|
||||
VPADDD Y0, Y4, Y4
|
||||
VPADDD Y1, Y5, Y5
|
||||
VPADDD Y2, Y6, Y6
|
||||
VPADDD Y3, Y7, Y7
|
||||
XOR_AVX2(DI, SI, 128, Y4, Y5, Y6, Y7, Y12, Y13)
|
||||
VPADDQ TWO, Y3, Y3
|
||||
|
||||
VPADDD TMP_0, Y0, Y12
|
||||
VPADDD TMP_1, Y1, Y13
|
||||
VPADDD Y2, Y14, Y14
|
||||
VPADDD Y3, Y15, Y15
|
||||
VPADDQ TWO, Y3, Y3
|
||||
VPADDD Y0, Y8, Y8
|
||||
VPADDD Y1, Y9, Y9
|
||||
VPADDD Y2, Y10, Y10
|
||||
VPADDD Y3, Y11, Y11
|
||||
XOR_AVX2(DI, SI, 256, Y8, Y9, Y10, Y11, Y12, Y13)
|
||||
VPADDQ TWO, Y3, Y3
|
||||
|
||||
CMPQ CX, $512
|
||||
JB less_than_512
|
||||
VPADDD TMP_0, Y0, Y12
|
||||
VPADDD TMP_1, Y1, Y13
|
||||
VPADDD Y2, Y14, Y14
|
||||
VPADDD Y3, Y15, Y15
|
||||
VPADDQ TWO, Y3, Y3
|
||||
|
||||
XOR_AVX2(DI, SI, 384, Y12, Y13, Y14, Y15, Y4, Y5)
|
||||
VMOVDQA Y3, STATE_3
|
||||
ADDQ $512, SI
|
||||
ADDQ $512, DI
|
||||
SUBQ $512, CX
|
||||
CMPQ CX, $448
|
||||
JA at_least_512
|
||||
CMPQ CX, $512
|
||||
JB less_than_512
|
||||
|
||||
TESTQ CX, CX
|
||||
JZ done
|
||||
XOR_AVX2(DI, SI, 384, Y12, Y13, Y14, Y15, Y4, Y5)
|
||||
VMOVDQA Y3, STATE_3
|
||||
ADDQ $512, SI
|
||||
ADDQ $512, DI
|
||||
SUBQ $512, CX
|
||||
CMPQ CX, $448
|
||||
JA at_least_512
|
||||
|
||||
VMOVDQA C16, Y14
|
||||
VMOVDQA C8, Y15
|
||||
TESTQ CX, CX
|
||||
JZ done
|
||||
|
||||
CMPQ CX, $64
|
||||
JBE between_0_and_64
|
||||
CMPQ CX, $192
|
||||
JBE between_64_and_192
|
||||
CMPQ CX, $320
|
||||
JBE between_192_and_320
|
||||
JMP between_320_and_448
|
||||
VMOVDQA C16, Y14
|
||||
VMOVDQA C8, Y15
|
||||
|
||||
CMPQ CX, $64
|
||||
JBE between_0_and_64
|
||||
CMPQ CX, $192
|
||||
JBE between_64_and_192
|
||||
CMPQ CX, $320
|
||||
JBE between_192_and_320
|
||||
JMP between_320_and_448
|
||||
|
||||
less_than_512:
|
||||
XOR_UPPER_AVX2(DI, SI, 384, Y12, Y13, Y14, Y15, Y4, Y5)
|
||||
EXTRACT_LOWER(BX, Y12, Y13, Y14, Y15, Y4)
|
||||
ADDQ $448, SI
|
||||
ADDQ $448, DI
|
||||
SUBQ $448, CX
|
||||
JMP finalize
|
||||
XOR_UPPER_AVX2(DI, SI, 384, Y12, Y13, Y14, Y15, Y4, Y5)
|
||||
EXTRACT_LOWER(BX, Y12, Y13, Y14, Y15, Y4)
|
||||
ADDQ $448, SI
|
||||
ADDQ $448, DI
|
||||
SUBQ $448, CX
|
||||
JMP finalize
|
||||
|
||||
between_320_and_448:
|
||||
VMOVDQA Y0, Y4
|
||||
VMOVDQA Y1, Y5
|
||||
VMOVDQA Y2, Y6
|
||||
VPADDQ TWO, Y3, Y7
|
||||
VMOVDQA Y0, Y8
|
||||
VMOVDQA Y1, Y9
|
||||
VMOVDQA Y2, Y10
|
||||
VPADDQ TWO, Y7, Y11
|
||||
VMOVDQA Y0, Y4
|
||||
VMOVDQA Y1, Y5
|
||||
VMOVDQA Y2, Y6
|
||||
VPADDQ TWO, Y3, Y7
|
||||
VMOVDQA Y0, Y8
|
||||
VMOVDQA Y1, Y9
|
||||
VMOVDQA Y2, Y10
|
||||
VPADDQ TWO, Y7, Y11
|
||||
|
||||
MOVQ DX, R9
|
||||
|
||||
MOVQ DX, R9
|
||||
chacha_loop_384:
|
||||
CHACHA_QROUND(Y0, Y1, Y2, Y3, Y13, Y14, Y15)
|
||||
CHACHA_QROUND(Y4, Y5, Y6, Y7, Y13, Y14, Y15)
|
||||
CHACHA_QROUND(Y8, Y9, Y10, Y11, Y13, Y14, Y15)
|
||||
CHACHA_SHUFFLE(Y1, Y2, Y3)
|
||||
CHACHA_SHUFFLE(Y5, Y6, Y7)
|
||||
CHACHA_SHUFFLE(Y9, Y10, Y11)
|
||||
CHACHA_QROUND(Y0, Y1, Y2, Y3, Y13, Y14, Y15)
|
||||
CHACHA_QROUND(Y4, Y5, Y6, Y7, Y13, Y14, Y15)
|
||||
CHACHA_QROUND(Y8, Y9, Y10, Y11, Y13, Y14, Y15)
|
||||
CHACHA_SHUFFLE(Y3, Y2, Y1)
|
||||
CHACHA_SHUFFLE(Y7, Y6, Y5)
|
||||
CHACHA_SHUFFLE(Y11, Y10, Y9)
|
||||
SUBQ $2, R9
|
||||
JA chacha_loop_384
|
||||
CHACHA_QROUND(Y0, Y1, Y2, Y3, Y13, Y14, Y15)
|
||||
CHACHA_QROUND(Y4, Y5, Y6, Y7, Y13, Y14, Y15)
|
||||
CHACHA_QROUND(Y8, Y9, Y10, Y11, Y13, Y14, Y15)
|
||||
CHACHA_SHUFFLE(Y1, Y2, Y3)
|
||||
CHACHA_SHUFFLE(Y5, Y6, Y7)
|
||||
CHACHA_SHUFFLE(Y9, Y10, Y11)
|
||||
CHACHA_QROUND(Y0, Y1, Y2, Y3, Y13, Y14, Y15)
|
||||
CHACHA_QROUND(Y4, Y5, Y6, Y7, Y13, Y14, Y15)
|
||||
CHACHA_QROUND(Y8, Y9, Y10, Y11, Y13, Y14, Y15)
|
||||
CHACHA_SHUFFLE(Y3, Y2, Y1)
|
||||
CHACHA_SHUFFLE(Y7, Y6, Y5)
|
||||
CHACHA_SHUFFLE(Y11, Y10, Y9)
|
||||
SUBQ $2, R9
|
||||
JA chacha_loop_384
|
||||
|
||||
VPADDD STATE_0, Y0, Y0
|
||||
VPADDD STATE_1, Y1, Y1
|
||||
VPADDD STATE_2, Y2, Y2
|
||||
VPADDD STATE_3, Y3, Y3
|
||||
XOR_AVX2(DI, SI, 0, Y0, Y1, Y2, Y3, Y12, Y13)
|
||||
VMOVDQA STATE_0, Y0
|
||||
VMOVDQA STATE_1, Y1
|
||||
VMOVDQA STATE_2, Y2
|
||||
VMOVDQA STATE_3, Y3
|
||||
VPADDQ TWO, Y3, Y3
|
||||
VPADDD STATE_0, Y0, Y0
|
||||
VPADDD STATE_1, Y1, Y1
|
||||
VPADDD STATE_2, Y2, Y2
|
||||
VPADDD STATE_3, Y3, Y3
|
||||
XOR_AVX2(DI, SI, 0, Y0, Y1, Y2, Y3, Y12, Y13)
|
||||
VMOVDQA STATE_0, Y0
|
||||
VMOVDQA STATE_1, Y1
|
||||
VMOVDQA STATE_2, Y2
|
||||
VMOVDQA STATE_3, Y3
|
||||
VPADDQ TWO, Y3, Y3
|
||||
|
||||
VPADDD Y0, Y4, Y4
|
||||
VPADDD Y1, Y5, Y5
|
||||
VPADDD Y2, Y6, Y6
|
||||
VPADDD Y3, Y7, Y7
|
||||
XOR_AVX2(DI, SI, 128, Y4, Y5, Y6, Y7, Y12, Y13)
|
||||
VPADDQ TWO, Y3, Y3
|
||||
VPADDD Y0, Y4, Y4
|
||||
VPADDD Y1, Y5, Y5
|
||||
VPADDD Y2, Y6, Y6
|
||||
VPADDD Y3, Y7, Y7
|
||||
XOR_AVX2(DI, SI, 128, Y4, Y5, Y6, Y7, Y12, Y13)
|
||||
VPADDQ TWO, Y3, Y3
|
||||
|
||||
VPADDD Y0, Y8, Y8
|
||||
VPADDD Y1, Y9, Y9
|
||||
VPADDD Y2, Y10, Y10
|
||||
VPADDD Y3, Y11, Y11
|
||||
VPADDQ TWO, Y3, Y3
|
||||
VPADDD Y0, Y8, Y8
|
||||
VPADDD Y1, Y9, Y9
|
||||
VPADDD Y2, Y10, Y10
|
||||
VPADDD Y3, Y11, Y11
|
||||
VPADDQ TWO, Y3, Y3
|
||||
|
||||
CMPQ CX, $384
|
||||
JB less_than_384
|
||||
|
||||
XOR_AVX2(DI, SI, 256, Y8, Y9, Y10, Y11, Y12, Y13)
|
||||
SUBQ $384, CX
|
||||
TESTQ CX, CX
|
||||
JE done
|
||||
CMPQ CX, $384
|
||||
JB less_than_384
|
||||
|
||||
ADDQ $384, SI
|
||||
ADDQ $384, DI
|
||||
JMP between_0_and_64
|
||||
XOR_AVX2(DI, SI, 256, Y8, Y9, Y10, Y11, Y12, Y13)
|
||||
SUBQ $384, CX
|
||||
TESTQ CX, CX
|
||||
JE done
|
||||
|
||||
ADDQ $384, SI
|
||||
ADDQ $384, DI
|
||||
JMP between_0_and_64
|
||||
|
||||
less_than_384:
|
||||
XOR_UPPER_AVX2(DI, SI, 256, Y8, Y9, Y10, Y11, Y12, Y13)
|
||||
EXTRACT_LOWER(BX, Y8, Y9, Y10, Y11, Y12)
|
||||
ADDQ $320, SI
|
||||
ADDQ $320, DI
|
||||
SUBQ $320, CX
|
||||
JMP finalize
|
||||
XOR_UPPER_AVX2(DI, SI, 256, Y8, Y9, Y10, Y11, Y12, Y13)
|
||||
EXTRACT_LOWER(BX, Y8, Y9, Y10, Y11, Y12)
|
||||
ADDQ $320, SI
|
||||
ADDQ $320, DI
|
||||
SUBQ $320, CX
|
||||
JMP finalize
|
||||
|
||||
between_192_and_320:
|
||||
VMOVDQA Y0, Y4
|
||||
VMOVDQA Y1, Y5
|
||||
VMOVDQA Y2, Y6
|
||||
VMOVDQA Y3, Y7
|
||||
VMOVDQA Y0, Y8
|
||||
VMOVDQA Y1, Y9
|
||||
VMOVDQA Y2, Y10
|
||||
VPADDQ TWO, Y3, Y11
|
||||
|
||||
MOVQ DX, R9
|
||||
VMOVDQA Y0, Y4
|
||||
VMOVDQA Y1, Y5
|
||||
VMOVDQA Y2, Y6
|
||||
VMOVDQA Y3, Y7
|
||||
VMOVDQA Y0, Y8
|
||||
VMOVDQA Y1, Y9
|
||||
VMOVDQA Y2, Y10
|
||||
VPADDQ TWO, Y3, Y11
|
||||
|
||||
MOVQ DX, R9
|
||||
|
||||
chacha_loop_256:
|
||||
CHACHA_QROUND(Y4, Y5, Y6, Y7, Y13, Y14, Y15)
|
||||
CHACHA_QROUND(Y8, Y9, Y10, Y11, Y13, Y14, Y15)
|
||||
CHACHA_SHUFFLE(Y5, Y6, Y7)
|
||||
CHACHA_SHUFFLE(Y9, Y10, Y11)
|
||||
CHACHA_QROUND(Y4, Y5, Y6, Y7, Y13, Y14, Y15)
|
||||
CHACHA_QROUND(Y8, Y9, Y10, Y11, Y13, Y14, Y15)
|
||||
CHACHA_SHUFFLE(Y7, Y6, Y5)
|
||||
CHACHA_SHUFFLE(Y11, Y10, Y9)
|
||||
SUBQ $2, R9
|
||||
JA chacha_loop_256
|
||||
CHACHA_QROUND(Y4, Y5, Y6, Y7, Y13, Y14, Y15)
|
||||
CHACHA_QROUND(Y8, Y9, Y10, Y11, Y13, Y14, Y15)
|
||||
CHACHA_SHUFFLE(Y5, Y6, Y7)
|
||||
CHACHA_SHUFFLE(Y9, Y10, Y11)
|
||||
CHACHA_QROUND(Y4, Y5, Y6, Y7, Y13, Y14, Y15)
|
||||
CHACHA_QROUND(Y8, Y9, Y10, Y11, Y13, Y14, Y15)
|
||||
CHACHA_SHUFFLE(Y7, Y6, Y5)
|
||||
CHACHA_SHUFFLE(Y11, Y10, Y9)
|
||||
SUBQ $2, R9
|
||||
JA chacha_loop_256
|
||||
|
||||
VPADDD Y0, Y4, Y4
|
||||
VPADDD Y1, Y5, Y5
|
||||
VPADDD Y2, Y6, Y6
|
||||
VPADDD Y3, Y7, Y7
|
||||
VPADDQ TWO, Y3, Y3
|
||||
XOR_AVX2(DI, SI, 0, Y4, Y5, Y6, Y7, Y12, Y13)
|
||||
VPADDD Y0, Y8, Y8
|
||||
VPADDD Y1, Y9, Y9
|
||||
VPADDD Y2, Y10, Y10
|
||||
VPADDD Y3, Y11, Y11
|
||||
VPADDQ TWO, Y3, Y3
|
||||
VPADDD Y0, Y4, Y4
|
||||
VPADDD Y1, Y5, Y5
|
||||
VPADDD Y2, Y6, Y6
|
||||
VPADDD Y3, Y7, Y7
|
||||
VPADDQ TWO, Y3, Y3
|
||||
XOR_AVX2(DI, SI, 0, Y4, Y5, Y6, Y7, Y12, Y13)
|
||||
VPADDD Y0, Y8, Y8
|
||||
VPADDD Y1, Y9, Y9
|
||||
VPADDD Y2, Y10, Y10
|
||||
VPADDD Y3, Y11, Y11
|
||||
VPADDQ TWO, Y3, Y3
|
||||
|
||||
CMPQ CX, $256
|
||||
JB less_than_256
|
||||
|
||||
XOR_AVX2(DI, SI, 128, Y8, Y9, Y10, Y11, Y12, Y13)
|
||||
SUBQ $256, CX
|
||||
TESTQ CX, CX
|
||||
JE done
|
||||
CMPQ CX, $256
|
||||
JB less_than_256
|
||||
|
||||
XOR_AVX2(DI, SI, 128, Y8, Y9, Y10, Y11, Y12, Y13)
|
||||
SUBQ $256, CX
|
||||
TESTQ CX, CX
|
||||
JE done
|
||||
|
||||
ADDQ $256, SI
|
||||
ADDQ $256, DI
|
||||
JMP between_0_and_64
|
||||
|
||||
ADDQ $256, SI
|
||||
ADDQ $256, DI
|
||||
JMP between_0_and_64
|
||||
|
||||
less_than_256:
|
||||
XOR_UPPER_AVX2(DI, SI, 128, Y8, Y9, Y10, Y11, Y12, Y13)
|
||||
EXTRACT_LOWER(BX, Y8, Y9, Y10, Y11, Y12)
|
||||
ADDQ $192, SI
|
||||
ADDQ $192, DI
|
||||
SUBQ $192, CX
|
||||
JMP finalize
|
||||
XOR_UPPER_AVX2(DI, SI, 128, Y8, Y9, Y10, Y11, Y12, Y13)
|
||||
EXTRACT_LOWER(BX, Y8, Y9, Y10, Y11, Y12)
|
||||
ADDQ $192, SI
|
||||
ADDQ $192, DI
|
||||
SUBQ $192, CX
|
||||
JMP finalize
|
||||
|
||||
between_64_and_192:
|
||||
VMOVDQA Y0, Y4
|
||||
VMOVDQA Y1, Y5
|
||||
VMOVDQA Y2, Y6
|
||||
VMOVDQA Y3, Y7
|
||||
VMOVDQA Y0, Y4
|
||||
VMOVDQA Y1, Y5
|
||||
VMOVDQA Y2, Y6
|
||||
VMOVDQA Y3, Y7
|
||||
|
||||
MOVQ DX, R9
|
||||
|
||||
MOVQ DX, R9
|
||||
chacha_loop_128:
|
||||
CHACHA_QROUND(Y4, Y5, Y6, Y7, Y13, Y14, Y15)
|
||||
CHACHA_SHUFFLE(Y5, Y6, Y7)
|
||||
CHACHA_QROUND(Y4, Y5, Y6, Y7, Y13, Y14, Y15)
|
||||
CHACHA_SHUFFLE(Y7, Y6, Y5)
|
||||
SUBQ $2, R9
|
||||
JA chacha_loop_128
|
||||
CHACHA_QROUND(Y4, Y5, Y6, Y7, Y13, Y14, Y15)
|
||||
CHACHA_SHUFFLE(Y5, Y6, Y7)
|
||||
CHACHA_QROUND(Y4, Y5, Y6, Y7, Y13, Y14, Y15)
|
||||
CHACHA_SHUFFLE(Y7, Y6, Y5)
|
||||
SUBQ $2, R9
|
||||
JA chacha_loop_128
|
||||
|
||||
VPADDD Y0, Y4, Y4
|
||||
VPADDD Y1, Y5, Y5
|
||||
VPADDD Y2, Y6, Y6
|
||||
VPADDD Y3, Y7, Y7
|
||||
VPADDQ TWO, Y3, Y3
|
||||
|
||||
CMPQ CX, $128
|
||||
JB less_than_128
|
||||
|
||||
XOR_AVX2(DI, SI, 0, Y4, Y5, Y6, Y7, Y12, Y13)
|
||||
SUBQ $128, CX
|
||||
TESTQ CX, CX
|
||||
JE done
|
||||
VPADDD Y0, Y4, Y4
|
||||
VPADDD Y1, Y5, Y5
|
||||
VPADDD Y2, Y6, Y6
|
||||
VPADDD Y3, Y7, Y7
|
||||
VPADDQ TWO, Y3, Y3
|
||||
|
||||
CMPQ CX, $128
|
||||
JB less_than_128
|
||||
|
||||
XOR_AVX2(DI, SI, 0, Y4, Y5, Y6, Y7, Y12, Y13)
|
||||
SUBQ $128, CX
|
||||
TESTQ CX, CX
|
||||
JE done
|
||||
|
||||
ADDQ $128, SI
|
||||
ADDQ $128, DI
|
||||
JMP between_0_and_64
|
||||
|
||||
ADDQ $128, SI
|
||||
ADDQ $128, DI
|
||||
JMP between_0_and_64
|
||||
|
||||
less_than_128:
|
||||
XOR_UPPER_AVX2(DI, SI, 0, Y4, Y5, Y6, Y7, Y12, Y13)
|
||||
EXTRACT_LOWER(BX, Y4, Y5, Y6, Y7, Y13)
|
||||
ADDQ $64, SI
|
||||
ADDQ $64, DI
|
||||
SUBQ $64, CX
|
||||
JMP finalize
|
||||
XOR_UPPER_AVX2(DI, SI, 0, Y4, Y5, Y6, Y7, Y12, Y13)
|
||||
EXTRACT_LOWER(BX, Y4, Y5, Y6, Y7, Y13)
|
||||
ADDQ $64, SI
|
||||
ADDQ $64, DI
|
||||
SUBQ $64, CX
|
||||
JMP finalize
|
||||
|
||||
between_0_and_64:
|
||||
VMOVDQA X0, X4
|
||||
VMOVDQA X1, X5
|
||||
VMOVDQA X2, X6
|
||||
VMOVDQA X3, X7
|
||||
VMOVDQA X0, X4
|
||||
VMOVDQA X1, X5
|
||||
VMOVDQA X2, X6
|
||||
VMOVDQA X3, X7
|
||||
|
||||
MOVQ DX, R9
|
||||
|
||||
MOVQ DX, R9
|
||||
chacha_loop_64:
|
||||
CHACHA_QROUND(X4, X5, X6, X7, X13, X14, X15)
|
||||
CHACHA_SHUFFLE(X5, X6, X7)
|
||||
CHACHA_QROUND(X4, X5, X6, X7, X13, X14, X15)
|
||||
CHACHA_SHUFFLE(X7, X6, X5)
|
||||
SUBQ $2, R9
|
||||
JA chacha_loop_64
|
||||
CHACHA_QROUND(X4, X5, X6, X7, X13, X14, X15)
|
||||
CHACHA_SHUFFLE(X5, X6, X7)
|
||||
CHACHA_QROUND(X4, X5, X6, X7, X13, X14, X15)
|
||||
CHACHA_SHUFFLE(X7, X6, X5)
|
||||
SUBQ $2, R9
|
||||
JA chacha_loop_64
|
||||
|
||||
VPADDD X0, X4, X4
|
||||
VPADDD X1, X5, X5
|
||||
VPADDD X2, X6, X6
|
||||
VPADDD X3, X7, X7
|
||||
VMOVDQU ·one_AVX<>(SB), X0
|
||||
VPADDQ X0, X3, X3
|
||||
VPADDD X0, X4, X4
|
||||
VPADDD X1, X5, X5
|
||||
VPADDD X2, X6, X6
|
||||
VPADDD X3, X7, X7
|
||||
VMOVDQU ·one_AVX<>(SB), X0
|
||||
VPADDQ X0, X3, X3
|
||||
|
||||
CMPQ CX, $64
|
||||
JB less_than_64
|
||||
CMPQ CX, $64
|
||||
JB less_than_64
|
||||
|
||||
XOR_AVX(DI, SI, 0, X4, X5, X6, X7, X13)
|
||||
SUBQ $64, CX
|
||||
JMP done
|
||||
XOR_AVX(DI, SI, 0, X4, X5, X6, X7, X13)
|
||||
SUBQ $64, CX
|
||||
JMP done
|
||||
|
||||
less_than_64:
|
||||
VMOVDQU X4, 0(BX)
|
||||
VMOVDQU X5, 16(BX)
|
||||
VMOVDQU X6, 32(BX)
|
||||
VMOVDQU X7, 48(BX)
|
||||
|
||||
VMOVDQU X4, 0(BX)
|
||||
VMOVDQU X5, 16(BX)
|
||||
VMOVDQU X6, 32(BX)
|
||||
VMOVDQU X7, 48(BX)
|
||||
|
||||
finalize:
|
||||
XORQ R11, R11
|
||||
XORQ R12, R12
|
||||
MOVQ CX, BP
|
||||
XORQ R11, R11
|
||||
XORQ R12, R12
|
||||
MOVQ CX, BP
|
||||
|
||||
xor_loop:
|
||||
MOVB 0(SI), R11
|
||||
MOVB 0(BX), R12
|
||||
XORQ R11, R12
|
||||
MOVB R12, 0(DI)
|
||||
INCQ SI
|
||||
INCQ BX
|
||||
INCQ DI
|
||||
DECQ BP
|
||||
JA xor_loop
|
||||
MOVB 0(SI), R11
|
||||
MOVB 0(BX), R12
|
||||
XORQ R11, R12
|
||||
MOVB R12, 0(DI)
|
||||
INCQ SI
|
||||
INCQ BX
|
||||
INCQ DI
|
||||
DECQ BP
|
||||
JA xor_loop
|
||||
|
||||
done:
|
||||
VMOVDQU X3, 48(AX)
|
||||
VZEROUPPER
|
||||
MOVQ R8, SP
|
||||
MOVQ CX, ret+72(FP)
|
||||
RET
|
||||
VMOVDQU X3, 48(AX)
|
||||
VZEROUPPER
|
||||
MOVQ R8, SP
|
||||
MOVQ CX, ret+72(FP)
|
||||
RET
|
||||
|
||||
// func hChaCha20AVX(out *[32]byte, nonce *[16]byte, key *[32]byte)
|
||||
TEXT ·hChaCha20AVX(SB), 4, $0-24
|
||||
MOVQ out+0(FP), DI
|
||||
MOVQ nonce+8(FP), AX
|
||||
MOVQ key+16(FP), BX
|
||||
MOVQ out+0(FP), DI
|
||||
MOVQ nonce+8(FP), AX
|
||||
MOVQ key+16(FP), BX
|
||||
|
||||
VMOVDQU ·sigma_AVX<>(SB), X0
|
||||
VMOVDQU 0(BX), X1
|
||||
VMOVDQU 16(BX), X2
|
||||
VMOVDQU 0(AX), X3
|
||||
VMOVDQU ·rol16_AVX2<>(SB), X5
|
||||
VMOVDQU ·rol8_AVX2<>(SB), X6
|
||||
VMOVDQU ·sigma_AVX<>(SB), X0
|
||||
VMOVDQU 0(BX), X1
|
||||
VMOVDQU 16(BX), X2
|
||||
VMOVDQU 0(AX), X3
|
||||
VMOVDQU ·rol16_AVX2<>(SB), X5
|
||||
VMOVDQU ·rol8_AVX2<>(SB), X6
|
||||
|
||||
MOVQ $20, CX
|
||||
|
||||
MOVQ $20, CX
|
||||
chacha_loop:
|
||||
CHACHA_QROUND(X0, X1, X2, X3, X4, X5, X6)
|
||||
CHACHA_SHUFFLE(X1, X2, X3)
|
||||
CHACHA_QROUND(X0, X1, X2, X3, X4, X5, X6)
|
||||
CHACHA_SHUFFLE(X3, X2, X1)
|
||||
SUBQ $2, CX
|
||||
JNZ chacha_loop
|
||||
CHACHA_QROUND(X0, X1, X2, X3, X4, X5, X6)
|
||||
CHACHA_SHUFFLE(X1, X2, X3)
|
||||
CHACHA_QROUND(X0, X1, X2, X3, X4, X5, X6)
|
||||
CHACHA_SHUFFLE(X3, X2, X1)
|
||||
SUBQ $2, CX
|
||||
JNZ chacha_loop
|
||||
|
||||
VMOVDQU X0, 0(DI)
|
||||
VMOVDQU X3, 16(DI)
|
||||
VZEROUPPER
|
||||
RET
|
||||
VMOVDQU X0, 0(DI)
|
||||
VMOVDQU X3, 16(DI)
|
||||
VZEROUPPER
|
||||
RET
|
||||
|
||||
// func supportsAVX2() bool
|
||||
TEXT ·supportsAVX2(SB), 4, $0-1
|
||||
MOVQ runtime·support_avx(SB), AX
|
||||
MOVQ runtime·support_avx2(SB), BX
|
||||
MOVQ runtime·support_avx2(SB), BX
|
||||
ANDQ AX, BX
|
||||
MOVB BX, ret+0(FP)
|
||||
RET
|
||||
MOVB BX, ret+0(FP)
|
||||
RET
|
||||
|
|
386
vendor/github.com/aead/chacha20/chacha/chacha_386.s
generated
vendored
386
vendor/github.com/aead/chacha20/chacha/chacha_386.s
generated
vendored
|
@ -25,231 +25,233 @@ DATA ·rol8<>+0x08(SB)/8, $0x0E0D0C0F0A09080B
|
|||
GLOBL ·rol8<>(SB), (NOPTR+RODATA), $16
|
||||
|
||||
#define ROTL_SSE2(n, t, v) \
|
||||
MOVO v, t; \
|
||||
PSLLL $n, t; \
|
||||
MOVO v, t; \
|
||||
PSLLL $n, t; \
|
||||
PSRLL $(32-n), v; \
|
||||
PXOR t, v
|
||||
PXOR t, v
|
||||
|
||||
#define CHACHA_QROUND_SSE2(v0 , v1 , v2 , v3 , t0) \
|
||||
PADDL v1, v0; \
|
||||
PXOR v0, v3; \
|
||||
#define CHACHA_QROUND_SSE2(v0, v1, v2, v3, t0) \
|
||||
PADDL v1, v0; \
|
||||
PXOR v0, v3; \
|
||||
ROTL_SSE2(16, t0, v3); \
|
||||
PADDL v3, v2; \
|
||||
PXOR v2, v1; \
|
||||
PADDL v3, v2; \
|
||||
PXOR v2, v1; \
|
||||
ROTL_SSE2(12, t0, v1); \
|
||||
PADDL v1, v0; \
|
||||
PXOR v0, v3; \
|
||||
ROTL_SSE2(8, t0, v3); \
|
||||
PADDL v3, v2; \
|
||||
PXOR v2, v1; \
|
||||
PADDL v1, v0; \
|
||||
PXOR v0, v3; \
|
||||
ROTL_SSE2(8, t0, v3); \
|
||||
PADDL v3, v2; \
|
||||
PXOR v2, v1; \
|
||||
ROTL_SSE2(7, t0, v1)
|
||||
|
||||
#define CHACHA_QROUND_SSSE3(v0 , v1 , v2 , v3 , t0, r16, r8) \
|
||||
PADDL v1, v0; \
|
||||
PXOR v0, v3; \
|
||||
PSHUFB r16, v3; \
|
||||
PADDL v3, v2; \
|
||||
PXOR v2, v1; \
|
||||
|
||||
#define CHACHA_QROUND_SSSE3(v0, v1, v2, v3, t0, r16, r8) \
|
||||
PADDL v1, v0; \
|
||||
PXOR v0, v3; \
|
||||
PSHUFB r16, v3; \
|
||||
PADDL v3, v2; \
|
||||
PXOR v2, v1; \
|
||||
ROTL_SSE2(12, t0, v1); \
|
||||
PADDL v1, v0; \
|
||||
PXOR v0, v3; \
|
||||
PSHUFB r8, v3; \
|
||||
PADDL v3, v2; \
|
||||
PXOR v2, v1; \
|
||||
PADDL v1, v0; \
|
||||
PXOR v0, v3; \
|
||||
PSHUFB r8, v3; \
|
||||
PADDL v3, v2; \
|
||||
PXOR v2, v1; \
|
||||
ROTL_SSE2(7, t0, v1)
|
||||
|
||||
#define CHACHA_SHUFFLE(v1, v2, v3) \
|
||||
PSHUFL $0x39, v1, v1; \
|
||||
PSHUFL $0x39, v1, v1; \
|
||||
PSHUFL $0x4E, v2, v2; \
|
||||
PSHUFL $0x93, v3, v3
|
||||
|
||||
#define XOR(dst, src, off, v0 , v1 , v2 , v3 , t0) \
|
||||
MOVOU 0+off(src), t0; \
|
||||
PXOR v0, t0; \
|
||||
MOVOU t0, 0+off(dst); \
|
||||
#define XOR(dst, src, off, v0, v1, v2, v3, t0) \
|
||||
MOVOU 0+off(src), t0; \
|
||||
PXOR v0, t0; \
|
||||
MOVOU t0, 0+off(dst); \
|
||||
MOVOU 16+off(src), t0; \
|
||||
PXOR v1, t0; \
|
||||
PXOR v1, t0; \
|
||||
MOVOU t0, 16+off(dst); \
|
||||
MOVOU 32+off(src), t0; \
|
||||
PXOR v2, t0; \
|
||||
PXOR v2, t0; \
|
||||
MOVOU t0, 32+off(dst); \
|
||||
MOVOU 48+off(src), t0; \
|
||||
PXOR v3, t0; \
|
||||
PXOR v3, t0; \
|
||||
MOVOU t0, 48+off(dst)
|
||||
|
||||
#define FINALIZE(dst, src, block, len, t0, t1) \
|
||||
XORL t0, t0; \
|
||||
XORL t1, t1; \
|
||||
finalize: \
|
||||
MOVB 0(src), t0; \
|
||||
MOVB 0(block), t1; \
|
||||
XORL t0, t1; \
|
||||
MOVB t1, 0(dst); \
|
||||
INCL src; \
|
||||
INCL block; \
|
||||
INCL dst; \
|
||||
DECL len; \
|
||||
JA finalize \
|
||||
|
||||
XORL t0, t0; \
|
||||
XORL t1, t1; \
|
||||
finalize: \
|
||||
MOVB 0(src), t0; \
|
||||
MOVB 0(block), t1; \
|
||||
XORL t0, t1; \
|
||||
MOVB t1, 0(dst); \
|
||||
INCL src; \
|
||||
INCL block; \
|
||||
INCL dst; \
|
||||
DECL len; \
|
||||
JA finalize \
|
||||
|
||||
// func xorKeyStreamSSE2(dst, src []byte, block, state *[64]byte, rounds int) int
|
||||
TEXT ·xorKeyStreamSSE2(SB),4,$0-40
|
||||
TEXT ·xorKeyStreamSSE2(SB), 4, $0-40
|
||||
MOVL dst_base+0(FP), DI
|
||||
MOVL src_base+12(FP), SI
|
||||
MOVL src_len+16(FP), CX
|
||||
MOVL state+28(FP), AX
|
||||
MOVL state+28(FP), AX
|
||||
MOVL rounds+32(FP), DX
|
||||
|
||||
MOVOU 0(AX), X0
|
||||
MOVOU 16(AX), X1
|
||||
MOVOU 32(AX), X2
|
||||
MOVOU 48(AX), X3
|
||||
MOVOU 0(AX), X0
|
||||
MOVOU 16(AX), X1
|
||||
MOVOU 32(AX), X2
|
||||
MOVOU 48(AX), X3
|
||||
|
||||
TESTL CX, CX
|
||||
JZ done
|
||||
TESTL CX, CX
|
||||
JZ done
|
||||
|
||||
at_least_64:
|
||||
MOVO X0, X4
|
||||
MOVO X1, X5
|
||||
MOVO X2, X6
|
||||
MOVO X3, X7
|
||||
MOVO X0, X4
|
||||
MOVO X1, X5
|
||||
MOVO X2, X6
|
||||
MOVO X3, X7
|
||||
|
||||
MOVL DX, BX
|
||||
|
||||
MOVL DX, BX
|
||||
chacha_loop:
|
||||
CHACHA_QROUND_SSE2(X4, X5, X6, X7, X0)
|
||||
CHACHA_SHUFFLE(X5, X6, X7)
|
||||
CHACHA_QROUND_SSE2(X4, X5, X6, X7, X0)
|
||||
CHACHA_SHUFFLE(X7, X6, X5)
|
||||
SUBL $2, BX
|
||||
JA chacha_loop
|
||||
CHACHA_QROUND_SSE2(X4, X5, X6, X7, X0)
|
||||
CHACHA_SHUFFLE(X5, X6, X7)
|
||||
CHACHA_QROUND_SSE2(X4, X5, X6, X7, X0)
|
||||
CHACHA_SHUFFLE(X7, X6, X5)
|
||||
SUBL $2, BX
|
||||
JA chacha_loop
|
||||
|
||||
MOVOU 0(AX), X0
|
||||
PADDL X0, X4
|
||||
PADDL X1, X5
|
||||
PADDL X2, X6
|
||||
PADDL X3, X7
|
||||
MOVOU ·one<>(SB), X0
|
||||
PADDQ X0, X3
|
||||
MOVOU 0(AX), X0
|
||||
PADDL X0, X4
|
||||
PADDL X1, X5
|
||||
PADDL X2, X6
|
||||
PADDL X3, X7
|
||||
MOVOU ·one<>(SB), X0
|
||||
PADDQ X0, X3
|
||||
|
||||
CMPL CX, $64
|
||||
JB less_than_64
|
||||
CMPL CX, $64
|
||||
JB less_than_64
|
||||
|
||||
XOR(DI, SI, 0, X4, X5, X6, X7, X0)
|
||||
MOVOU 0(AX), X0
|
||||
ADDL $64, SI
|
||||
ADDL $64, DI
|
||||
SUBL $64, CX
|
||||
JNZ at_least_64
|
||||
XOR(DI, SI, 0, X4, X5, X6, X7, X0)
|
||||
MOVOU 0(AX), X0
|
||||
ADDL $64, SI
|
||||
ADDL $64, DI
|
||||
SUBL $64, CX
|
||||
JNZ at_least_64
|
||||
|
||||
less_than_64:
|
||||
MOVL CX, BP
|
||||
TESTL BP, BP
|
||||
JZ done
|
||||
MOVL CX, BP
|
||||
TESTL BP, BP
|
||||
JZ done
|
||||
|
||||
MOVL block+24(FP), BX
|
||||
MOVOU X4, 0(BX)
|
||||
MOVOU X5, 16(BX)
|
||||
MOVOU X6, 32(BX)
|
||||
MOVOU X7, 48(BX)
|
||||
FINALIZE(DI, SI, BX, BP, AX, DX)
|
||||
MOVL block+24(FP), BX
|
||||
MOVOU X4, 0(BX)
|
||||
MOVOU X5, 16(BX)
|
||||
MOVOU X6, 32(BX)
|
||||
MOVOU X7, 48(BX)
|
||||
FINALIZE(DI, SI, BX, BP, AX, DX)
|
||||
|
||||
done:
|
||||
MOVL state+28(FP), AX
|
||||
MOVOU X3, 48(AX)
|
||||
MOVL CX, ret+36(FP)
|
||||
RET
|
||||
MOVL state+28(FP), AX
|
||||
MOVOU X3, 48(AX)
|
||||
MOVL CX, ret+36(FP)
|
||||
RET
|
||||
|
||||
// func xorKeyStreamSSSE3(dst, src []byte, block, state *[64]byte, rounds int) int
|
||||
TEXT ·xorKeyStreamSSSE3(SB),4,$64-40
|
||||
TEXT ·xorKeyStreamSSSE3(SB), 4, $64-40
|
||||
MOVL dst_base+0(FP), DI
|
||||
MOVL src_base+12(FP), SI
|
||||
MOVL src_len+16(FP), CX
|
||||
MOVL state+28(FP), AX
|
||||
MOVL state+28(FP), AX
|
||||
MOVL rounds+32(FP), DX
|
||||
|
||||
MOVOU 48(AX), X3
|
||||
TESTL CX, CX
|
||||
JZ done
|
||||
MOVOU 48(AX), X3
|
||||
TESTL CX, CX
|
||||
JZ done
|
||||
|
||||
MOVL SP, BP
|
||||
ADDL $16, SP
|
||||
ANDL $-16, SP
|
||||
MOVL SP, BP
|
||||
ADDL $16, SP
|
||||
ANDL $-16, SP
|
||||
|
||||
MOVOU ·one<>(SB), X0
|
||||
MOVOU 16(AX), X1
|
||||
MOVOU 32(AX), X2
|
||||
MOVO X0, 0(SP)
|
||||
MOVO X1, 16(SP)
|
||||
MOVO X2, 32(SP)
|
||||
MOVOU ·one<>(SB), X0
|
||||
MOVOU 16(AX), X1
|
||||
MOVOU 32(AX), X2
|
||||
MOVO X0, 0(SP)
|
||||
MOVO X1, 16(SP)
|
||||
MOVO X2, 32(SP)
|
||||
|
||||
MOVOU 0(AX), X0
|
||||
MOVOU ·rol16<>(SB), X1
|
||||
MOVOU ·rol8<>(SB), X2
|
||||
|
||||
MOVOU 0(AX), X0
|
||||
MOVOU ·rol16<>(SB), X1
|
||||
MOVOU ·rol8<>(SB), X2
|
||||
|
||||
at_least_64:
|
||||
MOVO X0, X4
|
||||
MOVO 16(SP), X5
|
||||
MOVO 32(SP), X6
|
||||
MOVO X3, X7
|
||||
MOVO X0, X4
|
||||
MOVO 16(SP), X5
|
||||
MOVO 32(SP), X6
|
||||
MOVO X3, X7
|
||||
|
||||
MOVL DX, BX
|
||||
|
||||
MOVL DX, BX
|
||||
chacha_loop:
|
||||
CHACHA_QROUND_SSSE3(X4, X5, X6, X7, X0, X1, X2)
|
||||
CHACHA_SHUFFLE(X5, X6, X7)
|
||||
CHACHA_QROUND_SSSE3(X4, X5, X6, X7, X0, X1, X2)
|
||||
CHACHA_SHUFFLE(X7, X6, X5)
|
||||
SUBL $2, BX
|
||||
JA chacha_loop
|
||||
CHACHA_QROUND_SSSE3(X4, X5, X6, X7, X0, X1, X2)
|
||||
CHACHA_SHUFFLE(X5, X6, X7)
|
||||
CHACHA_QROUND_SSSE3(X4, X5, X6, X7, X0, X1, X2)
|
||||
CHACHA_SHUFFLE(X7, X6, X5)
|
||||
SUBL $2, BX
|
||||
JA chacha_loop
|
||||
|
||||
MOVOU 0(AX), X0
|
||||
PADDL X0, X4
|
||||
PADDL 16(SP), X5
|
||||
PADDL 32(SP), X6
|
||||
PADDL X3, X7
|
||||
PADDQ 0(SP), X3
|
||||
MOVOU 0(AX), X0
|
||||
PADDL X0, X4
|
||||
PADDL 16(SP), X5
|
||||
PADDL 32(SP), X6
|
||||
PADDL X3, X7
|
||||
PADDQ 0(SP), X3
|
||||
|
||||
CMPL CX, $64
|
||||
JB less_than_64
|
||||
CMPL CX, $64
|
||||
JB less_than_64
|
||||
|
||||
XOR(DI, SI, 0, X4, X5, X6, X7, X0)
|
||||
MOVOU 0(AX), X0
|
||||
ADDL $64, SI
|
||||
ADDL $64, DI
|
||||
SUBL $64, CX
|
||||
JNZ at_least_64
|
||||
XOR(DI, SI, 0, X4, X5, X6, X7, X0)
|
||||
MOVOU 0(AX), X0
|
||||
ADDL $64, SI
|
||||
ADDL $64, DI
|
||||
SUBL $64, CX
|
||||
JNZ at_least_64
|
||||
|
||||
less_than_64:
|
||||
MOVL BP, SP
|
||||
MOVL CX, BP
|
||||
TESTL BP, BP
|
||||
JE done
|
||||
MOVL BP, SP
|
||||
MOVL CX, BP
|
||||
TESTL BP, BP
|
||||
JE done
|
||||
|
||||
MOVL block+24(FP), BX
|
||||
MOVOU X4, 0(BX)
|
||||
MOVOU X5, 16(BX)
|
||||
MOVOU X6, 32(BX)
|
||||
MOVOU X7, 48(BX)
|
||||
FINALIZE(DI, SI, BX, BP, AX, DX)
|
||||
MOVL block+24(FP), BX
|
||||
MOVOU X4, 0(BX)
|
||||
MOVOU X5, 16(BX)
|
||||
MOVOU X6, 32(BX)
|
||||
MOVOU X7, 48(BX)
|
||||
FINALIZE(DI, SI, BX, BP, AX, DX)
|
||||
|
||||
done:
|
||||
MOVL state+28(FP), AX
|
||||
MOVOU X3, 48(AX)
|
||||
MOVL CX, ret+36(FP)
|
||||
RET
|
||||
MOVL state+28(FP), AX
|
||||
MOVOU X3, 48(AX)
|
||||
MOVL CX, ret+36(FP)
|
||||
RET
|
||||
|
||||
// func supportsSSE2() bool
|
||||
TEXT ·supportsSSE2(SB), NOSPLIT, $0-1
|
||||
XORL AX, AX
|
||||
INCL AX
|
||||
CPUID
|
||||
SHRL $26, DX
|
||||
INCL AX
|
||||
CPUID
|
||||
SHRL $26, DX
|
||||
ANDL $1, DX
|
||||
MOVB DX, ret+0(FP)
|
||||
MOVB DX, ret+0(FP)
|
||||
RET
|
||||
|
||||
// func supportsSSSE3() bool
|
||||
TEXT ·supportsSSSE3(SB), NOSPLIT, $0-1
|
||||
XORL AX, AX
|
||||
INCL AX
|
||||
INCL AX
|
||||
CPUID
|
||||
SHRL $9, CX
|
||||
ANDL $1, CX
|
||||
|
@ -258,50 +260,52 @@ TEXT ·supportsSSSE3(SB), NOSPLIT, $0-1
|
|||
|
||||
// func hChaCha20SSE2(out *[32]byte, nonce *[16]byte, key *[32]byte)
|
||||
TEXT ·hChaCha20SSE2(SB), 4, $0-12
|
||||
MOVL out+0(FP), DI
|
||||
MOVL nonce+4(FP), AX
|
||||
MOVL key+8(FP), BX
|
||||
MOVL out+0(FP), DI
|
||||
MOVL nonce+4(FP), AX
|
||||
MOVL key+8(FP), BX
|
||||
|
||||
MOVOU ·sigma<>(SB), X0
|
||||
MOVOU 0(BX), X1
|
||||
MOVOU 16(BX), X2
|
||||
MOVOU 0(AX), X3
|
||||
MOVOU ·sigma<>(SB), X0
|
||||
MOVOU 0(BX), X1
|
||||
MOVOU 16(BX), X2
|
||||
MOVOU 0(AX), X3
|
||||
|
||||
MOVL $20, CX
|
||||
|
||||
MOVL $20, CX
|
||||
chacha_loop:
|
||||
CHACHA_QROUND_SSE2(X0, X1, X2, X3, X4)
|
||||
CHACHA_SHUFFLE(X1, X2, X3)
|
||||
CHACHA_QROUND_SSE2(X0, X1, X2, X3, X4)
|
||||
CHACHA_SHUFFLE(X3, X2, X1)
|
||||
SUBL $2, CX
|
||||
JNZ chacha_loop
|
||||
CHACHA_QROUND_SSE2(X0, X1, X2, X3, X4)
|
||||
CHACHA_SHUFFLE(X1, X2, X3)
|
||||
CHACHA_QROUND_SSE2(X0, X1, X2, X3, X4)
|
||||
CHACHA_SHUFFLE(X3, X2, X1)
|
||||
SUBL $2, CX
|
||||
JNZ chacha_loop
|
||||
|
||||
MOVOU X0, 0(DI)
|
||||
MOVOU X3, 16(DI)
|
||||
RET
|
||||
MOVOU X0, 0(DI)
|
||||
MOVOU X3, 16(DI)
|
||||
RET
|
||||
|
||||
// func hChaCha20SSSE3(out *[32]byte, nonce *[16]byte, key *[32]byte)
|
||||
TEXT ·hChaCha20SSSE3(SB), 4, $0-12
|
||||
MOVL out+0(FP), DI
|
||||
MOVL nonce+4(FP), AX
|
||||
MOVL key+8(FP), BX
|
||||
MOVL out+0(FP), DI
|
||||
MOVL nonce+4(FP), AX
|
||||
MOVL key+8(FP), BX
|
||||
|
||||
MOVOU ·sigma<>(SB), X0
|
||||
MOVOU 0(BX), X1
|
||||
MOVOU 16(BX), X2
|
||||
MOVOU 0(AX), X3
|
||||
MOVOU ·rol16<>(SB), X5
|
||||
MOVOU ·rol8<>(SB), X6
|
||||
MOVOU ·sigma<>(SB), X0
|
||||
MOVOU 0(BX), X1
|
||||
MOVOU 16(BX), X2
|
||||
MOVOU 0(AX), X3
|
||||
MOVOU ·rol16<>(SB), X5
|
||||
MOVOU ·rol8<>(SB), X6
|
||||
|
||||
MOVL $20, CX
|
||||
|
||||
MOVL $20, CX
|
||||
chacha_loop:
|
||||
CHACHA_QROUND_SSSE3(X0, X1, X2, X3, X4, X5, X6)
|
||||
CHACHA_SHUFFLE(X1, X2, X3)
|
||||
CHACHA_QROUND_SSSE3(X0, X1, X2, X3, X4, X5, X6)
|
||||
CHACHA_SHUFFLE(X3, X2, X1)
|
||||
SUBL $2, CX
|
||||
JNZ chacha_loop
|
||||
CHACHA_QROUND_SSSE3(X0, X1, X2, X3, X4, X5, X6)
|
||||
CHACHA_SHUFFLE(X1, X2, X3)
|
||||
CHACHA_QROUND_SSSE3(X0, X1, X2, X3, X4, X5, X6)
|
||||
CHACHA_SHUFFLE(X3, X2, X1)
|
||||
SUBL $2, CX
|
||||
JNZ chacha_loop
|
||||
|
||||
MOVOU X0, 0(DI)
|
||||
MOVOU X3, 16(DI)
|
||||
RET
|
||||
MOVOU X0, 0(DI)
|
||||
MOVOU X3, 16(DI)
|
||||
RET
|
||||
|
|
1240
vendor/github.com/aead/chacha20/chacha/chacha_amd64.s
generated
vendored
1240
vendor/github.com/aead/chacha20/chacha/chacha_amd64.s
generated
vendored
File diff suppressed because it is too large
Load diff
4
vendor/github.com/golang/protobuf/proto/encode.go
generated
vendored
4
vendor/github.com/golang/protobuf/proto/encode.go
generated
vendored
|
@ -174,11 +174,11 @@ func sizeFixed32(x uint64) int {
|
|||
// This is the format used for the sint64 protocol buffer type.
|
||||
func (p *Buffer) EncodeZigzag64(x uint64) error {
|
||||
// use signed number to get arithmetic right shift.
|
||||
return p.EncodeVarint(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||
return p.EncodeVarint((x << 1) ^ uint64((int64(x) >> 63)))
|
||||
}
|
||||
|
||||
func sizeZigzag64(x uint64) int {
|
||||
return sizeVarint(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||
return sizeVarint((x << 1) ^ uint64((int64(x) >> 63)))
|
||||
}
|
||||
|
||||
// EncodeZigzag32 writes a zigzag-encoded 32-bit integer
|
||||
|
|
2
vendor/github.com/golang/protobuf/proto/text_parser.go
generated
vendored
2
vendor/github.com/golang/protobuf/proto/text_parser.go
generated
vendored
|
@ -865,7 +865,7 @@ func (p *textParser) readAny(v reflect.Value, props *Properties) error {
|
|||
return p.readStruct(fv, terminator)
|
||||
case reflect.Uint32:
|
||||
if x, err := strconv.ParseUint(tok.value, 0, 32); err == nil {
|
||||
fv.SetUint(uint64(x))
|
||||
fv.SetUint(x)
|
||||
return nil
|
||||
}
|
||||
case reflect.Uint64:
|
||||
|
|
13
vendor/github.com/gorilla/websocket/doc.go
generated
vendored
13
vendor/github.com/gorilla/websocket/doc.go
generated
vendored
|
@ -6,9 +6,8 @@
|
|||
//
|
||||
// Overview
|
||||
//
|
||||
// The Conn type represents a WebSocket connection. A server application uses
|
||||
// the Upgrade function from an Upgrader object with a HTTP request handler
|
||||
// to get a pointer to a Conn:
|
||||
// The Conn type represents a WebSocket connection. A server application calls
|
||||
// the Upgrader.Upgrade method from an HTTP request handler to get a *Conn:
|
||||
//
|
||||
// var upgrader = websocket.Upgrader{
|
||||
// ReadBufferSize: 1024,
|
||||
|
@ -33,7 +32,7 @@
|
|||
// if err != nil {
|
||||
// return
|
||||
// }
|
||||
// if err = conn.WriteMessage(messageType, p); err != nil {
|
||||
// if err := conn.WriteMessage(messageType, p); err != nil {
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
|
@ -147,9 +146,9 @@
|
|||
// CheckOrigin: func(r *http.Request) bool { return true },
|
||||
// }
|
||||
//
|
||||
// The deprecated Upgrade function does not enforce an origin policy. It's the
|
||||
// application's responsibility to check the Origin header before calling
|
||||
// Upgrade.
|
||||
// The deprecated package-level Upgrade function does not perform origin
|
||||
// checking. The application is responsible for checking the Origin header
|
||||
// before calling the Upgrade function.
|
||||
//
|
||||
// Compression EXPERIMENTAL
|
||||
//
|
||||
|
|
5
vendor/github.com/gorilla/websocket/examples/chat/client.go
generated
vendored
5
vendor/github.com/gorilla/websocket/examples/chat/client.go
generated
vendored
|
@ -129,6 +129,9 @@ func serveWs(hub *Hub, w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
client := &Client{hub: hub, conn: conn, send: make(chan []byte, 256)}
|
||||
client.hub.register <- client
|
||||
|
||||
// Allow collection of memory referenced by the caller by doing all work in
|
||||
// new goroutines.
|
||||
go client.writePump()
|
||||
client.readPump()
|
||||
go client.readPump()
|
||||
}
|
||||
|
|
11
vendor/github.com/gorilla/websocket/json.go
generated
vendored
11
vendor/github.com/gorilla/websocket/json.go
generated
vendored
|
@ -9,12 +9,14 @@ import (
|
|||
"io"
|
||||
)
|
||||
|
||||
// WriteJSON is deprecated, use c.WriteJSON instead.
|
||||
// WriteJSON writes the JSON encoding of v as a message.
|
||||
//
|
||||
// Deprecated: Use c.WriteJSON instead.
|
||||
func WriteJSON(c *Conn, v interface{}) error {
|
||||
return c.WriteJSON(v)
|
||||
}
|
||||
|
||||
// WriteJSON writes the JSON encoding of v to the connection.
|
||||
// WriteJSON writes the JSON encoding of v as a message.
|
||||
//
|
||||
// See the documentation for encoding/json Marshal for details about the
|
||||
// conversion of Go values to JSON.
|
||||
|
@ -31,7 +33,10 @@ func (c *Conn) WriteJSON(v interface{}) error {
|
|||
return err2
|
||||
}
|
||||
|
||||
// ReadJSON is deprecated, use c.ReadJSON instead.
|
||||
// ReadJSON reads the next JSON-encoded message from the connection and stores
|
||||
// it in the value pointed to by v.
|
||||
//
|
||||
// Deprecated: Use c.ReadJSON instead.
|
||||
func ReadJSON(c *Conn, v interface{}) error {
|
||||
return c.ReadJSON(v)
|
||||
}
|
||||
|
|
7
vendor/github.com/gorilla/websocket/server.go
generated
vendored
7
vendor/github.com/gorilla/websocket/server.go
generated
vendored
|
@ -230,10 +230,11 @@ func (u *Upgrader) Upgrade(w http.ResponseWriter, r *http.Request, responseHeade
|
|||
|
||||
// Upgrade upgrades the HTTP server connection to the WebSocket protocol.
|
||||
//
|
||||
// This function is deprecated, use websocket.Upgrader instead.
|
||||
// Deprecated: Use websocket.Upgrader instead.
|
||||
//
|
||||
// The application is responsible for checking the request origin before
|
||||
// calling Upgrade. An example implementation of the same origin policy is:
|
||||
// Upgrade does not perform origin checking. The application is responsible for
|
||||
// checking the Origin header before calling Upgrade. An example implementation
|
||||
// of the same origin policy check is:
|
||||
//
|
||||
// if req.Header.Get("Origin") != "http://"+req.Host {
|
||||
// http.Error(w, "Origin not allowed", 403)
|
||||
|
|
4
vendor/github.com/gorilla/websocket/util.go
generated
vendored
4
vendor/github.com/gorilla/websocket/util.go
generated
vendored
|
@ -111,14 +111,14 @@ func nextTokenOrQuoted(s string) (value string, rest string) {
|
|||
case escape:
|
||||
escape = false
|
||||
p[j] = b
|
||||
j += 1
|
||||
j++
|
||||
case b == '\\':
|
||||
escape = true
|
||||
case b == '"':
|
||||
return string(p[:j]), s[i+1:]
|
||||
default:
|
||||
p[j] = b
|
||||
j += 1
|
||||
j++
|
||||
}
|
||||
}
|
||||
return "", ""
|
||||
|
|
2
vendor/github.com/lucas-clemente/quic-go/ackhandler/interfaces.go
generated
vendored
2
vendor/github.com/lucas-clemente/quic-go/ackhandler/interfaces.go
generated
vendored
|
@ -9,6 +9,7 @@ import (
|
|||
|
||||
// SentPacketHandler handles ACKs received for outgoing packets
|
||||
type SentPacketHandler interface {
|
||||
// SentPacket may modify the packet
|
||||
SentPacket(packet *Packet) error
|
||||
ReceivedAck(ackFrame *frames.AckFrame, withPacketNumber protocol.PacketNumber, recvTime time.Time) error
|
||||
|
||||
|
@ -26,5 +27,6 @@ type ReceivedPacketHandler interface {
|
|||
ReceivedPacket(packetNumber protocol.PacketNumber, shouldInstigateAck bool) error
|
||||
ReceivedStopWaiting(*frames.StopWaitingFrame) error
|
||||
|
||||
GetAlarmTimeout() time.Time
|
||||
GetAckFrame() *frames.AckFrame
|
||||
}
|
||||
|
|
45
vendor/github.com/lucas-clemente/quic-go/ackhandler/received_packet_handler.go
generated
vendored
45
vendor/github.com/lucas-clemente/quic-go/ackhandler/received_packet_handler.go
generated
vendored
|
@ -8,13 +8,6 @@ import (
|
|||
"github.com/lucas-clemente/quic-go/protocol"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrDuplicatePacket occurres when a duplicate packet is received
|
||||
ErrDuplicatePacket = errors.New("ReceivedPacketHandler: Duplicate Packet")
|
||||
// ErrPacketSmallerThanLastStopWaiting occurs when a packet arrives with a packet number smaller than the largest LeastUnacked of a StopWaitingFrame. If this error occurs, the packet should be ignored
|
||||
ErrPacketSmallerThanLastStopWaiting = errors.New("ReceivedPacketHandler: Packet number smaller than highest StopWaiting")
|
||||
)
|
||||
|
||||
var errInvalidPacketNumber = errors.New("ReceivedPacketHandler: Invalid packet number")
|
||||
|
||||
type receivedPacketHandler struct {
|
||||
|
@ -30,20 +23,14 @@ type receivedPacketHandler struct {
|
|||
retransmittablePacketsReceivedSinceLastAck int
|
||||
ackQueued bool
|
||||
ackAlarm time.Time
|
||||
ackAlarmResetCallback func(time.Time)
|
||||
lastAck *frames.AckFrame
|
||||
}
|
||||
|
||||
// NewReceivedPacketHandler creates a new receivedPacketHandler
|
||||
func NewReceivedPacketHandler(ackAlarmResetCallback func(time.Time)) ReceivedPacketHandler {
|
||||
// create a stopped timer, see https://github.com/golang/go/issues/12721#issuecomment-143010182
|
||||
timer := time.NewTimer(0)
|
||||
<-timer.C
|
||||
|
||||
func NewReceivedPacketHandler() ReceivedPacketHandler {
|
||||
return &receivedPacketHandler{
|
||||
packetHistory: newReceivedPacketHistory(),
|
||||
ackAlarmResetCallback: ackAlarmResetCallback,
|
||||
ackSendDelay: protocol.AckSendDelay,
|
||||
packetHistory: newReceivedPacketHistory(),
|
||||
ackSendDelay: protocol.AckSendDelay,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,19 +39,10 @@ func (h *receivedPacketHandler) ReceivedPacket(packetNumber protocol.PacketNumbe
|
|||
return errInvalidPacketNumber
|
||||
}
|
||||
|
||||
// if the packet number is smaller than the largest LeastUnacked value of a StopWaiting we received, we cannot detect if this packet has a duplicate number
|
||||
// the packet has to be ignored anyway
|
||||
if packetNumber <= h.ignorePacketsBelow {
|
||||
return ErrPacketSmallerThanLastStopWaiting
|
||||
}
|
||||
|
||||
if h.packetHistory.IsDuplicate(packetNumber) {
|
||||
return ErrDuplicatePacket
|
||||
}
|
||||
|
||||
err := h.packetHistory.ReceivedPacket(packetNumber)
|
||||
if err != nil {
|
||||
return err
|
||||
if packetNumber > h.ignorePacketsBelow {
|
||||
if err := h.packetHistory.ReceivedPacket(packetNumber); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if packetNumber > h.largestObserved {
|
||||
|
@ -89,7 +67,6 @@ func (h *receivedPacketHandler) ReceivedStopWaiting(f *frames.StopWaitingFrame)
|
|||
}
|
||||
|
||||
func (h *receivedPacketHandler) maybeQueueAck(packetNumber protocol.PacketNumber, shouldInstigateAck bool) {
|
||||
var ackAlarmSet bool
|
||||
h.packetsReceivedSinceLastAck++
|
||||
|
||||
if shouldInstigateAck {
|
||||
|
@ -124,7 +101,6 @@ func (h *receivedPacketHandler) maybeQueueAck(packetNumber protocol.PacketNumber
|
|||
} else {
|
||||
if h.ackAlarm.IsZero() {
|
||||
h.ackAlarm = time.Now().Add(h.ackSendDelay)
|
||||
ackAlarmSet = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -132,11 +108,6 @@ func (h *receivedPacketHandler) maybeQueueAck(packetNumber protocol.PacketNumber
|
|||
if h.ackQueued {
|
||||
// cancel the ack alarm
|
||||
h.ackAlarm = time.Time{}
|
||||
ackAlarmSet = false
|
||||
}
|
||||
|
||||
if ackAlarmSet {
|
||||
h.ackAlarmResetCallback(h.ackAlarm)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -164,3 +135,5 @@ func (h *receivedPacketHandler) GetAckFrame() *frames.AckFrame {
|
|||
|
||||
return ack
|
||||
}
|
||||
|
||||
func (h *receivedPacketHandler) GetAlarmTimeout() time.Time { return h.ackAlarm }
|
||||
|
|
2
vendor/github.com/lucas-clemente/quic-go/ackhandler/received_packet_history.go
generated
vendored
2
vendor/github.com/lucas-clemente/quic-go/ackhandler/received_packet_history.go
generated
vendored
|
@ -2,9 +2,9 @@ package ackhandler
|
|||
|
||||
import (
|
||||
"github.com/lucas-clemente/quic-go/frames"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/protocol"
|
||||
"github.com/lucas-clemente/quic-go/qerr"
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
)
|
||||
|
||||
type receivedPacketHistory struct {
|
||||
|
|
38
vendor/github.com/lucas-clemente/quic-go/ackhandler/retransmittable.go
generated
vendored
Normal file
38
vendor/github.com/lucas-clemente/quic-go/ackhandler/retransmittable.go
generated
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
package ackhandler
|
||||
|
||||
import (
|
||||
"github.com/lucas-clemente/quic-go/frames"
|
||||
)
|
||||
|
||||
// Returns a new slice with all non-retransmittable frames deleted.
|
||||
func stripNonRetransmittableFrames(fs []frames.Frame) []frames.Frame {
|
||||
res := make([]frames.Frame, 0, len(fs))
|
||||
for _, f := range fs {
|
||||
if IsFrameRetransmittable(f) {
|
||||
res = append(res, f)
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// IsFrameRetransmittable returns true if the frame should be retransmitted.
|
||||
func IsFrameRetransmittable(f frames.Frame) bool {
|
||||
switch f.(type) {
|
||||
case *frames.StopWaitingFrame:
|
||||
return false
|
||||
case *frames.AckFrame:
|
||||
return false
|
||||
default:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// HasRetransmittableFrames returns true if at least one frame is retransmittable.
|
||||
func HasRetransmittableFrames(fs []frames.Frame) bool {
|
||||
for _, f := range fs {
|
||||
if IsFrameRetransmittable(f) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
38
vendor/github.com/lucas-clemente/quic-go/ackhandler/sent_packet_handler.go
generated
vendored
38
vendor/github.com/lucas-clemente/quic-go/ackhandler/sent_packet_handler.go
generated
vendored
|
@ -7,9 +7,9 @@ import (
|
|||
|
||||
"github.com/lucas-clemente/quic-go/congestion"
|
||||
"github.com/lucas-clemente/quic-go/frames"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/protocol"
|
||||
"github.com/lucas-clemente/quic-go/qerr"
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -106,26 +106,27 @@ func (h *sentPacketHandler) SentPacket(packet *Packet) error {
|
|||
}
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
packet.SendTime = now
|
||||
if packet.Length == 0 {
|
||||
return errors.New("SentPacketHandler: packet cannot be empty")
|
||||
}
|
||||
h.bytesInFlight += packet.Length
|
||||
|
||||
h.lastSentPacketNumber = packet.PacketNumber
|
||||
h.packetHistory.PushBack(*packet)
|
||||
now := time.Now()
|
||||
|
||||
packet.Frames = stripNonRetransmittableFrames(packet.Frames)
|
||||
isRetransmittable := len(packet.Frames) != 0
|
||||
|
||||
if isRetransmittable {
|
||||
packet.SendTime = now
|
||||
h.bytesInFlight += packet.Length
|
||||
h.packetHistory.PushBack(*packet)
|
||||
}
|
||||
|
||||
h.congestion.OnPacketSent(
|
||||
now,
|
||||
h.bytesInFlight,
|
||||
packet.PacketNumber,
|
||||
packet.Length,
|
||||
true, /* TODO: is retransmittable */
|
||||
isRetransmittable,
|
||||
)
|
||||
|
||||
h.updateLossDetectionAlarm()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -310,10 +311,11 @@ func (h *sentPacketHandler) DequeuePacketForRetransmission() *Packet {
|
|||
if len(h.retransmissionQueue) == 0 {
|
||||
return nil
|
||||
}
|
||||
queueLen := len(h.retransmissionQueue)
|
||||
// packets are usually NACKed in descending order. So use the slice as a stack
|
||||
packet := h.retransmissionQueue[queueLen-1]
|
||||
h.retransmissionQueue = h.retransmissionQueue[:queueLen-1]
|
||||
packet := h.retransmissionQueue[0]
|
||||
// Shift the slice and don't retain anything that isn't needed.
|
||||
copy(h.retransmissionQueue, h.retransmissionQueue[1:])
|
||||
h.retransmissionQueue[len(h.retransmissionQueue)-1] = nil
|
||||
h.retransmissionQueue = h.retransmissionQueue[:len(h.retransmissionQueue)-1]
|
||||
return packet
|
||||
}
|
||||
|
||||
|
@ -333,7 +335,11 @@ func (h *sentPacketHandler) SendingAllowed() bool {
|
|||
h.bytesInFlight,
|
||||
h.congestion.GetCongestionWindow())
|
||||
}
|
||||
return !(congestionLimited || maxTrackedLimited)
|
||||
// Workaround for #555:
|
||||
// Always allow sending of retransmissions. This should probably be limited
|
||||
// to RTOs, but we currently don't have a nice way of distinguishing them.
|
||||
haveRetransmissions := len(h.retransmissionQueue) > 0
|
||||
return !maxTrackedLimited && (!congestionLimited || haveRetransmissions)
|
||||
}
|
||||
|
||||
func (h *sentPacketHandler) retransmitOldestTwoPackets() {
|
||||
|
|
118
vendor/github.com/lucas-clemente/quic-go/client.go
generated
vendored
118
vendor/github.com/lucas-clemente/quic-go/client.go
generated
vendored
|
@ -2,6 +2,7 @@ package quic
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
|
@ -9,9 +10,9 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/protocol"
|
||||
"github.com/lucas-clemente/quic-go/qerr"
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
)
|
||||
|
||||
type client struct {
|
||||
|
@ -24,6 +25,7 @@ type client struct {
|
|||
errorChan chan struct{}
|
||||
handshakeChan <-chan handshakeEvent
|
||||
|
||||
tlsConf *tls.Config
|
||||
config *Config
|
||||
versionNegotiated bool // has version negotiation completed yet
|
||||
|
||||
|
@ -39,7 +41,7 @@ var (
|
|||
|
||||
// DialAddr establishes a new QUIC connection to a server.
|
||||
// The hostname for SNI is taken from the given address.
|
||||
func DialAddr(addr string, config *Config) (Session, error) {
|
||||
func DialAddr(addr string, tlsConf *tls.Config, config *Config) (Session, error) {
|
||||
udpAddr, err := net.ResolveUDPAddr("udp", addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -48,12 +50,16 @@ func DialAddr(addr string, config *Config) (Session, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return Dial(udpConn, udpAddr, addr, config)
|
||||
return Dial(udpConn, udpAddr, addr, tlsConf, config)
|
||||
}
|
||||
|
||||
// DialAddrNonFWSecure establishes a new QUIC connection to a server.
|
||||
// The hostname for SNI is taken from the given address.
|
||||
func DialAddrNonFWSecure(addr string, config *Config) (NonFWSession, error) {
|
||||
func DialAddrNonFWSecure(
|
||||
addr string,
|
||||
tlsConf *tls.Config,
|
||||
config *Config,
|
||||
) (NonFWSession, error) {
|
||||
udpAddr, err := net.ResolveUDPAddr("udp", addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -62,20 +68,33 @@ func DialAddrNonFWSecure(addr string, config *Config) (NonFWSession, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return DialNonFWSecure(udpConn, udpAddr, addr, config)
|
||||
return DialNonFWSecure(udpConn, udpAddr, addr, tlsConf, config)
|
||||
}
|
||||
|
||||
// DialNonFWSecure establishes a new non-forward-secure QUIC connection to a server using a net.PacketConn.
|
||||
// The host parameter is used for SNI.
|
||||
func DialNonFWSecure(pconn net.PacketConn, remoteAddr net.Addr, host string, config *Config) (NonFWSession, error) {
|
||||
func DialNonFWSecure(
|
||||
pconn net.PacketConn,
|
||||
remoteAddr net.Addr,
|
||||
host string,
|
||||
tlsConf *tls.Config,
|
||||
config *Config,
|
||||
) (NonFWSession, error) {
|
||||
connID, err := utils.GenerateConnectionID()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
hostname, _, err := net.SplitHostPort(host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
var hostname string
|
||||
if tlsConf != nil {
|
||||
hostname = tlsConf.ServerName
|
||||
}
|
||||
|
||||
if hostname == "" {
|
||||
hostname, _, err = net.SplitHostPort(host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
clientConfig := populateClientConfig(config)
|
||||
|
@ -83,6 +102,7 @@ func DialNonFWSecure(pconn net.PacketConn, remoteAddr net.Addr, host string, con
|
|||
conn: &conn{pconn: pconn, currentAddr: remoteAddr},
|
||||
connectionID: connID,
|
||||
hostname: hostname,
|
||||
tlsConf: tlsConf,
|
||||
config: clientConfig,
|
||||
version: clientConfig.Versions[0],
|
||||
errorChan: make(chan struct{}),
|
||||
|
@ -93,15 +113,21 @@ func DialNonFWSecure(pconn net.PacketConn, remoteAddr net.Addr, host string, con
|
|||
return nil, err
|
||||
}
|
||||
|
||||
utils.Infof("Starting new connection to %s (%s), connectionID %x, version %d", hostname, c.conn.RemoteAddr().String(), c.connectionID, c.version)
|
||||
utils.Infof("Starting new connection to %s (%s -> %s), connectionID %x, version %d", hostname, c.conn.LocalAddr().String(), c.conn.RemoteAddr().String(), c.connectionID, c.version)
|
||||
|
||||
return c.session.(NonFWSession), c.establishSecureConnection()
|
||||
}
|
||||
|
||||
// Dial establishes a new QUIC connection to a server using a net.PacketConn.
|
||||
// The host parameter is used for SNI.
|
||||
func Dial(pconn net.PacketConn, remoteAddr net.Addr, host string, config *Config) (Session, error) {
|
||||
sess, err := DialNonFWSecure(pconn, remoteAddr, host, config)
|
||||
func Dial(
|
||||
pconn net.PacketConn,
|
||||
remoteAddr net.Addr,
|
||||
host string,
|
||||
tlsConf *tls.Config,
|
||||
config *Config,
|
||||
) (Session, error) {
|
||||
sess, err := DialNonFWSecure(pconn, remoteAddr, host, tlsConf, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -112,16 +138,38 @@ func Dial(pconn net.PacketConn, remoteAddr net.Addr, host string, config *Config
|
|||
return sess, nil
|
||||
}
|
||||
|
||||
// populateClientConfig populates fields in the quic.Config with their default values, if none are set
|
||||
// it may be called with nil
|
||||
func populateClientConfig(config *Config) *Config {
|
||||
if config == nil {
|
||||
config = &Config{}
|
||||
}
|
||||
versions := config.Versions
|
||||
if len(versions) == 0 {
|
||||
versions = protocol.SupportedVersions
|
||||
}
|
||||
|
||||
handshakeTimeout := protocol.DefaultHandshakeTimeout
|
||||
if config.HandshakeTimeout != 0 {
|
||||
handshakeTimeout = config.HandshakeTimeout
|
||||
}
|
||||
|
||||
maxReceiveStreamFlowControlWindow := config.MaxReceiveStreamFlowControlWindow
|
||||
if maxReceiveStreamFlowControlWindow == 0 {
|
||||
maxReceiveStreamFlowControlWindow = protocol.DefaultMaxReceiveStreamFlowControlWindowClient
|
||||
}
|
||||
maxReceiveConnectionFlowControlWindow := config.MaxReceiveConnectionFlowControlWindow
|
||||
if maxReceiveConnectionFlowControlWindow == 0 {
|
||||
maxReceiveConnectionFlowControlWindow = protocol.DefaultMaxReceiveConnectionFlowControlWindowClient
|
||||
}
|
||||
|
||||
return &Config{
|
||||
TLSConfig: config.TLSConfig,
|
||||
Versions: versions,
|
||||
RequestConnectionIDTruncation: config.RequestConnectionIDTruncation,
|
||||
Versions: versions,
|
||||
HandshakeTimeout: handshakeTimeout,
|
||||
RequestConnectionIDTruncation: config.RequestConnectionIDTruncation,
|
||||
MaxReceiveStreamFlowControlWindow: maxReceiveStreamFlowControlWindow,
|
||||
MaxReceiveConnectionFlowControlWindow: maxReceiveConnectionFlowControlWindow,
|
||||
KeepAlive: config.KeepAlive,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -163,31 +211,46 @@ func (c *client) listen() {
|
|||
}
|
||||
data = data[:n]
|
||||
|
||||
err = c.handlePacket(addr, data)
|
||||
if err != nil {
|
||||
utils.Errorf("error handling packet: %s", err.Error())
|
||||
c.session.Close(err)
|
||||
break
|
||||
}
|
||||
c.handlePacket(addr, data)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *client) handlePacket(remoteAddr net.Addr, packet []byte) error {
|
||||
func (c *client) handlePacket(remoteAddr net.Addr, packet []byte) {
|
||||
rcvTime := time.Now()
|
||||
|
||||
r := bytes.NewReader(packet)
|
||||
hdr, err := ParsePublicHeader(r, protocol.PerspectiveServer)
|
||||
if err != nil {
|
||||
return qerr.Error(qerr.InvalidPacketHeader, err.Error())
|
||||
utils.Errorf("error parsing packet from %s: %s", remoteAddr.String(), err.Error())
|
||||
// drop this packet if we can't parse the Public Header
|
||||
return
|
||||
}
|
||||
hdr.Raw = packet[:len(packet)-r.Len()]
|
||||
|
||||
c.mutex.Lock()
|
||||
defer c.mutex.Unlock()
|
||||
|
||||
if hdr.ResetFlag {
|
||||
cr := c.conn.RemoteAddr()
|
||||
// check if the remote address and the connection ID match
|
||||
// otherwise this might be an attacker trying to inject a PUBLIC_RESET to kill the connection
|
||||
if cr.Network() != remoteAddr.Network() || cr.String() != remoteAddr.String() || hdr.ConnectionID != c.connectionID {
|
||||
utils.Infof("Received a spoofed Public Reset. Ignoring.")
|
||||
return
|
||||
}
|
||||
pr, err := parsePublicReset(r)
|
||||
if err != nil {
|
||||
utils.Infof("Received a Public Reset for connection %x. An error occurred parsing the packet.")
|
||||
return
|
||||
}
|
||||
utils.Infof("Received Public Reset, rejected packet number: %#x.", pr.rejectedPacketNumber)
|
||||
c.session.closeRemote(qerr.Error(qerr.PublicReset, fmt.Sprintf("Received a Public Reset for packet number %#x", pr.rejectedPacketNumber)))
|
||||
return
|
||||
}
|
||||
|
||||
// ignore delayed / duplicated version negotiation packets
|
||||
if c.versionNegotiated && hdr.VersionFlag {
|
||||
return nil
|
||||
return
|
||||
}
|
||||
|
||||
// this is the first packet after the client sent a packet with the VersionFlag set
|
||||
|
@ -198,7 +261,10 @@ func (c *client) handlePacket(remoteAddr net.Addr, packet []byte) error {
|
|||
|
||||
if hdr.VersionFlag {
|
||||
// version negotiation packets have no payload
|
||||
return c.handlePacketWithVersionFlag(hdr)
|
||||
if err := c.handlePacketWithVersionFlag(hdr); err != nil {
|
||||
c.session.Close(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
c.session.handlePacket(&receivedPacket{
|
||||
|
@ -207,7 +273,6 @@ func (c *client) handlePacket(remoteAddr net.Addr, packet []byte) error {
|
|||
data: packet[len(packet)-r.Len():],
|
||||
rcvTime: rcvTime,
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *client) handlePacketWithVersionFlag(hdr *PublicHeader) error {
|
||||
|
@ -246,6 +311,7 @@ func (c *client) createNewSession(negotiatedVersions []protocol.VersionNumber) e
|
|||
c.hostname,
|
||||
c.version,
|
||||
c.connectionID,
|
||||
c.tlsConf,
|
||||
c.config,
|
||||
negotiatedVersions,
|
||||
)
|
||||
|
|
2
vendor/github.com/lucas-clemente/quic-go/congestion/cubic.go
generated
vendored
2
vendor/github.com/lucas-clemente/quic-go/congestion/cubic.go
generated
vendored
|
@ -4,8 +4,8 @@ import (
|
|||
"math"
|
||||
"time"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/protocol"
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
)
|
||||
|
||||
// This cubic implementation is based on the one found in Chromiums's QUIC
|
||||
|
|
2
vendor/github.com/lucas-clemente/quic-go/congestion/cubic_sender.go
generated
vendored
2
vendor/github.com/lucas-clemente/quic-go/congestion/cubic_sender.go
generated
vendored
|
@ -3,8 +3,8 @@ package congestion
|
|||
import (
|
||||
"time"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/protocol"
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
2
vendor/github.com/lucas-clemente/quic-go/congestion/hybrid_slow_start.go
generated
vendored
2
vendor/github.com/lucas-clemente/quic-go/congestion/hybrid_slow_start.go
generated
vendored
|
@ -3,8 +3,8 @@ package congestion
|
|||
import (
|
||||
"time"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/protocol"
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
)
|
||||
|
||||
// Note(pwestin): the magic clamping numbers come from the original code in
|
||||
|
|
2
vendor/github.com/lucas-clemente/quic-go/congestion/prr_sender.go
generated
vendored
2
vendor/github.com/lucas-clemente/quic-go/congestion/prr_sender.go
generated
vendored
|
@ -3,8 +3,8 @@ package congestion
|
|||
import (
|
||||
"time"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/protocol"
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
)
|
||||
|
||||
// PrrSender implements the Proportional Rate Reduction (PRR) per RFC 6937
|
||||
|
|
2
vendor/github.com/lucas-clemente/quic-go/congestion/rtt_stats.go
generated
vendored
2
vendor/github.com/lucas-clemente/quic-go/congestion/rtt_stats.go
generated
vendored
|
@ -3,7 +3,7 @@ package congestion
|
|||
import (
|
||||
"time"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
9
vendor/github.com/lucas-clemente/quic-go/crypto/cert_chain.go
generated
vendored
9
vendor/github.com/lucas-clemente/quic-go/crypto/cert_chain.go
generated
vendored
|
@ -102,3 +102,12 @@ func (cc *certChain) getCertForSNI(sni string) (*tls.Certificate, error) {
|
|||
// If nothing matches, return the first certificate.
|
||||
return &c.Certificates[0], nil
|
||||
}
|
||||
|
||||
func maybeGetConfigForClient(c *tls.Config, sni string) (*tls.Config, error) {
|
||||
if c.GetConfigForClient == nil {
|
||||
return c, nil
|
||||
}
|
||||
return c.GetConfigForClient(&tls.ClientHelloInfo{
|
||||
ServerName: sni,
|
||||
})
|
||||
}
|
||||
|
|
2
vendor/github.com/lucas-clemente/quic-go/crypto/cert_compression.go
generated
vendored
2
vendor/github.com/lucas-clemente/quic-go/crypto/cert_compression.go
generated
vendored
|
@ -9,7 +9,7 @@ import (
|
|||
"fmt"
|
||||
"hash/fnv"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
)
|
||||
|
||||
type entryType uint8
|
||||
|
|
5
vendor/github.com/lucas-clemente/quic-go/crypto/cert_manager.go
generated
vendored
5
vendor/github.com/lucas-clemente/quic-go/crypto/cert_manager.go
generated
vendored
|
@ -107,15 +107,14 @@ func (c *certManager) Verify(hostname string) error {
|
|||
var opts x509.VerifyOptions
|
||||
if c.config != nil {
|
||||
opts.Roots = c.config.RootCAs
|
||||
opts.DNSName = c.config.ServerName
|
||||
if c.config.Time == nil {
|
||||
opts.CurrentTime = time.Now()
|
||||
} else {
|
||||
opts.CurrentTime = c.config.Time()
|
||||
}
|
||||
} else {
|
||||
opts.DNSName = hostname
|
||||
}
|
||||
// we don't need to care about the tls.Config.ServerName here, since hostname has already been set to that value in the session setup
|
||||
opts.DNSName = hostname
|
||||
|
||||
// the first certificate is the leaf certificate, all others are intermediates
|
||||
if len(c.chain) > 1 {
|
||||
|
|
14
vendor/github.com/lucas-clemente/quic-go/crypto/config_for_client_1.8.go
generated
vendored
14
vendor/github.com/lucas-clemente/quic-go/crypto/config_for_client_1.8.go
generated
vendored
|
@ -1,14 +0,0 @@
|
|||
// +build go1.8
|
||||
|
||||
package crypto
|
||||
|
||||
import "crypto/tls"
|
||||
|
||||
func maybeGetConfigForClient(c *tls.Config, sni string) (*tls.Config, error) {
|
||||
if c.GetConfigForClient == nil {
|
||||
return c, nil
|
||||
}
|
||||
return c.GetConfigForClient(&tls.ClientHelloInfo{
|
||||
ServerName: sni,
|
||||
})
|
||||
}
|
9
vendor/github.com/lucas-clemente/quic-go/crypto/config_for_client_pre1.8.go
generated
vendored
9
vendor/github.com/lucas-clemente/quic-go/crypto/config_for_client_pre1.8.go
generated
vendored
|
@ -1,9 +0,0 @@
|
|||
// +build !go1.8
|
||||
|
||||
package crypto
|
||||
|
||||
import "crypto/tls"
|
||||
|
||||
func maybeGetConfigForClient(c *tls.Config, sni string) (*tls.Config, error) {
|
||||
return c, nil
|
||||
}
|
2
vendor/github.com/lucas-clemente/quic-go/crypto/key_derivation.go
generated
vendored
2
vendor/github.com/lucas-clemente/quic-go/crypto/key_derivation.go
generated
vendored
|
@ -5,8 +5,8 @@ import (
|
|||
"crypto/sha256"
|
||||
"io"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/protocol"
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
|
||||
"golang.org/x/crypto/hkdf"
|
||||
)
|
||||
|
|
4
vendor/github.com/lucas-clemente/quic-go/example/client/main.go
generated
vendored
4
vendor/github.com/lucas-clemente/quic-go/example/client/main.go
generated
vendored
|
@ -8,7 +8,7 @@ import (
|
|||
"sync"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/h2quic"
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
@ -24,7 +24,7 @@ func main() {
|
|||
utils.SetLogTimeFormat("")
|
||||
|
||||
hclient := &http.Client{
|
||||
Transport: &h2quic.QuicRoundTripper{},
|
||||
Transport: &h2quic.RoundTripper{},
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
|
|
10
vendor/github.com/lucas-clemente/quic-go/example/echo/echo.go
generated
vendored
10
vendor/github.com/lucas-clemente/quic-go/example/echo/echo.go
generated
vendored
|
@ -31,10 +31,7 @@ func main() {
|
|||
|
||||
// Start a server that echos all data on the first stream opened by the client
|
||||
func echoServer() error {
|
||||
cfgServer := &quic.Config{
|
||||
TLSConfig: generateTLSConfig(),
|
||||
}
|
||||
listener, err := quic.ListenAddr(addr, cfgServer)
|
||||
listener, err := quic.ListenAddr(addr, generateTLSConfig(), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -52,10 +49,7 @@ func echoServer() error {
|
|||
}
|
||||
|
||||
func clientMain() error {
|
||||
cfgClient := &quic.Config{
|
||||
TLSConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
}
|
||||
session, err := quic.DialAddr(addr, cfgClient)
|
||||
session, err := quic.DialAddr(addr, &tls.Config{InsecureSkipVerify: true}, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
2
vendor/github.com/lucas-clemente/quic-go/example/main.go
generated
vendored
2
vendor/github.com/lucas-clemente/quic-go/example/main.go
generated
vendored
|
@ -18,7 +18,7 @@ import (
|
|||
_ "net/http/pprof"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/h2quic"
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
)
|
||||
|
||||
type binds []string
|
||||
|
|
11
vendor/github.com/lucas-clemente/quic-go/flowcontrol/flow_control_manager.go
generated
vendored
11
vendor/github.com/lucas-clemente/quic-go/flowcontrol/flow_control_manager.go
generated
vendored
|
@ -7,9 +7,9 @@ import (
|
|||
|
||||
"github.com/lucas-clemente/quic-go/congestion"
|
||||
"github.com/lucas-clemente/quic-go/handshake"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/protocol"
|
||||
"github.com/lucas-clemente/quic-go/qerr"
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
)
|
||||
|
||||
type flowControlManager struct {
|
||||
|
@ -78,7 +78,7 @@ func (f *flowControlManager) ResetStream(streamID protocol.StreamID, byteOffset
|
|||
if streamFlowController.ContributesToConnection() {
|
||||
f.connFlowController.IncrementHighestReceived(increment)
|
||||
if f.connFlowController.CheckFlowControlViolation() {
|
||||
return qerr.Error(qerr.FlowControlReceivedTooMuchData, fmt.Sprintf("Received %d bytes for the connection, allowed %d bytes", byteOffset, f.connFlowController.receiveWindow))
|
||||
return qerr.Error(qerr.FlowControlReceivedTooMuchData, fmt.Sprintf("Received %d bytes for the connection, allowed %d bytes", f.connFlowController.highestReceived, f.connFlowController.receiveWindow))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -107,7 +107,7 @@ func (f *flowControlManager) UpdateHighestReceived(streamID protocol.StreamID, b
|
|||
if streamFlowController.ContributesToConnection() {
|
||||
f.connFlowController.IncrementHighestReceived(increment)
|
||||
if f.connFlowController.CheckFlowControlViolation() {
|
||||
return qerr.Error(qerr.FlowControlReceivedTooMuchData, fmt.Sprintf("Received %d bytes for the connection, allowed %d bytes", byteOffset, f.connFlowController.receiveWindow))
|
||||
return qerr.Error(qerr.FlowControlReceivedTooMuchData, fmt.Sprintf("Received %d bytes for the connection, allowed %d bytes", f.connFlowController.highestReceived, f.connFlowController.receiveWindow))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -157,6 +157,11 @@ func (f *flowControlManager) GetReceiveWindow(streamID protocol.StreamID) (proto
|
|||
f.mutex.RLock()
|
||||
defer f.mutex.RUnlock()
|
||||
|
||||
// StreamID can be 0 when retransmitting
|
||||
if streamID == 0 {
|
||||
return f.connFlowController.receiveWindow, nil
|
||||
}
|
||||
|
||||
flowController, err := f.getFlowController(streamID)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
|
|
2
vendor/github.com/lucas-clemente/quic-go/flowcontrol/flow_controller.go
generated
vendored
2
vendor/github.com/lucas-clemente/quic-go/flowcontrol/flow_controller.go
generated
vendored
|
@ -6,8 +6,8 @@ import (
|
|||
|
||||
"github.com/lucas-clemente/quic-go/congestion"
|
||||
"github.com/lucas-clemente/quic-go/handshake"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/protocol"
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
)
|
||||
|
||||
type flowController struct {
|
||||
|
|
2
vendor/github.com/lucas-clemente/quic-go/frames/ack_frame.go
generated
vendored
2
vendor/github.com/lucas-clemente/quic-go/frames/ack_frame.go
generated
vendored
|
@ -5,8 +5,8 @@ import (
|
|||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/protocol"
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
2
vendor/github.com/lucas-clemente/quic-go/frames/blocked_frame.go
generated
vendored
2
vendor/github.com/lucas-clemente/quic-go/frames/blocked_frame.go
generated
vendored
|
@ -3,8 +3,8 @@ package frames
|
|||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/protocol"
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
)
|
||||
|
||||
// A BlockedFrame in QUIC
|
||||
|
|
2
vendor/github.com/lucas-clemente/quic-go/frames/connection_close_frame.go
generated
vendored
2
vendor/github.com/lucas-clemente/quic-go/frames/connection_close_frame.go
generated
vendored
|
@ -6,9 +6,9 @@ import (
|
|||
"io"
|
||||
"math"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/protocol"
|
||||
"github.com/lucas-clemente/quic-go/qerr"
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
)
|
||||
|
||||
// A ConnectionCloseFrame in QUIC
|
||||
|
|
2
vendor/github.com/lucas-clemente/quic-go/frames/goaway_frame.go
generated
vendored
2
vendor/github.com/lucas-clemente/quic-go/frames/goaway_frame.go
generated
vendored
|
@ -4,9 +4,9 @@ import (
|
|||
"bytes"
|
||||
"io"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/protocol"
|
||||
"github.com/lucas-clemente/quic-go/qerr"
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
)
|
||||
|
||||
// A GoawayFrame is a GOAWAY frame
|
||||
|
|
2
vendor/github.com/lucas-clemente/quic-go/frames/log.go
generated
vendored
2
vendor/github.com/lucas-clemente/quic-go/frames/log.go
generated
vendored
|
@ -1,6 +1,6 @@
|
|||
package frames
|
||||
|
||||
import "github.com/lucas-clemente/quic-go/utils"
|
||||
import "github.com/lucas-clemente/quic-go/internal/utils"
|
||||
|
||||
// LogFrame logs a frame, either sent or received
|
||||
func LogFrame(frame Frame, sent bool) {
|
||||
|
|
2
vendor/github.com/lucas-clemente/quic-go/frames/rst_stream_frame.go
generated
vendored
2
vendor/github.com/lucas-clemente/quic-go/frames/rst_stream_frame.go
generated
vendored
|
@ -3,8 +3,8 @@ package frames
|
|||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/protocol"
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
)
|
||||
|
||||
// A RstStreamFrame in QUIC
|
||||
|
|
2
vendor/github.com/lucas-clemente/quic-go/frames/stop_waiting_frame.go
generated
vendored
2
vendor/github.com/lucas-clemente/quic-go/frames/stop_waiting_frame.go
generated
vendored
|
@ -4,9 +4,9 @@ import (
|
|||
"bytes"
|
||||
"errors"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/protocol"
|
||||
"github.com/lucas-clemente/quic-go/qerr"
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
)
|
||||
|
||||
// A StopWaitingFrame in QUIC
|
||||
|
|
2
vendor/github.com/lucas-clemente/quic-go/frames/stream_frame.go
generated
vendored
2
vendor/github.com/lucas-clemente/quic-go/frames/stream_frame.go
generated
vendored
|
@ -4,9 +4,9 @@ import (
|
|||
"bytes"
|
||||
"errors"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/protocol"
|
||||
"github.com/lucas-clemente/quic-go/qerr"
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
)
|
||||
|
||||
// A StreamFrame of QUIC
|
||||
|
|
2
vendor/github.com/lucas-clemente/quic-go/frames/window_update_frame.go
generated
vendored
2
vendor/github.com/lucas-clemente/quic-go/frames/window_update_frame.go
generated
vendored
|
@ -3,8 +3,8 @@ package frames
|
|||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/protocol"
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
)
|
||||
|
||||
// A WindowUpdateFrame in QUIC
|
||||
|
|
124
vendor/github.com/lucas-clemente/quic-go/h2quic/client.go
generated
vendored
124
vendor/github.com/lucas-clemente/quic-go/h2quic/client.go
generated
vendored
|
@ -15,59 +15,72 @@ import (
|
|||
"golang.org/x/net/idna"
|
||||
|
||||
quic "github.com/lucas-clemente/quic-go"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/protocol"
|
||||
"github.com/lucas-clemente/quic-go/qerr"
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
)
|
||||
|
||||
// Client is a HTTP2 client doing QUIC requests
|
||||
type Client struct {
|
||||
type roundTripperOpts struct {
|
||||
DisableCompression bool
|
||||
}
|
||||
|
||||
var dialAddr = quic.DialAddr
|
||||
|
||||
// client is a HTTP2 client doing QUIC requests
|
||||
type client struct {
|
||||
mutex sync.RWMutex
|
||||
|
||||
dialAddr func(hostname string, config *quic.Config) (quic.Session, error)
|
||||
config *quic.Config
|
||||
|
||||
t *QuicRoundTripper
|
||||
tlsConf *tls.Config
|
||||
config *quic.Config
|
||||
opts *roundTripperOpts
|
||||
|
||||
hostname string
|
||||
encryptionLevel protocol.EncryptionLevel
|
||||
handshakeErr error
|
||||
dialChan chan struct{} // will be closed once the handshake is complete and the header stream has been opened
|
||||
dialOnce sync.Once
|
||||
|
||||
session quic.Session
|
||||
headerStream quic.Stream
|
||||
headerErr *qerr.QuicError
|
||||
headerErrored chan struct{} // this channel is closed if an error occurs on the header stream
|
||||
requestWriter *requestWriter
|
||||
|
||||
responses map[protocol.StreamID]chan *http.Response
|
||||
}
|
||||
|
||||
var _ h2quicClient = &Client{}
|
||||
var _ http.RoundTripper = &client{}
|
||||
|
||||
// NewClient creates a new client
|
||||
func NewClient(t *QuicRoundTripper, tlsConfig *tls.Config, hostname string) *Client {
|
||||
return &Client{
|
||||
t: t,
|
||||
dialAddr: quic.DialAddr,
|
||||
var defaultQuicConfig = &quic.Config{
|
||||
RequestConnectionIDTruncation: true,
|
||||
KeepAlive: true,
|
||||
}
|
||||
|
||||
// newClient creates a new client
|
||||
func newClient(
|
||||
hostname string,
|
||||
tlsConfig *tls.Config,
|
||||
opts *roundTripperOpts,
|
||||
quicConfig *quic.Config,
|
||||
) *client {
|
||||
config := defaultQuicConfig
|
||||
if quicConfig != nil {
|
||||
config = quicConfig
|
||||
}
|
||||
return &client{
|
||||
hostname: authorityAddr("https", hostname),
|
||||
responses: make(map[protocol.StreamID]chan *http.Response),
|
||||
encryptionLevel: protocol.EncryptionUnencrypted,
|
||||
config: &quic.Config{
|
||||
TLSConfig: tlsConfig,
|
||||
RequestConnectionIDTruncation: true,
|
||||
},
|
||||
dialChan: make(chan struct{}),
|
||||
tlsConf: tlsConfig,
|
||||
config: config,
|
||||
opts: opts,
|
||||
headerErrored: make(chan struct{}),
|
||||
}
|
||||
}
|
||||
|
||||
// Dial dials the connection
|
||||
func (c *Client) Dial() (err error) {
|
||||
defer func() {
|
||||
c.handshakeErr = err
|
||||
close(c.dialChan)
|
||||
}()
|
||||
|
||||
c.session, err = c.dialAddr(c.hostname, c.config)
|
||||
// dial dials the connection
|
||||
func (c *client) dial() error {
|
||||
var err error
|
||||
c.session, err = dialAddr(c.hostname, c.tlsConf, c.config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -82,10 +95,10 @@ func (c *Client) Dial() (err error) {
|
|||
}
|
||||
c.requestWriter = newRequestWriter(c.headerStream)
|
||||
go c.handleHeaderStream()
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) handleHeaderStream() {
|
||||
func (c *client) handleHeaderStream() {
|
||||
decoder := hpack.NewDecoder(4096, func(hf hpack.HeaderField) {})
|
||||
h2framer := http2.NewFramer(nil, c.headerStream)
|
||||
|
||||
|
@ -111,7 +124,7 @@ func (c *Client) handleHeaderStream() {
|
|||
}
|
||||
|
||||
c.mutex.RLock()
|
||||
headerChan, ok := c.responses[protocol.StreamID(hframe.StreamID)]
|
||||
responseChan, ok := c.responses[protocol.StreamID(hframe.StreamID)]
|
||||
c.mutex.RUnlock()
|
||||
if !ok {
|
||||
c.headerErr = qerr.Error(qerr.InternalError, fmt.Sprintf("h2client BUG: response channel for stream %d not found", lastStream))
|
||||
|
@ -122,41 +135,38 @@ func (c *Client) handleHeaderStream() {
|
|||
if err != nil {
|
||||
c.headerErr = qerr.Error(qerr.InternalError, err.Error())
|
||||
}
|
||||
headerChan <- rsp
|
||||
responseChan <- rsp
|
||||
}
|
||||
|
||||
// stop all running request
|
||||
utils.Debugf("Error handling header stream %d: %s", lastStream, c.headerErr.Error())
|
||||
c.mutex.Lock()
|
||||
for _, responseChan := range c.responses {
|
||||
close(responseChan)
|
||||
}
|
||||
c.mutex.Unlock()
|
||||
close(c.headerErrored)
|
||||
}
|
||||
|
||||
// Do executes a request and returns a response
|
||||
func (c *Client) Do(req *http.Request) (*http.Response, error) {
|
||||
// Roundtrip executes a request and returns a response
|
||||
func (c *client) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
// TODO: add port to address, if it doesn't have one
|
||||
if req.URL.Scheme != "https" {
|
||||
return nil, errors.New("quic http2: unsupported scheme")
|
||||
}
|
||||
if authorityAddr("https", hostnameFromRequest(req)) != c.hostname {
|
||||
utils.Debugf("%s vs %s", req.Host, c.hostname)
|
||||
return nil, errors.New("h2quic Client BUG: Do called for the wrong client")
|
||||
return nil, fmt.Errorf("h2quic Client BUG: RoundTrip called for the wrong client (expected %s, got %s)", c.hostname, req.Host)
|
||||
}
|
||||
|
||||
hasBody := (req.Body != nil)
|
||||
c.dialOnce.Do(func() {
|
||||
c.handshakeErr = c.dial()
|
||||
})
|
||||
|
||||
// wait until the handshake is complete
|
||||
<-c.dialChan
|
||||
if c.handshakeErr != nil {
|
||||
return nil, c.handshakeErr
|
||||
}
|
||||
|
||||
hasBody := (req.Body != nil)
|
||||
|
||||
responseChan := make(chan *http.Response)
|
||||
dataStream, err := c.session.OpenStreamSync()
|
||||
if err != nil {
|
||||
c.Close(err)
|
||||
_ = c.CloseWithError(err)
|
||||
return nil, err
|
||||
}
|
||||
c.mutex.Lock()
|
||||
|
@ -164,14 +174,14 @@ func (c *Client) Do(req *http.Request) (*http.Response, error) {
|
|||
c.mutex.Unlock()
|
||||
|
||||
var requestedGzip bool
|
||||
if !c.t.disableCompression() && req.Header.Get("Accept-Encoding") == "" && req.Header.Get("Range") == "" && req.Method != "HEAD" {
|
||||
if !c.opts.DisableCompression && req.Header.Get("Accept-Encoding") == "" && req.Header.Get("Range") == "" && req.Method != "HEAD" {
|
||||
requestedGzip = true
|
||||
}
|
||||
// TODO: add support for trailers
|
||||
endStream := !hasBody
|
||||
err = c.requestWriter.WriteRequest(req, dataStream.StreamID(), endStream, requestedGzip)
|
||||
if err != nil {
|
||||
c.Close(err)
|
||||
_ = c.CloseWithError(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -198,15 +208,15 @@ func (c *Client) Do(req *http.Request) (*http.Response, error) {
|
|||
c.mutex.Lock()
|
||||
delete(c.responses, dataStream.StreamID())
|
||||
c.mutex.Unlock()
|
||||
if res == nil { // an error occured on the header stream
|
||||
c.Close(c.headerErr)
|
||||
return nil, c.headerErr
|
||||
}
|
||||
case err := <-resc:
|
||||
bodySent = true
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case <-c.headerErrored:
|
||||
// an error occured on the header stream
|
||||
_ = c.CloseWithError(c.headerErr)
|
||||
return nil, c.headerErr
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -230,11 +240,10 @@ func (c *Client) Do(req *http.Request) (*http.Response, error) {
|
|||
}
|
||||
|
||||
res.Request = req
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (c *Client) writeRequestBody(dataStream quic.Stream, body io.ReadCloser) (err error) {
|
||||
func (c *client) writeRequestBody(dataStream quic.Stream, body io.ReadCloser) (err error) {
|
||||
defer func() {
|
||||
cerr := body.Close()
|
||||
if err == nil {
|
||||
|
@ -252,8 +261,15 @@ func (c *Client) writeRequestBody(dataStream quic.Stream, body io.ReadCloser) (e
|
|||
}
|
||||
|
||||
// Close closes the client
|
||||
func (c *Client) Close(e error) {
|
||||
_ = c.session.Close(e)
|
||||
func (c *client) CloseWithError(e error) error {
|
||||
if c.session == nil {
|
||||
return nil
|
||||
}
|
||||
return c.session.Close(e)
|
||||
}
|
||||
|
||||
func (c *client) Close() error {
|
||||
return c.CloseWithError(nil)
|
||||
}
|
||||
|
||||
// copied from net/transport.go
|
||||
|
|
2
vendor/github.com/lucas-clemente/quic-go/h2quic/request_writer.go
generated
vendored
2
vendor/github.com/lucas-clemente/quic-go/h2quic/request_writer.go
generated
vendored
|
@ -13,8 +13,8 @@ import (
|
|||
"golang.org/x/net/lex/httplex"
|
||||
|
||||
quic "github.com/lucas-clemente/quic-go"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/protocol"
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
)
|
||||
|
||||
type requestWriter struct {
|
||||
|
|
2
vendor/github.com/lucas-clemente/quic-go/h2quic/response_writer.go
generated
vendored
2
vendor/github.com/lucas-clemente/quic-go/h2quic/response_writer.go
generated
vendored
|
@ -8,8 +8,8 @@ import (
|
|||
"sync"
|
||||
|
||||
quic "github.com/lucas-clemente/quic-go"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/protocol"
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
"golang.org/x/net/http2"
|
||||
"golang.org/x/net/http2/hpack"
|
||||
)
|
||||
|
|
70
vendor/github.com/lucas-clemente/quic-go/h2quic/roundtrip.go
generated
vendored
70
vendor/github.com/lucas-clemente/quic-go/h2quic/roundtrip.go
generated
vendored
|
@ -4,20 +4,23 @@ import (
|
|||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
quic "github.com/lucas-clemente/quic-go"
|
||||
|
||||
"golang.org/x/net/lex/httplex"
|
||||
)
|
||||
|
||||
type h2quicClient interface {
|
||||
Dial() error
|
||||
Do(*http.Request) (*http.Response, error)
|
||||
type roundTripCloser interface {
|
||||
http.RoundTripper
|
||||
io.Closer
|
||||
}
|
||||
|
||||
// QuicRoundTripper implements the http.RoundTripper interface
|
||||
type QuicRoundTripper struct {
|
||||
// RoundTripper implements the http.RoundTripper interface
|
||||
type RoundTripper struct {
|
||||
mutex sync.Mutex
|
||||
|
||||
// DisableCompression, if true, prevents the Transport from
|
||||
|
@ -34,13 +37,29 @@ type QuicRoundTripper struct {
|
|||
// tls.Client. If nil, the default configuration is used.
|
||||
TLSClientConfig *tls.Config
|
||||
|
||||
clients map[string]h2quicClient
|
||||
// QuicConfig is the quic.Config used for dialing new connections.
|
||||
// If nil, reasonable default values will be used.
|
||||
QuicConfig *quic.Config
|
||||
|
||||
clients map[string]roundTripCloser
|
||||
}
|
||||
|
||||
var _ http.RoundTripper = &QuicRoundTripper{}
|
||||
// RoundTripOpt are options for the Transport.RoundTripOpt method.
|
||||
type RoundTripOpt struct {
|
||||
// OnlyCachedConn controls whether the RoundTripper may
|
||||
// create a new QUIC connection. If set true and
|
||||
// no cached connection is available, RoundTrip
|
||||
// will return ErrNoCachedConn.
|
||||
OnlyCachedConn bool
|
||||
}
|
||||
|
||||
// RoundTrip does a round trip
|
||||
func (r *QuicRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
var _ roundTripCloser = &RoundTripper{}
|
||||
|
||||
// ErrNoCachedConn is returned when RoundTripper.OnlyCachedConn is set
|
||||
var ErrNoCachedConn = errors.New("h2quic: no cached connection was available")
|
||||
|
||||
// RoundTripOpt is like RoundTrip, but takes options.
|
||||
func (r *RoundTripper) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Response, error) {
|
||||
if req.URL == nil {
|
||||
closeRequestBody(req)
|
||||
return nil, errors.New("quic: nil Request.URL")
|
||||
|
@ -76,35 +95,48 @@ func (r *QuicRoundTripper) RoundTrip(req *http.Request) (*http.Response, error)
|
|||
}
|
||||
|
||||
hostname := authorityAddr("https", hostnameFromRequest(req))
|
||||
client, err := r.getClient(hostname)
|
||||
cl, err := r.getClient(hostname, opt.OnlyCachedConn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return client.Do(req)
|
||||
return cl.RoundTrip(req)
|
||||
}
|
||||
|
||||
func (r *QuicRoundTripper) getClient(hostname string) (h2quicClient, error) {
|
||||
// RoundTrip does a round trip.
|
||||
func (r *RoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
return r.RoundTripOpt(req, RoundTripOpt{})
|
||||
}
|
||||
|
||||
func (r *RoundTripper) getClient(hostname string, onlyCached bool) (http.RoundTripper, error) {
|
||||
r.mutex.Lock()
|
||||
defer r.mutex.Unlock()
|
||||
|
||||
if r.clients == nil {
|
||||
r.clients = make(map[string]h2quicClient)
|
||||
r.clients = make(map[string]roundTripCloser)
|
||||
}
|
||||
|
||||
client, ok := r.clients[hostname]
|
||||
if !ok {
|
||||
client = NewClient(r, r.TLSClientConfig, hostname)
|
||||
err := client.Dial()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if onlyCached {
|
||||
return nil, ErrNoCachedConn
|
||||
}
|
||||
client = newClient(hostname, r.TLSClientConfig, &roundTripperOpts{DisableCompression: r.DisableCompression}, r.QuicConfig)
|
||||
r.clients[hostname] = client
|
||||
}
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func (r *QuicRoundTripper) disableCompression() bool {
|
||||
return r.DisableCompression
|
||||
// Close closes the QUIC connections that this RoundTripper has used
|
||||
func (r *RoundTripper) Close() error {
|
||||
r.mutex.Lock()
|
||||
defer r.mutex.Unlock()
|
||||
for _, client := range r.clients {
|
||||
if err := client.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
r.clients = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func closeRequestBody(req *http.Request) {
|
||||
|
|
27
vendor/github.com/lucas-clemente/quic-go/h2quic/server.go
generated
vendored
27
vendor/github.com/lucas-clemente/quic-go/h2quic/server.go
generated
vendored
|
@ -13,9 +13,9 @@ import (
|
|||
"time"
|
||||
|
||||
quic "github.com/lucas-clemente/quic-go"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/protocol"
|
||||
"github.com/lucas-clemente/quic-go/qerr"
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
"golang.org/x/net/http2"
|
||||
"golang.org/x/net/http2/hpack"
|
||||
)
|
||||
|
@ -29,10 +29,20 @@ type remoteCloser interface {
|
|||
CloseRemote(protocol.ByteCount)
|
||||
}
|
||||
|
||||
// allows mocking of quic.Listen and quic.ListenAddr
|
||||
var (
|
||||
quicListen = quic.Listen
|
||||
quicListenAddr = quic.ListenAddr
|
||||
)
|
||||
|
||||
// Server is a HTTP2 server listening for QUIC connections.
|
||||
type Server struct {
|
||||
*http.Server
|
||||
|
||||
// By providing a quic.Config, it is possible to set parameters of the QUIC connection.
|
||||
// If nil, it uses reasonable default values.
|
||||
QuicConfig *quic.Config
|
||||
|
||||
// Private flag for demo, do not use
|
||||
CloseAfterFirstRequest bool
|
||||
|
||||
|
@ -69,11 +79,11 @@ func (s *Server) ListenAndServeTLS(certFile, keyFile string) error {
|
|||
}
|
||||
|
||||
// Serve an existing UDP connection.
|
||||
func (s *Server) Serve(conn *net.UDPConn) error {
|
||||
func (s *Server) Serve(conn net.PacketConn) error {
|
||||
return s.serveImpl(s.TLSConfig, conn)
|
||||
}
|
||||
|
||||
func (s *Server) serveImpl(tlsConfig *tls.Config, conn *net.UDPConn) error {
|
||||
func (s *Server) serveImpl(tlsConfig *tls.Config, conn net.PacketConn) error {
|
||||
if s.Server == nil {
|
||||
return errors.New("use of h2quic.Server without http.Server")
|
||||
}
|
||||
|
@ -83,17 +93,12 @@ func (s *Server) serveImpl(tlsConfig *tls.Config, conn *net.UDPConn) error {
|
|||
return errors.New("ListenAndServe may only be called once")
|
||||
}
|
||||
|
||||
config := quic.Config{
|
||||
TLSConfig: tlsConfig,
|
||||
Versions: protocol.SupportedVersions,
|
||||
}
|
||||
|
||||
var ln quic.Listener
|
||||
var err error
|
||||
if conn == nil {
|
||||
ln, err = quic.ListenAddr(s.Addr, &config)
|
||||
ln, err = quicListenAddr(s.Addr, tlsConfig, s.QuicConfig)
|
||||
} else {
|
||||
ln, err = quic.Listen(conn, &config)
|
||||
ln, err = quicListen(conn, tlsConfig, s.QuicConfig)
|
||||
}
|
||||
if err != nil {
|
||||
s.listenerMutex.Unlock()
|
||||
|
@ -255,7 +260,6 @@ func (s *Server) CloseGracefully(timeout time.Duration) error {
|
|||
|
||||
// SetQuicHeaders can be used to set the proper headers that announce that this server supports QUIC.
|
||||
// The values that are set depend on the port information from s.Server.Addr, and currently look like this (if Addr has port 443):
|
||||
// Alternate-Protocol: 443:quic
|
||||
// Alt-Svc: quic=":443"; ma=2592000; v="33,32,31,30"
|
||||
func (s *Server) SetQuicHeaders(hdr http.Header) error {
|
||||
port := atomic.LoadUint32(&s.port)
|
||||
|
@ -283,7 +287,6 @@ func (s *Server) SetQuicHeaders(hdr http.Header) error {
|
|||
}
|
||||
}
|
||||
|
||||
hdr.Add("Alternate-Protocol", fmt.Sprintf("%d:quic", port))
|
||||
hdr.Add("Alt-Svc", fmt.Sprintf(`quic=":%d"; ma=2592000; v="%s"`, port, s.supportedVersionsAsString))
|
||||
|
||||
return nil
|
||||
|
|
33
vendor/github.com/lucas-clemente/quic-go/handshake/connection_parameters_manager.go
generated
vendored
33
vendor/github.com/lucas-clemente/quic-go/handshake/connection_parameters_manager.go
generated
vendored
|
@ -5,9 +5,9 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/protocol"
|
||||
"github.com/lucas-clemente/quic-go/qerr"
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
)
|
||||
|
||||
// ConnectionParametersManager negotiates and stores the connection parameters
|
||||
|
@ -50,6 +50,8 @@ type connectionParametersManager struct {
|
|||
sendConnectionFlowControlWindow protocol.ByteCount
|
||||
receiveStreamFlowControlWindow protocol.ByteCount
|
||||
receiveConnectionFlowControlWindow protocol.ByteCount
|
||||
maxReceiveStreamFlowControlWindow protocol.ByteCount
|
||||
maxReceiveConnectionFlowControlWindow protocol.ByteCount
|
||||
}
|
||||
|
||||
var _ ConnectionParametersManager = &connectionParametersManager{}
|
||||
|
@ -61,14 +63,19 @@ var (
|
|||
)
|
||||
|
||||
// NewConnectionParamatersManager creates a new connection parameters manager
|
||||
func NewConnectionParamatersManager(pers protocol.Perspective, v protocol.VersionNumber) ConnectionParametersManager {
|
||||
func NewConnectionParamatersManager(
|
||||
pers protocol.Perspective, v protocol.VersionNumber,
|
||||
maxReceiveStreamFlowControlWindow protocol.ByteCount, maxReceiveConnectionFlowControlWindow protocol.ByteCount,
|
||||
) ConnectionParametersManager {
|
||||
h := &connectionParametersManager{
|
||||
perspective: pers,
|
||||
version: v,
|
||||
sendStreamFlowControlWindow: protocol.InitialStreamFlowControlWindow, // can only be changed by the client
|
||||
sendConnectionFlowControlWindow: protocol.InitialConnectionFlowControlWindow, // can only be changed by the client
|
||||
receiveStreamFlowControlWindow: protocol.ReceiveStreamFlowControlWindow,
|
||||
receiveConnectionFlowControlWindow: protocol.ReceiveConnectionFlowControlWindow,
|
||||
perspective: pers,
|
||||
version: v,
|
||||
sendStreamFlowControlWindow: protocol.InitialStreamFlowControlWindow, // can only be changed by the client
|
||||
sendConnectionFlowControlWindow: protocol.InitialConnectionFlowControlWindow, // can only be changed by the client
|
||||
receiveStreamFlowControlWindow: protocol.ReceiveStreamFlowControlWindow,
|
||||
receiveConnectionFlowControlWindow: protocol.ReceiveConnectionFlowControlWindow,
|
||||
maxReceiveStreamFlowControlWindow: maxReceiveStreamFlowControlWindow,
|
||||
maxReceiveConnectionFlowControlWindow: maxReceiveConnectionFlowControlWindow,
|
||||
}
|
||||
|
||||
if h.perspective == protocol.PerspectiveServer {
|
||||
|
@ -207,10 +214,7 @@ func (h *connectionParametersManager) GetReceiveStreamFlowControlWindow() protoc
|
|||
|
||||
// GetMaxReceiveStreamFlowControlWindow gets the maximum size of the stream-level flow control window for sending data
|
||||
func (h *connectionParametersManager) GetMaxReceiveStreamFlowControlWindow() protocol.ByteCount {
|
||||
if h.perspective == protocol.PerspectiveServer {
|
||||
return protocol.MaxReceiveStreamFlowControlWindowServer
|
||||
}
|
||||
return protocol.MaxReceiveStreamFlowControlWindowClient
|
||||
return h.maxReceiveStreamFlowControlWindow
|
||||
}
|
||||
|
||||
// GetReceiveConnectionFlowControlWindow gets the size of the stream-level flow control window for receiving data
|
||||
|
@ -222,10 +226,7 @@ func (h *connectionParametersManager) GetReceiveConnectionFlowControlWindow() pr
|
|||
|
||||
// GetMaxReceiveConnectionFlowControlWindow gets the maximum size of the stream-level flow control window for sending data
|
||||
func (h *connectionParametersManager) GetMaxReceiveConnectionFlowControlWindow() protocol.ByteCount {
|
||||
if h.perspective == protocol.PerspectiveServer {
|
||||
return protocol.MaxReceiveConnectionFlowControlWindowServer
|
||||
}
|
||||
return protocol.MaxReceiveConnectionFlowControlWindowClient
|
||||
return h.maxReceiveConnectionFlowControlWindow
|
||||
}
|
||||
|
||||
// GetMaxOutgoingStreams gets the maximum number of outgoing streams per connection
|
||||
|
|
7
vendor/github.com/lucas-clemente/quic-go/handshake/crypto_setup_client.go
generated
vendored
7
vendor/github.com/lucas-clemente/quic-go/handshake/crypto_setup_client.go
generated
vendored
|
@ -12,9 +12,9 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/crypto"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/protocol"
|
||||
"github.com/lucas-clemente/quic-go/qerr"
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
)
|
||||
|
||||
type cryptoSetupClient struct {
|
||||
|
@ -332,7 +332,6 @@ func (h *cryptoSetupClient) Open(dst, src []byte, packetNumber protocol.PacketNu
|
|||
func (h *cryptoSetupClient) GetSealer() (protocol.EncryptionLevel, Sealer) {
|
||||
h.mutex.RLock()
|
||||
defer h.mutex.RUnlock()
|
||||
|
||||
if h.forwardSecureAEAD != nil {
|
||||
return protocol.EncryptionForwardSecure, h.sealForwardSecure
|
||||
} else if h.secureAEAD != nil {
|
||||
|
@ -342,6 +341,10 @@ func (h *cryptoSetupClient) GetSealer() (protocol.EncryptionLevel, Sealer) {
|
|||
}
|
||||
}
|
||||
|
||||
func (h *cryptoSetupClient) GetSealerForCryptoStream() (protocol.EncryptionLevel, Sealer) {
|
||||
return protocol.EncryptionUnencrypted, h.sealUnencrypted
|
||||
}
|
||||
|
||||
func (h *cryptoSetupClient) GetSealerWithEncryptionLevel(encLevel protocol.EncryptionLevel) (Sealer, error) {
|
||||
h.mutex.RLock()
|
||||
defer h.mutex.RUnlock()
|
||||
|
|
17
vendor/github.com/lucas-clemente/quic-go/handshake/crypto_setup_server.go
generated
vendored
17
vendor/github.com/lucas-clemente/quic-go/handshake/crypto_setup_server.go
generated
vendored
|
@ -10,9 +10,9 @@ import (
|
|||
"sync"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/crypto"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/protocol"
|
||||
"github.com/lucas-clemente/quic-go/qerr"
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
)
|
||||
|
||||
// KeyDerivationFunction is used for key derivation
|
||||
|
@ -214,12 +214,16 @@ func (h *cryptoSetupServer) Open(dst, src []byte, packetNumber protocol.PacketNu
|
|||
func (h *cryptoSetupServer) GetSealer() (protocol.EncryptionLevel, Sealer) {
|
||||
h.mutex.RLock()
|
||||
defer h.mutex.RUnlock()
|
||||
|
||||
if h.forwardSecureAEAD != nil && h.sentSHLO {
|
||||
if h.forwardSecureAEAD != nil {
|
||||
return protocol.EncryptionForwardSecure, h.sealForwardSecure
|
||||
} else if h.secureAEAD != nil {
|
||||
// secureAEAD and forwardSecureAEAD are created at the same time (when receiving the CHLO)
|
||||
// make sure that the SHLO isn't sent forward-secure
|
||||
}
|
||||
return protocol.EncryptionUnencrypted, h.sealUnencrypted
|
||||
}
|
||||
|
||||
func (h *cryptoSetupServer) GetSealerForCryptoStream() (protocol.EncryptionLevel, Sealer) {
|
||||
h.mutex.RLock()
|
||||
defer h.mutex.RUnlock()
|
||||
if h.secureAEAD != nil {
|
||||
return protocol.EncryptionSecure, h.sealSecure
|
||||
}
|
||||
return protocol.EncryptionUnencrypted, h.sealUnencrypted
|
||||
|
@ -251,7 +255,6 @@ func (h *cryptoSetupServer) sealUnencrypted(dst, src []byte, packetNumber protoc
|
|||
}
|
||||
|
||||
func (h *cryptoSetupServer) sealSecure(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) []byte {
|
||||
h.sentSHLO = true
|
||||
return h.secureAEAD.Seal(dst, src, packetNumber, associatedData)
|
||||
}
|
||||
|
||||
|
|
2
vendor/github.com/lucas-clemente/quic-go/handshake/ephermal_cache.go
generated
vendored
2
vendor/github.com/lucas-clemente/quic-go/handshake/ephermal_cache.go
generated
vendored
|
@ -5,8 +5,8 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/crypto"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/protocol"
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
2
vendor/github.com/lucas-clemente/quic-go/handshake/handshake_message.go
generated
vendored
2
vendor/github.com/lucas-clemente/quic-go/handshake/handshake_message.go
generated
vendored
|
@ -7,9 +7,9 @@ import (
|
|||
"io"
|
||||
"sort"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/protocol"
|
||||
"github.com/lucas-clemente/quic-go/qerr"
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
)
|
||||
|
||||
// A HandshakeMessage is a handshake message
|
||||
|
|
1
vendor/github.com/lucas-clemente/quic-go/handshake/interface.go
generated
vendored
1
vendor/github.com/lucas-clemente/quic-go/handshake/interface.go
generated
vendored
|
@ -15,6 +15,7 @@ type CryptoSetup interface {
|
|||
|
||||
GetSealer() (protocol.EncryptionLevel, Sealer)
|
||||
GetSealerWithEncryptionLevel(protocol.EncryptionLevel) (Sealer, error)
|
||||
GetSealerForCryptoStream() (protocol.EncryptionLevel, Sealer)
|
||||
}
|
||||
|
||||
// TransportParameters are parameters sent to the peer during the handshake
|
||||
|
|
2
vendor/github.com/lucas-clemente/quic-go/handshake/server_config_client.go
generated
vendored
2
vendor/github.com/lucas-clemente/quic-go/handshake/server_config_client.go
generated
vendored
|
@ -8,8 +8,8 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/crypto"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/qerr"
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
)
|
||||
|
||||
type serverConfigClient struct {
|
||||
|
|
133
vendor/github.com/lucas-clemente/quic-go/integrationtests/handshake/rtt.go
generated
vendored
Normal file
133
vendor/github.com/lucas-clemente/quic-go/integrationtests/handshake/rtt.go
generated
vendored
Normal file
|
@ -0,0 +1,133 @@
|
|||
package handshaketests
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
quic "github.com/lucas-clemente/quic-go"
|
||||
"github.com/lucas-clemente/quic-go/integrationtests/proxy"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/protocol"
|
||||
"github.com/lucas-clemente/quic-go/qerr"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/testdata"
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
var _ = Describe("Handshake integration tets", func() {
|
||||
var (
|
||||
proxy *quicproxy.QuicProxy
|
||||
server quic.Listener
|
||||
serverConfig *quic.Config
|
||||
testStartedAt time.Time
|
||||
)
|
||||
rtt := 400 * time.Millisecond
|
||||
|
||||
BeforeEach(func() {
|
||||
serverConfig = &quic.Config{}
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
Expect(proxy.Close()).To(Succeed())
|
||||
Expect(server.Close()).To(Succeed())
|
||||
})
|
||||
|
||||
runServerAndProxy := func() {
|
||||
var err error
|
||||
// start the server
|
||||
server, err = quic.ListenAddr("localhost:0", testdata.GetTLSConfig(), serverConfig)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
// start the proxy
|
||||
proxy, err = quicproxy.NewQuicProxy("localhost:0", quicproxy.Opts{
|
||||
RemoteAddr: server.Addr().String(),
|
||||
DelayPacket: func(_ quicproxy.Direction, _ protocol.PacketNumber) time.Duration { return rtt / 2 },
|
||||
})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
testStartedAt = time.Now()
|
||||
|
||||
go func() {
|
||||
for {
|
||||
_, _ = server.Accept()
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
expectDurationInRTTs := func(num int) {
|
||||
testDuration := time.Since(testStartedAt)
|
||||
expectedDuration := time.Duration(num) * rtt
|
||||
Expect(testDuration).To(SatisfyAll(
|
||||
BeNumerically(">=", expectedDuration),
|
||||
BeNumerically("<", expectedDuration+rtt),
|
||||
))
|
||||
}
|
||||
|
||||
It("fails when there's no matching version, after 1 RTT", func() {
|
||||
Expect(len(protocol.SupportedVersions)).To(BeNumerically(">", 1))
|
||||
serverConfig.Versions = protocol.SupportedVersions[:1]
|
||||
runServerAndProxy()
|
||||
clientConfig := &quic.Config{
|
||||
Versions: protocol.SupportedVersions[1:2],
|
||||
}
|
||||
_, err := quic.DialAddr(proxy.LocalAddr().String(), nil, clientConfig)
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(err.(qerr.ErrorCode)).To(Equal(qerr.InvalidVersion))
|
||||
expectDurationInRTTs(1)
|
||||
})
|
||||
|
||||
// 1 RTT for verifying the source address
|
||||
// 1 RTT to become secure
|
||||
// 1 RTT to become forward-secure
|
||||
It("is forward-secure after 3 RTTs", func() {
|
||||
runServerAndProxy()
|
||||
_, err := quic.DialAddr(proxy.LocalAddr().String(), &tls.Config{InsecureSkipVerify: true}, nil)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
expectDurationInRTTs(3)
|
||||
})
|
||||
|
||||
// 1 RTT for verifying the source address
|
||||
// 1 RTT to become secure
|
||||
// TODO (marten-seemann): enable this test (see #625)
|
||||
PIt("is secure after 2 RTTs", func() {
|
||||
utils.SetLogLevel(utils.LogLevelDebug)
|
||||
runServerAndProxy()
|
||||
_, err := quic.DialAddrNonFWSecure(proxy.LocalAddr().String(), &tls.Config{InsecureSkipVerify: true}, nil)
|
||||
fmt.Println("#### is non fw secure ###")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
expectDurationInRTTs(2)
|
||||
})
|
||||
|
||||
It("is forward-secure after 2 RTTs when the server doesn't require an STK", func() {
|
||||
serverConfig.AcceptSTK = func(_ net.Addr, _ *quic.STK) bool {
|
||||
return true
|
||||
}
|
||||
runServerAndProxy()
|
||||
_, err := quic.DialAddr(proxy.LocalAddr().String(), &tls.Config{InsecureSkipVerify: true}, nil)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
expectDurationInRTTs(2)
|
||||
})
|
||||
|
||||
It("doesn't complete the handshake when the server never accepts the STK", func() {
|
||||
serverConfig.AcceptSTK = func(_ net.Addr, _ *quic.STK) bool {
|
||||
return false
|
||||
}
|
||||
runServerAndProxy()
|
||||
_, err := quic.DialAddr(proxy.LocalAddr().String(), &tls.Config{InsecureSkipVerify: true}, nil)
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(err.(*qerr.QuicError).ErrorCode).To(Equal(qerr.CryptoTooManyRejects))
|
||||
})
|
||||
|
||||
It("doesn't complete the handshake when the handshake timeout is too short", func() {
|
||||
serverConfig.HandshakeTimeout = 2 * rtt
|
||||
runServerAndProxy()
|
||||
_, err := quic.DialAddr(proxy.LocalAddr().String(), &tls.Config{InsecureSkipVerify: true}, nil)
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(err.(*qerr.QuicError).ErrorCode).To(Equal(qerr.HandshakeTimeout))
|
||||
// 2 RTTs during the timeout
|
||||
// plus 1 RTT: the timer starts 0.5 RTTs after sending the first packet, and the CONNECTION_CLOSE needs another 0.5 RTTs to reach the client
|
||||
expectDurationInRTTs(3)
|
||||
})
|
||||
})
|
40
vendor/github.com/lucas-clemente/quic-go/interface.go
generated
vendored
40
vendor/github.com/lucas-clemente/quic-go/interface.go
generated
vendored
|
@ -1,7 +1,6 @@
|
|||
package quic
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"io"
|
||||
"net"
|
||||
"time"
|
||||
|
@ -11,12 +10,32 @@ import (
|
|||
|
||||
// Stream is the interface implemented by QUIC streams
|
||||
type Stream interface {
|
||||
// Read reads data from the stream.
|
||||
// Read can be made to time out and return a net.Error with Timeout() == true
|
||||
// after a fixed time limit; see SetDeadline and SetReadDeadline.
|
||||
io.Reader
|
||||
// Write writes data to the stream.
|
||||
// Write can be made to time out and return a net.Error with Timeout() == true
|
||||
// after a fixed time limit; see SetDeadline and SetWriteDeadline.
|
||||
io.Writer
|
||||
io.Closer
|
||||
StreamID() protocol.StreamID
|
||||
// Reset closes the stream with an error.
|
||||
Reset(error)
|
||||
// SetReadDeadline sets the deadline for future Read calls and
|
||||
// any currently-blocked Read call.
|
||||
// A zero value for t means Read will not time out.
|
||||
SetReadDeadline(t time.Time) error
|
||||
// SetWriteDeadline sets the deadline for future Write calls
|
||||
// and any currently-blocked Write call.
|
||||
// Even if write times out, it may return n > 0, indicating that
|
||||
// some of the data was successfully written.
|
||||
// A zero value for t means Write will not time out.
|
||||
SetWriteDeadline(t time.Time) error
|
||||
// SetDeadline sets the read and write deadlines associated
|
||||
// with the connection. It is equivalent to calling both
|
||||
// SetReadDeadline and SetWriteDeadline.
|
||||
SetDeadline(t time.Time) error
|
||||
}
|
||||
|
||||
// A Session is a QUIC connection between two peers.
|
||||
|
@ -37,6 +56,9 @@ type Session interface {
|
|||
RemoteAddr() net.Addr
|
||||
// Close closes the connection. The error will be sent to the remote peer in a CONNECTION_CLOSE frame. An error value of nil is allowed and will cause a normal PeerGoingAway to be sent.
|
||||
Close(error) error
|
||||
// WaitUntilClosed() blocks until the session is closed.
|
||||
// Warning: This API should not be considered stable and might change soon.
|
||||
WaitUntilClosed()
|
||||
}
|
||||
|
||||
// A NonFWSession is a QUIC connection between two peers half-way through the handshake.
|
||||
|
@ -61,21 +83,31 @@ type STK struct {
|
|||
// Config contains all configuration data needed for a QUIC server or client.
|
||||
// More config parameters (such as timeouts) will be added soon, see e.g. https://github.com/lucas-clemente/quic-go/issues/441.
|
||||
type Config struct {
|
||||
TLSConfig *tls.Config
|
||||
// The QUIC versions that can be negotiated.
|
||||
// If not set, it uses all versions available.
|
||||
// Warning: This API should not be considered stable and will change soon.
|
||||
Versions []protocol.VersionNumber
|
||||
// Ask the server to truncate the connection ID sent in the Public Header.
|
||||
// If not set, the default checks if
|
||||
// This saves 8 bytes in the Public Header in every packet. However, if the IP address of the server changes, the connection cannot be migrated.
|
||||
// Currently only valid for the client.
|
||||
RequestConnectionIDTruncation bool
|
||||
// HandshakeTimeout is the maximum duration that the cryptographic handshake may take.
|
||||
// If the timeout is exceeded, the connection is closed.
|
||||
// If this value is zero, the timeout is set to 10 seconds.
|
||||
HandshakeTimeout time.Duration
|
||||
// AcceptSTK determines if an STK is accepted.
|
||||
// It is called with stk = nil if the client didn't send an STK.
|
||||
// If not set, it verifies that the address matches, and that the STK was issued within the last 24 hours
|
||||
// If not set, it verifies that the address matches, and that the STK was issued within the last 24 hours.
|
||||
// This option is only valid for the server.
|
||||
AcceptSTK func(clientAddr net.Addr, stk *STK) bool
|
||||
// MaxReceiveStreamFlowControlWindow is the maximum stream-level flow control window for receiving data.
|
||||
// If this value is zero, it will default to 1 MB for the server and 6 MB for the client.
|
||||
MaxReceiveStreamFlowControlWindow protocol.ByteCount
|
||||
// MaxReceiveConnectionFlowControlWindow is the connection-level flow control window for receiving data.
|
||||
// If this value is zero, it will default to 1.5 MB for the server and 15 MB for the client.
|
||||
MaxReceiveConnectionFlowControlWindow protocol.ByteCount
|
||||
// KeepAlive defines whether this peer will periodically send PING frames to keep the connection alive.
|
||||
KeepAlive bool
|
||||
}
|
||||
|
||||
// A Listener for incoming QUIC connections
|
||||
|
|
153
vendor/github.com/lucas-clemente/quic-go/internal/mocks/cpm.go
generated
vendored
Normal file
153
vendor/github.com/lucas-clemente/quic-go/internal/mocks/cpm.go
generated
vendored
Normal file
|
@ -0,0 +1,153 @@
|
|||
// Automatically generated by MockGen. DO NOT EDIT!
|
||||
// Source: github.com/lucas-clemente/quic-go/handshake (interfaces: ConnectionParametersManager)
|
||||
|
||||
package mocks
|
||||
|
||||
import (
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
handshake "github.com/lucas-clemente/quic-go/handshake"
|
||||
protocol "github.com/lucas-clemente/quic-go/protocol"
|
||||
time "time"
|
||||
)
|
||||
|
||||
// Mock of ConnectionParametersManager interface
|
||||
type MockConnectionParametersManager struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *_MockConnectionParametersManagerRecorder
|
||||
}
|
||||
|
||||
// Recorder for MockConnectionParametersManager (not exported)
|
||||
type _MockConnectionParametersManagerRecorder struct {
|
||||
mock *MockConnectionParametersManager
|
||||
}
|
||||
|
||||
func NewMockConnectionParametersManager(ctrl *gomock.Controller) *MockConnectionParametersManager {
|
||||
mock := &MockConnectionParametersManager{ctrl: ctrl}
|
||||
mock.recorder = &_MockConnectionParametersManagerRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
func (_m *MockConnectionParametersManager) EXPECT() *_MockConnectionParametersManagerRecorder {
|
||||
return _m.recorder
|
||||
}
|
||||
|
||||
func (_m *MockConnectionParametersManager) GetHelloMap() (map[handshake.Tag][]byte, error) {
|
||||
ret := _m.ctrl.Call(_m, "GetHelloMap")
|
||||
ret0, _ := ret[0].(map[handshake.Tag][]byte)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
func (_mr *_MockConnectionParametersManagerRecorder) GetHelloMap() *gomock.Call {
|
||||
return _mr.mock.ctrl.RecordCall(_mr.mock, "GetHelloMap")
|
||||
}
|
||||
|
||||
func (_m *MockConnectionParametersManager) GetIdleConnectionStateLifetime() time.Duration {
|
||||
ret := _m.ctrl.Call(_m, "GetIdleConnectionStateLifetime")
|
||||
ret0, _ := ret[0].(time.Duration)
|
||||
return ret0
|
||||
}
|
||||
|
||||
func (_mr *_MockConnectionParametersManagerRecorder) GetIdleConnectionStateLifetime() *gomock.Call {
|
||||
return _mr.mock.ctrl.RecordCall(_mr.mock, "GetIdleConnectionStateLifetime")
|
||||
}
|
||||
|
||||
func (_m *MockConnectionParametersManager) GetMaxIncomingStreams() uint32 {
|
||||
ret := _m.ctrl.Call(_m, "GetMaxIncomingStreams")
|
||||
ret0, _ := ret[0].(uint32)
|
||||
return ret0
|
||||
}
|
||||
|
||||
func (_mr *_MockConnectionParametersManagerRecorder) GetMaxIncomingStreams() *gomock.Call {
|
||||
return _mr.mock.ctrl.RecordCall(_mr.mock, "GetMaxIncomingStreams")
|
||||
}
|
||||
|
||||
func (_m *MockConnectionParametersManager) GetMaxOutgoingStreams() uint32 {
|
||||
ret := _m.ctrl.Call(_m, "GetMaxOutgoingStreams")
|
||||
ret0, _ := ret[0].(uint32)
|
||||
return ret0
|
||||
}
|
||||
|
||||
func (_mr *_MockConnectionParametersManagerRecorder) GetMaxOutgoingStreams() *gomock.Call {
|
||||
return _mr.mock.ctrl.RecordCall(_mr.mock, "GetMaxOutgoingStreams")
|
||||
}
|
||||
|
||||
func (_m *MockConnectionParametersManager) GetMaxReceiveConnectionFlowControlWindow() protocol.ByteCount {
|
||||
ret := _m.ctrl.Call(_m, "GetMaxReceiveConnectionFlowControlWindow")
|
||||
ret0, _ := ret[0].(protocol.ByteCount)
|
||||
return ret0
|
||||
}
|
||||
|
||||
func (_mr *_MockConnectionParametersManagerRecorder) GetMaxReceiveConnectionFlowControlWindow() *gomock.Call {
|
||||
return _mr.mock.ctrl.RecordCall(_mr.mock, "GetMaxReceiveConnectionFlowControlWindow")
|
||||
}
|
||||
|
||||
func (_m *MockConnectionParametersManager) GetMaxReceiveStreamFlowControlWindow() protocol.ByteCount {
|
||||
ret := _m.ctrl.Call(_m, "GetMaxReceiveStreamFlowControlWindow")
|
||||
ret0, _ := ret[0].(protocol.ByteCount)
|
||||
return ret0
|
||||
}
|
||||
|
||||
func (_mr *_MockConnectionParametersManagerRecorder) GetMaxReceiveStreamFlowControlWindow() *gomock.Call {
|
||||
return _mr.mock.ctrl.RecordCall(_mr.mock, "GetMaxReceiveStreamFlowControlWindow")
|
||||
}
|
||||
|
||||
func (_m *MockConnectionParametersManager) GetReceiveConnectionFlowControlWindow() protocol.ByteCount {
|
||||
ret := _m.ctrl.Call(_m, "GetReceiveConnectionFlowControlWindow")
|
||||
ret0, _ := ret[0].(protocol.ByteCount)
|
||||
return ret0
|
||||
}
|
||||
|
||||
func (_mr *_MockConnectionParametersManagerRecorder) GetReceiveConnectionFlowControlWindow() *gomock.Call {
|
||||
return _mr.mock.ctrl.RecordCall(_mr.mock, "GetReceiveConnectionFlowControlWindow")
|
||||
}
|
||||
|
||||
func (_m *MockConnectionParametersManager) GetReceiveStreamFlowControlWindow() protocol.ByteCount {
|
||||
ret := _m.ctrl.Call(_m, "GetReceiveStreamFlowControlWindow")
|
||||
ret0, _ := ret[0].(protocol.ByteCount)
|
||||
return ret0
|
||||
}
|
||||
|
||||
func (_mr *_MockConnectionParametersManagerRecorder) GetReceiveStreamFlowControlWindow() *gomock.Call {
|
||||
return _mr.mock.ctrl.RecordCall(_mr.mock, "GetReceiveStreamFlowControlWindow")
|
||||
}
|
||||
|
||||
func (_m *MockConnectionParametersManager) GetSendConnectionFlowControlWindow() protocol.ByteCount {
|
||||
ret := _m.ctrl.Call(_m, "GetSendConnectionFlowControlWindow")
|
||||
ret0, _ := ret[0].(protocol.ByteCount)
|
||||
return ret0
|
||||
}
|
||||
|
||||
func (_mr *_MockConnectionParametersManagerRecorder) GetSendConnectionFlowControlWindow() *gomock.Call {
|
||||
return _mr.mock.ctrl.RecordCall(_mr.mock, "GetSendConnectionFlowControlWindow")
|
||||
}
|
||||
|
||||
func (_m *MockConnectionParametersManager) GetSendStreamFlowControlWindow() protocol.ByteCount {
|
||||
ret := _m.ctrl.Call(_m, "GetSendStreamFlowControlWindow")
|
||||
ret0, _ := ret[0].(protocol.ByteCount)
|
||||
return ret0
|
||||
}
|
||||
|
||||
func (_mr *_MockConnectionParametersManagerRecorder) GetSendStreamFlowControlWindow() *gomock.Call {
|
||||
return _mr.mock.ctrl.RecordCall(_mr.mock, "GetSendStreamFlowControlWindow")
|
||||
}
|
||||
|
||||
func (_m *MockConnectionParametersManager) SetFromMap(_param0 map[handshake.Tag][]byte) error {
|
||||
ret := _m.ctrl.Call(_m, "SetFromMap", _param0)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
func (_mr *_MockConnectionParametersManagerRecorder) SetFromMap(arg0 interface{}) *gomock.Call {
|
||||
return _mr.mock.ctrl.RecordCall(_mr.mock, "SetFromMap", arg0)
|
||||
}
|
||||
|
||||
func (_m *MockConnectionParametersManager) TruncateConnectionID() bool {
|
||||
ret := _m.ctrl.Call(_m, "TruncateConnectionID")
|
||||
ret0, _ := ret[0].(bool)
|
||||
return ret0
|
||||
}
|
||||
|
||||
func (_mr *_MockConnectionParametersManagerRecorder) TruncateConnectionID() *gomock.Call {
|
||||
return _mr.mock.ctrl.RecordCall(_mr.mock, "TruncateConnectionID")
|
||||
}
|
4
vendor/github.com/lucas-clemente/quic-go/internal/mocks/gen.go
generated
vendored
Normal file
4
vendor/github.com/lucas-clemente/quic-go/internal/mocks/gen.go
generated
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
package mocks
|
||||
|
||||
//go:generate mockgen -destination mocks_fc/flow_control_manager.go -package mocks_fc github.com/lucas-clemente/quic-go/flowcontrol FlowControlManager
|
||||
//go:generate mockgen -destination cpm.go -package mocks github.com/lucas-clemente/quic-go/handshake ConnectionParametersManager
|
140
vendor/github.com/lucas-clemente/quic-go/internal/mocks/mocks_fc/flow_control_manager.go
generated
vendored
Normal file
140
vendor/github.com/lucas-clemente/quic-go/internal/mocks/mocks_fc/flow_control_manager.go
generated
vendored
Normal file
|
@ -0,0 +1,140 @@
|
|||
// Automatically generated by MockGen. DO NOT EDIT!
|
||||
// Source: github.com/lucas-clemente/quic-go/flowcontrol (interfaces: FlowControlManager)
|
||||
|
||||
package mocks_fc
|
||||
|
||||
import (
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
flowcontrol "github.com/lucas-clemente/quic-go/flowcontrol"
|
||||
protocol "github.com/lucas-clemente/quic-go/protocol"
|
||||
)
|
||||
|
||||
// Mock of FlowControlManager interface
|
||||
type MockFlowControlManager struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *_MockFlowControlManagerRecorder
|
||||
}
|
||||
|
||||
// Recorder for MockFlowControlManager (not exported)
|
||||
type _MockFlowControlManagerRecorder struct {
|
||||
mock *MockFlowControlManager
|
||||
}
|
||||
|
||||
func NewMockFlowControlManager(ctrl *gomock.Controller) *MockFlowControlManager {
|
||||
mock := &MockFlowControlManager{ctrl: ctrl}
|
||||
mock.recorder = &_MockFlowControlManagerRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
func (_m *MockFlowControlManager) EXPECT() *_MockFlowControlManagerRecorder {
|
||||
return _m.recorder
|
||||
}
|
||||
|
||||
func (_m *MockFlowControlManager) AddBytesRead(_param0 protocol.StreamID, _param1 protocol.ByteCount) error {
|
||||
ret := _m.ctrl.Call(_m, "AddBytesRead", _param0, _param1)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
func (_mr *_MockFlowControlManagerRecorder) AddBytesRead(arg0, arg1 interface{}) *gomock.Call {
|
||||
return _mr.mock.ctrl.RecordCall(_mr.mock, "AddBytesRead", arg0, arg1)
|
||||
}
|
||||
|
||||
func (_m *MockFlowControlManager) AddBytesSent(_param0 protocol.StreamID, _param1 protocol.ByteCount) error {
|
||||
ret := _m.ctrl.Call(_m, "AddBytesSent", _param0, _param1)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
func (_mr *_MockFlowControlManagerRecorder) AddBytesSent(arg0, arg1 interface{}) *gomock.Call {
|
||||
return _mr.mock.ctrl.RecordCall(_mr.mock, "AddBytesSent", arg0, arg1)
|
||||
}
|
||||
|
||||
func (_m *MockFlowControlManager) GetReceiveWindow(_param0 protocol.StreamID) (protocol.ByteCount, error) {
|
||||
ret := _m.ctrl.Call(_m, "GetReceiveWindow", _param0)
|
||||
ret0, _ := ret[0].(protocol.ByteCount)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
func (_mr *_MockFlowControlManagerRecorder) GetReceiveWindow(arg0 interface{}) *gomock.Call {
|
||||
return _mr.mock.ctrl.RecordCall(_mr.mock, "GetReceiveWindow", arg0)
|
||||
}
|
||||
|
||||
func (_m *MockFlowControlManager) GetWindowUpdates() []flowcontrol.WindowUpdate {
|
||||
ret := _m.ctrl.Call(_m, "GetWindowUpdates")
|
||||
ret0, _ := ret[0].([]flowcontrol.WindowUpdate)
|
||||
return ret0
|
||||
}
|
||||
|
||||
func (_mr *_MockFlowControlManagerRecorder) GetWindowUpdates() *gomock.Call {
|
||||
return _mr.mock.ctrl.RecordCall(_mr.mock, "GetWindowUpdates")
|
||||
}
|
||||
|
||||
func (_m *MockFlowControlManager) NewStream(_param0 protocol.StreamID, _param1 bool) {
|
||||
_m.ctrl.Call(_m, "NewStream", _param0, _param1)
|
||||
}
|
||||
|
||||
func (_mr *_MockFlowControlManagerRecorder) NewStream(arg0, arg1 interface{}) *gomock.Call {
|
||||
return _mr.mock.ctrl.RecordCall(_mr.mock, "NewStream", arg0, arg1)
|
||||
}
|
||||
|
||||
func (_m *MockFlowControlManager) RemainingConnectionWindowSize() protocol.ByteCount {
|
||||
ret := _m.ctrl.Call(_m, "RemainingConnectionWindowSize")
|
||||
ret0, _ := ret[0].(protocol.ByteCount)
|
||||
return ret0
|
||||
}
|
||||
|
||||
func (_mr *_MockFlowControlManagerRecorder) RemainingConnectionWindowSize() *gomock.Call {
|
||||
return _mr.mock.ctrl.RecordCall(_mr.mock, "RemainingConnectionWindowSize")
|
||||
}
|
||||
|
||||
func (_m *MockFlowControlManager) RemoveStream(_param0 protocol.StreamID) {
|
||||
_m.ctrl.Call(_m, "RemoveStream", _param0)
|
||||
}
|
||||
|
||||
func (_mr *_MockFlowControlManagerRecorder) RemoveStream(arg0 interface{}) *gomock.Call {
|
||||
return _mr.mock.ctrl.RecordCall(_mr.mock, "RemoveStream", arg0)
|
||||
}
|
||||
|
||||
func (_m *MockFlowControlManager) ResetStream(_param0 protocol.StreamID, _param1 protocol.ByteCount) error {
|
||||
ret := _m.ctrl.Call(_m, "ResetStream", _param0, _param1)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
func (_mr *_MockFlowControlManagerRecorder) ResetStream(arg0, arg1 interface{}) *gomock.Call {
|
||||
return _mr.mock.ctrl.RecordCall(_mr.mock, "ResetStream", arg0, arg1)
|
||||
}
|
||||
|
||||
func (_m *MockFlowControlManager) SendWindowSize(_param0 protocol.StreamID) (protocol.ByteCount, error) {
|
||||
ret := _m.ctrl.Call(_m, "SendWindowSize", _param0)
|
||||
ret0, _ := ret[0].(protocol.ByteCount)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
func (_mr *_MockFlowControlManagerRecorder) SendWindowSize(arg0 interface{}) *gomock.Call {
|
||||
return _mr.mock.ctrl.RecordCall(_mr.mock, "SendWindowSize", arg0)
|
||||
}
|
||||
|
||||
func (_m *MockFlowControlManager) UpdateHighestReceived(_param0 protocol.StreamID, _param1 protocol.ByteCount) error {
|
||||
ret := _m.ctrl.Call(_m, "UpdateHighestReceived", _param0, _param1)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
func (_mr *_MockFlowControlManagerRecorder) UpdateHighestReceived(arg0, arg1 interface{}) *gomock.Call {
|
||||
return _mr.mock.ctrl.RecordCall(_mr.mock, "UpdateHighestReceived", arg0, arg1)
|
||||
}
|
||||
|
||||
func (_m *MockFlowControlManager) UpdateWindow(_param0 protocol.StreamID, _param1 protocol.ByteCount) (bool, error) {
|
||||
ret := _m.ctrl.Call(_m, "UpdateWindow", _param0, _param1)
|
||||
ret0, _ := ret[0].(bool)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
func (_mr *_MockFlowControlManagerRecorder) UpdateWindow(arg0, arg1 interface{}) *gomock.Call {
|
||||
return _mr.mock.ctrl.RecordCall(_mr.mock, "UpdateWindow", arg0, arg1)
|
||||
}
|
|
@ -1,26 +1,26 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
// LogLevel of quic-go
|
||||
type LogLevel uint8
|
||||
|
||||
const (
|
||||
logEnv = "QUIC_GO_LOG_LEVEL"
|
||||
const logEnv = "QUIC_GO_LOG_LEVEL"
|
||||
|
||||
// LogLevelDebug enables debug logs (e.g. packet contents)
|
||||
LogLevelDebug LogLevel = iota
|
||||
// LogLevelInfo enables info logs (e.g. packets)
|
||||
LogLevelInfo
|
||||
const (
|
||||
// LogLevelNothing disables
|
||||
LogLevelNothing LogLevel = iota
|
||||
// LogLevelError enables err logs
|
||||
LogLevelError
|
||||
// LogLevelNothing disables
|
||||
LogLevelNothing
|
||||
// LogLevelInfo enables info logs (e.g. packets)
|
||||
LogLevelInfo
|
||||
// LogLevelDebug enables debug logs (e.g. packet contents)
|
||||
LogLevelDebug
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -49,14 +49,14 @@ func Debugf(format string, args ...interface{}) {
|
|||
|
||||
// Infof logs something
|
||||
func Infof(format string, args ...interface{}) {
|
||||
if logLevel <= LogLevelInfo {
|
||||
if logLevel >= LogLevelInfo {
|
||||
logMessage(format, args...)
|
||||
}
|
||||
}
|
||||
|
||||
// Errorf logs something
|
||||
func Errorf(format string, args ...interface{}) {
|
||||
if logLevel <= LogLevelError {
|
||||
if logLevel >= LogLevelError {
|
||||
logMessage(format, args...)
|
||||
}
|
||||
}
|
||||
|
@ -79,13 +79,16 @@ func init() {
|
|||
}
|
||||
|
||||
func readLoggingEnv() {
|
||||
env := os.Getenv(logEnv)
|
||||
if env == "" {
|
||||
switch os.Getenv(logEnv) {
|
||||
case "":
|
||||
return
|
||||
case "DEBUG":
|
||||
logLevel = LogLevelDebug
|
||||
case "INFO":
|
||||
logLevel = LogLevelInfo
|
||||
case "ERROR":
|
||||
logLevel = LogLevelError
|
||||
default:
|
||||
fmt.Fprintln(os.Stderr, "invalid quic-go log level, see https://github.com/lucas-clemente/quic-go/wiki/Logging")
|
||||
}
|
||||
level, err := strconv.Atoi(env)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
logLevel = LogLevel(level)
|
||||
}
|
43
vendor/github.com/lucas-clemente/quic-go/internal/utils/timer.go
generated
vendored
Normal file
43
vendor/github.com/lucas-clemente/quic-go/internal/utils/timer.go
generated
vendored
Normal file
|
@ -0,0 +1,43 @@
|
|||
package utils
|
||||
|
||||
import "time"
|
||||
|
||||
// A Timer wrapper that behaves correctly when resetting
|
||||
type Timer struct {
|
||||
t *time.Timer
|
||||
read bool
|
||||
deadline time.Time
|
||||
}
|
||||
|
||||
// NewTimer creates a new timer that is not set
|
||||
func NewTimer() *Timer {
|
||||
return &Timer{t: time.NewTimer(0)}
|
||||
}
|
||||
|
||||
// Chan returns the channel of the wrapped timer
|
||||
func (t *Timer) Chan() <-chan time.Time {
|
||||
return t.t.C
|
||||
}
|
||||
|
||||
// Reset the timer, no matter whether the value was read or not
|
||||
func (t *Timer) Reset(deadline time.Time) {
|
||||
if deadline.Equal(t.deadline) {
|
||||
// No need to reset the timer
|
||||
return
|
||||
}
|
||||
|
||||
// We need to drain the timer if the value from its channel was not read yet.
|
||||
// See https://groups.google.com/forum/#!topic/golang-dev/c9UUfASVPoU
|
||||
if !t.t.Stop() && !t.read {
|
||||
<-t.t.C
|
||||
}
|
||||
t.t.Reset(deadline.Sub(time.Now()))
|
||||
|
||||
t.read = false
|
||||
t.deadline = deadline
|
||||
}
|
||||
|
||||
// SetRead should be called after the value from the chan was read
|
||||
func (t *Timer) SetRead() {
|
||||
t.read = true
|
||||
}
|
353
vendor/github.com/lucas-clemente/quic-go/packet_packer.go
generated
vendored
353
vendor/github.com/lucas-clemente/quic-go/packet_packer.go
generated
vendored
|
@ -9,7 +9,6 @@ import (
|
|||
"github.com/lucas-clemente/quic-go/frames"
|
||||
"github.com/lucas-clemente/quic-go/handshake"
|
||||
"github.com/lucas-clemente/quic-go/protocol"
|
||||
"github.com/lucas-clemente/quic-go/qerr"
|
||||
)
|
||||
|
||||
type packedPacket struct {
|
||||
|
@ -24,18 +23,24 @@ type packetPacker struct {
|
|||
perspective protocol.Perspective
|
||||
version protocol.VersionNumber
|
||||
cryptoSetup handshake.CryptoSetup
|
||||
// as long as packets are not sent with forward-secure encryption, we limit the MaxPacketSize such that they can be retransmitted as a whole
|
||||
isForwardSecure bool
|
||||
|
||||
packetNumberGenerator *packetNumberGenerator
|
||||
connectionParameters handshake.ConnectionParametersManager
|
||||
streamFramer *streamFramer
|
||||
|
||||
connectionParameters handshake.ConnectionParametersManager
|
||||
|
||||
streamFramer *streamFramer
|
||||
controlFrames []frames.Frame
|
||||
stopWaiting *frames.StopWaitingFrame
|
||||
ackFrame *frames.AckFrame
|
||||
leastUnacked protocol.PacketNumber
|
||||
}
|
||||
|
||||
func newPacketPacker(connectionID protocol.ConnectionID, cryptoSetup handshake.CryptoSetup, connectionParameters handshake.ConnectionParametersManager, streamFramer *streamFramer, perspective protocol.Perspective, version protocol.VersionNumber) *packetPacker {
|
||||
func newPacketPacker(connectionID protocol.ConnectionID,
|
||||
cryptoSetup handshake.CryptoSetup,
|
||||
connectionParameters handshake.ConnectionParametersManager,
|
||||
streamFramer *streamFramer,
|
||||
perspective protocol.Perspective,
|
||||
version protocol.VersionNumber,
|
||||
) *packetPacker {
|
||||
return &packetPacker{
|
||||
cryptoSetup: cryptoSetup,
|
||||
connectionID: connectionID,
|
||||
|
@ -48,109 +53,91 @@ func newPacketPacker(connectionID protocol.ConnectionID, cryptoSetup handshake.C
|
|||
}
|
||||
|
||||
// PackConnectionClose packs a packet that ONLY contains a ConnectionCloseFrame
|
||||
func (p *packetPacker) PackConnectionClose(ccf *frames.ConnectionCloseFrame, leastUnacked protocol.PacketNumber) (*packedPacket, error) {
|
||||
// in case the connection is closed, all queued control frames aren't of any use anymore
|
||||
// discard them and queue the ConnectionCloseFrame
|
||||
p.controlFrames = []frames.Frame{ccf}
|
||||
return p.packPacket(nil, leastUnacked, nil)
|
||||
func (p *packetPacker) PackConnectionClose(ccf *frames.ConnectionCloseFrame) (*packedPacket, error) {
|
||||
frames := []frames.Frame{ccf}
|
||||
encLevel, sealer := p.cryptoSetup.GetSealer()
|
||||
ph := p.getPublicHeader(encLevel)
|
||||
raw, err := p.writeAndSealPacket(ph, frames, sealer)
|
||||
return &packedPacket{
|
||||
number: ph.PacketNumber,
|
||||
raw: raw,
|
||||
frames: frames,
|
||||
encryptionLevel: encLevel,
|
||||
}, err
|
||||
}
|
||||
|
||||
// RetransmitNonForwardSecurePacket retransmits a handshake packet, that was sent with less than forward-secure encryption
|
||||
func (p *packetPacker) RetransmitNonForwardSecurePacket(stopWaitingFrame *frames.StopWaitingFrame, packet *ackhandler.Packet) (*packedPacket, error) {
|
||||
func (p *packetPacker) PackAckPacket() (*packedPacket, error) {
|
||||
if p.ackFrame == nil {
|
||||
return nil, errors.New("packet packer BUG: no ack frame queued")
|
||||
}
|
||||
encLevel, sealer := p.cryptoSetup.GetSealer()
|
||||
ph := p.getPublicHeader(encLevel)
|
||||
frames := []frames.Frame{p.ackFrame}
|
||||
if p.stopWaiting != nil {
|
||||
p.stopWaiting.PacketNumber = ph.PacketNumber
|
||||
p.stopWaiting.PacketNumberLen = ph.PacketNumberLen
|
||||
frames = append(frames, p.stopWaiting)
|
||||
p.stopWaiting = nil
|
||||
}
|
||||
p.ackFrame = nil
|
||||
raw, err := p.writeAndSealPacket(ph, frames, sealer)
|
||||
return &packedPacket{
|
||||
number: ph.PacketNumber,
|
||||
raw: raw,
|
||||
frames: frames,
|
||||
encryptionLevel: encLevel,
|
||||
}, err
|
||||
}
|
||||
|
||||
// PackHandshakeRetransmission retransmits a handshake packet, that was sent with less than forward-secure encryption
|
||||
func (p *packetPacker) PackHandshakeRetransmission(packet *ackhandler.Packet) (*packedPacket, error) {
|
||||
if packet.EncryptionLevel == protocol.EncryptionForwardSecure {
|
||||
return nil, errors.New("PacketPacker BUG: forward-secure encrypted handshake packets don't need special treatment")
|
||||
}
|
||||
if stopWaitingFrame == nil {
|
||||
return nil, errors.New("PacketPacker BUG: Handshake retransmissions must contain a StopWaitingFrame")
|
||||
}
|
||||
|
||||
return p.packPacket(stopWaitingFrame, 0, packet)
|
||||
}
|
||||
|
||||
// PackPacket packs a new packet
|
||||
// the stopWaitingFrame is *guaranteed* to be included in the next packet
|
||||
// the other controlFrames are sent in the next packet, but might be queued and sent in the next packet if the packet would overflow MaxPacketSize otherwise
|
||||
func (p *packetPacker) PackPacket(stopWaitingFrame *frames.StopWaitingFrame, controlFrames []frames.Frame, leastUnacked protocol.PacketNumber) (*packedPacket, error) {
|
||||
p.controlFrames = append(p.controlFrames, controlFrames...)
|
||||
return p.packPacket(stopWaitingFrame, leastUnacked, nil)
|
||||
}
|
||||
|
||||
func (p *packetPacker) packPacket(stopWaitingFrame *frames.StopWaitingFrame, leastUnacked protocol.PacketNumber, handshakePacketToRetransmit *ackhandler.Packet) (*packedPacket, error) {
|
||||
// handshakePacketToRetransmit is only set for handshake retransmissions
|
||||
isHandshakeRetransmission := (handshakePacketToRetransmit != nil)
|
||||
|
||||
var sealFunc handshake.Sealer
|
||||
var encLevel protocol.EncryptionLevel
|
||||
|
||||
if isHandshakeRetransmission {
|
||||
var err error
|
||||
encLevel = handshakePacketToRetransmit.EncryptionLevel
|
||||
sealFunc, err = p.cryptoSetup.GetSealerWithEncryptionLevel(encLevel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
encLevel, sealFunc = p.cryptoSetup.GetSealer()
|
||||
}
|
||||
|
||||
currentPacketNumber := p.packetNumberGenerator.Peek()
|
||||
packetNumberLen := protocol.GetPacketNumberLengthForPublicHeader(currentPacketNumber, leastUnacked)
|
||||
responsePublicHeader := &PublicHeader{
|
||||
ConnectionID: p.connectionID,
|
||||
PacketNumber: currentPacketNumber,
|
||||
PacketNumberLen: packetNumberLen,
|
||||
TruncateConnectionID: p.connectionParameters.TruncateConnectionID(),
|
||||
}
|
||||
|
||||
if p.perspective == protocol.PerspectiveServer && encLevel == protocol.EncryptionSecure {
|
||||
responsePublicHeader.DiversificationNonce = p.cryptoSetup.DiversificationNonce()
|
||||
}
|
||||
|
||||
if p.perspective == protocol.PerspectiveClient && encLevel != protocol.EncryptionForwardSecure {
|
||||
responsePublicHeader.VersionFlag = true
|
||||
responsePublicHeader.VersionNumber = p.version
|
||||
}
|
||||
|
||||
publicHeaderLength, err := responsePublicHeader.GetLength(p.perspective)
|
||||
sealer, err := p.cryptoSetup.GetSealerWithEncryptionLevel(packet.EncryptionLevel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if p.stopWaiting == nil {
|
||||
return nil, errors.New("PacketPacker BUG: Handshake retransmissions must contain a StopWaitingFrame")
|
||||
}
|
||||
ph := p.getPublicHeader(packet.EncryptionLevel)
|
||||
p.stopWaiting.PacketNumber = ph.PacketNumber
|
||||
p.stopWaiting.PacketNumberLen = ph.PacketNumberLen
|
||||
frames := append([]frames.Frame{p.stopWaiting}, packet.Frames...)
|
||||
p.stopWaiting = nil
|
||||
raw, err := p.writeAndSealPacket(ph, frames, sealer)
|
||||
return &packedPacket{
|
||||
number: ph.PacketNumber,
|
||||
raw: raw,
|
||||
frames: frames,
|
||||
encryptionLevel: packet.EncryptionLevel,
|
||||
}, err
|
||||
}
|
||||
|
||||
if stopWaitingFrame != nil {
|
||||
stopWaitingFrame.PacketNumber = currentPacketNumber
|
||||
stopWaitingFrame.PacketNumberLen = packetNumberLen
|
||||
// PackPacket packs a new packet
|
||||
// the other controlFrames are sent in the next packet, but might be queued and sent in the next packet if the packet would overflow MaxPacketSize otherwise
|
||||
func (p *packetPacker) PackPacket() (*packedPacket, error) {
|
||||
if p.streamFramer.HasCryptoStreamFrame() {
|
||||
return p.packCryptoPacket()
|
||||
}
|
||||
|
||||
// we're packing a ConnectionClose, don't add any StreamFrames
|
||||
var isConnectionClose bool
|
||||
if len(p.controlFrames) == 1 {
|
||||
_, isConnectionClose = p.controlFrames[0].(*frames.ConnectionCloseFrame)
|
||||
encLevel, sealer := p.cryptoSetup.GetSealer()
|
||||
|
||||
publicHeader := p.getPublicHeader(encLevel)
|
||||
publicHeaderLength, err := publicHeader.GetLength(p.perspective)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if p.stopWaiting != nil {
|
||||
p.stopWaiting.PacketNumber = publicHeader.PacketNumber
|
||||
p.stopWaiting.PacketNumberLen = publicHeader.PacketNumberLen
|
||||
}
|
||||
|
||||
var payloadFrames []frames.Frame
|
||||
if isHandshakeRetransmission {
|
||||
payloadFrames = append(payloadFrames, stopWaitingFrame)
|
||||
// don't retransmit Acks and StopWaitings
|
||||
for _, f := range handshakePacketToRetransmit.Frames {
|
||||
switch f.(type) {
|
||||
case *frames.AckFrame:
|
||||
continue
|
||||
case *frames.StopWaitingFrame:
|
||||
continue
|
||||
}
|
||||
payloadFrames = append(payloadFrames, f)
|
||||
}
|
||||
} else if isConnectionClose {
|
||||
payloadFrames = []frames.Frame{p.controlFrames[0]}
|
||||
} else {
|
||||
maxSize := protocol.MaxFrameAndPublicHeaderSize - publicHeaderLength
|
||||
if !p.isForwardSecure {
|
||||
maxSize -= protocol.NonForwardSecurePacketSizeReduction
|
||||
}
|
||||
payloadFrames, err = p.composeNextPacket(stopWaitingFrame, maxSize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
maxSize := protocol.MaxFrameAndPublicHeaderSize - publicHeaderLength
|
||||
payloadFrames, err := p.composeNextPacket(maxSize, p.canSendData(encLevel))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Check if we have enough frames to send
|
||||
|
@ -158,71 +145,76 @@ func (p *packetPacker) packPacket(stopWaitingFrame *frames.StopWaitingFrame, lea
|
|||
return nil, nil
|
||||
}
|
||||
// Don't send out packets that only contain a StopWaitingFrame
|
||||
if len(payloadFrames) == 1 && stopWaitingFrame != nil {
|
||||
if len(payloadFrames) == 1 && p.stopWaiting != nil {
|
||||
return nil, nil
|
||||
}
|
||||
p.stopWaiting = nil
|
||||
p.ackFrame = nil
|
||||
|
||||
raw := getPacketBuffer()
|
||||
buffer := bytes.NewBuffer(raw)
|
||||
|
||||
if err = responsePublicHeader.Write(buffer, p.version, p.perspective); err != nil {
|
||||
raw, err := p.writeAndSealPacket(publicHeader, payloadFrames, sealer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
payloadStartIndex := buffer.Len()
|
||||
|
||||
var hasNonCryptoStreamData bool // does this frame contain any stream frame on a stream > 1
|
||||
for _, frame := range payloadFrames {
|
||||
if sf, ok := frame.(*frames.StreamFrame); ok && sf.StreamID != 1 {
|
||||
hasNonCryptoStreamData = true
|
||||
}
|
||||
err = frame.Write(buffer, p.version)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if protocol.ByteCount(buffer.Len()+12) > protocol.MaxPacketSize {
|
||||
return nil, errors.New("PacketPacker BUG: packet too large")
|
||||
}
|
||||
|
||||
raw = raw[0:buffer.Len()]
|
||||
_ = sealFunc(raw[payloadStartIndex:payloadStartIndex], raw[payloadStartIndex:], currentPacketNumber, raw[:payloadStartIndex])
|
||||
raw = raw[0 : buffer.Len()+12]
|
||||
|
||||
if hasNonCryptoStreamData && encLevel <= protocol.EncryptionUnencrypted {
|
||||
return nil, qerr.AttemptToSendUnencryptedStreamData
|
||||
}
|
||||
|
||||
num := p.packetNumberGenerator.Pop()
|
||||
if num != currentPacketNumber {
|
||||
return nil, errors.New("PacketPacker BUG: Peeked and Popped packet numbers do not match.")
|
||||
}
|
||||
|
||||
return &packedPacket{
|
||||
number: currentPacketNumber,
|
||||
number: publicHeader.PacketNumber,
|
||||
raw: raw,
|
||||
frames: payloadFrames,
|
||||
encryptionLevel: encLevel,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *packetPacker) composeNextPacket(stopWaitingFrame *frames.StopWaitingFrame, maxFrameSize protocol.ByteCount) ([]frames.Frame, error) {
|
||||
func (p *packetPacker) packCryptoPacket() (*packedPacket, error) {
|
||||
encLevel, sealer := p.cryptoSetup.GetSealerForCryptoStream()
|
||||
publicHeader := p.getPublicHeader(encLevel)
|
||||
publicHeaderLength, err := publicHeader.GetLength(p.perspective)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
maxLen := protocol.MaxFrameAndPublicHeaderSize - protocol.NonForwardSecurePacketSizeReduction - publicHeaderLength
|
||||
frames := []frames.Frame{p.streamFramer.PopCryptoStreamFrame(maxLen)}
|
||||
raw, err := p.writeAndSealPacket(publicHeader, frames, sealer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &packedPacket{
|
||||
number: publicHeader.PacketNumber,
|
||||
raw: raw,
|
||||
frames: frames,
|
||||
encryptionLevel: encLevel,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *packetPacker) composeNextPacket(
|
||||
maxFrameSize protocol.ByteCount,
|
||||
canSendStreamFrames bool,
|
||||
) ([]frames.Frame, error) {
|
||||
var payloadLength protocol.ByteCount
|
||||
var payloadFrames []frames.Frame
|
||||
|
||||
if stopWaitingFrame != nil {
|
||||
payloadFrames = append(payloadFrames, stopWaitingFrame)
|
||||
minLength, err := stopWaitingFrame.MinLength(p.version)
|
||||
// STOP_WAITING and ACK will always fit
|
||||
if p.stopWaiting != nil {
|
||||
payloadFrames = append(payloadFrames, p.stopWaiting)
|
||||
l, err := p.stopWaiting.MinLength(p.version)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
payloadLength += minLength
|
||||
payloadLength += l
|
||||
}
|
||||
if p.ackFrame != nil {
|
||||
payloadFrames = append(payloadFrames, p.ackFrame)
|
||||
l, err := p.ackFrame.MinLength(p.version)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
payloadLength += l
|
||||
}
|
||||
|
||||
for len(p.controlFrames) > 0 {
|
||||
frame := p.controlFrames[len(p.controlFrames)-1]
|
||||
minLength, _ := frame.MinLength(p.version) // controlFrames does not contain any StopWaitingFrames. So it will *never* return an error
|
||||
minLength, err := frame.MinLength(p.version)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if payloadLength+minLength > maxFrameSize {
|
||||
break
|
||||
}
|
||||
|
@ -235,6 +227,10 @@ func (p *packetPacker) composeNextPacket(stopWaitingFrame *frames.StopWaitingFra
|
|||
return nil, fmt.Errorf("Packet Packer BUG: packet payload (%d) too large (%d)", payloadLength, maxFrameSize)
|
||||
}
|
||||
|
||||
if !canSendStreamFrames {
|
||||
return payloadFrames, nil
|
||||
}
|
||||
|
||||
// temporarily increase the maxFrameSize by 2 bytes
|
||||
// this leads to a properly sized packet in all cases, since we do all the packet length calculations with StreamFrames that have the DataLen set
|
||||
// however, for the last StreamFrame in the packet, we can omit the DataLen, thus saving 2 bytes and yielding a packet of exactly the correct size
|
||||
|
@ -257,10 +253,79 @@ func (p *packetPacker) composeNextPacket(stopWaitingFrame *frames.StopWaitingFra
|
|||
return payloadFrames, nil
|
||||
}
|
||||
|
||||
func (p *packetPacker) QueueControlFrameForNextPacket(f frames.Frame) {
|
||||
p.controlFrames = append(p.controlFrames, f)
|
||||
func (p *packetPacker) QueueControlFrame(frame frames.Frame) {
|
||||
switch f := frame.(type) {
|
||||
case *frames.StopWaitingFrame:
|
||||
p.stopWaiting = f
|
||||
case *frames.AckFrame:
|
||||
p.ackFrame = f
|
||||
default:
|
||||
p.controlFrames = append(p.controlFrames, f)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *packetPacker) SetForwardSecure() {
|
||||
p.isForwardSecure = true
|
||||
func (p *packetPacker) getPublicHeader(encLevel protocol.EncryptionLevel) *PublicHeader {
|
||||
pnum := p.packetNumberGenerator.Peek()
|
||||
packetNumberLen := protocol.GetPacketNumberLengthForPublicHeader(pnum, p.leastUnacked)
|
||||
publicHeader := &PublicHeader{
|
||||
ConnectionID: p.connectionID,
|
||||
PacketNumber: pnum,
|
||||
PacketNumberLen: packetNumberLen,
|
||||
TruncateConnectionID: p.connectionParameters.TruncateConnectionID(),
|
||||
}
|
||||
|
||||
if p.perspective == protocol.PerspectiveServer && encLevel == protocol.EncryptionSecure {
|
||||
publicHeader.DiversificationNonce = p.cryptoSetup.DiversificationNonce()
|
||||
}
|
||||
if p.perspective == protocol.PerspectiveClient && encLevel != protocol.EncryptionForwardSecure {
|
||||
publicHeader.VersionFlag = true
|
||||
publicHeader.VersionNumber = p.version
|
||||
}
|
||||
|
||||
return publicHeader
|
||||
}
|
||||
|
||||
func (p *packetPacker) writeAndSealPacket(
|
||||
publicHeader *PublicHeader,
|
||||
payloadFrames []frames.Frame,
|
||||
sealer handshake.Sealer,
|
||||
) ([]byte, error) {
|
||||
raw := getPacketBuffer()
|
||||
buffer := bytes.NewBuffer(raw)
|
||||
|
||||
if err := publicHeader.Write(buffer, p.version, p.perspective); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
payloadStartIndex := buffer.Len()
|
||||
for _, frame := range payloadFrames {
|
||||
err := frame.Write(buffer, p.version)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if protocol.ByteCount(buffer.Len()+12) > protocol.MaxPacketSize {
|
||||
return nil, errors.New("PacketPacker BUG: packet too large")
|
||||
}
|
||||
|
||||
raw = raw[0:buffer.Len()]
|
||||
_ = sealer(raw[payloadStartIndex:payloadStartIndex], raw[payloadStartIndex:], publicHeader.PacketNumber, raw[:payloadStartIndex])
|
||||
raw = raw[0 : buffer.Len()+12]
|
||||
|
||||
num := p.packetNumberGenerator.Pop()
|
||||
if num != publicHeader.PacketNumber {
|
||||
return nil, errors.New("packetPacker BUG: Peeked and Popped packet numbers do not match")
|
||||
}
|
||||
|
||||
return raw, nil
|
||||
}
|
||||
|
||||
func (p *packetPacker) canSendData(encLevel protocol.EncryptionLevel) bool {
|
||||
if p.perspective == protocol.PerspectiveClient {
|
||||
return encLevel >= protocol.EncryptionSecure
|
||||
}
|
||||
return encLevel == protocol.EncryptionForwardSecure
|
||||
}
|
||||
|
||||
func (p *packetPacker) SetLeastUnacked(leastUnacked protocol.PacketNumber) {
|
||||
p.leastUnacked = leastUnacked
|
||||
}
|
||||
|
|
5
vendor/github.com/lucas-clemente/quic-go/packet_unpacker.go
generated
vendored
5
vendor/github.com/lucas-clemente/quic-go/packet_unpacker.go
generated
vendored
|
@ -10,6 +10,11 @@ import (
|
|||
"github.com/lucas-clemente/quic-go/qerr"
|
||||
)
|
||||
|
||||
type unpackedPacket struct {
|
||||
encryptionLevel protocol.EncryptionLevel
|
||||
frames []frames.Frame
|
||||
}
|
||||
|
||||
type quicAEAD interface {
|
||||
Open(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, protocol.EncryptionLevel, error)
|
||||
}
|
||||
|
|
2
vendor/github.com/lucas-clemente/quic-go/protocol/protocol.go
generated
vendored
2
vendor/github.com/lucas-clemente/quic-go/protocol/protocol.go
generated
vendored
|
@ -31,7 +31,7 @@ type StreamID uint32
|
|||
type ByteCount uint64
|
||||
|
||||
// MaxByteCount is the maximum value of a ByteCount
|
||||
const MaxByteCount = math.MaxUint64
|
||||
const MaxByteCount = ByteCount(math.MaxUint64)
|
||||
|
||||
// MaxReceivePacketSize maximum packet size of any QUIC packet, based on
|
||||
// ethernet's max size, minus the IP and UDP headers. IPv6 has a 40 byte header,
|
||||
|
|
20
vendor/github.com/lucas-clemente/quic-go/protocol/server_parameters.go
generated
vendored
20
vendor/github.com/lucas-clemente/quic-go/protocol/server_parameters.go
generated
vendored
|
@ -39,21 +39,21 @@ const ReceiveStreamFlowControlWindow ByteCount = (1 << 10) * 32 // 32 kB
|
|||
// This is the value that Google servers are using
|
||||
const ReceiveConnectionFlowControlWindow ByteCount = (1 << 10) * 48 // 48 kB
|
||||
|
||||
// MaxReceiveStreamFlowControlWindowServer is the maximum stream-level flow control window for receiving data
|
||||
// DefaultMaxReceiveStreamFlowControlWindowServer is the default maximum stream-level flow control window for receiving data, for the server
|
||||
// This is the value that Google servers are using
|
||||
const MaxReceiveStreamFlowControlWindowServer ByteCount = 1 * (1 << 20) // 1 MB
|
||||
const DefaultMaxReceiveStreamFlowControlWindowServer ByteCount = 1 * (1 << 20) // 1 MB
|
||||
|
||||
// MaxReceiveConnectionFlowControlWindowServer is the connection-level flow control window for receiving data
|
||||
// DefaultMaxReceiveConnectionFlowControlWindowServer is the default connection-level flow control window for receiving data, for the server
|
||||
// This is the value that Google servers are using
|
||||
const MaxReceiveConnectionFlowControlWindowServer ByteCount = 1.5 * (1 << 20) // 1.5 MB
|
||||
const DefaultMaxReceiveConnectionFlowControlWindowServer ByteCount = 1.5 * (1 << 20) // 1.5 MB
|
||||
|
||||
// MaxReceiveStreamFlowControlWindowClient is the maximum stream-level flow control window for receiving data, for the client
|
||||
// DefaultMaxReceiveStreamFlowControlWindowClient is the default maximum stream-level flow control window for receiving data, for the client
|
||||
// This is the value that Chromium is using
|
||||
const MaxReceiveStreamFlowControlWindowClient ByteCount = 6 * (1 << 20) // 6 MB
|
||||
const DefaultMaxReceiveStreamFlowControlWindowClient ByteCount = 6 * (1 << 20) // 6 MB
|
||||
|
||||
// MaxReceiveConnectionFlowControlWindowClient is the connection-level flow control window for receiving data, for the server
|
||||
// DefaultMaxReceiveConnectionFlowControlWindowClient is the default connection-level flow control window for receiving data, for the client
|
||||
// This is the value that Google servers are using
|
||||
const MaxReceiveConnectionFlowControlWindowClient ByteCount = 15 * (1 << 20) // 15 MB
|
||||
const DefaultMaxReceiveConnectionFlowControlWindowClient ByteCount = 15 * (1 << 20) // 15 MB
|
||||
|
||||
// ConnectionFlowControlMultiplier determines how much larger the connection flow control windows needs to be relative to any stream's flow control window
|
||||
// This is the value that Chromium is using
|
||||
|
@ -128,8 +128,8 @@ const MaxIdleTimeoutServer = 1 * time.Minute
|
|||
// MaxIdleTimeoutClient is the idle timeout that the client suggests to the server
|
||||
const MaxIdleTimeoutClient = 2 * time.Minute
|
||||
|
||||
// MaxTimeForCryptoHandshake is the default timeout for a connection until the crypto handshake succeeds.
|
||||
const MaxTimeForCryptoHandshake = 10 * time.Second
|
||||
// DefaultHandshakeTimeout is the default timeout for a connection until the crypto handshake succeeds.
|
||||
const DefaultHandshakeTimeout = 10 * time.Second
|
||||
|
||||
// ClosedSessionDeleteTimeout the server ignores packets arriving on a connection that is already closed
|
||||
// after this time all information about the old connection will be deleted
|
||||
|
|
2
vendor/github.com/lucas-clemente/quic-go/public_header.go
generated
vendored
2
vendor/github.com/lucas-clemente/quic-go/public_header.go
generated
vendored
|
@ -4,9 +4,9 @@ import (
|
|||
"bytes"
|
||||
"errors"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/protocol"
|
||||
"github.com/lucas-clemente/quic-go/qerr"
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
2
vendor/github.com/lucas-clemente/quic-go/public_reset.go
generated
vendored
2
vendor/github.com/lucas-clemente/quic-go/public_reset.go
generated
vendored
|
@ -6,8 +6,8 @@ import (
|
|||
"errors"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/handshake"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/protocol"
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
)
|
||||
|
||||
type publicReset struct {
|
||||
|
|
12
vendor/github.com/lucas-clemente/quic-go/qerr/quic_error.go
generated
vendored
12
vendor/github.com/lucas-clemente/quic-go/qerr/quic_error.go
generated
vendored
|
@ -3,7 +3,7 @@ package qerr
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
)
|
||||
|
||||
// ErrorCode can be used as a normal error without reason.
|
||||
|
@ -31,6 +31,16 @@ func (e *QuicError) Error() string {
|
|||
return fmt.Sprintf("%s: %s", e.ErrorCode.String(), e.ErrorMessage)
|
||||
}
|
||||
|
||||
func (e *QuicError) Timeout() bool {
|
||||
switch e.ErrorCode {
|
||||
case NetworkIdleTimeout,
|
||||
HandshakeTimeout,
|
||||
TimeoutsWithOpenStreams:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ToQuicError converts an arbitrary error to a QuicError. It leaves QuicErrors
|
||||
// unchanged, and properly handles `ErrorCode`s.
|
||||
func ToQuicError(err error) *QuicError {
|
||||
|
|
49
vendor/github.com/lucas-clemente/quic-go/server.go
generated
vendored
49
vendor/github.com/lucas-clemente/quic-go/server.go
generated
vendored
|
@ -2,6 +2,7 @@ package quic
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"net"
|
||||
"sync"
|
||||
|
@ -9,9 +10,9 @@ import (
|
|||
|
||||
"github.com/lucas-clemente/quic-go/crypto"
|
||||
"github.com/lucas-clemente/quic-go/handshake"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/protocol"
|
||||
"github.com/lucas-clemente/quic-go/qerr"
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
)
|
||||
|
||||
// packetHandler handles packets
|
||||
|
@ -19,11 +20,13 @@ type packetHandler interface {
|
|||
Session
|
||||
handlePacket(*receivedPacket)
|
||||
run() error
|
||||
closeRemote(error)
|
||||
}
|
||||
|
||||
// A Listener of QUIC
|
||||
type server struct {
|
||||
config *Config
|
||||
tlsConf *tls.Config
|
||||
config *Config
|
||||
|
||||
conn net.PacketConn
|
||||
|
||||
|
@ -38,14 +41,15 @@ type server struct {
|
|||
sessionQueue chan Session
|
||||
errorChan chan struct{}
|
||||
|
||||
newSession func(conn connection, v protocol.VersionNumber, connectionID protocol.ConnectionID, sCfg *handshake.ServerConfig, config *Config) (packetHandler, <-chan handshakeEvent, error)
|
||||
newSession func(conn connection, v protocol.VersionNumber, connectionID protocol.ConnectionID, sCfg *handshake.ServerConfig, tlsConf *tls.Config, config *Config) (packetHandler, <-chan handshakeEvent, error)
|
||||
}
|
||||
|
||||
var _ Listener = &server{}
|
||||
|
||||
// ListenAddr creates a QUIC server listening on a given address.
|
||||
// The listener is not active until Serve() is called.
|
||||
func ListenAddr(addr string, config *Config) (Listener, error) {
|
||||
// The tls.Config must not be nil, the quic.Config may be nil.
|
||||
func ListenAddr(addr string, tlsConf *tls.Config, config *Config) (Listener, error) {
|
||||
udpAddr, err := net.ResolveUDPAddr("udp", addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -54,13 +58,14 @@ func ListenAddr(addr string, config *Config) (Listener, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return Listen(conn, config)
|
||||
return Listen(conn, tlsConf, config)
|
||||
}
|
||||
|
||||
// Listen listens for QUIC connections on a given net.PacketConn.
|
||||
// The listener is not active until Serve() is called.
|
||||
func Listen(conn net.PacketConn, config *Config) (Listener, error) {
|
||||
certChain := crypto.NewCertChain(config.TLSConfig)
|
||||
// The tls.Config must not be nil, the quic.Config may be nil.
|
||||
func Listen(conn net.PacketConn, tlsConf *tls.Config, config *Config) (Listener, error) {
|
||||
certChain := crypto.NewCertChain(tlsConf)
|
||||
kex, err := crypto.NewCurve25519KEX()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -72,6 +77,7 @@ func Listen(conn net.PacketConn, config *Config) (Listener, error) {
|
|||
|
||||
s := &server{
|
||||
conn: conn,
|
||||
tlsConf: tlsConf,
|
||||
config: populateServerConfig(config),
|
||||
certChain: certChain,
|
||||
scfg: scfg,
|
||||
|
@ -101,20 +107,42 @@ var defaultAcceptSTK = func(clientAddr net.Addr, stk *STK) bool {
|
|||
return sourceAddr == stk.remoteAddr
|
||||
}
|
||||
|
||||
// populateServerConfig populates fields in the quic.Config with their default values, if none are set
|
||||
// it may be called with nil
|
||||
func populateServerConfig(config *Config) *Config {
|
||||
if config == nil {
|
||||
config = &Config{}
|
||||
}
|
||||
versions := config.Versions
|
||||
if len(versions) == 0 {
|
||||
versions = protocol.SupportedVersions
|
||||
}
|
||||
|
||||
vsa := defaultAcceptSTK
|
||||
if config.AcceptSTK != nil {
|
||||
vsa = config.AcceptSTK
|
||||
}
|
||||
|
||||
handshakeTimeout := protocol.DefaultHandshakeTimeout
|
||||
if config.HandshakeTimeout != 0 {
|
||||
handshakeTimeout = config.HandshakeTimeout
|
||||
}
|
||||
|
||||
maxReceiveStreamFlowControlWindow := config.MaxReceiveStreamFlowControlWindow
|
||||
if maxReceiveStreamFlowControlWindow == 0 {
|
||||
maxReceiveStreamFlowControlWindow = protocol.DefaultMaxReceiveStreamFlowControlWindowServer
|
||||
}
|
||||
maxReceiveConnectionFlowControlWindow := config.MaxReceiveConnectionFlowControlWindow
|
||||
if maxReceiveConnectionFlowControlWindow == 0 {
|
||||
maxReceiveConnectionFlowControlWindow = protocol.DefaultMaxReceiveConnectionFlowControlWindowServer
|
||||
}
|
||||
|
||||
return &Config{
|
||||
TLSConfig: config.TLSConfig,
|
||||
Versions: versions,
|
||||
AcceptSTK: vsa,
|
||||
Versions: versions,
|
||||
HandshakeTimeout: handshakeTimeout,
|
||||
AcceptSTK: vsa,
|
||||
MaxReceiveStreamFlowControlWindow: maxReceiveStreamFlowControlWindow,
|
||||
MaxReceiveConnectionFlowControlWindow: maxReceiveConnectionFlowControlWindow,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -238,6 +266,7 @@ func (s *server) handlePacket(pconn net.PacketConn, remoteAddr net.Addr, packet
|
|||
version,
|
||||
hdr.ConnectionID,
|
||||
s.scfg,
|
||||
s.tlsConf,
|
||||
s.config,
|
||||
)
|
||||
if err != nil {
|
||||
|
|
460
vendor/github.com/lucas-clemente/quic-go/session.go
generated
vendored
460
vendor/github.com/lucas-clemente/quic-go/session.go
generated
vendored
|
@ -1,10 +1,11 @@
|
|||
package quic
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"sync/atomic"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/ackhandler"
|
||||
|
@ -12,9 +13,9 @@ import (
|
|||
"github.com/lucas-clemente/quic-go/flowcontrol"
|
||||
"github.com/lucas-clemente/quic-go/frames"
|
||||
"github.com/lucas-clemente/quic-go/handshake"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/protocol"
|
||||
"github.com/lucas-clemente/quic-go/qerr"
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
)
|
||||
|
||||
type unpacker interface {
|
||||
|
@ -31,7 +32,6 @@ type receivedPacket struct {
|
|||
var (
|
||||
errRstStreamOnInvalidStream = errors.New("RST_STREAM received for unknown stream")
|
||||
errWindowUpdateOnClosedStream = errors.New("WINDOW_UPDATE received for an already closed stream")
|
||||
errSessionAlreadyClosed = errors.New("cannot close session; it was already closed before")
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -54,6 +54,7 @@ type session struct {
|
|||
connectionID protocol.ConnectionID
|
||||
perspective protocol.Perspective
|
||||
version protocol.VersionNumber
|
||||
tlsConf *tls.Config
|
||||
config *Config
|
||||
|
||||
conn connection
|
||||
|
@ -77,8 +78,10 @@ type session struct {
|
|||
sendingScheduled chan struct{}
|
||||
// closeChan is used to notify the run loop that it should terminate.
|
||||
closeChan chan closeError
|
||||
// runClosed is closed once the run loop exits
|
||||
// it is used to block Close() and WaitUntilClosed()
|
||||
runClosed chan struct{}
|
||||
closed uint32 // atomic bool
|
||||
closeOnce sync.Once
|
||||
|
||||
// when we receive too many undecryptable packets during the handshake, we send a Public reset
|
||||
// but only after a time of protocol.PublicResetTimeout has passed
|
||||
|
@ -97,8 +100,6 @@ type session struct {
|
|||
// it receives at most 3 handshake events: 2 when the encryption level changes, and one error
|
||||
handshakeChan chan<- handshakeEvent
|
||||
|
||||
nextAckScheduledTime time.Time
|
||||
|
||||
connectionParameters handshake.ConnectionParametersManager
|
||||
|
||||
lastRcvdPacketNumber protocol.PacketNumber
|
||||
|
@ -109,9 +110,10 @@ type session struct {
|
|||
sessionCreationTime time.Time
|
||||
lastNetworkActivityTime time.Time
|
||||
|
||||
timer *time.Timer
|
||||
currentDeadline time.Time
|
||||
timerRead bool
|
||||
timer *utils.Timer
|
||||
// keepAlivePingSent stores whether a Ping frame was sent to the peer or not
|
||||
// it is reset as soon as we receive a packet from the peer
|
||||
keepAlivePingSent bool
|
||||
}
|
||||
|
||||
var _ Session = &session{}
|
||||
|
@ -122,6 +124,7 @@ func newSession(
|
|||
v protocol.VersionNumber,
|
||||
connectionID protocol.ConnectionID,
|
||||
sCfg *handshake.ServerConfig,
|
||||
tlsConf *tls.Config,
|
||||
config *Config,
|
||||
) (packetHandler, <-chan handshakeEvent, error) {
|
||||
s := &session{
|
||||
|
@ -130,46 +133,8 @@ func newSession(
|
|||
perspective: protocol.PerspectiveServer,
|
||||
version: v,
|
||||
config: config,
|
||||
|
||||
connectionParameters: handshake.NewConnectionParamatersManager(protocol.PerspectiveServer, v),
|
||||
}
|
||||
|
||||
s.setup()
|
||||
cryptoStream, _ := s.GetOrOpenStream(1)
|
||||
_, _ = s.AcceptStream() // don't expose the crypto stream
|
||||
aeadChanged := make(chan protocol.EncryptionLevel, 2)
|
||||
s.aeadChanged = aeadChanged
|
||||
handshakeChan := make(chan handshakeEvent, 3)
|
||||
s.handshakeChan = handshakeChan
|
||||
verifySourceAddr := func(clientAddr net.Addr, hstk *handshake.STK) bool {
|
||||
if hstk == nil {
|
||||
return config.AcceptSTK(clientAddr, nil)
|
||||
}
|
||||
return config.AcceptSTK(
|
||||
clientAddr,
|
||||
&STK{remoteAddr: hstk.RemoteAddr, sentTime: hstk.SentTime},
|
||||
)
|
||||
}
|
||||
var err error
|
||||
s.cryptoSetup, err = newCryptoSetup(
|
||||
connectionID,
|
||||
conn.RemoteAddr(),
|
||||
v,
|
||||
sCfg,
|
||||
cryptoStream,
|
||||
s.connectionParameters,
|
||||
config.Versions,
|
||||
verifySourceAddr,
|
||||
aeadChanged,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
s.packer = newPacketPacker(connectionID, s.cryptoSetup, s.connectionParameters, s.streamFramer, s.perspective, s.version)
|
||||
s.unpacker = &packetUnpacker{aead: s.cryptoSetup, version: s.version}
|
||||
|
||||
return s, handshakeChan, err
|
||||
return s.setup(sCfg, "", nil)
|
||||
}
|
||||
|
||||
// declare this as a variable, such that we can it mock it in the tests
|
||||
|
@ -178,6 +143,7 @@ var newClientSession = func(
|
|||
hostname string,
|
||||
v protocol.VersionNumber,
|
||||
connectionID protocol.ConnectionID,
|
||||
tlsConf *tls.Config,
|
||||
config *Config,
|
||||
negotiatedVersions []protocol.VersionNumber,
|
||||
) (packetHandler, <-chan handshakeEvent, error) {
|
||||
|
@ -186,68 +152,92 @@ var newClientSession = func(
|
|||
connectionID: connectionID,
|
||||
perspective: protocol.PerspectiveClient,
|
||||
version: v,
|
||||
tlsConf: tlsConf,
|
||||
config: config,
|
||||
|
||||
connectionParameters: handshake.NewConnectionParamatersManager(protocol.PerspectiveClient, v),
|
||||
}
|
||||
return s.setup(nil, hostname, negotiatedVersions)
|
||||
}
|
||||
|
||||
s.receivedPacketHandler = ackhandler.NewReceivedPacketHandler(s.ackAlarmChanged)
|
||||
s.setup()
|
||||
|
||||
func (s *session) setup(
|
||||
scfg *handshake.ServerConfig,
|
||||
hostname string,
|
||||
negotiatedVersions []protocol.VersionNumber,
|
||||
) (packetHandler, <-chan handshakeEvent, error) {
|
||||
aeadChanged := make(chan protocol.EncryptionLevel, 2)
|
||||
s.aeadChanged = aeadChanged
|
||||
handshakeChan := make(chan handshakeEvent, 3)
|
||||
s.handshakeChan = handshakeChan
|
||||
cryptoStream, _ := s.OpenStream()
|
||||
var err error
|
||||
s.cryptoSetup, err = newCryptoSetupClient(
|
||||
hostname,
|
||||
connectionID,
|
||||
v,
|
||||
cryptoStream,
|
||||
config.TLSConfig,
|
||||
s.connectionParameters,
|
||||
aeadChanged,
|
||||
&handshake.TransportParameters{RequestConnectionIDTruncation: config.RequestConnectionIDTruncation},
|
||||
negotiatedVersions,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
s.packer = newPacketPacker(connectionID, s.cryptoSetup, s.connectionParameters, s.streamFramer, s.perspective, s.version)
|
||||
s.unpacker = &packetUnpacker{aead: s.cryptoSetup, version: s.version}
|
||||
|
||||
return s, handshakeChan, err
|
||||
}
|
||||
|
||||
// setup is called from newSession and newClientSession and initializes values that are independent of the perspective
|
||||
func (s *session) setup() {
|
||||
s.rttStats = &congestion.RTTStats{}
|
||||
flowControlManager := flowcontrol.NewFlowControlManager(s.connectionParameters, s.rttStats)
|
||||
|
||||
sentPacketHandler := ackhandler.NewSentPacketHandler(s.rttStats)
|
||||
|
||||
now := time.Now()
|
||||
|
||||
s.sentPacketHandler = sentPacketHandler
|
||||
s.flowControlManager = flowControlManager
|
||||
s.receivedPacketHandler = ackhandler.NewReceivedPacketHandler(s.ackAlarmChanged)
|
||||
|
||||
s.runClosed = make(chan struct{})
|
||||
s.handshakeCompleteChan = make(chan error, 1)
|
||||
s.receivedPackets = make(chan *receivedPacket, protocol.MaxSessionUnprocessedPackets)
|
||||
s.closeChan = make(chan closeError, 1)
|
||||
s.sendingScheduled = make(chan struct{}, 1)
|
||||
s.undecryptablePackets = make([]*receivedPacket, 0, protocol.MaxUndecryptablePackets)
|
||||
s.aeadChanged = make(chan protocol.EncryptionLevel, 2)
|
||||
s.runClosed = make(chan struct{})
|
||||
s.handshakeCompleteChan = make(chan error, 1)
|
||||
|
||||
s.timer = time.NewTimer(0)
|
||||
s.timer = utils.NewTimer()
|
||||
now := time.Now()
|
||||
s.lastNetworkActivityTime = now
|
||||
s.sessionCreationTime = now
|
||||
|
||||
s.rttStats = &congestion.RTTStats{}
|
||||
s.connectionParameters = handshake.NewConnectionParamatersManager(s.perspective, s.version,
|
||||
s.config.MaxReceiveStreamFlowControlWindow, s.config.MaxReceiveConnectionFlowControlWindow)
|
||||
s.sentPacketHandler = ackhandler.NewSentPacketHandler(s.rttStats)
|
||||
s.flowControlManager = flowcontrol.NewFlowControlManager(s.connectionParameters, s.rttStats)
|
||||
s.receivedPacketHandler = ackhandler.NewReceivedPacketHandler()
|
||||
s.streamsMap = newStreamsMap(s.newStream, s.perspective, s.connectionParameters)
|
||||
s.streamFramer = newStreamFramer(s.streamsMap, s.flowControlManager)
|
||||
|
||||
var err error
|
||||
if s.perspective == protocol.PerspectiveServer {
|
||||
cryptoStream, _ := s.GetOrOpenStream(1)
|
||||
_, _ = s.AcceptStream() // don't expose the crypto stream
|
||||
verifySourceAddr := func(clientAddr net.Addr, hstk *handshake.STK) bool {
|
||||
var stk *STK
|
||||
if hstk != nil {
|
||||
stk = &STK{remoteAddr: hstk.RemoteAddr, sentTime: hstk.SentTime}
|
||||
}
|
||||
return s.config.AcceptSTK(clientAddr, stk)
|
||||
}
|
||||
s.cryptoSetup, err = newCryptoSetup(
|
||||
s.connectionID,
|
||||
s.conn.RemoteAddr(),
|
||||
s.version,
|
||||
scfg,
|
||||
cryptoStream,
|
||||
s.connectionParameters,
|
||||
s.config.Versions,
|
||||
verifySourceAddr,
|
||||
aeadChanged,
|
||||
)
|
||||
} else {
|
||||
cryptoStream, _ := s.OpenStream()
|
||||
s.cryptoSetup, err = newCryptoSetupClient(
|
||||
hostname,
|
||||
s.connectionID,
|
||||
s.version,
|
||||
cryptoStream,
|
||||
s.tlsConf,
|
||||
s.connectionParameters,
|
||||
aeadChanged,
|
||||
&handshake.TransportParameters{RequestConnectionIDTruncation: s.config.RequestConnectionIDTruncation},
|
||||
negotiatedVersions,
|
||||
)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
s.packer = newPacketPacker(s.connectionID,
|
||||
s.cryptoSetup,
|
||||
s.connectionParameters,
|
||||
s.streamFramer,
|
||||
s.perspective,
|
||||
s.version,
|
||||
)
|
||||
s.unpacker = &packetUnpacker{aead: s.cryptoSetup, version: s.version}
|
||||
|
||||
return s, handshakeChan, nil
|
||||
}
|
||||
|
||||
// run the session main loop
|
||||
|
@ -276,8 +266,8 @@ runLoop:
|
|||
select {
|
||||
case closeErr = <-s.closeChan:
|
||||
break runLoop
|
||||
case <-s.timer.C:
|
||||
s.timerRead = true
|
||||
case <-s.timer.Chan():
|
||||
s.timer.SetRead()
|
||||
// We do all the interesting stuff after the switch statement, so
|
||||
// nothing to see here.
|
||||
case <-s.sendingScheduled:
|
||||
|
@ -290,7 +280,7 @@ runLoop:
|
|||
s.tryQueueingUndecryptablePacket(p)
|
||||
continue
|
||||
}
|
||||
s.close(err)
|
||||
s.closeLocal(err)
|
||||
continue
|
||||
}
|
||||
// This is a bit unclean, but works properly, since the packet always
|
||||
|
@ -303,32 +293,35 @@ runLoop:
|
|||
close(s.handshakeChan)
|
||||
close(s.handshakeCompleteChan)
|
||||
} else {
|
||||
if l == protocol.EncryptionForwardSecure {
|
||||
s.packer.SetForwardSecure()
|
||||
}
|
||||
s.tryDecryptingQueuedPackets()
|
||||
s.handshakeChan <- handshakeEvent{encLevel: l}
|
||||
}
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
if s.sentPacketHandler.GetAlarmTimeout().Before(now) {
|
||||
if timeout := s.sentPacketHandler.GetAlarmTimeout(); !timeout.IsZero() && timeout.Before(now) {
|
||||
// This could cause packets to be retransmitted, so check it before trying
|
||||
// to send packets.
|
||||
s.sentPacketHandler.OnAlarm()
|
||||
}
|
||||
|
||||
if s.config.KeepAlive && s.handshakeComplete && time.Since(s.lastNetworkActivityTime) >= s.idleTimeout()/2 {
|
||||
// send the PING frame since there is no activity in the session
|
||||
s.packer.QueueControlFrame(&frames.PingFrame{})
|
||||
s.keepAlivePingSent = true
|
||||
}
|
||||
|
||||
if err := s.sendPacket(); err != nil {
|
||||
s.close(err)
|
||||
s.closeLocal(err)
|
||||
}
|
||||
if !s.receivedTooManyUndecrytablePacketsTime.IsZero() && s.receivedTooManyUndecrytablePacketsTime.Add(protocol.PublicResetTimeout).Before(now) && len(s.undecryptablePackets) != 0 {
|
||||
s.close(qerr.Error(qerr.DecryptionFailure, "too many undecryptable packets received"))
|
||||
s.closeLocal(qerr.Error(qerr.DecryptionFailure, "too many undecryptable packets received"))
|
||||
}
|
||||
if now.Sub(s.lastNetworkActivityTime) >= s.idleTimeout() {
|
||||
s.close(qerr.Error(qerr.NetworkIdleTimeout, "No recent network activity."))
|
||||
s.closeLocal(qerr.Error(qerr.NetworkIdleTimeout, "No recent network activity."))
|
||||
}
|
||||
if !s.handshakeComplete && now.Sub(s.sessionCreationTime) >= protocol.MaxTimeForCryptoHandshake {
|
||||
s.close(qerr.Error(qerr.NetworkIdleTimeout, "Crypto handshake did not complete in time."))
|
||||
if !s.handshakeComplete && now.Sub(s.sessionCreationTime) >= s.config.HandshakeTimeout {
|
||||
s.closeLocal(qerr.Error(qerr.HandshakeTimeout, "Crypto handshake did not complete in time."))
|
||||
}
|
||||
s.garbageCollectStreams()
|
||||
}
|
||||
|
@ -344,37 +337,33 @@ runLoop:
|
|||
return closeErr.err
|
||||
}
|
||||
|
||||
func (s *session) maybeResetTimer() {
|
||||
nextDeadline := s.lastNetworkActivityTime.Add(s.idleTimeout())
|
||||
func (s *session) WaitUntilClosed() {
|
||||
<-s.runClosed
|
||||
}
|
||||
|
||||
if !s.nextAckScheduledTime.IsZero() {
|
||||
nextDeadline = utils.MinTime(nextDeadline, s.nextAckScheduledTime)
|
||||
func (s *session) maybeResetTimer() {
|
||||
var deadline time.Time
|
||||
if s.config.KeepAlive && s.handshakeComplete && !s.keepAlivePingSent {
|
||||
deadline = s.lastNetworkActivityTime.Add(s.idleTimeout() / 2)
|
||||
} else {
|
||||
deadline = s.lastNetworkActivityTime.Add(s.idleTimeout())
|
||||
}
|
||||
|
||||
if ackAlarm := s.receivedPacketHandler.GetAlarmTimeout(); !ackAlarm.IsZero() {
|
||||
deadline = utils.MinTime(deadline, ackAlarm)
|
||||
}
|
||||
if lossTime := s.sentPacketHandler.GetAlarmTimeout(); !lossTime.IsZero() {
|
||||
nextDeadline = utils.MinTime(nextDeadline, lossTime)
|
||||
deadline = utils.MinTime(deadline, lossTime)
|
||||
}
|
||||
if !s.handshakeComplete {
|
||||
handshakeDeadline := s.sessionCreationTime.Add(protocol.MaxTimeForCryptoHandshake)
|
||||
nextDeadline = utils.MinTime(nextDeadline, handshakeDeadline)
|
||||
handshakeDeadline := s.sessionCreationTime.Add(s.config.HandshakeTimeout)
|
||||
deadline = utils.MinTime(deadline, handshakeDeadline)
|
||||
}
|
||||
if !s.receivedTooManyUndecrytablePacketsTime.IsZero() {
|
||||
nextDeadline = utils.MinTime(nextDeadline, s.receivedTooManyUndecrytablePacketsTime.Add(protocol.PublicResetTimeout))
|
||||
deadline = utils.MinTime(deadline, s.receivedTooManyUndecrytablePacketsTime.Add(protocol.PublicResetTimeout))
|
||||
}
|
||||
|
||||
if nextDeadline.Equal(s.currentDeadline) {
|
||||
// No need to reset the timer
|
||||
return
|
||||
}
|
||||
|
||||
// We need to drain the timer if the value from its channel was not read yet.
|
||||
// See https://groups.google.com/forum/#!topic/golang-dev/c9UUfASVPoU
|
||||
if !s.timer.Stop() && !s.timerRead {
|
||||
<-s.timer.C
|
||||
}
|
||||
s.timer.Reset(nextDeadline.Sub(time.Now()))
|
||||
|
||||
s.timerRead = false
|
||||
s.currentDeadline = nextDeadline
|
||||
s.timer.Reset(deadline)
|
||||
}
|
||||
|
||||
func (s *session) idleTimeout() time.Duration {
|
||||
|
@ -398,6 +387,7 @@ func (s *session) handlePacketImpl(p *receivedPacket) error {
|
|||
}
|
||||
|
||||
s.lastNetworkActivityTime = p.rcvTime
|
||||
s.keepAlivePingSent = false
|
||||
hdr := p.publicHeader
|
||||
data := p.data
|
||||
|
||||
|
@ -433,19 +423,8 @@ func (s *session) handlePacketImpl(p *receivedPacket) error {
|
|||
// Only do this after decrypting, so we are sure the packet is not attacker-controlled
|
||||
s.largestRcvdPacketNumber = utils.MaxPacketNumber(s.largestRcvdPacketNumber, hdr.PacketNumber)
|
||||
|
||||
err = s.receivedPacketHandler.ReceivedPacket(hdr.PacketNumber, packet.IsRetransmittable())
|
||||
// ignore duplicate packets
|
||||
if err == ackhandler.ErrDuplicatePacket {
|
||||
utils.Infof("Ignoring packet 0x%x due to ErrDuplicatePacket", hdr.PacketNumber)
|
||||
return nil
|
||||
}
|
||||
// ignore packets with packet numbers smaller than the LeastUnacked of a StopWaiting
|
||||
if err == ackhandler.ErrPacketSmallerThanLastStopWaiting {
|
||||
utils.Infof("Ignoring packet 0x%x due to ErrPacketSmallerThanLastStopWaiting", hdr.PacketNumber)
|
||||
return nil
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
isRetransmittable := ackhandler.HasRetransmittableFrames(packet.frames)
|
||||
if err = s.receivedPacketHandler.ReceivedPacket(hdr.PacketNumber, isRetransmittable); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -462,7 +441,7 @@ func (s *session) handleFrames(fs []frames.Frame) error {
|
|||
case *frames.AckFrame:
|
||||
err = s.handleAckFrame(frame)
|
||||
case *frames.ConnectionCloseFrame:
|
||||
s.registerClose(qerr.Error(frame.ErrorCode, frame.ReasonPhrase), true)
|
||||
s.closeRemote(qerr.Error(frame.ErrorCode, frame.ReasonPhrase))
|
||||
case *frames.GoawayFrame:
|
||||
err = errors.New("unimplemented: handling GOAWAY frames")
|
||||
case *frames.StopWaitingFrame:
|
||||
|
@ -548,48 +527,31 @@ func (s *session) handleAckFrame(frame *frames.AckFrame) error {
|
|||
return s.sentPacketHandler.ReceivedAck(frame, s.lastRcvdPacketNumber, s.lastNetworkActivityTime)
|
||||
}
|
||||
|
||||
func (s *session) registerClose(e error, remoteClose bool) error {
|
||||
// Only close once
|
||||
if !atomic.CompareAndSwapUint32(&s.closed, 0, 1) {
|
||||
return errSessionAlreadyClosed
|
||||
}
|
||||
func (s *session) closeLocal(e error) {
|
||||
s.closeOnce.Do(func() {
|
||||
s.closeChan <- closeError{err: e, remote: false}
|
||||
})
|
||||
}
|
||||
|
||||
if e == nil {
|
||||
e = qerr.PeerGoingAway
|
||||
}
|
||||
|
||||
if e == errCloseSessionForNewVersion {
|
||||
s.streamsMap.CloseWithError(e)
|
||||
s.closeStreamsWithError(e)
|
||||
}
|
||||
|
||||
s.closeChan <- closeError{err: e, remote: remoteClose}
|
||||
return nil
|
||||
func (s *session) closeRemote(e error) {
|
||||
s.closeOnce.Do(func() {
|
||||
s.closeChan <- closeError{err: e, remote: true}
|
||||
})
|
||||
}
|
||||
|
||||
// Close the connection. If err is nil it will be set to qerr.PeerGoingAway.
|
||||
// It waits until the run loop has stopped before returning
|
||||
func (s *session) Close(e error) error {
|
||||
err := s.registerClose(e, false)
|
||||
if err == errSessionAlreadyClosed {
|
||||
return nil
|
||||
}
|
||||
|
||||
// wait for the run loop to finish
|
||||
s.closeLocal(e)
|
||||
<-s.runClosed
|
||||
return err
|
||||
}
|
||||
|
||||
// close the connection. Use this when called from the run loop
|
||||
func (s *session) close(e error) error {
|
||||
err := s.registerClose(e, false)
|
||||
if err == errSessionAlreadyClosed {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *session) handleCloseError(closeErr closeError) error {
|
||||
if closeErr.err == nil {
|
||||
closeErr.err = qerr.PeerGoingAway
|
||||
}
|
||||
|
||||
var quicErr *qerr.QuicError
|
||||
var ok bool
|
||||
if quicErr, ok = closeErr.err.(*qerr.QuicError); !ok {
|
||||
|
@ -602,13 +564,12 @@ func (s *session) handleCloseError(closeErr closeError) error {
|
|||
utils.Errorf("Closing session with error: %s", closeErr.err.Error())
|
||||
}
|
||||
|
||||
s.streamsMap.CloseWithError(quicErr)
|
||||
|
||||
if closeErr.err == errCloseSessionForNewVersion {
|
||||
return nil
|
||||
}
|
||||
|
||||
s.streamsMap.CloseWithError(quicErr)
|
||||
s.closeStreamsWithError(quicErr)
|
||||
|
||||
// If this is a remote close we're done here
|
||||
if closeErr.remote {
|
||||
return nil
|
||||
|
@ -620,27 +581,37 @@ func (s *session) handleCloseError(closeErr closeError) error {
|
|||
return s.sendConnectionClose(quicErr)
|
||||
}
|
||||
|
||||
func (s *session) closeStreamsWithError(err error) {
|
||||
s.streamsMap.Iterate(func(str *stream) (bool, error) {
|
||||
str.Cancel(err)
|
||||
return true, nil
|
||||
})
|
||||
}
|
||||
|
||||
func (s *session) sendPacket() error {
|
||||
s.packer.SetLeastUnacked(s.sentPacketHandler.GetLeastUnacked())
|
||||
|
||||
// Get WindowUpdate frames
|
||||
// this call triggers the flow controller to increase the flow control windows, if necessary
|
||||
windowUpdateFrames := s.getWindowUpdateFrames()
|
||||
for _, wuf := range windowUpdateFrames {
|
||||
s.packer.QueueControlFrame(wuf)
|
||||
}
|
||||
|
||||
ack := s.receivedPacketHandler.GetAckFrame()
|
||||
if ack != nil {
|
||||
s.packer.QueueControlFrame(ack)
|
||||
}
|
||||
|
||||
// Repeatedly try sending until we don't have any more data, or run out of the congestion window
|
||||
for {
|
||||
if !s.sentPacketHandler.SendingAllowed() {
|
||||
return nil
|
||||
}
|
||||
|
||||
var controlFrames []frames.Frame
|
||||
|
||||
// get WindowUpdate frames
|
||||
// this call triggers the flow controller to increase the flow control windows, if necessary
|
||||
windowUpdateFrames := s.getWindowUpdateFrames()
|
||||
for _, wuf := range windowUpdateFrames {
|
||||
controlFrames = append(controlFrames, wuf)
|
||||
if ack == nil {
|
||||
return nil
|
||||
}
|
||||
// If we aren't allowed to send, at least try sending an ACK frame
|
||||
swf := s.sentPacketHandler.GetStopWaitingFrame(false)
|
||||
if swf != nil {
|
||||
s.packer.QueueControlFrame(swf)
|
||||
}
|
||||
packet, err := s.packer.PackAckPacket()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.sendPackedPacket(packet)
|
||||
}
|
||||
|
||||
// check for retransmissions first
|
||||
|
@ -649,75 +620,67 @@ func (s *session) sendPacket() error {
|
|||
if retransmitPacket == nil {
|
||||
break
|
||||
}
|
||||
utils.Debugf("\tDequeueing retransmission for packet 0x%x", retransmitPacket.PacketNumber)
|
||||
|
||||
if retransmitPacket.EncryptionLevel != protocol.EncryptionForwardSecure {
|
||||
utils.Debugf("\tDequeueing handshake retransmission for packet 0x%x", retransmitPacket.PacketNumber)
|
||||
stopWaitingFrame := s.sentPacketHandler.GetStopWaitingFrame(true)
|
||||
var packet *packedPacket
|
||||
packet, err := s.packer.RetransmitNonForwardSecurePacket(stopWaitingFrame, retransmitPacket)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if packet == nil {
|
||||
if s.handshakeComplete {
|
||||
// Don't retransmit handshake packets when the handshake is complete
|
||||
continue
|
||||
}
|
||||
err = s.sendPackedPacket(packet)
|
||||
utils.Debugf("\tDequeueing handshake retransmission for packet 0x%x", retransmitPacket.PacketNumber)
|
||||
s.packer.QueueControlFrame(s.sentPacketHandler.GetStopWaitingFrame(true))
|
||||
packet, err := s.packer.PackHandshakeRetransmission(retransmitPacket)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
if err = s.sendPackedPacket(packet); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
utils.Debugf("\tDequeueing retransmission for packet 0x%x", retransmitPacket.PacketNumber)
|
||||
// resend the frames that were in the packet
|
||||
for _, frame := range retransmitPacket.GetFramesForRetransmission() {
|
||||
switch frame.(type) {
|
||||
switch f := frame.(type) {
|
||||
case *frames.StreamFrame:
|
||||
s.streamFramer.AddFrameForRetransmission(frame.(*frames.StreamFrame))
|
||||
s.streamFramer.AddFrameForRetransmission(f)
|
||||
case *frames.WindowUpdateFrame:
|
||||
// only retransmit WindowUpdates if the stream is not yet closed and the we haven't sent another WindowUpdate with a higher ByteOffset for the stream
|
||||
var currentOffset protocol.ByteCount
|
||||
f := frame.(*frames.WindowUpdateFrame)
|
||||
currentOffset, err := s.flowControlManager.GetReceiveWindow(f.StreamID)
|
||||
if err == nil && f.ByteOffset >= currentOffset {
|
||||
controlFrames = append(controlFrames, frame)
|
||||
s.packer.QueueControlFrame(f)
|
||||
}
|
||||
default:
|
||||
controlFrames = append(controlFrames, frame)
|
||||
s.packer.QueueControlFrame(frame)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ack := s.receivedPacketHandler.GetAckFrame()
|
||||
if ack != nil {
|
||||
controlFrames = append(controlFrames, ack)
|
||||
}
|
||||
hasRetransmission := s.streamFramer.HasFramesForRetransmission()
|
||||
var stopWaitingFrame *frames.StopWaitingFrame
|
||||
if ack != nil || hasRetransmission {
|
||||
stopWaitingFrame = s.sentPacketHandler.GetStopWaitingFrame(hasRetransmission)
|
||||
swf := s.sentPacketHandler.GetStopWaitingFrame(hasRetransmission)
|
||||
if swf != nil {
|
||||
s.packer.QueueControlFrame(swf)
|
||||
}
|
||||
}
|
||||
packet, err := s.packer.PackPacket(stopWaitingFrame, controlFrames, s.sentPacketHandler.GetLeastUnacked())
|
||||
if err != nil {
|
||||
packet, err := s.packer.PackPacket()
|
||||
if err != nil || packet == nil {
|
||||
return err
|
||||
}
|
||||
if packet == nil {
|
||||
return nil
|
||||
}
|
||||
// send every window update twice
|
||||
for _, f := range windowUpdateFrames {
|
||||
s.packer.QueueControlFrameForNextPacket(f)
|
||||
if err = s.sendPackedPacket(packet); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = s.sendPackedPacket(packet)
|
||||
if err != nil {
|
||||
return err
|
||||
// send every window update twice
|
||||
for _, f := range windowUpdateFrames {
|
||||
s.packer.QueueControlFrame(f)
|
||||
}
|
||||
s.nextAckScheduledTime = time.Time{}
|
||||
windowUpdateFrames = nil
|
||||
ack = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (s *session) sendPackedPacket(packet *packedPacket) error {
|
||||
defer putPacketBuffer(packet.raw)
|
||||
err := s.sentPacketHandler.SentPacket(&ackhandler.Packet{
|
||||
PacketNumber: packet.number,
|
||||
Frames: packet.frames,
|
||||
|
@ -727,22 +690,19 @@ func (s *session) sendPackedPacket(packet *packedPacket) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.logPacket(packet)
|
||||
|
||||
err = s.conn.Write(packet.raw)
|
||||
putPacketBuffer(packet.raw)
|
||||
return err
|
||||
return s.conn.Write(packet.raw)
|
||||
}
|
||||
|
||||
func (s *session) sendConnectionClose(quicErr *qerr.QuicError) error {
|
||||
packet, err := s.packer.PackConnectionClose(&frames.ConnectionCloseFrame{ErrorCode: quicErr.ErrorCode, ReasonPhrase: quicErr.ErrorMessage}, s.sentPacketHandler.GetLeastUnacked())
|
||||
s.packer.SetLeastUnacked(s.sentPacketHandler.GetLeastUnacked())
|
||||
packet, err := s.packer.PackConnectionClose(&frames.ConnectionCloseFrame{
|
||||
ErrorCode: quicErr.ErrorCode,
|
||||
ReasonPhrase: quicErr.ErrorMessage,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if packet == nil {
|
||||
return errors.New("Session BUG: expected packet not to be nil")
|
||||
}
|
||||
s.logPacket(packet)
|
||||
return s.conn.Write(packet.raw)
|
||||
}
|
||||
|
@ -752,11 +712,9 @@ func (s *session) logPacket(packet *packedPacket) {
|
|||
// We don't need to allocate the slices for calling the format functions
|
||||
return
|
||||
}
|
||||
if utils.Debug() {
|
||||
utils.Debugf("-> Sending packet 0x%x (%d bytes), %s", packet.number, len(packet.raw), packet.encryptionLevel)
|
||||
for _, frame := range packet.frames {
|
||||
frames.LogFrame(frame, true)
|
||||
}
|
||||
utils.Debugf("-> Sending packet 0x%x (%d bytes) for connection %x, %s", packet.number, len(packet.raw), s.connectionID, packet.encryptionLevel)
|
||||
for _, frame := range packet.frames {
|
||||
frames.LogFrame(frame, true)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -790,27 +748,21 @@ func (s *session) WaitUntilHandshakeComplete() error {
|
|||
}
|
||||
|
||||
func (s *session) queueResetStreamFrame(id protocol.StreamID, offset protocol.ByteCount) {
|
||||
s.packer.QueueControlFrameForNextPacket(&frames.RstStreamFrame{
|
||||
s.packer.QueueControlFrame(&frames.RstStreamFrame{
|
||||
StreamID: id,
|
||||
ByteOffset: offset,
|
||||
})
|
||||
s.scheduleSending()
|
||||
}
|
||||
|
||||
func (s *session) newStream(id protocol.StreamID) (*stream, error) {
|
||||
stream, err := newStream(id, s.scheduleSending, s.queueResetStreamFrame, s.flowControlManager)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (s *session) newStream(id protocol.StreamID) *stream {
|
||||
// TODO: find a better solution for determining which streams contribute to connection level flow control
|
||||
if id == 1 || id == 3 {
|
||||
s.flowControlManager.NewStream(id, false)
|
||||
} else {
|
||||
s.flowControlManager.NewStream(id, true)
|
||||
}
|
||||
|
||||
return stream, nil
|
||||
return newStream(id, s.scheduleSending, s.queueResetStreamFrame, s.flowControlManager)
|
||||
}
|
||||
|
||||
// garbageCollectStreams goes through all streams and removes EOF'ed streams
|
||||
|
@ -844,6 +796,7 @@ func (s *session) scheduleSending() {
|
|||
|
||||
func (s *session) tryQueueingUndecryptablePacket(p *receivedPacket) {
|
||||
if s.handshakeComplete {
|
||||
utils.Debugf("Received undecryptable packet from %s after the handshake: %#v, %d bytes data", p.remoteAddr.String(), p.publicHeader, len(p.data))
|
||||
return
|
||||
}
|
||||
if len(s.undecryptablePackets)+1 > protocol.MaxUndecryptablePackets {
|
||||
|
@ -875,11 +828,6 @@ func (s *session) getWindowUpdateFrames() []*frames.WindowUpdateFrame {
|
|||
return res
|
||||
}
|
||||
|
||||
func (s *session) ackAlarmChanged(t time.Time) {
|
||||
s.nextAckScheduledTime = t
|
||||
s.maybeResetTimer()
|
||||
}
|
||||
|
||||
func (s *session) LocalAddr() net.Addr {
|
||||
return s.conn.LocalAddr()
|
||||
}
|
||||
|
|
170
vendor/github.com/lucas-clemente/quic-go/stream.go
generated
vendored
170
vendor/github.com/lucas-clemente/quic-go/stream.go
generated
vendored
|
@ -3,12 +3,14 @@ package quic
|
|||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/flowcontrol"
|
||||
"github.com/lucas-clemente/quic-go/frames"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/protocol"
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
)
|
||||
|
||||
// A Stream assembles the data from StreamFrames and provides a super-convenient Read-Interface
|
||||
|
@ -40,31 +42,41 @@ type stream struct {
|
|||
// resetRemotely is set if RegisterRemoteError() is called
|
||||
resetRemotely utils.AtomicBool
|
||||
|
||||
frameQueue *streamFrameSorter
|
||||
newFrameOrErrCond sync.Cond
|
||||
frameQueue *streamFrameSorter
|
||||
readChan chan struct{}
|
||||
readDeadline time.Time
|
||||
|
||||
dataForWriting []byte
|
||||
finSent utils.AtomicBool
|
||||
rstSent utils.AtomicBool
|
||||
doneWritingOrErrCond sync.Cond
|
||||
dataForWriting []byte
|
||||
finSent utils.AtomicBool
|
||||
rstSent utils.AtomicBool
|
||||
writeChan chan struct{}
|
||||
writeDeadline time.Time
|
||||
|
||||
flowControlManager flowcontrol.FlowControlManager
|
||||
}
|
||||
|
||||
type deadlineError struct{}
|
||||
|
||||
func (deadlineError) Error() string { return "deadline exceeded" }
|
||||
func (deadlineError) Temporary() bool { return true }
|
||||
func (deadlineError) Timeout() bool { return true }
|
||||
|
||||
var errDeadline net.Error = &deadlineError{}
|
||||
|
||||
// newStream creates a new Stream
|
||||
func newStream(StreamID protocol.StreamID, onData func(), onReset func(protocol.StreamID, protocol.ByteCount), flowControlManager flowcontrol.FlowControlManager) (*stream, error) {
|
||||
s := &stream{
|
||||
func newStream(StreamID protocol.StreamID,
|
||||
onData func(),
|
||||
onReset func(protocol.StreamID, protocol.ByteCount),
|
||||
flowControlManager flowcontrol.FlowControlManager) *stream {
|
||||
return &stream{
|
||||
onData: onData,
|
||||
onReset: onReset,
|
||||
streamID: StreamID,
|
||||
flowControlManager: flowControlManager,
|
||||
frameQueue: newStreamFrameSorter(),
|
||||
readChan: make(chan struct{}, 1),
|
||||
writeChan: make(chan struct{}, 1),
|
||||
}
|
||||
|
||||
s.newFrameOrErrCond.L = &s.mutex
|
||||
s.doneWritingOrErrCond.L = &s.mutex
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// Read implements io.Reader. It is not thread safe!
|
||||
|
@ -83,10 +95,10 @@ func (s *stream) Read(p []byte) (int, error) {
|
|||
for bytesRead < len(p) {
|
||||
s.mutex.Lock()
|
||||
frame := s.frameQueue.Head()
|
||||
|
||||
if frame == nil && bytesRead > 0 {
|
||||
err = s.err
|
||||
s.mutex.Unlock()
|
||||
return bytesRead, s.err
|
||||
return bytesRead, err
|
||||
}
|
||||
|
||||
var err error
|
||||
|
@ -96,11 +108,28 @@ func (s *stream) Read(p []byte) (int, error) {
|
|||
err = s.err
|
||||
break
|
||||
}
|
||||
|
||||
deadline := s.readDeadline
|
||||
if !deadline.IsZero() && !time.Now().Before(deadline) {
|
||||
err = errDeadline
|
||||
break
|
||||
}
|
||||
|
||||
if frame != nil {
|
||||
s.readPosInFrame = int(s.readOffset - frame.Offset)
|
||||
break
|
||||
}
|
||||
s.newFrameOrErrCond.Wait()
|
||||
|
||||
s.mutex.Unlock()
|
||||
if deadline.IsZero() {
|
||||
<-s.readChan
|
||||
} else {
|
||||
select {
|
||||
case <-s.readChan:
|
||||
case <-time.After(deadline.Sub(time.Now())):
|
||||
}
|
||||
}
|
||||
s.mutex.Lock()
|
||||
frame = s.frameQueue.Head()
|
||||
}
|
||||
s.mutex.Unlock()
|
||||
|
@ -145,34 +174,49 @@ func (s *stream) Read(p []byte) (int, error) {
|
|||
}
|
||||
|
||||
func (s *stream) Write(p []byte) (int, error) {
|
||||
if s.resetLocally.Get() {
|
||||
return 0, s.err
|
||||
}
|
||||
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
|
||||
if s.err != nil {
|
||||
if s.resetLocally.Get() || s.err != nil {
|
||||
return 0, s.err
|
||||
}
|
||||
|
||||
if len(p) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
s.dataForWriting = make([]byte, len(p))
|
||||
copy(s.dataForWriting, p)
|
||||
|
||||
s.onData()
|
||||
|
||||
for s.dataForWriting != nil && s.err == nil {
|
||||
s.doneWritingOrErrCond.Wait()
|
||||
var err error
|
||||
for {
|
||||
deadline := s.writeDeadline
|
||||
if !deadline.IsZero() && !time.Now().Before(deadline) {
|
||||
err = errDeadline
|
||||
break
|
||||
}
|
||||
if s.dataForWriting == nil || s.err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
s.mutex.Unlock()
|
||||
if deadline.IsZero() {
|
||||
<-s.writeChan
|
||||
} else {
|
||||
select {
|
||||
case <-s.writeChan:
|
||||
case <-time.After(deadline.Sub(time.Now())):
|
||||
}
|
||||
}
|
||||
s.mutex.Lock()
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if s.err != nil {
|
||||
return 0, s.err
|
||||
return len(p) - len(s.dataForWriting), s.err
|
||||
}
|
||||
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
|
@ -188,14 +232,12 @@ func (s *stream) lenOfDataForWriting() protocol.ByteCount {
|
|||
|
||||
func (s *stream) getDataForWriting(maxBytes protocol.ByteCount) []byte {
|
||||
s.mutex.Lock()
|
||||
if s.err != nil {
|
||||
s.mutex.Unlock()
|
||||
return nil
|
||||
}
|
||||
if s.dataForWriting == nil {
|
||||
s.mutex.Unlock()
|
||||
defer s.mutex.Unlock()
|
||||
|
||||
if s.err != nil || s.dataForWriting == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var ret []byte
|
||||
if protocol.ByteCount(len(s.dataForWriting)) > maxBytes {
|
||||
ret = s.dataForWriting[:maxBytes]
|
||||
|
@ -203,10 +245,9 @@ func (s *stream) getDataForWriting(maxBytes protocol.ByteCount) []byte {
|
|||
} else {
|
||||
ret = s.dataForWriting
|
||||
s.dataForWriting = nil
|
||||
s.doneWritingOrErrCond.Signal()
|
||||
s.signalWrite()
|
||||
}
|
||||
s.writeOffset += protocol.ByteCount(len(ret))
|
||||
s.mutex.Unlock()
|
||||
return ret
|
||||
}
|
||||
|
||||
|
@ -249,7 +290,52 @@ func (s *stream) AddStreamFrame(frame *frames.StreamFrame) error {
|
|||
if err != nil && err != errDuplicateStreamData {
|
||||
return err
|
||||
}
|
||||
s.newFrameOrErrCond.Signal()
|
||||
s.signalRead()
|
||||
return nil
|
||||
}
|
||||
|
||||
// signalRead performs a non-blocking send on the readChan
|
||||
func (s *stream) signalRead() {
|
||||
select {
|
||||
case s.readChan <- struct{}{}:
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
// signalRead performs a non-blocking send on the writeChan
|
||||
func (s *stream) signalWrite() {
|
||||
select {
|
||||
case s.writeChan <- struct{}{}:
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
func (s *stream) SetReadDeadline(t time.Time) error {
|
||||
s.mutex.Lock()
|
||||
oldDeadline := s.readDeadline
|
||||
s.readDeadline = t
|
||||
s.mutex.Unlock()
|
||||
// if the new deadline is before the currently set deadline, wake up Read()
|
||||
if t.Before(oldDeadline) {
|
||||
s.signalRead()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *stream) SetWriteDeadline(t time.Time) error {
|
||||
s.mutex.Lock()
|
||||
oldDeadline := s.writeDeadline
|
||||
s.writeDeadline = t
|
||||
s.mutex.Unlock()
|
||||
if t.Before(oldDeadline) {
|
||||
s.signalWrite()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *stream) SetDeadline(t time.Time) error {
|
||||
_ = s.SetReadDeadline(t) // SetReadDeadline never errors
|
||||
_ = s.SetWriteDeadline(t) // SetWriteDeadline never errors
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -266,8 +352,8 @@ func (s *stream) Cancel(err error) {
|
|||
// errors must not be changed!
|
||||
if s.err == nil {
|
||||
s.err = err
|
||||
s.newFrameOrErrCond.Signal()
|
||||
s.doneWritingOrErrCond.Signal()
|
||||
s.signalRead()
|
||||
s.signalWrite()
|
||||
}
|
||||
s.mutex.Unlock()
|
||||
}
|
||||
|
@ -282,8 +368,8 @@ func (s *stream) Reset(err error) {
|
|||
// errors must not be changed!
|
||||
if s.err == nil {
|
||||
s.err = err
|
||||
s.newFrameOrErrCond.Signal()
|
||||
s.doneWritingOrErrCond.Signal()
|
||||
s.signalRead()
|
||||
s.signalWrite()
|
||||
}
|
||||
if s.shouldSendReset() {
|
||||
s.onReset(s.streamID, s.writeOffset)
|
||||
|
@ -302,7 +388,7 @@ func (s *stream) RegisterRemoteError(err error) {
|
|||
// errors must not be changed!
|
||||
if s.err == nil {
|
||||
s.err = err
|
||||
s.doneWritingOrErrCond.Signal()
|
||||
s.signalWrite()
|
||||
}
|
||||
if s.shouldSendReset() {
|
||||
s.onReset(s.streamID, s.writeOffset)
|
||||
|
|
2
vendor/github.com/lucas-clemente/quic-go/stream_frame_sorter.go
generated
vendored
2
vendor/github.com/lucas-clemente/quic-go/stream_frame_sorter.go
generated
vendored
|
@ -4,8 +4,8 @@ import (
|
|||
"errors"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/frames"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/protocol"
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
)
|
||||
|
||||
type streamFrameSorter struct {
|
||||
|
|
36
vendor/github.com/lucas-clemente/quic-go/stream_framer.go
generated
vendored
36
vendor/github.com/lucas-clemente/quic-go/stream_framer.go
generated
vendored
|
@ -3,8 +3,8 @@ package quic
|
|||
import (
|
||||
"github.com/lucas-clemente/quic-go/flowcontrol"
|
||||
"github.com/lucas-clemente/quic-go/frames"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/protocol"
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
)
|
||||
|
||||
type streamFramer struct {
|
||||
|
@ -45,6 +45,28 @@ func (f *streamFramer) HasFramesForRetransmission() bool {
|
|||
return len(f.retransmissionQueue) > 0
|
||||
}
|
||||
|
||||
func (f *streamFramer) HasCryptoStreamFrame() bool {
|
||||
// TODO(#657): Flow control
|
||||
cs, _ := f.streamsMap.GetOrOpenStream(1)
|
||||
return cs.lenOfDataForWriting() > 0
|
||||
}
|
||||
|
||||
// TODO(lclemente): This is somewhat duplicate with the normal path for generating frames.
|
||||
// TODO(#657): Flow control
|
||||
func (f *streamFramer) PopCryptoStreamFrame(maxLen protocol.ByteCount) *frames.StreamFrame {
|
||||
if !f.HasCryptoStreamFrame() {
|
||||
return nil
|
||||
}
|
||||
cs, _ := f.streamsMap.GetOrOpenStream(1)
|
||||
frame := &frames.StreamFrame{
|
||||
StreamID: 1,
|
||||
Offset: cs.writeOffset,
|
||||
}
|
||||
frameHeaderBytes, _ := frame.MinLength(protocol.VersionWhatever) // can never error
|
||||
frame.Data = cs.getDataForWriting(maxLen - frameHeaderBytes)
|
||||
return frame
|
||||
}
|
||||
|
||||
func (f *streamFramer) maybePopFramesForRetransmission(maxLen protocol.ByteCount) (res []*frames.StreamFrame, currentLen protocol.ByteCount) {
|
||||
for len(f.retransmissionQueue) > 0 {
|
||||
frame := f.retransmissionQueue[0]
|
||||
|
@ -76,7 +98,7 @@ func (f *streamFramer) maybePopNormalFrames(maxBytes protocol.ByteCount) (res []
|
|||
var currentLen protocol.ByteCount
|
||||
|
||||
fn := func(s *stream) (bool, error) {
|
||||
if s == nil {
|
||||
if s == nil || s.streamID == 1 /* crypto stream is handled separately */ {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
|
@ -90,7 +112,8 @@ func (f *streamFramer) maybePopNormalFrames(maxBytes protocol.ByteCount) (res []
|
|||
maxLen := maxBytes - currentLen - frameHeaderBytes
|
||||
|
||||
var sendWindowSize protocol.ByteCount
|
||||
if s.lenOfDataForWriting() != 0 {
|
||||
lenStreamData := s.lenOfDataForWriting()
|
||||
if lenStreamData != 0 {
|
||||
sendWindowSize, _ = f.flowControlManager.SendWindowSize(s.streamID)
|
||||
maxLen = utils.MinByteCount(maxLen, sendWindowSize)
|
||||
}
|
||||
|
@ -99,7 +122,12 @@ func (f *streamFramer) maybePopNormalFrames(maxBytes protocol.ByteCount) (res []
|
|||
return true, nil
|
||||
}
|
||||
|
||||
data := s.getDataForWriting(maxLen)
|
||||
var data []byte
|
||||
if lenStreamData != 0 {
|
||||
// Only getDataForWriting() if we didn't have data earlier, so that we
|
||||
// don't send without FC approval (if a Write() raced).
|
||||
data = s.getDataForWriting(maxLen)
|
||||
}
|
||||
|
||||
// This is unlikely, but check it nonetheless, the scheduler might have jumped in. Seems to happen in ~20% of cases in the tests.
|
||||
shouldSendFin := s.shouldSendFin()
|
||||
|
|
47
vendor/github.com/lucas-clemente/quic-go/streams_map.go
generated
vendored
47
vendor/github.com/lucas-clemente/quic-go/streams_map.go
generated
vendored
|
@ -36,7 +36,7 @@ type streamsMap struct {
|
|||
}
|
||||
|
||||
type streamLambda func(*stream) (bool, error)
|
||||
type newStreamLambda func(protocol.StreamID) (*stream, error)
|
||||
type newStreamLambda func(protocol.StreamID) *stream
|
||||
|
||||
var (
|
||||
errMapAccess = errors.New("streamsMap: Error accessing the streams map")
|
||||
|
@ -83,15 +83,27 @@ func (m *streamsMap) GetOrOpenStream(id protocol.StreamID) (*stream, error) {
|
|||
return s, nil
|
||||
}
|
||||
|
||||
if id <= m.highestStreamOpenedByPeer {
|
||||
return nil, nil
|
||||
if m.perspective == protocol.PerspectiveServer {
|
||||
if id%2 == 0 {
|
||||
if id <= m.nextStream { // this is a server-side stream that we already opened. Must have been closed already
|
||||
return nil, nil
|
||||
}
|
||||
return nil, qerr.Error(qerr.InvalidStreamID, fmt.Sprintf("attempted to open stream %d from client-side", id))
|
||||
}
|
||||
if id <= m.highestStreamOpenedByPeer { // this is a client-side stream that doesn't exist anymore. Must have been closed already
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
if m.perspective == protocol.PerspectiveServer && id%2 == 0 {
|
||||
return nil, qerr.Error(qerr.InvalidStreamID, fmt.Sprintf("attempted to open stream %d from client-side", id))
|
||||
}
|
||||
if m.perspective == protocol.PerspectiveClient && id%2 == 1 {
|
||||
return nil, qerr.Error(qerr.InvalidStreamID, fmt.Sprintf("attempted to open stream %d from server-side", id))
|
||||
if m.perspective == protocol.PerspectiveClient {
|
||||
if id%2 == 1 {
|
||||
if id <= m.nextStream { // this is a client-side stream that we already opened.
|
||||
return nil, nil
|
||||
}
|
||||
return nil, qerr.Error(qerr.InvalidStreamID, fmt.Sprintf("attempted to open stream %d from server-side", id))
|
||||
}
|
||||
if id <= m.highestStreamOpenedByPeer { // this is a server-side stream that doesn't exist anymore. Must have been closed already
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
// sid is the next stream that will be opened
|
||||
|
@ -120,11 +132,6 @@ func (m *streamsMap) openRemoteStream(id protocol.StreamID) (*stream, error) {
|
|||
return nil, qerr.Error(qerr.InvalidStreamID, fmt.Sprintf("attempted to open stream %d, which is a lot smaller than the highest opened stream, %d", id, m.highestStreamOpenedByPeer))
|
||||
}
|
||||
|
||||
s, err := m.newStream(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if m.perspective == protocol.PerspectiveServer {
|
||||
m.numIncomingStreams++
|
||||
} else {
|
||||
|
@ -135,6 +142,7 @@ func (m *streamsMap) openRemoteStream(id protocol.StreamID) (*stream, error) {
|
|||
m.highestStreamOpenedByPeer = id
|
||||
}
|
||||
|
||||
s := m.newStream(id)
|
||||
m.putStream(s)
|
||||
return s, nil
|
||||
}
|
||||
|
@ -145,11 +153,6 @@ func (m *streamsMap) openStreamImpl() (*stream, error) {
|
|||
return nil, qerr.TooManyOpenStreams
|
||||
}
|
||||
|
||||
s, err := m.newStream(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if m.perspective == protocol.PerspectiveServer {
|
||||
m.numOutgoingStreams++
|
||||
} else {
|
||||
|
@ -157,6 +160,7 @@ func (m *streamsMap) openStreamImpl() (*stream, error) {
|
|||
}
|
||||
|
||||
m.nextStream += 2
|
||||
s := m.newStream(id)
|
||||
m.putStream(s)
|
||||
return s, nil
|
||||
}
|
||||
|
@ -319,8 +323,11 @@ func (m *streamsMap) RemoveStream(id protocol.StreamID) error {
|
|||
|
||||
func (m *streamsMap) CloseWithError(err error) {
|
||||
m.mutex.Lock()
|
||||
defer m.mutex.Unlock()
|
||||
m.closeErr = err
|
||||
m.nextStreamOrErrCond.Broadcast()
|
||||
m.openStreamOrErrCond.Broadcast()
|
||||
m.mutex.Unlock()
|
||||
for _, s := range m.openStreams {
|
||||
m.streams[s].Cancel(err)
|
||||
}
|
||||
}
|
||||
|
|
31
vendor/github.com/lucas-clemente/quic-go/unpacked_packet.go
generated
vendored
31
vendor/github.com/lucas-clemente/quic-go/unpacked_packet.go
generated
vendored
|
@ -1,31 +0,0 @@
|
|||
package quic
|
||||
|
||||
import (
|
||||
"github.com/lucas-clemente/quic-go/frames"
|
||||
"github.com/lucas-clemente/quic-go/protocol"
|
||||
)
|
||||
|
||||
type unpackedPacket struct {
|
||||
encryptionLevel protocol.EncryptionLevel
|
||||
frames []frames.Frame
|
||||
}
|
||||
|
||||
func (u *unpackedPacket) IsRetransmittable() bool {
|
||||
for _, f := range u.frames {
|
||||
switch f.(type) {
|
||||
case *frames.StreamFrame:
|
||||
return true
|
||||
case *frames.RstStreamFrame:
|
||||
return true
|
||||
case *frames.WindowUpdateFrame:
|
||||
return true
|
||||
case *frames.BlockedFrame:
|
||||
return true
|
||||
case *frames.PingFrame:
|
||||
return true
|
||||
case *frames.GoawayFrame:
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
78
vendor/github.com/miekg/dns/client.go
generated
vendored
78
vendor/github.com/miekg/dns/client.go
generated
vendored
|
@ -4,6 +4,7 @@ package dns
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
|
@ -70,6 +71,43 @@ func Exchange(m *Msg, a string) (r *Msg, err error) {
|
|||
return r, err
|
||||
}
|
||||
|
||||
// ExchangeContext performs a synchronous UDP query, like Exchange. It
|
||||
// additionally obeys deadlines from the passed Context.
|
||||
func ExchangeContext(ctx context.Context, m *Msg, a string) (r *Msg, err error) {
|
||||
// Combine context deadline with built-in timeout. Context chooses whichever
|
||||
// is sooner.
|
||||
timeoutCtx, cancel := context.WithTimeout(ctx, dnsTimeout)
|
||||
defer cancel()
|
||||
deadline, _ := timeoutCtx.Deadline()
|
||||
|
||||
co := new(Conn)
|
||||
dialer := net.Dialer{}
|
||||
co.Conn, err = dialer.DialContext(timeoutCtx, "udp", a)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer co.Conn.Close()
|
||||
|
||||
opt := m.IsEdns0()
|
||||
// If EDNS0 is used use that for size.
|
||||
if opt != nil && opt.UDPSize() >= MinMsgSize {
|
||||
co.UDPSize = opt.UDPSize()
|
||||
}
|
||||
|
||||
co.SetWriteDeadline(deadline)
|
||||
if err = co.WriteMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
co.SetReadDeadline(deadline)
|
||||
r, err = co.ReadMsg()
|
||||
if err == nil && r.Id != m.Id {
|
||||
err = ErrId
|
||||
}
|
||||
return r, err
|
||||
}
|
||||
|
||||
// ExchangeConn performs a synchronous query. It sends the message m via the connection
|
||||
// c and waits for a reply. The connection c is not closed by ExchangeConn.
|
||||
// This function is going away, but can easily be mimicked:
|
||||
|
@ -106,8 +144,18 @@ func ExchangeConn(c net.Conn, m *Msg) (r *Msg, err error) {
|
|||
// buffer, see SetEdns0. Messages without an OPT RR will fallback to the historic limit
|
||||
// of 512 bytes.
|
||||
func (c *Client) Exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err error) {
|
||||
return c.ExchangeContext(context.Background(), m, a)
|
||||
}
|
||||
|
||||
// ExchangeContext acts like Exchange, but honors the deadline on the provided
|
||||
// context, if present. If there is both a context deadline and a configured
|
||||
// timeout on the client, the earliest of the two takes effect.
|
||||
func (c *Client) ExchangeContext(ctx context.Context, m *Msg, a string) (
|
||||
r *Msg,
|
||||
rtt time.Duration,
|
||||
err error) {
|
||||
if !c.SingleInflight {
|
||||
return c.exchange(m, a)
|
||||
return c.exchange(ctx, m, a)
|
||||
}
|
||||
// This adds a bunch of garbage, TODO(miek).
|
||||
t := "nop"
|
||||
|
@ -119,7 +167,7 @@ func (c *Client) Exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err erro
|
|||
cl = cl1
|
||||
}
|
||||
r, rtt, err, shared := c.group.Do(m.Question[0].Name+t+cl, func() (*Msg, time.Duration, error) {
|
||||
return c.exchange(m, a)
|
||||
return c.exchange(ctx, m, a)
|
||||
})
|
||||
if r != nil && shared {
|
||||
r = r.Copy()
|
||||
|
@ -154,7 +202,7 @@ func (c *Client) writeTimeout() time.Duration {
|
|||
return dnsTimeout
|
||||
}
|
||||
|
||||
func (c *Client) exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err error) {
|
||||
func (c *Client) exchange(ctx context.Context, m *Msg, a string) (r *Msg, rtt time.Duration, err error) {
|
||||
var co *Conn
|
||||
network := "udp"
|
||||
tls := false
|
||||
|
@ -180,10 +228,13 @@ func (c *Client) exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err erro
|
|||
deadline = time.Now().Add(c.Timeout)
|
||||
}
|
||||
|
||||
dialDeadline := deadlineOrTimeoutOrCtx(ctx, deadline, c.dialTimeout())
|
||||
dialTimeout := dialDeadline.Sub(time.Now())
|
||||
|
||||
if tls {
|
||||
co, err = DialTimeoutWithTLS(network, a, c.TLSConfig, c.dialTimeout())
|
||||
co, err = DialTimeoutWithTLS(network, a, c.TLSConfig, dialTimeout)
|
||||
} else {
|
||||
co, err = DialTimeout(network, a, c.dialTimeout())
|
||||
co, err = DialTimeout(network, a, dialTimeout)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
@ -202,12 +253,12 @@ func (c *Client) exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err erro
|
|||
}
|
||||
|
||||
co.TsigSecret = c.TsigSecret
|
||||
co.SetWriteDeadline(deadlineOrTimeout(deadline, c.writeTimeout()))
|
||||
co.SetWriteDeadline(deadlineOrTimeoutOrCtx(ctx, deadline, c.writeTimeout()))
|
||||
if err = co.WriteMsg(m); err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
co.SetReadDeadline(deadlineOrTimeout(deadline, c.readTimeout()))
|
||||
co.SetReadDeadline(deadlineOrTimeoutOrCtx(ctx, deadline, c.readTimeout()))
|
||||
r, err = co.ReadMsg()
|
||||
if err == nil && r.Id != m.Id {
|
||||
err = ErrId
|
||||
|
@ -459,9 +510,22 @@ func DialTimeoutWithTLS(network, address string, tlsConfig *tls.Config, timeout
|
|||
return conn, nil
|
||||
}
|
||||
|
||||
// deadlineOrTimeout chooses between the provided deadline and timeout
|
||||
// by always preferring the deadline so long as it's non-zero (regardless
|
||||
// of which is bigger), and returns the equivalent deadline value.
|
||||
func deadlineOrTimeout(deadline time.Time, timeout time.Duration) time.Time {
|
||||
if deadline.IsZero() {
|
||||
return time.Now().Add(timeout)
|
||||
}
|
||||
return deadline
|
||||
}
|
||||
|
||||
// deadlineOrTimeoutOrCtx returns the earliest of: a context deadline, or the
|
||||
// output of deadlineOrtimeout.
|
||||
func deadlineOrTimeoutOrCtx(ctx context.Context, deadline time.Time, timeout time.Duration) time.Time {
|
||||
result := deadlineOrTimeout(deadline, timeout)
|
||||
if ctxDeadline, ok := ctx.Deadline(); ok && ctxDeadline.Before(result) {
|
||||
result = ctxDeadline
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
|
2
vendor/github.com/miekg/dns/msg_helpers.go
generated
vendored
2
vendor/github.com/miekg/dns/msg_helpers.go
generated
vendored
|
@ -96,7 +96,7 @@ func unpackHeader(msg []byte, off int) (rr RR_Header, off1 int, truncmsg []byte,
|
|||
return hdr, len(msg), msg, err
|
||||
}
|
||||
msg, err = truncateMsgFromRdlength(msg, off, hdr.Rdlength)
|
||||
return hdr, off, msg, nil
|
||||
return hdr, off, msg, err
|
||||
}
|
||||
|
||||
// pack packs an RR header, returning the offset to the end of the header.
|
||||
|
|
42
vendor/github.com/miekg/dns/types.go
generated
vendored
42
vendor/github.com/miekg/dns/types.go
generated
vendored
|
@ -115,27 +115,27 @@ const (
|
|||
ClassNONE = 254
|
||||
ClassANY = 255
|
||||
|
||||
// Message Response Codes.
|
||||
RcodeSuccess = 0
|
||||
RcodeFormatError = 1
|
||||
RcodeServerFailure = 2
|
||||
RcodeNameError = 3
|
||||
RcodeNotImplemented = 4
|
||||
RcodeRefused = 5
|
||||
RcodeYXDomain = 6
|
||||
RcodeYXRrset = 7
|
||||
RcodeNXRrset = 8
|
||||
RcodeNotAuth = 9
|
||||
RcodeNotZone = 10
|
||||
RcodeBadSig = 16 // TSIG
|
||||
RcodeBadVers = 16 // EDNS0
|
||||
RcodeBadKey = 17
|
||||
RcodeBadTime = 18
|
||||
RcodeBadMode = 19 // TKEY
|
||||
RcodeBadName = 20
|
||||
RcodeBadAlg = 21
|
||||
RcodeBadTrunc = 22 // TSIG
|
||||
RcodeBadCookie = 23 // DNS Cookies
|
||||
// Message Response Codes, see https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml
|
||||
RcodeSuccess = 0 // NoError - No Error [DNS]
|
||||
RcodeFormatError = 1 // FormErr - Format Error [DNS]
|
||||
RcodeServerFailure = 2 // ServFail - Server Failure [DNS]
|
||||
RcodeNameError = 3 // NXDomain - Non-Existent Domain [DNS]
|
||||
RcodeNotImplemented = 4 // NotImp - Not Implemented [DNS]
|
||||
RcodeRefused = 5 // Refused - Query Refused [DNS]
|
||||
RcodeYXDomain = 6 // YXDomain - Name Exists when it should not [DNS Update]
|
||||
RcodeYXRrset = 7 // YXRRSet - RR Set Exists when it should not [DNS Update]
|
||||
RcodeNXRrset = 8 // NXRRSet - RR Set that should exist does not [DNS Update]
|
||||
RcodeNotAuth = 9 // NotAuth - Server Not Authoritative for zone [DNS Update]
|
||||
RcodeNotZone = 10 // NotZone - Name not contained in zone [DNS Update/TSIG]
|
||||
RcodeBadSig = 16 // BADSIG - TSIG Signature Failure [TSIG]
|
||||
RcodeBadVers = 16 // BADVERS - Bad OPT Version [EDNS0]
|
||||
RcodeBadKey = 17 // BADKEY - Key not recognized [TSIG]
|
||||
RcodeBadTime = 18 // BADTIME - Signature out of time window [TSIG]
|
||||
RcodeBadMode = 19 // BADMODE - Bad TKEY Mode [TKEY]
|
||||
RcodeBadName = 20 // BADNAME - Duplicate key name [TKEY]
|
||||
RcodeBadAlg = 21 // BADALG - Algorithm not supported [TKEY]
|
||||
RcodeBadTrunc = 22 // BADTRUNC - Bad Truncation [TSIG]
|
||||
RcodeBadCookie = 23 // BADCOOKIE - Bad/missing Server Cookie [DNS Cookies]
|
||||
|
||||
// Message Opcodes. There is no 3.
|
||||
OpcodeQuery = 0
|
||||
|
|
11
vendor/github.com/miekg/dns/xfr.go
generated
vendored
11
vendor/github.com/miekg/dns/xfr.go
generated
vendored
|
@ -1,6 +1,7 @@
|
|||
package dns
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
@ -81,6 +82,10 @@ func (t *Transfer) inAxfr(id uint16, c chan *Envelope) {
|
|||
return
|
||||
}
|
||||
if first {
|
||||
if in.Rcode != RcodeSuccess {
|
||||
c <- &Envelope{in.Answer, &Error{err: fmt.Sprintf(errXFR, in.Rcode)}}
|
||||
return
|
||||
}
|
||||
if !isSOAFirst(in) {
|
||||
c <- &Envelope{in.Answer, ErrSoa}
|
||||
return
|
||||
|
@ -126,6 +131,10 @@ func (t *Transfer) inIxfr(id uint16, c chan *Envelope) {
|
|||
return
|
||||
}
|
||||
if first {
|
||||
if in.Rcode != RcodeSuccess {
|
||||
c <- &Envelope{in.Answer, &Error{err: fmt.Sprintf(errXFR, in.Rcode)}}
|
||||
return
|
||||
}
|
||||
// A single SOA RR signals "no changes"
|
||||
if len(in.Answer) == 1 && isSOAFirst(in) {
|
||||
c <- &Envelope{in.Answer, nil}
|
||||
|
@ -242,3 +251,5 @@ func isSOALast(in *Msg) bool {
|
|||
}
|
||||
return false
|
||||
}
|
||||
|
||||
const errXFR = "bad xfr rcode: %d"
|
||||
|
|
4
vendor/github.com/russross/blackfriday/inline.go
generated
vendored
4
vendor/github.com/russross/blackfriday/inline.go
generated
vendored
|
@ -488,6 +488,7 @@ func link(p *parser, out *bytes.Buffer, data []byte, offset int) int {
|
|||
}
|
||||
|
||||
p.notes = append(p.notes, ref)
|
||||
p.notesRecord[string(ref.link)] = struct{}{}
|
||||
|
||||
link = ref.link
|
||||
title = ref.title
|
||||
|
@ -498,9 +499,10 @@ func link(p *parser, out *bytes.Buffer, data []byte, offset int) int {
|
|||
return 0
|
||||
}
|
||||
|
||||
if t == linkDeferredFootnote {
|
||||
if t == linkDeferredFootnote && !p.isFootnote(lr) {
|
||||
lr.noteId = len(p.notes) + 1
|
||||
p.notes = append(p.notes, lr)
|
||||
p.notesRecord[string(lr.link)] = struct{}{}
|
||||
}
|
||||
|
||||
// keep link and title from reference
|
||||
|
|
9
vendor/github.com/russross/blackfriday/markdown.go
generated
vendored
9
vendor/github.com/russross/blackfriday/markdown.go
generated
vendored
|
@ -218,7 +218,8 @@ type parser struct {
|
|||
// Footnotes need to be ordered as well as available to quickly check for
|
||||
// presence. If a ref is also a footnote, it's stored both in refs and here
|
||||
// in notes. Slice is nil if footnotes not enabled.
|
||||
notes []*reference
|
||||
notes []*reference
|
||||
notesRecord map[string]struct{}
|
||||
}
|
||||
|
||||
func (p *parser) getRef(refid string) (ref *reference, found bool) {
|
||||
|
@ -241,6 +242,11 @@ func (p *parser) getRef(refid string) (ref *reference, found bool) {
|
|||
return ref, found
|
||||
}
|
||||
|
||||
func (p *parser) isFootnote(ref *reference) bool {
|
||||
_, ok := p.notesRecord[string(ref.link)]
|
||||
return ok
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
// Public interface
|
||||
|
@ -376,6 +382,7 @@ func MarkdownOptions(input []byte, renderer Renderer, opts Options) []byte {
|
|||
|
||||
if extensions&EXTENSION_FOOTNOTES != 0 {
|
||||
p.notes = make([]*reference, 0)
|
||||
p.notesRecord = make(map[string]struct{})
|
||||
}
|
||||
|
||||
first := firstPass(p, input)
|
||||
|
|
13
vendor/github.com/xenolf/lego/acme/http.go
generated
vendored
13
vendor/github.com/xenolf/lego/acme/http.go
generated
vendored
|
@ -5,6 +5,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
@ -15,7 +16,17 @@ import (
|
|||
var UserAgent string
|
||||
|
||||
// HTTPClient is an HTTP client with a reasonable timeout value.
|
||||
var HTTPClient = http.Client{Timeout: 10 * time.Second}
|
||||
var HTTPClient = http.Client{
|
||||
Transport: &http.Transport{
|
||||
Dial: (&net.Dialer{
|
||||
Timeout: 30 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
}).Dial,
|
||||
TLSHandshakeTimeout: 15 * time.Second,
|
||||
ResponseHeaderTimeout: 15 * time.Second,
|
||||
ExpectContinueTimeout: 1 * time.Second,
|
||||
},
|
||||
}
|
||||
|
||||
const (
|
||||
// defaultGoUserAgent is the Go HTTP package user agent string. Too
|
||||
|
|
8
vendor/golang.org/x/crypto/acme/acme.go
generated
vendored
8
vendor/golang.org/x/crypto/acme/acme.go
generated
vendored
|
@ -207,7 +207,7 @@ func (c *Client) CreateCert(ctx context.Context, csr []byte, exp time.Duration,
|
|||
return nil, "", responseError(res)
|
||||
}
|
||||
|
||||
curl := res.Header.Get("location") // cert permanent URL
|
||||
curl := res.Header.Get("Location") // cert permanent URL
|
||||
if res.ContentLength == 0 {
|
||||
// no cert in the body; poll until we get it
|
||||
cert, err := c.FetchCert(ctx, curl, bundle)
|
||||
|
@ -240,7 +240,7 @@ func (c *Client) FetchCert(ctx context.Context, url string, bundle bool) ([][]by
|
|||
if res.StatusCode > 299 {
|
||||
return nil, responseError(res)
|
||||
}
|
||||
d := retryAfter(res.Header.Get("retry-after"), 3*time.Second)
|
||||
d := retryAfter(res.Header.Get("Retry-After"), 3*time.Second)
|
||||
select {
|
||||
case <-time.After(d):
|
||||
// retry
|
||||
|
@ -444,7 +444,7 @@ func (c *Client) WaitAuthorization(ctx context.Context, url string) (*Authorizat
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
retry := res.Header.Get("retry-after")
|
||||
retry := res.Header.Get("Retry-After")
|
||||
if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted {
|
||||
res.Body.Close()
|
||||
if err := sleep(retry, 1); err != nil {
|
||||
|
@ -703,7 +703,7 @@ func (c *Client) retryPostJWS(ctx context.Context, key crypto.Signer, url string
|
|||
// clear any nonces that we might've stored that might now be
|
||||
// considered bad
|
||||
c.clearNonces()
|
||||
retry := res.Header.Get("retry-after")
|
||||
retry := res.Header.Get("Retry-After")
|
||||
if err := sleep(retry, 1); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
9
vendor/golang.org/x/crypto/acme/autocert/listener.go
generated
vendored
9
vendor/golang.org/x/crypto/acme/autocert/listener.go
generated
vendored
|
@ -36,6 +36,9 @@ import (
|
|||
// operating system-specific cache or temp directory. This may not
|
||||
// be suitable for servers spanning multiple machines.
|
||||
//
|
||||
// The returned listener uses a *tls.Config that enables HTTP/2, and
|
||||
// should only be used with servers that support HTTP/2.
|
||||
//
|
||||
// The returned Listener also enables TCP keep-alives on the accepted
|
||||
// connections. The returned *tls.Conn are returned before their TLS
|
||||
// handshake has completed.
|
||||
|
@ -58,6 +61,9 @@ func NewListener(domains ...string) net.Listener {
|
|||
// Listener listens on the standard TLS port (443) on all interfaces
|
||||
// and returns a net.Listener returning *tls.Conn connections.
|
||||
//
|
||||
// The returned listener uses a *tls.Config that enables HTTP/2, and
|
||||
// should only be used with servers that support HTTP/2.
|
||||
//
|
||||
// The returned Listener also enables TCP keep-alives on the accepted
|
||||
// connections. The returned *tls.Conn are returned before their TLS
|
||||
// handshake has completed.
|
||||
|
@ -68,7 +74,8 @@ func (m *Manager) Listener() net.Listener {
|
|||
ln := &listener{
|
||||
m: m,
|
||||
conf: &tls.Config{
|
||||
GetCertificate: m.GetCertificate, // bonus: panic on nil m
|
||||
GetCertificate: m.GetCertificate, // bonus: panic on nil m
|
||||
NextProtos: []string{"h2", "http/1.1"}, // Enable HTTP/2
|
||||
},
|
||||
}
|
||||
ln.tcpListener, ln.tcpListenErr = net.Listen("tcp", ":443")
|
||||
|
|
2
vendor/golang.org/x/crypto/curve25519/const_amd64.h
generated
vendored
2
vendor/golang.org/x/crypto/curve25519/const_amd64.h
generated
vendored
|
@ -3,6 +3,6 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This code was translated into a form compatible with 6a from the public
|
||||
// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
|
||||
// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html
|
||||
|
||||
#define REDMASK51 0x0007FFFFFFFFFFFF
|
||||
|
|
2
vendor/golang.org/x/crypto/curve25519/const_amd64.s
generated
vendored
2
vendor/golang.org/x/crypto/curve25519/const_amd64.s
generated
vendored
|
@ -3,7 +3,7 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This code was translated into a form compatible with 6a from the public
|
||||
// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
|
||||
// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html
|
||||
|
||||
// +build amd64,!gccgo,!appengine
|
||||
|
||||
|
|
2
vendor/golang.org/x/crypto/curve25519/doc.go
generated
vendored
2
vendor/golang.org/x/crypto/curve25519/doc.go
generated
vendored
|
@ -3,7 +3,7 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package curve25519 provides an implementation of scalar multiplication on
|
||||
// the elliptic curve known as curve25519. See http://cr.yp.to/ecdh.html
|
||||
// the elliptic curve known as curve25519. See https://cr.yp.to/ecdh.html
|
||||
package curve25519 // import "golang.org/x/crypto/curve25519"
|
||||
|
||||
// basePoint is the x coordinate of the generator of the curve.
|
||||
|
|
2
vendor/golang.org/x/crypto/curve25519/freeze_amd64.s
generated
vendored
2
vendor/golang.org/x/crypto/curve25519/freeze_amd64.s
generated
vendored
|
@ -3,7 +3,7 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This code was translated into a form compatible with 6a from the public
|
||||
// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
|
||||
// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html
|
||||
|
||||
// +build amd64,!gccgo,!appengine
|
||||
|
||||
|
|
2
vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s
generated
vendored
2
vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s
generated
vendored
|
@ -3,7 +3,7 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This code was translated into a form compatible with 6a from the public
|
||||
// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
|
||||
// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html
|
||||
|
||||
// +build amd64,!gccgo,!appengine
|
||||
|
||||
|
|
2
vendor/golang.org/x/crypto/curve25519/mul_amd64.s
generated
vendored
2
vendor/golang.org/x/crypto/curve25519/mul_amd64.s
generated
vendored
|
@ -3,7 +3,7 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This code was translated into a form compatible with 6a from the public
|
||||
// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
|
||||
// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html
|
||||
|
||||
// +build amd64,!gccgo,!appengine
|
||||
|
||||
|
|
2
vendor/golang.org/x/crypto/curve25519/square_amd64.s
generated
vendored
2
vendor/golang.org/x/crypto/curve25519/square_amd64.s
generated
vendored
|
@ -3,7 +3,7 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This code was translated into a form compatible with 6a from the public
|
||||
// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
|
||||
// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html
|
||||
|
||||
// +build amd64,!gccgo,!appengine
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue