source: trunk/ETSI-Testsuites/ETSI_auto_IOT/codec/c++/isup_codets.cpp @ 28

Last change on this file since 28 was 22, checked in by rings, 14 years ago
  • Property svn:executable set to *
File size: 7.5 KB
Line 
1#include <arpa/inet.h>
2#include "gen_classes.h"
3
4namespace t3devlib { namespace gen {
5
6// ISUP codec
7
8// ISUP is going to be difficult to encode and decode for the following reasons:
9// • the bit order for the transmission is reversed: the LSB is sent first.
10//   This will cause some difficulties since the order of the fields in the
11//   TTCN-3 types follows the order of transmission, not the order in memory
12//   (note that there are lots of fields that are less than 8-bit long).
13//   Consequently the codec generator cannot be used directly to
14//   encode/decode the message (since it processes the order of the buffer in
15//   the memory order -> MSB first)
16// • numeric fields that span across multiple bytes are not always encoded in
17//   the same order
18//   ∘ eg. the 'Network Number Indicator' and the 'Network Identity' are both
19//     encoded in DCB but the digits are not ordered in the same way:
20//     ‣ the NNI 1234 is encoded as "\x21\x43"
21//     ‣ the NI  1234 is encoded as "\x12\x34"
22//   ∘ for some fields the byte order is not given: eg.
23// • Call Identity in the Call Reference parameter
24// • Diagnostics in the Cause Indicator parameter
25// • Local Reference in the Connection request parameter
26//     ‣ -> in which order is it assumed to be in the test suite ?
27//     ‣ when the order is given, then the Most Signifiant Byte comes first
28//       -> then we should assume that this is the default order
29//
30// Design strategy
31//
32// Knowing that ISUP messages are a concatenation of a lot of small fields
33// (less than 8 bit), the coding/decoding task will be complex since it will
34// be necessary to align correctly each field. Then care about the order of
35// the bits.
36//
37// Some consideration should be taken to ease the work
38// • The two issues above should be handled separately: one part of the codec
39//   will deal with the concatenation/alignment of fields and the other one
40//   will deal with the order of the bits in the fields.
41// • For all the alignement/concatenation requirements, we should rely on the
42//   capabilities of the codec generator. It has already been validated for
43//   such a task. In order to handle the fields in the same order as in the
44//   transmission, it will be necessary to reverse the order of the bits in
45//   the whole buffer before decoding and after encoding. After decoding and
46//   before encoding, it will also be necessary to reverse the bits an all
47//   the fields and sub-fields in the TTCN-3 structure. However since this
48//   order differs from one field to another, it better to merge this part
49//   with the next task below.
50// • The second part of the codec is to order the bits in the field correctly
51//   according to the properties of the field being encoded/decoded. There
52//   are some general rules, but lots of fields will have to be handled on a
53//   case per case basis.
54
55
56
57// reverse the order of the bits in the buffer between the current position
58// and the current end marker
59void buffer_reverse_remaining_bytes (Variable* var, Buffer& buffer) throw (DecodeError)
60{
61        if ((buffer.GetPosition() % 8) | (buffer.GetBitsLeft() % 8))
62                throw DecodeError (var, "Unaligned data");
63       
64        //TODO: optimise
65        for (int i = buffer.GetPosition() ; i < buffer.GetEndMarker() ; i+=8)
66        {
67                unsigned char c = buffer.GetValueBin()[i/8];
68                unsigned char r = 0;
69
70                for (int j=8 ; j ; j--) {
71                        r = (r << 1) | (c & 1);
72                        c = c >> 1;
73                }
74                buffer.Replace (i, &r, 8);
75        }
76}
77
78// reverse the order of the bits in every bitstring in the message
79//TODO: reverse the octetstrings too
80void reverse_all_bitstrings (Variable& var)
81{
82        switch (var.GetBaseType()) {
83        case Variable::btRecord:
84        case Variable::btSet: {
85                RecordSet& rs = static_cast<RecordSet&> (var);
86                for (int i=rs.GetSize()-1 ; i>=0 ; i--) {
87                        if (rs.IsPresent (i))
88                                reverse_all_bitstrings (*rs.GetField(i));
89                }
90                break;
91        }
92        case Variable::btRecordOf:
93        case Variable::btSetOf: {
94                RecordOfSetOf& rs = static_cast<RecordOfSetOf&> (var);
95                for (int i=rs.GetSize()-1 ; i>=0 ; i--) {
96                        reverse_all_bitstrings (*rs.GetField(i));
97                }
98                break;
99        }
100        case Variable::btUnion:
101                reverse_all_bitstrings (*static_cast<Union&> (var).GetField());
102                break;
103       
104        case Variable::btBitstring:
105                goto reverse_bitstring;
106       
107        default:
108                ;
109        }
110        return;
111
112reverse_bitstring:
113        Bitstring& bs = static_cast<Bitstring&>(var);
114
115        unsigned char buff[16]; // should be big enough
116        assert (bs.GetLength() < 16*8);
117       
118        const unsigned char*    src = bs.GetValueBin();
119        unsigned char*          dst = buff + (bs.GetLength() / 8);
120        int                     k   = bs.GetLength() % 8;
121
122        // process pack of 8 bits
123        int i;
124        for (i=bs.GetLength() ; i>8 ; i-=8, src++)
125        {
126                unsigned char c = *src;
127
128                for (int j=8 ; j ; j--) {
129                        if (k == 0) {
130                                dst--;
131                                k = 8;
132                        }
133
134                        *dst = (*dst >> 1) | (c & 0x80);
135                        c = c << 1;
136                }
137        }
138
139        // process the remaining bits
140        {
141                unsigned char c = *src;
142
143                for ( ; i>0 ; i--) {
144                        if (k == 0) {
145                                dst--;
146                                k = 8;
147                        }
148
149                        *dst = (*dst >> 1) | (c & 0x80);
150                        c = c << 1;
151                }
152        }
153
154        bs.SetValueBin (buff, bs.GetLength());
155}
156
157// read a bistring and return its value with all the bits reversed
158int get_reverse_value (const Bitstring& bs)
159{
160        unsigned char buff[sizeof(uint32_t)]; // should be big enough (assume we have 32 bits for int)
161        assert (bs.GetLength() < sizeof(uint32_t)*8);
162        memset (buff, 0, sizeof(uint32_t));
163       
164        const unsigned char*    src = bs.GetValueBin();
165        unsigned char*          dst = buff + (bs.GetLength() / 8);
166        int                     k   = bs.GetLength() % 8;
167
168        // process pack of 8 bits
169        int i;
170        for (i=bs.GetLength() ; i>8 ; i-=8, src++)
171        {
172                unsigned char c = *src;
173
174                for (int j=8 ; j ; j--) {
175                        if (k == 0) {
176                                dst--;
177                                k = 8;
178                        }
179
180                        *dst = (*dst >> 1) | (c & 0x80);
181                        c = c << 1;
182                }
183        }
184
185        // process the remaining bits
186        {
187                unsigned char c = *src;
188
189                for ( ; i>0 ; i--) {
190                        if (k == 0) {
191                                dst--;
192                                k = 8;
193                        }
194
195                        *dst = (*dst >> 1) | (c & 0x80);
196                        c = c << 1;
197                }
198        }
199
200        uint32_t result = ntohl (*reinterpret_cast<uint32_t*> (buff));
201        return result >> ((sizeof(int)*8) - bs.GetLength());
202}
203
204// map used to resolve the message type in ISUP_BICC_MSG
205class IsupMsgTypeMap
206{
207public:
208        static int GetBiccField (int msg_type)
209        {
210                std::map<int, int>::iterator it = msInstance.mMap.find (msg_type);
211
212                return (it != msInstance.mMap.end()) ? it->second : msInstance.mUnknown;
213        }
214
215private:
216        IsupMsgTypeMap()
217        {
218                mMap[1] = ISUP_BICC_MSG::id_iAM_MSG;
219
220                mUnknown = ISUP_BICC_MSG::id_uNKNOWN_MSG;
221        }
222
223        static IsupMsgTypeMap           msInstance;
224
225        std::map<int, int>      mMap;
226        int                     mUnknown;
227};
228IsupMsgTypeMap          IsupMsgTypeMap::msInstance;
229
230void ISUP_BICC_MSG::PreDecode (Buffer& buffer) throw (DecodeError)
231{
232        int position = buffer.GetPosition();
233
234        // read ahead one byte to get the message type
235        Unsigned msg_type(8);
236        msg_type.Decode (buffer);
237        SetHypChosenId (IsupMsgTypeMap::GetBiccField (msg_type.GetValue()));
238
239        buffer.SetPosition(position);
240}
241
242void IAM_MSG::PreDecode (Buffer& buffer) throw (DecodeError)
243{
244        buffer_reverse_remaining_bytes (this, buffer);
245}
246
247void IAM_MSG::PostDecode (Buffer& buffer) throw (DecodeError)
248{
249        reverse_all_bitstrings (*this);
250        buffer_reverse_remaining_bytes (this, buffer);
251}
252
253void IAM_MSG::PostDecode (Buffer& buffer, DecodeError& e) throw (DecodeError)
254{
255        reverse_all_bitstrings (*this);
256
257        // dump the error here
258        // because there is an issue w/ propagating the exceptions in t3devkit
259        e.Dump (std::cerr);
260        throw DecodeIgnoreMessage (this);
261}
262
263void CDN_PAR_lv::PreDecode (Buffer& buffer) throw (DecodeError)
264{
265        int position = buffer.GetPosition();
266        Bit8 len;
267        len.Decode(buffer);
268        SetHypLength (get_reverse_value (len) * 8);
269
270        buffer.SetPosition (position);
271}
272
273
274}} // namespace t3devlib::gen
275
Note: See TracBrowser for help on using the repository browser.