Commit | Line | Data |
---|---|---|
de4dee04 PP |
1 | # -*- coding: utf-8 -*- |
2 | # | |
3 | # Copyright (C) 2015 - Philippe Proulx <pproulx@efficios.com> | |
4 | # Copyright (C) 2014 - David Goulet <dgoulet@efficios.com> | |
5 | # | |
6 | # This library is free software; you can redistribute it and/or modify it under | |
7 | # the terms of the GNU Lesser General Public License as published by the Free | |
8 | # Software Foundation; version 2.1 of the License. | |
9 | # | |
10 | # This library is distributed in the hope that it will be useful, but WITHOUT | |
11 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | |
12 | # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more | |
13 | # details. | |
14 | # | |
15 | # You should have received a copy of the GNU Lesser General Public License | |
16 | # along with this library; if not, write to the Free Software Foundation, Inc., | |
17 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
18 | ||
19 | from __future__ import unicode_literals | |
20 | import lttngust.debug as dbg | |
21 | import struct | |
22 | ||
23 | ||
24 | # server command header | |
25 | _server_cmd_header_struct = struct.Struct('>QII') | |
26 | ||
27 | ||
28 | # server command header size | |
29 | _SERVER_CMD_HEADER_SIZE = _server_cmd_header_struct.size | |
30 | ||
31 | ||
32 | class _ServerCmdHeader(object): | |
33 | def __init__(self, data_size, cmd_id, cmd_version): | |
34 | self.data_size = data_size | |
35 | self.cmd_id = cmd_id | |
36 | self.cmd_version = cmd_version | |
37 | ||
38 | ||
39 | def _server_cmd_header_from_data(data): | |
40 | try: | |
41 | data_size, cmd_id, cmd_version = _server_cmd_header_struct.unpack(data) | |
42 | except (Exception) as e: | |
43 | dbg._pdebug('cannot decode command header: {}'.format(e)) | |
44 | return None | |
45 | ||
46 | return _ServerCmdHeader(data_size, cmd_id, cmd_version) | |
47 | ||
48 | ||
49 | class _ServerCmd(object): | |
50 | def __init__(self, header): | |
51 | self.header = header | |
52 | ||
53 | @classmethod | |
54 | def from_data(cls, header, data): | |
55 | raise NotImplementedError() | |
56 | ||
57 | ||
58 | class _ServerCmdList(_ServerCmd): | |
59 | @classmethod | |
60 | def from_data(cls, header, data): | |
61 | return cls(header) | |
62 | ||
63 | ||
64 | class _ServerCmdEnable(_ServerCmd): | |
65 | _NAME_OFFSET = 8 | |
66 | _loglevel_struct = struct.Struct('>II') | |
67 | ||
68 | def __init__(self, header, loglevel, loglevel_type, name): | |
69 | super(self.__class__, self).__init__(header) | |
70 | self.loglevel = loglevel | |
71 | self.loglevel_type = loglevel_type | |
72 | self.name = name | |
73 | ||
74 | @classmethod | |
75 | def from_data(cls, header, data): | |
76 | try: | |
77 | loglevel, loglevel_type = cls._loglevel_struct.unpack_from(data) | |
78 | data_name = data[cls._loglevel_struct.size:] | |
79 | name = data_name.rstrip(b'\0').decode() | |
80 | ||
81 | return cls(header, loglevel, loglevel_type, name) | |
82 | except (Exception) as e: | |
83 | dbg._pdebug('cannot decode enable command: {}'.format(e)) | |
84 | return None | |
85 | ||
86 | ||
87 | class _ServerCmdDisable(_ServerCmd): | |
88 | def __init__(self, header, name): | |
89 | super(self.__class__, self).__init__(header) | |
90 | self.name = name | |
91 | ||
92 | @classmethod | |
93 | def from_data(cls, header, data): | |
94 | try: | |
95 | name = data.rstrip(b'\0').decode() | |
96 | ||
97 | return cls(header, name) | |
98 | except (Exception) as e: | |
99 | dbg._pdebug('cannot decode disable command: {}'.format(e)) | |
100 | return None | |
101 | ||
102 | ||
103 | class _ServerCmdRegistrationDone(_ServerCmd): | |
104 | @classmethod | |
105 | def from_data(cls, header, data): | |
106 | return cls(header) | |
107 | ||
108 | ||
109 | _SERVER_CMD_ID_TO_SERVER_CMD = { | |
110 | 1: _ServerCmdList, | |
111 | 2: _ServerCmdEnable, | |
112 | 3: _ServerCmdDisable, | |
113 | 4: _ServerCmdRegistrationDone, | |
114 | } | |
115 | ||
116 | ||
117 | def _server_cmd_from_data(header, data): | |
118 | if header.cmd_id not in _SERVER_CMD_ID_TO_SERVER_CMD: | |
119 | return None | |
120 | ||
121 | return _SERVER_CMD_ID_TO_SERVER_CMD[header.cmd_id].from_data(header, data) | |
122 | ||
123 | ||
124 | _CLIENT_CMD_REPLY_STATUS_SUCCESS = 1 | |
125 | _CLIENT_CMD_REPLY_STATUS_INVALID_CMD = 2 | |
126 | ||
127 | ||
128 | class _ClientCmdReplyHeader(object): | |
129 | _payload_struct = struct.Struct('>I') | |
130 | ||
131 | def __init__(self, status_code=_CLIENT_CMD_REPLY_STATUS_SUCCESS): | |
132 | self.status_code = status_code | |
133 | ||
134 | def get_data(self): | |
135 | return self._payload_struct.pack(self.status_code) | |
136 | ||
137 | ||
138 | class _ClientCmdReplyEnable(_ClientCmdReplyHeader): | |
139 | pass | |
140 | ||
141 | ||
142 | class _ClientCmdReplyDisable(_ClientCmdReplyHeader): | |
143 | pass | |
144 | ||
145 | ||
146 | class _ClientCmdReplyList(_ClientCmdReplyHeader): | |
147 | _nb_events_struct = struct.Struct('>I') | |
148 | _data_size_struct = struct.Struct('>I') | |
149 | ||
150 | def __init__(self, names, status_code=_CLIENT_CMD_REPLY_STATUS_SUCCESS): | |
151 | super(self.__class__, self).__init__(status_code) | |
152 | self.names = names | |
153 | ||
154 | def get_data(self): | |
155 | upper_data = super(self.__class__, self).get_data() | |
156 | nb_events_data = self._nb_events_struct.pack(len(self.names)) | |
157 | names_data = bytes() | |
158 | ||
159 | for name in self.names: | |
160 | names_data += name.encode() + b'\0' | |
161 | ||
162 | data_size_data = self._data_size_struct.pack(len(names_data)) | |
163 | ||
164 | return upper_data + data_size_data + nb_events_data + names_data | |
165 | ||
166 | ||
167 | class _ClientRegisterCmd(object): | |
168 | _payload_struct = struct.Struct('>IIII') | |
169 | ||
170 | def __init__(self, domain, pid, major, minor): | |
171 | self.domain = domain | |
172 | self.pid = pid | |
173 | self.major = major | |
174 | self.minor = minor | |
175 | ||
176 | def get_data(self): | |
177 | return self._payload_struct.pack(self.domain, self.pid, self.major, | |
178 | self.minor) |