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