Mercurial > public > mercurial-scm > hg-stable
annotate mercurial/wireprotoframing.py @ 40126:e2fe1074024c
wireprotov2: update stream encoding specification
The encoding of data within streams in the frame-based protocol is
not yet defined or implemented. This means that all data in wire
protocol version 2 is currently being sent out raw, without
compression. That's obviously not ideal.
This commit formalizes the beginnings of stream encoding support
in the protocol.
I suspect we'll change behavior substantially in the future. My goal
is to get something landed so we can use compression. We can build
out more robust support later.
Because the frame type ID changed, this is strictly BC. But existing
code wasn't using the frame. I'll bump the framing protocol version
later once code is introduced to use the new frame.
Differential Revision: https://phab.mercurial-scm.org/D4915
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Thu, 04 Oct 2018 14:05:16 -0700 |
parents | b099e6032f38 |
children | 327d40b94bed |
rev | line source |
---|---|
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
1 # wireprotoframing.py - unified framing protocol for wire protocol |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
2 # |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
3 # Copyright 2018 Gregory Szorc <gregory.szorc@gmail.com> |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
4 # |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
5 # This software may be used and distributed according to the terms of the |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
6 # GNU General Public License version 2 or any later version. |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
7 |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
8 # This file contains functionality to support the unified frame-based wire |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
9 # protocol. For details about the protocol, see |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
10 # `hg help internals.wireprotocol`. |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
11 |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
12 from __future__ import absolute_import |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
13 |
37543
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
14 import collections |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
15 import struct |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
16 |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
17 from .i18n import _ |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
18 from .thirdparty import ( |
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
19 attr, |
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
20 ) |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
21 from . import ( |
37474
d33997123ea5
py3: system-stringify repr(frame)
Yuya Nishihara <yuya@tcha.org>
parents:
37473
diff
changeset
|
22 encoding, |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
23 error, |
40026
b099e6032f38
wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40025
diff
changeset
|
24 pycompat, |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
25 util, |
40021
ed919b90acda
wireprotov2: define type to represent pre-encoded object
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39843
diff
changeset
|
26 wireprototypes, |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
27 ) |
37087
f0b6fbea00cf
stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents:
37066
diff
changeset
|
28 from .utils import ( |
39465
36f487a332ad
wireprotoframing: use our CBOR module
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37728
diff
changeset
|
29 cborutil, |
37087
f0b6fbea00cf
stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents:
37066
diff
changeset
|
30 stringutil, |
f0b6fbea00cf
stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents:
37066
diff
changeset
|
31 ) |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
32 |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
33 FRAME_HEADER_SIZE = 8 |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
34 DEFAULT_MAX_FRAME_SIZE = 32768 |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
35 |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
36 STREAM_FLAG_BEGIN_STREAM = 0x01 |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
37 STREAM_FLAG_END_STREAM = 0x02 |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
38 STREAM_FLAG_ENCODING_APPLIED = 0x04 |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
39 |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
40 STREAM_FLAGS = { |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
41 b'stream-begin': STREAM_FLAG_BEGIN_STREAM, |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
42 b'stream-end': STREAM_FLAG_END_STREAM, |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
43 b'encoded': STREAM_FLAG_ENCODING_APPLIED, |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
44 } |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
45 |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
46 FRAME_TYPE_COMMAND_REQUEST = 0x01 |
37723
e8fba6d578f0
wireprotov2: change frame type value for command data
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
47 FRAME_TYPE_COMMAND_DATA = 0x02 |
37724
deff7cf7eefd
wireprotov2: change frame type and name for command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37723
diff
changeset
|
48 FRAME_TYPE_COMMAND_RESPONSE = 0x03 |
37058
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
49 FRAME_TYPE_ERROR_RESPONSE = 0x05 |
37063
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
50 FRAME_TYPE_TEXT_OUTPUT = 0x06 |
37291
b0041036214e
wireproto: define frame to represent progress updates
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37290
diff
changeset
|
51 FRAME_TYPE_PROGRESS = 0x07 |
40126
e2fe1074024c
wireprotov2: update stream encoding specification
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40026
diff
changeset
|
52 FRAME_TYPE_SENDER_PROTOCOL_SETTINGS = 0x08 |
e2fe1074024c
wireprotov2: update stream encoding specification
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40026
diff
changeset
|
53 FRAME_TYPE_STREAM_SETTINGS = 0x09 |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
54 |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
55 FRAME_TYPES = { |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
56 b'command-request': FRAME_TYPE_COMMAND_REQUEST, |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
57 b'command-data': FRAME_TYPE_COMMAND_DATA, |
37724
deff7cf7eefd
wireprotov2: change frame type and name for command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37723
diff
changeset
|
58 b'command-response': FRAME_TYPE_COMMAND_RESPONSE, |
37058
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
59 b'error-response': FRAME_TYPE_ERROR_RESPONSE, |
37063
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
60 b'text-output': FRAME_TYPE_TEXT_OUTPUT, |
37291
b0041036214e
wireproto: define frame to represent progress updates
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37290
diff
changeset
|
61 b'progress': FRAME_TYPE_PROGRESS, |
40126
e2fe1074024c
wireprotov2: update stream encoding specification
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40026
diff
changeset
|
62 b'sender-protocol-settings': FRAME_TYPE_SENDER_PROTOCOL_SETTINGS, |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
63 b'stream-settings': FRAME_TYPE_STREAM_SETTINGS, |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
64 } |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
65 |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
66 FLAG_COMMAND_REQUEST_NEW = 0x01 |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
67 FLAG_COMMAND_REQUEST_CONTINUATION = 0x02 |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
68 FLAG_COMMAND_REQUEST_MORE_FRAMES = 0x04 |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
69 FLAG_COMMAND_REQUEST_EXPECT_DATA = 0x08 |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
70 |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
71 FLAGS_COMMAND_REQUEST = { |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
72 b'new': FLAG_COMMAND_REQUEST_NEW, |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
73 b'continuation': FLAG_COMMAND_REQUEST_CONTINUATION, |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
74 b'more': FLAG_COMMAND_REQUEST_MORE_FRAMES, |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
75 b'have-data': FLAG_COMMAND_REQUEST_EXPECT_DATA, |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
76 } |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
77 |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
78 FLAG_COMMAND_DATA_CONTINUATION = 0x01 |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
79 FLAG_COMMAND_DATA_EOS = 0x02 |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
80 |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
81 FLAGS_COMMAND_DATA = { |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
82 b'continuation': FLAG_COMMAND_DATA_CONTINUATION, |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
83 b'eos': FLAG_COMMAND_DATA_EOS, |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
84 } |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
85 |
37724
deff7cf7eefd
wireprotov2: change frame type and name for command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37723
diff
changeset
|
86 FLAG_COMMAND_RESPONSE_CONTINUATION = 0x01 |
deff7cf7eefd
wireprotov2: change frame type and name for command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37723
diff
changeset
|
87 FLAG_COMMAND_RESPONSE_EOS = 0x02 |
37058
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
88 |
37724
deff7cf7eefd
wireprotov2: change frame type and name for command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37723
diff
changeset
|
89 FLAGS_COMMAND_RESPONSE = { |
deff7cf7eefd
wireprotov2: change frame type and name for command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37723
diff
changeset
|
90 b'continuation': FLAG_COMMAND_RESPONSE_CONTINUATION, |
deff7cf7eefd
wireprotov2: change frame type and name for command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37723
diff
changeset
|
91 b'eos': FLAG_COMMAND_RESPONSE_EOS, |
37058
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
92 } |
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
93 |
40126
e2fe1074024c
wireprotov2: update stream encoding specification
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40026
diff
changeset
|
94 FLAG_SENDER_PROTOCOL_SETTINGS_CONTINUATION = 0x01 |
e2fe1074024c
wireprotov2: update stream encoding specification
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40026
diff
changeset
|
95 FLAG_SENDER_PROTOCOL_SETTINGS_EOS = 0x02 |
e2fe1074024c
wireprotov2: update stream encoding specification
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40026
diff
changeset
|
96 |
e2fe1074024c
wireprotov2: update stream encoding specification
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40026
diff
changeset
|
97 FLAGS_SENDER_PROTOCOL_SETTINGS = { |
e2fe1074024c
wireprotov2: update stream encoding specification
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40026
diff
changeset
|
98 b'continuation': FLAG_SENDER_PROTOCOL_SETTINGS_CONTINUATION, |
e2fe1074024c
wireprotov2: update stream encoding specification
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40026
diff
changeset
|
99 b'eos': FLAG_SENDER_PROTOCOL_SETTINGS_EOS, |
e2fe1074024c
wireprotov2: update stream encoding specification
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40026
diff
changeset
|
100 } |
e2fe1074024c
wireprotov2: update stream encoding specification
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40026
diff
changeset
|
101 |
e2fe1074024c
wireprotov2: update stream encoding specification
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40026
diff
changeset
|
102 FLAG_STREAM_ENCODING_SETTINGS_CONTINUATION = 0x01 |
e2fe1074024c
wireprotov2: update stream encoding specification
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40026
diff
changeset
|
103 FLAG_STREAM_ENCODING_SETTINGS_EOS = 0x02 |
e2fe1074024c
wireprotov2: update stream encoding specification
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40026
diff
changeset
|
104 |
e2fe1074024c
wireprotov2: update stream encoding specification
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40026
diff
changeset
|
105 FLAGS_STREAM_ENCODING_SETTINGS = { |
e2fe1074024c
wireprotov2: update stream encoding specification
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40026
diff
changeset
|
106 b'continuation': FLAG_STREAM_ENCODING_SETTINGS_CONTINUATION, |
e2fe1074024c
wireprotov2: update stream encoding specification
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40026
diff
changeset
|
107 b'eos': FLAG_STREAM_ENCODING_SETTINGS_EOS, |
e2fe1074024c
wireprotov2: update stream encoding specification
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40026
diff
changeset
|
108 } |
e2fe1074024c
wireprotov2: update stream encoding specification
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40026
diff
changeset
|
109 |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
110 # Maps frame types to their available flags. |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
111 FRAME_TYPE_FLAGS = { |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
112 FRAME_TYPE_COMMAND_REQUEST: FLAGS_COMMAND_REQUEST, |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
113 FRAME_TYPE_COMMAND_DATA: FLAGS_COMMAND_DATA, |
37724
deff7cf7eefd
wireprotov2: change frame type and name for command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37723
diff
changeset
|
114 FRAME_TYPE_COMMAND_RESPONSE: FLAGS_COMMAND_RESPONSE, |
37726
0c184ca594bb
wireprotov2: change behavior of error frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37725
diff
changeset
|
115 FRAME_TYPE_ERROR_RESPONSE: {}, |
37063
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
116 FRAME_TYPE_TEXT_OUTPUT: {}, |
37291
b0041036214e
wireproto: define frame to represent progress updates
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37290
diff
changeset
|
117 FRAME_TYPE_PROGRESS: {}, |
40126
e2fe1074024c
wireprotov2: update stream encoding specification
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40026
diff
changeset
|
118 FRAME_TYPE_SENDER_PROTOCOL_SETTINGS: FLAGS_SENDER_PROTOCOL_SETTINGS, |
e2fe1074024c
wireprotov2: update stream encoding specification
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40026
diff
changeset
|
119 FRAME_TYPE_STREAM_SETTINGS: FLAGS_STREAM_ENCODING_SETTINGS, |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
120 } |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
121 |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
122 ARGUMENT_RECORD_HEADER = struct.Struct(r'<HH') |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
123 |
37298
5ef2da00e935
wireproto: implement custom __repr__ for frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37292
diff
changeset
|
124 def humanflags(mapping, value): |
5ef2da00e935
wireproto: implement custom __repr__ for frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37292
diff
changeset
|
125 """Convert a numeric flags value to a human value, using a mapping table.""" |
37473
7c2c7c749411
wireproto: show unknown id and flags in repr(frame)
Yuya Nishihara <yuya@tcha.org>
parents:
37472
diff
changeset
|
126 namemap = {v: k for k, v in mapping.iteritems()} |
37298
5ef2da00e935
wireproto: implement custom __repr__ for frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37292
diff
changeset
|
127 flags = [] |
37473
7c2c7c749411
wireproto: show unknown id and flags in repr(frame)
Yuya Nishihara <yuya@tcha.org>
parents:
37472
diff
changeset
|
128 val = 1 |
7c2c7c749411
wireproto: show unknown id and flags in repr(frame)
Yuya Nishihara <yuya@tcha.org>
parents:
37472
diff
changeset
|
129 while value >= val: |
37298
5ef2da00e935
wireproto: implement custom __repr__ for frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37292
diff
changeset
|
130 if value & val: |
37473
7c2c7c749411
wireproto: show unknown id and flags in repr(frame)
Yuya Nishihara <yuya@tcha.org>
parents:
37472
diff
changeset
|
131 flags.append(namemap.get(val, '<unknown 0x%02x>' % val)) |
7c2c7c749411
wireproto: show unknown id and flags in repr(frame)
Yuya Nishihara <yuya@tcha.org>
parents:
37472
diff
changeset
|
132 val <<= 1 |
37298
5ef2da00e935
wireproto: implement custom __repr__ for frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37292
diff
changeset
|
133 |
5ef2da00e935
wireproto: implement custom __repr__ for frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37292
diff
changeset
|
134 return b'|'.join(flags) |
5ef2da00e935
wireproto: implement custom __repr__ for frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37292
diff
changeset
|
135 |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
136 @attr.s(slots=True) |
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
137 class frameheader(object): |
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
138 """Represents the data in a frame header.""" |
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
139 |
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
140 length = attr.ib() |
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
141 requestid = attr.ib() |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
142 streamid = attr.ib() |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
143 streamflags = attr.ib() |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
144 typeid = attr.ib() |
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
145 flags = attr.ib() |
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
146 |
37298
5ef2da00e935
wireproto: implement custom __repr__ for frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37292
diff
changeset
|
147 @attr.s(slots=True, repr=False) |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
148 class frame(object): |
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
149 """Represents a parsed frame.""" |
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
150 |
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
151 requestid = attr.ib() |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
152 streamid = attr.ib() |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
153 streamflags = attr.ib() |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
154 typeid = attr.ib() |
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
155 flags = attr.ib() |
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
156 payload = attr.ib() |
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
157 |
37474
d33997123ea5
py3: system-stringify repr(frame)
Yuya Nishihara <yuya@tcha.org>
parents:
37473
diff
changeset
|
158 @encoding.strmethod |
37298
5ef2da00e935
wireproto: implement custom __repr__ for frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37292
diff
changeset
|
159 def __repr__(self): |
37473
7c2c7c749411
wireproto: show unknown id and flags in repr(frame)
Yuya Nishihara <yuya@tcha.org>
parents:
37472
diff
changeset
|
160 typename = '<unknown 0x%02x>' % self.typeid |
37298
5ef2da00e935
wireproto: implement custom __repr__ for frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37292
diff
changeset
|
161 for name, value in FRAME_TYPES.iteritems(): |
5ef2da00e935
wireproto: implement custom __repr__ for frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37292
diff
changeset
|
162 if value == self.typeid: |
5ef2da00e935
wireproto: implement custom __repr__ for frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37292
diff
changeset
|
163 typename = name |
5ef2da00e935
wireproto: implement custom __repr__ for frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37292
diff
changeset
|
164 break |
5ef2da00e935
wireproto: implement custom __repr__ for frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37292
diff
changeset
|
165 |
5ef2da00e935
wireproto: implement custom __repr__ for frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37292
diff
changeset
|
166 return ('frame(size=%d; request=%d; stream=%d; streamflags=%s; ' |
5ef2da00e935
wireproto: implement custom __repr__ for frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37292
diff
changeset
|
167 'type=%s; flags=%s)' % ( |
5ef2da00e935
wireproto: implement custom __repr__ for frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37292
diff
changeset
|
168 len(self.payload), self.requestid, self.streamid, |
5ef2da00e935
wireproto: implement custom __repr__ for frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37292
diff
changeset
|
169 humanflags(STREAM_FLAGS, self.streamflags), typename, |
37472
2f81926c7f89
wireproto: fix repr(frame) to not crash by unknown type id
Yuya Nishihara <yuya@tcha.org>
parents:
37319
diff
changeset
|
170 humanflags(FRAME_TYPE_FLAGS.get(self.typeid, {}), self.flags))) |
37298
5ef2da00e935
wireproto: implement custom __repr__ for frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37292
diff
changeset
|
171 |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
172 def makeframe(requestid, streamid, streamflags, typeid, flags, payload): |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
173 """Assemble a frame into a byte array.""" |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
174 # TODO assert size of payload. |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
175 frame = bytearray(FRAME_HEADER_SIZE + len(payload)) |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
176 |
37060
2ec1fb9de638
wireproto: add request IDs to frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37059
diff
changeset
|
177 # 24 bits length |
2ec1fb9de638
wireproto: add request IDs to frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37059
diff
changeset
|
178 # 16 bits request id |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
179 # 8 bits stream id |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
180 # 8 bits stream flags |
37060
2ec1fb9de638
wireproto: add request IDs to frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37059
diff
changeset
|
181 # 4 bits type |
2ec1fb9de638
wireproto: add request IDs to frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37059
diff
changeset
|
182 # 4 bits flags |
2ec1fb9de638
wireproto: add request IDs to frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37059
diff
changeset
|
183 |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
184 l = struct.pack(r'<I', len(payload)) |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
185 frame[0:3] = l[0:3] |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
186 struct.pack_into(r'<HBB', frame, 3, requestid, streamid, streamflags) |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
187 frame[7] = (typeid << 4) | flags |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
188 frame[8:] = payload |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
189 |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
190 return frame |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
191 |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
192 def makeframefromhumanstring(s): |
37060
2ec1fb9de638
wireproto: add request IDs to frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37059
diff
changeset
|
193 """Create a frame from a human readable string |
2ec1fb9de638
wireproto: add request IDs to frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37059
diff
changeset
|
194 |
2ec1fb9de638
wireproto: add request IDs to frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37059
diff
changeset
|
195 Strings have the form: |
2ec1fb9de638
wireproto: add request IDs to frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37059
diff
changeset
|
196 |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
197 <request-id> <stream-id> <stream-flags> <type> <flags> <payload> |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
198 |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
199 This can be used by user-facing applications and tests for creating |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
200 frames easily without having to type out a bunch of constants. |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
201 |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
202 Request ID and stream IDs are integers. |
37060
2ec1fb9de638
wireproto: add request IDs to frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37059
diff
changeset
|
203 |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
204 Stream flags, frame type, and flags can be specified by integer or |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
205 named constant. |
37060
2ec1fb9de638
wireproto: add request IDs to frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37059
diff
changeset
|
206 |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
207 Flags can be delimited by `|` to bitwise OR them together. |
37290
cc5a040fe150
wireproto: syntax for encoding CBOR into frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37289
diff
changeset
|
208 |
cc5a040fe150
wireproto: syntax for encoding CBOR into frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37289
diff
changeset
|
209 If the payload begins with ``cbor:``, the following string will be |
37476
e9dea82ea1f3
wireproto: convert python literal to object without using unsafe eval()
Yuya Nishihara <yuya@tcha.org>
parents:
37474
diff
changeset
|
210 evaluated as Python literal and the resulting object will be fed into |
37290
cc5a040fe150
wireproto: syntax for encoding CBOR into frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37289
diff
changeset
|
211 a CBOR encoder. Otherwise, the payload is interpreted as a Python |
cc5a040fe150
wireproto: syntax for encoding CBOR into frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37289
diff
changeset
|
212 byte string literal. |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
213 """ |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
214 fields = s.split(b' ', 5) |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
215 requestid, streamid, streamflags, frametype, frameflags, payload = fields |
37060
2ec1fb9de638
wireproto: add request IDs to frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37059
diff
changeset
|
216 |
2ec1fb9de638
wireproto: add request IDs to frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37059
diff
changeset
|
217 requestid = int(requestid) |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
218 streamid = int(streamid) |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
219 |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
220 finalstreamflags = 0 |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
221 for flag in streamflags.split(b'|'): |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
222 if flag in STREAM_FLAGS: |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
223 finalstreamflags |= STREAM_FLAGS[flag] |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
224 else: |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
225 finalstreamflags |= int(flag) |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
226 |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
227 if frametype in FRAME_TYPES: |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
228 frametype = FRAME_TYPES[frametype] |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
229 else: |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
230 frametype = int(frametype) |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
231 |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
232 finalflags = 0 |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
233 validflags = FRAME_TYPE_FLAGS[frametype] |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
234 for flag in frameflags.split(b'|'): |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
235 if flag in validflags: |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
236 finalflags |= validflags[flag] |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
237 else: |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
238 finalflags |= int(flag) |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
239 |
37290
cc5a040fe150
wireproto: syntax for encoding CBOR into frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37289
diff
changeset
|
240 if payload.startswith(b'cbor:'): |
39465
36f487a332ad
wireprotoframing: use our CBOR module
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37728
diff
changeset
|
241 payload = b''.join(cborutil.streamencode( |
36f487a332ad
wireprotoframing: use our CBOR module
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37728
diff
changeset
|
242 stringutil.evalpythonliteral(payload[5:]))) |
37290
cc5a040fe150
wireproto: syntax for encoding CBOR into frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37289
diff
changeset
|
243 |
cc5a040fe150
wireproto: syntax for encoding CBOR into frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37289
diff
changeset
|
244 else: |
cc5a040fe150
wireproto: syntax for encoding CBOR into frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37289
diff
changeset
|
245 payload = stringutil.unescapestr(payload) |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
246 |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
247 return makeframe(requestid=requestid, streamid=streamid, |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
248 streamflags=finalstreamflags, typeid=frametype, |
37065
fe4c944f95bb
wireproto: use named arguments when passing around frame data
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37064
diff
changeset
|
249 flags=finalflags, payload=payload) |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
250 |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
251 def parseheader(data): |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
252 """Parse a unified framing protocol frame header from a buffer. |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
253 |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
254 The header is expected to be in the buffer at offset 0 and the |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
255 buffer is expected to be large enough to hold a full header. |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
256 """ |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
257 # 24 bits payload length (little endian) |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
258 # 16 bits request ID |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
259 # 8 bits stream ID |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
260 # 8 bits stream flags |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
261 # 4 bits frame type |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
262 # 4 bits frame flags |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
263 # ... payload |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
264 framelength = data[0] + 256 * data[1] + 16384 * data[2] |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
265 requestid, streamid, streamflags = struct.unpack_from(r'<HBB', data, 3) |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
266 typeflags = data[7] |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
267 |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
268 frametype = (typeflags & 0xf0) >> 4 |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
269 frameflags = typeflags & 0x0f |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
270 |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
271 return frameheader(framelength, requestid, streamid, streamflags, |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
272 frametype, frameflags) |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
273 |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
274 def readframe(fh): |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
275 """Read a unified framing protocol frame from a file object. |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
276 |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
277 Returns a 3-tuple of (type, flags, payload) for the decoded frame or |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
278 None if no frame is available. May raise if a malformed frame is |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
279 seen. |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
280 """ |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
281 header = bytearray(FRAME_HEADER_SIZE) |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
282 |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
283 readcount = fh.readinto(header) |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
284 |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
285 if readcount == 0: |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
286 return None |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
287 |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
288 if readcount != FRAME_HEADER_SIZE: |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
289 raise error.Abort(_('received incomplete frame: got %d bytes: %s') % |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
290 (readcount, header)) |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
291 |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
292 h = parseheader(header) |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
293 |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
294 payload = fh.read(h.length) |
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
295 if len(payload) != h.length: |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
296 raise error.Abort(_('frame length error: expected %d; got %d') % |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
297 (h.length, len(payload))) |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
298 |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
299 return frame(h.requestid, h.streamid, h.streamflags, h.typeid, h.flags, |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
300 payload) |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
301 |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
302 def createcommandframes(stream, requestid, cmd, args, datafh=None, |
40025
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40021
diff
changeset
|
303 maxframesize=DEFAULT_MAX_FRAME_SIZE, |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40021
diff
changeset
|
304 redirect=None): |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
305 """Create frames necessary to transmit a request to run a command. |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
306 |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
307 This is a generator of bytearrays. Each item represents a frame |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
308 ready to be sent over the wire to a peer. |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
309 """ |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
310 data = {b'name': cmd} |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
311 if args: |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
312 data[b'args'] = args |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
313 |
40025
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40021
diff
changeset
|
314 if redirect: |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40021
diff
changeset
|
315 data[b'redirect'] = redirect |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40021
diff
changeset
|
316 |
39465
36f487a332ad
wireprotoframing: use our CBOR module
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37728
diff
changeset
|
317 data = b''.join(cborutil.streamencode(data)) |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
318 |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
319 offset = 0 |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
320 |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
321 while True: |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
322 flags = 0 |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
323 |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
324 # Must set new or continuation flag. |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
325 if not offset: |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
326 flags |= FLAG_COMMAND_REQUEST_NEW |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
327 else: |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
328 flags |= FLAG_COMMAND_REQUEST_CONTINUATION |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
329 |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
330 # Data frames is set on all frames. |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
331 if datafh: |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
332 flags |= FLAG_COMMAND_REQUEST_EXPECT_DATA |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
333 |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
334 payload = data[offset:offset + maxframesize] |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
335 offset += len(payload) |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
336 |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
337 if len(payload) == maxframesize and offset < len(data): |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
338 flags |= FLAG_COMMAND_REQUEST_MORE_FRAMES |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
339 |
37287
3ed344546d9e
wireproto: start to associate frame generation with a stream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37087
diff
changeset
|
340 yield stream.makeframe(requestid=requestid, |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
341 typeid=FRAME_TYPE_COMMAND_REQUEST, |
37287
3ed344546d9e
wireproto: start to associate frame generation with a stream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37087
diff
changeset
|
342 flags=flags, |
3ed344546d9e
wireproto: start to associate frame generation with a stream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37087
diff
changeset
|
343 payload=payload) |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
344 |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
345 if not (flags & FLAG_COMMAND_REQUEST_MORE_FRAMES): |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
346 break |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
347 |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
348 if datafh: |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
349 while True: |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
350 data = datafh.read(DEFAULT_MAX_FRAME_SIZE) |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
351 |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
352 done = False |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
353 if len(data) == DEFAULT_MAX_FRAME_SIZE: |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
354 flags = FLAG_COMMAND_DATA_CONTINUATION |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
355 else: |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
356 flags = FLAG_COMMAND_DATA_EOS |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
357 assert datafh.read(1) == b'' |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
358 done = True |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
359 |
37287
3ed344546d9e
wireproto: start to associate frame generation with a stream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37087
diff
changeset
|
360 yield stream.makeframe(requestid=requestid, |
3ed344546d9e
wireproto: start to associate frame generation with a stream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37087
diff
changeset
|
361 typeid=FRAME_TYPE_COMMAND_DATA, |
3ed344546d9e
wireproto: start to associate frame generation with a stream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37087
diff
changeset
|
362 flags=flags, |
3ed344546d9e
wireproto: start to associate frame generation with a stream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37087
diff
changeset
|
363 payload=data) |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
364 |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
365 if done: |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
366 break |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
367 |
37724
deff7cf7eefd
wireprotov2: change frame type and name for command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37723
diff
changeset
|
368 def createcommandresponseframesfrombytes(stream, requestid, data, |
deff7cf7eefd
wireprotov2: change frame type and name for command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37723
diff
changeset
|
369 maxframesize=DEFAULT_MAX_FRAME_SIZE): |
37058
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
370 """Create a raw frame to send a bytes response from static bytes input. |
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
371 |
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
372 Returns a generator of bytearrays. |
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
373 """ |
37725
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37724
diff
changeset
|
374 # Automatically send the overall CBOR response map. |
39465
36f487a332ad
wireprotoframing: use our CBOR module
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37728
diff
changeset
|
375 overall = b''.join(cborutil.streamencode({b'status': b'ok'})) |
37725
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37724
diff
changeset
|
376 if len(overall) > maxframesize: |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37724
diff
changeset
|
377 raise error.ProgrammingError('not yet implemented') |
37058
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
378 |
37725
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37724
diff
changeset
|
379 # Simple case where we can fit the full response in a single frame. |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37724
diff
changeset
|
380 if len(overall) + len(data) <= maxframesize: |
37724
deff7cf7eefd
wireprotov2: change frame type and name for command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37723
diff
changeset
|
381 flags = FLAG_COMMAND_RESPONSE_EOS |
37287
3ed344546d9e
wireproto: start to associate frame generation with a stream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37087
diff
changeset
|
382 yield stream.makeframe(requestid=requestid, |
37724
deff7cf7eefd
wireprotov2: change frame type and name for command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37723
diff
changeset
|
383 typeid=FRAME_TYPE_COMMAND_RESPONSE, |
37485
0b7475ea38cf
wireproto: port heads command to wire protocol v2
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37476
diff
changeset
|
384 flags=flags, |
37725
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37724
diff
changeset
|
385 payload=overall + data) |
37058
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
386 return |
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
387 |
37725
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37724
diff
changeset
|
388 # It's easier to send the overall CBOR map in its own frame than to track |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37724
diff
changeset
|
389 # offsets. |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37724
diff
changeset
|
390 yield stream.makeframe(requestid=requestid, |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37724
diff
changeset
|
391 typeid=FRAME_TYPE_COMMAND_RESPONSE, |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37724
diff
changeset
|
392 flags=FLAG_COMMAND_RESPONSE_CONTINUATION, |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37724
diff
changeset
|
393 payload=overall) |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37724
diff
changeset
|
394 |
37058
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
395 offset = 0 |
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
396 while True: |
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
397 chunk = data[offset:offset + maxframesize] |
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
398 offset += len(chunk) |
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
399 done = offset == len(data) |
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
400 |
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
401 if done: |
37724
deff7cf7eefd
wireprotov2: change frame type and name for command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37723
diff
changeset
|
402 flags = FLAG_COMMAND_RESPONSE_EOS |
37058
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
403 else: |
37724
deff7cf7eefd
wireprotov2: change frame type and name for command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37723
diff
changeset
|
404 flags = FLAG_COMMAND_RESPONSE_CONTINUATION |
37058
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
405 |
37287
3ed344546d9e
wireproto: start to associate frame generation with a stream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37087
diff
changeset
|
406 yield stream.makeframe(requestid=requestid, |
37724
deff7cf7eefd
wireprotov2: change frame type and name for command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37723
diff
changeset
|
407 typeid=FRAME_TYPE_COMMAND_RESPONSE, |
37287
3ed344546d9e
wireproto: start to associate frame generation with a stream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37087
diff
changeset
|
408 flags=flags, |
3ed344546d9e
wireproto: start to associate frame generation with a stream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37087
diff
changeset
|
409 payload=chunk) |
37058
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
410 |
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
411 if done: |
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
412 break |
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
413 |
37728
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
414 def createbytesresponseframesfromgen(stream, requestid, gen, |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
415 maxframesize=DEFAULT_MAX_FRAME_SIZE): |
39575
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
416 """Generator of frames from a generator of byte chunks. |
37728
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
417 |
39575
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
418 This assumes that another frame will follow whatever this emits. i.e. |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
419 this always emits the continuation flag and never emits the end-of-stream |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
420 flag. |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
421 """ |
37728
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
422 cb = util.chunkbuffer(gen) |
39575
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
423 flags = FLAG_COMMAND_RESPONSE_CONTINUATION |
37728
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
424 |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
425 while True: |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
426 chunk = cb.read(maxframesize) |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
427 if not chunk: |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
428 break |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
429 |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
430 yield stream.makeframe(requestid=requestid, |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
431 typeid=FRAME_TYPE_COMMAND_RESPONSE, |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
432 flags=flags, |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
433 payload=chunk) |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
434 |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
435 flags |= FLAG_COMMAND_RESPONSE_CONTINUATION |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
436 |
39575
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
437 def createcommandresponseokframe(stream, requestid): |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
438 overall = b''.join(cborutil.streamencode({b'status': b'ok'})) |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
439 |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
440 return stream.makeframe(requestid=requestid, |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
441 typeid=FRAME_TYPE_COMMAND_RESPONSE, |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
442 flags=FLAG_COMMAND_RESPONSE_CONTINUATION, |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
443 payload=overall) |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
444 |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
445 def createcommandresponseeosframe(stream, requestid): |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
446 """Create an empty payload frame representing command end-of-stream.""" |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
447 return stream.makeframe(requestid=requestid, |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
448 typeid=FRAME_TYPE_COMMAND_RESPONSE, |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
449 flags=FLAG_COMMAND_RESPONSE_EOS, |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
450 payload=b'') |
37728
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
451 |
40026
b099e6032f38
wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40025
diff
changeset
|
452 def createalternatelocationresponseframe(stream, requestid, location): |
b099e6032f38
wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40025
diff
changeset
|
453 data = { |
b099e6032f38
wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40025
diff
changeset
|
454 b'status': b'redirect', |
b099e6032f38
wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40025
diff
changeset
|
455 b'location': { |
b099e6032f38
wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40025
diff
changeset
|
456 b'url': location.url, |
b099e6032f38
wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40025
diff
changeset
|
457 b'mediatype': location.mediatype, |
b099e6032f38
wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40025
diff
changeset
|
458 } |
b099e6032f38
wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40025
diff
changeset
|
459 } |
b099e6032f38
wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40025
diff
changeset
|
460 |
b099e6032f38
wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40025
diff
changeset
|
461 for a in (r'size', r'fullhashes', r'fullhashseed', r'serverdercerts', |
b099e6032f38
wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40025
diff
changeset
|
462 r'servercadercerts'): |
b099e6032f38
wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40025
diff
changeset
|
463 value = getattr(location, a) |
b099e6032f38
wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40025
diff
changeset
|
464 if value is not None: |
b099e6032f38
wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40025
diff
changeset
|
465 data[b'location'][pycompat.bytestr(a)] = value |
b099e6032f38
wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40025
diff
changeset
|
466 |
b099e6032f38
wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40025
diff
changeset
|
467 return stream.makeframe(requestid=requestid, |
b099e6032f38
wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40025
diff
changeset
|
468 typeid=FRAME_TYPE_COMMAND_RESPONSE, |
b099e6032f38
wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40025
diff
changeset
|
469 flags=FLAG_COMMAND_RESPONSE_CONTINUATION, |
b099e6032f38
wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40025
diff
changeset
|
470 payload=b''.join(cborutil.streamencode(data))) |
b099e6032f38
wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40025
diff
changeset
|
471 |
37728
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
472 def createcommanderrorresponse(stream, requestid, message, args=None): |
39503
43d92d68ac88
wireprotov2peer: properly format errors
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39465
diff
changeset
|
473 # TODO should this be using a list of {'msg': ..., 'args': {}} so atom |
43d92d68ac88
wireprotov2peer: properly format errors
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39465
diff
changeset
|
474 # formatting works consistently? |
37728
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
475 m = { |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
476 b'status': b'error', |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
477 b'error': { |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
478 b'message': message, |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
479 } |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
480 } |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
481 |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
482 if args: |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
483 m[b'error'][b'args'] = args |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
484 |
39465
36f487a332ad
wireprotoframing: use our CBOR module
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37728
diff
changeset
|
485 overall = b''.join(cborutil.streamencode(m)) |
37728
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
486 |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
487 yield stream.makeframe(requestid=requestid, |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
488 typeid=FRAME_TYPE_COMMAND_RESPONSE, |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
489 flags=FLAG_COMMAND_RESPONSE_EOS, |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
490 payload=overall) |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
491 |
37726
0c184ca594bb
wireprotov2: change behavior of error frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37725
diff
changeset
|
492 def createerrorframe(stream, requestid, msg, errtype): |
37058
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
493 # TODO properly handle frame size limits. |
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
494 assert len(msg) <= DEFAULT_MAX_FRAME_SIZE |
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
495 |
39465
36f487a332ad
wireprotoframing: use our CBOR module
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37728
diff
changeset
|
496 payload = b''.join(cborutil.streamencode({ |
37726
0c184ca594bb
wireprotov2: change behavior of error frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37725
diff
changeset
|
497 b'type': errtype, |
0c184ca594bb
wireprotov2: change behavior of error frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37725
diff
changeset
|
498 b'message': [{b'msg': msg}], |
39465
36f487a332ad
wireprotoframing: use our CBOR module
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37728
diff
changeset
|
499 })) |
37058
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
500 |
37287
3ed344546d9e
wireproto: start to associate frame generation with a stream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37087
diff
changeset
|
501 yield stream.makeframe(requestid=requestid, |
3ed344546d9e
wireproto: start to associate frame generation with a stream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37087
diff
changeset
|
502 typeid=FRAME_TYPE_ERROR_RESPONSE, |
37726
0c184ca594bb
wireprotov2: change behavior of error frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37725
diff
changeset
|
503 flags=0, |
0c184ca594bb
wireprotov2: change behavior of error frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37725
diff
changeset
|
504 payload=payload) |
37058
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
505 |
37319
36d17f37db91
wireproto: convert human output frames to CBOR
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37299
diff
changeset
|
506 def createtextoutputframe(stream, requestid, atoms, |
36d17f37db91
wireproto: convert human output frames to CBOR
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37299
diff
changeset
|
507 maxframesize=DEFAULT_MAX_FRAME_SIZE): |
37063
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
508 """Create a text output frame to render text to people. |
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
509 |
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
510 ``atoms`` is a 3-tuple of (formatting string, args, labels). |
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
511 |
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
512 The formatting string contains ``%s`` tokens to be replaced by the |
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
513 corresponding indexed entry in ``args``. ``labels`` is an iterable of |
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
514 formatters to be applied at rendering time. In terms of the ``ui`` |
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
515 class, each atom corresponds to a ``ui.write()``. |
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
516 """ |
37319
36d17f37db91
wireproto: convert human output frames to CBOR
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37299
diff
changeset
|
517 atomdicts = [] |
37063
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
518 |
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
519 for (formatting, args, labels) in atoms: |
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
520 # TODO look for localstr, other types here? |
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
521 |
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
522 if not isinstance(formatting, bytes): |
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
523 raise ValueError('must use bytes formatting strings') |
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
524 for arg in args: |
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
525 if not isinstance(arg, bytes): |
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
526 raise ValueError('must use bytes for arguments') |
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
527 for label in labels: |
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
528 if not isinstance(label, bytes): |
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
529 raise ValueError('must use bytes for labels') |
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
530 |
37319
36d17f37db91
wireproto: convert human output frames to CBOR
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37299
diff
changeset
|
531 # Formatting string must be ASCII. |
36d17f37db91
wireproto: convert human output frames to CBOR
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37299
diff
changeset
|
532 formatting = formatting.decode(r'ascii', r'replace').encode(r'ascii') |
37063
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
533 |
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
534 # Arguments must be UTF-8. |
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
535 args = [a.decode(r'utf-8', r'replace').encode(r'utf-8') for a in args] |
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
536 |
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
537 # Labels must be ASCII. |
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
538 labels = [l.decode(r'ascii', r'strict').encode(r'ascii') |
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
539 for l in labels] |
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
540 |
37319
36d17f37db91
wireproto: convert human output frames to CBOR
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37299
diff
changeset
|
541 atom = {b'msg': formatting} |
36d17f37db91
wireproto: convert human output frames to CBOR
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37299
diff
changeset
|
542 if args: |
36d17f37db91
wireproto: convert human output frames to CBOR
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37299
diff
changeset
|
543 atom[b'args'] = args |
36d17f37db91
wireproto: convert human output frames to CBOR
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37299
diff
changeset
|
544 if labels: |
36d17f37db91
wireproto: convert human output frames to CBOR
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37299
diff
changeset
|
545 atom[b'labels'] = labels |
37063
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
546 |
37319
36d17f37db91
wireproto: convert human output frames to CBOR
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37299
diff
changeset
|
547 atomdicts.append(atom) |
37063
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
548 |
39465
36f487a332ad
wireprotoframing: use our CBOR module
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37728
diff
changeset
|
549 payload = b''.join(cborutil.streamencode(atomdicts)) |
37063
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
550 |
37319
36d17f37db91
wireproto: convert human output frames to CBOR
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37299
diff
changeset
|
551 if len(payload) > maxframesize: |
37063
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
552 raise ValueError('cannot encode data in a single frame') |
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
553 |
37287
3ed344546d9e
wireproto: start to associate frame generation with a stream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37087
diff
changeset
|
554 yield stream.makeframe(requestid=requestid, |
3ed344546d9e
wireproto: start to associate frame generation with a stream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37087
diff
changeset
|
555 typeid=FRAME_TYPE_TEXT_OUTPUT, |
3ed344546d9e
wireproto: start to associate frame generation with a stream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37087
diff
changeset
|
556 flags=0, |
37319
36d17f37db91
wireproto: convert human output frames to CBOR
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37299
diff
changeset
|
557 payload=payload) |
37287
3ed344546d9e
wireproto: start to associate frame generation with a stream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37087
diff
changeset
|
558 |
39576
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
559 class bufferingcommandresponseemitter(object): |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
560 """Helper object to emit command response frames intelligently. |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
561 |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
562 Raw command response data is likely emitted in chunks much smaller |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
563 than what can fit in a single frame. This class exists to buffer |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
564 chunks until enough data is available to fit in a single frame. |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
565 |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
566 TODO we'll need something like this when compression is supported. |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
567 So it might make sense to implement this functionality at the stream |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
568 level. |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
569 """ |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
570 def __init__(self, stream, requestid, maxframesize=DEFAULT_MAX_FRAME_SIZE): |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
571 self._stream = stream |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
572 self._requestid = requestid |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
573 self._maxsize = maxframesize |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
574 self._chunks = [] |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
575 self._chunkssize = 0 |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
576 |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
577 def send(self, data): |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
578 """Send new data for emission. |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
579 |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
580 Is a generator of new frames that were derived from the new input. |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
581 |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
582 If the special input ``None`` is received, flushes all buffered |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
583 data to frames. |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
584 """ |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
585 |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
586 if data is None: |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
587 for frame in self._flush(): |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
588 yield frame |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
589 return |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
590 |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
591 # There is a ton of potential to do more complicated things here. |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
592 # Our immediate goal is to coalesce small chunks into big frames, |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
593 # not achieve the fewest number of frames possible. So we go with |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
594 # a simple implementation: |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
595 # |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
596 # * If a chunk is too large for a frame, we flush and emit frames |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
597 # for the new chunk. |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
598 # * If a chunk can be buffered without total buffered size limits |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
599 # being exceeded, we do that. |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
600 # * If a chunk causes us to go over our buffering limit, we flush |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
601 # and then buffer the new chunk. |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
602 |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
603 if len(data) > self._maxsize: |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
604 for frame in self._flush(): |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
605 yield frame |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
606 |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
607 # Now emit frames for the big chunk. |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
608 offset = 0 |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
609 while True: |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
610 chunk = data[offset:offset + self._maxsize] |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
611 offset += len(chunk) |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
612 |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
613 yield self._stream.makeframe( |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
614 self._requestid, |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
615 typeid=FRAME_TYPE_COMMAND_RESPONSE, |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
616 flags=FLAG_COMMAND_RESPONSE_CONTINUATION, |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
617 payload=chunk) |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
618 |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
619 if offset == len(data): |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
620 return |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
621 |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
622 # If we don't have enough to constitute a full frame, buffer and |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
623 # return. |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
624 if len(data) + self._chunkssize < self._maxsize: |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
625 self._chunks.append(data) |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
626 self._chunkssize += len(data) |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
627 return |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
628 |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
629 # Else flush what we have and buffer the new chunk. We could do |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
630 # something more intelligent here, like break the chunk. Let's |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
631 # keep things simple for now. |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
632 for frame in self._flush(): |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
633 yield frame |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
634 |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
635 self._chunks.append(data) |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
636 self._chunkssize = len(data) |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
637 |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
638 def _flush(self): |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
639 payload = b''.join(self._chunks) |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
640 assert len(payload) <= self._maxsize |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
641 |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
642 self._chunks[:] = [] |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
643 self._chunkssize = 0 |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
644 |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
645 yield self._stream.makeframe( |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
646 self._requestid, |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
647 typeid=FRAME_TYPE_COMMAND_RESPONSE, |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
648 flags=FLAG_COMMAND_RESPONSE_CONTINUATION, |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
649 payload=payload) |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
650 |
37287
3ed344546d9e
wireproto: start to associate frame generation with a stream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37087
diff
changeset
|
651 class stream(object): |
3ed344546d9e
wireproto: start to associate frame generation with a stream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37087
diff
changeset
|
652 """Represents a logical unidirectional series of frames.""" |
3ed344546d9e
wireproto: start to associate frame generation with a stream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37087
diff
changeset
|
653 |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
654 def __init__(self, streamid, active=False): |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
655 self.streamid = streamid |
37655
b9502b5f2066
wireprotoframing: use value passed into function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37544
diff
changeset
|
656 self._active = active |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
657 |
37287
3ed344546d9e
wireproto: start to associate frame generation with a stream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37087
diff
changeset
|
658 def makeframe(self, requestid, typeid, flags, payload): |
3ed344546d9e
wireproto: start to associate frame generation with a stream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37087
diff
changeset
|
659 """Create a frame to be sent out over this stream. |
3ed344546d9e
wireproto: start to associate frame generation with a stream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37087
diff
changeset
|
660 |
3ed344546d9e
wireproto: start to associate frame generation with a stream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37087
diff
changeset
|
661 Only returns the frame instance. Does not actually send it. |
3ed344546d9e
wireproto: start to associate frame generation with a stream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37087
diff
changeset
|
662 """ |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
663 streamflags = 0 |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
664 if not self._active: |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
665 streamflags |= STREAM_FLAG_BEGIN_STREAM |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
666 self._active = True |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
667 |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
668 return makeframe(requestid, self.streamid, streamflags, typeid, flags, |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
669 payload) |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
670 |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
671 def ensureserverstream(stream): |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
672 if stream.streamid % 2: |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
673 raise error.ProgrammingError('server should only write to even ' |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
674 'numbered streams; %d is not even' % |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
675 stream.streamid) |
37063
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
676 |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
677 class serverreactor(object): |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
678 """Holds state of a server handling frame-based protocol requests. |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
679 |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
680 This class is the "brain" of the unified frame-based protocol server |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
681 component. While the protocol is stateless from the perspective of |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
682 requests/commands, something needs to track which frames have been |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
683 received, what frames to expect, etc. This class is that thing. |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
684 |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
685 Instances are modeled as a state machine of sorts. Instances are also |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
686 reactionary to external events. The point of this class is to encapsulate |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
687 the state of the connection and the exchange of frames, not to perform |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
688 work. Instead, callers tell this class when something occurs, like a |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
689 frame arriving. If that activity is worthy of a follow-up action (say |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
690 *run a command*), the return value of that handler will say so. |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
691 |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
692 I/O and CPU intensive operations are purposefully delegated outside of |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
693 this class. |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
694 |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
695 Consumers are expected to tell instances when events occur. They do so by |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
696 calling the various ``on*`` methods. These methods return a 2-tuple |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
697 describing any follow-up action(s) to take. The first element is the |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
698 name of an action to perform. The second is a data structure (usually |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
699 a dict) specific to that action that contains more information. e.g. |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
700 if the server wants to send frames back to the client, the data structure |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
701 will contain a reference to those frames. |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
702 |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
703 Valid actions that consumers can be instructed to take are: |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
704 |
37058
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
705 sendframes |
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
706 Indicates that frames should be sent to the client. The ``framegen`` |
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
707 key contains a generator of frames that should be sent. The server |
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
708 assumes that all frames are sent to the client. |
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
709 |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
710 error |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
711 Indicates that an error occurred. Consumer should probably abort. |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
712 |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
713 runcommand |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
714 Indicates that the consumer should run a wire protocol command. Details |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
715 of the command to run are given in the data structure. |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
716 |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
717 wantframe |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
718 Indicates that nothing of interest happened and the server is waiting on |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
719 more frames from the client before anything interesting can be done. |
37059
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
720 |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
721 noop |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
722 Indicates no additional action is required. |
37061
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
723 |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
724 Known Issues |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
725 ------------ |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
726 |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
727 There are no limits to the number of partially received commands or their |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
728 size. A malicious client could stream command request data and exhaust the |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
729 server's memory. |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
730 |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
731 Partially received commands are not acted upon when end of input is |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
732 reached. Should the server error if it receives a partial request? |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
733 Should the client send a message to abort a partially transmitted request |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
734 to facilitate graceful shutdown? |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
735 |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
736 Active requests that haven't been responded to aren't tracked. This means |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
737 that if we receive a command and instruct its dispatch, another command |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
738 with its request ID can come in over the wire and there will be a race |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
739 between who responds to what. |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
740 """ |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
741 |
37059
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
742 def __init__(self, deferoutput=False): |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
743 """Construct a new server reactor. |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
744 |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
745 ``deferoutput`` can be used to indicate that no output frames should be |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
746 instructed to be sent until input has been exhausted. In this mode, |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
747 events that would normally generate output frames (such as a command |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
748 response being ready) will instead defer instructing the consumer to |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
749 send those frames. This is useful for half-duplex transports where the |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
750 sender cannot receive until all data has been transmitted. |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
751 """ |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
752 self._deferoutput = deferoutput |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
753 self._state = 'idle' |
37289
5fadc63ac99f
wireproto: explicit API to create outgoing streams
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37288
diff
changeset
|
754 self._nextoutgoingstreamid = 2 |
37059
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
755 self._bufferedframegens = [] |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
756 # stream id -> stream instance for all active streams from the client. |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
757 self._incomingstreams = {} |
37289
5fadc63ac99f
wireproto: explicit API to create outgoing streams
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37288
diff
changeset
|
758 self._outgoingstreams = {} |
37061
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
759 # request id -> dict of commands that are actively being received. |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
760 self._receivingcommands = {} |
37066
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
761 # Request IDs that have been received and are actively being processed. |
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
762 # Once all output for a request has been sent, it is removed from this |
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
763 # set. |
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
764 self._activecommands = set() |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
765 |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
766 def onframerecv(self, frame): |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
767 """Process a frame that has been received off the wire. |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
768 |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
769 Returns a dict with an ``action`` key that details what action, |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
770 if any, the consumer should take next. |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
771 """ |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
772 if not frame.streamid % 2: |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
773 self._state = 'errored' |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
774 return self._makeerrorresult( |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
775 _('received frame with even numbered stream ID: %d') % |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
776 frame.streamid) |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
777 |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
778 if frame.streamid not in self._incomingstreams: |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
779 if not frame.streamflags & STREAM_FLAG_BEGIN_STREAM: |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
780 self._state = 'errored' |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
781 return self._makeerrorresult( |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
782 _('received frame on unknown inactive stream without ' |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
783 'beginning of stream flag set')) |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
784 |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
785 self._incomingstreams[frame.streamid] = stream(frame.streamid) |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
786 |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
787 if frame.streamflags & STREAM_FLAG_ENCODING_APPLIED: |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
788 # TODO handle decoding frames |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
789 self._state = 'errored' |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
790 raise error.ProgrammingError('support for decoding stream payloads ' |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
791 'not yet implemented') |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
792 |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
793 if frame.streamflags & STREAM_FLAG_END_STREAM: |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
794 del self._incomingstreams[frame.streamid] |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
795 |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
796 handlers = { |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
797 'idle': self._onframeidle, |
37061
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
798 'command-receiving': self._onframecommandreceiving, |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
799 'errored': self._onframeerrored, |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
800 } |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
801 |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
802 meth = handlers.get(self._state) |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
803 if not meth: |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
804 raise error.ProgrammingError('unhandled state: %s' % self._state) |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
805 |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
806 return meth(frame) |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
807 |
37724
deff7cf7eefd
wireprotov2: change frame type and name for command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37723
diff
changeset
|
808 def oncommandresponseready(self, stream, requestid, data): |
37058
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
809 """Signal that a bytes response is ready to be sent to the client. |
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
810 |
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
811 The raw bytes response is passed as an argument. |
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
812 """ |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
813 ensureserverstream(stream) |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
814 |
37066
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
815 def sendframes(): |
37724
deff7cf7eefd
wireprotov2: change frame type and name for command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37723
diff
changeset
|
816 for frame in createcommandresponseframesfrombytes(stream, requestid, |
deff7cf7eefd
wireprotov2: change frame type and name for command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37723
diff
changeset
|
817 data): |
37066
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
818 yield frame |
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
819 |
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
820 self._activecommands.remove(requestid) |
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
821 |
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
822 result = sendframes() |
37059
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
823 |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
824 if self._deferoutput: |
37066
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
825 self._bufferedframegens.append(result) |
37059
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
826 return 'noop', {} |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
827 else: |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
828 return 'sendframes', { |
37066
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
829 'framegen': result, |
37059
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
830 } |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
831 |
39575
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
832 def oncommandresponsereadyobjects(self, stream, requestid, objs): |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
833 """Signal that objects are ready to be sent to the client. |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
834 |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
835 ``objs`` is an iterable of objects (typically a generator) that will |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
836 be encoded via CBOR and added to frames, which will be sent to the |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
837 client. |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
838 """ |
37728
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
839 ensureserverstream(stream) |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
840 |
39575
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
841 # We need to take care over exception handling. Uncaught exceptions |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
842 # when generating frames could lead to premature end of the frame |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
843 # stream and the possibility of the server or client process getting |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
844 # in a bad state. |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
845 # |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
846 # Keep in mind that if ``objs`` is a generator, advancing it could |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
847 # raise exceptions that originated in e.g. wire protocol command |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
848 # functions. That is why we differentiate between exceptions raised |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
849 # when iterating versus other exceptions that occur. |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
850 # |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
851 # In all cases, when the function finishes, the request is fully |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
852 # handled and no new frames for it should be seen. |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
853 |
37728
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
854 def sendframes(): |
39575
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
855 emitted = False |
40026
b099e6032f38
wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40025
diff
changeset
|
856 alternatelocationsent = False |
39576
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
857 emitter = bufferingcommandresponseemitter(stream, requestid) |
39575
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
858 while True: |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
859 try: |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
860 o = next(objs) |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
861 except StopIteration: |
39576
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
862 for frame in emitter.send(None): |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
863 yield frame |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
864 |
39575
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
865 if emitted: |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
866 yield createcommandresponseeosframe(stream, requestid) |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
867 break |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
868 |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
869 except error.WireprotoCommandError as e: |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
870 for frame in createcommanderrorresponse( |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
871 stream, requestid, e.message, e.messageargs): |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
872 yield frame |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
873 break |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
874 |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
875 except Exception as e: |
39843
bce1c1af7518
py3: cast exception to bytes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39576
diff
changeset
|
876 for frame in createerrorframe( |
bce1c1af7518
py3: cast exception to bytes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39576
diff
changeset
|
877 stream, requestid, '%s' % stringutil.forcebytestr(e), |
bce1c1af7518
py3: cast exception to bytes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39576
diff
changeset
|
878 errtype='server'): |
bce1c1af7518
py3: cast exception to bytes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39576
diff
changeset
|
879 |
39575
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
880 yield frame |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
881 |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
882 break |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
883 |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
884 try: |
40026
b099e6032f38
wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40025
diff
changeset
|
885 # Alternate location responses can only be the first and |
b099e6032f38
wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40025
diff
changeset
|
886 # only object in the output stream. |
b099e6032f38
wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40025
diff
changeset
|
887 if isinstance(o, wireprototypes.alternatelocationresponse): |
b099e6032f38
wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40025
diff
changeset
|
888 if emitted: |
b099e6032f38
wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40025
diff
changeset
|
889 raise error.ProgrammingError( |
b099e6032f38
wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40025
diff
changeset
|
890 'alternatelocationresponse seen after initial ' |
b099e6032f38
wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40025
diff
changeset
|
891 'output object') |
b099e6032f38
wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40025
diff
changeset
|
892 |
b099e6032f38
wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40025
diff
changeset
|
893 yield createalternatelocationresponseframe( |
b099e6032f38
wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40025
diff
changeset
|
894 stream, requestid, o) |
b099e6032f38
wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40025
diff
changeset
|
895 |
b099e6032f38
wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40025
diff
changeset
|
896 alternatelocationsent = True |
b099e6032f38
wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40025
diff
changeset
|
897 emitted = True |
b099e6032f38
wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40025
diff
changeset
|
898 continue |
b099e6032f38
wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40025
diff
changeset
|
899 |
b099e6032f38
wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40025
diff
changeset
|
900 if alternatelocationsent: |
b099e6032f38
wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40025
diff
changeset
|
901 raise error.ProgrammingError( |
b099e6032f38
wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40025
diff
changeset
|
902 'object follows alternatelocationresponse') |
b099e6032f38
wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40025
diff
changeset
|
903 |
39575
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
904 if not emitted: |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
905 yield createcommandresponseokframe(stream, requestid) |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
906 emitted = True |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
907 |
40021
ed919b90acda
wireprotov2: define type to represent pre-encoded object
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39843
diff
changeset
|
908 # Objects emitted by command functions can be serializable |
ed919b90acda
wireprotov2: define type to represent pre-encoded object
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39843
diff
changeset
|
909 # data structures or special types. |
ed919b90acda
wireprotov2: define type to represent pre-encoded object
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39843
diff
changeset
|
910 # TODO consider extracting the content normalization to a |
ed919b90acda
wireprotov2: define type to represent pre-encoded object
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39843
diff
changeset
|
911 # standalone function, as it may be useful for e.g. cachers. |
ed919b90acda
wireprotov2: define type to represent pre-encoded object
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39843
diff
changeset
|
912 |
ed919b90acda
wireprotov2: define type to represent pre-encoded object
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39843
diff
changeset
|
913 # A pre-encoded object is sent directly to the emitter. |
ed919b90acda
wireprotov2: define type to represent pre-encoded object
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39843
diff
changeset
|
914 if isinstance(o, wireprototypes.encodedresponse): |
ed919b90acda
wireprotov2: define type to represent pre-encoded object
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39843
diff
changeset
|
915 for frame in emitter.send(o.data): |
39576
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
916 yield frame |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
917 |
40021
ed919b90acda
wireprotov2: define type to represent pre-encoded object
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39843
diff
changeset
|
918 # A regular object is CBOR encoded. |
ed919b90acda
wireprotov2: define type to represent pre-encoded object
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39843
diff
changeset
|
919 else: |
ed919b90acda
wireprotov2: define type to represent pre-encoded object
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39843
diff
changeset
|
920 for chunk in cborutil.streamencode(o): |
ed919b90acda
wireprotov2: define type to represent pre-encoded object
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39843
diff
changeset
|
921 for frame in emitter.send(chunk): |
ed919b90acda
wireprotov2: define type to represent pre-encoded object
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39843
diff
changeset
|
922 yield frame |
ed919b90acda
wireprotov2: define type to represent pre-encoded object
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39843
diff
changeset
|
923 |
39575
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
924 except Exception as e: |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
925 for frame in createerrorframe(stream, requestid, |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
926 '%s' % e, |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
927 errtype='server'): |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
928 yield frame |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
929 |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
930 break |
37728
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
931 |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
932 self._activecommands.remove(requestid) |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
933 |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
934 return self._handlesendframes(sendframes()) |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
935 |
37059
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
936 def oninputeof(self): |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
937 """Signals that end of input has been received. |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
938 |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
939 No more frames will be received. All pending activity should be |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
940 completed. |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
941 """ |
37061
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
942 # TODO should we do anything about in-flight commands? |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
943 |
37059
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
944 if not self._deferoutput or not self._bufferedframegens: |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
945 return 'noop', {} |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
946 |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
947 # If we buffered all our responses, emit those. |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
948 def makegen(): |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
949 for gen in self._bufferedframegens: |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
950 for frame in gen: |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
951 yield frame |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
952 |
37058
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
953 return 'sendframes', { |
37059
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
954 'framegen': makegen(), |
37058
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
955 } |
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
956 |
37728
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
957 def _handlesendframes(self, framegen): |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
958 if self._deferoutput: |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
959 self._bufferedframegens.append(framegen) |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
960 return 'noop', {} |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
961 else: |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
962 return 'sendframes', { |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
963 'framegen': framegen, |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
964 } |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
965 |
37726
0c184ca594bb
wireprotov2: change behavior of error frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37725
diff
changeset
|
966 def onservererror(self, stream, requestid, msg): |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
967 ensureserverstream(stream) |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
968 |
37728
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
969 def sendframes(): |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
970 for frame in createerrorframe(stream, requestid, msg, |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
971 errtype='server'): |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
972 yield frame |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
973 |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
974 self._activecommands.remove(requestid) |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
975 |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
976 return self._handlesendframes(sendframes()) |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
977 |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
978 def oncommanderror(self, stream, requestid, message, args=None): |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
979 """Called when a command encountered an error before sending output.""" |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
980 ensureserverstream(stream) |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
981 |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
982 def sendframes(): |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
983 for frame in createcommanderrorresponse(stream, requestid, message, |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
984 args): |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
985 yield frame |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
986 |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
987 self._activecommands.remove(requestid) |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
988 |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
989 return self._handlesendframes(sendframes()) |
37058
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
990 |
37289
5fadc63ac99f
wireproto: explicit API to create outgoing streams
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37288
diff
changeset
|
991 def makeoutputstream(self): |
5fadc63ac99f
wireproto: explicit API to create outgoing streams
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37288
diff
changeset
|
992 """Create a stream to be used for sending data to the client.""" |
5fadc63ac99f
wireproto: explicit API to create outgoing streams
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37288
diff
changeset
|
993 streamid = self._nextoutgoingstreamid |
5fadc63ac99f
wireproto: explicit API to create outgoing streams
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37288
diff
changeset
|
994 self._nextoutgoingstreamid += 2 |
5fadc63ac99f
wireproto: explicit API to create outgoing streams
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37288
diff
changeset
|
995 |
5fadc63ac99f
wireproto: explicit API to create outgoing streams
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37288
diff
changeset
|
996 s = stream(streamid) |
5fadc63ac99f
wireproto: explicit API to create outgoing streams
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37288
diff
changeset
|
997 self._outgoingstreams[streamid] = s |
5fadc63ac99f
wireproto: explicit API to create outgoing streams
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37288
diff
changeset
|
998 |
5fadc63ac99f
wireproto: explicit API to create outgoing streams
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37288
diff
changeset
|
999 return s |
5fadc63ac99f
wireproto: explicit API to create outgoing streams
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37288
diff
changeset
|
1000 |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1001 def _makeerrorresult(self, msg): |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1002 return 'error', { |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1003 'message': msg, |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1004 } |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1005 |
37061
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1006 def _makeruncommandresult(self, requestid): |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1007 entry = self._receivingcommands[requestid] |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1008 |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1009 if not entry['requestdone']: |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1010 self._state = 'errored' |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1011 raise error.ProgrammingError('should not be called without ' |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1012 'requestdone set') |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1013 |
37061
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1014 del self._receivingcommands[requestid] |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1015 |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1016 if self._receivingcommands: |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1017 self._state = 'command-receiving' |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1018 else: |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1019 self._state = 'idle' |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1020 |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1021 # Decode the payloads as CBOR. |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1022 entry['payload'].seek(0) |
39465
36f487a332ad
wireprotoframing: use our CBOR module
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37728
diff
changeset
|
1023 request = cborutil.decodeall(entry['payload'].getvalue())[0] |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1024 |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1025 if b'name' not in request: |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1026 self._state = 'errored' |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1027 return self._makeerrorresult( |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1028 _('command request missing "name" field')) |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1029 |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1030 if b'args' not in request: |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1031 request[b'args'] = {} |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1032 |
37066
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
1033 assert requestid not in self._activecommands |
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
1034 self._activecommands.add(requestid) |
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
1035 |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1036 return 'runcommand', { |
37061
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1037 'requestid': requestid, |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1038 'command': request[b'name'], |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1039 'args': request[b'args'], |
40026
b099e6032f38
wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40025
diff
changeset
|
1040 'redirect': request.get(b'redirect'), |
37061
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1041 'data': entry['data'].getvalue() if entry['data'] else None, |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1042 } |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1043 |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1044 def _makewantframeresult(self): |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1045 return 'wantframe', { |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1046 'state': self._state, |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1047 } |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1048 |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1049 def _validatecommandrequestframe(self, frame): |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1050 new = frame.flags & FLAG_COMMAND_REQUEST_NEW |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1051 continuation = frame.flags & FLAG_COMMAND_REQUEST_CONTINUATION |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1052 |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1053 if new and continuation: |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1054 self._state = 'errored' |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1055 return self._makeerrorresult( |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1056 _('received command request frame with both new and ' |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1057 'continuation flags set')) |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1058 |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1059 if not new and not continuation: |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1060 self._state = 'errored' |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1061 return self._makeerrorresult( |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1062 _('received command request frame with neither new nor ' |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1063 'continuation flags set')) |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1064 |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
1065 def _onframeidle(self, frame): |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1066 # The only frame type that should be received in this state is a |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1067 # command request. |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1068 if frame.typeid != FRAME_TYPE_COMMAND_REQUEST: |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1069 self._state = 'errored' |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1070 return self._makeerrorresult( |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1071 _('expected command request frame; got %d') % frame.typeid) |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1072 |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1073 res = self._validatecommandrequestframe(frame) |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1074 if res: |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1075 return res |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1076 |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
1077 if frame.requestid in self._receivingcommands: |
37061
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1078 self._state = 'errored' |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1079 return self._makeerrorresult( |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
1080 _('request with ID %d already received') % frame.requestid) |
37061
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1081 |
37066
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
1082 if frame.requestid in self._activecommands: |
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
1083 self._state = 'errored' |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1084 return self._makeerrorresult( |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1085 _('request with ID %d is already active') % frame.requestid) |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1086 |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1087 new = frame.flags & FLAG_COMMAND_REQUEST_NEW |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1088 moreframes = frame.flags & FLAG_COMMAND_REQUEST_MORE_FRAMES |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1089 expectingdata = frame.flags & FLAG_COMMAND_REQUEST_EXPECT_DATA |
37066
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
1090 |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1091 if not new: |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1092 self._state = 'errored' |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1093 return self._makeerrorresult( |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1094 _('received command request frame without new flag set')) |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1095 |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1096 payload = util.bytesio() |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1097 payload.write(frame.payload) |
37061
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1098 |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
1099 self._receivingcommands[frame.requestid] = { |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1100 'payload': payload, |
37061
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1101 'data': None, |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1102 'requestdone': not moreframes, |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1103 'expectingdata': bool(expectingdata), |
37061
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1104 } |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1105 |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1106 # This is the final frame for this request. Dispatch it. |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1107 if not moreframes and not expectingdata: |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
1108 return self._makeruncommandresult(frame.requestid) |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1109 |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1110 assert moreframes or expectingdata |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1111 self._state = 'command-receiving' |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1112 return self._makewantframeresult() |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1113 |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
1114 def _onframecommandreceiving(self, frame): |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1115 if frame.typeid == FRAME_TYPE_COMMAND_REQUEST: |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1116 # Process new command requests as such. |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1117 if frame.flags & FLAG_COMMAND_REQUEST_NEW: |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1118 return self._onframeidle(frame) |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1119 |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1120 res = self._validatecommandrequestframe(frame) |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1121 if res: |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1122 return res |
37061
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1123 |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1124 # All other frames should be related to a command that is currently |
37066
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
1125 # receiving but is not active. |
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
1126 if frame.requestid in self._activecommands: |
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
1127 self._state = 'errored' |
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
1128 return self._makeerrorresult( |
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
1129 _('received frame for request that is still active: %d') % |
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
1130 frame.requestid) |
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
1131 |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
1132 if frame.requestid not in self._receivingcommands: |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1133 self._state = 'errored' |
37061
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1134 return self._makeerrorresult( |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1135 _('received frame for request that is not receiving: %d') % |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
1136 frame.requestid) |
37061
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1137 |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
1138 entry = self._receivingcommands[frame.requestid] |
37061
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1139 |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1140 if frame.typeid == FRAME_TYPE_COMMAND_REQUEST: |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1141 moreframes = frame.flags & FLAG_COMMAND_REQUEST_MORE_FRAMES |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1142 expectingdata = bool(frame.flags & FLAG_COMMAND_REQUEST_EXPECT_DATA) |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1143 |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1144 if entry['requestdone']: |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1145 self._state = 'errored' |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1146 return self._makeerrorresult( |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1147 _('received command request frame when request frames ' |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1148 'were supposedly done')) |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1149 |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1150 if expectingdata != entry['expectingdata']: |
37061
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1151 self._state = 'errored' |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1152 return self._makeerrorresult( |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1153 _('mismatch between expect data flag and previous frame')) |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1154 |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1155 entry['payload'].write(frame.payload) |
37061
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1156 |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1157 if not moreframes: |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1158 entry['requestdone'] = True |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1159 |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1160 if not moreframes and not expectingdata: |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1161 return self._makeruncommandresult(frame.requestid) |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1162 |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1163 return self._makewantframeresult() |
37061
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1164 |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
1165 elif frame.typeid == FRAME_TYPE_COMMAND_DATA: |
37061
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1166 if not entry['expectingdata']: |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1167 self._state = 'errored' |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1168 return self._makeerrorresult(_( |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1169 'received command data frame for request that is not ' |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
1170 'expecting data: %d') % frame.requestid) |
37061
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1171 |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1172 if entry['data'] is None: |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1173 entry['data'] = util.bytesio() |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1174 |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
1175 return self._handlecommanddataframe(frame, entry) |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1176 else: |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1177 self._state = 'errored' |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1178 return self._makeerrorresult(_( |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1179 'received unexpected frame type: %d') % frame.typeid) |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1180 |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
1181 def _handlecommanddataframe(self, frame, entry): |
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
1182 assert frame.typeid == FRAME_TYPE_COMMAND_DATA |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1183 |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1184 # TODO support streaming data instead of buffering it. |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
1185 entry['data'].write(frame.payload) |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1186 |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
1187 if frame.flags & FLAG_COMMAND_DATA_CONTINUATION: |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1188 return self._makewantframeresult() |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
1189 elif frame.flags & FLAG_COMMAND_DATA_EOS: |
37061
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1190 entry['data'].seek(0) |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
1191 return self._makeruncommandresult(frame.requestid) |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1192 else: |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1193 self._state = 'errored' |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1194 return self._makeerrorresult(_('command data frame without ' |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1195 'flags')) |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1196 |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
1197 def _onframeerrored(self, frame): |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1198 return self._makeerrorresult(_('server already errored')) |
37543
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1199 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1200 class commandrequest(object): |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1201 """Represents a request to run a command.""" |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1202 |
40025
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40021
diff
changeset
|
1203 def __init__(self, requestid, name, args, datafh=None, redirect=None): |
37543
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1204 self.requestid = requestid |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1205 self.name = name |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1206 self.args = args |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1207 self.datafh = datafh |
40025
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40021
diff
changeset
|
1208 self.redirect = redirect |
37543
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1209 self.state = 'pending' |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1210 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1211 class clientreactor(object): |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1212 """Holds state of a client issuing frame-based protocol requests. |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1213 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1214 This is like ``serverreactor`` but for client-side state. |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1215 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1216 Each instance is bound to the lifetime of a connection. For persistent |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1217 connection transports using e.g. TCP sockets and speaking the raw |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1218 framing protocol, there will be a single instance for the lifetime of |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1219 the TCP socket. For transports where there are multiple discrete |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1220 interactions (say tunneled within in HTTP request), there will be a |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1221 separate instance for each distinct interaction. |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1222 """ |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1223 def __init__(self, hasmultiplesend=False, buffersends=True): |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1224 """Create a new instance. |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1225 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1226 ``hasmultiplesend`` indicates whether multiple sends are supported |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1227 by the transport. When True, it is possible to send commands immediately |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1228 instead of buffering until the caller signals an intent to finish a |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1229 send operation. |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1230 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1231 ``buffercommands`` indicates whether sends should be buffered until the |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1232 last request has been issued. |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1233 """ |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1234 self._hasmultiplesend = hasmultiplesend |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1235 self._buffersends = buffersends |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1236 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1237 self._canissuecommands = True |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1238 self._cansend = True |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1239 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1240 self._nextrequestid = 1 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1241 # We only support a single outgoing stream for now. |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1242 self._outgoingstream = stream(1) |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1243 self._pendingrequests = collections.deque() |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1244 self._activerequests = {} |
37544
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1245 self._incomingstreams = {} |
37543
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1246 |
40025
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40021
diff
changeset
|
1247 def callcommand(self, name, args, datafh=None, redirect=None): |
37543
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1248 """Request that a command be executed. |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1249 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1250 Receives the command name, a dict of arguments to pass to the command, |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1251 and an optional file object containing the raw data for the command. |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1252 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1253 Returns a 3-tuple of (request, action, action data). |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1254 """ |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1255 if not self._canissuecommands: |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1256 raise error.ProgrammingError('cannot issue new commands') |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1257 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1258 requestid = self._nextrequestid |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1259 self._nextrequestid += 2 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1260 |
40025
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40021
diff
changeset
|
1261 request = commandrequest(requestid, name, args, datafh=datafh, |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40021
diff
changeset
|
1262 redirect=redirect) |
37543
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1263 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1264 if self._buffersends: |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1265 self._pendingrequests.append(request) |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1266 return request, 'noop', {} |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1267 else: |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1268 if not self._cansend: |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1269 raise error.ProgrammingError('sends cannot be performed on ' |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1270 'this instance') |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1271 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1272 if not self._hasmultiplesend: |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1273 self._cansend = False |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1274 self._canissuecommands = False |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1275 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1276 return request, 'sendframes', { |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1277 'framegen': self._makecommandframes(request), |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1278 } |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1279 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1280 def flushcommands(self): |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1281 """Request that all queued commands be sent. |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1282 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1283 If any commands are buffered, this will instruct the caller to send |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1284 them over the wire. If no commands are buffered it instructs the client |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1285 to no-op. |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1286 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1287 If instances aren't configured for multiple sends, no new command |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1288 requests are allowed after this is called. |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1289 """ |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1290 if not self._pendingrequests: |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1291 return 'noop', {} |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1292 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1293 if not self._cansend: |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1294 raise error.ProgrammingError('sends cannot be performed on this ' |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1295 'instance') |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1296 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1297 # If the instance only allows sending once, mark that we have fired |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1298 # our one shot. |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1299 if not self._hasmultiplesend: |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1300 self._canissuecommands = False |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1301 self._cansend = False |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1302 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1303 def makeframes(): |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1304 while self._pendingrequests: |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1305 request = self._pendingrequests.popleft() |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1306 for frame in self._makecommandframes(request): |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1307 yield frame |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1308 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1309 return 'sendframes', { |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1310 'framegen': makeframes(), |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1311 } |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1312 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1313 def _makecommandframes(self, request): |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1314 """Emit frames to issue a command request. |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1315 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1316 As a side-effect, update request accounting to reflect its changed |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1317 state. |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1318 """ |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1319 self._activerequests[request.requestid] = request |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1320 request.state = 'sending' |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1321 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1322 res = createcommandframes(self._outgoingstream, |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1323 request.requestid, |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1324 request.name, |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1325 request.args, |
40025
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40021
diff
changeset
|
1326 datafh=request.datafh, |
86b22a4cfab1
wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents:
40021
diff
changeset
|
1327 redirect=request.redirect) |
37543
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1328 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1329 for frame in res: |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1330 yield frame |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1331 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1332 request.state = 'sent' |
37544
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1333 |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1334 def onframerecv(self, frame): |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1335 """Process a frame that has been received off the wire. |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1336 |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1337 Returns a 2-tuple of (action, meta) describing further action the |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1338 caller needs to take as a result of receiving this frame. |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1339 """ |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1340 if frame.streamid % 2: |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1341 return 'error', { |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1342 'message': ( |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1343 _('received frame with odd numbered stream ID: %d') % |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1344 frame.streamid), |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1345 } |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1346 |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1347 if frame.streamid not in self._incomingstreams: |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1348 if not frame.streamflags & STREAM_FLAG_BEGIN_STREAM: |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1349 return 'error', { |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1350 'message': _('received frame on unknown stream ' |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1351 'without beginning of stream flag set'), |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1352 } |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1353 |
37656
e6870bca1f47
wireprotoframing: record when new stream is encountered
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37655
diff
changeset
|
1354 self._incomingstreams[frame.streamid] = stream(frame.streamid) |
e6870bca1f47
wireprotoframing: record when new stream is encountered
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37655
diff
changeset
|
1355 |
37544
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1356 if frame.streamflags & STREAM_FLAG_ENCODING_APPLIED: |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1357 raise error.ProgrammingError('support for decoding stream ' |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1358 'payloads not yet implemneted') |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1359 |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1360 if frame.streamflags & STREAM_FLAG_END_STREAM: |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1361 del self._incomingstreams[frame.streamid] |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1362 |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1363 if frame.requestid not in self._activerequests: |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1364 return 'error', { |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1365 'message': (_('received frame for inactive request ID: %d') % |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1366 frame.requestid), |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1367 } |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1368 |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1369 request = self._activerequests[frame.requestid] |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1370 request.state = 'receiving' |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1371 |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1372 handlers = { |
37724
deff7cf7eefd
wireprotov2: change frame type and name for command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37723
diff
changeset
|
1373 FRAME_TYPE_COMMAND_RESPONSE: self._oncommandresponseframe, |
37726
0c184ca594bb
wireprotov2: change behavior of error frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37725
diff
changeset
|
1374 FRAME_TYPE_ERROR_RESPONSE: self._onerrorresponseframe, |
37544
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1375 } |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1376 |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1377 meth = handlers.get(frame.typeid) |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1378 if not meth: |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1379 raise error.ProgrammingError('unhandled frame type: %d' % |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1380 frame.typeid) |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1381 |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1382 return meth(request, frame) |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1383 |
37724
deff7cf7eefd
wireprotov2: change frame type and name for command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37723
diff
changeset
|
1384 def _oncommandresponseframe(self, request, frame): |
deff7cf7eefd
wireprotov2: change frame type and name for command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37723
diff
changeset
|
1385 if frame.flags & FLAG_COMMAND_RESPONSE_EOS: |
37544
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1386 request.state = 'received' |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1387 del self._activerequests[request.requestid] |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1388 |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1389 return 'responsedata', { |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1390 'request': request, |
37724
deff7cf7eefd
wireprotov2: change frame type and name for command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37723
diff
changeset
|
1391 'expectmore': frame.flags & FLAG_COMMAND_RESPONSE_CONTINUATION, |
deff7cf7eefd
wireprotov2: change frame type and name for command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37723
diff
changeset
|
1392 'eos': frame.flags & FLAG_COMMAND_RESPONSE_EOS, |
37544
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1393 'data': frame.payload, |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1394 } |
37726
0c184ca594bb
wireprotov2: change behavior of error frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37725
diff
changeset
|
1395 |
0c184ca594bb
wireprotov2: change behavior of error frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37725
diff
changeset
|
1396 def _onerrorresponseframe(self, request, frame): |
0c184ca594bb
wireprotov2: change behavior of error frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37725
diff
changeset
|
1397 request.state = 'errored' |
0c184ca594bb
wireprotov2: change behavior of error frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37725
diff
changeset
|
1398 del self._activerequests[request.requestid] |
0c184ca594bb
wireprotov2: change behavior of error frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37725
diff
changeset
|
1399 |
0c184ca594bb
wireprotov2: change behavior of error frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37725
diff
changeset
|
1400 # The payload should be a CBOR map. |
39465
36f487a332ad
wireprotoframing: use our CBOR module
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37728
diff
changeset
|
1401 m = cborutil.decodeall(frame.payload)[0] |
37726
0c184ca594bb
wireprotov2: change behavior of error frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37725
diff
changeset
|
1402 |
0c184ca594bb
wireprotov2: change behavior of error frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37725
diff
changeset
|
1403 return 'error', { |
0c184ca594bb
wireprotov2: change behavior of error frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37725
diff
changeset
|
1404 'request': request, |
0c184ca594bb
wireprotov2: change behavior of error frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37725
diff
changeset
|
1405 'type': m['type'], |
0c184ca594bb
wireprotov2: change behavior of error frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37725
diff
changeset
|
1406 'message': m['message'], |
0c184ca594bb
wireprotov2: change behavior of error frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37725
diff
changeset
|
1407 } |