Mercurial > hg-stable
annotate mercurial/wireprotoframing.py @ 40009:842ffcf1d42f
storageutil: extract most of emitrevisions() to standalone function
As part of implementing a storage backend, I found myself copying
most of revlog.emitrevisions(). This code is highly nuanced and it
bothered me greatly to be copying such low-level code.
This commit extracts the bulk of revlog.emitrevisions() into a
new standalone function. In order to make the function generally
usable, all "self" function calls that aren't exposed on the
ifilestorage interface are passed in via callable arguments.
No meaningful behavior should have changed as part of the port.
Upcoming commits will tweak behavior to make the code more
generically usable.
Differential Revision: https://phab.mercurial-scm.org/D4803
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Fri, 28 Sep 2018 16:16:22 -0700 |
parents | bce1c1af7518 |
children | ed919b90acda |
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, |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
24 util, |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
25 ) |
37087
f0b6fbea00cf
stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents:
37066
diff
changeset
|
26 from .utils import ( |
39465
36f487a332ad
wireprotoframing: use our CBOR module
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37728
diff
changeset
|
27 cborutil, |
37087
f0b6fbea00cf
stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents:
37066
diff
changeset
|
28 stringutil, |
f0b6fbea00cf
stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents:
37066
diff
changeset
|
29 ) |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
30 |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
31 FRAME_HEADER_SIZE = 8 |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
32 DEFAULT_MAX_FRAME_SIZE = 32768 |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
33 |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
34 STREAM_FLAG_BEGIN_STREAM = 0x01 |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
35 STREAM_FLAG_END_STREAM = 0x02 |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
36 STREAM_FLAG_ENCODING_APPLIED = 0x04 |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
37 |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
38 STREAM_FLAGS = { |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
39 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
|
40 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
|
41 b'encoded': STREAM_FLAG_ENCODING_APPLIED, |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
42 } |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
43 |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
44 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
|
45 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
|
46 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
|
47 FRAME_TYPE_ERROR_RESPONSE = 0x05 |
37063
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
48 FRAME_TYPE_TEXT_OUTPUT = 0x06 |
37291
b0041036214e
wireproto: define frame to represent progress updates
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37290
diff
changeset
|
49 FRAME_TYPE_PROGRESS = 0x07 |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
50 FRAME_TYPE_STREAM_SETTINGS = 0x08 |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
51 |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
52 FRAME_TYPES = { |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
53 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
|
54 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
|
55 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
|
56 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
|
57 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
|
58 b'progress': FRAME_TYPE_PROGRESS, |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
59 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
|
60 } |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
61 |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
62 FLAG_COMMAND_REQUEST_NEW = 0x01 |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
63 FLAG_COMMAND_REQUEST_CONTINUATION = 0x02 |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
64 FLAG_COMMAND_REQUEST_MORE_FRAMES = 0x04 |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
65 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
|
66 |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
67 FLAGS_COMMAND_REQUEST = { |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
68 b'new': FLAG_COMMAND_REQUEST_NEW, |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
69 b'continuation': FLAG_COMMAND_REQUEST_CONTINUATION, |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
70 b'more': FLAG_COMMAND_REQUEST_MORE_FRAMES, |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
71 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
|
72 } |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
73 |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
74 FLAG_COMMAND_DATA_CONTINUATION = 0x01 |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
75 FLAG_COMMAND_DATA_EOS = 0x02 |
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 FLAGS_COMMAND_DATA = { |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
78 b'continuation': FLAG_COMMAND_DATA_CONTINUATION, |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
79 b'eos': FLAG_COMMAND_DATA_EOS, |
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 |
37724
deff7cf7eefd
wireprotov2: change frame type and name for command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37723
diff
changeset
|
82 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
|
83 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
|
84 |
37724
deff7cf7eefd
wireprotov2: change frame type and name for command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37723
diff
changeset
|
85 FLAGS_COMMAND_RESPONSE = { |
deff7cf7eefd
wireprotov2: change frame type and name for command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37723
diff
changeset
|
86 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
|
87 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
|
88 } |
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
89 |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
90 # 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
|
91 FRAME_TYPE_FLAGS = { |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
92 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
|
93 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
|
94 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
|
95 FRAME_TYPE_ERROR_RESPONSE: {}, |
37063
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
96 FRAME_TYPE_TEXT_OUTPUT: {}, |
37291
b0041036214e
wireproto: define frame to represent progress updates
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37290
diff
changeset
|
97 FRAME_TYPE_PROGRESS: {}, |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
98 FRAME_TYPE_STREAM_SETTINGS: {}, |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
99 } |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
100 |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
101 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
|
102 |
37298
5ef2da00e935
wireproto: implement custom __repr__ for frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37292
diff
changeset
|
103 def humanflags(mapping, value): |
5ef2da00e935
wireproto: implement custom __repr__ for frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37292
diff
changeset
|
104 """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
|
105 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
|
106 flags = [] |
37473
7c2c7c749411
wireproto: show unknown id and flags in repr(frame)
Yuya Nishihara <yuya@tcha.org>
parents:
37472
diff
changeset
|
107 val = 1 |
7c2c7c749411
wireproto: show unknown id and flags in repr(frame)
Yuya Nishihara <yuya@tcha.org>
parents:
37472
diff
changeset
|
108 while value >= val: |
37298
5ef2da00e935
wireproto: implement custom __repr__ for frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37292
diff
changeset
|
109 if value & val: |
37473
7c2c7c749411
wireproto: show unknown id and flags in repr(frame)
Yuya Nishihara <yuya@tcha.org>
parents:
37472
diff
changeset
|
110 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
|
111 val <<= 1 |
37298
5ef2da00e935
wireproto: implement custom __repr__ for frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37292
diff
changeset
|
112 |
5ef2da00e935
wireproto: implement custom __repr__ for frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37292
diff
changeset
|
113 return b'|'.join(flags) |
5ef2da00e935
wireproto: implement custom __repr__ for frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37292
diff
changeset
|
114 |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
115 @attr.s(slots=True) |
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
116 class frameheader(object): |
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
117 """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
|
118 |
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
119 length = attr.ib() |
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
120 requestid = attr.ib() |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
121 streamid = attr.ib() |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
122 streamflags = attr.ib() |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
123 typeid = attr.ib() |
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
124 flags = attr.ib() |
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
125 |
37298
5ef2da00e935
wireproto: implement custom __repr__ for frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37292
diff
changeset
|
126 @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
|
127 class frame(object): |
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
128 """Represents a parsed frame.""" |
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
129 |
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
130 requestid = attr.ib() |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
131 streamid = attr.ib() |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
132 streamflags = attr.ib() |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
133 typeid = attr.ib() |
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
134 flags = attr.ib() |
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
135 payload = attr.ib() |
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
136 |
37474
d33997123ea5
py3: system-stringify repr(frame)
Yuya Nishihara <yuya@tcha.org>
parents:
37473
diff
changeset
|
137 @encoding.strmethod |
37298
5ef2da00e935
wireproto: implement custom __repr__ for frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37292
diff
changeset
|
138 def __repr__(self): |
37473
7c2c7c749411
wireproto: show unknown id and flags in repr(frame)
Yuya Nishihara <yuya@tcha.org>
parents:
37472
diff
changeset
|
139 typename = '<unknown 0x%02x>' % self.typeid |
37298
5ef2da00e935
wireproto: implement custom __repr__ for frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37292
diff
changeset
|
140 for name, value in FRAME_TYPES.iteritems(): |
5ef2da00e935
wireproto: implement custom __repr__ for frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37292
diff
changeset
|
141 if value == self.typeid: |
5ef2da00e935
wireproto: implement custom __repr__ for frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37292
diff
changeset
|
142 typename = name |
5ef2da00e935
wireproto: implement custom __repr__ for frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37292
diff
changeset
|
143 break |
5ef2da00e935
wireproto: implement custom __repr__ for frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37292
diff
changeset
|
144 |
5ef2da00e935
wireproto: implement custom __repr__ for frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37292
diff
changeset
|
145 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
|
146 'type=%s; flags=%s)' % ( |
5ef2da00e935
wireproto: implement custom __repr__ for frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37292
diff
changeset
|
147 len(self.payload), self.requestid, self.streamid, |
5ef2da00e935
wireproto: implement custom __repr__ for frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37292
diff
changeset
|
148 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
|
149 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
|
150 |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
151 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
|
152 """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
|
153 # TODO assert size of payload. |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
154 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
|
155 |
37060
2ec1fb9de638
wireproto: add request IDs to frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37059
diff
changeset
|
156 # 24 bits length |
2ec1fb9de638
wireproto: add request IDs to frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37059
diff
changeset
|
157 # 16 bits request id |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
158 # 8 bits stream id |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
159 # 8 bits stream flags |
37060
2ec1fb9de638
wireproto: add request IDs to frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37059
diff
changeset
|
160 # 4 bits type |
2ec1fb9de638
wireproto: add request IDs to frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37059
diff
changeset
|
161 # 4 bits flags |
2ec1fb9de638
wireproto: add request IDs to frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37059
diff
changeset
|
162 |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
163 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
|
164 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
|
165 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
|
166 frame[7] = (typeid << 4) | flags |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
167 frame[8:] = payload |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
168 |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
169 return frame |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
170 |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
171 def makeframefromhumanstring(s): |
37060
2ec1fb9de638
wireproto: add request IDs to frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37059
diff
changeset
|
172 """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
|
173 |
2ec1fb9de638
wireproto: add request IDs to frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37059
diff
changeset
|
174 Strings have the form: |
2ec1fb9de638
wireproto: add request IDs to frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37059
diff
changeset
|
175 |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
176 <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
|
177 |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
178 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
|
179 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
|
180 |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
181 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
|
182 |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
183 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
|
184 named constant. |
37060
2ec1fb9de638
wireproto: add request IDs to frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37059
diff
changeset
|
185 |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
186 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
|
187 |
cc5a040fe150
wireproto: syntax for encoding CBOR into frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37289
diff
changeset
|
188 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
|
189 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
|
190 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
|
191 byte string literal. |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
192 """ |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
193 fields = s.split(b' ', 5) |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
194 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
|
195 |
2ec1fb9de638
wireproto: add request IDs to frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37059
diff
changeset
|
196 requestid = int(requestid) |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
197 streamid = int(streamid) |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
198 |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
199 finalstreamflags = 0 |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
200 for flag in streamflags.split(b'|'): |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
201 if flag in STREAM_FLAGS: |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
202 finalstreamflags |= STREAM_FLAGS[flag] |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
203 else: |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
204 finalstreamflags |= int(flag) |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
205 |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
206 if frametype in FRAME_TYPES: |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
207 frametype = FRAME_TYPES[frametype] |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
208 else: |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
209 frametype = int(frametype) |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
210 |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
211 finalflags = 0 |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
212 validflags = FRAME_TYPE_FLAGS[frametype] |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
213 for flag in frameflags.split(b'|'): |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
214 if flag in validflags: |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
215 finalflags |= validflags[flag] |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
216 else: |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
217 finalflags |= int(flag) |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
218 |
37290
cc5a040fe150
wireproto: syntax for encoding CBOR into frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37289
diff
changeset
|
219 if payload.startswith(b'cbor:'): |
39465
36f487a332ad
wireprotoframing: use our CBOR module
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37728
diff
changeset
|
220 payload = b''.join(cborutil.streamencode( |
36f487a332ad
wireprotoframing: use our CBOR module
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37728
diff
changeset
|
221 stringutil.evalpythonliteral(payload[5:]))) |
37290
cc5a040fe150
wireproto: syntax for encoding CBOR into frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37289
diff
changeset
|
222 |
cc5a040fe150
wireproto: syntax for encoding CBOR into frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37289
diff
changeset
|
223 else: |
cc5a040fe150
wireproto: syntax for encoding CBOR into frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37289
diff
changeset
|
224 payload = stringutil.unescapestr(payload) |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
225 |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
226 return makeframe(requestid=requestid, streamid=streamid, |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
227 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
|
228 flags=finalflags, payload=payload) |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
229 |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
230 def parseheader(data): |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
231 """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
|
232 |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
233 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
|
234 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
|
235 """ |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
236 # 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
|
237 # 16 bits request ID |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
238 # 8 bits stream ID |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
239 # 8 bits stream flags |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
240 # 4 bits frame type |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
241 # 4 bits frame flags |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
242 # ... payload |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
243 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
|
244 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
|
245 typeflags = data[7] |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
246 |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
247 frametype = (typeflags & 0xf0) >> 4 |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
248 frameflags = typeflags & 0x0f |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
249 |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
250 return frameheader(framelength, requestid, streamid, streamflags, |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
251 frametype, frameflags) |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
252 |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
253 def readframe(fh): |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
254 """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
|
255 |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
256 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
|
257 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
|
258 seen. |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
259 """ |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
260 header = bytearray(FRAME_HEADER_SIZE) |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
261 |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
262 readcount = fh.readinto(header) |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
263 |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
264 if readcount == 0: |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
265 return None |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
266 |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
267 if readcount != FRAME_HEADER_SIZE: |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
268 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
|
269 (readcount, header)) |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
270 |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
271 h = parseheader(header) |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
272 |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
273 payload = fh.read(h.length) |
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
274 if len(payload) != h.length: |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
275 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
|
276 (h.length, len(payload))) |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
277 |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
278 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
|
279 payload) |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
280 |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
281 def createcommandframes(stream, requestid, cmd, args, datafh=None, |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
282 maxframesize=DEFAULT_MAX_FRAME_SIZE): |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
283 """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
|
284 |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
285 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
|
286 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
|
287 """ |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
288 data = {b'name': cmd} |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
289 if args: |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
290 data[b'args'] = args |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
291 |
39465
36f487a332ad
wireprotoframing: use our CBOR module
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37728
diff
changeset
|
292 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
|
293 |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
294 offset = 0 |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
295 |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
296 while True: |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
297 flags = 0 |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
298 |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
299 # Must set new or continuation flag. |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
300 if not offset: |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
301 flags |= FLAG_COMMAND_REQUEST_NEW |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
302 else: |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
303 flags |= FLAG_COMMAND_REQUEST_CONTINUATION |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
304 |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
305 # Data frames is set on all frames. |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
306 if datafh: |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
307 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
|
308 |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
309 payload = data[offset:offset + maxframesize] |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
310 offset += len(payload) |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
311 |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
312 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
|
313 flags |= FLAG_COMMAND_REQUEST_MORE_FRAMES |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
314 |
37287
3ed344546d9e
wireproto: start to associate frame generation with a stream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37087
diff
changeset
|
315 yield stream.makeframe(requestid=requestid, |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
316 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
|
317 flags=flags, |
3ed344546d9e
wireproto: start to associate frame generation with a stream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37087
diff
changeset
|
318 payload=payload) |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
319 |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
320 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
|
321 break |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
322 |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
323 if datafh: |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
324 while True: |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
325 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
|
326 |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
327 done = False |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
328 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
|
329 flags = FLAG_COMMAND_DATA_CONTINUATION |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
330 else: |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
331 flags = FLAG_COMMAND_DATA_EOS |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
332 assert datafh.read(1) == b'' |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
333 done = True |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
334 |
37287
3ed344546d9e
wireproto: start to associate frame generation with a stream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37087
diff
changeset
|
335 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
|
336 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
|
337 flags=flags, |
3ed344546d9e
wireproto: start to associate frame generation with a stream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37087
diff
changeset
|
338 payload=data) |
37054
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
339 |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
340 if done: |
40206e227412
wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
341 break |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
342 |
37724
deff7cf7eefd
wireprotov2: change frame type and name for command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37723
diff
changeset
|
343 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
|
344 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
|
345 """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
|
346 |
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
347 Returns a generator of bytearrays. |
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
348 """ |
37725
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37724
diff
changeset
|
349 # Automatically send the overall CBOR response map. |
39465
36f487a332ad
wireprotoframing: use our CBOR module
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37728
diff
changeset
|
350 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
|
351 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
|
352 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
|
353 |
37725
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37724
diff
changeset
|
354 # 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
|
355 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
|
356 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
|
357 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
|
358 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
|
359 flags=flags, |
37725
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37724
diff
changeset
|
360 payload=overall + data) |
37058
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
361 return |
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
362 |
37725
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37724
diff
changeset
|
363 # 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
|
364 # offsets. |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37724
diff
changeset
|
365 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
|
366 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
|
367 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
|
368 payload=overall) |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37724
diff
changeset
|
369 |
37058
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
370 offset = 0 |
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
371 while True: |
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
372 chunk = data[offset:offset + maxframesize] |
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
373 offset += len(chunk) |
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
374 done = offset == len(data) |
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
375 |
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
376 if done: |
37724
deff7cf7eefd
wireprotov2: change frame type and name for command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37723
diff
changeset
|
377 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
|
378 else: |
37724
deff7cf7eefd
wireprotov2: change frame type and name for command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37723
diff
changeset
|
379 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
|
380 |
37287
3ed344546d9e
wireproto: start to associate frame generation with a stream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37087
diff
changeset
|
381 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
|
382 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
|
383 flags=flags, |
3ed344546d9e
wireproto: start to associate frame generation with a stream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37087
diff
changeset
|
384 payload=chunk) |
37058
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
385 |
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
386 if done: |
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
387 break |
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
388 |
37728
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
389 def createbytesresponseframesfromgen(stream, requestid, gen, |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
390 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
|
391 """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
|
392 |
39575
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
393 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
|
394 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
|
395 flag. |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
396 """ |
37728
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
397 cb = util.chunkbuffer(gen) |
39575
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
398 flags = FLAG_COMMAND_RESPONSE_CONTINUATION |
37728
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
399 |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
400 while True: |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
401 chunk = cb.read(maxframesize) |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
402 if not chunk: |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
403 break |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
404 |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
405 yield stream.makeframe(requestid=requestid, |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
406 typeid=FRAME_TYPE_COMMAND_RESPONSE, |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
407 flags=flags, |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
408 payload=chunk) |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
409 |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
410 flags |= FLAG_COMMAND_RESPONSE_CONTINUATION |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
411 |
39575
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
412 def createcommandresponseokframe(stream, requestid): |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
413 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
|
414 |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
415 return stream.makeframe(requestid=requestid, |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
416 typeid=FRAME_TYPE_COMMAND_RESPONSE, |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
417 flags=FLAG_COMMAND_RESPONSE_CONTINUATION, |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
418 payload=overall) |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
419 |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
420 def createcommandresponseeosframe(stream, requestid): |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
421 """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
|
422 return stream.makeframe(requestid=requestid, |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
423 typeid=FRAME_TYPE_COMMAND_RESPONSE, |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
424 flags=FLAG_COMMAND_RESPONSE_EOS, |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
425 payload=b'') |
37728
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
426 |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
427 def createcommanderrorresponse(stream, requestid, message, args=None): |
39503
43d92d68ac88
wireprotov2peer: properly format errors
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39465
diff
changeset
|
428 # 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
|
429 # formatting works consistently? |
37728
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
430 m = { |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
431 b'status': b'error', |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
432 b'error': { |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
433 b'message': message, |
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 } |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
436 |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
437 if args: |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
438 m[b'error'][b'args'] = args |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
439 |
39465
36f487a332ad
wireprotoframing: use our CBOR module
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37728
diff
changeset
|
440 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
|
441 |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
442 yield stream.makeframe(requestid=requestid, |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
443 typeid=FRAME_TYPE_COMMAND_RESPONSE, |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
444 flags=FLAG_COMMAND_RESPONSE_EOS, |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
445 payload=overall) |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
446 |
37726
0c184ca594bb
wireprotov2: change behavior of error frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37725
diff
changeset
|
447 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
|
448 # 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
|
449 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
|
450 |
39465
36f487a332ad
wireprotoframing: use our CBOR module
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37728
diff
changeset
|
451 payload = b''.join(cborutil.streamencode({ |
37726
0c184ca594bb
wireprotov2: change behavior of error frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37725
diff
changeset
|
452 b'type': errtype, |
0c184ca594bb
wireprotov2: change behavior of error frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37725
diff
changeset
|
453 b'message': [{b'msg': msg}], |
39465
36f487a332ad
wireprotoframing: use our CBOR module
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37728
diff
changeset
|
454 })) |
37058
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
455 |
37287
3ed344546d9e
wireproto: start to associate frame generation with a stream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37087
diff
changeset
|
456 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
|
457 typeid=FRAME_TYPE_ERROR_RESPONSE, |
37726
0c184ca594bb
wireprotov2: change behavior of error frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37725
diff
changeset
|
458 flags=0, |
0c184ca594bb
wireprotov2: change behavior of error frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37725
diff
changeset
|
459 payload=payload) |
37058
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
460 |
37319
36d17f37db91
wireproto: convert human output frames to CBOR
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37299
diff
changeset
|
461 def createtextoutputframe(stream, requestid, atoms, |
36d17f37db91
wireproto: convert human output frames to CBOR
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37299
diff
changeset
|
462 maxframesize=DEFAULT_MAX_FRAME_SIZE): |
37063
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
463 """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
|
464 |
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
465 ``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
|
466 |
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
467 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
|
468 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
|
469 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
|
470 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
|
471 """ |
37319
36d17f37db91
wireproto: convert human output frames to CBOR
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37299
diff
changeset
|
472 atomdicts = [] |
37063
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
473 |
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
474 for (formatting, args, labels) in atoms: |
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
475 # 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
|
476 |
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
477 if not isinstance(formatting, bytes): |
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
478 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
|
479 for arg in args: |
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
480 if not isinstance(arg, bytes): |
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
481 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
|
482 for label in labels: |
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
483 if not isinstance(label, bytes): |
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
484 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
|
485 |
37319
36d17f37db91
wireproto: convert human output frames to CBOR
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37299
diff
changeset
|
486 # Formatting string must be ASCII. |
36d17f37db91
wireproto: convert human output frames to CBOR
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37299
diff
changeset
|
487 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
|
488 |
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
489 # Arguments must be UTF-8. |
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
490 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
|
491 |
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
492 # Labels must be ASCII. |
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
493 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
|
494 for l in labels] |
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
495 |
37319
36d17f37db91
wireproto: convert human output frames to CBOR
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37299
diff
changeset
|
496 atom = {b'msg': formatting} |
36d17f37db91
wireproto: convert human output frames to CBOR
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37299
diff
changeset
|
497 if args: |
36d17f37db91
wireproto: convert human output frames to CBOR
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37299
diff
changeset
|
498 atom[b'args'] = args |
36d17f37db91
wireproto: convert human output frames to CBOR
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37299
diff
changeset
|
499 if labels: |
36d17f37db91
wireproto: convert human output frames to CBOR
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37299
diff
changeset
|
500 atom[b'labels'] = labels |
37063
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
501 |
37319
36d17f37db91
wireproto: convert human output frames to CBOR
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37299
diff
changeset
|
502 atomdicts.append(atom) |
37063
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
503 |
39465
36f487a332ad
wireprotoframing: use our CBOR module
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37728
diff
changeset
|
504 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
|
505 |
37319
36d17f37db91
wireproto: convert human output frames to CBOR
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37299
diff
changeset
|
506 if len(payload) > maxframesize: |
37063
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
507 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
|
508 |
37287
3ed344546d9e
wireproto: start to associate frame generation with a stream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37087
diff
changeset
|
509 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
|
510 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
|
511 flags=0, |
37319
36d17f37db91
wireproto: convert human output frames to CBOR
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37299
diff
changeset
|
512 payload=payload) |
37287
3ed344546d9e
wireproto: start to associate frame generation with a stream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37087
diff
changeset
|
513 |
39576
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
514 class bufferingcommandresponseemitter(object): |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
515 """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
|
516 |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
517 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
|
518 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
|
519 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
|
520 |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
521 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
|
522 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
|
523 level. |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
524 """ |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
525 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
|
526 self._stream = stream |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
527 self._requestid = requestid |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
528 self._maxsize = maxframesize |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
529 self._chunks = [] |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
530 self._chunkssize = 0 |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
531 |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
532 def send(self, data): |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
533 """Send new data for emission. |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
534 |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
535 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
|
536 |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
537 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
|
538 data to frames. |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
539 """ |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
540 |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
541 if data is None: |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
542 for frame in self._flush(): |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
543 yield frame |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
544 return |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
545 |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
546 # 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
|
547 # 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
|
548 # 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
|
549 # a simple implementation: |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
550 # |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
551 # * 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
|
552 # for the new chunk. |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
553 # * 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
|
554 # being exceeded, we do that. |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
555 # * 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
|
556 # 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
|
557 |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
558 if len(data) > self._maxsize: |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
559 for frame in self._flush(): |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
560 yield frame |
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 # 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
|
563 offset = 0 |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
564 while True: |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
565 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
|
566 offset += len(chunk) |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
567 |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
568 yield self._stream.makeframe( |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
569 self._requestid, |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
570 typeid=FRAME_TYPE_COMMAND_RESPONSE, |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
571 flags=FLAG_COMMAND_RESPONSE_CONTINUATION, |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
572 payload=chunk) |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
573 |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
574 if offset == len(data): |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
575 return |
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 # 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
|
578 # return. |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
579 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
|
580 self._chunks.append(data) |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
581 self._chunkssize += len(data) |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
582 return |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
583 |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
584 # 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
|
585 # 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
|
586 # keep things simple for now. |
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 |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
590 self._chunks.append(data) |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
591 self._chunkssize = len(data) |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
592 |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
593 def _flush(self): |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
594 payload = b''.join(self._chunks) |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
595 assert len(payload) <= self._maxsize |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
596 |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
597 self._chunks[:] = [] |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
598 self._chunkssize = 0 |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
599 |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
600 yield self._stream.makeframe( |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
601 self._requestid, |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
602 typeid=FRAME_TYPE_COMMAND_RESPONSE, |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
603 flags=FLAG_COMMAND_RESPONSE_CONTINUATION, |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
604 payload=payload) |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
605 |
37287
3ed344546d9e
wireproto: start to associate frame generation with a stream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37087
diff
changeset
|
606 class stream(object): |
3ed344546d9e
wireproto: start to associate frame generation with a stream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37087
diff
changeset
|
607 """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
|
608 |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
609 def __init__(self, streamid, active=False): |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
610 self.streamid = streamid |
37655
b9502b5f2066
wireprotoframing: use value passed into function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37544
diff
changeset
|
611 self._active = active |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
612 |
37287
3ed344546d9e
wireproto: start to associate frame generation with a stream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37087
diff
changeset
|
613 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
|
614 """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
|
615 |
3ed344546d9e
wireproto: start to associate frame generation with a stream
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37087
diff
changeset
|
616 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
|
617 """ |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
618 streamflags = 0 |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
619 if not self._active: |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
620 streamflags |= STREAM_FLAG_BEGIN_STREAM |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
621 self._active = True |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
622 |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
623 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
|
624 payload) |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
625 |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
626 def ensureserverstream(stream): |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
627 if stream.streamid % 2: |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
628 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
|
629 'numbered streams; %d is not even' % |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
630 stream.streamid) |
37063
0a6c5cc09a88
wireproto: define human output side channel frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37061
diff
changeset
|
631 |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
632 class serverreactor(object): |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
633 """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
|
634 |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
635 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
|
636 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
|
637 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
|
638 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
|
639 |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
640 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
|
641 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
|
642 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
|
643 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
|
644 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
|
645 *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
|
646 |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
647 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
|
648 this class. |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
649 |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
650 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
|
651 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
|
652 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
|
653 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
|
654 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
|
655 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
|
656 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
|
657 |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
658 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
|
659 |
37058
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
660 sendframes |
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
661 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
|
662 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
|
663 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
|
664 |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
665 error |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
666 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
|
667 |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
668 runcommand |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
669 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
|
670 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
|
671 |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
672 wantframe |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
673 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
|
674 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
|
675 |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
676 noop |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
677 Indicates no additional action is required. |
37061
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
678 |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
679 Known Issues |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
680 ------------ |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
681 |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
682 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
|
683 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
|
684 server's memory. |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
685 |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
686 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
|
687 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
|
688 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
|
689 to facilitate graceful shutdown? |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
690 |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
691 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
|
692 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
|
693 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
|
694 between who responds to what. |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
695 """ |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
696 |
37059
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
697 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
|
698 """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
|
699 |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
700 ``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
|
701 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
|
702 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
|
703 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
|
704 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
|
705 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
|
706 """ |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
707 self._deferoutput = deferoutput |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
708 self._state = 'idle' |
37289
5fadc63ac99f
wireproto: explicit API to create outgoing streams
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37288
diff
changeset
|
709 self._nextoutgoingstreamid = 2 |
37059
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
710 self._bufferedframegens = [] |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
711 # 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
|
712 self._incomingstreams = {} |
37289
5fadc63ac99f
wireproto: explicit API to create outgoing streams
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37288
diff
changeset
|
713 self._outgoingstreams = {} |
37061
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
714 # 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
|
715 self._receivingcommands = {} |
37066
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
716 # 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
|
717 # 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
|
718 # set. |
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
719 self._activecommands = set() |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
720 |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
721 def onframerecv(self, frame): |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
722 """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
|
723 |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
724 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
|
725 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
|
726 """ |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
727 if not frame.streamid % 2: |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
728 self._state = 'errored' |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
729 return self._makeerrorresult( |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
730 _('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
|
731 frame.streamid) |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
732 |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
733 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
|
734 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
|
735 self._state = 'errored' |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
736 return self._makeerrorresult( |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
737 _('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
|
738 'beginning of stream flag set')) |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
739 |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
740 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
|
741 |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
742 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
|
743 # TODO handle decoding frames |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
744 self._state = 'errored' |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
745 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
|
746 'not yet implemented') |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
747 |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
748 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
|
749 del self._incomingstreams[frame.streamid] |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
750 |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
751 handlers = { |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
752 'idle': self._onframeidle, |
37061
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
753 'command-receiving': self._onframecommandreceiving, |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
754 'errored': self._onframeerrored, |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
755 } |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
756 |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
757 meth = handlers.get(self._state) |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
758 if not meth: |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
759 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
|
760 |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
761 return meth(frame) |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
762 |
37724
deff7cf7eefd
wireprotov2: change frame type and name for command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37723
diff
changeset
|
763 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
|
764 """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
|
765 |
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
766 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
|
767 """ |
37288
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
768 ensureserverstream(stream) |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
769 |
37066
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
770 def sendframes(): |
37724
deff7cf7eefd
wireprotov2: change frame type and name for command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37723
diff
changeset
|
771 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
|
772 data): |
37066
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
773 yield frame |
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
774 |
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
775 self._activecommands.remove(requestid) |
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
776 |
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
777 result = sendframes() |
37059
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
778 |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
779 if self._deferoutput: |
37066
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
780 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
|
781 return 'noop', {} |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
782 else: |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
783 return 'sendframes', { |
37066
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
784 'framegen': result, |
37059
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
785 } |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
786 |
39575
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
787 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
|
788 """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
|
789 |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
790 ``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
|
791 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
|
792 client. |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
793 """ |
37728
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
794 ensureserverstream(stream) |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
795 |
39575
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
796 # 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
|
797 # 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
|
798 # 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
|
799 # in a bad state. |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
800 # |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
801 # 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
|
802 # 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
|
803 # 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
|
804 # 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
|
805 # |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
806 # 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
|
807 # 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
|
808 |
37728
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
809 def sendframes(): |
39575
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
810 emitted = False |
39576
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
811 emitter = bufferingcommandresponseemitter(stream, requestid) |
39575
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
812 while True: |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
813 try: |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
814 o = next(objs) |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
815 except StopIteration: |
39576
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
816 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
|
817 yield frame |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
818 |
39575
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
819 if emitted: |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
820 yield createcommandresponseeosframe(stream, requestid) |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
821 break |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
822 |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
823 except error.WireprotoCommandError as e: |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
824 for frame in createcommanderrorresponse( |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
825 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
|
826 yield frame |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
827 break |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
828 |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
829 except Exception as e: |
39843
bce1c1af7518
py3: cast exception to bytes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39576
diff
changeset
|
830 for frame in createerrorframe( |
bce1c1af7518
py3: cast exception to bytes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39576
diff
changeset
|
831 stream, requestid, '%s' % stringutil.forcebytestr(e), |
bce1c1af7518
py3: cast exception to bytes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39576
diff
changeset
|
832 errtype='server'): |
bce1c1af7518
py3: cast exception to bytes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39576
diff
changeset
|
833 |
39575
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
834 yield frame |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
835 |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
836 break |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
837 |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
838 try: |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
839 if not emitted: |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
840 yield createcommandresponseokframe(stream, requestid) |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
841 emitted = True |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
842 |
39576
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
843 for chunk in cborutil.streamencode(o): |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
844 for frame in emitter.send(chunk): |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
845 yield frame |
84bf6ded9317
wireprotoframing: buffer emitted data to reduce frame count
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39575
diff
changeset
|
846 |
39575
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
847 except Exception as e: |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
848 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
|
849 '%s' % e, |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
850 errtype='server'): |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
851 yield frame |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
852 |
07b58266bce3
wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39503
diff
changeset
|
853 break |
37728
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
854 |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
855 self._activecommands.remove(requestid) |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
856 |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
857 return self._handlesendframes(sendframes()) |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
858 |
37059
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
859 def oninputeof(self): |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
860 """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
|
861 |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
862 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
|
863 completed. |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
864 """ |
37061
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
865 # 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
|
866 |
37059
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
867 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
|
868 return 'noop', {} |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
869 |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
870 # 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
|
871 def makegen(): |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
872 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
|
873 for frame in gen: |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
874 yield frame |
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
875 |
37058
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
876 return 'sendframes', { |
37059
861e9d37e56e
wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37058
diff
changeset
|
877 'framegen': makegen(), |
37058
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
878 } |
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
879 |
37728
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
880 def _handlesendframes(self, framegen): |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
881 if self._deferoutput: |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
882 self._bufferedframegens.append(framegen) |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
883 return 'noop', {} |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
884 else: |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
885 return 'sendframes', { |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
886 'framegen': framegen, |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
887 } |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
888 |
37726
0c184ca594bb
wireprotov2: change behavior of error frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37725
diff
changeset
|
889 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
|
890 ensureserverstream(stream) |
9bfcbe4f4745
wireproto: add streams to frame-based protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37287
diff
changeset
|
891 |
37728
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
892 def sendframes(): |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
893 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
|
894 errtype='server'): |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
895 yield frame |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
896 |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
897 self._activecommands.remove(requestid) |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
898 |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
899 return self._handlesendframes(sendframes()) |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
900 |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
901 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
|
902 """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
|
903 ensureserverstream(stream) |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
904 |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
905 def sendframes(): |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
906 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
|
907 args): |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
908 yield frame |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
909 |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
910 self._activecommands.remove(requestid) |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
911 |
564a3eec6e63
wireprotov2: add support for more response types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37726
diff
changeset
|
912 return self._handlesendframes(sendframes()) |
37058
61393f888dfe
wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37055
diff
changeset
|
913 |
37289
5fadc63ac99f
wireproto: explicit API to create outgoing streams
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37288
diff
changeset
|
914 def makeoutputstream(self): |
5fadc63ac99f
wireproto: explicit API to create outgoing streams
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37288
diff
changeset
|
915 """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
|
916 streamid = self._nextoutgoingstreamid |
5fadc63ac99f
wireproto: explicit API to create outgoing streams
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37288
diff
changeset
|
917 self._nextoutgoingstreamid += 2 |
5fadc63ac99f
wireproto: explicit API to create outgoing streams
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37288
diff
changeset
|
918 |
5fadc63ac99f
wireproto: explicit API to create outgoing streams
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37288
diff
changeset
|
919 s = stream(streamid) |
5fadc63ac99f
wireproto: explicit API to create outgoing streams
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37288
diff
changeset
|
920 self._outgoingstreams[streamid] = s |
5fadc63ac99f
wireproto: explicit API to create outgoing streams
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37288
diff
changeset
|
921 |
5fadc63ac99f
wireproto: explicit API to create outgoing streams
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37288
diff
changeset
|
922 return s |
5fadc63ac99f
wireproto: explicit API to create outgoing streams
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37288
diff
changeset
|
923 |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
924 def _makeerrorresult(self, msg): |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
925 return 'error', { |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
926 'message': msg, |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
927 } |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
928 |
37061
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
929 def _makeruncommandresult(self, requestid): |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
930 entry = self._receivingcommands[requestid] |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
931 |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
932 if not entry['requestdone']: |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
933 self._state = 'errored' |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
934 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
|
935 'requestdone set') |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
936 |
37061
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
937 del self._receivingcommands[requestid] |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
938 |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
939 if self._receivingcommands: |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
940 self._state = 'command-receiving' |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
941 else: |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
942 self._state = 'idle' |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
943 |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
944 # Decode the payloads as CBOR. |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
945 entry['payload'].seek(0) |
39465
36f487a332ad
wireprotoframing: use our CBOR module
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37728
diff
changeset
|
946 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
|
947 |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
948 if b'name' not in request: |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
949 self._state = 'errored' |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
950 return self._makeerrorresult( |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
951 _('command request missing "name" field')) |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
952 |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
953 if b'args' not in request: |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
954 request[b'args'] = {} |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
955 |
37066
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
956 assert requestid not in self._activecommands |
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
957 self._activecommands.add(requestid) |
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
958 |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
959 return 'runcommand', { |
37061
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
960 'requestid': requestid, |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
961 'command': request[b'name'], |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
962 'args': request[b'args'], |
37061
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
963 '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
|
964 } |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
965 |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
966 def _makewantframeresult(self): |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
967 return 'wantframe', { |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
968 'state': self._state, |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
969 } |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
970 |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
971 def _validatecommandrequestframe(self, frame): |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
972 new = frame.flags & FLAG_COMMAND_REQUEST_NEW |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
973 continuation = frame.flags & FLAG_COMMAND_REQUEST_CONTINUATION |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
974 |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
975 if new and continuation: |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
976 self._state = 'errored' |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
977 return self._makeerrorresult( |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
978 _('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
|
979 'continuation flags set')) |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
980 |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
981 if not new and not continuation: |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
982 self._state = 'errored' |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
983 return self._makeerrorresult( |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
984 _('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
|
985 'continuation flags set')) |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
986 |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
987 def _onframeidle(self, frame): |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
988 # 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
|
989 # command request. |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
990 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
|
991 self._state = 'errored' |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
992 return self._makeerrorresult( |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
993 _('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
|
994 |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
995 res = self._validatecommandrequestframe(frame) |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
996 if res: |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
997 return res |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
998 |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
999 if frame.requestid in self._receivingcommands: |
37061
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1000 self._state = 'errored' |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1001 return self._makeerrorresult( |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
1002 _('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
|
1003 |
37066
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
1004 if frame.requestid in self._activecommands: |
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
1005 self._state = 'errored' |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1006 return self._makeerrorresult( |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1007 _('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
|
1008 |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1009 new = frame.flags & FLAG_COMMAND_REQUEST_NEW |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1010 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
|
1011 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
|
1012 |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1013 if not new: |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1014 self._state = 'errored' |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1015 return self._makeerrorresult( |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1016 _('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
|
1017 |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1018 payload = util.bytesio() |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1019 payload.write(frame.payload) |
37061
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1020 |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
1021 self._receivingcommands[frame.requestid] = { |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1022 'payload': payload, |
37061
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1023 'data': None, |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1024 'requestdone': not moreframes, |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1025 'expectingdata': bool(expectingdata), |
37061
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1026 } |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1027 |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1028 # 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
|
1029 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
|
1030 return self._makeruncommandresult(frame.requestid) |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1031 |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1032 assert moreframes or expectingdata |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1033 self._state = 'command-receiving' |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1034 return self._makewantframeresult() |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1035 |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
1036 def _onframecommandreceiving(self, frame): |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1037 if frame.typeid == FRAME_TYPE_COMMAND_REQUEST: |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1038 # Process new command requests as such. |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1039 if frame.flags & FLAG_COMMAND_REQUEST_NEW: |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1040 return self._onframeidle(frame) |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1041 |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1042 res = self._validatecommandrequestframe(frame) |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1043 if res: |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1044 return res |
37061
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1045 |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1046 # 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
|
1047 # receiving but is not active. |
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
1048 if frame.requestid in self._activecommands: |
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
1049 self._state = 'errored' |
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
1050 return self._makeerrorresult( |
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
1051 _('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
|
1052 frame.requestid) |
39304dd63589
wireproto: explicitly track which requests are active
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37065
diff
changeset
|
1053 |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
1054 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
|
1055 self._state = 'errored' |
37061
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1056 return self._makeerrorresult( |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1057 _('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
|
1058 frame.requestid) |
37061
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1059 |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
1060 entry = self._receivingcommands[frame.requestid] |
37061
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1061 |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1062 if frame.typeid == FRAME_TYPE_COMMAND_REQUEST: |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1063 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
|
1064 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
|
1065 |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1066 if entry['requestdone']: |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1067 self._state = 'errored' |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1068 return self._makeerrorresult( |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1069 _('received command request frame when request frames ' |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1070 'were supposedly done')) |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1071 |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1072 if expectingdata != entry['expectingdata']: |
37061
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1073 self._state = 'errored' |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1074 return self._makeerrorresult( |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1075 _('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
|
1076 |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1077 entry['payload'].write(frame.payload) |
37061
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1078 |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1079 if not moreframes: |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1080 entry['requestdone'] = True |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1081 |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1082 if not moreframes and not expectingdata: |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1083 return self._makeruncommandresult(frame.requestid) |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1084 |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1085 return self._makewantframeresult() |
37061
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1086 |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
1087 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
|
1088 if not entry['expectingdata']: |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1089 self._state = 'errored' |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1090 return self._makeerrorresult(_( |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1091 '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
|
1092 'expecting data: %d') % frame.requestid) |
37061
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1093 |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1094 if entry['data'] is None: |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1095 entry['data'] = util.bytesio() |
c5e9c3b47366
wireproto: support for receiving multiple requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37060
diff
changeset
|
1096 |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
1097 return self._handlecommanddataframe(frame, entry) |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1098 else: |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1099 self._state = 'errored' |
37292
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1100 return self._makeerrorresult(_( |
3d0e2cd86e05
wireproto: use CBOR for command requests
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37291
diff
changeset
|
1101 '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
|
1102 |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
1103 def _handlecommanddataframe(self, frame, entry): |
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
1104 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
|
1105 |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1106 # 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
|
1107 entry['data'].write(frame.payload) |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1108 |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
1109 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
|
1110 return self._makewantframeresult() |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
1111 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
|
1112 entry['data'].seek(0) |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
1113 return self._makeruncommandresult(frame.requestid) |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1114 else: |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1115 self._state = 'errored' |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1116 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
|
1117 'flags')) |
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1118 |
37064
884a0c1604ad
wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37063
diff
changeset
|
1119 def _onframeerrored(self, frame): |
37055
8c3c47362934
wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37054
diff
changeset
|
1120 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
|
1121 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1122 class commandrequest(object): |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1123 """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
|
1124 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1125 def __init__(self, requestid, name, args, datafh=None): |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1126 self.requestid = requestid |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1127 self.name = name |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1128 self.args = args |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1129 self.datafh = datafh |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1130 self.state = 'pending' |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1131 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1132 class clientreactor(object): |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1133 """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
|
1134 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1135 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
|
1136 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1137 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
|
1138 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
|
1139 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
|
1140 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
|
1141 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
|
1142 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
|
1143 """ |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1144 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
|
1145 """Create a new instance. |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1146 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1147 ``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
|
1148 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
|
1149 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
|
1150 send operation. |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1151 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1152 ``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
|
1153 last request has been issued. |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1154 """ |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1155 self._hasmultiplesend = hasmultiplesend |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1156 self._buffersends = buffersends |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1157 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1158 self._canissuecommands = True |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1159 self._cansend = True |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1160 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1161 self._nextrequestid = 1 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1162 # 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
|
1163 self._outgoingstream = stream(1) |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1164 self._pendingrequests = collections.deque() |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1165 self._activerequests = {} |
37544
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1166 self._incomingstreams = {} |
37543
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1167 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1168 def callcommand(self, name, args, datafh=None): |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1169 """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
|
1170 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1171 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
|
1172 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
|
1173 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1174 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
|
1175 """ |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1176 if not self._canissuecommands: |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1177 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
|
1178 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1179 requestid = self._nextrequestid |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1180 self._nextrequestid += 2 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1181 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1182 request = commandrequest(requestid, name, args, datafh=datafh) |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1183 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1184 if self._buffersends: |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1185 self._pendingrequests.append(request) |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1186 return request, 'noop', {} |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1187 else: |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1188 if not self._cansend: |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1189 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
|
1190 'this instance') |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1191 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1192 if not self._hasmultiplesend: |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1193 self._cansend = False |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1194 self._canissuecommands = False |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1195 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1196 return request, 'sendframes', { |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1197 'framegen': self._makecommandframes(request), |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1198 } |
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 def flushcommands(self): |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1201 """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
|
1202 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1203 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
|
1204 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
|
1205 to no-op. |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1206 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1207 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
|
1208 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
|
1209 """ |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1210 if not self._pendingrequests: |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1211 return 'noop', {} |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1212 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1213 if not self._cansend: |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1214 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
|
1215 'instance') |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1216 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1217 # 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
|
1218 # our one shot. |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1219 if not self._hasmultiplesend: |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1220 self._canissuecommands = False |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1221 self._cansend = False |
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 makeframes(): |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1224 while self._pendingrequests: |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1225 request = self._pendingrequests.popleft() |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1226 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
|
1227 yield frame |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1228 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1229 return 'sendframes', { |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1230 'framegen': makeframes(), |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1231 } |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1232 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1233 def _makecommandframes(self, request): |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1234 """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
|
1235 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1236 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
|
1237 state. |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1238 """ |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1239 self._activerequests[request.requestid] = request |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1240 request.state = 'sending' |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1241 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1242 res = createcommandframes(self._outgoingstream, |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1243 request.requestid, |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1244 request.name, |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1245 request.args, |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1246 request.datafh) |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1247 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1248 for frame in res: |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1249 yield frame |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1250 |
01361be9e2dc
wireproto: introduce a reactor for client-side state
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37485
diff
changeset
|
1251 request.state = 'sent' |
37544
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1252 |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1253 def onframerecv(self, frame): |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1254 """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
|
1255 |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1256 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
|
1257 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
|
1258 """ |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1259 if frame.streamid % 2: |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1260 return 'error', { |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1261 'message': ( |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1262 _('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
|
1263 frame.streamid), |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1264 } |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1265 |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1266 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
|
1267 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
|
1268 return 'error', { |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1269 'message': _('received frame on unknown stream ' |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1270 'without beginning of stream flag set'), |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1271 } |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1272 |
37656
e6870bca1f47
wireprotoframing: record when new stream is encountered
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37655
diff
changeset
|
1273 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
|
1274 |
37544
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1275 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
|
1276 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
|
1277 'payloads not yet implemneted') |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1278 |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1279 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
|
1280 del self._incomingstreams[frame.streamid] |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1281 |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1282 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
|
1283 return 'error', { |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1284 '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
|
1285 frame.requestid), |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1286 } |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1287 |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1288 request = self._activerequests[frame.requestid] |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1289 request.state = 'receiving' |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1290 |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1291 handlers = { |
37724
deff7cf7eefd
wireprotov2: change frame type and name for command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37723
diff
changeset
|
1292 FRAME_TYPE_COMMAND_RESPONSE: self._oncommandresponseframe, |
37726
0c184ca594bb
wireprotov2: change behavior of error frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37725
diff
changeset
|
1293 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
|
1294 } |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1295 |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1296 meth = handlers.get(frame.typeid) |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1297 if not meth: |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1298 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
|
1299 frame.typeid) |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1300 |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1301 return meth(request, frame) |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1302 |
37724
deff7cf7eefd
wireprotov2: change frame type and name for command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37723
diff
changeset
|
1303 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
|
1304 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
|
1305 request.state = 'received' |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1306 del self._activerequests[request.requestid] |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1307 |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1308 return 'responsedata', { |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1309 'request': request, |
37724
deff7cf7eefd
wireprotov2: change frame type and name for command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37723
diff
changeset
|
1310 '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
|
1311 '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
|
1312 'data': frame.payload, |
55b5ba8d4e68
wireproto: client reactor support for receiving frames
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37543
diff
changeset
|
1313 } |
37726
0c184ca594bb
wireprotov2: change behavior of error frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37725
diff
changeset
|
1314 |
0c184ca594bb
wireprotov2: change behavior of error frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37725
diff
changeset
|
1315 def _onerrorresponseframe(self, request, frame): |
0c184ca594bb
wireprotov2: change behavior of error frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37725
diff
changeset
|
1316 request.state = 'errored' |
0c184ca594bb
wireprotov2: change behavior of error frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37725
diff
changeset
|
1317 del self._activerequests[request.requestid] |
0c184ca594bb
wireprotov2: change behavior of error frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37725
diff
changeset
|
1318 |
0c184ca594bb
wireprotov2: change behavior of error frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37725
diff
changeset
|
1319 # The payload should be a CBOR map. |
39465
36f487a332ad
wireprotoframing: use our CBOR module
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37728
diff
changeset
|
1320 m = cborutil.decodeall(frame.payload)[0] |
37726
0c184ca594bb
wireprotov2: change behavior of error frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37725
diff
changeset
|
1321 |
0c184ca594bb
wireprotov2: change behavior of error frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37725
diff
changeset
|
1322 return 'error', { |
0c184ca594bb
wireprotov2: change behavior of error frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37725
diff
changeset
|
1323 'request': request, |
0c184ca594bb
wireprotov2: change behavior of error frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37725
diff
changeset
|
1324 'type': m['type'], |
0c184ca594bb
wireprotov2: change behavior of error frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37725
diff
changeset
|
1325 'message': m['message'], |
0c184ca594bb
wireprotov2: change behavior of error frame
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37725
diff
changeset
|
1326 } |