1 /*
2  * Copyright (c) 2007 - 2015 Joseph Gaeddert
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20  * THE SOFTWARE.
21  */
22 
23 //
24 // Packetizer
25 //
26 
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 
31 #include "liquid.internal.h"
32 
33 // reallocate memory for buffers
34 void packetizer_realloc_buffers(packetizer _p, unsigned int _len);
35 
36 // computes the number of encoded bytes after packetizing
37 //
38 //  _n      :   number of uncoded input bytes
39 //  _crc    :   error-detecting scheme
40 //  _fec0   :   inner forward error-correction code
41 //  _fec1   :   outer forward error-correction code
packetizer_compute_enc_msg_len(unsigned int _n,int _crc,int _fec0,int _fec1)42 unsigned int packetizer_compute_enc_msg_len(unsigned int _n,
43                                             int _crc,
44                                             int _fec0,
45                                             int _fec1)
46 {
47     unsigned int k = _n + crc_get_length(_crc);
48     unsigned int n0 = fec_get_enc_msg_length(_fec0, k);
49     unsigned int n1 = fec_get_enc_msg_length(_fec1, n0);
50 
51     return n1;
52 }
53 
54 // computes the number of decoded bytes before packetizing
55 //
56 //  _k      :   number of encoded bytes
57 //  _crc    :   error-detecting scheme
58 //  _fec0   :   inner forward error-correction code
59 //  _fec1   :   outer forward error-correction code
packetizer_compute_dec_msg_len(unsigned int _k,int _crc,int _fec0,int _fec1)60 unsigned int packetizer_compute_dec_msg_len(unsigned int _k,
61                                             int _crc,
62                                             int _fec0,
63                                             int _fec1)
64 {
65     unsigned int n_hat = 0;
66     unsigned int k_hat = 0;
67 
68     // check for zero-length packet
69     // TODO : implement faster method
70     while (k_hat < _k) {
71         // compute encoded packet length
72         k_hat = packetizer_compute_enc_msg_len(n_hat, _crc, _fec0, _fec1);
73 
74         //
75         if (k_hat == _k)
76             return n_hat;
77         else if (k_hat > _k)
78             return n_hat;   // TODO : check this special condition
79         else
80             n_hat++;
81     }
82 
83     return 0;
84 }
85 
86 
87 // create packetizer object
88 //
89 //  _n      :   number of uncoded intput bytes
90 //  _crc    :   error-detecting scheme
91 //  _fec0   :   inner forward error-correction code
92 //  _fec1   :   outer forward error-correction code
packetizer_create(unsigned int _n,int _crc,int _fec0,int _fec1)93 packetizer packetizer_create(unsigned int _n,
94                              int _crc,
95                              int _fec0,
96                              int _fec1)
97 {
98     packetizer p = (packetizer) malloc(sizeof(struct packetizer_s));
99 
100     p->msg_len      = _n;
101     p->packet_len   = packetizer_compute_enc_msg_len(_n, _crc, _fec0, _fec1);
102     p->check        = _crc;
103     p->crc_length   = crc_get_length(p->check);
104 
105     // allocate memory for buffers (scale by 8 for soft decoding)
106     p->buffer_len = p->packet_len;
107     p->buffer_0 = (unsigned char*) malloc(8*p->buffer_len);
108     p->buffer_1 = (unsigned char*) malloc(8*p->buffer_len);
109 
110     // create plan
111     p->plan_len = 2;
112     p->plan = (struct fecintlv_plan*) malloc((p->plan_len)*sizeof(struct fecintlv_plan));
113 
114     // set schemes
115     unsigned int i;
116     unsigned int n0 = _n + p->crc_length;
117     for (i=0; i<p->plan_len; i++) {
118         // set schemes
119         p->plan[i].fs = (i==0) ? _fec0 : _fec1;
120 
121         // compute lengths
122         p->plan[i].dec_msg_len = n0;
123         p->plan[i].enc_msg_len = fec_get_enc_msg_length(p->plan[i].fs,
124                                                         p->plan[i].dec_msg_len);
125 
126         // create objects
127         p->plan[i].f = fec_create(p->plan[i].fs, NULL);
128         p->plan[i].q = interleaver_create(p->plan[i].enc_msg_len);
129 
130         // set interleaver depth to zero if no error correction scheme
131         // is applied to this plan
132         if (p->plan[i].fs == LIQUID_FEC_NONE)
133             interleaver_set_depth(p->plan[i].q, 0);
134 
135         // update length
136         n0 = p->plan[i].enc_msg_len;
137     }
138 
139     return p;
140 }
141 
142 // re-create packetizer object
143 //
144 //  _p      :   initialz packetizer object
145 //  _n      :   number of uncoded intput bytes
146 //  _crc    :   error-detecting scheme
147 //  _fec0   :   inner forward error-correction code
148 //  _fec1   :   outer forward error-correction code
packetizer_recreate(packetizer _p,unsigned int _n,int _crc,int _fec0,int _fec1)149 packetizer packetizer_recreate(packetizer _p,
150                                unsigned int _n,
151                                int _crc,
152                                int _fec0,
153                                int _fec1)
154 {
155     if (_p == NULL) {
156         // packetizer was never created
157         return packetizer_create(_n, _crc, _fec0, _fec1);
158     }
159 
160     // check values
161     if (_p->msg_len     ==  _n      &&
162         _p->check       ==  _crc    &&
163         _p->plan[0].fs  ==  _fec0   &&
164         _p->plan[1].fs  ==  _fec1 )
165     {
166         // no change; return input pointer
167         return _p;
168     }
169 
170     // something has changed; destroy old object and create new one
171     // TODO : rather than completely destroying object, only change values that are necessary
172     packetizer_destroy(_p);
173     return packetizer_create(_n,_crc,_fec0,_fec1);
174 }
175 
176 // destroy packetizer object
packetizer_destroy(packetizer _p)177 void packetizer_destroy(packetizer _p)
178 {
179     if (!_p) {
180         return;
181     }
182 
183     // free fec, interleaver objects
184     unsigned int i;
185     for (i=0; i<_p->plan_len; i++) {
186         fec_destroy(_p->plan[i].f);
187         interleaver_destroy(_p->plan[i].q);
188     };
189 
190     // free plan
191     free(_p->plan);
192 
193     // free buffers
194     free(_p->buffer_0);
195     free(_p->buffer_1);
196 
197     // free packetizer object
198     free(_p);
199 }
200 
201 // print packetizer object internals
packetizer_print(packetizer _p)202 void packetizer_print(packetizer _p)
203 {
204     printf("packetizer [dec: %u, enc: %u]\n", _p->msg_len, _p->packet_len);
205     printf("     : crc      %-10u %-10u %-16s\n",
206             _p->msg_len,
207             _p->msg_len + _p->crc_length,
208             crc_scheme_str[_p->check][0]);
209     unsigned int i;
210     for (i=0; i<_p->plan_len; i++) {
211         printf("%4u : fec      %-10u %-10u %-16s\n",
212             i,
213             _p->plan[i].dec_msg_len,
214             _p->plan[i].enc_msg_len,
215             fec_scheme_str[_p->plan[i].fs][1]);
216     }
217 }
218 
219 // get decoded message length
packetizer_get_dec_msg_len(packetizer _p)220 unsigned int packetizer_get_dec_msg_len(packetizer _p)
221 {
222     return _p->msg_len;
223 }
224 
225 // get encoded message length
packetizer_get_enc_msg_len(packetizer _p)226 unsigned int packetizer_get_enc_msg_len(packetizer _p)
227 {
228     return _p->packet_len;
229 }
230 
packetizer_get_crc(packetizer _p)231 crc_scheme packetizer_get_crc(packetizer _p)
232 {
233     return _p->check;
234 }
235 
packetizer_get_fec0(packetizer _p)236 fec_scheme packetizer_get_fec0(packetizer _p)
237 {
238     return _p->plan[0].fs;
239 }
240 
packetizer_get_fec1(packetizer _p)241 fec_scheme packetizer_get_fec1(packetizer _p)
242 {
243     return _p->plan[1].fs;
244 }
245 
246 // Execute the packetizer on an input message
247 //
248 //  _p      :   packetizer object
249 //  _msg    :   input message (uncoded bytes)
250 //  _pkt    :   encoded output message
packetizer_encode(packetizer _p,const unsigned char * _msg,unsigned char * _pkt)251 void packetizer_encode(packetizer            _p,
252                        const unsigned char * _msg,
253                        unsigned char *       _pkt)
254 {
255     unsigned int i;
256 
257     // copy input message to internal buffer[0] (or initialize to zeros)
258     if (_msg != NULL) {
259         // copy user-defined input
260         memmove(_p->buffer_0, _msg, _p->msg_len);
261     } else {
262         // initialize with zeros
263         memset(_p->buffer_0, 0x00, _p->msg_len);
264     }
265 
266     // compute crc, append to buffer
267     unsigned int key = crc_generate_key(_p->check, _p->buffer_0, _p->msg_len);
268     for (i=0; i<_p->crc_length; i++) {
269         // append byte to buffer
270         _p->buffer_0[_p->msg_len+_p->crc_length-i-1] = key & 0xff;
271 
272         // shift key by 8 bits
273         key >>= 8;
274     }
275 
276     // whiten input sequence
277     scramble_data(_p->buffer_0, _p->msg_len + _p->crc_length);
278 
279     // execute fec/interleaver plans
280     for (i=0; i<_p->plan_len; i++) {
281         // run the encoder: buffer[0] > buffer[1]
282         fec_encode(_p->plan[i].f,
283                    _p->plan[i].dec_msg_len,
284                    _p->buffer_0,
285                    _p->buffer_1);
286 
287         // run the interleaver: buffer[1] > buffer[0]
288         interleaver_encode(_p->plan[i].q,
289                            _p->buffer_1,
290                            _p->buffer_0);
291     }
292 
293     // copy result to output
294     memmove(_pkt, _p->buffer_0, _p->packet_len);
295 }
296 
297 // Execute the packetizer to decode an input message, return validity
298 // check of resulting data
299 //
300 //  _p      :   packetizer object
301 //  _pkt    :   input message (coded bytes)
302 //  _msg    :   decoded output message
packetizer_decode(packetizer _p,const unsigned char * _pkt,unsigned char * _msg)303 int packetizer_decode(packetizer            _p,
304                       const unsigned char * _pkt,
305                       unsigned char *       _msg)
306 {
307     // copy coded message to internal buffer[0]
308     memmove(_p->buffer_0, _pkt, _p->packet_len);
309 
310     // execute fec/interleaver plans
311     unsigned int i;
312     for (i=_p->plan_len; i>0; i--) {
313         // run the de-interleaver: buffer[0] > buffer[1]
314         interleaver_decode(_p->plan[i-1].q,
315                            _p->buffer_0,
316                            _p->buffer_1);
317 
318         // run the decoder: buffer[1] > buffer[0]
319         fec_decode(_p->plan[i-1].f,
320                    _p->plan[i-1].dec_msg_len,
321                    _p->buffer_1,
322                    _p->buffer_0);
323     }
324 
325     // remove sequence whitening
326     unscramble_data(_p->buffer_0, _p->msg_len + _p->crc_length);
327 
328     // strip crc, validate message
329     unsigned int key = 0;
330     for (i=0; i<_p->crc_length; i++) {
331         key <<= 8;
332 
333         key |= _p->buffer_0[_p->msg_len+i];
334     }
335 
336     // copy result to output
337     memmove(_msg, _p->buffer_0, _p->msg_len);
338 
339     // return crc validity
340     return crc_validate_message(_p->check,
341                                 _p->buffer_0,
342                                 _p->msg_len,
343                                 key);
344 }
345 
346 // Execute the packetizer to decode an input message, return validity
347 // check of resulting data
348 //
349 //  _p      :   packetizer object
350 //  _pkt    :   input message (coded soft bits)
351 //  _msg    :   decoded output message
packetizer_decode_soft(packetizer _p,const unsigned char * _pkt,unsigned char * _msg)352 int packetizer_decode_soft(packetizer            _p,
353                            const unsigned char * _pkt,
354                            unsigned char *       _msg)
355 {
356     // copy coded message to internal buffer[0]
357     memmove(_p->buffer_0, _pkt, 8*_p->packet_len);
358 
359     //
360     // decode outer level using soft decoding
361     //
362 
363     // run the de-interleaver: buffer[0] > buffer[1]
364     interleaver_decode_soft(_p->plan[1].q,
365                             _p->buffer_0,
366                             _p->buffer_1);
367 
368     // run the decoder: buffer[1] > buffer[0]
369     fec_decode_soft(_p->plan[1].f,
370                     _p->plan[1].dec_msg_len,
371                     _p->buffer_1,
372                     _p->buffer_0);
373 
374     //
375     // decode inner level using hard decoding
376     //
377 
378     // run the de-interleaver: buffer[0] > buffer[1]
379     interleaver_decode(_p->plan[0].q,
380                        _p->buffer_0,
381                        _p->buffer_1);
382 
383     // run the decoder: buffer[1] > buffer[0]
384     fec_decode(_p->plan[0].f,
385                _p->plan[0].dec_msg_len,
386                _p->buffer_1,
387                _p->buffer_0);
388 
389     // remove sequence whitening
390     unscramble_data(_p->buffer_0, _p->msg_len + _p->crc_length);
391 
392     // strip crc, validate message
393     unsigned int key = 0;
394     unsigned int i;
395     for (i=0; i<_p->crc_length; i++) {
396         key <<= 8;
397 
398         key |= _p->buffer_0[_p->msg_len+i];
399     }
400 
401     // copy result to output
402     memmove(_msg, _p->buffer_0, _p->msg_len);
403 
404     // return crc validity
405     return crc_validate_message(_p->check,
406                                 _p->buffer_0,
407                                 _p->msg_len,
408                                 key);
409 }
410 
packetizer_set_scheme(packetizer _p,int _fec0,int _fec1)411 void packetizer_set_scheme(packetizer _p, int _fec0, int _fec1)
412 {
413     //
414 }
415 
416 //
417 // internal methods
418 //
419 
packetizer_realloc_buffers(packetizer _p,unsigned int _len)420 void packetizer_realloc_buffers(packetizer _p, unsigned int _len)
421 {
422     _p->buffer_len = _len;
423     _p->buffer_0 = (unsigned char*) realloc(_p->buffer_0, _p->buffer_len);
424     _p->buffer_1 = (unsigned char*) realloc(_p->buffer_1, _p->buffer_len);
425 }
426 
427