root/branch/UMPA/umpa/_packets.py @ 3583

Revision 3583, 6.3 kB (checked in by getxsick, 5 years ago)

Removed unnecessary method.

Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4# Copyright (C) 2008 Adriano Monteiro Marques.
5#
6# Author: Bartosz SKOWRON <getxsick at gmail dot com>
7#
8# This library is free software; you can redistribute it and/or modify
9# it under the terms of the GNU Lesser General Public License as published
10# by the Free Software Foundation; either version 2.1 of the License, or
11# (at your option) any later version.
12#
13# This library is distributed in the hope that it will be useful, but
14# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16# License for more details.
17#
18# You should have received a copy of the GNU Lesser General Public License
19# along with this library; if not, write to the Free Software Foundation,
20# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
22"""
23This module manages with packets.
24
25Packet class is a protocol container.
26Use it to build a packet which contains several protocols.
27"""
28
29import struct
30import warnings
31
32import umpa.utils.bits
33from umpa.utils.exceptions import UMPAStrictException
34
35BYTE = 8
36
37class StrictWarning(Warning):
38    """
39    New category of warning.
40
41    It's being used for warning message with reference
42    to strict attribute of Packet's objects.
43    """
44
45    pass
46
47def strict_warn(layer_a, layer_b):
48    """
49    Issue the warning with prepared message as a StrictWarning category.
50
51    @type layer_a: C{int}
52    @param layer_a: layer for first protocol.
53
54    @type layer_b: C{int}
55    @param layer_b: layer for second protocol.
56    """
57
58    msg = "bad protocols ordering. first layer %d, second %d." % (layer_a,
59                                                                    layer_b)
60    warnings.warn(msg, StrictWarning, stacklevel=3)
61
62class Packet(object):
63    """
64    This is a protocol container.
65
66    Use this to build a completely packets.
67    An instance of the class should contains protocols which you want to send.
68    """
69
70    def __init__(self, *protos, **kwds):
71        """
72        Create a new Packet().
73
74        @type *protos: Optional C{Protocol}
75        @param *protos: protocols which will be included into the object.
76
77        @type **kwds: Optional C{bool}
78        @param **kwds: 2 keys are proper:
79            -- strict (default True): if True object will keep protocols order.
80            It avoids to build odd packets with with unsaved layer order
81            -- warn (default True): if True and strict is True, object will
82            issue warnings. Otherwise warnings are ignored.
83        """
84       
85        if 'strict' in kwds:
86            self.strict = kwds['strict']
87        else:
88            self.strict = True      # default value
89           
90        if 'warn' in kwds:
91            self.warn = kwds['warn']
92        else:
93            self.warn = True        # default value
94
95        self.protos = []
96        self._add_new_protocols(protos)
97        self.raw = None
98        self.bits = 0
99
100    def __str__(self):
101        """
102        Print in human-readable tree-style a content of the packet.
103
104        It calls print statement for protocols.
105
106        @return: call __str__ method of super-class.
107        """
108
109        print "Packet contains %d protocols" % len(self.protos)
110        for proto in self.protos:
111            print proto
112        return super(Packet, self).__str__()
113
114    def include(self, *protos):
115        """
116        Add protocols into packet.
117
118        @type *protos: C{Protocol}
119        @param *protos: protocols which will be included into the packet.
120        """
121
122        self._add_new_protocols(protos)
123
124    def _add_new_protocols(self, protos):
125        """
126        Add protocols into packet.
127
128        Check the strict attribute and
129        raise UMPAStrictException or issues warnings if needed.
130
131        @type protos: C{Protocol}
132        @param protos: protocols which will be included into the packet.
133        """
134
135        for p in protos:
136            if len(self.protos) > 0:
137                last_proto = self.protos[-1]
138                if p.layer - last_proto.layer != 1: # FIXME: should allow only this?
139                    if self.strict:
140                        raise UMPAStrictException("bad protocols ordering. \
141first layer %d, second %d." % (last_proto.layer, p.layer))
142                    else:
143                        strict_warn(last_proto.layer, p.layer)
144                last_proto.__dict__['payload'] = p
145            self.protos.append(p)
146
147    def get_raw(self):
148        """
149        Return raw packet in the bit-mode (big-endian).
150
151        Call every protocols to get the raw bits of them,
152        collect the results and return the raw packet.
153
154        @return: Struct packed bits of every protocols in big-endian order.
155        """
156
157        self.raw = 0
158        self.bits = 0
159        proto_id = 0
160        for proto in reversed(self.protos):
161            # unfortunately we must pass list of protocols to every protocol
162            # because some fields handle with other protocols, so they need
163            # an access to them
164            raw_proto, bit_proto = proto._get_raw(tuple(self.protos),
165                                                                    self.bits)
166            self.raw |= raw_proto << self.bits
167            self.bits += bit_proto
168        # split into chunks
169        # we make it because we need string for socket object
170        # so after that we pack it by struct module.pack()
171        byte_chunks = umpa.utils.bits.split_into_chunks(self.raw, self.bits)
172        return struct.pack('!' + 'B'*(self.bits/BYTE), *byte_chunks)
173
174    def _getwarn(self):
175        """
176        Return warn attribute.
177
178        Warn attribute set a behaviour of strict attribute.
179        If warn is True and strict is True, object will
180        issue warnings if needed. Otherwise warnings are ignored.
181
182        @return: warn attribute.
183        """
184        return self._warn
185
186    def _setwarn(self, val):
187        """
188        Set warn attribute
189
190        Warn attribute set a behaviour of strict attribute.
191        If warn is True and strict is True, object will
192        issue warnings if needed. Otherwise warnings are ignored.
193
194        @type val: C{bool}
195        @param val: bool value.
196        """
197
198        self._warn = val
199        if self._warn:
200            warnings.simplefilter('always', StrictWarning)
201        else:
202            warnings.simplefilter('ignore', StrictWarning)
203
204    warn = property(_getwarn, _setwarn)
Note: See TracBrowser for help on using the browser.