Mercurial > public > mercurial-scm > hg
annotate mercurial/wireprotov2peer.py @ 40026:7e807b8a9e56
wireprotov2: client support for following content redirects
And with the server actually sending content redirects, it is finally
time to implement client support for following them!
When a redirect response is seen, we wait until all data for that
request has been received (it should be nearly immediate since no
data is expected to follow the redirect message). Then we use
a URL opener to make a request. We stuff that response into the
client handler and construct a new response object to track it.
When readdata() is called for servicing requests, we attempt to
read data from the first redirected response. During data reading,
data is processed similarly to as if it came from a frame payload.
The existing test for the functionality demonstrates the client
transparently following the redirect and obtaining the command
response data from an alternate URL!
There is still plenty of work to do here, including shoring up
testing. I'm not convinced things will work in the presence of
multiple redirect responses. And we don't yet implement support
for integrity verification or configuring server certificates
to validate the connection. But it's a start. And it should enable
us to start experimenting with "real" caches.
Differential Revision: https://phab.mercurial-scm.org/D4778
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Wed, 26 Sep 2018 18:08:08 -0700 |
parents | 86b22a4cfab1 |
children | cfeba1aafb9d |
rev | line source |
---|---|
37719
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
1 # wireprotov2peer.py - client side code for wire protocol version 2 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
2 # |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
3 # Copyright 2018 Gregory Szorc <gregory.szorc@gmail.com> |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
4 # |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
5 # This software may be used and distributed according to the terms of the |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
6 # GNU General Public License version 2 or any later version. |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
7 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
8 from __future__ import absolute_import |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
9 |
39561
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
10 import threading |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
11 |
37719
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
12 from .i18n import _ |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
13 from . import ( |
37721
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
14 encoding, |
37719
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
15 error, |
40026
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
16 pycompat, |
40024
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
17 sslutil, |
40026
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
18 url as urlmod, |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
19 util, |
37719
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
20 wireprotoframing, |
40026
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
21 wireprototypes, |
37719
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
22 ) |
39450
9f51fd22ed50
wireprotov2peer: use our CBOR decoder
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39438
diff
changeset
|
23 from .utils import ( |
9f51fd22ed50
wireprotov2peer: use our CBOR decoder
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39438
diff
changeset
|
24 cborutil, |
9f51fd22ed50
wireprotov2peer: use our CBOR decoder
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39438
diff
changeset
|
25 ) |
37719
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
26 |
37725
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
27 def formatrichmessage(atoms): |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
28 """Format an encoded message from the framing protocol.""" |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
29 |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
30 chunks = [] |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
31 |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
32 for atom in atoms: |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
33 msg = _(atom[b'msg']) |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
34 |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
35 if b'args' in atom: |
39486
43d92d68ac88
wireprotov2peer: properly format errors
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39485
diff
changeset
|
36 msg = msg % tuple(atom[b'args']) |
37725
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
37 |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
38 chunks.append(msg) |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
39 |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
40 return b''.join(chunks) |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
41 |
40024
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
42 SUPPORTED_REDIRECT_PROTOCOLS = { |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
43 b'http', |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
44 b'https', |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
45 } |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
46 |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
47 SUPPORTED_CONTENT_HASHES = { |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
48 b'sha1', |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
49 b'sha256', |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
50 } |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
51 |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
52 def redirecttargetsupported(ui, target): |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
53 """Determine whether a redirect target entry is supported. |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
54 |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
55 ``target`` should come from the capabilities data structure emitted by |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
56 the server. |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
57 """ |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
58 if target.get(b'protocol') not in SUPPORTED_REDIRECT_PROTOCOLS: |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
59 ui.note(_('(remote redirect target %s uses unsupported protocol: %s)\n') |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
60 % (target[b'name'], target.get(b'protocol', b''))) |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
61 return False |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
62 |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
63 if target.get(b'snirequired') and not sslutil.hassni: |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
64 ui.note(_('(redirect target %s requires SNI, which is unsupported)\n') % |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
65 target[b'name']) |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
66 return False |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
67 |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
68 if b'tlsversions' in target: |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
69 tlsversions = set(target[b'tlsversions']) |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
70 supported = set() |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
71 |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
72 for v in sslutil.supportedprotocols: |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
73 assert v.startswith(b'tls') |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
74 supported.add(v[3:]) |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
75 |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
76 if not tlsversions & supported: |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
77 ui.note(_('(remote redirect target %s requires unsupported TLS ' |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
78 'versions: %s)\n') % ( |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
79 target[b'name'], b', '.join(sorted(tlsversions)))) |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
80 return False |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
81 |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
82 ui.note(_('(remote redirect target %s is compatible)\n') % target[b'name']) |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
83 |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
84 return True |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
85 |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
86 def supportedredirects(ui, apidescriptor): |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
87 """Resolve the "redirect" command request key given an API descriptor. |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
88 |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
89 Given an API descriptor returned by the server, returns a data structure |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
90 that can be used in hte "redirect" field of command requests to advertise |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
91 support for compatible redirect targets. |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
92 |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
93 Returns None if no redirect targets are remotely advertised or if none are |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
94 supported. |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
95 """ |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
96 if not apidescriptor or b'redirect' not in apidescriptor: |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
97 return None |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
98 |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
99 targets = [t[b'name'] for t in apidescriptor[b'redirect'][b'targets'] |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
100 if redirecttargetsupported(ui, t)] |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
101 |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
102 hashes = [h for h in apidescriptor[b'redirect'][b'hashes'] |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
103 if h in SUPPORTED_CONTENT_HASHES] |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
104 |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
105 return { |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
106 b'targets': targets, |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
107 b'hashes': hashes, |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
108 } |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
109 |
37720
d715a85003c8
wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37719
diff
changeset
|
110 class commandresponse(object): |
39561
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
111 """Represents the response to a command request. |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
112 |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
113 Instances track the state of the command and hold its results. |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
114 |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
115 An external entity is required to update the state of the object when |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
116 events occur. |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
117 """ |
37720
d715a85003c8
wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37719
diff
changeset
|
118 |
40026
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
119 def __init__(self, requestid, command, fromredirect=False): |
37720
d715a85003c8
wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37719
diff
changeset
|
120 self.requestid = requestid |
d715a85003c8
wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37719
diff
changeset
|
121 self.command = command |
40026
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
122 self.fromredirect = fromredirect |
37720
d715a85003c8
wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37719
diff
changeset
|
123 |
39561
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
124 # Whether all remote input related to this command has been |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
125 # received. |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
126 self._inputcomplete = False |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
127 |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
128 # We have a lock that is acquired when important object state is |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
129 # mutated. This is to prevent race conditions between 1 thread |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
130 # sending us new data and another consuming it. |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
131 self._lock = threading.RLock() |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
132 |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
133 # An event is set when state of the object changes. This event |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
134 # is waited on by the generator emitting objects. |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
135 self._serviceable = threading.Event() |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
136 |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
137 self._pendingevents = [] |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
138 self._decoder = cborutil.bufferingdecoder() |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
139 self._seeninitial = False |
40026
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
140 self._redirect = None |
39561
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
141 |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
142 def _oninputcomplete(self): |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
143 with self._lock: |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
144 self._inputcomplete = True |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
145 self._serviceable.set() |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
146 |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
147 def _onresponsedata(self, data): |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
148 available, readcount, wanted = self._decoder.decode(data) |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
149 |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
150 if not available: |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
151 return |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
152 |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
153 with self._lock: |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
154 for o in self._decoder.getavailable(): |
40026
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
155 if not self._seeninitial and not self.fromredirect: |
39561
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
156 self._handleinitial(o) |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
157 continue |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
158 |
40026
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
159 # We should never see an object after a content redirect, |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
160 # as the spec says the main status object containing the |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
161 # content redirect is the only object in the stream. Fail |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
162 # if we see a misbehaving server. |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
163 if self._redirect: |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
164 raise error.Abort(_('received unexpected response data ' |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
165 'after content redirect; the remote is ' |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
166 'buggy')) |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
167 |
39561
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
168 self._pendingevents.append(o) |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
169 |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
170 self._serviceable.set() |
37720
d715a85003c8
wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37719
diff
changeset
|
171 |
39561
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
172 def _handleinitial(self, o): |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
173 self._seeninitial = True |
40024
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
174 if o[b'status'] == b'ok': |
39561
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
175 return |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
176 |
40024
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
177 elif o[b'status'] == b'redirect': |
40026
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
178 l = o[b'location'] |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
179 self._redirect = wireprototypes.alternatelocationresponse( |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
180 url=l[b'url'], |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
181 mediatype=l[b'mediatype'], |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
182 size=l.get(b'size'), |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
183 fullhashes=l.get(b'fullhashes'), |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
184 fullhashseed=l.get(b'fullhashseed'), |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
185 serverdercerts=l.get(b'serverdercerts'), |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
186 servercadercerts=l.get(b'servercadercerts')) |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
187 return |
40024
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
188 |
39561
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
189 atoms = [{'msg': o[b'error'][b'message']}] |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
190 if b'args' in o[b'error']: |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
191 atoms[0]['args'] = o[b'error'][b'args'] |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
192 |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
193 raise error.RepoError(formatrichmessage(atoms)) |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
194 |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
195 def objects(self): |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
196 """Obtained decoded objects from this response. |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
197 |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
198 This is a generator of data structures that were decoded from the |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
199 command response. |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
200 |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
201 Obtaining the next member of the generator may block due to waiting |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
202 on external data to become available. |
37720
d715a85003c8
wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37719
diff
changeset
|
203 |
39561
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
204 If the server encountered an error in the middle of serving the data |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
205 or if another error occurred, an exception may be raised when |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
206 advancing the generator. |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
207 """ |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
208 while True: |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
209 # TODO this can infinite loop if self._inputcomplete is never |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
210 # set. We likely want to tie the lifetime of this object/state |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
211 # to that of the background thread receiving frames and updating |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
212 # our state. |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
213 self._serviceable.wait(1.0) |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
214 |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
215 with self._lock: |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
216 self._serviceable.clear() |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
217 |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
218 # Make copies because objects could be mutated during |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
219 # iteration. |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
220 stop = self._inputcomplete |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
221 pending = list(self._pendingevents) |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
222 self._pendingevents[:] = [] |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
223 |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
224 for o in pending: |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
225 yield o |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
226 |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
227 if stop: |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
228 break |
37720
d715a85003c8
wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37719
diff
changeset
|
229 |
37719
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
230 class clienthandler(object): |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
231 """Object to handle higher-level client activities. |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
232 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
233 The ``clientreactor`` is used to hold low-level state about the frame-based |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
234 protocol, such as which requests and streams are active. This type is used |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
235 for higher-level operations, such as reading frames from a socket, exposing |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
236 and managing a higher-level primitive for representing command responses, |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
237 etc. This class is what peers should probably use to bridge wire activity |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
238 with the higher-level peer API. |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
239 """ |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
240 |
40026
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
241 def __init__(self, ui, clientreactor, opener=None, |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
242 requestbuilder=util.urlreq.request): |
37719
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
243 self._ui = ui |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
244 self._reactor = clientreactor |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
245 self._requests = {} |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
246 self._futures = {} |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
247 self._responses = {} |
40026
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
248 self._redirects = [] |
40019
f5a05bb48116
wireprotov2: change name and behavior of readframe()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39561
diff
changeset
|
249 self._frameseof = False |
40026
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
250 self._opener = opener or urlmod.opener(ui) |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
251 self._requestbuilder = requestbuilder |
37719
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
252 |
40024
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
253 def callcommand(self, command, args, f, redirect=None): |
37719
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
254 """Register a request to call a command. |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
255 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
256 Returns an iterable of frames that should be sent over the wire. |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
257 """ |
40024
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
258 request, action, meta = self._reactor.callcommand(command, args, |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40019
diff
changeset
|
259 redirect=redirect) |
37719
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
260 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
261 if action != 'noop': |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
262 raise error.ProgrammingError('%s not yet supported' % action) |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
263 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
264 rid = request.requestid |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
265 self._requests[rid] = request |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
266 self._futures[rid] = f |
39561
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
267 # TODO we need some kind of lifetime on response instances otherwise |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
268 # objects() may deadlock. |
37720
d715a85003c8
wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37719
diff
changeset
|
269 self._responses[rid] = commandresponse(rid, command) |
37719
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
270 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
271 return iter(()) |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
272 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
273 def flushcommands(self): |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
274 """Flush all queued commands. |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
275 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
276 Returns an iterable of frames that should be sent over the wire. |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
277 """ |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
278 action, meta = self._reactor.flushcommands() |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
279 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
280 if action != 'sendframes': |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
281 raise error.ProgrammingError('%s not yet supported' % action) |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
282 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
283 return meta['framegen'] |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
284 |
40019
f5a05bb48116
wireprotov2: change name and behavior of readframe()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39561
diff
changeset
|
285 def readdata(self, framefh): |
f5a05bb48116
wireprotov2: change name and behavior of readframe()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39561
diff
changeset
|
286 """Attempt to read data and do work. |
37719
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
287 |
40019
f5a05bb48116
wireprotov2: change name and behavior of readframe()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39561
diff
changeset
|
288 Returns None if no data was read. Presumably this means we're |
f5a05bb48116
wireprotov2: change name and behavior of readframe()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39561
diff
changeset
|
289 done with all read I/O. |
37719
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
290 """ |
40019
f5a05bb48116
wireprotov2: change name and behavior of readframe()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39561
diff
changeset
|
291 if not self._frameseof: |
f5a05bb48116
wireprotov2: change name and behavior of readframe()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39561
diff
changeset
|
292 frame = wireprotoframing.readframe(framefh) |
f5a05bb48116
wireprotov2: change name and behavior of readframe()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39561
diff
changeset
|
293 if frame is None: |
f5a05bb48116
wireprotov2: change name and behavior of readframe()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39561
diff
changeset
|
294 # TODO tell reactor? |
f5a05bb48116
wireprotov2: change name and behavior of readframe()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39561
diff
changeset
|
295 self._frameseof = True |
f5a05bb48116
wireprotov2: change name and behavior of readframe()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39561
diff
changeset
|
296 else: |
f5a05bb48116
wireprotov2: change name and behavior of readframe()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39561
diff
changeset
|
297 self._ui.note(_('received %r\n') % frame) |
f5a05bb48116
wireprotov2: change name and behavior of readframe()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39561
diff
changeset
|
298 self._processframe(frame) |
37719
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
299 |
40026
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
300 # Also try to read the first redirect. |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
301 if self._redirects: |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
302 if not self._processredirect(*self._redirects[0]): |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
303 self._redirects.pop(0) |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
304 |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
305 if self._frameseof and not self._redirects: |
40019
f5a05bb48116
wireprotov2: change name and behavior of readframe()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39561
diff
changeset
|
306 return None |
37719
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
307 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
308 return True |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
309 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
310 def _processframe(self, frame): |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
311 """Process a single read frame.""" |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
312 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
313 action, meta = self._reactor.onframerecv(frame) |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
314 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
315 if action == 'error': |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
316 e = error.RepoError(meta['message']) |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
317 |
39561
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
318 if frame.requestid in self._responses: |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
319 self._responses[frame.requestid]._oninputcomplete() |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
320 |
37719
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
321 if frame.requestid in self._futures: |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
322 self._futures[frame.requestid].set_exception(e) |
39561
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
323 del self._futures[frame.requestid] |
37719
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
324 else: |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
325 raise e |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
326 |
39559
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39486
diff
changeset
|
327 return |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39486
diff
changeset
|
328 |
37719
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
329 if frame.requestid not in self._requests: |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
330 raise error.ProgrammingError( |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
331 'received frame for unknown request; this is either a bug in ' |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
332 'the clientreactor not screening for this or this instance was ' |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
333 'never told about this request: %r' % frame) |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
334 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
335 response = self._responses[frame.requestid] |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
336 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
337 if action == 'responsedata': |
39485
42bc1c70a6b8
wireprotov2peer: report exceptions in frame handling against request future
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39450
diff
changeset
|
338 # Any failures processing this frame should bubble up to the |
42bc1c70a6b8
wireprotov2peer: report exceptions in frame handling against request future
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39450
diff
changeset
|
339 # future tracking the request. |
42bc1c70a6b8
wireprotov2peer: report exceptions in frame handling against request future
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39450
diff
changeset
|
340 try: |
42bc1c70a6b8
wireprotov2peer: report exceptions in frame handling against request future
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39450
diff
changeset
|
341 self._processresponsedata(frame, meta, response) |
42bc1c70a6b8
wireprotov2peer: report exceptions in frame handling against request future
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39450
diff
changeset
|
342 except BaseException as e: |
42bc1c70a6b8
wireprotov2peer: report exceptions in frame handling against request future
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39450
diff
changeset
|
343 self._futures[frame.requestid].set_exception(e) |
39561
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
344 del self._futures[frame.requestid] |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
345 response._oninputcomplete() |
37719
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
346 else: |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
347 raise error.ProgrammingError( |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
348 'unhandled action from clientreactor: %s' % action) |
37721
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
349 |
39438
c734a5c82f38
wireprotov2peer: split responsedata handling into separate function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39435
diff
changeset
|
350 def _processresponsedata(self, frame, meta, response): |
39561
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
351 # This can raise. The caller can handle it. |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
352 response._onresponsedata(meta['data']) |
39438
c734a5c82f38
wireprotov2peer: split responsedata handling into separate function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39435
diff
changeset
|
353 |
40026
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
354 # If we got a content redirect response, we want to fetch it and |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
355 # expose the data as if we received it inline. But we also want to |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
356 # keep our internal request accounting in order. Our strategy is to |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
357 # basically put meaningful response handling on pause until EOS occurs |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
358 # and the stream accounting is in a good state. At that point, we follow |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
359 # the redirect and replace the response object with its data. |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
360 |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
361 redirect = response._redirect |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
362 handlefuture = False if redirect else True |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
363 |
39438
c734a5c82f38
wireprotov2peer: split responsedata handling into separate function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39435
diff
changeset
|
364 if meta['eos']: |
39561
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
365 response._oninputcomplete() |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
366 del self._requests[frame.requestid] |
39438
c734a5c82f38
wireprotov2peer: split responsedata handling into separate function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39435
diff
changeset
|
367 |
40026
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
368 if redirect: |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
369 self._followredirect(frame.requestid, redirect) |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
370 return |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
371 |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
372 if not handlefuture: |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
373 return |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
374 |
39561
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
375 # If the command has a decoder, we wait until all input has been |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
376 # received before resolving the future. Otherwise we resolve the |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
377 # future immediately. |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
378 if frame.requestid not in self._futures: |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
379 return |
39438
c734a5c82f38
wireprotov2peer: split responsedata handling into separate function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39435
diff
changeset
|
380 |
39561
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
381 if response.command not in COMMAND_DECODERS: |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
382 self._futures[frame.requestid].set_result(response.objects()) |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
383 del self._futures[frame.requestid] |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
384 elif response._inputcomplete: |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
385 decoded = COMMAND_DECODERS[response.command](response.objects()) |
d06834e0f48e
wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39559
diff
changeset
|
386 self._futures[frame.requestid].set_result(decoded) |
39438
c734a5c82f38
wireprotov2peer: split responsedata handling into separate function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39435
diff
changeset
|
387 del self._futures[frame.requestid] |
c734a5c82f38
wireprotov2peer: split responsedata handling into separate function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39435
diff
changeset
|
388 |
40026
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
389 def _followredirect(self, requestid, redirect): |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
390 """Called to initiate redirect following for a request.""" |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
391 self._ui.note(_('(following redirect to %s)\n') % redirect.url) |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
392 |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
393 # TODO handle framed responses. |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
394 if redirect.mediatype != b'application/mercurial-cbor': |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
395 raise error.Abort(_('cannot handle redirects for the %s media type') |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
396 % redirect.mediatype) |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
397 |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
398 if redirect.fullhashes: |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
399 self._ui.warn(_('(support for validating hashes on content ' |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
400 'redirects not supported)\n')) |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
401 |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
402 if redirect.serverdercerts or redirect.servercadercerts: |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
403 self._ui.warn(_('(support for pinning server certificates on ' |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
404 'content redirects not supported)\n')) |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
405 |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
406 headers = { |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
407 r'Accept': redirect.mediatype, |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
408 } |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
409 |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
410 req = self._requestbuilder(pycompat.strurl(redirect.url), None, headers) |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
411 |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
412 try: |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
413 res = self._opener.open(req) |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
414 except util.urlerr.httperror as e: |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
415 if e.code == 401: |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
416 raise error.Abort(_('authorization failed')) |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
417 raise |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
418 except util.httplib.HTTPException as e: |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
419 self._ui.debug('http error requesting %s\n' % req.get_full_url()) |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
420 self._ui.traceback() |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
421 raise IOError(None, e) |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
422 |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
423 urlmod.wrapresponse(res) |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
424 |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
425 # The existing response object is associated with frame data. Rather |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
426 # than try to normalize its state, just create a new object. |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
427 oldresponse = self._responses[requestid] |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
428 self._responses[requestid] = commandresponse(requestid, |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
429 oldresponse.command, |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
430 fromredirect=True) |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
431 |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
432 self._redirects.append((requestid, res)) |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
433 |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
434 def _processredirect(self, rid, res): |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
435 """Called to continue processing a response from a redirect.""" |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
436 response = self._responses[rid] |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
437 |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
438 try: |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
439 data = res.read(32768) |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
440 response._onresponsedata(data) |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
441 |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
442 # We're at end of stream. |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
443 if not data: |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
444 response._oninputcomplete() |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
445 |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
446 if rid not in self._futures: |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
447 return |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
448 |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
449 if response.command not in COMMAND_DECODERS: |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
450 self._futures[rid].set_result(response.objects()) |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
451 del self._futures[rid] |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
452 elif response._inputcomplete: |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
453 decoded = COMMAND_DECODERS[response.command](response.objects()) |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
454 self._futures[rid].set_result(decoded) |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
455 del self._futures[rid] |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
456 |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
457 return bool(data) |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
458 |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
459 except BaseException as e: |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
460 self._futures[rid].set_exception(e) |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
461 del self._futures[rid] |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
462 response._oninputcomplete() |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
463 return False |
7e807b8a9e56
wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40024
diff
changeset
|
464 |
37725
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
465 def decodebranchmap(objs): |
37721
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
466 # Response should be a single CBOR map of branch name to array of nodes. |
37725
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
467 bm = next(objs) |
37721
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
468 |
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
469 return {encoding.tolocal(k): v for k, v in bm.items()} |
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
470 |
37725
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
471 def decodeheads(objs): |
37721
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
472 # Array of node bytestrings. |
37725
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
473 return next(objs) |
37721
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
474 |
37725
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
475 def decodeknown(objs): |
37721
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
476 # Bytestring where each byte is a 0 or 1. |
37725
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
477 raw = next(objs) |
37721
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
478 |
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
479 return [True if c == '1' else False for c in raw] |
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
480 |
37725
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
481 def decodelistkeys(objs): |
37721
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
482 # Map with bytestring keys and values. |
37725
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
483 return next(objs) |
37721
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
484 |
37725
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
485 def decodelookup(objs): |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
486 return next(objs) |
37721
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
487 |
37725
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
488 def decodepushkey(objs): |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
489 return next(objs) |
37721
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
490 |
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
491 COMMAND_DECODERS = { |
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
492 'branchmap': decodebranchmap, |
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
493 'heads': decodeheads, |
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
494 'known': decodeknown, |
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
495 'listkeys': decodelistkeys, |
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
496 'lookup': decodelookup, |
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
497 'pushkey': decodepushkey, |
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
498 } |