1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
U
[±dtFã@sþdZddlmZddlmZmZmZmZmZm    Z    m
Z
m Z m Z ddl Z ddlmZmZmZddlmZmZmZmZmZddlmZdd    lmZdd
lmZmZmZmZm Z m!Z!d Z"Gd d „d ƒZ#ee$e    ee
e%dœdd„Z&ee$e ee    edœdd„Z'dS)zR
wsproto/handshake
~~~~~~~~~~~~~~~~~~
 
An implementation of WebSocket handshakes.
é)Údeque)    ÚcastÚDequeÚDictÚ    GeneratorÚIterableÚListÚOptionalÚSequenceÚUnionNé)Ú
ConnectionÚConnectionStateÚConnectionType)ÚAcceptConnectionÚEventÚRejectConnectionÚ
RejectDataÚRequest)Ú    Extension)ÚHeaders)Úgenerate_accept_tokenÚgenerate_nonceÚLocalProtocolErrorÚnormed_header_dictÚRemoteProtocolErrorÚsplit_comma_headers13c@seZdZdZeddœdd„Zeedœdd„ƒZee    e
dœd    d
„ƒZ e e eefdd œd d „Zeedœdd„Ze    eddœdd„Zeeddfdœdd„Zejedœdd„Zeedœdd„Zeedœdd„Zeedœdd„Zeedœdd „Zej edœd!d"„Z!edœd#d$„Z"dS)%Ú H11Handshakez4A Handshake implementation for HTTP/1.1 connections.N)Úconnection_typeÚreturncCsV|tjk|_tj|_|jr*t tj¡|_nt tj    ¡|_d|_
t ƒ|_ d|_ d|_dS©N)rÚCLIENTÚclientrÚ
CONNECTINGÚ_stateÚh11r Ú_h11_connectionÚSERVERÚ _connectionrÚ_eventsÚ_initiating_requestÚ_nonce)Úselfr©r-úHd:\z\workplace\vscode\pyvenv\venv\Lib\site-packages\wsproto/handshake.pyÚ__init__*s zH11Handshake.__init__)rcCs|jSr )r$©r,r-r-r.Ústate8szH11Handshake.statecCs|jS)zÙReturn the established connection.
 
        This will either return the connection or raise a
        LocalProtocolError if the connection has not yet been
        established.
 
        :rtype: h11.Connection
        )r(r0r-r-r.Ú
connection<s
zH11Handshake.connection)ÚheadersÚpathrcCs>|jrtdƒ‚tjd||d}t tj¡}| | |¡¡dS)zóInitiate an upgrade connection.
 
        This should be used if the request has already be received and
        parsed.
 
        :param list headers: HTTP headers represented as a list of 2-tuples.
        :param str path: A URL path.
        z?Cannot initiate an upgrade connection when acting as the clientóGET©ÚmethodÚtargetr3N)r"rr%rr r!Ú receive_dataÚsend)r,r3r4Zupgrade_requestZ
h11_clientr-r-r.Úinitiate_upgrade_connectionHs ÿ z(H11Handshake.initiate_upgrade_connection)ÚeventrcCs€d}t|tƒr|| |¡7}n^t|tƒr8|| |¡7}nDt|tƒrR|| |¡7}n*t|tƒrl|| |¡7}nt    d|›dƒ‚|S)a
Send an event to the remote.
 
        This will return the bytes to send based on the event or raise
        a LocalProtocolError if the event is not valid given the
        state.
 
        :returns: Data to send to the WebSocket peer.
        :rtype: bytes
        ózEvent z$ cannot be sent during the handshake)
Ú
isinstancerÚ_initiate_connectionrÚ_acceptrÚ_rejectrÚ_send_reject_datar©r,r<Údatar-r-r.r:[s
 
 
 
 
 
ÿzH11Handshake.send)rDrcCsl|j |p d¡z|j ¡}Wn$tjk
rBtdtƒd‚YnXt|tjƒsd|tjksd|tj    krhqh|j
rHt|tj ƒrÂ|j dkrš|j  | |¡¡n&|j  tt|jƒ|j dd¡tj|_n„t|tjƒrötj|_|j  tt|jƒ|j dd¡nPt|tjƒr|j  t|jdd¡n*t|tjƒrf|j  tddd¡tj|_qt|tjƒr|j  | |¡¡qd    S)
zåReceive data from the remote.
 
        A list of events that the remote peer triggered by sending
        this data can be retrieved with :meth:`events`.
 
        :param bytes data: Data received from the WebSocket peer.
        r=zBad HTTP message©Z
event_hintéeF)r3Ú status_codeÚhas_bodyT)rDÚ body_finishedN)r&r9Z
next_eventr%rrr>ZConnectionClosedZ    NEED_DATAZPAUSEDr"ÚInformationalResponserGr)ÚappendÚ_establish_client_connectionÚlistr3rÚCLOSEDr$ÚResponseÚ    REJECTINGÚDatarrDÚ EndOfMessagerÚ_process_connection_request)r,rDr<r-r-r.r9tsZÿ 
ÿþý 
ýÿ
 ýÿ ÿ
 zH11Handshake.receive_dataccs|jr|j ¡VqdS)z¢Return a generator that provides any events that have been generated
        by protocol activity.
 
        :returns: a generator that yields H11 events.
        N)r)Úpopleftr0r-r-r.Úevents¬szH11Handshake.eventsc Cs¨|jdkrtdtƒd‚d}g}d}d}g}d}d}g}    |jD]¢\}
} |
 ¡}
|
dkr`t| ƒ}nr|
dkrv|  d¡}q>n\|
dkr| t| ƒ¡q>nB|
d    krž| }n4|
d
kr¸| t| ƒ¡q>n|
d krÆ| }n |
d krÒ| }|     |
| f¡q>|dksþt    d d„|Dƒƒs tdtƒd‚|t
kr:tdtdt
fg|r.dnddd‚|dkrRtdtƒd‚| ¡dkrntdtƒd‚|dkr†tdtƒd‚t ||    |||j  d¡d|_ |j S)Nr5zRequest method must be GETrEr=ó
connectionshostÚidnaósec-websocket-extensionsósec-websocket-keyósec-websocket-protocolssec-websocket-versionóupgradecss|]}| ¡dkVqdS©ÚupgradeN©Úlower©Ú.0Útokenr-r-r.Ú    <genexpr>Úsz;H11Handshake._process_connection_request.<locals>.<genexpr>ú%Missing header, 'Connection: Upgrade'z'Missing header, 'Sec-WebSocket-Version'óSec-WebSocket-Versioniªi)r3rGz#Missing header, 'Sec-WebSocket-Key'ó    websocketú$Missing header, 'Upgrade: WebSocket'zMissing header, 'Host'Úascii)Ú
extensionsÚ extra_headersÚhostÚ subprotocolsr8)r7rrr3r_rÚdecodeÚextendrKÚanyÚWEBSOCKET_VERSIONrr8r*) r,r<Úconnection_tokensrirkÚkeyrlr]Úversionr3ÚnameÚvaluer-r-r.rS·sŽ
ÿ
 
ÿ
ÿ
 þþ
ÿÿ
ÿ
ûz(H11Handshake._process_connection_requestcCsð|jdk    st‚t|jjƒ}|d}t|ƒ}ddd|fg}|jdk    rv|j|jjkr`td|j›ƒ‚| d|j     d¡f¡|j
r¨t t t t|jj
ƒ|j
ƒ}|r¨| d|f¡tjd    ||jd
}t|jrÊtjntj|j
ƒ|_tj|_|j |¡pîd S) NrY©óUpgrades    WebSocket©s
ConnectionrwsSec-WebSocket-Acceptzunexpected subprotocol óSec-WebSocket-ProtocolrhóSec-WebSocket-ExtensionsrF©rGr3r=)r*ÚAssertionErrorrrjrÚ subprotocolrlrrKÚencoderiÚserver_extensions_handshakerr
Ústrr%rJr r"rr!r'r(rÚOPENr$r&r:)r,r<Zrequest_headersÚnonceÚ accept_tokenr3ÚacceptsÚresponser-r-r.r@þs> ý
ÿþÿþzH11Handshake._acceptcCs†|jtjkrtd|jƒ‚t|jƒ}|js4| d¡tj    |j
|d}|j   |¡pRd}tj |_|js‚||j   t ¡¡pvd7}tj|_|S)Nz)Connection cannot be rejected in state %s)scontent-lengthó0r{r=)r1rr#rrMr3rHrKr%rOrGr&r:rPr$rRrN)r,r<r3r…rDr-r-r.rA%s ÿ
 
zH11Handshake._rejectcCs`|jtjkrtd|j›ƒ‚|j tj|jd¡p4d}|j    r\||j t 
¡¡pPd7}tj |_ |S)Nz$Cannot send rejection data in state )rDr=) r1rrPrr&r:r%rQrDrIrRrNr$rCr-r-r.rB6s 
ÿzH11Handshake._send_reject_data)Úrequestrc
Cs ||_tƒ|_d|j d¡fddd|jfdtfg}|jrT| dd |j¡ d    ¡f¡|j    rði}|j    D] }t
|t ƒsvt ‚|  ¡||j<qdg}| ¡D]D\}}| d    ¡}t
|tƒr¾|rÖ| |¡q’| d
|| d    ¡f¡q’|rð| d d  |¡f¡tjd |j d    ¡||jd}    |j |    ¡pdS)NsHostrWrvrxsSec-WebSocket-Keyreryz, rhó%s; %srzó, r5r6r=)r*rr+rkr~rprlrKÚjoinrir>rr|ÚofferrtÚitemsÚboolr%rr8rjr&r:)
r,r‡r3ZoffersÚerirtÚparamsZbnamer]r-r-r.r?DsDûþÿ
 
 
 
ýz!H11Handshake._initiate_connectionc Csš|jdk    st‚|jdk    st‚d}d}g}d}d}g}|jD]z\}}    | ¡}|dkr^t|    ƒ}q:nH|dkrrt|    ƒ}q:n4|dkr‚|    }q:n$|dkr˜|     d¡}q:n|dkr¦|    }q:| ||    f¡q:|dksÐtdd    „|DƒƒsÞt    d
t
ƒd ‚| ¡d krøt    d t
ƒd ‚t |jƒ}
||
krt    dt
ƒd ‚|dk    rF||jj krFt    d|›t
ƒd ‚t |ttt|jjƒƒ} t|jrntjntj| |jjdƒ|_tj|_t| ||dS)Nr=rVrXssec-websocket-acceptrZrhr[css|]}| ¡dkVqdSr\r^r`r-r-r.rcsz<H11Handshake._establish_client_connection.<locals>.<genexpr>rdrErfrgzBad accept tokenzunrecognized subprotocol r)rirjr})r*r|r+r3r_rrmrKrorrrrlÚclient_extensions_handshakerr
rrir r"rr!r'r&Z trailing_datar(rrr$r) r,r<Úacceptrqr„r}r]r3rtrurƒrir-r-r.rLos|
ÿÿ ÿ
 
 
þÿ
ýÿz)H11Handshake._establish_client_connectioncCsd |jj|j|j¡S)Nz{}(client={}, state={}))ÚformatÚ    __class__Ú__name__r"r1r0r-r-r.Ú__repr__°s
ÿzH11Handshake.__repr__)#r”Ú
__module__Ú __qualname__Ú__doc__rr/Úpropertyrr1r    r r2rr Úbytesr€r;rr:r9rrUr%rrSrr@rrArrBr?rJrLr•r-r-r-r.r's0 
þ 8 þ G',þ Ar)Ú    requestedÚ    supportedrc
Csìi}|D]h}| dd¡d ¡}|D]J}|j|kr$| |¡}t|tƒrV|rnd||j<q$|dk    r$| d¡||j<q$q|règ}| ¡D]Z\}}| d¡}    t|tƒr²|s¦t‚|     |    ¡q‚|dkrÊ|     d|    ¡q‚|     d    |    |f¡q‚d
 
|¡SdS) zƒAgree on the extensions to use returning an appropriate header value.
 
    This returns None if there are no agreed extensions
    ú;r rTNrhr=s%srˆr‰) ÚsplitÚstriprtr‘r>rr~rŒr|rKrŠ)
r›rœr„r‹rtÚ    extensionr‘rirZ
name_bytesr-r-r.r¶s.
 
 
 
 
 
r)ÚacceptedrœrcCsfg}|D]X}| dd¡d ¡}|D]&}|j|kr$| |¡| |¡qq$td|›tƒd‚q|S)Nrr rzunrecognized extension rE)ržrŸrtÚfinalizerKrr)r¡rœrir‘rtr r-r-r.rÚs
 
 
ÿr)(r˜Ú collectionsrÚtypingrrrrrrr    r
r r%r2r rrrUrrrrrrirrZ    utilitiesrrrrrrrprr€ršrrr-r-r-r.Ú<module>s* ,    
þ %þ