slidge-whatsapp 0.2.5__cp311-cp311-manylinux_2_36_aarch64.whl → 0.3.0__cp311-cp311-manylinux_2_36_aarch64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of slidge-whatsapp might be problematic. Click here for more details.

Files changed (484) hide show
  1. slidge_whatsapp/config.py +3 -0
  2. slidge_whatsapp/contact.py +15 -3
  3. slidge_whatsapp/event.go +171 -70
  4. slidge_whatsapp/gateway.go +16 -68
  5. slidge_whatsapp/gateway.py +4 -5
  6. slidge_whatsapp/generated/_whatsapp.cpython-311-aarch64-linux-gnu.h +168 -151
  7. slidge_whatsapp/generated/_whatsapp.cpython-311-aarch64-linux-gnu.so +0 -0
  8. slidge_whatsapp/generated/build.py +142 -128
  9. slidge_whatsapp/generated/whatsapp.c +1689 -1417
  10. slidge_whatsapp/generated/whatsapp.go +1011 -900
  11. slidge_whatsapp/generated/whatsapp.py +1175 -1050
  12. slidge_whatsapp/generated/whatsapp_go.h +168 -151
  13. slidge_whatsapp/go.mod +21 -15
  14. slidge_whatsapp/go.sum +49 -31
  15. slidge_whatsapp/group.py +34 -30
  16. slidge_whatsapp/media/media.go +22 -12
  17. slidge_whatsapp/session.go +106 -82
  18. slidge_whatsapp/session.py +46 -14
  19. slidge_whatsapp/vendor/github.com/beeper/argo-go/LICENSE +9 -0
  20. slidge_whatsapp/vendor/github.com/beeper/argo-go/block/blockreader.go +329 -0
  21. slidge_whatsapp/vendor/github.com/beeper/argo-go/block/blockwriter.go +417 -0
  22. slidge_whatsapp/vendor/github.com/beeper/argo-go/codec/decoder.go +652 -0
  23. slidge_whatsapp/vendor/github.com/beeper/argo-go/codec/encoder.go +985 -0
  24. slidge_whatsapp/vendor/github.com/beeper/argo-go/header/header.go +135 -0
  25. slidge_whatsapp/vendor/github.com/beeper/argo-go/internal/util/util.go +133 -0
  26. slidge_whatsapp/vendor/github.com/beeper/argo-go/label/label.go +384 -0
  27. slidge_whatsapp/vendor/github.com/beeper/argo-go/label/wiremarkers.go +37 -0
  28. slidge_whatsapp/vendor/github.com/beeper/argo-go/pkg/bitset/bitset.go +197 -0
  29. slidge_whatsapp/vendor/github.com/beeper/argo-go/pkg/buf/buf.go +420 -0
  30. slidge_whatsapp/vendor/github.com/beeper/argo-go/pkg/varint/varint.go +246 -0
  31. slidge_whatsapp/vendor/github.com/beeper/argo-go/wire/wire.go +614 -0
  32. slidge_whatsapp/vendor/github.com/beeper/argo-go/wirecodec/decode.go +341 -0
  33. slidge_whatsapp/vendor/github.com/ebitengine/purego/dlfcn.go +4 -4
  34. slidge_whatsapp/vendor/github.com/ebitengine/purego/dlfcn_darwin.go +0 -5
  35. slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/go_libinit.go +3 -0
  36. slidge_whatsapp/vendor/github.com/ebitengine/purego/internal/fakecgo/symbols.go +40 -20
  37. slidge_whatsapp/vendor/github.com/elliotchance/orderedmap/v3/LICENSE +21 -0
  38. slidge_whatsapp/vendor/github.com/elliotchance/orderedmap/v3/list.go +95 -0
  39. slidge_whatsapp/vendor/github.com/elliotchance/orderedmap/v3/orderedmap.go +187 -0
  40. slidge_whatsapp/vendor/github.com/gen2brain/go-fitz/fitz.go +1 -0
  41. slidge_whatsapp/vendor/github.com/gen2brain/go-fitz/fitz_cgo.go +3 -0
  42. slidge_whatsapp/vendor/github.com/gen2brain/go-fitz/fitz_nocgo.go +4 -5
  43. slidge_whatsapp/vendor/github.com/gen2brain/go-fitz/purego_darwin.go +11 -1
  44. slidge_whatsapp/vendor/github.com/gen2brain/go-fitz/purego_linux.go +10 -0
  45. slidge_whatsapp/vendor/github.com/gen2brain/go-fitz/purego_windows.go +12 -0
  46. slidge_whatsapp/vendor/github.com/jupiterrider/ffi/.gitignore +0 -2
  47. slidge_whatsapp/vendor/github.com/jupiterrider/ffi/CHANGELOG.md +44 -1
  48. slidge_whatsapp/vendor/github.com/jupiterrider/ffi/COPYRIGHT.txt +6 -1
  49. slidge_whatsapp/vendor/github.com/jupiterrider/ffi/README.md +14 -17
  50. slidge_whatsapp/vendor/github.com/jupiterrider/ffi/abi.go +1 -1
  51. slidge_whatsapp/vendor/github.com/jupiterrider/ffi/abi2.go +7 -0
  52. slidge_whatsapp/vendor/github.com/jupiterrider/ffi/assets/libffi/LICENSE +21 -0
  53. slidge_whatsapp/vendor/github.com/jupiterrider/ffi/assets/libffi/darwin_amd64/libffi.8.dylib +0 -0
  54. slidge_whatsapp/vendor/github.com/jupiterrider/ffi/assets/libffi/darwin_arm64/libffi.8.dylib +0 -0
  55. slidge_whatsapp/vendor/github.com/jupiterrider/ffi/assets/libffi/windows_amd64/libffi-8.dll +0 -0
  56. slidge_whatsapp/vendor/github.com/jupiterrider/ffi/cif.go +15 -0
  57. slidge_whatsapp/vendor/github.com/jupiterrider/ffi/cif_arm64.go +16 -0
  58. slidge_whatsapp/vendor/github.com/jupiterrider/ffi/embed.go +49 -0
  59. slidge_whatsapp/vendor/github.com/jupiterrider/ffi/embed_darwin_amd64.go +10 -0
  60. slidge_whatsapp/vendor/github.com/jupiterrider/ffi/embed_darwin_arm64.go +10 -0
  61. slidge_whatsapp/vendor/github.com/jupiterrider/ffi/embed_windows_amd64.go +10 -0
  62. slidge_whatsapp/vendor/github.com/jupiterrider/ffi/ffi.go +53 -15
  63. slidge_whatsapp/vendor/github.com/jupiterrider/ffi/fun.go +10 -2
  64. slidge_whatsapp/vendor/github.com/jupiterrider/ffi/init.go +22 -9
  65. slidge_whatsapp/vendor/github.com/jupiterrider/ffi/lib.go +1 -1
  66. slidge_whatsapp/vendor/github.com/jupiterrider/ffi/lib_unix.go +1 -1
  67. slidge_whatsapp/vendor/github.com/jupiterrider/ffi/lib_windows.go +1 -1
  68. slidge_whatsapp/vendor/github.com/mattn/go-sqlite3/README.md +4 -7
  69. slidge_whatsapp/vendor/github.com/mattn/go-sqlite3/callback.go +2 -1
  70. slidge_whatsapp/vendor/github.com/mattn/go-sqlite3/sqlite3-binding.c +11545 -6680
  71. slidge_whatsapp/vendor/github.com/mattn/go-sqlite3/sqlite3-binding.h +527 -273
  72. slidge_whatsapp/vendor/github.com/mattn/go-sqlite3/sqlite3.go +57 -23
  73. slidge_whatsapp/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_unlock_notify.c +4 -0
  74. slidge_whatsapp/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_unlock_notify.go +4 -0
  75. slidge_whatsapp/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_userauth.go +13 -140
  76. slidge_whatsapp/vendor/github.com/mattn/go-sqlite3/sqlite3ext.h +4 -0
  77. slidge_whatsapp/vendor/github.com/petermattis/goid/.gitignore +4 -0
  78. slidge_whatsapp/vendor/github.com/petermattis/goid/LICENSE +202 -0
  79. slidge_whatsapp/vendor/github.com/petermattis/goid/README.md +4 -0
  80. slidge_whatsapp/vendor/github.com/petermattis/goid/goid.go +35 -0
  81. slidge_whatsapp/vendor/github.com/petermattis/goid/goid_gccgo.go +26 -0
  82. slidge_whatsapp/vendor/github.com/petermattis/goid/goid_go1.3.c +23 -0
  83. slidge_whatsapp/vendor/github.com/petermattis/goid/goid_go1.3.go +22 -0
  84. slidge_whatsapp/vendor/github.com/petermattis/goid/goid_go1.4.go +35 -0
  85. slidge_whatsapp/vendor/github.com/petermattis/goid/goid_go1.4.s +18 -0
  86. slidge_whatsapp/vendor/github.com/petermattis/goid/goid_go1.5.go +28 -0
  87. slidge_whatsapp/vendor/github.com/petermattis/goid/goid_go1.5.s +44 -0
  88. slidge_whatsapp/vendor/github.com/petermattis/goid/goid_slow.go +24 -0
  89. slidge_whatsapp/vendor/github.com/petermattis/goid/runtime_gccgo_go1.8.go +17 -0
  90. slidge_whatsapp/vendor/github.com/petermattis/goid/runtime_go1.23.go +38 -0
  91. slidge_whatsapp/vendor/github.com/petermattis/goid/runtime_go1.25.go +37 -0
  92. slidge_whatsapp/vendor/github.com/petermattis/goid/runtime_go1.5.go +57 -0
  93. slidge_whatsapp/vendor/github.com/petermattis/goid/runtime_go1.6.go +43 -0
  94. slidge_whatsapp/vendor/github.com/petermattis/goid/runtime_go1.9.go +37 -0
  95. slidge_whatsapp/vendor/github.com/rs/zerolog/CONTRIBUTING.md +43 -0
  96. slidge_whatsapp/vendor/github.com/rs/zerolog/README.md +31 -0
  97. slidge_whatsapp/vendor/github.com/rs/zerolog/console.go +20 -5
  98. slidge_whatsapp/vendor/github.com/rs/zerolog/log/log.go +131 -0
  99. slidge_whatsapp/vendor/github.com/rs/zerolog/log.go +1 -1
  100. slidge_whatsapp/vendor/github.com/rs/zerolog/sampler.go +4 -1
  101. slidge_whatsapp/vendor/github.com/rs/zerolog/writer.go +9 -0
  102. slidge_whatsapp/vendor/github.com/vektah/gqlparser/v2/LICENSE +19 -0
  103. slidge_whatsapp/vendor/github.com/vektah/gqlparser/v2/ast/argmap.go +37 -0
  104. slidge_whatsapp/vendor/github.com/vektah/gqlparser/v2/ast/collections.go +148 -0
  105. slidge_whatsapp/vendor/github.com/vektah/gqlparser/v2/ast/comment.go +31 -0
  106. slidge_whatsapp/vendor/github.com/vektah/gqlparser/v2/ast/decode.go +216 -0
  107. slidge_whatsapp/vendor/github.com/vektah/gqlparser/v2/ast/definition.go +110 -0
  108. slidge_whatsapp/vendor/github.com/vektah/gqlparser/v2/ast/directive.go +43 -0
  109. slidge_whatsapp/vendor/github.com/vektah/gqlparser/v2/ast/document.go +89 -0
  110. slidge_whatsapp/vendor/github.com/vektah/gqlparser/v2/ast/dumper.go +159 -0
  111. slidge_whatsapp/vendor/github.com/vektah/gqlparser/v2/ast/fragment.go +41 -0
  112. slidge_whatsapp/vendor/github.com/vektah/gqlparser/v2/ast/operation.go +32 -0
  113. slidge_whatsapp/vendor/github.com/vektah/gqlparser/v2/ast/path.go +72 -0
  114. slidge_whatsapp/vendor/github.com/vektah/gqlparser/v2/ast/selection.go +41 -0
  115. slidge_whatsapp/vendor/github.com/vektah/gqlparser/v2/ast/source.go +19 -0
  116. slidge_whatsapp/vendor/github.com/vektah/gqlparser/v2/ast/type.go +68 -0
  117. slidge_whatsapp/vendor/github.com/vektah/gqlparser/v2/ast/value.go +122 -0
  118. slidge_whatsapp/vendor/go.mau.fi/libsignal/groups/GroupCipher.go +17 -6
  119. slidge_whatsapp/vendor/go.mau.fi/libsignal/groups/GroupSessionBuilder.go +17 -7
  120. slidge_whatsapp/vendor/go.mau.fi/libsignal/groups/state/store/SenderKeyStore.go +4 -2
  121. slidge_whatsapp/vendor/go.mau.fi/libsignal/keys/chain/ChainKey.go +1 -0
  122. slidge_whatsapp/vendor/go.mau.fi/libsignal/keys/identity/IdentityKey.go +1 -0
  123. slidge_whatsapp/vendor/go.mau.fi/libsignal/logger/DefaultLogger.go +2 -2
  124. slidge_whatsapp/vendor/go.mau.fi/libsignal/serialize/FingerprintProtocol.pb.go +3 -2
  125. slidge_whatsapp/vendor/go.mau.fi/libsignal/serialize/LocalStorageProtocol.pb.go +3 -2
  126. slidge_whatsapp/vendor/go.mau.fi/libsignal/serialize/WhisperTextProtocol.pb.go +3 -2
  127. slidge_whatsapp/vendor/go.mau.fi/libsignal/session/Session.go +41 -17
  128. slidge_whatsapp/vendor/go.mau.fi/libsignal/session/SessionCipher.go +64 -30
  129. slidge_whatsapp/vendor/go.mau.fi/libsignal/state/store/IdentityKeyStore.go +5 -3
  130. slidge_whatsapp/vendor/go.mau.fi/libsignal/state/store/MessageKeyStore.go +6 -4
  131. slidge_whatsapp/vendor/go.mau.fi/libsignal/state/store/PreKeyStore.go +6 -4
  132. slidge_whatsapp/vendor/go.mau.fi/libsignal/state/store/SessionStore.go +8 -6
  133. slidge_whatsapp/vendor/go.mau.fi/libsignal/state/store/SignedPreKeyStore.go +7 -5
  134. slidge_whatsapp/vendor/go.mau.fi/util/dbutil/connlog.go +257 -0
  135. slidge_whatsapp/vendor/go.mau.fi/util/dbutil/database.go +309 -0
  136. slidge_whatsapp/vendor/go.mau.fi/util/dbutil/iter.go +233 -0
  137. slidge_whatsapp/vendor/go.mau.fi/util/dbutil/json.go +47 -0
  138. slidge_whatsapp/vendor/go.mau.fi/util/dbutil/log.go +129 -0
  139. slidge_whatsapp/vendor/go.mau.fi/util/dbutil/massinsert.go +164 -0
  140. slidge_whatsapp/vendor/go.mau.fi/util/dbutil/queryhelper.go +137 -0
  141. slidge_whatsapp/vendor/go.mau.fi/util/dbutil/reflectscan.go +30 -0
  142. slidge_whatsapp/vendor/go.mau.fi/util/dbutil/transaction.go +180 -0
  143. slidge_whatsapp/vendor/go.mau.fi/util/dbutil/upgrades.go +250 -0
  144. slidge_whatsapp/vendor/go.mau.fi/util/dbutil/upgradetable.go +331 -0
  145. slidge_whatsapp/vendor/go.mau.fi/util/exerrors/dualerror.go +33 -0
  146. slidge_whatsapp/vendor/go.mau.fi/util/exerrors/must.go +23 -0
  147. slidge_whatsapp/vendor/go.mau.fi/util/exhttp/cors.go +32 -0
  148. slidge_whatsapp/vendor/go.mau.fi/util/exhttp/handleerrors.go +98 -0
  149. slidge_whatsapp/vendor/go.mau.fi/util/exhttp/json.go +36 -0
  150. slidge_whatsapp/vendor/go.mau.fi/util/exhttp/middleware.go +30 -0
  151. slidge_whatsapp/vendor/go.mau.fi/util/exhttp/networkerror.go +38 -0
  152. slidge_whatsapp/vendor/go.mau.fi/util/exstrings/stringutil.go +104 -0
  153. slidge_whatsapp/vendor/go.mau.fi/util/exsync/event.go +104 -0
  154. slidge_whatsapp/vendor/go.mau.fi/util/exsync/returnonce.go +25 -0
  155. slidge_whatsapp/vendor/go.mau.fi/util/exsync/ringbuffer.go +139 -0
  156. slidge_whatsapp/vendor/go.mau.fi/util/exsync/syncmap.go +94 -0
  157. slidge_whatsapp/vendor/go.mau.fi/util/exsync/syncset.go +136 -0
  158. slidge_whatsapp/vendor/go.mau.fi/util/exzerolog/callermarshal.go +28 -0
  159. slidge_whatsapp/vendor/go.mau.fi/util/exzerolog/defaults.go +32 -0
  160. slidge_whatsapp/vendor/go.mau.fi/util/exzerolog/generics.go +45 -0
  161. slidge_whatsapp/vendor/go.mau.fi/util/exzerolog/writer.go +81 -0
  162. slidge_whatsapp/vendor/go.mau.fi/util/ptr/ptr.go +43 -0
  163. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/.pre-commit-config.yaml +3 -3
  164. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/appstate/decode.go +27 -26
  165. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/appstate/encode.go +4 -3
  166. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/appstate/hash.go +1 -1
  167. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/appstate/keys.go +5 -4
  168. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/appstate.go +32 -26
  169. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/argo/argo-wire-type-store.argo +63 -0
  170. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/argo/argo.go +62 -0
  171. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/argo/name-to-queryids.json +306 -0
  172. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/armadillomessage.go +42 -8
  173. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/binary/encoder.go +1 -1
  174. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/broadcast.go +5 -4
  175. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/call.go +2 -1
  176. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/client.go +134 -55
  177. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/connectionevents.go +34 -11
  178. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/download-to-file.go +63 -30
  179. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/download.go +78 -34
  180. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/errors.go +4 -0
  181. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/group.go +157 -55
  182. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/internals.go +202 -154
  183. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/keepalive.go +3 -2
  184. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/mediaconn.go +5 -3
  185. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/mediaretry.go +2 -1
  186. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/message.go +448 -138
  187. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/msgsecret.go +106 -31
  188. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/newsletter.go +83 -7
  189. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/notification.go +83 -43
  190. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/pair-code.go +9 -6
  191. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/pair.go +42 -18
  192. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/prekeys.go +9 -5
  193. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/presence.go +17 -7
  194. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/privacysettings.go +10 -11
  195. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/extra.go +7 -0
  196. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloAddMessage/InstamadilloAddMessage.pb.go +983 -0
  197. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloAddMessage/InstamadilloAddMessage.proto +85 -0
  198. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloAddMessage/extra.go +3 -0
  199. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeActionLog/InstamadilloCoreTypeActionLog.pb.go +197 -0
  200. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeActionLog/InstamadilloCoreTypeActionLog.proto +13 -0
  201. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeAdminMessage/InstamadilloCoreTypeAdminMessage.pb.go +279 -0
  202. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeAdminMessage/InstamadilloCoreTypeAdminMessage.proto +21 -0
  203. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeCollection/InstamadilloCoreTypeCollection.pb.go +137 -0
  204. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeCollection/InstamadilloCoreTypeCollection.proto +10 -0
  205. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeLink/InstamadilloCoreTypeLink.pb.go +313 -0
  206. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeLink/InstamadilloCoreTypeLink.proto +27 -0
  207. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeMedia/InstamadilloCoreTypeMedia.pb.go +1299 -0
  208. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeMedia/InstamadilloCoreTypeMedia.proto +112 -0
  209. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeText/InstamadilloCoreTypeText.pb.go +514 -0
  210. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeText/InstamadilloCoreTypeText.proto +47 -0
  211. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloDeleteMessage/InstamadilloDeleteMessage.pb.go +123 -0
  212. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloDeleteMessage/InstamadilloDeleteMessage.proto +7 -0
  213. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloDeleteMessage/extra.go +3 -0
  214. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloSupplementMessage/InstamadilloSupplementMessage.pb.go +720 -0
  215. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloSupplementMessage/InstamadilloSupplementMessage.proto +59 -0
  216. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloSupplementMessage/extra.go +3 -0
  217. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloTransportPayload/InstamadilloTransportPayload.pb.go +365 -0
  218. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloTransportPayload/InstamadilloTransportPayload.proto +33 -0
  219. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloXmaContentRef/InstamadilloXmaContentRef.pb.go +1238 -0
  220. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloXmaContentRef/InstamadilloXmaContentRef.proto +105 -0
  221. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waAdv/WAAdv.pb.go +39 -9
  222. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waArmadilloApplication/WAArmadilloApplication.pb.go +354 -175
  223. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waArmadilloApplication/WAArmadilloApplication.proto +5 -5
  224. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waArmadilloXMA/WAArmadilloXMA.pb.go +170 -15
  225. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waArmadilloXMA/WAArmadilloXMA.proto +4 -0
  226. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waBotMetadata/WABotMetadata.pb.go +5156 -0
  227. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waBotMetadata/WABotMetadata.proto +516 -0
  228. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waCert/WACert.pb.go +29 -9
  229. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waChatLockSettings/WAProtobufsChatLockSettings.pb.go +13 -9
  230. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waCommon/WACommon.pb.go +344 -31
  231. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waCommon/WACommon.proto +26 -0
  232. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waCompanionReg/{WAWebProtobufsCompanionReg.pb.go → WACompanionReg.pb.go} +211 -89
  233. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waCompanionReg/{WAWebProtobufsCompanionReg.proto → WACompanionReg.proto} +5 -1
  234. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waConsumerApplication/WAConsumerApplication.pb.go +173 -9
  235. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waDeviceCapabilities/WAProtobufsDeviceCapabilities.pb.go +78 -16
  236. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waDeviceCapabilities/WAProtobufsDeviceCapabilities.proto +5 -0
  237. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waE2E/WAWebProtobufsE2E.pb.go +7463 -5180
  238. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waE2E/WAWebProtobufsE2E.proto +366 -343
  239. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waHistorySync/WAWebProtobufsHistorySync.pb.go +485 -135
  240. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waHistorySync/WAWebProtobufsHistorySync.proto +17 -0
  241. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waLidMigrationSyncPayload/WAWebProtobufLidMigrationSyncPayload.pb.go +198 -0
  242. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waLidMigrationSyncPayload/WAWebProtobufLidMigrationSyncPayload.proto +14 -0
  243. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waMediaTransport/WAMediaTransport.pb.go +162 -9
  244. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waMediaTransport/WAMediaTransport.proto +1 -0
  245. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waMmsRetry/WAMmsRetry.pb.go +32 -9
  246. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waMmsRetry/WAMmsRetry.proto +1 -0
  247. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waMsgApplication/WAMsgApplication.pb.go +192 -52
  248. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waMsgApplication/WAMsgApplication.proto +8 -0
  249. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waMsgTransport/WAMsgTransport.pb.go +60 -9
  250. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waMsgTransport/extra.go +7 -6
  251. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waMultiDevice/WAMultiDevice.pb.go +39 -9
  252. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waServerSync/WAServerSync.pb.go +61 -9
  253. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waStatusAttributions/WAStatusAttributions.pb.go +952 -0
  254. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waStatusAttributions/WAStatusAttributions.proto +88 -0
  255. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waSyncAction/WASyncAction.pb.go +1802 -453
  256. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waSyncAction/WASyncAction.proto +92 -0
  257. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waUserPassword/WAProtobufsUserPassword.pb.go +27 -9
  258. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waVnameCert/WAWebProtobufsVnameCert.pb.go +59 -9
  259. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waWa6/WAWebProtobufsWa6.pb.go +435 -109
  260. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waWa6/WAWebProtobufsWa6.proto +11 -0
  261. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waWeb/WAWebProtobufsWeb.pb.go +563 -9
  262. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waWeb/WAWebProtobufsWeb.proto +4 -0
  263. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/receipt.go +32 -9
  264. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/reportingfields.json +1 -0
  265. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/reportingtoken.go +176 -0
  266. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/retry.go +39 -21
  267. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/send.go +267 -79
  268. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/sendfb.go +28 -16
  269. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/clientpayload.go +3 -1
  270. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/noop.go +87 -44
  271. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/signal.go +75 -88
  272. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/sqlstore/container.go +86 -65
  273. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/sqlstore/lidmap.go +186 -0
  274. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/sqlstore/store.go +314 -170
  275. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/sqlstore/upgrades/00-latest-schema.sql +155 -0
  276. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/sqlstore/upgrades/03-message-secrets.sql +11 -0
  277. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/sqlstore/upgrades/04-privacy-tokens.sql +8 -0
  278. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/sqlstore/upgrades/05-account-jid-format.sql +2 -0
  279. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/sqlstore/upgrades/06-facebook-uuid.sql +2 -0
  280. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/sqlstore/upgrades/07-account-lid.sql +2 -0
  281. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/sqlstore/upgrades/08-lid-mapping.sql +5 -0
  282. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/sqlstore/upgrades/09-decryption-buffer.sql +10 -0
  283. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/sqlstore/upgrades/10-chat-db-lid-migration-ts.sql +2 -0
  284. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/sqlstore/upgrades/upgrades.go +22 -0
  285. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/store.go +109 -56
  286. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/types/botmap.go +210 -0
  287. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/types/call.go +1 -0
  288. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/types/events/events.go +21 -2
  289. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/types/group.go +15 -6
  290. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/types/jid.go +9 -9
  291. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/types/message.go +18 -0
  292. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/types/user.go +2 -0
  293. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/update.go +3 -2
  294. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/upload.go +1 -1
  295. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/user.go +59 -37
  296. slidge_whatsapp/vendor/golang.org/x/crypto/curve25519/curve25519.go +1 -1
  297. slidge_whatsapp/vendor/golang.org/x/exp/LICENSE +27 -0
  298. slidge_whatsapp/vendor/golang.org/x/exp/PATENTS +22 -0
  299. slidge_whatsapp/vendor/golang.org/x/exp/constraints/constraints.go +54 -0
  300. slidge_whatsapp/vendor/golang.org/x/net/http/httpguts/guts.go +50 -0
  301. slidge_whatsapp/vendor/golang.org/x/net/http/httpguts/httplex.go +347 -0
  302. slidge_whatsapp/vendor/golang.org/x/net/http2/.gitignore +2 -0
  303. slidge_whatsapp/vendor/golang.org/x/net/http2/ascii.go +53 -0
  304. slidge_whatsapp/vendor/golang.org/x/net/http2/ciphers.go +641 -0
  305. slidge_whatsapp/vendor/golang.org/x/net/http2/client_conn_pool.go +311 -0
  306. slidge_whatsapp/vendor/golang.org/x/net/http2/config.go +164 -0
  307. slidge_whatsapp/vendor/golang.org/x/net/http2/databuffer.go +149 -0
  308. slidge_whatsapp/vendor/golang.org/x/net/http2/errors.go +145 -0
  309. slidge_whatsapp/vendor/golang.org/x/net/http2/flow.go +120 -0
  310. slidge_whatsapp/vendor/golang.org/x/net/http2/frame.go +1702 -0
  311. slidge_whatsapp/vendor/golang.org/x/net/http2/gotrack.go +181 -0
  312. slidge_whatsapp/vendor/golang.org/x/net/http2/hpack/encode.go +245 -0
  313. slidge_whatsapp/vendor/golang.org/x/net/http2/hpack/hpack.go +523 -0
  314. slidge_whatsapp/vendor/golang.org/x/net/http2/hpack/huffman.go +226 -0
  315. slidge_whatsapp/vendor/golang.org/x/net/http2/hpack/static_table.go +188 -0
  316. slidge_whatsapp/vendor/golang.org/x/net/http2/hpack/tables.go +403 -0
  317. slidge_whatsapp/vendor/golang.org/x/net/http2/http2.go +410 -0
  318. slidge_whatsapp/vendor/golang.org/x/net/http2/pipe.go +184 -0
  319. slidge_whatsapp/vendor/golang.org/x/net/http2/server.go +3332 -0
  320. slidge_whatsapp/vendor/golang.org/x/net/http2/transport.go +3233 -0
  321. slidge_whatsapp/vendor/golang.org/x/net/http2/unencrypted.go +32 -0
  322. slidge_whatsapp/vendor/golang.org/x/net/http2/write.go +381 -0
  323. slidge_whatsapp/vendor/golang.org/x/net/http2/writesched.go +251 -0
  324. slidge_whatsapp/vendor/golang.org/x/net/http2/writesched_priority.go +451 -0
  325. slidge_whatsapp/vendor/golang.org/x/net/http2/writesched_random.go +77 -0
  326. slidge_whatsapp/vendor/golang.org/x/net/http2/writesched_roundrobin.go +119 -0
  327. slidge_whatsapp/vendor/golang.org/x/net/idna/go118.go +13 -0
  328. slidge_whatsapp/vendor/golang.org/x/net/idna/idna10.0.0.go +769 -0
  329. slidge_whatsapp/vendor/golang.org/x/net/idna/idna9.0.0.go +717 -0
  330. slidge_whatsapp/vendor/golang.org/x/net/idna/pre_go118.go +11 -0
  331. slidge_whatsapp/vendor/golang.org/x/net/idna/punycode.go +217 -0
  332. slidge_whatsapp/vendor/golang.org/x/net/idna/tables10.0.0.go +4559 -0
  333. slidge_whatsapp/vendor/golang.org/x/net/idna/tables11.0.0.go +4653 -0
  334. slidge_whatsapp/vendor/golang.org/x/net/idna/tables12.0.0.go +4733 -0
  335. slidge_whatsapp/vendor/golang.org/x/net/idna/tables13.0.0.go +4959 -0
  336. slidge_whatsapp/vendor/golang.org/x/net/idna/tables15.0.0.go +5144 -0
  337. slidge_whatsapp/vendor/golang.org/x/net/idna/tables9.0.0.go +4486 -0
  338. slidge_whatsapp/vendor/golang.org/x/net/idna/trie.go +51 -0
  339. slidge_whatsapp/vendor/golang.org/x/net/idna/trie12.0.0.go +30 -0
  340. slidge_whatsapp/vendor/golang.org/x/net/idna/trie13.0.0.go +30 -0
  341. slidge_whatsapp/vendor/golang.org/x/net/idna/trieval.go +119 -0
  342. slidge_whatsapp/vendor/golang.org/x/net/internal/httpcommon/ascii.go +53 -0
  343. slidge_whatsapp/vendor/golang.org/x/net/internal/httpcommon/headermap.go +115 -0
  344. slidge_whatsapp/vendor/golang.org/x/net/internal/httpcommon/request.go +467 -0
  345. slidge_whatsapp/vendor/golang.org/x/sys/unix/affinity_linux.go +1 -3
  346. slidge_whatsapp/vendor/golang.org/x/sys/unix/mkerrors.sh +3 -0
  347. slidge_whatsapp/vendor/golang.org/x/sys/unix/syscall_darwin.go +93 -0
  348. slidge_whatsapp/vendor/golang.org/x/sys/unix/syscall_linux.go +16 -26
  349. slidge_whatsapp/vendor/golang.org/x/sys/unix/syscall_solaris.go +1 -1
  350. slidge_whatsapp/vendor/golang.org/x/sys/unix/zerrors_linux.go +47 -16
  351. slidge_whatsapp/vendor/golang.org/x/sys/unix/zerrors_linux_386.go +3 -0
  352. slidge_whatsapp/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go +3 -0
  353. slidge_whatsapp/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go +3 -0
  354. slidge_whatsapp/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go +3 -0
  355. slidge_whatsapp/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go +3 -0
  356. slidge_whatsapp/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go +3 -0
  357. slidge_whatsapp/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go +3 -0
  358. slidge_whatsapp/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go +3 -0
  359. slidge_whatsapp/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go +3 -0
  360. slidge_whatsapp/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go +3 -0
  361. slidge_whatsapp/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go +3 -0
  362. slidge_whatsapp/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go +3 -0
  363. slidge_whatsapp/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go +3 -0
  364. slidge_whatsapp/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go +3 -0
  365. slidge_whatsapp/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go +3 -0
  366. slidge_whatsapp/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go +84 -0
  367. slidge_whatsapp/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s +20 -0
  368. slidge_whatsapp/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go +84 -0
  369. slidge_whatsapp/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s +20 -0
  370. slidge_whatsapp/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go +4 -4
  371. slidge_whatsapp/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go +1 -0
  372. slidge_whatsapp/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go +1 -0
  373. slidge_whatsapp/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go +1 -0
  374. slidge_whatsapp/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go +1 -0
  375. slidge_whatsapp/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go +1 -0
  376. slidge_whatsapp/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go +1 -0
  377. slidge_whatsapp/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go +1 -0
  378. slidge_whatsapp/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go +1 -0
  379. slidge_whatsapp/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go +1 -0
  380. slidge_whatsapp/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go +1 -0
  381. slidge_whatsapp/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go +1 -0
  382. slidge_whatsapp/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go +1 -0
  383. slidge_whatsapp/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go +1 -0
  384. slidge_whatsapp/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go +1 -0
  385. slidge_whatsapp/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go +1 -0
  386. slidge_whatsapp/vendor/golang.org/x/sys/unix/ztypes_linux.go +168 -12
  387. slidge_whatsapp/vendor/golang.org/x/sys/unix/ztypes_linux_386.go +17 -1
  388. slidge_whatsapp/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go +16 -0
  389. slidge_whatsapp/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go +18 -2
  390. slidge_whatsapp/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go +16 -0
  391. slidge_whatsapp/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go +16 -0
  392. slidge_whatsapp/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go +17 -1
  393. slidge_whatsapp/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go +16 -0
  394. slidge_whatsapp/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go +16 -0
  395. slidge_whatsapp/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go +17 -1
  396. slidge_whatsapp/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go +18 -2
  397. slidge_whatsapp/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go +16 -0
  398. slidge_whatsapp/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go +16 -0
  399. slidge_whatsapp/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go +16 -0
  400. slidge_whatsapp/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go +16 -0
  401. slidge_whatsapp/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go +16 -0
  402. slidge_whatsapp/vendor/golang.org/x/sys/windows/security_windows.go +44 -5
  403. slidge_whatsapp/vendor/golang.org/x/sys/windows/syscall_windows.go +4 -2
  404. slidge_whatsapp/vendor/golang.org/x/sys/windows/types_windows.go +245 -0
  405. slidge_whatsapp/vendor/golang.org/x/sys/windows/zsyscall_windows.go +491 -482
  406. slidge_whatsapp/vendor/golang.org/x/text/LICENSE +27 -0
  407. slidge_whatsapp/vendor/golang.org/x/text/PATENTS +22 -0
  408. slidge_whatsapp/vendor/golang.org/x/text/secure/bidirule/bidirule.go +336 -0
  409. slidge_whatsapp/vendor/golang.org/x/text/secure/bidirule/bidirule10.0.0.go +11 -0
  410. slidge_whatsapp/vendor/golang.org/x/text/secure/bidirule/bidirule9.0.0.go +14 -0
  411. slidge_whatsapp/vendor/golang.org/x/text/transform/transform.go +709 -0
  412. slidge_whatsapp/vendor/golang.org/x/text/unicode/bidi/bidi.go +359 -0
  413. slidge_whatsapp/vendor/golang.org/x/text/unicode/bidi/bracket.go +335 -0
  414. slidge_whatsapp/vendor/golang.org/x/text/unicode/bidi/core.go +1071 -0
  415. slidge_whatsapp/vendor/golang.org/x/text/unicode/bidi/prop.go +206 -0
  416. slidge_whatsapp/vendor/golang.org/x/text/unicode/bidi/tables10.0.0.go +1815 -0
  417. slidge_whatsapp/vendor/golang.org/x/text/unicode/bidi/tables11.0.0.go +1887 -0
  418. slidge_whatsapp/vendor/golang.org/x/text/unicode/bidi/tables12.0.0.go +1923 -0
  419. slidge_whatsapp/vendor/golang.org/x/text/unicode/bidi/tables13.0.0.go +1955 -0
  420. slidge_whatsapp/vendor/golang.org/x/text/unicode/bidi/tables15.0.0.go +2042 -0
  421. slidge_whatsapp/vendor/golang.org/x/text/unicode/bidi/tables9.0.0.go +1781 -0
  422. slidge_whatsapp/vendor/golang.org/x/text/unicode/bidi/trieval.go +48 -0
  423. slidge_whatsapp/vendor/golang.org/x/text/unicode/norm/composition.go +512 -0
  424. slidge_whatsapp/vendor/golang.org/x/text/unicode/norm/forminfo.go +279 -0
  425. slidge_whatsapp/vendor/golang.org/x/text/unicode/norm/input.go +109 -0
  426. slidge_whatsapp/vendor/golang.org/x/text/unicode/norm/iter.go +458 -0
  427. slidge_whatsapp/vendor/golang.org/x/text/unicode/norm/normalize.go +610 -0
  428. slidge_whatsapp/vendor/golang.org/x/text/unicode/norm/readwriter.go +125 -0
  429. slidge_whatsapp/vendor/golang.org/x/text/unicode/norm/tables10.0.0.go +7657 -0
  430. slidge_whatsapp/vendor/golang.org/x/text/unicode/norm/tables11.0.0.go +7693 -0
  431. slidge_whatsapp/vendor/golang.org/x/text/unicode/norm/tables12.0.0.go +7710 -0
  432. slidge_whatsapp/vendor/golang.org/x/text/unicode/norm/tables13.0.0.go +7760 -0
  433. slidge_whatsapp/vendor/golang.org/x/text/unicode/norm/tables15.0.0.go +7907 -0
  434. slidge_whatsapp/vendor/golang.org/x/text/unicode/norm/tables9.0.0.go +7637 -0
  435. slidge_whatsapp/vendor/golang.org/x/text/unicode/norm/transform.go +88 -0
  436. slidge_whatsapp/vendor/golang.org/x/text/unicode/norm/trie.go +54 -0
  437. slidge_whatsapp/vendor/google.golang.org/protobuf/encoding/protowire/wire.go +25 -1
  438. slidge_whatsapp/vendor/google.golang.org/protobuf/internal/editiondefaults/editions_defaults.binpb +0 -0
  439. slidge_whatsapp/vendor/google.golang.org/protobuf/internal/filedesc/editions.go +13 -5
  440. slidge_whatsapp/vendor/google.golang.org/protobuf/internal/filedesc/presence.go +33 -0
  441. slidge_whatsapp/vendor/google.golang.org/protobuf/internal/genid/api_gen.go +6 -0
  442. slidge_whatsapp/vendor/google.golang.org/protobuf/internal/genid/descriptor_gen.go +81 -19
  443. slidge_whatsapp/vendor/google.golang.org/protobuf/internal/impl/codec_message_opaque.go +2 -1
  444. slidge_whatsapp/vendor/google.golang.org/protobuf/internal/impl/message_opaque.go +8 -37
  445. slidge_whatsapp/vendor/google.golang.org/protobuf/internal/impl/presence.go +0 -3
  446. slidge_whatsapp/vendor/google.golang.org/protobuf/internal/strs/{strings_unsafe_go121.go → strings_unsafe.go} +0 -2
  447. slidge_whatsapp/vendor/google.golang.org/protobuf/internal/version/version.go +1 -1
  448. slidge_whatsapp/vendor/google.golang.org/protobuf/proto/merge.go +6 -0
  449. slidge_whatsapp/vendor/google.golang.org/protobuf/reflect/protoreflect/source_gen.go +10 -0
  450. slidge_whatsapp/vendor/google.golang.org/protobuf/reflect/protoreflect/{value_unsafe_go121.go → value_unsafe.go} +0 -2
  451. slidge_whatsapp/vendor/modules.txt +80 -21
  452. {slidge_whatsapp-0.2.5.dist-info → slidge_whatsapp-0.3.0.dist-info}/METADATA +5 -4
  453. {slidge_whatsapp-0.2.5.dist-info → slidge_whatsapp-0.3.0.dist-info}/RECORD +456 -263
  454. {slidge_whatsapp-0.2.5.dist-info → slidge_whatsapp-0.3.0.dist-info}/WHEEL +1 -1
  455. slidge_whatsapp/vendor/github.com/jupiterrider/ffi/abi_amd64.go +0 -7
  456. slidge_whatsapp/vendor/github.com/rs/zerolog/CNAME +0 -1
  457. slidge_whatsapp/vendor/github.com/rs/zerolog/_config.yml +0 -1
  458. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waAdv/WAAdv.pb.raw +0 -0
  459. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waArmadilloApplication/WAArmadilloApplication.pb.raw +0 -0
  460. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waArmadilloXMA/WAArmadilloXMA.pb.raw +0 -0
  461. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waCert/WACert.pb.raw +0 -23
  462. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waChatLockSettings/WAProtobufsChatLockSettings.pb.raw +0 -7
  463. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waCommon/WACommon.pb.raw +0 -0
  464. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waCompanionReg/WAWebProtobufsCompanionReg.pb.raw +0 -0
  465. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waConsumerApplication/WAConsumerApplication.pb.raw +0 -0
  466. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waDeviceCapabilities/WAProtobufsDeviceCapabilities.pb.raw +0 -0
  467. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waE2E/WAWebProtobufsE2E.pb.raw +0 -0
  468. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waHistorySync/WAWebProtobufsHistorySync.pb.raw +0 -0
  469. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waMediaTransport/WAMediaTransport.pb.raw +0 -0
  470. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waMmsRetry/WAMmsRetry.pb.raw +0 -0
  471. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waMsgApplication/WAMsgApplication.pb.raw +0 -0
  472. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waMsgTransport/WAMsgTransport.pb.raw +0 -0
  473. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waMultiDevice/WAMultiDevice.pb.raw +0 -0
  474. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waServerSync/WAServerSync.pb.raw +0 -0
  475. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waSyncAction/WASyncAction.pb.raw +0 -0
  476. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waUserPassword/WAProtobufsUserPassword.pb.raw +0 -0
  477. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waVnameCert/WAWebProtobufsVnameCert.pb.raw +0 -0
  478. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waWa6/WAWebProtobufsWa6.pb.raw +0 -0
  479. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waWeb/WAWebProtobufsWeb.pb.raw +0 -0
  480. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/sqlstore/upgrade.go +0 -296
  481. slidge_whatsapp/vendor/google.golang.org/protobuf/internal/strs/strings_unsafe_go120.go +0 -94
  482. slidge_whatsapp/vendor/google.golang.org/protobuf/reflect/protoreflect/value_unsafe_go120.go +0 -98
  483. {slidge_whatsapp-0.2.5.dist-info → slidge_whatsapp-0.3.0.dist-info}/entry_points.txt +0 -0
  484. {slidge_whatsapp-0.2.5.dist-info → slidge_whatsapp-0.3.0.dist-info/licenses}/LICENSE +0 -0
@@ -0,0 +1,3233 @@
1
+ // Copyright 2015 The Go Authors. All rights reserved.
2
+ // Use of this source code is governed by a BSD-style
3
+ // license that can be found in the LICENSE file.
4
+
5
+ // Transport code.
6
+
7
+ package http2
8
+
9
+ import (
10
+ "bufio"
11
+ "bytes"
12
+ "compress/gzip"
13
+ "context"
14
+ "crypto/rand"
15
+ "crypto/tls"
16
+ "errors"
17
+ "fmt"
18
+ "io"
19
+ "io/fs"
20
+ "log"
21
+ "math"
22
+ "math/bits"
23
+ mathrand "math/rand"
24
+ "net"
25
+ "net/http"
26
+ "net/http/httptrace"
27
+ "net/textproto"
28
+ "strconv"
29
+ "strings"
30
+ "sync"
31
+ "sync/atomic"
32
+ "time"
33
+
34
+ "golang.org/x/net/http/httpguts"
35
+ "golang.org/x/net/http2/hpack"
36
+ "golang.org/x/net/idna"
37
+ "golang.org/x/net/internal/httpcommon"
38
+ )
39
+
40
+ const (
41
+ // transportDefaultConnFlow is how many connection-level flow control
42
+ // tokens we give the server at start-up, past the default 64k.
43
+ transportDefaultConnFlow = 1 << 30
44
+
45
+ // transportDefaultStreamFlow is how many stream-level flow
46
+ // control tokens we announce to the peer, and how many bytes
47
+ // we buffer per stream.
48
+ transportDefaultStreamFlow = 4 << 20
49
+
50
+ defaultUserAgent = "Go-http-client/2.0"
51
+
52
+ // initialMaxConcurrentStreams is a connections maxConcurrentStreams until
53
+ // it's received servers initial SETTINGS frame, which corresponds with the
54
+ // spec's minimum recommended value.
55
+ initialMaxConcurrentStreams = 100
56
+
57
+ // defaultMaxConcurrentStreams is a connections default maxConcurrentStreams
58
+ // if the server doesn't include one in its initial SETTINGS frame.
59
+ defaultMaxConcurrentStreams = 1000
60
+ )
61
+
62
+ // Transport is an HTTP/2 Transport.
63
+ //
64
+ // A Transport internally caches connections to servers. It is safe
65
+ // for concurrent use by multiple goroutines.
66
+ type Transport struct {
67
+ // DialTLSContext specifies an optional dial function with context for
68
+ // creating TLS connections for requests.
69
+ //
70
+ // If DialTLSContext and DialTLS is nil, tls.Dial is used.
71
+ //
72
+ // If the returned net.Conn has a ConnectionState method like tls.Conn,
73
+ // it will be used to set http.Response.TLS.
74
+ DialTLSContext func(ctx context.Context, network, addr string, cfg *tls.Config) (net.Conn, error)
75
+
76
+ // DialTLS specifies an optional dial function for creating
77
+ // TLS connections for requests.
78
+ //
79
+ // If DialTLSContext and DialTLS is nil, tls.Dial is used.
80
+ //
81
+ // Deprecated: Use DialTLSContext instead, which allows the transport
82
+ // to cancel dials as soon as they are no longer needed.
83
+ // If both are set, DialTLSContext takes priority.
84
+ DialTLS func(network, addr string, cfg *tls.Config) (net.Conn, error)
85
+
86
+ // TLSClientConfig specifies the TLS configuration to use with
87
+ // tls.Client. If nil, the default configuration is used.
88
+ TLSClientConfig *tls.Config
89
+
90
+ // ConnPool optionally specifies an alternate connection pool to use.
91
+ // If nil, the default is used.
92
+ ConnPool ClientConnPool
93
+
94
+ // DisableCompression, if true, prevents the Transport from
95
+ // requesting compression with an "Accept-Encoding: gzip"
96
+ // request header when the Request contains no existing
97
+ // Accept-Encoding value. If the Transport requests gzip on
98
+ // its own and gets a gzipped response, it's transparently
99
+ // decoded in the Response.Body. However, if the user
100
+ // explicitly requested gzip it is not automatically
101
+ // uncompressed.
102
+ DisableCompression bool
103
+
104
+ // AllowHTTP, if true, permits HTTP/2 requests using the insecure,
105
+ // plain-text "http" scheme. Note that this does not enable h2c support.
106
+ AllowHTTP bool
107
+
108
+ // MaxHeaderListSize is the http2 SETTINGS_MAX_HEADER_LIST_SIZE to
109
+ // send in the initial settings frame. It is how many bytes
110
+ // of response headers are allowed. Unlike the http2 spec, zero here
111
+ // means to use a default limit (currently 10MB). If you actually
112
+ // want to advertise an unlimited value to the peer, Transport
113
+ // interprets the highest possible value here (0xffffffff or 1<<32-1)
114
+ // to mean no limit.
115
+ MaxHeaderListSize uint32
116
+
117
+ // MaxReadFrameSize is the http2 SETTINGS_MAX_FRAME_SIZE to send in the
118
+ // initial settings frame. It is the size in bytes of the largest frame
119
+ // payload that the sender is willing to receive. If 0, no setting is
120
+ // sent, and the value is provided by the peer, which should be 16384
121
+ // according to the spec:
122
+ // https://datatracker.ietf.org/doc/html/rfc7540#section-6.5.2.
123
+ // Values are bounded in the range 16k to 16M.
124
+ MaxReadFrameSize uint32
125
+
126
+ // MaxDecoderHeaderTableSize optionally specifies the http2
127
+ // SETTINGS_HEADER_TABLE_SIZE to send in the initial settings frame. It
128
+ // informs the remote endpoint of the maximum size of the header compression
129
+ // table used to decode header blocks, in octets. If zero, the default value
130
+ // of 4096 is used.
131
+ MaxDecoderHeaderTableSize uint32
132
+
133
+ // MaxEncoderHeaderTableSize optionally specifies an upper limit for the
134
+ // header compression table used for encoding request headers. Received
135
+ // SETTINGS_HEADER_TABLE_SIZE settings are capped at this limit. If zero,
136
+ // the default value of 4096 is used.
137
+ MaxEncoderHeaderTableSize uint32
138
+
139
+ // StrictMaxConcurrentStreams controls whether the server's
140
+ // SETTINGS_MAX_CONCURRENT_STREAMS should be respected
141
+ // globally. If false, new TCP connections are created to the
142
+ // server as needed to keep each under the per-connection
143
+ // SETTINGS_MAX_CONCURRENT_STREAMS limit. If true, the
144
+ // server's SETTINGS_MAX_CONCURRENT_STREAMS is interpreted as
145
+ // a global limit and callers of RoundTrip block when needed,
146
+ // waiting for their turn.
147
+ StrictMaxConcurrentStreams bool
148
+
149
+ // IdleConnTimeout is the maximum amount of time an idle
150
+ // (keep-alive) connection will remain idle before closing
151
+ // itself.
152
+ // Zero means no limit.
153
+ IdleConnTimeout time.Duration
154
+
155
+ // ReadIdleTimeout is the timeout after which a health check using ping
156
+ // frame will be carried out if no frame is received on the connection.
157
+ // Note that a ping response will is considered a received frame, so if
158
+ // there is no other traffic on the connection, the health check will
159
+ // be performed every ReadIdleTimeout interval.
160
+ // If zero, no health check is performed.
161
+ ReadIdleTimeout time.Duration
162
+
163
+ // PingTimeout is the timeout after which the connection will be closed
164
+ // if a response to Ping is not received.
165
+ // Defaults to 15s.
166
+ PingTimeout time.Duration
167
+
168
+ // WriteByteTimeout is the timeout after which the connection will be
169
+ // closed no data can be written to it. The timeout begins when data is
170
+ // available to write, and is extended whenever any bytes are written.
171
+ WriteByteTimeout time.Duration
172
+
173
+ // CountError, if non-nil, is called on HTTP/2 transport errors.
174
+ // It's intended to increment a metric for monitoring, such
175
+ // as an expvar or Prometheus metric.
176
+ // The errType consists of only ASCII word characters.
177
+ CountError func(errType string)
178
+
179
+ // t1, if non-nil, is the standard library Transport using
180
+ // this transport. Its settings are used (but not its
181
+ // RoundTrip method, etc).
182
+ t1 *http.Transport
183
+
184
+ connPoolOnce sync.Once
185
+ connPoolOrDef ClientConnPool // non-nil version of ConnPool
186
+
187
+ *transportTestHooks
188
+ }
189
+
190
+ // Hook points used for testing.
191
+ // Outside of tests, t.transportTestHooks is nil and these all have minimal implementations.
192
+ // Inside tests, see the testSyncHooks function docs.
193
+
194
+ type transportTestHooks struct {
195
+ newclientconn func(*ClientConn)
196
+ }
197
+
198
+ func (t *Transport) maxHeaderListSize() uint32 {
199
+ n := int64(t.MaxHeaderListSize)
200
+ if t.t1 != nil && t.t1.MaxResponseHeaderBytes != 0 {
201
+ n = t.t1.MaxResponseHeaderBytes
202
+ if n > 0 {
203
+ n = adjustHTTP1MaxHeaderSize(n)
204
+ }
205
+ }
206
+ if n <= 0 {
207
+ return 10 << 20
208
+ }
209
+ if n >= 0xffffffff {
210
+ return 0
211
+ }
212
+ return uint32(n)
213
+ }
214
+
215
+ func (t *Transport) disableCompression() bool {
216
+ return t.DisableCompression || (t.t1 != nil && t.t1.DisableCompression)
217
+ }
218
+
219
+ // ConfigureTransport configures a net/http HTTP/1 Transport to use HTTP/2.
220
+ // It returns an error if t1 has already been HTTP/2-enabled.
221
+ //
222
+ // Use ConfigureTransports instead to configure the HTTP/2 Transport.
223
+ func ConfigureTransport(t1 *http.Transport) error {
224
+ _, err := ConfigureTransports(t1)
225
+ return err
226
+ }
227
+
228
+ // ConfigureTransports configures a net/http HTTP/1 Transport to use HTTP/2.
229
+ // It returns a new HTTP/2 Transport for further configuration.
230
+ // It returns an error if t1 has already been HTTP/2-enabled.
231
+ func ConfigureTransports(t1 *http.Transport) (*Transport, error) {
232
+ return configureTransports(t1)
233
+ }
234
+
235
+ func configureTransports(t1 *http.Transport) (*Transport, error) {
236
+ connPool := new(clientConnPool)
237
+ t2 := &Transport{
238
+ ConnPool: noDialClientConnPool{connPool},
239
+ t1: t1,
240
+ }
241
+ connPool.t = t2
242
+ if err := registerHTTPSProtocol(t1, noDialH2RoundTripper{t2}); err != nil {
243
+ return nil, err
244
+ }
245
+ if t1.TLSClientConfig == nil {
246
+ t1.TLSClientConfig = new(tls.Config)
247
+ }
248
+ if !strSliceContains(t1.TLSClientConfig.NextProtos, "h2") {
249
+ t1.TLSClientConfig.NextProtos = append([]string{"h2"}, t1.TLSClientConfig.NextProtos...)
250
+ }
251
+ if !strSliceContains(t1.TLSClientConfig.NextProtos, "http/1.1") {
252
+ t1.TLSClientConfig.NextProtos = append(t1.TLSClientConfig.NextProtos, "http/1.1")
253
+ }
254
+ upgradeFn := func(scheme, authority string, c net.Conn) http.RoundTripper {
255
+ addr := authorityAddr(scheme, authority)
256
+ if used, err := connPool.addConnIfNeeded(addr, t2, c); err != nil {
257
+ go c.Close()
258
+ return erringRoundTripper{err}
259
+ } else if !used {
260
+ // Turns out we don't need this c.
261
+ // For example, two goroutines made requests to the same host
262
+ // at the same time, both kicking off TCP dials. (since protocol
263
+ // was unknown)
264
+ go c.Close()
265
+ }
266
+ if scheme == "http" {
267
+ return (*unencryptedTransport)(t2)
268
+ }
269
+ return t2
270
+ }
271
+ if t1.TLSNextProto == nil {
272
+ t1.TLSNextProto = make(map[string]func(string, *tls.Conn) http.RoundTripper)
273
+ }
274
+ t1.TLSNextProto[NextProtoTLS] = func(authority string, c *tls.Conn) http.RoundTripper {
275
+ return upgradeFn("https", authority, c)
276
+ }
277
+ // The "unencrypted_http2" TLSNextProto key is used to pass off non-TLS HTTP/2 conns.
278
+ t1.TLSNextProto[nextProtoUnencryptedHTTP2] = func(authority string, c *tls.Conn) http.RoundTripper {
279
+ nc, err := unencryptedNetConnFromTLSConn(c)
280
+ if err != nil {
281
+ go c.Close()
282
+ return erringRoundTripper{err}
283
+ }
284
+ return upgradeFn("http", authority, nc)
285
+ }
286
+ return t2, nil
287
+ }
288
+
289
+ // unencryptedTransport is a Transport with a RoundTrip method that
290
+ // always permits http:// URLs.
291
+ type unencryptedTransport Transport
292
+
293
+ func (t *unencryptedTransport) RoundTrip(req *http.Request) (*http.Response, error) {
294
+ return (*Transport)(t).RoundTripOpt(req, RoundTripOpt{allowHTTP: true})
295
+ }
296
+
297
+ func (t *Transport) connPool() ClientConnPool {
298
+ t.connPoolOnce.Do(t.initConnPool)
299
+ return t.connPoolOrDef
300
+ }
301
+
302
+ func (t *Transport) initConnPool() {
303
+ if t.ConnPool != nil {
304
+ t.connPoolOrDef = t.ConnPool
305
+ } else {
306
+ t.connPoolOrDef = &clientConnPool{t: t}
307
+ }
308
+ }
309
+
310
+ // ClientConn is the state of a single HTTP/2 client connection to an
311
+ // HTTP/2 server.
312
+ type ClientConn struct {
313
+ t *Transport
314
+ tconn net.Conn // usually *tls.Conn, except specialized impls
315
+ tlsState *tls.ConnectionState // nil only for specialized impls
316
+ atomicReused uint32 // whether conn is being reused; atomic
317
+ singleUse bool // whether being used for a single http.Request
318
+ getConnCalled bool // used by clientConnPool
319
+
320
+ // readLoop goroutine fields:
321
+ readerDone chan struct{} // closed on error
322
+ readerErr error // set before readerDone is closed
323
+
324
+ idleTimeout time.Duration // or 0 for never
325
+ idleTimer *time.Timer
326
+
327
+ mu sync.Mutex // guards following
328
+ cond *sync.Cond // hold mu; broadcast on flow/closed changes
329
+ flow outflow // our conn-level flow control quota (cs.outflow is per stream)
330
+ inflow inflow // peer's conn-level flow control
331
+ doNotReuse bool // whether conn is marked to not be reused for any future requests
332
+ closing bool
333
+ closed bool
334
+ closedOnIdle bool // true if conn was closed for idleness
335
+ seenSettings bool // true if we've seen a settings frame, false otherwise
336
+ seenSettingsChan chan struct{} // closed when seenSettings is true or frame reading fails
337
+ wantSettingsAck bool // we sent a SETTINGS frame and haven't heard back
338
+ goAway *GoAwayFrame // if non-nil, the GoAwayFrame we received
339
+ goAwayDebug string // goAway frame's debug data, retained as a string
340
+ streams map[uint32]*clientStream // client-initiated
341
+ streamsReserved int // incr by ReserveNewRequest; decr on RoundTrip
342
+ nextStreamID uint32
343
+ pendingRequests int // requests blocked and waiting to be sent because len(streams) == maxConcurrentStreams
344
+ pings map[[8]byte]chan struct{} // in flight ping data to notification channel
345
+ br *bufio.Reader
346
+ lastActive time.Time
347
+ lastIdle time.Time // time last idle
348
+ // Settings from peer: (also guarded by wmu)
349
+ maxFrameSize uint32
350
+ maxConcurrentStreams uint32
351
+ peerMaxHeaderListSize uint64
352
+ peerMaxHeaderTableSize uint32
353
+ initialWindowSize uint32
354
+ initialStreamRecvWindowSize int32
355
+ readIdleTimeout time.Duration
356
+ pingTimeout time.Duration
357
+ extendedConnectAllowed bool
358
+
359
+ // rstStreamPingsBlocked works around an unfortunate gRPC behavior.
360
+ // gRPC strictly limits the number of PING frames that it will receive.
361
+ // The default is two pings per two hours, but the limit resets every time
362
+ // the gRPC endpoint sends a HEADERS or DATA frame. See golang/go#70575.
363
+ //
364
+ // rstStreamPingsBlocked is set after receiving a response to a PING frame
365
+ // bundled with an RST_STREAM (see pendingResets below), and cleared after
366
+ // receiving a HEADERS or DATA frame.
367
+ rstStreamPingsBlocked bool
368
+
369
+ // pendingResets is the number of RST_STREAM frames we have sent to the peer,
370
+ // without confirming that the peer has received them. When we send a RST_STREAM,
371
+ // we bundle it with a PING frame, unless a PING is already in flight. We count
372
+ // the reset stream against the connection's concurrency limit until we get
373
+ // a PING response. This limits the number of requests we'll try to send to a
374
+ // completely unresponsive connection.
375
+ pendingResets int
376
+
377
+ // reqHeaderMu is a 1-element semaphore channel controlling access to sending new requests.
378
+ // Write to reqHeaderMu to lock it, read from it to unlock.
379
+ // Lock reqmu BEFORE mu or wmu.
380
+ reqHeaderMu chan struct{}
381
+
382
+ // wmu is held while writing.
383
+ // Acquire BEFORE mu when holding both, to avoid blocking mu on network writes.
384
+ // Only acquire both at the same time when changing peer settings.
385
+ wmu sync.Mutex
386
+ bw *bufio.Writer
387
+ fr *Framer
388
+ werr error // first write error that has occurred
389
+ hbuf bytes.Buffer // HPACK encoder writes into this
390
+ henc *hpack.Encoder
391
+ }
392
+
393
+ // clientStream is the state for a single HTTP/2 stream. One of these
394
+ // is created for each Transport.RoundTrip call.
395
+ type clientStream struct {
396
+ cc *ClientConn
397
+
398
+ // Fields of Request that we may access even after the response body is closed.
399
+ ctx context.Context
400
+ reqCancel <-chan struct{}
401
+
402
+ trace *httptrace.ClientTrace // or nil
403
+ ID uint32
404
+ bufPipe pipe // buffered pipe with the flow-controlled response payload
405
+ requestedGzip bool
406
+ isHead bool
407
+
408
+ abortOnce sync.Once
409
+ abort chan struct{} // closed to signal stream should end immediately
410
+ abortErr error // set if abort is closed
411
+
412
+ peerClosed chan struct{} // closed when the peer sends an END_STREAM flag
413
+ donec chan struct{} // closed after the stream is in the closed state
414
+ on100 chan struct{} // buffered; written to if a 100 is received
415
+
416
+ respHeaderRecv chan struct{} // closed when headers are received
417
+ res *http.Response // set if respHeaderRecv is closed
418
+
419
+ flow outflow // guarded by cc.mu
420
+ inflow inflow // guarded by cc.mu
421
+ bytesRemain int64 // -1 means unknown; owned by transportResponseBody.Read
422
+ readErr error // sticky read error; owned by transportResponseBody.Read
423
+
424
+ reqBody io.ReadCloser
425
+ reqBodyContentLength int64 // -1 means unknown
426
+ reqBodyClosed chan struct{} // guarded by cc.mu; non-nil on Close, closed when done
427
+
428
+ // owned by writeRequest:
429
+ sentEndStream bool // sent an END_STREAM flag to the peer
430
+ sentHeaders bool
431
+
432
+ // owned by clientConnReadLoop:
433
+ firstByte bool // got the first response byte
434
+ pastHeaders bool // got first MetaHeadersFrame (actual headers)
435
+ pastTrailers bool // got optional second MetaHeadersFrame (trailers)
436
+ readClosed bool // peer sent an END_STREAM flag
437
+ readAborted bool // read loop reset the stream
438
+ totalHeaderSize int64 // total size of 1xx headers seen
439
+
440
+ trailer http.Header // accumulated trailers
441
+ resTrailer *http.Header // client's Response.Trailer
442
+ }
443
+
444
+ var got1xxFuncForTests func(int, textproto.MIMEHeader) error
445
+
446
+ // get1xxTraceFunc returns the value of request's httptrace.ClientTrace.Got1xxResponse func,
447
+ // if any. It returns nil if not set or if the Go version is too old.
448
+ func (cs *clientStream) get1xxTraceFunc() func(int, textproto.MIMEHeader) error {
449
+ if fn := got1xxFuncForTests; fn != nil {
450
+ return fn
451
+ }
452
+ return traceGot1xxResponseFunc(cs.trace)
453
+ }
454
+
455
+ func (cs *clientStream) abortStream(err error) {
456
+ cs.cc.mu.Lock()
457
+ defer cs.cc.mu.Unlock()
458
+ cs.abortStreamLocked(err)
459
+ }
460
+
461
+ func (cs *clientStream) abortStreamLocked(err error) {
462
+ cs.abortOnce.Do(func() {
463
+ cs.abortErr = err
464
+ close(cs.abort)
465
+ })
466
+ if cs.reqBody != nil {
467
+ cs.closeReqBodyLocked()
468
+ }
469
+ // TODO(dneil): Clean up tests where cs.cc.cond is nil.
470
+ if cs.cc.cond != nil {
471
+ // Wake up writeRequestBody if it is waiting on flow control.
472
+ cs.cc.cond.Broadcast()
473
+ }
474
+ }
475
+
476
+ func (cs *clientStream) abortRequestBodyWrite() {
477
+ cc := cs.cc
478
+ cc.mu.Lock()
479
+ defer cc.mu.Unlock()
480
+ if cs.reqBody != nil && cs.reqBodyClosed == nil {
481
+ cs.closeReqBodyLocked()
482
+ cc.cond.Broadcast()
483
+ }
484
+ }
485
+
486
+ func (cs *clientStream) closeReqBodyLocked() {
487
+ if cs.reqBodyClosed != nil {
488
+ return
489
+ }
490
+ cs.reqBodyClosed = make(chan struct{})
491
+ reqBodyClosed := cs.reqBodyClosed
492
+ go func() {
493
+ cs.reqBody.Close()
494
+ close(reqBodyClosed)
495
+ }()
496
+ }
497
+
498
+ type stickyErrWriter struct {
499
+ conn net.Conn
500
+ timeout time.Duration
501
+ err *error
502
+ }
503
+
504
+ func (sew stickyErrWriter) Write(p []byte) (n int, err error) {
505
+ if *sew.err != nil {
506
+ return 0, *sew.err
507
+ }
508
+ n, err = writeWithByteTimeout(sew.conn, sew.timeout, p)
509
+ *sew.err = err
510
+ return n, err
511
+ }
512
+
513
+ // noCachedConnError is the concrete type of ErrNoCachedConn, which
514
+ // needs to be detected by net/http regardless of whether it's its
515
+ // bundled version (in h2_bundle.go with a rewritten type name) or
516
+ // from a user's x/net/http2. As such, as it has a unique method name
517
+ // (IsHTTP2NoCachedConnError) that net/http sniffs for via func
518
+ // isNoCachedConnError.
519
+ type noCachedConnError struct{}
520
+
521
+ func (noCachedConnError) IsHTTP2NoCachedConnError() {}
522
+ func (noCachedConnError) Error() string { return "http2: no cached connection was available" }
523
+
524
+ // isNoCachedConnError reports whether err is of type noCachedConnError
525
+ // or its equivalent renamed type in net/http2's h2_bundle.go. Both types
526
+ // may coexist in the same running program.
527
+ func isNoCachedConnError(err error) bool {
528
+ _, ok := err.(interface{ IsHTTP2NoCachedConnError() })
529
+ return ok
530
+ }
531
+
532
+ var ErrNoCachedConn error = noCachedConnError{}
533
+
534
+ // RoundTripOpt are options for the Transport.RoundTripOpt method.
535
+ type RoundTripOpt struct {
536
+ // OnlyCachedConn controls whether RoundTripOpt may
537
+ // create a new TCP connection. If set true and
538
+ // no cached connection is available, RoundTripOpt
539
+ // will return ErrNoCachedConn.
540
+ OnlyCachedConn bool
541
+
542
+ allowHTTP bool // allow http:// URLs
543
+ }
544
+
545
+ func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) {
546
+ return t.RoundTripOpt(req, RoundTripOpt{})
547
+ }
548
+
549
+ // authorityAddr returns a given authority (a host/IP, or host:port / ip:port)
550
+ // and returns a host:port. The port 443 is added if needed.
551
+ func authorityAddr(scheme string, authority string) (addr string) {
552
+ host, port, err := net.SplitHostPort(authority)
553
+ if err != nil { // authority didn't have a port
554
+ host = authority
555
+ port = ""
556
+ }
557
+ if port == "" { // authority's port was empty
558
+ port = "443"
559
+ if scheme == "http" {
560
+ port = "80"
561
+ }
562
+ }
563
+ if a, err := idna.ToASCII(host); err == nil {
564
+ host = a
565
+ }
566
+ // IPv6 address literal, without a port:
567
+ if strings.HasPrefix(host, "[") && strings.HasSuffix(host, "]") {
568
+ return host + ":" + port
569
+ }
570
+ return net.JoinHostPort(host, port)
571
+ }
572
+
573
+ // RoundTripOpt is like RoundTrip, but takes options.
574
+ func (t *Transport) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Response, error) {
575
+ switch req.URL.Scheme {
576
+ case "https":
577
+ // Always okay.
578
+ case "http":
579
+ if !t.AllowHTTP && !opt.allowHTTP {
580
+ return nil, errors.New("http2: unencrypted HTTP/2 not enabled")
581
+ }
582
+ default:
583
+ return nil, errors.New("http2: unsupported scheme")
584
+ }
585
+
586
+ addr := authorityAddr(req.URL.Scheme, req.URL.Host)
587
+ for retry := 0; ; retry++ {
588
+ cc, err := t.connPool().GetClientConn(req, addr)
589
+ if err != nil {
590
+ t.vlogf("http2: Transport failed to get client conn for %s: %v", addr, err)
591
+ return nil, err
592
+ }
593
+ reused := !atomic.CompareAndSwapUint32(&cc.atomicReused, 0, 1)
594
+ traceGotConn(req, cc, reused)
595
+ res, err := cc.RoundTrip(req)
596
+ if err != nil && retry <= 6 {
597
+ roundTripErr := err
598
+ if req, err = shouldRetryRequest(req, err); err == nil {
599
+ // After the first retry, do exponential backoff with 10% jitter.
600
+ if retry == 0 {
601
+ t.vlogf("RoundTrip retrying after failure: %v", roundTripErr)
602
+ continue
603
+ }
604
+ backoff := float64(uint(1) << (uint(retry) - 1))
605
+ backoff += backoff * (0.1 * mathrand.Float64())
606
+ d := time.Second * time.Duration(backoff)
607
+ tm := time.NewTimer(d)
608
+ select {
609
+ case <-tm.C:
610
+ t.vlogf("RoundTrip retrying after failure: %v", roundTripErr)
611
+ continue
612
+ case <-req.Context().Done():
613
+ tm.Stop()
614
+ err = req.Context().Err()
615
+ }
616
+ }
617
+ }
618
+ if err == errClientConnNotEstablished {
619
+ // This ClientConn was created recently,
620
+ // this is the first request to use it,
621
+ // and the connection is closed and not usable.
622
+ //
623
+ // In this state, cc.idleTimer will remove the conn from the pool
624
+ // when it fires. Stop the timer and remove it here so future requests
625
+ // won't try to use this connection.
626
+ //
627
+ // If the timer has already fired and we're racing it, the redundant
628
+ // call to MarkDead is harmless.
629
+ if cc.idleTimer != nil {
630
+ cc.idleTimer.Stop()
631
+ }
632
+ t.connPool().MarkDead(cc)
633
+ }
634
+ if err != nil {
635
+ t.vlogf("RoundTrip failure: %v", err)
636
+ return nil, err
637
+ }
638
+ return res, nil
639
+ }
640
+ }
641
+
642
+ // CloseIdleConnections closes any connections which were previously
643
+ // connected from previous requests but are now sitting idle.
644
+ // It does not interrupt any connections currently in use.
645
+ func (t *Transport) CloseIdleConnections() {
646
+ if cp, ok := t.connPool().(clientConnPoolIdleCloser); ok {
647
+ cp.closeIdleConnections()
648
+ }
649
+ }
650
+
651
+ var (
652
+ errClientConnClosed = errors.New("http2: client conn is closed")
653
+ errClientConnUnusable = errors.New("http2: client conn not usable")
654
+ errClientConnNotEstablished = errors.New("http2: client conn could not be established")
655
+ errClientConnGotGoAway = errors.New("http2: Transport received Server's graceful shutdown GOAWAY")
656
+ errClientConnForceClosed = errors.New("http2: client connection force closed via ClientConn.Close")
657
+ )
658
+
659
+ // shouldRetryRequest is called by RoundTrip when a request fails to get
660
+ // response headers. It is always called with a non-nil error.
661
+ // It returns either a request to retry (either the same request, or a
662
+ // modified clone), or an error if the request can't be replayed.
663
+ func shouldRetryRequest(req *http.Request, err error) (*http.Request, error) {
664
+ if !canRetryError(err) {
665
+ return nil, err
666
+ }
667
+ // If the Body is nil (or http.NoBody), it's safe to reuse
668
+ // this request and its Body.
669
+ if req.Body == nil || req.Body == http.NoBody {
670
+ return req, nil
671
+ }
672
+
673
+ // If the request body can be reset back to its original
674
+ // state via the optional req.GetBody, do that.
675
+ if req.GetBody != nil {
676
+ body, err := req.GetBody()
677
+ if err != nil {
678
+ return nil, err
679
+ }
680
+ newReq := *req
681
+ newReq.Body = body
682
+ return &newReq, nil
683
+ }
684
+
685
+ // The Request.Body can't reset back to the beginning, but we
686
+ // don't seem to have started to read from it yet, so reuse
687
+ // the request directly.
688
+ if err == errClientConnUnusable {
689
+ return req, nil
690
+ }
691
+
692
+ return nil, fmt.Errorf("http2: Transport: cannot retry err [%v] after Request.Body was written; define Request.GetBody to avoid this error", err)
693
+ }
694
+
695
+ func canRetryError(err error) bool {
696
+ if err == errClientConnUnusable || err == errClientConnGotGoAway {
697
+ return true
698
+ }
699
+ if se, ok := err.(StreamError); ok {
700
+ if se.Code == ErrCodeProtocol && se.Cause == errFromPeer {
701
+ // See golang/go#47635, golang/go#42777
702
+ return true
703
+ }
704
+ return se.Code == ErrCodeRefusedStream
705
+ }
706
+ return false
707
+ }
708
+
709
+ func (t *Transport) dialClientConn(ctx context.Context, addr string, singleUse bool) (*ClientConn, error) {
710
+ if t.transportTestHooks != nil {
711
+ return t.newClientConn(nil, singleUse)
712
+ }
713
+ host, _, err := net.SplitHostPort(addr)
714
+ if err != nil {
715
+ return nil, err
716
+ }
717
+ tconn, err := t.dialTLS(ctx, "tcp", addr, t.newTLSConfig(host))
718
+ if err != nil {
719
+ return nil, err
720
+ }
721
+ return t.newClientConn(tconn, singleUse)
722
+ }
723
+
724
+ func (t *Transport) newTLSConfig(host string) *tls.Config {
725
+ cfg := new(tls.Config)
726
+ if t.TLSClientConfig != nil {
727
+ *cfg = *t.TLSClientConfig.Clone()
728
+ }
729
+ if !strSliceContains(cfg.NextProtos, NextProtoTLS) {
730
+ cfg.NextProtos = append([]string{NextProtoTLS}, cfg.NextProtos...)
731
+ }
732
+ if cfg.ServerName == "" {
733
+ cfg.ServerName = host
734
+ }
735
+ return cfg
736
+ }
737
+
738
+ func (t *Transport) dialTLS(ctx context.Context, network, addr string, tlsCfg *tls.Config) (net.Conn, error) {
739
+ if t.DialTLSContext != nil {
740
+ return t.DialTLSContext(ctx, network, addr, tlsCfg)
741
+ } else if t.DialTLS != nil {
742
+ return t.DialTLS(network, addr, tlsCfg)
743
+ }
744
+
745
+ tlsCn, err := t.dialTLSWithContext(ctx, network, addr, tlsCfg)
746
+ if err != nil {
747
+ return nil, err
748
+ }
749
+ state := tlsCn.ConnectionState()
750
+ if p := state.NegotiatedProtocol; p != NextProtoTLS {
751
+ return nil, fmt.Errorf("http2: unexpected ALPN protocol %q; want %q", p, NextProtoTLS)
752
+ }
753
+ if !state.NegotiatedProtocolIsMutual {
754
+ return nil, errors.New("http2: could not negotiate protocol mutually")
755
+ }
756
+ return tlsCn, nil
757
+ }
758
+
759
+ // disableKeepAlives reports whether connections should be closed as
760
+ // soon as possible after handling the first request.
761
+ func (t *Transport) disableKeepAlives() bool {
762
+ return t.t1 != nil && t.t1.DisableKeepAlives
763
+ }
764
+
765
+ func (t *Transport) expectContinueTimeout() time.Duration {
766
+ if t.t1 == nil {
767
+ return 0
768
+ }
769
+ return t.t1.ExpectContinueTimeout
770
+ }
771
+
772
+ func (t *Transport) NewClientConn(c net.Conn) (*ClientConn, error) {
773
+ return t.newClientConn(c, t.disableKeepAlives())
774
+ }
775
+
776
+ func (t *Transport) newClientConn(c net.Conn, singleUse bool) (*ClientConn, error) {
777
+ conf := configFromTransport(t)
778
+ cc := &ClientConn{
779
+ t: t,
780
+ tconn: c,
781
+ readerDone: make(chan struct{}),
782
+ nextStreamID: 1,
783
+ maxFrameSize: 16 << 10, // spec default
784
+ initialWindowSize: 65535, // spec default
785
+ initialStreamRecvWindowSize: conf.MaxUploadBufferPerStream,
786
+ maxConcurrentStreams: initialMaxConcurrentStreams, // "infinite", per spec. Use a smaller value until we have received server settings.
787
+ peerMaxHeaderListSize: 0xffffffffffffffff, // "infinite", per spec. Use 2^64-1 instead.
788
+ streams: make(map[uint32]*clientStream),
789
+ singleUse: singleUse,
790
+ seenSettingsChan: make(chan struct{}),
791
+ wantSettingsAck: true,
792
+ readIdleTimeout: conf.SendPingTimeout,
793
+ pingTimeout: conf.PingTimeout,
794
+ pings: make(map[[8]byte]chan struct{}),
795
+ reqHeaderMu: make(chan struct{}, 1),
796
+ lastActive: time.Now(),
797
+ }
798
+ if t.transportTestHooks != nil {
799
+ t.transportTestHooks.newclientconn(cc)
800
+ c = cc.tconn
801
+ }
802
+ if VerboseLogs {
803
+ t.vlogf("http2: Transport creating client conn %p to %v", cc, c.RemoteAddr())
804
+ }
805
+
806
+ cc.cond = sync.NewCond(&cc.mu)
807
+ cc.flow.add(int32(initialWindowSize))
808
+
809
+ // TODO: adjust this writer size to account for frame size +
810
+ // MTU + crypto/tls record padding.
811
+ cc.bw = bufio.NewWriter(stickyErrWriter{
812
+ conn: c,
813
+ timeout: conf.WriteByteTimeout,
814
+ err: &cc.werr,
815
+ })
816
+ cc.br = bufio.NewReader(c)
817
+ cc.fr = NewFramer(cc.bw, cc.br)
818
+ cc.fr.SetMaxReadFrameSize(conf.MaxReadFrameSize)
819
+ if t.CountError != nil {
820
+ cc.fr.countError = t.CountError
821
+ }
822
+ maxHeaderTableSize := conf.MaxDecoderHeaderTableSize
823
+ cc.fr.ReadMetaHeaders = hpack.NewDecoder(maxHeaderTableSize, nil)
824
+ cc.fr.MaxHeaderListSize = t.maxHeaderListSize()
825
+
826
+ cc.henc = hpack.NewEncoder(&cc.hbuf)
827
+ cc.henc.SetMaxDynamicTableSizeLimit(conf.MaxEncoderHeaderTableSize)
828
+ cc.peerMaxHeaderTableSize = initialHeaderTableSize
829
+
830
+ if cs, ok := c.(connectionStater); ok {
831
+ state := cs.ConnectionState()
832
+ cc.tlsState = &state
833
+ }
834
+
835
+ initialSettings := []Setting{
836
+ {ID: SettingEnablePush, Val: 0},
837
+ {ID: SettingInitialWindowSize, Val: uint32(cc.initialStreamRecvWindowSize)},
838
+ }
839
+ initialSettings = append(initialSettings, Setting{ID: SettingMaxFrameSize, Val: conf.MaxReadFrameSize})
840
+ if max := t.maxHeaderListSize(); max != 0 {
841
+ initialSettings = append(initialSettings, Setting{ID: SettingMaxHeaderListSize, Val: max})
842
+ }
843
+ if maxHeaderTableSize != initialHeaderTableSize {
844
+ initialSettings = append(initialSettings, Setting{ID: SettingHeaderTableSize, Val: maxHeaderTableSize})
845
+ }
846
+
847
+ cc.bw.Write(clientPreface)
848
+ cc.fr.WriteSettings(initialSettings...)
849
+ cc.fr.WriteWindowUpdate(0, uint32(conf.MaxUploadBufferPerConnection))
850
+ cc.inflow.init(conf.MaxUploadBufferPerConnection + initialWindowSize)
851
+ cc.bw.Flush()
852
+ if cc.werr != nil {
853
+ cc.Close()
854
+ return nil, cc.werr
855
+ }
856
+
857
+ // Start the idle timer after the connection is fully initialized.
858
+ if d := t.idleConnTimeout(); d != 0 {
859
+ cc.idleTimeout = d
860
+ cc.idleTimer = time.AfterFunc(d, cc.onIdleTimeout)
861
+ }
862
+
863
+ go cc.readLoop()
864
+ return cc, nil
865
+ }
866
+
867
+ func (cc *ClientConn) healthCheck() {
868
+ pingTimeout := cc.pingTimeout
869
+ // We don't need to periodically ping in the health check, because the readLoop of ClientConn will
870
+ // trigger the healthCheck again if there is no frame received.
871
+ ctx, cancel := context.WithTimeout(context.Background(), pingTimeout)
872
+ defer cancel()
873
+ cc.vlogf("http2: Transport sending health check")
874
+ err := cc.Ping(ctx)
875
+ if err != nil {
876
+ cc.vlogf("http2: Transport health check failure: %v", err)
877
+ cc.closeForLostPing()
878
+ } else {
879
+ cc.vlogf("http2: Transport health check success")
880
+ }
881
+ }
882
+
883
+ // SetDoNotReuse marks cc as not reusable for future HTTP requests.
884
+ func (cc *ClientConn) SetDoNotReuse() {
885
+ cc.mu.Lock()
886
+ defer cc.mu.Unlock()
887
+ cc.doNotReuse = true
888
+ }
889
+
890
+ func (cc *ClientConn) setGoAway(f *GoAwayFrame) {
891
+ cc.mu.Lock()
892
+ defer cc.mu.Unlock()
893
+
894
+ old := cc.goAway
895
+ cc.goAway = f
896
+
897
+ // Merge the previous and current GoAway error frames.
898
+ if cc.goAwayDebug == "" {
899
+ cc.goAwayDebug = string(f.DebugData())
900
+ }
901
+ if old != nil && old.ErrCode != ErrCodeNo {
902
+ cc.goAway.ErrCode = old.ErrCode
903
+ }
904
+ last := f.LastStreamID
905
+ for streamID, cs := range cc.streams {
906
+ if streamID <= last {
907
+ // The server's GOAWAY indicates that it received this stream.
908
+ // It will either finish processing it, or close the connection
909
+ // without doing so. Either way, leave the stream alone for now.
910
+ continue
911
+ }
912
+ if streamID == 1 && cc.goAway.ErrCode != ErrCodeNo {
913
+ // Don't retry the first stream on a connection if we get a non-NO error.
914
+ // If the server is sending an error on a new connection,
915
+ // retrying the request on a new one probably isn't going to work.
916
+ cs.abortStreamLocked(fmt.Errorf("http2: Transport received GOAWAY from server ErrCode:%v", cc.goAway.ErrCode))
917
+ } else {
918
+ // Aborting the stream with errClentConnGotGoAway indicates that
919
+ // the request should be retried on a new connection.
920
+ cs.abortStreamLocked(errClientConnGotGoAway)
921
+ }
922
+ }
923
+ }
924
+
925
+ // CanTakeNewRequest reports whether the connection can take a new request,
926
+ // meaning it has not been closed or received or sent a GOAWAY.
927
+ //
928
+ // If the caller is going to immediately make a new request on this
929
+ // connection, use ReserveNewRequest instead.
930
+ func (cc *ClientConn) CanTakeNewRequest() bool {
931
+ cc.mu.Lock()
932
+ defer cc.mu.Unlock()
933
+ return cc.canTakeNewRequestLocked()
934
+ }
935
+
936
+ // ReserveNewRequest is like CanTakeNewRequest but also reserves a
937
+ // concurrent stream in cc. The reservation is decremented on the
938
+ // next call to RoundTrip.
939
+ func (cc *ClientConn) ReserveNewRequest() bool {
940
+ cc.mu.Lock()
941
+ defer cc.mu.Unlock()
942
+ if st := cc.idleStateLocked(); !st.canTakeNewRequest {
943
+ return false
944
+ }
945
+ cc.streamsReserved++
946
+ return true
947
+ }
948
+
949
+ // ClientConnState describes the state of a ClientConn.
950
+ type ClientConnState struct {
951
+ // Closed is whether the connection is closed.
952
+ Closed bool
953
+
954
+ // Closing is whether the connection is in the process of
955
+ // closing. It may be closing due to shutdown, being a
956
+ // single-use connection, being marked as DoNotReuse, or
957
+ // having received a GOAWAY frame.
958
+ Closing bool
959
+
960
+ // StreamsActive is how many streams are active.
961
+ StreamsActive int
962
+
963
+ // StreamsReserved is how many streams have been reserved via
964
+ // ClientConn.ReserveNewRequest.
965
+ StreamsReserved int
966
+
967
+ // StreamsPending is how many requests have been sent in excess
968
+ // of the peer's advertised MaxConcurrentStreams setting and
969
+ // are waiting for other streams to complete.
970
+ StreamsPending int
971
+
972
+ // MaxConcurrentStreams is how many concurrent streams the
973
+ // peer advertised as acceptable. Zero means no SETTINGS
974
+ // frame has been received yet.
975
+ MaxConcurrentStreams uint32
976
+
977
+ // LastIdle, if non-zero, is when the connection last
978
+ // transitioned to idle state.
979
+ LastIdle time.Time
980
+ }
981
+
982
+ // State returns a snapshot of cc's state.
983
+ func (cc *ClientConn) State() ClientConnState {
984
+ cc.wmu.Lock()
985
+ maxConcurrent := cc.maxConcurrentStreams
986
+ if !cc.seenSettings {
987
+ maxConcurrent = 0
988
+ }
989
+ cc.wmu.Unlock()
990
+
991
+ cc.mu.Lock()
992
+ defer cc.mu.Unlock()
993
+ return ClientConnState{
994
+ Closed: cc.closed,
995
+ Closing: cc.closing || cc.singleUse || cc.doNotReuse || cc.goAway != nil,
996
+ StreamsActive: len(cc.streams) + cc.pendingResets,
997
+ StreamsReserved: cc.streamsReserved,
998
+ StreamsPending: cc.pendingRequests,
999
+ LastIdle: cc.lastIdle,
1000
+ MaxConcurrentStreams: maxConcurrent,
1001
+ }
1002
+ }
1003
+
1004
+ // clientConnIdleState describes the suitability of a client
1005
+ // connection to initiate a new RoundTrip request.
1006
+ type clientConnIdleState struct {
1007
+ canTakeNewRequest bool
1008
+ }
1009
+
1010
+ func (cc *ClientConn) idleState() clientConnIdleState {
1011
+ cc.mu.Lock()
1012
+ defer cc.mu.Unlock()
1013
+ return cc.idleStateLocked()
1014
+ }
1015
+
1016
+ func (cc *ClientConn) idleStateLocked() (st clientConnIdleState) {
1017
+ if cc.singleUse && cc.nextStreamID > 1 {
1018
+ return
1019
+ }
1020
+ var maxConcurrentOkay bool
1021
+ if cc.t.StrictMaxConcurrentStreams {
1022
+ // We'll tell the caller we can take a new request to
1023
+ // prevent the caller from dialing a new TCP
1024
+ // connection, but then we'll block later before
1025
+ // writing it.
1026
+ maxConcurrentOkay = true
1027
+ } else {
1028
+ // We can take a new request if the total of
1029
+ // - active streams;
1030
+ // - reservation slots for new streams; and
1031
+ // - streams for which we have sent a RST_STREAM and a PING,
1032
+ // but received no subsequent frame
1033
+ // is less than the concurrency limit.
1034
+ maxConcurrentOkay = cc.currentRequestCountLocked() < int(cc.maxConcurrentStreams)
1035
+ }
1036
+
1037
+ st.canTakeNewRequest = cc.goAway == nil && !cc.closed && !cc.closing && maxConcurrentOkay &&
1038
+ !cc.doNotReuse &&
1039
+ int64(cc.nextStreamID)+2*int64(cc.pendingRequests) < math.MaxInt32 &&
1040
+ !cc.tooIdleLocked()
1041
+
1042
+ // If this connection has never been used for a request and is closed,
1043
+ // then let it take a request (which will fail).
1044
+ // If the conn was closed for idleness, we're racing the idle timer;
1045
+ // don't try to use the conn. (Issue #70515.)
1046
+ //
1047
+ // This avoids a situation where an error early in a connection's lifetime
1048
+ // goes unreported.
1049
+ if cc.nextStreamID == 1 && cc.streamsReserved == 0 && cc.closed && !cc.closedOnIdle {
1050
+ st.canTakeNewRequest = true
1051
+ }
1052
+
1053
+ return
1054
+ }
1055
+
1056
+ // currentRequestCountLocked reports the number of concurrency slots currently in use,
1057
+ // including active streams, reserved slots, and reset streams waiting for acknowledgement.
1058
+ func (cc *ClientConn) currentRequestCountLocked() int {
1059
+ return len(cc.streams) + cc.streamsReserved + cc.pendingResets
1060
+ }
1061
+
1062
+ func (cc *ClientConn) canTakeNewRequestLocked() bool {
1063
+ st := cc.idleStateLocked()
1064
+ return st.canTakeNewRequest
1065
+ }
1066
+
1067
+ // tooIdleLocked reports whether this connection has been been sitting idle
1068
+ // for too much wall time.
1069
+ func (cc *ClientConn) tooIdleLocked() bool {
1070
+ // The Round(0) strips the monontonic clock reading so the
1071
+ // times are compared based on their wall time. We don't want
1072
+ // to reuse a connection that's been sitting idle during
1073
+ // VM/laptop suspend if monotonic time was also frozen.
1074
+ return cc.idleTimeout != 0 && !cc.lastIdle.IsZero() && time.Since(cc.lastIdle.Round(0)) > cc.idleTimeout
1075
+ }
1076
+
1077
+ // onIdleTimeout is called from a time.AfterFunc goroutine. It will
1078
+ // only be called when we're idle, but because we're coming from a new
1079
+ // goroutine, there could be a new request coming in at the same time,
1080
+ // so this simply calls the synchronized closeIfIdle to shut down this
1081
+ // connection. The timer could just call closeIfIdle, but this is more
1082
+ // clear.
1083
+ func (cc *ClientConn) onIdleTimeout() {
1084
+ cc.closeIfIdle()
1085
+ }
1086
+
1087
+ func (cc *ClientConn) closeConn() {
1088
+ t := time.AfterFunc(250*time.Millisecond, cc.forceCloseConn)
1089
+ defer t.Stop()
1090
+ cc.tconn.Close()
1091
+ }
1092
+
1093
+ // A tls.Conn.Close can hang for a long time if the peer is unresponsive.
1094
+ // Try to shut it down more aggressively.
1095
+ func (cc *ClientConn) forceCloseConn() {
1096
+ tc, ok := cc.tconn.(*tls.Conn)
1097
+ if !ok {
1098
+ return
1099
+ }
1100
+ if nc := tc.NetConn(); nc != nil {
1101
+ nc.Close()
1102
+ }
1103
+ }
1104
+
1105
+ func (cc *ClientConn) closeIfIdle() {
1106
+ cc.mu.Lock()
1107
+ if len(cc.streams) > 0 || cc.streamsReserved > 0 {
1108
+ cc.mu.Unlock()
1109
+ return
1110
+ }
1111
+ cc.closed = true
1112
+ cc.closedOnIdle = true
1113
+ nextID := cc.nextStreamID
1114
+ // TODO: do clients send GOAWAY too? maybe? Just Close:
1115
+ cc.mu.Unlock()
1116
+
1117
+ if VerboseLogs {
1118
+ cc.vlogf("http2: Transport closing idle conn %p (forSingleUse=%v, maxStream=%v)", cc, cc.singleUse, nextID-2)
1119
+ }
1120
+ cc.closeConn()
1121
+ }
1122
+
1123
+ func (cc *ClientConn) isDoNotReuseAndIdle() bool {
1124
+ cc.mu.Lock()
1125
+ defer cc.mu.Unlock()
1126
+ return cc.doNotReuse && len(cc.streams) == 0
1127
+ }
1128
+
1129
+ var shutdownEnterWaitStateHook = func() {}
1130
+
1131
+ // Shutdown gracefully closes the client connection, waiting for running streams to complete.
1132
+ func (cc *ClientConn) Shutdown(ctx context.Context) error {
1133
+ if err := cc.sendGoAway(); err != nil {
1134
+ return err
1135
+ }
1136
+ // Wait for all in-flight streams to complete or connection to close
1137
+ done := make(chan struct{})
1138
+ cancelled := false // guarded by cc.mu
1139
+ go func() {
1140
+ cc.mu.Lock()
1141
+ defer cc.mu.Unlock()
1142
+ for {
1143
+ if len(cc.streams) == 0 || cc.closed {
1144
+ cc.closed = true
1145
+ close(done)
1146
+ break
1147
+ }
1148
+ if cancelled {
1149
+ break
1150
+ }
1151
+ cc.cond.Wait()
1152
+ }
1153
+ }()
1154
+ shutdownEnterWaitStateHook()
1155
+ select {
1156
+ case <-done:
1157
+ cc.closeConn()
1158
+ return nil
1159
+ case <-ctx.Done():
1160
+ cc.mu.Lock()
1161
+ // Free the goroutine above
1162
+ cancelled = true
1163
+ cc.cond.Broadcast()
1164
+ cc.mu.Unlock()
1165
+ return ctx.Err()
1166
+ }
1167
+ }
1168
+
1169
+ func (cc *ClientConn) sendGoAway() error {
1170
+ cc.mu.Lock()
1171
+ closing := cc.closing
1172
+ cc.closing = true
1173
+ maxStreamID := cc.nextStreamID
1174
+ cc.mu.Unlock()
1175
+ if closing {
1176
+ // GOAWAY sent already
1177
+ return nil
1178
+ }
1179
+
1180
+ cc.wmu.Lock()
1181
+ defer cc.wmu.Unlock()
1182
+ // Send a graceful shutdown frame to server
1183
+ if err := cc.fr.WriteGoAway(maxStreamID, ErrCodeNo, nil); err != nil {
1184
+ return err
1185
+ }
1186
+ if err := cc.bw.Flush(); err != nil {
1187
+ return err
1188
+ }
1189
+ // Prevent new requests
1190
+ return nil
1191
+ }
1192
+
1193
+ // closes the client connection immediately. In-flight requests are interrupted.
1194
+ // err is sent to streams.
1195
+ func (cc *ClientConn) closeForError(err error) {
1196
+ cc.mu.Lock()
1197
+ cc.closed = true
1198
+ for _, cs := range cc.streams {
1199
+ cs.abortStreamLocked(err)
1200
+ }
1201
+ cc.cond.Broadcast()
1202
+ cc.mu.Unlock()
1203
+ cc.closeConn()
1204
+ }
1205
+
1206
+ // Close closes the client connection immediately.
1207
+ //
1208
+ // In-flight requests are interrupted. For a graceful shutdown, use Shutdown instead.
1209
+ func (cc *ClientConn) Close() error {
1210
+ cc.closeForError(errClientConnForceClosed)
1211
+ return nil
1212
+ }
1213
+
1214
+ // closes the client connection immediately. In-flight requests are interrupted.
1215
+ func (cc *ClientConn) closeForLostPing() {
1216
+ err := errors.New("http2: client connection lost")
1217
+ if f := cc.t.CountError; f != nil {
1218
+ f("conn_close_lost_ping")
1219
+ }
1220
+ cc.closeForError(err)
1221
+ }
1222
+
1223
+ // errRequestCanceled is a copy of net/http's errRequestCanceled because it's not
1224
+ // exported. At least they'll be DeepEqual for h1-vs-h2 comparisons tests.
1225
+ var errRequestCanceled = errors.New("net/http: request canceled")
1226
+
1227
+ func (cc *ClientConn) responseHeaderTimeout() time.Duration {
1228
+ if cc.t.t1 != nil {
1229
+ return cc.t.t1.ResponseHeaderTimeout
1230
+ }
1231
+ // No way to do this (yet?) with just an http2.Transport. Probably
1232
+ // no need. Request.Cancel this is the new way. We only need to support
1233
+ // this for compatibility with the old http.Transport fields when
1234
+ // we're doing transparent http2.
1235
+ return 0
1236
+ }
1237
+
1238
+ // actualContentLength returns a sanitized version of
1239
+ // req.ContentLength, where 0 actually means zero (not unknown) and -1
1240
+ // means unknown.
1241
+ func actualContentLength(req *http.Request) int64 {
1242
+ if req.Body == nil || req.Body == http.NoBody {
1243
+ return 0
1244
+ }
1245
+ if req.ContentLength != 0 {
1246
+ return req.ContentLength
1247
+ }
1248
+ return -1
1249
+ }
1250
+
1251
+ func (cc *ClientConn) decrStreamReservations() {
1252
+ cc.mu.Lock()
1253
+ defer cc.mu.Unlock()
1254
+ cc.decrStreamReservationsLocked()
1255
+ }
1256
+
1257
+ func (cc *ClientConn) decrStreamReservationsLocked() {
1258
+ if cc.streamsReserved > 0 {
1259
+ cc.streamsReserved--
1260
+ }
1261
+ }
1262
+
1263
+ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
1264
+ return cc.roundTrip(req, nil)
1265
+ }
1266
+
1267
+ func (cc *ClientConn) roundTrip(req *http.Request, streamf func(*clientStream)) (*http.Response, error) {
1268
+ ctx := req.Context()
1269
+ cs := &clientStream{
1270
+ cc: cc,
1271
+ ctx: ctx,
1272
+ reqCancel: req.Cancel,
1273
+ isHead: req.Method == "HEAD",
1274
+ reqBody: req.Body,
1275
+ reqBodyContentLength: actualContentLength(req),
1276
+ trace: httptrace.ContextClientTrace(ctx),
1277
+ peerClosed: make(chan struct{}),
1278
+ abort: make(chan struct{}),
1279
+ respHeaderRecv: make(chan struct{}),
1280
+ donec: make(chan struct{}),
1281
+ }
1282
+
1283
+ cs.requestedGzip = httpcommon.IsRequestGzip(req.Method, req.Header, cc.t.disableCompression())
1284
+
1285
+ go cs.doRequest(req, streamf)
1286
+
1287
+ waitDone := func() error {
1288
+ select {
1289
+ case <-cs.donec:
1290
+ return nil
1291
+ case <-ctx.Done():
1292
+ return ctx.Err()
1293
+ case <-cs.reqCancel:
1294
+ return errRequestCanceled
1295
+ }
1296
+ }
1297
+
1298
+ handleResponseHeaders := func() (*http.Response, error) {
1299
+ res := cs.res
1300
+ if res.StatusCode > 299 {
1301
+ // On error or status code 3xx, 4xx, 5xx, etc abort any
1302
+ // ongoing write, assuming that the server doesn't care
1303
+ // about our request body. If the server replied with 1xx or
1304
+ // 2xx, however, then assume the server DOES potentially
1305
+ // want our body (e.g. full-duplex streaming:
1306
+ // golang.org/issue/13444). If it turns out the server
1307
+ // doesn't, they'll RST_STREAM us soon enough. This is a
1308
+ // heuristic to avoid adding knobs to Transport. Hopefully
1309
+ // we can keep it.
1310
+ cs.abortRequestBodyWrite()
1311
+ }
1312
+ res.Request = req
1313
+ res.TLS = cc.tlsState
1314
+ if res.Body == noBody && actualContentLength(req) == 0 {
1315
+ // If there isn't a request or response body still being
1316
+ // written, then wait for the stream to be closed before
1317
+ // RoundTrip returns.
1318
+ if err := waitDone(); err != nil {
1319
+ return nil, err
1320
+ }
1321
+ }
1322
+ return res, nil
1323
+ }
1324
+
1325
+ cancelRequest := func(cs *clientStream, err error) error {
1326
+ cs.cc.mu.Lock()
1327
+ bodyClosed := cs.reqBodyClosed
1328
+ cs.cc.mu.Unlock()
1329
+ // Wait for the request body to be closed.
1330
+ //
1331
+ // If nothing closed the body before now, abortStreamLocked
1332
+ // will have started a goroutine to close it.
1333
+ //
1334
+ // Closing the body before returning avoids a race condition
1335
+ // with net/http checking its readTrackingBody to see if the
1336
+ // body was read from or closed. See golang/go#60041.
1337
+ //
1338
+ // The body is closed in a separate goroutine without the
1339
+ // connection mutex held, but dropping the mutex before waiting
1340
+ // will keep us from holding it indefinitely if the body
1341
+ // close is slow for some reason.
1342
+ if bodyClosed != nil {
1343
+ <-bodyClosed
1344
+ }
1345
+ return err
1346
+ }
1347
+
1348
+ for {
1349
+ select {
1350
+ case <-cs.respHeaderRecv:
1351
+ return handleResponseHeaders()
1352
+ case <-cs.abort:
1353
+ select {
1354
+ case <-cs.respHeaderRecv:
1355
+ // If both cs.respHeaderRecv and cs.abort are signaling,
1356
+ // pick respHeaderRecv. The server probably wrote the
1357
+ // response and immediately reset the stream.
1358
+ // golang.org/issue/49645
1359
+ return handleResponseHeaders()
1360
+ default:
1361
+ waitDone()
1362
+ return nil, cs.abortErr
1363
+ }
1364
+ case <-ctx.Done():
1365
+ err := ctx.Err()
1366
+ cs.abortStream(err)
1367
+ return nil, cancelRequest(cs, err)
1368
+ case <-cs.reqCancel:
1369
+ cs.abortStream(errRequestCanceled)
1370
+ return nil, cancelRequest(cs, errRequestCanceled)
1371
+ }
1372
+ }
1373
+ }
1374
+
1375
+ // doRequest runs for the duration of the request lifetime.
1376
+ //
1377
+ // It sends the request and performs post-request cleanup (closing Request.Body, etc.).
1378
+ func (cs *clientStream) doRequest(req *http.Request, streamf func(*clientStream)) {
1379
+ err := cs.writeRequest(req, streamf)
1380
+ cs.cleanupWriteRequest(err)
1381
+ }
1382
+
1383
+ var errExtendedConnectNotSupported = errors.New("net/http: extended connect not supported by peer")
1384
+
1385
+ // writeRequest sends a request.
1386
+ //
1387
+ // It returns nil after the request is written, the response read,
1388
+ // and the request stream is half-closed by the peer.
1389
+ //
1390
+ // It returns non-nil if the request ends otherwise.
1391
+ // If the returned error is StreamError, the error Code may be used in resetting the stream.
1392
+ func (cs *clientStream) writeRequest(req *http.Request, streamf func(*clientStream)) (err error) {
1393
+ cc := cs.cc
1394
+ ctx := cs.ctx
1395
+
1396
+ // wait for setting frames to be received, a server can change this value later,
1397
+ // but we just wait for the first settings frame
1398
+ var isExtendedConnect bool
1399
+ if req.Method == "CONNECT" && req.Header.Get(":protocol") != "" {
1400
+ isExtendedConnect = true
1401
+ }
1402
+
1403
+ // Acquire the new-request lock by writing to reqHeaderMu.
1404
+ // This lock guards the critical section covering allocating a new stream ID
1405
+ // (requires mu) and creating the stream (requires wmu).
1406
+ if cc.reqHeaderMu == nil {
1407
+ panic("RoundTrip on uninitialized ClientConn") // for tests
1408
+ }
1409
+ if isExtendedConnect {
1410
+ select {
1411
+ case <-cs.reqCancel:
1412
+ return errRequestCanceled
1413
+ case <-ctx.Done():
1414
+ return ctx.Err()
1415
+ case <-cc.seenSettingsChan:
1416
+ if !cc.extendedConnectAllowed {
1417
+ return errExtendedConnectNotSupported
1418
+ }
1419
+ }
1420
+ }
1421
+ select {
1422
+ case cc.reqHeaderMu <- struct{}{}:
1423
+ case <-cs.reqCancel:
1424
+ return errRequestCanceled
1425
+ case <-ctx.Done():
1426
+ return ctx.Err()
1427
+ }
1428
+
1429
+ cc.mu.Lock()
1430
+ if cc.idleTimer != nil {
1431
+ cc.idleTimer.Stop()
1432
+ }
1433
+ cc.decrStreamReservationsLocked()
1434
+ if err := cc.awaitOpenSlotForStreamLocked(cs); err != nil {
1435
+ cc.mu.Unlock()
1436
+ <-cc.reqHeaderMu
1437
+ return err
1438
+ }
1439
+ cc.addStreamLocked(cs) // assigns stream ID
1440
+ if isConnectionCloseRequest(req) {
1441
+ cc.doNotReuse = true
1442
+ }
1443
+ cc.mu.Unlock()
1444
+
1445
+ if streamf != nil {
1446
+ streamf(cs)
1447
+ }
1448
+
1449
+ continueTimeout := cc.t.expectContinueTimeout()
1450
+ if continueTimeout != 0 {
1451
+ if !httpguts.HeaderValuesContainsToken(req.Header["Expect"], "100-continue") {
1452
+ continueTimeout = 0
1453
+ } else {
1454
+ cs.on100 = make(chan struct{}, 1)
1455
+ }
1456
+ }
1457
+
1458
+ // Past this point (where we send request headers), it is possible for
1459
+ // RoundTrip to return successfully. Since the RoundTrip contract permits
1460
+ // the caller to "mutate or reuse" the Request after closing the Response's Body,
1461
+ // we must take care when referencing the Request from here on.
1462
+ err = cs.encodeAndWriteHeaders(req)
1463
+ <-cc.reqHeaderMu
1464
+ if err != nil {
1465
+ return err
1466
+ }
1467
+
1468
+ hasBody := cs.reqBodyContentLength != 0
1469
+ if !hasBody {
1470
+ cs.sentEndStream = true
1471
+ } else {
1472
+ if continueTimeout != 0 {
1473
+ traceWait100Continue(cs.trace)
1474
+ timer := time.NewTimer(continueTimeout)
1475
+ select {
1476
+ case <-timer.C:
1477
+ err = nil
1478
+ case <-cs.on100:
1479
+ err = nil
1480
+ case <-cs.abort:
1481
+ err = cs.abortErr
1482
+ case <-ctx.Done():
1483
+ err = ctx.Err()
1484
+ case <-cs.reqCancel:
1485
+ err = errRequestCanceled
1486
+ }
1487
+ timer.Stop()
1488
+ if err != nil {
1489
+ traceWroteRequest(cs.trace, err)
1490
+ return err
1491
+ }
1492
+ }
1493
+
1494
+ if err = cs.writeRequestBody(req); err != nil {
1495
+ if err != errStopReqBodyWrite {
1496
+ traceWroteRequest(cs.trace, err)
1497
+ return err
1498
+ }
1499
+ } else {
1500
+ cs.sentEndStream = true
1501
+ }
1502
+ }
1503
+
1504
+ traceWroteRequest(cs.trace, err)
1505
+
1506
+ var respHeaderTimer <-chan time.Time
1507
+ var respHeaderRecv chan struct{}
1508
+ if d := cc.responseHeaderTimeout(); d != 0 {
1509
+ timer := time.NewTimer(d)
1510
+ defer timer.Stop()
1511
+ respHeaderTimer = timer.C
1512
+ respHeaderRecv = cs.respHeaderRecv
1513
+ }
1514
+ // Wait until the peer half-closes its end of the stream,
1515
+ // or until the request is aborted (via context, error, or otherwise),
1516
+ // whichever comes first.
1517
+ for {
1518
+ select {
1519
+ case <-cs.peerClosed:
1520
+ return nil
1521
+ case <-respHeaderTimer:
1522
+ return errTimeout
1523
+ case <-respHeaderRecv:
1524
+ respHeaderRecv = nil
1525
+ respHeaderTimer = nil // keep waiting for END_STREAM
1526
+ case <-cs.abort:
1527
+ return cs.abortErr
1528
+ case <-ctx.Done():
1529
+ return ctx.Err()
1530
+ case <-cs.reqCancel:
1531
+ return errRequestCanceled
1532
+ }
1533
+ }
1534
+ }
1535
+
1536
+ func (cs *clientStream) encodeAndWriteHeaders(req *http.Request) error {
1537
+ cc := cs.cc
1538
+ ctx := cs.ctx
1539
+
1540
+ cc.wmu.Lock()
1541
+ defer cc.wmu.Unlock()
1542
+
1543
+ // If the request was canceled while waiting for cc.mu, just quit.
1544
+ select {
1545
+ case <-cs.abort:
1546
+ return cs.abortErr
1547
+ case <-ctx.Done():
1548
+ return ctx.Err()
1549
+ case <-cs.reqCancel:
1550
+ return errRequestCanceled
1551
+ default:
1552
+ }
1553
+
1554
+ // Encode headers.
1555
+ //
1556
+ // we send: HEADERS{1}, CONTINUATION{0,} + DATA{0,} (DATA is
1557
+ // sent by writeRequestBody below, along with any Trailers,
1558
+ // again in form HEADERS{1}, CONTINUATION{0,})
1559
+ cc.hbuf.Reset()
1560
+ res, err := encodeRequestHeaders(req, cs.requestedGzip, cc.peerMaxHeaderListSize, func(name, value string) {
1561
+ cc.writeHeader(name, value)
1562
+ })
1563
+ if err != nil {
1564
+ return fmt.Errorf("http2: %w", err)
1565
+ }
1566
+ hdrs := cc.hbuf.Bytes()
1567
+
1568
+ // Write the request.
1569
+ endStream := !res.HasBody && !res.HasTrailers
1570
+ cs.sentHeaders = true
1571
+ err = cc.writeHeaders(cs.ID, endStream, int(cc.maxFrameSize), hdrs)
1572
+ traceWroteHeaders(cs.trace)
1573
+ return err
1574
+ }
1575
+
1576
+ func encodeRequestHeaders(req *http.Request, addGzipHeader bool, peerMaxHeaderListSize uint64, headerf func(name, value string)) (httpcommon.EncodeHeadersResult, error) {
1577
+ return httpcommon.EncodeHeaders(req.Context(), httpcommon.EncodeHeadersParam{
1578
+ Request: httpcommon.Request{
1579
+ Header: req.Header,
1580
+ Trailer: req.Trailer,
1581
+ URL: req.URL,
1582
+ Host: req.Host,
1583
+ Method: req.Method,
1584
+ ActualContentLength: actualContentLength(req),
1585
+ },
1586
+ AddGzipHeader: addGzipHeader,
1587
+ PeerMaxHeaderListSize: peerMaxHeaderListSize,
1588
+ DefaultUserAgent: defaultUserAgent,
1589
+ }, headerf)
1590
+ }
1591
+
1592
+ // cleanupWriteRequest performs post-request tasks.
1593
+ //
1594
+ // If err (the result of writeRequest) is non-nil and the stream is not closed,
1595
+ // cleanupWriteRequest will send a reset to the peer.
1596
+ func (cs *clientStream) cleanupWriteRequest(err error) {
1597
+ cc := cs.cc
1598
+
1599
+ if cs.ID == 0 {
1600
+ // We were canceled before creating the stream, so return our reservation.
1601
+ cc.decrStreamReservations()
1602
+ }
1603
+
1604
+ // TODO: write h12Compare test showing whether
1605
+ // Request.Body is closed by the Transport,
1606
+ // and in multiple cases: server replies <=299 and >299
1607
+ // while still writing request body
1608
+ cc.mu.Lock()
1609
+ mustCloseBody := false
1610
+ if cs.reqBody != nil && cs.reqBodyClosed == nil {
1611
+ mustCloseBody = true
1612
+ cs.reqBodyClosed = make(chan struct{})
1613
+ }
1614
+ bodyClosed := cs.reqBodyClosed
1615
+ closeOnIdle := cc.singleUse || cc.doNotReuse || cc.t.disableKeepAlives() || cc.goAway != nil
1616
+ cc.mu.Unlock()
1617
+ if mustCloseBody {
1618
+ cs.reqBody.Close()
1619
+ close(bodyClosed)
1620
+ }
1621
+ if bodyClosed != nil {
1622
+ <-bodyClosed
1623
+ }
1624
+
1625
+ if err != nil && cs.sentEndStream {
1626
+ // If the connection is closed immediately after the response is read,
1627
+ // we may be aborted before finishing up here. If the stream was closed
1628
+ // cleanly on both sides, there is no error.
1629
+ select {
1630
+ case <-cs.peerClosed:
1631
+ err = nil
1632
+ default:
1633
+ }
1634
+ }
1635
+ if err != nil {
1636
+ cs.abortStream(err) // possibly redundant, but harmless
1637
+ if cs.sentHeaders {
1638
+ if se, ok := err.(StreamError); ok {
1639
+ if se.Cause != errFromPeer {
1640
+ cc.writeStreamReset(cs.ID, se.Code, false, err)
1641
+ }
1642
+ } else {
1643
+ // We're cancelling an in-flight request.
1644
+ //
1645
+ // This could be due to the server becoming unresponsive.
1646
+ // To avoid sending too many requests on a dead connection,
1647
+ // we let the request continue to consume a concurrency slot
1648
+ // until we can confirm the server is still responding.
1649
+ // We do this by sending a PING frame along with the RST_STREAM
1650
+ // (unless a ping is already in flight).
1651
+ //
1652
+ // For simplicity, we don't bother tracking the PING payload:
1653
+ // We reset cc.pendingResets any time we receive a PING ACK.
1654
+ //
1655
+ // We skip this if the conn is going to be closed on idle,
1656
+ // because it's short lived and will probably be closed before
1657
+ // we get the ping response.
1658
+ ping := false
1659
+ if !closeOnIdle {
1660
+ cc.mu.Lock()
1661
+ // rstStreamPingsBlocked works around a gRPC behavior:
1662
+ // see comment on the field for details.
1663
+ if !cc.rstStreamPingsBlocked {
1664
+ if cc.pendingResets == 0 {
1665
+ ping = true
1666
+ }
1667
+ cc.pendingResets++
1668
+ }
1669
+ cc.mu.Unlock()
1670
+ }
1671
+ cc.writeStreamReset(cs.ID, ErrCodeCancel, ping, err)
1672
+ }
1673
+ }
1674
+ cs.bufPipe.CloseWithError(err) // no-op if already closed
1675
+ } else {
1676
+ if cs.sentHeaders && !cs.sentEndStream {
1677
+ cc.writeStreamReset(cs.ID, ErrCodeNo, false, nil)
1678
+ }
1679
+ cs.bufPipe.CloseWithError(errRequestCanceled)
1680
+ }
1681
+ if cs.ID != 0 {
1682
+ cc.forgetStreamID(cs.ID)
1683
+ }
1684
+
1685
+ cc.wmu.Lock()
1686
+ werr := cc.werr
1687
+ cc.wmu.Unlock()
1688
+ if werr != nil {
1689
+ cc.Close()
1690
+ }
1691
+
1692
+ close(cs.donec)
1693
+ }
1694
+
1695
+ // awaitOpenSlotForStreamLocked waits until len(streams) < maxConcurrentStreams.
1696
+ // Must hold cc.mu.
1697
+ func (cc *ClientConn) awaitOpenSlotForStreamLocked(cs *clientStream) error {
1698
+ for {
1699
+ if cc.closed && cc.nextStreamID == 1 && cc.streamsReserved == 0 {
1700
+ // This is the very first request sent to this connection.
1701
+ // Return a fatal error which aborts the retry loop.
1702
+ return errClientConnNotEstablished
1703
+ }
1704
+ cc.lastActive = time.Now()
1705
+ if cc.closed || !cc.canTakeNewRequestLocked() {
1706
+ return errClientConnUnusable
1707
+ }
1708
+ cc.lastIdle = time.Time{}
1709
+ if cc.currentRequestCountLocked() < int(cc.maxConcurrentStreams) {
1710
+ return nil
1711
+ }
1712
+ cc.pendingRequests++
1713
+ cc.cond.Wait()
1714
+ cc.pendingRequests--
1715
+ select {
1716
+ case <-cs.abort:
1717
+ return cs.abortErr
1718
+ default:
1719
+ }
1720
+ }
1721
+ }
1722
+
1723
+ // requires cc.wmu be held
1724
+ func (cc *ClientConn) writeHeaders(streamID uint32, endStream bool, maxFrameSize int, hdrs []byte) error {
1725
+ first := true // first frame written (HEADERS is first, then CONTINUATION)
1726
+ for len(hdrs) > 0 && cc.werr == nil {
1727
+ chunk := hdrs
1728
+ if len(chunk) > maxFrameSize {
1729
+ chunk = chunk[:maxFrameSize]
1730
+ }
1731
+ hdrs = hdrs[len(chunk):]
1732
+ endHeaders := len(hdrs) == 0
1733
+ if first {
1734
+ cc.fr.WriteHeaders(HeadersFrameParam{
1735
+ StreamID: streamID,
1736
+ BlockFragment: chunk,
1737
+ EndStream: endStream,
1738
+ EndHeaders: endHeaders,
1739
+ })
1740
+ first = false
1741
+ } else {
1742
+ cc.fr.WriteContinuation(streamID, endHeaders, chunk)
1743
+ }
1744
+ }
1745
+ cc.bw.Flush()
1746
+ return cc.werr
1747
+ }
1748
+
1749
+ // internal error values; they don't escape to callers
1750
+ var (
1751
+ // abort request body write; don't send cancel
1752
+ errStopReqBodyWrite = errors.New("http2: aborting request body write")
1753
+
1754
+ // abort request body write, but send stream reset of cancel.
1755
+ errStopReqBodyWriteAndCancel = errors.New("http2: canceling request")
1756
+
1757
+ errReqBodyTooLong = errors.New("http2: request body larger than specified content length")
1758
+ )
1759
+
1760
+ // frameScratchBufferLen returns the length of a buffer to use for
1761
+ // outgoing request bodies to read/write to/from.
1762
+ //
1763
+ // It returns max(1, min(peer's advertised max frame size,
1764
+ // Request.ContentLength+1, 512KB)).
1765
+ func (cs *clientStream) frameScratchBufferLen(maxFrameSize int) int {
1766
+ const max = 512 << 10
1767
+ n := int64(maxFrameSize)
1768
+ if n > max {
1769
+ n = max
1770
+ }
1771
+ if cl := cs.reqBodyContentLength; cl != -1 && cl+1 < n {
1772
+ // Add an extra byte past the declared content-length to
1773
+ // give the caller's Request.Body io.Reader a chance to
1774
+ // give us more bytes than they declared, so we can catch it
1775
+ // early.
1776
+ n = cl + 1
1777
+ }
1778
+ if n < 1 {
1779
+ return 1
1780
+ }
1781
+ return int(n) // doesn't truncate; max is 512K
1782
+ }
1783
+
1784
+ // Seven bufPools manage different frame sizes. This helps to avoid scenarios where long-running
1785
+ // streaming requests using small frame sizes occupy large buffers initially allocated for prior
1786
+ // requests needing big buffers. The size ranges are as follows:
1787
+ // {0 KB, 16 KB], {16 KB, 32 KB], {32 KB, 64 KB], {64 KB, 128 KB], {128 KB, 256 KB],
1788
+ // {256 KB, 512 KB], {512 KB, infinity}
1789
+ // In practice, the maximum scratch buffer size should not exceed 512 KB due to
1790
+ // frameScratchBufferLen(maxFrameSize), thus the "infinity pool" should never be used.
1791
+ // It exists mainly as a safety measure, for potential future increases in max buffer size.
1792
+ var bufPools [7]sync.Pool // of *[]byte
1793
+ func bufPoolIndex(size int) int {
1794
+ if size <= 16384 {
1795
+ return 0
1796
+ }
1797
+ size -= 1
1798
+ bits := bits.Len(uint(size))
1799
+ index := bits - 14
1800
+ if index >= len(bufPools) {
1801
+ return len(bufPools) - 1
1802
+ }
1803
+ return index
1804
+ }
1805
+
1806
+ func (cs *clientStream) writeRequestBody(req *http.Request) (err error) {
1807
+ cc := cs.cc
1808
+ body := cs.reqBody
1809
+ sentEnd := false // whether we sent the final DATA frame w/ END_STREAM
1810
+
1811
+ hasTrailers := req.Trailer != nil
1812
+ remainLen := cs.reqBodyContentLength
1813
+ hasContentLen := remainLen != -1
1814
+
1815
+ cc.mu.Lock()
1816
+ maxFrameSize := int(cc.maxFrameSize)
1817
+ cc.mu.Unlock()
1818
+
1819
+ // Scratch buffer for reading into & writing from.
1820
+ scratchLen := cs.frameScratchBufferLen(maxFrameSize)
1821
+ var buf []byte
1822
+ index := bufPoolIndex(scratchLen)
1823
+ if bp, ok := bufPools[index].Get().(*[]byte); ok && len(*bp) >= scratchLen {
1824
+ defer bufPools[index].Put(bp)
1825
+ buf = *bp
1826
+ } else {
1827
+ buf = make([]byte, scratchLen)
1828
+ defer bufPools[index].Put(&buf)
1829
+ }
1830
+
1831
+ var sawEOF bool
1832
+ for !sawEOF {
1833
+ n, err := body.Read(buf)
1834
+ if hasContentLen {
1835
+ remainLen -= int64(n)
1836
+ if remainLen == 0 && err == nil {
1837
+ // The request body's Content-Length was predeclared and
1838
+ // we just finished reading it all, but the underlying io.Reader
1839
+ // returned the final chunk with a nil error (which is one of
1840
+ // the two valid things a Reader can do at EOF). Because we'd prefer
1841
+ // to send the END_STREAM bit early, double-check that we're actually
1842
+ // at EOF. Subsequent reads should return (0, EOF) at this point.
1843
+ // If either value is different, we return an error in one of two ways below.
1844
+ var scratch [1]byte
1845
+ var n1 int
1846
+ n1, err = body.Read(scratch[:])
1847
+ remainLen -= int64(n1)
1848
+ }
1849
+ if remainLen < 0 {
1850
+ err = errReqBodyTooLong
1851
+ return err
1852
+ }
1853
+ }
1854
+ if err != nil {
1855
+ cc.mu.Lock()
1856
+ bodyClosed := cs.reqBodyClosed != nil
1857
+ cc.mu.Unlock()
1858
+ switch {
1859
+ case bodyClosed:
1860
+ return errStopReqBodyWrite
1861
+ case err == io.EOF:
1862
+ sawEOF = true
1863
+ err = nil
1864
+ default:
1865
+ return err
1866
+ }
1867
+ }
1868
+
1869
+ remain := buf[:n]
1870
+ for len(remain) > 0 && err == nil {
1871
+ var allowed int32
1872
+ allowed, err = cs.awaitFlowControl(len(remain))
1873
+ if err != nil {
1874
+ return err
1875
+ }
1876
+ cc.wmu.Lock()
1877
+ data := remain[:allowed]
1878
+ remain = remain[allowed:]
1879
+ sentEnd = sawEOF && len(remain) == 0 && !hasTrailers
1880
+ err = cc.fr.WriteData(cs.ID, sentEnd, data)
1881
+ if err == nil {
1882
+ // TODO(bradfitz): this flush is for latency, not bandwidth.
1883
+ // Most requests won't need this. Make this opt-in or
1884
+ // opt-out? Use some heuristic on the body type? Nagel-like
1885
+ // timers? Based on 'n'? Only last chunk of this for loop,
1886
+ // unless flow control tokens are low? For now, always.
1887
+ // If we change this, see comment below.
1888
+ err = cc.bw.Flush()
1889
+ }
1890
+ cc.wmu.Unlock()
1891
+ }
1892
+ if err != nil {
1893
+ return err
1894
+ }
1895
+ }
1896
+
1897
+ if sentEnd {
1898
+ // Already sent END_STREAM (which implies we have no
1899
+ // trailers) and flushed, because currently all
1900
+ // WriteData frames above get a flush. So we're done.
1901
+ return nil
1902
+ }
1903
+
1904
+ // Since the RoundTrip contract permits the caller to "mutate or reuse"
1905
+ // a request after the Response's Body is closed, verify that this hasn't
1906
+ // happened before accessing the trailers.
1907
+ cc.mu.Lock()
1908
+ trailer := req.Trailer
1909
+ err = cs.abortErr
1910
+ cc.mu.Unlock()
1911
+ if err != nil {
1912
+ return err
1913
+ }
1914
+
1915
+ cc.wmu.Lock()
1916
+ defer cc.wmu.Unlock()
1917
+ var trls []byte
1918
+ if len(trailer) > 0 {
1919
+ trls, err = cc.encodeTrailers(trailer)
1920
+ if err != nil {
1921
+ return err
1922
+ }
1923
+ }
1924
+
1925
+ // Two ways to send END_STREAM: either with trailers, or
1926
+ // with an empty DATA frame.
1927
+ if len(trls) > 0 {
1928
+ err = cc.writeHeaders(cs.ID, true, maxFrameSize, trls)
1929
+ } else {
1930
+ err = cc.fr.WriteData(cs.ID, true, nil)
1931
+ }
1932
+ if ferr := cc.bw.Flush(); ferr != nil && err == nil {
1933
+ err = ferr
1934
+ }
1935
+ return err
1936
+ }
1937
+
1938
+ // awaitFlowControl waits for [1, min(maxBytes, cc.cs.maxFrameSize)] flow
1939
+ // control tokens from the server.
1940
+ // It returns either the non-zero number of tokens taken or an error
1941
+ // if the stream is dead.
1942
+ func (cs *clientStream) awaitFlowControl(maxBytes int) (taken int32, err error) {
1943
+ cc := cs.cc
1944
+ ctx := cs.ctx
1945
+ cc.mu.Lock()
1946
+ defer cc.mu.Unlock()
1947
+ for {
1948
+ if cc.closed {
1949
+ return 0, errClientConnClosed
1950
+ }
1951
+ if cs.reqBodyClosed != nil {
1952
+ return 0, errStopReqBodyWrite
1953
+ }
1954
+ select {
1955
+ case <-cs.abort:
1956
+ return 0, cs.abortErr
1957
+ case <-ctx.Done():
1958
+ return 0, ctx.Err()
1959
+ case <-cs.reqCancel:
1960
+ return 0, errRequestCanceled
1961
+ default:
1962
+ }
1963
+ if a := cs.flow.available(); a > 0 {
1964
+ take := a
1965
+ if int(take) > maxBytes {
1966
+
1967
+ take = int32(maxBytes) // can't truncate int; take is int32
1968
+ }
1969
+ if take > int32(cc.maxFrameSize) {
1970
+ take = int32(cc.maxFrameSize)
1971
+ }
1972
+ cs.flow.take(take)
1973
+ return take, nil
1974
+ }
1975
+ cc.cond.Wait()
1976
+ }
1977
+ }
1978
+
1979
+ // requires cc.wmu be held.
1980
+ func (cc *ClientConn) encodeTrailers(trailer http.Header) ([]byte, error) {
1981
+ cc.hbuf.Reset()
1982
+
1983
+ hlSize := uint64(0)
1984
+ for k, vv := range trailer {
1985
+ for _, v := range vv {
1986
+ hf := hpack.HeaderField{Name: k, Value: v}
1987
+ hlSize += uint64(hf.Size())
1988
+ }
1989
+ }
1990
+ if hlSize > cc.peerMaxHeaderListSize {
1991
+ return nil, errRequestHeaderListSize
1992
+ }
1993
+
1994
+ for k, vv := range trailer {
1995
+ lowKey, ascii := httpcommon.LowerHeader(k)
1996
+ if !ascii {
1997
+ // Skip writing invalid headers. Per RFC 7540, Section 8.1.2, header
1998
+ // field names have to be ASCII characters (just as in HTTP/1.x).
1999
+ continue
2000
+ }
2001
+ // Transfer-Encoding, etc.. have already been filtered at the
2002
+ // start of RoundTrip
2003
+ for _, v := range vv {
2004
+ cc.writeHeader(lowKey, v)
2005
+ }
2006
+ }
2007
+ return cc.hbuf.Bytes(), nil
2008
+ }
2009
+
2010
+ func (cc *ClientConn) writeHeader(name, value string) {
2011
+ if VerboseLogs {
2012
+ log.Printf("http2: Transport encoding header %q = %q", name, value)
2013
+ }
2014
+ cc.henc.WriteField(hpack.HeaderField{Name: name, Value: value})
2015
+ }
2016
+
2017
+ type resAndError struct {
2018
+ _ incomparable
2019
+ res *http.Response
2020
+ err error
2021
+ }
2022
+
2023
+ // requires cc.mu be held.
2024
+ func (cc *ClientConn) addStreamLocked(cs *clientStream) {
2025
+ cs.flow.add(int32(cc.initialWindowSize))
2026
+ cs.flow.setConnFlow(&cc.flow)
2027
+ cs.inflow.init(cc.initialStreamRecvWindowSize)
2028
+ cs.ID = cc.nextStreamID
2029
+ cc.nextStreamID += 2
2030
+ cc.streams[cs.ID] = cs
2031
+ if cs.ID == 0 {
2032
+ panic("assigned stream ID 0")
2033
+ }
2034
+ }
2035
+
2036
+ func (cc *ClientConn) forgetStreamID(id uint32) {
2037
+ cc.mu.Lock()
2038
+ slen := len(cc.streams)
2039
+ delete(cc.streams, id)
2040
+ if len(cc.streams) != slen-1 {
2041
+ panic("forgetting unknown stream id")
2042
+ }
2043
+ cc.lastActive = time.Now()
2044
+ if len(cc.streams) == 0 && cc.idleTimer != nil {
2045
+ cc.idleTimer.Reset(cc.idleTimeout)
2046
+ cc.lastIdle = time.Now()
2047
+ }
2048
+ // Wake up writeRequestBody via clientStream.awaitFlowControl and
2049
+ // wake up RoundTrip if there is a pending request.
2050
+ cc.cond.Broadcast()
2051
+
2052
+ closeOnIdle := cc.singleUse || cc.doNotReuse || cc.t.disableKeepAlives() || cc.goAway != nil
2053
+ if closeOnIdle && cc.streamsReserved == 0 && len(cc.streams) == 0 {
2054
+ if VerboseLogs {
2055
+ cc.vlogf("http2: Transport closing idle conn %p (forSingleUse=%v, maxStream=%v)", cc, cc.singleUse, cc.nextStreamID-2)
2056
+ }
2057
+ cc.closed = true
2058
+ defer cc.closeConn()
2059
+ }
2060
+
2061
+ cc.mu.Unlock()
2062
+ }
2063
+
2064
+ // clientConnReadLoop is the state owned by the clientConn's frame-reading readLoop.
2065
+ type clientConnReadLoop struct {
2066
+ _ incomparable
2067
+ cc *ClientConn
2068
+ }
2069
+
2070
+ // readLoop runs in its own goroutine and reads and dispatches frames.
2071
+ func (cc *ClientConn) readLoop() {
2072
+ rl := &clientConnReadLoop{cc: cc}
2073
+ defer rl.cleanup()
2074
+ cc.readerErr = rl.run()
2075
+ if ce, ok := cc.readerErr.(ConnectionError); ok {
2076
+ cc.wmu.Lock()
2077
+ cc.fr.WriteGoAway(0, ErrCode(ce), nil)
2078
+ cc.wmu.Unlock()
2079
+ }
2080
+ }
2081
+
2082
+ // GoAwayError is returned by the Transport when the server closes the
2083
+ // TCP connection after sending a GOAWAY frame.
2084
+ type GoAwayError struct {
2085
+ LastStreamID uint32
2086
+ ErrCode ErrCode
2087
+ DebugData string
2088
+ }
2089
+
2090
+ func (e GoAwayError) Error() string {
2091
+ return fmt.Sprintf("http2: server sent GOAWAY and closed the connection; LastStreamID=%v, ErrCode=%v, debug=%q",
2092
+ e.LastStreamID, e.ErrCode, e.DebugData)
2093
+ }
2094
+
2095
+ func isEOFOrNetReadError(err error) bool {
2096
+ if err == io.EOF {
2097
+ return true
2098
+ }
2099
+ ne, ok := err.(*net.OpError)
2100
+ return ok && ne.Op == "read"
2101
+ }
2102
+
2103
+ func (rl *clientConnReadLoop) cleanup() {
2104
+ cc := rl.cc
2105
+ defer cc.closeConn()
2106
+ defer close(cc.readerDone)
2107
+
2108
+ if cc.idleTimer != nil {
2109
+ cc.idleTimer.Stop()
2110
+ }
2111
+
2112
+ // Close any response bodies if the server closes prematurely.
2113
+ // TODO: also do this if we've written the headers but not
2114
+ // gotten a response yet.
2115
+ err := cc.readerErr
2116
+ cc.mu.Lock()
2117
+ if cc.goAway != nil && isEOFOrNetReadError(err) {
2118
+ err = GoAwayError{
2119
+ LastStreamID: cc.goAway.LastStreamID,
2120
+ ErrCode: cc.goAway.ErrCode,
2121
+ DebugData: cc.goAwayDebug,
2122
+ }
2123
+ } else if err == io.EOF {
2124
+ err = io.ErrUnexpectedEOF
2125
+ }
2126
+ cc.closed = true
2127
+
2128
+ // If the connection has never been used, and has been open for only a short time,
2129
+ // leave it in the connection pool for a little while.
2130
+ //
2131
+ // This avoids a situation where new connections are constantly created,
2132
+ // added to the pool, fail, and are removed from the pool, without any error
2133
+ // being surfaced to the user.
2134
+ unusedWaitTime := 5 * time.Second
2135
+ if cc.idleTimeout > 0 && unusedWaitTime > cc.idleTimeout {
2136
+ unusedWaitTime = cc.idleTimeout
2137
+ }
2138
+ idleTime := time.Now().Sub(cc.lastActive)
2139
+ if atomic.LoadUint32(&cc.atomicReused) == 0 && idleTime < unusedWaitTime && !cc.closedOnIdle {
2140
+ cc.idleTimer = time.AfterFunc(unusedWaitTime-idleTime, func() {
2141
+ cc.t.connPool().MarkDead(cc)
2142
+ })
2143
+ } else {
2144
+ cc.mu.Unlock() // avoid any deadlocks in MarkDead
2145
+ cc.t.connPool().MarkDead(cc)
2146
+ cc.mu.Lock()
2147
+ }
2148
+
2149
+ for _, cs := range cc.streams {
2150
+ select {
2151
+ case <-cs.peerClosed:
2152
+ // The server closed the stream before closing the conn,
2153
+ // so no need to interrupt it.
2154
+ default:
2155
+ cs.abortStreamLocked(err)
2156
+ }
2157
+ }
2158
+ cc.cond.Broadcast()
2159
+ cc.mu.Unlock()
2160
+
2161
+ if !cc.seenSettings {
2162
+ // If we have a pending request that wants extended CONNECT,
2163
+ // let it continue and fail with the connection error.
2164
+ cc.extendedConnectAllowed = true
2165
+ close(cc.seenSettingsChan)
2166
+ }
2167
+ }
2168
+
2169
+ // countReadFrameError calls Transport.CountError with a string
2170
+ // representing err.
2171
+ func (cc *ClientConn) countReadFrameError(err error) {
2172
+ f := cc.t.CountError
2173
+ if f == nil || err == nil {
2174
+ return
2175
+ }
2176
+ if ce, ok := err.(ConnectionError); ok {
2177
+ errCode := ErrCode(ce)
2178
+ f(fmt.Sprintf("read_frame_conn_error_%s", errCode.stringToken()))
2179
+ return
2180
+ }
2181
+ if errors.Is(err, io.EOF) {
2182
+ f("read_frame_eof")
2183
+ return
2184
+ }
2185
+ if errors.Is(err, io.ErrUnexpectedEOF) {
2186
+ f("read_frame_unexpected_eof")
2187
+ return
2188
+ }
2189
+ if errors.Is(err, ErrFrameTooLarge) {
2190
+ f("read_frame_too_large")
2191
+ return
2192
+ }
2193
+ f("read_frame_other")
2194
+ }
2195
+
2196
+ func (rl *clientConnReadLoop) run() error {
2197
+ cc := rl.cc
2198
+ gotSettings := false
2199
+ readIdleTimeout := cc.readIdleTimeout
2200
+ var t *time.Timer
2201
+ if readIdleTimeout != 0 {
2202
+ t = time.AfterFunc(readIdleTimeout, cc.healthCheck)
2203
+ }
2204
+ for {
2205
+ f, err := cc.fr.ReadFrame()
2206
+ if t != nil {
2207
+ t.Reset(readIdleTimeout)
2208
+ }
2209
+ if err != nil {
2210
+ cc.vlogf("http2: Transport readFrame error on conn %p: (%T) %v", cc, err, err)
2211
+ }
2212
+ if se, ok := err.(StreamError); ok {
2213
+ if cs := rl.streamByID(se.StreamID, notHeaderOrDataFrame); cs != nil {
2214
+ if se.Cause == nil {
2215
+ se.Cause = cc.fr.errDetail
2216
+ }
2217
+ rl.endStreamError(cs, se)
2218
+ }
2219
+ continue
2220
+ } else if err != nil {
2221
+ cc.countReadFrameError(err)
2222
+ return err
2223
+ }
2224
+ if VerboseLogs {
2225
+ cc.vlogf("http2: Transport received %s", summarizeFrame(f))
2226
+ }
2227
+ if !gotSettings {
2228
+ if _, ok := f.(*SettingsFrame); !ok {
2229
+ cc.logf("protocol error: received %T before a SETTINGS frame", f)
2230
+ return ConnectionError(ErrCodeProtocol)
2231
+ }
2232
+ gotSettings = true
2233
+ }
2234
+
2235
+ switch f := f.(type) {
2236
+ case *MetaHeadersFrame:
2237
+ err = rl.processHeaders(f)
2238
+ case *DataFrame:
2239
+ err = rl.processData(f)
2240
+ case *GoAwayFrame:
2241
+ err = rl.processGoAway(f)
2242
+ case *RSTStreamFrame:
2243
+ err = rl.processResetStream(f)
2244
+ case *SettingsFrame:
2245
+ err = rl.processSettings(f)
2246
+ case *PushPromiseFrame:
2247
+ err = rl.processPushPromise(f)
2248
+ case *WindowUpdateFrame:
2249
+ err = rl.processWindowUpdate(f)
2250
+ case *PingFrame:
2251
+ err = rl.processPing(f)
2252
+ default:
2253
+ cc.logf("Transport: unhandled response frame type %T", f)
2254
+ }
2255
+ if err != nil {
2256
+ if VerboseLogs {
2257
+ cc.vlogf("http2: Transport conn %p received error from processing frame %v: %v", cc, summarizeFrame(f), err)
2258
+ }
2259
+ return err
2260
+ }
2261
+ }
2262
+ }
2263
+
2264
+ func (rl *clientConnReadLoop) processHeaders(f *MetaHeadersFrame) error {
2265
+ cs := rl.streamByID(f.StreamID, headerOrDataFrame)
2266
+ if cs == nil {
2267
+ // We'd get here if we canceled a request while the
2268
+ // server had its response still in flight. So if this
2269
+ // was just something we canceled, ignore it.
2270
+ return nil
2271
+ }
2272
+ if cs.readClosed {
2273
+ rl.endStreamError(cs, StreamError{
2274
+ StreamID: f.StreamID,
2275
+ Code: ErrCodeProtocol,
2276
+ Cause: errors.New("protocol error: headers after END_STREAM"),
2277
+ })
2278
+ return nil
2279
+ }
2280
+ if !cs.firstByte {
2281
+ if cs.trace != nil {
2282
+ // TODO(bradfitz): move first response byte earlier,
2283
+ // when we first read the 9 byte header, not waiting
2284
+ // until all the HEADERS+CONTINUATION frames have been
2285
+ // merged. This works for now.
2286
+ traceFirstResponseByte(cs.trace)
2287
+ }
2288
+ cs.firstByte = true
2289
+ }
2290
+ if !cs.pastHeaders {
2291
+ cs.pastHeaders = true
2292
+ } else {
2293
+ return rl.processTrailers(cs, f)
2294
+ }
2295
+
2296
+ res, err := rl.handleResponse(cs, f)
2297
+ if err != nil {
2298
+ if _, ok := err.(ConnectionError); ok {
2299
+ return err
2300
+ }
2301
+ // Any other error type is a stream error.
2302
+ rl.endStreamError(cs, StreamError{
2303
+ StreamID: f.StreamID,
2304
+ Code: ErrCodeProtocol,
2305
+ Cause: err,
2306
+ })
2307
+ return nil // return nil from process* funcs to keep conn alive
2308
+ }
2309
+ if res == nil {
2310
+ // (nil, nil) special case. See handleResponse docs.
2311
+ return nil
2312
+ }
2313
+ cs.resTrailer = &res.Trailer
2314
+ cs.res = res
2315
+ close(cs.respHeaderRecv)
2316
+ if f.StreamEnded() {
2317
+ rl.endStream(cs)
2318
+ }
2319
+ return nil
2320
+ }
2321
+
2322
+ // may return error types nil, or ConnectionError. Any other error value
2323
+ // is a StreamError of type ErrCodeProtocol. The returned error in that case
2324
+ // is the detail.
2325
+ //
2326
+ // As a special case, handleResponse may return (nil, nil) to skip the
2327
+ // frame (currently only used for 1xx responses).
2328
+ func (rl *clientConnReadLoop) handleResponse(cs *clientStream, f *MetaHeadersFrame) (*http.Response, error) {
2329
+ if f.Truncated {
2330
+ return nil, errResponseHeaderListSize
2331
+ }
2332
+
2333
+ status := f.PseudoValue("status")
2334
+ if status == "" {
2335
+ return nil, errors.New("malformed response from server: missing status pseudo header")
2336
+ }
2337
+ statusCode, err := strconv.Atoi(status)
2338
+ if err != nil {
2339
+ return nil, errors.New("malformed response from server: malformed non-numeric status pseudo header")
2340
+ }
2341
+
2342
+ regularFields := f.RegularFields()
2343
+ strs := make([]string, len(regularFields))
2344
+ header := make(http.Header, len(regularFields))
2345
+ res := &http.Response{
2346
+ Proto: "HTTP/2.0",
2347
+ ProtoMajor: 2,
2348
+ Header: header,
2349
+ StatusCode: statusCode,
2350
+ Status: status + " " + http.StatusText(statusCode),
2351
+ }
2352
+ for _, hf := range regularFields {
2353
+ key := httpcommon.CanonicalHeader(hf.Name)
2354
+ if key == "Trailer" {
2355
+ t := res.Trailer
2356
+ if t == nil {
2357
+ t = make(http.Header)
2358
+ res.Trailer = t
2359
+ }
2360
+ foreachHeaderElement(hf.Value, func(v string) {
2361
+ t[httpcommon.CanonicalHeader(v)] = nil
2362
+ })
2363
+ } else {
2364
+ vv := header[key]
2365
+ if vv == nil && len(strs) > 0 {
2366
+ // More than likely this will be a single-element key.
2367
+ // Most headers aren't multi-valued.
2368
+ // Set the capacity on strs[0] to 1, so any future append
2369
+ // won't extend the slice into the other strings.
2370
+ vv, strs = strs[:1:1], strs[1:]
2371
+ vv[0] = hf.Value
2372
+ header[key] = vv
2373
+ } else {
2374
+ header[key] = append(vv, hf.Value)
2375
+ }
2376
+ }
2377
+ }
2378
+
2379
+ if statusCode >= 100 && statusCode <= 199 {
2380
+ if f.StreamEnded() {
2381
+ return nil, errors.New("1xx informational response with END_STREAM flag")
2382
+ }
2383
+ if fn := cs.get1xxTraceFunc(); fn != nil {
2384
+ // If the 1xx response is being delivered to the user,
2385
+ // then they're responsible for limiting the number
2386
+ // of responses.
2387
+ if err := fn(statusCode, textproto.MIMEHeader(header)); err != nil {
2388
+ return nil, err
2389
+ }
2390
+ } else {
2391
+ // If the user didn't examine the 1xx response, then we
2392
+ // limit the size of all 1xx headers.
2393
+ //
2394
+ // This differs a bit from the HTTP/1 implementation, which
2395
+ // limits the size of all 1xx headers plus the final response.
2396
+ // Use the larger limit of MaxHeaderListSize and
2397
+ // net/http.Transport.MaxResponseHeaderBytes.
2398
+ limit := int64(cs.cc.t.maxHeaderListSize())
2399
+ if t1 := cs.cc.t.t1; t1 != nil && t1.MaxResponseHeaderBytes > limit {
2400
+ limit = t1.MaxResponseHeaderBytes
2401
+ }
2402
+ for _, h := range f.Fields {
2403
+ cs.totalHeaderSize += int64(h.Size())
2404
+ }
2405
+ if cs.totalHeaderSize > limit {
2406
+ if VerboseLogs {
2407
+ log.Printf("http2: 1xx informational responses too large")
2408
+ }
2409
+ return nil, errors.New("header list too large")
2410
+ }
2411
+ }
2412
+ if statusCode == 100 {
2413
+ traceGot100Continue(cs.trace)
2414
+ select {
2415
+ case cs.on100 <- struct{}{}:
2416
+ default:
2417
+ }
2418
+ }
2419
+ cs.pastHeaders = false // do it all again
2420
+ return nil, nil
2421
+ }
2422
+
2423
+ res.ContentLength = -1
2424
+ if clens := res.Header["Content-Length"]; len(clens) == 1 {
2425
+ if cl, err := strconv.ParseUint(clens[0], 10, 63); err == nil {
2426
+ res.ContentLength = int64(cl)
2427
+ } else {
2428
+ // TODO: care? unlike http/1, it won't mess up our framing, so it's
2429
+ // more safe smuggling-wise to ignore.
2430
+ }
2431
+ } else if len(clens) > 1 {
2432
+ // TODO: care? unlike http/1, it won't mess up our framing, so it's
2433
+ // more safe smuggling-wise to ignore.
2434
+ } else if f.StreamEnded() && !cs.isHead {
2435
+ res.ContentLength = 0
2436
+ }
2437
+
2438
+ if cs.isHead {
2439
+ res.Body = noBody
2440
+ return res, nil
2441
+ }
2442
+
2443
+ if f.StreamEnded() {
2444
+ if res.ContentLength > 0 {
2445
+ res.Body = missingBody{}
2446
+ } else {
2447
+ res.Body = noBody
2448
+ }
2449
+ return res, nil
2450
+ }
2451
+
2452
+ cs.bufPipe.setBuffer(&dataBuffer{expected: res.ContentLength})
2453
+ cs.bytesRemain = res.ContentLength
2454
+ res.Body = transportResponseBody{cs}
2455
+
2456
+ if cs.requestedGzip && asciiEqualFold(res.Header.Get("Content-Encoding"), "gzip") {
2457
+ res.Header.Del("Content-Encoding")
2458
+ res.Header.Del("Content-Length")
2459
+ res.ContentLength = -1
2460
+ res.Body = &gzipReader{body: res.Body}
2461
+ res.Uncompressed = true
2462
+ }
2463
+ return res, nil
2464
+ }
2465
+
2466
+ func (rl *clientConnReadLoop) processTrailers(cs *clientStream, f *MetaHeadersFrame) error {
2467
+ if cs.pastTrailers {
2468
+ // Too many HEADERS frames for this stream.
2469
+ return ConnectionError(ErrCodeProtocol)
2470
+ }
2471
+ cs.pastTrailers = true
2472
+ if !f.StreamEnded() {
2473
+ // We expect that any headers for trailers also
2474
+ // has END_STREAM.
2475
+ return ConnectionError(ErrCodeProtocol)
2476
+ }
2477
+ if len(f.PseudoFields()) > 0 {
2478
+ // No pseudo header fields are defined for trailers.
2479
+ // TODO: ConnectionError might be overly harsh? Check.
2480
+ return ConnectionError(ErrCodeProtocol)
2481
+ }
2482
+
2483
+ trailer := make(http.Header)
2484
+ for _, hf := range f.RegularFields() {
2485
+ key := httpcommon.CanonicalHeader(hf.Name)
2486
+ trailer[key] = append(trailer[key], hf.Value)
2487
+ }
2488
+ cs.trailer = trailer
2489
+
2490
+ rl.endStream(cs)
2491
+ return nil
2492
+ }
2493
+
2494
+ // transportResponseBody is the concrete type of Transport.RoundTrip's
2495
+ // Response.Body. It is an io.ReadCloser.
2496
+ type transportResponseBody struct {
2497
+ cs *clientStream
2498
+ }
2499
+
2500
+ func (b transportResponseBody) Read(p []byte) (n int, err error) {
2501
+ cs := b.cs
2502
+ cc := cs.cc
2503
+
2504
+ if cs.readErr != nil {
2505
+ return 0, cs.readErr
2506
+ }
2507
+ n, err = b.cs.bufPipe.Read(p)
2508
+ if cs.bytesRemain != -1 {
2509
+ if int64(n) > cs.bytesRemain {
2510
+ n = int(cs.bytesRemain)
2511
+ if err == nil {
2512
+ err = errors.New("net/http: server replied with more than declared Content-Length; truncated")
2513
+ cs.abortStream(err)
2514
+ }
2515
+ cs.readErr = err
2516
+ return int(cs.bytesRemain), err
2517
+ }
2518
+ cs.bytesRemain -= int64(n)
2519
+ if err == io.EOF && cs.bytesRemain > 0 {
2520
+ err = io.ErrUnexpectedEOF
2521
+ cs.readErr = err
2522
+ return n, err
2523
+ }
2524
+ }
2525
+ if n == 0 {
2526
+ // No flow control tokens to send back.
2527
+ return
2528
+ }
2529
+
2530
+ cc.mu.Lock()
2531
+ connAdd := cc.inflow.add(n)
2532
+ var streamAdd int32
2533
+ if err == nil { // No need to refresh if the stream is over or failed.
2534
+ streamAdd = cs.inflow.add(n)
2535
+ }
2536
+ cc.mu.Unlock()
2537
+
2538
+ if connAdd != 0 || streamAdd != 0 {
2539
+ cc.wmu.Lock()
2540
+ defer cc.wmu.Unlock()
2541
+ if connAdd != 0 {
2542
+ cc.fr.WriteWindowUpdate(0, mustUint31(connAdd))
2543
+ }
2544
+ if streamAdd != 0 {
2545
+ cc.fr.WriteWindowUpdate(cs.ID, mustUint31(streamAdd))
2546
+ }
2547
+ cc.bw.Flush()
2548
+ }
2549
+ return
2550
+ }
2551
+
2552
+ var errClosedResponseBody = errors.New("http2: response body closed")
2553
+
2554
+ func (b transportResponseBody) Close() error {
2555
+ cs := b.cs
2556
+ cc := cs.cc
2557
+
2558
+ cs.bufPipe.BreakWithError(errClosedResponseBody)
2559
+ cs.abortStream(errClosedResponseBody)
2560
+
2561
+ unread := cs.bufPipe.Len()
2562
+ if unread > 0 {
2563
+ cc.mu.Lock()
2564
+ // Return connection-level flow control.
2565
+ connAdd := cc.inflow.add(unread)
2566
+ cc.mu.Unlock()
2567
+
2568
+ // TODO(dneil): Acquiring this mutex can block indefinitely.
2569
+ // Move flow control return to a goroutine?
2570
+ cc.wmu.Lock()
2571
+ // Return connection-level flow control.
2572
+ if connAdd > 0 {
2573
+ cc.fr.WriteWindowUpdate(0, uint32(connAdd))
2574
+ }
2575
+ cc.bw.Flush()
2576
+ cc.wmu.Unlock()
2577
+ }
2578
+
2579
+ select {
2580
+ case <-cs.donec:
2581
+ case <-cs.ctx.Done():
2582
+ // See golang/go#49366: The net/http package can cancel the
2583
+ // request context after the response body is fully read.
2584
+ // Don't treat this as an error.
2585
+ return nil
2586
+ case <-cs.reqCancel:
2587
+ return errRequestCanceled
2588
+ }
2589
+ return nil
2590
+ }
2591
+
2592
+ func (rl *clientConnReadLoop) processData(f *DataFrame) error {
2593
+ cc := rl.cc
2594
+ cs := rl.streamByID(f.StreamID, headerOrDataFrame)
2595
+ data := f.Data()
2596
+ if cs == nil {
2597
+ cc.mu.Lock()
2598
+ neverSent := cc.nextStreamID
2599
+ cc.mu.Unlock()
2600
+ if f.StreamID >= neverSent {
2601
+ // We never asked for this.
2602
+ cc.logf("http2: Transport received unsolicited DATA frame; closing connection")
2603
+ return ConnectionError(ErrCodeProtocol)
2604
+ }
2605
+ // We probably did ask for this, but canceled. Just ignore it.
2606
+ // TODO: be stricter here? only silently ignore things which
2607
+ // we canceled, but not things which were closed normally
2608
+ // by the peer? Tough without accumulating too much state.
2609
+
2610
+ // But at least return their flow control:
2611
+ if f.Length > 0 {
2612
+ cc.mu.Lock()
2613
+ ok := cc.inflow.take(f.Length)
2614
+ connAdd := cc.inflow.add(int(f.Length))
2615
+ cc.mu.Unlock()
2616
+ if !ok {
2617
+ return ConnectionError(ErrCodeFlowControl)
2618
+ }
2619
+ if connAdd > 0 {
2620
+ cc.wmu.Lock()
2621
+ cc.fr.WriteWindowUpdate(0, uint32(connAdd))
2622
+ cc.bw.Flush()
2623
+ cc.wmu.Unlock()
2624
+ }
2625
+ }
2626
+ return nil
2627
+ }
2628
+ if cs.readClosed {
2629
+ cc.logf("protocol error: received DATA after END_STREAM")
2630
+ rl.endStreamError(cs, StreamError{
2631
+ StreamID: f.StreamID,
2632
+ Code: ErrCodeProtocol,
2633
+ })
2634
+ return nil
2635
+ }
2636
+ if !cs.pastHeaders {
2637
+ cc.logf("protocol error: received DATA before a HEADERS frame")
2638
+ rl.endStreamError(cs, StreamError{
2639
+ StreamID: f.StreamID,
2640
+ Code: ErrCodeProtocol,
2641
+ })
2642
+ return nil
2643
+ }
2644
+ if f.Length > 0 {
2645
+ if cs.isHead && len(data) > 0 {
2646
+ cc.logf("protocol error: received DATA on a HEAD request")
2647
+ rl.endStreamError(cs, StreamError{
2648
+ StreamID: f.StreamID,
2649
+ Code: ErrCodeProtocol,
2650
+ })
2651
+ return nil
2652
+ }
2653
+ // Check connection-level flow control.
2654
+ cc.mu.Lock()
2655
+ if !takeInflows(&cc.inflow, &cs.inflow, f.Length) {
2656
+ cc.mu.Unlock()
2657
+ return ConnectionError(ErrCodeFlowControl)
2658
+ }
2659
+ // Return any padded flow control now, since we won't
2660
+ // refund it later on body reads.
2661
+ var refund int
2662
+ if pad := int(f.Length) - len(data); pad > 0 {
2663
+ refund += pad
2664
+ }
2665
+
2666
+ didReset := false
2667
+ var err error
2668
+ if len(data) > 0 {
2669
+ if _, err = cs.bufPipe.Write(data); err != nil {
2670
+ // Return len(data) now if the stream is already closed,
2671
+ // since data will never be read.
2672
+ didReset = true
2673
+ refund += len(data)
2674
+ }
2675
+ }
2676
+
2677
+ sendConn := cc.inflow.add(refund)
2678
+ var sendStream int32
2679
+ if !didReset {
2680
+ sendStream = cs.inflow.add(refund)
2681
+ }
2682
+ cc.mu.Unlock()
2683
+
2684
+ if sendConn > 0 || sendStream > 0 {
2685
+ cc.wmu.Lock()
2686
+ if sendConn > 0 {
2687
+ cc.fr.WriteWindowUpdate(0, uint32(sendConn))
2688
+ }
2689
+ if sendStream > 0 {
2690
+ cc.fr.WriteWindowUpdate(cs.ID, uint32(sendStream))
2691
+ }
2692
+ cc.bw.Flush()
2693
+ cc.wmu.Unlock()
2694
+ }
2695
+
2696
+ if err != nil {
2697
+ rl.endStreamError(cs, err)
2698
+ return nil
2699
+ }
2700
+ }
2701
+
2702
+ if f.StreamEnded() {
2703
+ rl.endStream(cs)
2704
+ }
2705
+ return nil
2706
+ }
2707
+
2708
+ func (rl *clientConnReadLoop) endStream(cs *clientStream) {
2709
+ // TODO: check that any declared content-length matches, like
2710
+ // server.go's (*stream).endStream method.
2711
+ if !cs.readClosed {
2712
+ cs.readClosed = true
2713
+ // Close cs.bufPipe and cs.peerClosed with cc.mu held to avoid a
2714
+ // race condition: The caller can read io.EOF from Response.Body
2715
+ // and close the body before we close cs.peerClosed, causing
2716
+ // cleanupWriteRequest to send a RST_STREAM.
2717
+ rl.cc.mu.Lock()
2718
+ defer rl.cc.mu.Unlock()
2719
+ cs.bufPipe.closeWithErrorAndCode(io.EOF, cs.copyTrailers)
2720
+ close(cs.peerClosed)
2721
+ }
2722
+ }
2723
+
2724
+ func (rl *clientConnReadLoop) endStreamError(cs *clientStream, err error) {
2725
+ cs.readAborted = true
2726
+ cs.abortStream(err)
2727
+ }
2728
+
2729
+ // Constants passed to streamByID for documentation purposes.
2730
+ const (
2731
+ headerOrDataFrame = true
2732
+ notHeaderOrDataFrame = false
2733
+ )
2734
+
2735
+ // streamByID returns the stream with the given id, or nil if no stream has that id.
2736
+ // If headerOrData is true, it clears rst.StreamPingsBlocked.
2737
+ func (rl *clientConnReadLoop) streamByID(id uint32, headerOrData bool) *clientStream {
2738
+ rl.cc.mu.Lock()
2739
+ defer rl.cc.mu.Unlock()
2740
+ if headerOrData {
2741
+ // Work around an unfortunate gRPC behavior.
2742
+ // See comment on ClientConn.rstStreamPingsBlocked for details.
2743
+ rl.cc.rstStreamPingsBlocked = false
2744
+ }
2745
+ cs := rl.cc.streams[id]
2746
+ if cs != nil && !cs.readAborted {
2747
+ return cs
2748
+ }
2749
+ return nil
2750
+ }
2751
+
2752
+ func (cs *clientStream) copyTrailers() {
2753
+ for k, vv := range cs.trailer {
2754
+ t := cs.resTrailer
2755
+ if *t == nil {
2756
+ *t = make(http.Header)
2757
+ }
2758
+ (*t)[k] = vv
2759
+ }
2760
+ }
2761
+
2762
+ func (rl *clientConnReadLoop) processGoAway(f *GoAwayFrame) error {
2763
+ cc := rl.cc
2764
+ cc.t.connPool().MarkDead(cc)
2765
+ if f.ErrCode != 0 {
2766
+ // TODO: deal with GOAWAY more. particularly the error code
2767
+ cc.vlogf("transport got GOAWAY with error code = %v", f.ErrCode)
2768
+ if fn := cc.t.CountError; fn != nil {
2769
+ fn("recv_goaway_" + f.ErrCode.stringToken())
2770
+ }
2771
+ }
2772
+ cc.setGoAway(f)
2773
+ return nil
2774
+ }
2775
+
2776
+ func (rl *clientConnReadLoop) processSettings(f *SettingsFrame) error {
2777
+ cc := rl.cc
2778
+ // Locking both mu and wmu here allows frame encoding to read settings with only wmu held.
2779
+ // Acquiring wmu when f.IsAck() is unnecessary, but convenient and mostly harmless.
2780
+ cc.wmu.Lock()
2781
+ defer cc.wmu.Unlock()
2782
+
2783
+ if err := rl.processSettingsNoWrite(f); err != nil {
2784
+ return err
2785
+ }
2786
+ if !f.IsAck() {
2787
+ cc.fr.WriteSettingsAck()
2788
+ cc.bw.Flush()
2789
+ }
2790
+ return nil
2791
+ }
2792
+
2793
+ func (rl *clientConnReadLoop) processSettingsNoWrite(f *SettingsFrame) error {
2794
+ cc := rl.cc
2795
+ cc.mu.Lock()
2796
+ defer cc.mu.Unlock()
2797
+
2798
+ if f.IsAck() {
2799
+ if cc.wantSettingsAck {
2800
+ cc.wantSettingsAck = false
2801
+ return nil
2802
+ }
2803
+ return ConnectionError(ErrCodeProtocol)
2804
+ }
2805
+
2806
+ var seenMaxConcurrentStreams bool
2807
+ err := f.ForeachSetting(func(s Setting) error {
2808
+ switch s.ID {
2809
+ case SettingMaxFrameSize:
2810
+ cc.maxFrameSize = s.Val
2811
+ case SettingMaxConcurrentStreams:
2812
+ cc.maxConcurrentStreams = s.Val
2813
+ seenMaxConcurrentStreams = true
2814
+ case SettingMaxHeaderListSize:
2815
+ cc.peerMaxHeaderListSize = uint64(s.Val)
2816
+ case SettingInitialWindowSize:
2817
+ // Values above the maximum flow-control
2818
+ // window size of 2^31-1 MUST be treated as a
2819
+ // connection error (Section 5.4.1) of type
2820
+ // FLOW_CONTROL_ERROR.
2821
+ if s.Val > math.MaxInt32 {
2822
+ return ConnectionError(ErrCodeFlowControl)
2823
+ }
2824
+
2825
+ // Adjust flow control of currently-open
2826
+ // frames by the difference of the old initial
2827
+ // window size and this one.
2828
+ delta := int32(s.Val) - int32(cc.initialWindowSize)
2829
+ for _, cs := range cc.streams {
2830
+ cs.flow.add(delta)
2831
+ }
2832
+ cc.cond.Broadcast()
2833
+
2834
+ cc.initialWindowSize = s.Val
2835
+ case SettingHeaderTableSize:
2836
+ cc.henc.SetMaxDynamicTableSize(s.Val)
2837
+ cc.peerMaxHeaderTableSize = s.Val
2838
+ case SettingEnableConnectProtocol:
2839
+ if err := s.Valid(); err != nil {
2840
+ return err
2841
+ }
2842
+ // If the peer wants to send us SETTINGS_ENABLE_CONNECT_PROTOCOL,
2843
+ // we require that it do so in the first SETTINGS frame.
2844
+ //
2845
+ // When we attempt to use extended CONNECT, we wait for the first
2846
+ // SETTINGS frame to see if the server supports it. If we let the
2847
+ // server enable the feature with a later SETTINGS frame, then
2848
+ // users will see inconsistent results depending on whether we've
2849
+ // seen that frame or not.
2850
+ if !cc.seenSettings {
2851
+ cc.extendedConnectAllowed = s.Val == 1
2852
+ }
2853
+ default:
2854
+ cc.vlogf("Unhandled Setting: %v", s)
2855
+ }
2856
+ return nil
2857
+ })
2858
+ if err != nil {
2859
+ return err
2860
+ }
2861
+
2862
+ if !cc.seenSettings {
2863
+ if !seenMaxConcurrentStreams {
2864
+ // This was the servers initial SETTINGS frame and it
2865
+ // didn't contain a MAX_CONCURRENT_STREAMS field so
2866
+ // increase the number of concurrent streams this
2867
+ // connection can establish to our default.
2868
+ cc.maxConcurrentStreams = defaultMaxConcurrentStreams
2869
+ }
2870
+ close(cc.seenSettingsChan)
2871
+ cc.seenSettings = true
2872
+ }
2873
+
2874
+ return nil
2875
+ }
2876
+
2877
+ func (rl *clientConnReadLoop) processWindowUpdate(f *WindowUpdateFrame) error {
2878
+ cc := rl.cc
2879
+ cs := rl.streamByID(f.StreamID, notHeaderOrDataFrame)
2880
+ if f.StreamID != 0 && cs == nil {
2881
+ return nil
2882
+ }
2883
+
2884
+ cc.mu.Lock()
2885
+ defer cc.mu.Unlock()
2886
+
2887
+ fl := &cc.flow
2888
+ if cs != nil {
2889
+ fl = &cs.flow
2890
+ }
2891
+ if !fl.add(int32(f.Increment)) {
2892
+ // For stream, the sender sends RST_STREAM with an error code of FLOW_CONTROL_ERROR
2893
+ if cs != nil {
2894
+ rl.endStreamError(cs, StreamError{
2895
+ StreamID: f.StreamID,
2896
+ Code: ErrCodeFlowControl,
2897
+ })
2898
+ return nil
2899
+ }
2900
+
2901
+ return ConnectionError(ErrCodeFlowControl)
2902
+ }
2903
+ cc.cond.Broadcast()
2904
+ return nil
2905
+ }
2906
+
2907
+ func (rl *clientConnReadLoop) processResetStream(f *RSTStreamFrame) error {
2908
+ cs := rl.streamByID(f.StreamID, notHeaderOrDataFrame)
2909
+ if cs == nil {
2910
+ // TODO: return error if server tries to RST_STREAM an idle stream
2911
+ return nil
2912
+ }
2913
+ serr := streamError(cs.ID, f.ErrCode)
2914
+ serr.Cause = errFromPeer
2915
+ if f.ErrCode == ErrCodeProtocol {
2916
+ rl.cc.SetDoNotReuse()
2917
+ }
2918
+ if fn := cs.cc.t.CountError; fn != nil {
2919
+ fn("recv_rststream_" + f.ErrCode.stringToken())
2920
+ }
2921
+ cs.abortStream(serr)
2922
+
2923
+ cs.bufPipe.CloseWithError(serr)
2924
+ return nil
2925
+ }
2926
+
2927
+ // Ping sends a PING frame to the server and waits for the ack.
2928
+ func (cc *ClientConn) Ping(ctx context.Context) error {
2929
+ c := make(chan struct{})
2930
+ // Generate a random payload
2931
+ var p [8]byte
2932
+ for {
2933
+ if _, err := rand.Read(p[:]); err != nil {
2934
+ return err
2935
+ }
2936
+ cc.mu.Lock()
2937
+ // check for dup before insert
2938
+ if _, found := cc.pings[p]; !found {
2939
+ cc.pings[p] = c
2940
+ cc.mu.Unlock()
2941
+ break
2942
+ }
2943
+ cc.mu.Unlock()
2944
+ }
2945
+ var pingError error
2946
+ errc := make(chan struct{})
2947
+ go func() {
2948
+ cc.wmu.Lock()
2949
+ defer cc.wmu.Unlock()
2950
+ if pingError = cc.fr.WritePing(false, p); pingError != nil {
2951
+ close(errc)
2952
+ return
2953
+ }
2954
+ if pingError = cc.bw.Flush(); pingError != nil {
2955
+ close(errc)
2956
+ return
2957
+ }
2958
+ }()
2959
+ select {
2960
+ case <-c:
2961
+ return nil
2962
+ case <-errc:
2963
+ return pingError
2964
+ case <-ctx.Done():
2965
+ return ctx.Err()
2966
+ case <-cc.readerDone:
2967
+ // connection closed
2968
+ return cc.readerErr
2969
+ }
2970
+ }
2971
+
2972
+ func (rl *clientConnReadLoop) processPing(f *PingFrame) error {
2973
+ if f.IsAck() {
2974
+ cc := rl.cc
2975
+ cc.mu.Lock()
2976
+ defer cc.mu.Unlock()
2977
+ // If ack, notify listener if any
2978
+ if c, ok := cc.pings[f.Data]; ok {
2979
+ close(c)
2980
+ delete(cc.pings, f.Data)
2981
+ }
2982
+ if cc.pendingResets > 0 {
2983
+ // See clientStream.cleanupWriteRequest.
2984
+ cc.pendingResets = 0
2985
+ cc.rstStreamPingsBlocked = true
2986
+ cc.cond.Broadcast()
2987
+ }
2988
+ return nil
2989
+ }
2990
+ cc := rl.cc
2991
+ cc.wmu.Lock()
2992
+ defer cc.wmu.Unlock()
2993
+ if err := cc.fr.WritePing(true, f.Data); err != nil {
2994
+ return err
2995
+ }
2996
+ return cc.bw.Flush()
2997
+ }
2998
+
2999
+ func (rl *clientConnReadLoop) processPushPromise(f *PushPromiseFrame) error {
3000
+ // We told the peer we don't want them.
3001
+ // Spec says:
3002
+ // "PUSH_PROMISE MUST NOT be sent if the SETTINGS_ENABLE_PUSH
3003
+ // setting of the peer endpoint is set to 0. An endpoint that
3004
+ // has set this setting and has received acknowledgement MUST
3005
+ // treat the receipt of a PUSH_PROMISE frame as a connection
3006
+ // error (Section 5.4.1) of type PROTOCOL_ERROR."
3007
+ return ConnectionError(ErrCodeProtocol)
3008
+ }
3009
+
3010
+ // writeStreamReset sends a RST_STREAM frame.
3011
+ // When ping is true, it also sends a PING frame with a random payload.
3012
+ func (cc *ClientConn) writeStreamReset(streamID uint32, code ErrCode, ping bool, err error) {
3013
+ // TODO: map err to more interesting error codes, once the
3014
+ // HTTP community comes up with some. But currently for
3015
+ // RST_STREAM there's no equivalent to GOAWAY frame's debug
3016
+ // data, and the error codes are all pretty vague ("cancel").
3017
+ cc.wmu.Lock()
3018
+ cc.fr.WriteRSTStream(streamID, code)
3019
+ if ping {
3020
+ var payload [8]byte
3021
+ rand.Read(payload[:])
3022
+ cc.fr.WritePing(false, payload)
3023
+ }
3024
+ cc.bw.Flush()
3025
+ cc.wmu.Unlock()
3026
+ }
3027
+
3028
+ var (
3029
+ errResponseHeaderListSize = errors.New("http2: response header list larger than advertised limit")
3030
+ errRequestHeaderListSize = httpcommon.ErrRequestHeaderListSize
3031
+ )
3032
+
3033
+ func (cc *ClientConn) logf(format string, args ...interface{}) {
3034
+ cc.t.logf(format, args...)
3035
+ }
3036
+
3037
+ func (cc *ClientConn) vlogf(format string, args ...interface{}) {
3038
+ cc.t.vlogf(format, args...)
3039
+ }
3040
+
3041
+ func (t *Transport) vlogf(format string, args ...interface{}) {
3042
+ if VerboseLogs {
3043
+ t.logf(format, args...)
3044
+ }
3045
+ }
3046
+
3047
+ func (t *Transport) logf(format string, args ...interface{}) {
3048
+ log.Printf(format, args...)
3049
+ }
3050
+
3051
+ var noBody io.ReadCloser = noBodyReader{}
3052
+
3053
+ type noBodyReader struct{}
3054
+
3055
+ func (noBodyReader) Close() error { return nil }
3056
+ func (noBodyReader) Read([]byte) (int, error) { return 0, io.EOF }
3057
+
3058
+ type missingBody struct{}
3059
+
3060
+ func (missingBody) Close() error { return nil }
3061
+ func (missingBody) Read([]byte) (int, error) { return 0, io.ErrUnexpectedEOF }
3062
+
3063
+ func strSliceContains(ss []string, s string) bool {
3064
+ for _, v := range ss {
3065
+ if v == s {
3066
+ return true
3067
+ }
3068
+ }
3069
+ return false
3070
+ }
3071
+
3072
+ type erringRoundTripper struct{ err error }
3073
+
3074
+ func (rt erringRoundTripper) RoundTripErr() error { return rt.err }
3075
+ func (rt erringRoundTripper) RoundTrip(*http.Request) (*http.Response, error) { return nil, rt.err }
3076
+
3077
+ // gzipReader wraps a response body so it can lazily
3078
+ // call gzip.NewReader on the first call to Read
3079
+ type gzipReader struct {
3080
+ _ incomparable
3081
+ body io.ReadCloser // underlying Response.Body
3082
+ zr *gzip.Reader // lazily-initialized gzip reader
3083
+ zerr error // sticky error
3084
+ }
3085
+
3086
+ func (gz *gzipReader) Read(p []byte) (n int, err error) {
3087
+ if gz.zerr != nil {
3088
+ return 0, gz.zerr
3089
+ }
3090
+ if gz.zr == nil {
3091
+ gz.zr, err = gzip.NewReader(gz.body)
3092
+ if err != nil {
3093
+ gz.zerr = err
3094
+ return 0, err
3095
+ }
3096
+ }
3097
+ return gz.zr.Read(p)
3098
+ }
3099
+
3100
+ func (gz *gzipReader) Close() error {
3101
+ if err := gz.body.Close(); err != nil {
3102
+ return err
3103
+ }
3104
+ gz.zerr = fs.ErrClosed
3105
+ return nil
3106
+ }
3107
+
3108
+ type errorReader struct{ err error }
3109
+
3110
+ func (r errorReader) Read(p []byte) (int, error) { return 0, r.err }
3111
+
3112
+ // isConnectionCloseRequest reports whether req should use its own
3113
+ // connection for a single request and then close the connection.
3114
+ func isConnectionCloseRequest(req *http.Request) bool {
3115
+ return req.Close || httpguts.HeaderValuesContainsToken(req.Header["Connection"], "close")
3116
+ }
3117
+
3118
+ // registerHTTPSProtocol calls Transport.RegisterProtocol but
3119
+ // converting panics into errors.
3120
+ func registerHTTPSProtocol(t *http.Transport, rt noDialH2RoundTripper) (err error) {
3121
+ defer func() {
3122
+ if e := recover(); e != nil {
3123
+ err = fmt.Errorf("%v", e)
3124
+ }
3125
+ }()
3126
+ t.RegisterProtocol("https", rt)
3127
+ return nil
3128
+ }
3129
+
3130
+ // noDialH2RoundTripper is a RoundTripper which only tries to complete the request
3131
+ // if there's already has a cached connection to the host.
3132
+ // (The field is exported so it can be accessed via reflect from net/http; tested
3133
+ // by TestNoDialH2RoundTripperType)
3134
+ type noDialH2RoundTripper struct{ *Transport }
3135
+
3136
+ func (rt noDialH2RoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
3137
+ res, err := rt.Transport.RoundTrip(req)
3138
+ if isNoCachedConnError(err) {
3139
+ return nil, http.ErrSkipAltProtocol
3140
+ }
3141
+ return res, err
3142
+ }
3143
+
3144
+ func (t *Transport) idleConnTimeout() time.Duration {
3145
+ // to keep things backwards compatible, we use non-zero values of
3146
+ // IdleConnTimeout, followed by using the IdleConnTimeout on the underlying
3147
+ // http1 transport, followed by 0
3148
+ if t.IdleConnTimeout != 0 {
3149
+ return t.IdleConnTimeout
3150
+ }
3151
+
3152
+ if t.t1 != nil {
3153
+ return t.t1.IdleConnTimeout
3154
+ }
3155
+
3156
+ return 0
3157
+ }
3158
+
3159
+ func traceGetConn(req *http.Request, hostPort string) {
3160
+ trace := httptrace.ContextClientTrace(req.Context())
3161
+ if trace == nil || trace.GetConn == nil {
3162
+ return
3163
+ }
3164
+ trace.GetConn(hostPort)
3165
+ }
3166
+
3167
+ func traceGotConn(req *http.Request, cc *ClientConn, reused bool) {
3168
+ trace := httptrace.ContextClientTrace(req.Context())
3169
+ if trace == nil || trace.GotConn == nil {
3170
+ return
3171
+ }
3172
+ ci := httptrace.GotConnInfo{Conn: cc.tconn}
3173
+ ci.Reused = reused
3174
+ cc.mu.Lock()
3175
+ ci.WasIdle = len(cc.streams) == 0 && reused
3176
+ if ci.WasIdle && !cc.lastActive.IsZero() {
3177
+ ci.IdleTime = time.Since(cc.lastActive)
3178
+ }
3179
+ cc.mu.Unlock()
3180
+
3181
+ trace.GotConn(ci)
3182
+ }
3183
+
3184
+ func traceWroteHeaders(trace *httptrace.ClientTrace) {
3185
+ if trace != nil && trace.WroteHeaders != nil {
3186
+ trace.WroteHeaders()
3187
+ }
3188
+ }
3189
+
3190
+ func traceGot100Continue(trace *httptrace.ClientTrace) {
3191
+ if trace != nil && trace.Got100Continue != nil {
3192
+ trace.Got100Continue()
3193
+ }
3194
+ }
3195
+
3196
+ func traceWait100Continue(trace *httptrace.ClientTrace) {
3197
+ if trace != nil && trace.Wait100Continue != nil {
3198
+ trace.Wait100Continue()
3199
+ }
3200
+ }
3201
+
3202
+ func traceWroteRequest(trace *httptrace.ClientTrace, err error) {
3203
+ if trace != nil && trace.WroteRequest != nil {
3204
+ trace.WroteRequest(httptrace.WroteRequestInfo{Err: err})
3205
+ }
3206
+ }
3207
+
3208
+ func traceFirstResponseByte(trace *httptrace.ClientTrace) {
3209
+ if trace != nil && trace.GotFirstResponseByte != nil {
3210
+ trace.GotFirstResponseByte()
3211
+ }
3212
+ }
3213
+
3214
+ func traceGot1xxResponseFunc(trace *httptrace.ClientTrace) func(int, textproto.MIMEHeader) error {
3215
+ if trace != nil {
3216
+ return trace.Got1xxResponse
3217
+ }
3218
+ return nil
3219
+ }
3220
+
3221
+ // dialTLSWithContext uses tls.Dialer, added in Go 1.15, to open a TLS
3222
+ // connection.
3223
+ func (t *Transport) dialTLSWithContext(ctx context.Context, network, addr string, cfg *tls.Config) (*tls.Conn, error) {
3224
+ dialer := &tls.Dialer{
3225
+ Config: cfg,
3226
+ }
3227
+ cn, err := dialer.DialContext(ctx, network, addr)
3228
+ if err != nil {
3229
+ return nil, err
3230
+ }
3231
+ tlsCn := cn.(*tls.Conn) // DialContext comment promises this will always succeed
3232
+ return tlsCn, nil
3233
+ }