1 /*
2  * $Id: msgqueue_manager.c 53 2011-05-09 16:55:39Z kaori $
3  *
4  * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
5  * Copyright (c) 2002-2011, Professor Benoit Macq
6  * Copyright (c) 2010-2011, Kaori Hagihara
7  * Copyright (c) 2011,      Lucian Corlaciu, GSoC
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <string.h>
37 #include <ctype.h>
38 #ifdef _WIN32
39 #include <io.h>
40 #else
41 #include <unistd.h>
42 #endif
43 #include "msgqueue_manager.h"
44 #include "metadata_manager.h"
45 #include "index_manager.h"
46 
47 #ifdef SERVER
48 #include "fcgi_stdio.h"
49 #define logstream FCGI_stdout
50 #else
51 #define FCGI_stdout stdout
52 #define FCGI_stderr stderr
53 #define logstream stderr
54 #endif /*SERVER*/
55 
gene_msgqueue(bool stateless,cachemodel_param_t * cachemodel)56 msgqueue_param_t * gene_msgqueue( bool stateless, cachemodel_param_t *cachemodel)
57 {
58   msgqueue_param_t *msgqueue;
59 
60   msgqueue = (msgqueue_param_t *)malloc( sizeof(msgqueue_param_t));
61 
62   msgqueue->first = NULL;
63   msgqueue->last  = NULL;
64 
65   msgqueue->stateless = stateless;
66   msgqueue->cachemodel = cachemodel;
67 
68   return msgqueue;
69 }
70 
delete_msgqueue(msgqueue_param_t ** msgqueue)71 void delete_msgqueue( msgqueue_param_t **msgqueue)
72 {
73   message_param_t *ptr, *next;
74 
75   if( !(*msgqueue))
76     return;
77 
78   ptr = (*msgqueue)->first;
79 
80   while( ptr){
81     next = ptr->next;
82     free( ptr);
83     ptr = next;
84   }
85   if( (*msgqueue)->stateless && (*msgqueue)->cachemodel)
86     delete_cachemodel( &((*msgqueue)->cachemodel));
87 
88   free(*msgqueue);
89 }
90 
print_msgqueue(msgqueue_param_t * msgqueue)91 void print_msgqueue( msgqueue_param_t *msgqueue)
92 {
93   message_param_t *ptr;
94   char *message_class[] = { "Precinct", "Ext-Prec", "TileHead", "non", "Tile", "Ext-Tile", "Main", "non", "Meta"};
95 
96   if( !msgqueue)
97     return;
98 
99   fprintf( logstream, "message queue:\n");
100   ptr = msgqueue->first;
101 
102   while( ptr){
103     fprintf( logstream, "\t class_id: %lld %s\n", ptr->class_id, message_class[ptr->class_id]);
104     fprintf( logstream, "\t in_class_id: %lld\n", ptr->in_class_id );
105     fprintf( logstream, "\t csn: %lld\n", ptr->csn );
106     fprintf( logstream, "\t bin_offset: %#llx\n", ptr->bin_offset );
107     fprintf( logstream, "\t length: %#llx\n", ptr->length );
108     if( ptr->class_id%2)
109       fprintf( logstream, "\t aux: %lld\n", ptr->aux );
110     fprintf( logstream, "\t last_byte: %d\n", ptr->last_byte );
111     if( ptr->phld)
112       print_placeholder( ptr->phld);
113     else
114       fprintf( logstream, "\t res_offset: %#llx\n", ptr->res_offset );
115     fprintf( logstream, "\n");
116 
117     ptr = ptr->next;
118   }
119 }
120 
121 void enqueue_message( message_param_t *msg, msgqueue_param_t *msgqueue);
122 
enqueue_mainheader(msgqueue_param_t * msgqueue)123 void enqueue_mainheader( msgqueue_param_t *msgqueue)
124 {
125   cachemodel_param_t *cachemodel;
126   target_param_t *target;
127   index_param_t *codeidx;
128   message_param_t *msg;
129 
130   cachemodel = msgqueue->cachemodel;
131   target = cachemodel->target;
132   codeidx = target->codeidx;
133 
134   msg = (message_param_t *)malloc( sizeof(message_param_t));
135 
136   msg->last_byte = true;
137   msg->in_class_id = 0;
138   msg->class_id = MAINHEADER_MSG;
139   msg->csn = target->csn;
140   msg->bin_offset = 0;
141   msg->length = codeidx->mhead_length;
142   msg->aux = 0; /* non exist*/
143   msg->res_offset = codeidx->offset;
144   msg->phld = NULL;
145   msg->next = NULL;
146 
147   enqueue_message( msg, msgqueue);
148 
149   cachemodel->mhead_model = true;
150 }
151 
enqueue_tileheader(int tile_id,msgqueue_param_t * msgqueue)152 void enqueue_tileheader( int tile_id, msgqueue_param_t *msgqueue)
153 {
154   cachemodel_param_t *cachemodel;
155   target_param_t *target;
156   index_param_t *codeidx;
157   message_param_t *msg;
158 
159   cachemodel = msgqueue->cachemodel;
160   target = cachemodel->target;
161   codeidx = target->codeidx;
162 
163   if( !cachemodel->th_model[ tile_id]){
164     msg = (message_param_t *)malloc( sizeof(message_param_t));
165     msg->last_byte = true;
166     msg->in_class_id = tile_id;
167     msg->class_id = TILE_HEADER_MSG;
168     msg->csn = target->csn;
169     msg->bin_offset = 0;
170     msg->length = codeidx->tileheader[tile_id]->tlen-2; /* SOT marker segment is removed*/
171     msg->aux = 0; /* non exist*/
172     msg->res_offset = codeidx->offset + get_elemOff( codeidx->tilepart, 0, tile_id) + 2; /* skip SOT marker seg*/
173     msg->phld = NULL;
174     msg->next = NULL;
175 
176     enqueue_message( msg, msgqueue);
177     cachemodel->th_model[ tile_id] = true;
178   }
179 }
180 
enqueue_tile(int tile_id,int level,msgqueue_param_t * msgqueue)181 void enqueue_tile( int tile_id, int level, msgqueue_param_t *msgqueue)
182 {
183   cachemodel_param_t *cachemodel;
184   target_param_t *target;
185   bool *tp_model;
186   Byte8_t numOftparts; /* num of tile parts par tile*/
187   Byte8_t numOftiles;
188   index_param_t *codeidx;
189   faixbox_param_t *tilepart;
190   message_param_t *msg;
191   Byte8_t binOffset, binLength, class_id;
192   int i;
193 
194   cachemodel = msgqueue->cachemodel;
195   target = cachemodel->target;
196   codeidx  = target->codeidx;
197   tilepart = codeidx->tilepart;
198 
199   numOftparts = get_nmax( tilepart);
200   numOftiles  = get_m( tilepart);
201 
202   class_id = (numOftparts==1) ? TILE_MSG : EXT_TILE_MSG;
203 
204   if( tile_id < 0 || (int)numOftiles <= tile_id){
205     fprintf( FCGI_stderr, "Error, Invalid tile-id %d\n", tile_id);
206     return;
207   }
208 
209   tp_model = &cachemodel->tp_model[ tile_id*numOftparts];
210 
211   binOffset=0;
212   for( i=0; i<(int)numOftparts-level; i++){
213     binLength = get_elemLen( tilepart, i, tile_id);
214 
215     if( !tp_model[i]){
216       msg = (message_param_t *)malloc( sizeof(message_param_t));
217 
218       msg->last_byte = (i==(int)numOftparts-1);
219       msg->in_class_id = tile_id;
220       msg->class_id = class_id;
221       msg->csn = target->csn;
222       msg->bin_offset = binOffset;
223       msg->length = binLength;
224       msg->aux = numOftparts-i;
225       msg->res_offset = codeidx->offset+get_elemOff( tilepart, i, tile_id)/*-1*/;
226       msg->phld = NULL;
227       msg->next = NULL;
228 
229       enqueue_message( msg, msgqueue);
230 
231       tp_model[i] = true;
232     }
233     binOffset += binLength;
234   }
235 }
236 
enqueue_precinct(int seq_id,int tile_id,int comp_id,int layers,msgqueue_param_t * msgqueue)237 void enqueue_precinct( int seq_id, int tile_id, int comp_id, int layers, msgqueue_param_t *msgqueue)
238 {
239   cachemodel_param_t *cachemodel;
240   index_param_t *codeidx;
241   faixbox_param_t *precpacket;
242   message_param_t *msg;
243   Byte8_t nmax, binOffset, binLength;
244   int layer_id, numOflayers;
245 
246   cachemodel = msgqueue->cachemodel;
247   codeidx = cachemodel->target->codeidx;
248   precpacket = codeidx->precpacket[ comp_id];
249   numOflayers = codeidx->COD.numOflayers;
250 
251   nmax = get_nmax(precpacket);
252   if( layers < 0)
253     layers = numOflayers;
254 
255   binOffset = 0;
256   for( layer_id = 0; layer_id < layers; layer_id++){
257 
258     binLength = get_elemLen( precpacket, seq_id*numOflayers+layer_id, tile_id);
259 
260     if( !cachemodel->pp_model[comp_id][ tile_id*nmax+seq_id*numOflayers+layer_id]){
261 
262       msg = (message_param_t *)malloc( sizeof(message_param_t));
263       msg->last_byte = (layer_id == (numOflayers-1));
264       msg->in_class_id = comp_precinct_id( tile_id, comp_id, seq_id, codeidx->SIZ.Csiz, codeidx->SIZ.XTnum * codeidx->SIZ.YTnum);
265       msg->class_id = PRECINCT_MSG;
266       msg->csn = cachemodel->target->csn;
267       msg->bin_offset = binOffset;
268       msg->length = binLength;
269       msg->aux = 0;
270       msg->res_offset = codeidx->offset+get_elemOff( precpacket, seq_id*numOflayers+layer_id, tile_id);
271       msg->phld = NULL;
272       msg->next = NULL;
273 
274       enqueue_message( msg, msgqueue);
275 
276       cachemodel->pp_model[comp_id][ tile_id*nmax+seq_id*numOflayers+layer_id] = true;
277     }
278     binOffset += binLength;
279   }
280 }
281 
comp_precinct_id(int t,int c,int s,int num_components,int num_tiles)282 Byte8_t comp_precinct_id( int t, int c, int s, int num_components, int num_tiles)
283 {
284   return t + (c + s * num_components ) * num_tiles;
285 }
286 
287 void enqueue_box(  int meta_id, boxlist_param_t *boxlist, msgqueue_param_t *msgqueue, Byte8_t *binOffset);
288 void enqueue_phld( int meta_id, placeholderlist_param_t *phldlist, msgqueue_param_t *msgqueue, Byte8_t *binOffset);
289 void enqueue_boxcontents( int meta_id, boxcontents_param_t *boxcontents, msgqueue_param_t *msgqueue, Byte8_t *binOffset);
290 
enqueue_metadata(int meta_id,msgqueue_param_t * msgqueue)291 void enqueue_metadata( int meta_id, msgqueue_param_t *msgqueue)
292 {
293   metadatalist_param_t *metadatalist;
294   metadata_param_t *metadata;
295   Byte8_t binOffset;
296 
297   metadatalist = msgqueue->cachemodel->target->codeidx->metadatalist;
298   metadata = search_metadata( meta_id, metadatalist);
299 
300   if( !metadata){
301     fprintf( FCGI_stderr, "Error: metadata-bin %d not found\n", meta_id);
302     return;
303   }
304   binOffset = 0;
305 
306   if( metadata->boxlist)
307     enqueue_box( meta_id, metadata->boxlist, msgqueue, &binOffset);
308 
309   if( metadata->placeholderlist)
310     enqueue_phld( meta_id, metadata->placeholderlist, msgqueue, &binOffset);
311 
312   if( metadata->boxcontents)
313     enqueue_boxcontents( meta_id, metadata->boxcontents, msgqueue, &binOffset);
314 
315   msgqueue->last->last_byte = true;
316 }
317 
318 message_param_t * gene_metamsg( int meta_id, Byte8_t binoffset, Byte8_t length, Byte8_t res_offset, placeholder_param_t *phld, Byte8_t csn);
319 
enqueue_box(int meta_id,boxlist_param_t * boxlist,msgqueue_param_t * msgqueue,Byte8_t * binOffset)320 void enqueue_box( int meta_id, boxlist_param_t *boxlist, msgqueue_param_t *msgqueue, Byte8_t *binOffset)
321 {
322   box_param_t *box;
323   message_param_t *msg;
324 
325   box = boxlist->first;
326   while( box){
327     msg = gene_metamsg( meta_id, *binOffset, box->length, box->offset, NULL, msgqueue->cachemodel->target->csn);
328     enqueue_message( msg, msgqueue);
329 
330     *binOffset += box->length;
331     box = box->next;
332   }
333 }
334 
enqueue_phld(int meta_id,placeholderlist_param_t * phldlist,msgqueue_param_t * msgqueue,Byte8_t * binOffset)335 void enqueue_phld( int meta_id, placeholderlist_param_t *phldlist, msgqueue_param_t *msgqueue, Byte8_t *binOffset)
336 {
337   placeholder_param_t *phld;
338   message_param_t *msg;
339 
340   phld = phldlist->first;
341   while( phld){
342     msg = gene_metamsg( meta_id, *binOffset, phld->LBox, 0, phld, msgqueue->cachemodel->target->csn);
343     enqueue_message( msg, msgqueue);
344 
345     *binOffset += phld->LBox;
346     phld = phld->next;
347   }
348 }
349 
enqueue_boxcontents(int meta_id,boxcontents_param_t * boxcontents,msgqueue_param_t * msgqueue,Byte8_t * binOffset)350 void enqueue_boxcontents( int meta_id, boxcontents_param_t *boxcontents, msgqueue_param_t *msgqueue, Byte8_t *binOffset)
351 {
352   message_param_t *msg;
353 
354   msg = gene_metamsg( meta_id, *binOffset, boxcontents->length, boxcontents->offset, NULL, msgqueue->cachemodel->target->csn);
355   enqueue_message( msg, msgqueue);
356 
357   *binOffset += boxcontents->length;
358 }
359 
gene_metamsg(int meta_id,Byte8_t binOffset,Byte8_t length,Byte8_t res_offset,placeholder_param_t * phld,Byte8_t csn)360 message_param_t * gene_metamsg( int meta_id, Byte8_t binOffset, Byte8_t length, Byte8_t res_offset, placeholder_param_t *phld, Byte8_t csn)
361 {
362   message_param_t *msg;
363 
364   msg = (message_param_t *)malloc( sizeof(message_param_t));
365 
366   msg->last_byte = false;
367   msg->in_class_id = meta_id;
368   msg->class_id = METADATA_MSG;
369   msg->csn = csn;
370   msg->bin_offset = binOffset;
371   msg->length = length;
372   msg->aux = 0; /* non exist*/
373   msg->res_offset = res_offset;
374   msg->phld = phld;
375   msg->next = NULL;
376 
377   return msg;
378 }
379 
enqueue_message(message_param_t * msg,msgqueue_param_t * msgqueue)380 void enqueue_message( message_param_t *msg, msgqueue_param_t *msgqueue)
381 {
382   if( msgqueue->first)
383     msgqueue->last->next = msg;
384   else
385     msgqueue->first = msg;
386 
387   msgqueue->last = msg;
388 }
389 
390 void add_bin_id_vbas_stream( Byte_t bb, Byte_t c, Byte8_t in_class_id, int tmpfd);
391 void add_vbas_stream( Byte8_t code, int tmpfd);
392 void add_body_stream( message_param_t *msg, int fd, int tmpfd);
393 void add_placeholder_stream( placeholder_param_t *phld, int tmpfd);
394 
recons_stream_from_msgqueue(msgqueue_param_t * msgqueue,int tmpfd)395 void recons_stream_from_msgqueue( msgqueue_param_t *msgqueue, int tmpfd)
396 {
397   message_param_t *msg;
398   Byte8_t class_id, csn;
399   Byte_t bb, c;
400 
401   if( !(msgqueue))
402     return;
403 
404   msg = msgqueue->first;
405   class_id = -1;
406   csn = -1;
407   while( msg){
408     if( msg->csn == csn){
409       if( msg->class_id == class_id)
410 	bb = 1;
411       else{
412 	bb = 2;
413 	class_id = msg->class_id;
414       }
415     }
416     else{
417       bb = 3;
418       class_id = msg->class_id;
419       csn = msg->csn;
420     }
421 
422     c = msg->last_byte ? 1 : 0;
423 
424     add_bin_id_vbas_stream( bb, c, msg->in_class_id, tmpfd);
425 
426     if( bb >= 2)
427       add_vbas_stream( class_id, tmpfd);
428     if (bb == 3)
429       add_vbas_stream( csn, tmpfd);
430 
431     add_vbas_stream( msg->bin_offset, tmpfd);
432     add_vbas_stream (msg->length, tmpfd);
433 
434     if( msg->class_id%2) /* Aux is present only if the id is odd*/
435       add_vbas_stream( msg->aux, tmpfd);
436 
437     if( msg->phld)
438       add_placeholder_stream( msg->phld, tmpfd);
439     else
440       add_body_stream( msg, msgqueue->cachemodel->target->fd, tmpfd);
441 
442     msg = msg->next;
443   }
444 }
445 
446 void add_vbas_with_bytelen_stream( Byte8_t code, int bytelength, int tmpfd);
447 void print_binarycode( Byte8_t n, int segmentlen);
448 
add_bin_id_vbas_stream(Byte_t bb,Byte_t c,Byte8_t in_class_id,int tmpfd)449 void add_bin_id_vbas_stream( Byte_t bb, Byte_t c, Byte8_t in_class_id, int tmpfd)
450 {
451   int bytelength;
452   Byte8_t tmp;
453 
454   /* A.2.3 In-class identifiers */
455   /* 7k-3bits, where k is the number of bytes in the VBAS*/
456   bytelength = 1;
457   tmp = in_class_id >> 4;
458   while( tmp){
459     bytelength ++;
460     tmp >>= 7;
461   }
462 
463   in_class_id |= (((bb & 3) << 5) | (c & 1) << 4) << ((bytelength-1)*7);
464 
465   add_vbas_with_bytelen_stream( in_class_id, bytelength, tmpfd);
466 }
467 
add_vbas_stream(Byte8_t code,int tmpfd)468 void add_vbas_stream( Byte8_t code, int tmpfd)
469 {
470   int bytelength;
471   Byte8_t tmp;
472 
473   bytelength = 1;
474   tmp = code;
475   while( tmp >>= 7)
476     bytelength ++;
477 
478   add_vbas_with_bytelen_stream( code, bytelength, tmpfd);
479 }
480 
add_vbas_with_bytelen_stream(Byte8_t code,int bytelength,int tmpfd)481 void add_vbas_with_bytelen_stream( Byte8_t code, int bytelength, int tmpfd)
482 {
483   int n;
484   Byte8_t seg;
485 
486   n = bytelength - 1;
487   while( n >= 0) {
488     seg = ( code >> (n*7)) & 0x7f;
489     if( n)
490       seg |= 0x80;
491     if( write( tmpfd, ( Byte4_t *)&seg, 1) != 1){
492       fprintf( FCGI_stderr, "Error: failed to write vbas\n");
493       return;
494     }
495     n--;
496   }
497 }
498 
add_body_stream(message_param_t * msg,int fd,int tmpfd)499 void add_body_stream( message_param_t *msg, int fd, int tmpfd)
500 {
501   Byte_t *data;
502 
503   if( !(data = fetch_bytes( fd, msg->res_offset, msg->length))){
504     fprintf( FCGI_stderr, "Error: fetch_bytes in add_body_stream()\n");
505     return;
506   }
507 
508   if( write( tmpfd, data, msg->length) < 1){
509     free( data);
510     fprintf( FCGI_stderr, "Error: fwrite in add_body_stream()\n");
511     return;
512   }
513   free(data);
514 }
515 
516 void add_bigendian_bytestream( Byte8_t code, int bytelength, int tmpfd);
517 
add_placeholder_stream(placeholder_param_t * phld,int tmpfd)518 void add_placeholder_stream( placeholder_param_t *phld, int tmpfd)
519 {
520   add_bigendian_bytestream( phld->LBox, 4, tmpfd);
521   if( write( tmpfd, phld->TBox, 4) < 1){
522     fprintf( FCGI_stderr, "Error: fwrite in add_placeholder_stream()\n");
523     return;
524   }
525   add_bigendian_bytestream( phld->Flags, 4, tmpfd);
526   add_bigendian_bytestream( phld->OrigID, 8, tmpfd);
527 
528   if( write( tmpfd, phld->OrigBH, phld->OrigBHlen) < 1){
529     fprintf( FCGI_stderr, "Error: fwrite in add_placeholder_stream()\n");
530     return;
531   }
532 }
533 
add_bigendian_bytestream(Byte8_t code,int bytelength,int tmpfd)534 void add_bigendian_bytestream( Byte8_t code, int bytelength, int tmpfd)
535 {
536   int n;
537   Byte8_t seg;
538 
539   n = bytelength - 1;
540   while( n >= 0) {
541     seg = ( code >> (n*8)) & 0xff;
542     if( write( tmpfd, ( Byte4_t *)&seg, 1) != 1){
543       fprintf( FCGI_stderr, "ERROR: failed to write bigendian_bytestream\n");
544       return;
545     }
546     n--;
547   }
548 }
549 
print_binarycode(Byte8_t n,int segmentlen)550 void print_binarycode( Byte8_t n, int segmentlen)
551 {
552   char buf[256];
553   int i=0, j, k;
554 
555   do{
556     buf[i++] = n%2 ? '1' : '0';
557   }while((n=n/2));
558 
559   for( j=segmentlen-1; j>=i; j--)
560     putchar('0');
561 
562   for( j=i-1, k=0; j>=0; j--, k++){
563     putchar( buf[j]);
564     if( !((k+1)%segmentlen))
565       printf(" ");
566   }
567   printf("\n");
568 }
569 
570 Byte_t * parse_bin_id_vbas( Byte_t *streamptr, Byte_t *bb, Byte_t *c, Byte8_t *in_class_id);
571 Byte_t * parse_vbas( Byte_t *streamptr, Byte8_t *elem);
572 
parse_JPIPstream(Byte_t * JPIPstream,Byte8_t streamlen,Byte8_t offset,msgqueue_param_t * msgqueue)573 void parse_JPIPstream( Byte_t *JPIPstream, Byte8_t streamlen, Byte8_t offset, msgqueue_param_t *msgqueue)
574 {
575   Byte_t *ptr;  /* stream pointer*/
576   message_param_t *msg;
577   Byte_t bb, c;
578   Byte8_t class_id, csn;
579 
580   class_id = -1; /* dummy*/
581   csn = -1;
582   ptr = JPIPstream;
583   while( (Byte8_t)(ptr-JPIPstream) < streamlen){
584     msg = (message_param_t *)malloc( sizeof(message_param_t));
585 
586     ptr = parse_bin_id_vbas( ptr, &bb, &c, &msg->in_class_id);
587 
588     msg->last_byte   = c == 1 ? true : false;
589 
590     if( bb >= 2)
591       ptr = parse_vbas( ptr, &class_id);
592 
593     msg->class_id = class_id;
594 
595     if (bb == 3)
596       ptr = parse_vbas( ptr, &csn);
597     msg->csn = csn;
598 
599     ptr = parse_vbas( ptr, &msg->bin_offset);
600     ptr = parse_vbas( ptr, &msg->length);
601 
602     if( msg->class_id%2) /* Aux is present only if the id is odd*/
603       ptr = parse_vbas( ptr, &msg->aux);
604     else
605       msg->aux = 0;
606 
607     msg->res_offset = ptr-JPIPstream+offset;
608     msg->phld = NULL;
609     msg->next = NULL;
610 
611     if(msgqueue->first)
612       msgqueue->last->next = msg;
613     else
614       msgqueue->first = msg;
615     msgqueue->last = msg;
616 
617     ptr += msg->length;
618   }
619 }
620 
621 void parse_metadata( metadata_param_t *metadata, message_param_t *msg, Byte_t *stream);
622 
parse_metamsg(msgqueue_param_t * msgqueue,Byte_t * stream,Byte8_t streamlen,metadatalist_param_t * metadatalist)623 void parse_metamsg( msgqueue_param_t *msgqueue, Byte_t *stream, Byte8_t streamlen, metadatalist_param_t *metadatalist)
624 {
625   message_param_t *msg;
626   (void)streamlen;
627 
628   if( metadatalist == NULL)
629     return;
630 
631   msg = msgqueue->first;
632   while( msg){
633     if( msg->class_id == METADATA_MSG){
634       metadata_param_t *metadata = gene_metadata( msg->in_class_id, NULL, NULL, NULL);
635       insert_metadata_into_list( metadata, metadatalist);
636       parse_metadata( metadata, msg, stream+msg->res_offset);
637     }
638     msg = msg->next;
639   }
640 }
641 
642 placeholder_param_t * parse_phld( Byte_t *datastream, Byte8_t metalength);
643 
parse_metadata(metadata_param_t * metadata,message_param_t * msg,Byte_t * datastream)644 void parse_metadata( metadata_param_t *metadata, message_param_t *msg, Byte_t *datastream)
645 {
646   box_param_t *box;
647   placeholder_param_t *phld;
648   char *boxtype = (char *)(datastream+4);
649 
650   msg->phld = NULL;
651 
652   if( strncmp( boxtype, "phld", 4) == 0){
653     if( !metadata->placeholderlist)
654 	metadata->placeholderlist = gene_placeholderlist();
655 
656     phld = parse_phld( datastream, msg->length);
657     msg->phld = phld;
658     insert_placeholder_into_list( phld, metadata->placeholderlist);
659   }
660   else if( isalpha(boxtype[0]) && isalpha(boxtype[1]) &&
661 	   (isalnum(boxtype[2])||isspace(boxtype[2])) &&
662 	   (isalpha(boxtype[3])||isspace(boxtype[3]))){
663     if( !metadata->boxlist)
664       metadata->boxlist = gene_boxlist();
665 
666     box = gene_boxbyOffinStream( datastream, msg->res_offset);
667     insert_box_into_list( box, metadata->boxlist);
668   }
669   else
670     metadata->boxcontents = gene_boxcontents( msg->res_offset, msg->length);
671 }
672 
parse_phld(Byte_t * datastream,Byte8_t metalength)673 placeholder_param_t * parse_phld( Byte_t *datastream, Byte8_t metalength)
674 {
675   placeholder_param_t *phld;
676 
677   phld = (placeholder_param_t *)malloc( sizeof(placeholder_param_t));
678 
679   phld->LBox = big4( datastream);
680   strncpy( phld->TBox, "phld", 4);
681   phld->Flags = big4( datastream+8);
682   phld->OrigID = big8( datastream+12);
683   phld->OrigBHlen = metalength - 20;
684   phld->OrigBH = (Byte_t *)malloc(phld->OrigBHlen);
685   memcpy( phld->OrigBH, datastream+20, phld->OrigBHlen);
686   phld->next = NULL;
687 
688   return phld;
689 }
690 
parse_bin_id_vbas(Byte_t * streamptr,Byte_t * bb,Byte_t * c,Byte8_t * in_class_id)691 Byte_t * parse_bin_id_vbas( Byte_t *streamptr, Byte_t *bb, Byte_t *c, Byte8_t *in_class_id)
692 {
693   Byte_t code;
694   Byte_t *ptr;
695 
696   ptr = streamptr;
697   code = *(ptr++);
698 
699   *bb = (code >> 5) & 3;
700   *c  = (code >> 4) & 1;
701 
702   *in_class_id = code & 15;
703 
704   while(code >> 7){
705     code = *(ptr++);
706     *in_class_id = (*in_class_id << 7) | (code & 0x7f);
707   }
708   return ptr;
709 }
710 
parse_vbas(Byte_t * streamptr,Byte8_t * elem)711 Byte_t * parse_vbas( Byte_t *streamptr, Byte8_t *elem)
712 {
713   Byte_t code;
714   Byte_t *ptr;
715 
716   *elem = 0;
717   ptr = streamptr;
718   do{
719     code = *(ptr++);
720     *elem = (*elem << 7) | (code & 0x7f);
721   }while(code >> 7);
722 
723   return ptr;
724 }
725 
delete_message_in_msgqueue(message_param_t ** msg,msgqueue_param_t * msgqueue)726 void delete_message_in_msgqueue( message_param_t **msg, msgqueue_param_t *msgqueue)
727 {
728   message_param_t *ptr;
729 
730   if( !(*msg))
731     return;
732 
733   if( *msg == msgqueue->first)
734     msgqueue->first = (*msg)->next;
735   else{
736     ptr = msgqueue->first;
737     while( ptr->next != *msg){
738       ptr=ptr->next;
739     }
740 
741     ptr->next = (*msg)->next;
742 
743     if( *msg == msgqueue->last)
744       msgqueue->last = ptr;
745   }
746   free( *msg);
747 }
748