added tid request support to JPIP client and JPIP server quit request
[openjpeg.git] / applications / jpip / libopenjpip / box_manager.c
1 /*
2  * $Id: box_manager.c 44 2011-02-15 12:32:29Z 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  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include <stdio.h>
32 #include <string.h>
33 #include <stdlib.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <unistd.h>
37 #include <ctype.h>
38 #include "box_manager.h"
39
40 #ifdef SERVER
41 #include "fcgi_stdio.h"
42 #define logstream FCGI_stdout
43 #else
44 #define FCGI_stdout stdout
45 #define FCGI_stderr stderr
46 #define logstream stderr
47 #endif //SERVER
48
49 boxlist_param_t * gene_boxlist()
50 {
51   boxlist_param_t *boxlist;
52
53   boxlist = (boxlist_param_t *)malloc( sizeof(boxlist_param_t));
54   
55   boxlist->first = NULL;
56   boxlist->last  = NULL;
57
58   return boxlist;
59 }
60
61 boxlist_param_t * get_boxstructure( int fd, Byte8_t offset, Byte8_t length)
62 {
63   boxlist_param_t *boxlist;
64   box_param_t *box;
65   int pos;
66   
67   boxlist = NULL;
68   pos = offset;
69   do{
70     if(!(box = gene_boxbyOffset( fd, pos)))
71       break;
72     
73     pos += box->length;
74     
75     if( !boxlist)
76       boxlist = gene_boxlist();
77     insert_box_into_list( box, boxlist);
78   }while( pos < offset+length);
79
80   return boxlist;
81 }
82
83 box_param_t * gene_boxbyOffset( int fd, Byte8_t offset)
84 {
85   Byte_t *data;
86   Byte8_t boxlen, headlen;
87   char *boxtype;
88   box_param_t *box;
89
90   // read LBox and TBox
91   if(!(data = fetch_bytes( fd, offset, 8))){
92     fprintf( FCGI_stderr, "Error: error in gene_boxbyOffset( %d, %lld)\n", fd, offset);
93     return NULL;
94   }
95   
96   headlen = 8;
97   boxlen = (Byte8_t)big4(data);
98   boxtype = (char *)(data+4);  
99
100   // box type constraint
101   if( !isalpha(boxtype[0]) || !isalpha(boxtype[1]) ||
102       (!isalnum(boxtype[2])&&!isblank(boxtype[2])) ||
103       (!isalpha(boxtype[3])&&!isblank(boxtype[3]))){
104     free( data);
105     return NULL;
106   }
107   
108   if( boxlen == 1){
109     Byte_t *data2;
110     headlen = 16;
111     // read XLBox
112     if((data2 = fetch_bytes( fd, offset+8, 8))){
113       boxlen = big8(data2);
114       free(data2);
115     }
116     else{
117       fprintf( FCGI_stderr, "Error: error in gene_boxbyOffset( %d, %lld)\n", fd, offset);
118       free( data);
119       return NULL;
120     }
121   }
122   box = (box_param_t *)malloc( sizeof( box_param_t));
123   box->fd = fd;
124   box->offset = offset;
125   box->headlen = headlen;
126   box->length = boxlen;
127   strncpy( box->type, boxtype, 4);
128   box->next = NULL;
129   free( data);
130   return box;
131 }
132
133 box_param_t * gene_boxbyOffinStream( Byte_t *stream, Byte8_t offset)
134 {
135   Byte8_t boxlen, headlen;
136   char *boxtype;
137   box_param_t *box;
138
139   // read LBox and TBox
140   headlen = 8;
141   boxlen = (Byte8_t)big4( stream);
142   boxtype = (char *)( stream+4);  
143
144   // box type constraint
145   if( !isalpha(boxtype[0]) || !isalpha(boxtype[1]) ||
146       (!isalnum(boxtype[2])&&!isblank(boxtype[2])) ||
147       (!isalpha(boxtype[3])&&!isblank(boxtype[3]))){
148     return NULL;
149   }
150   
151   if( boxlen == 1){
152     headlen = 16;
153     boxlen = big8( stream+8); // read XLBox
154   }
155   box = (box_param_t *)malloc( sizeof( box_param_t));
156   box->fd = -1;
157   box->offset = offset;
158   box->headlen = headlen;
159   box->length = boxlen;
160   strncpy( box->type, boxtype, 4);
161   box->next = NULL;
162
163   return box;
164 }
165
166
167 box_param_t * gene_boxbyType( int fd, Byte8_t offset, Byte8_t length, char TBox[])
168 {
169   Byte8_t pos;
170   Byte_t *data;
171   Byte8_t boxlen, headlen;
172   char *boxtype;
173   box_param_t *foundbox;
174
175   
176   if( length==0){ // set the max length
177     struct stat sb;
178     if( fstat( fd, &sb) == -1){
179       fprintf( FCGI_stdout, "Reason: Target broken (fstat error)\r\n");
180       return NULL;
181     }
182     length = (Byte8_t)sb.st_size - offset;
183   }
184
185   pos = offset;
186   while( pos < offset+length-7){ // LBox+TBox-1=7
187     
188     // read LBox and TBox
189     if((data = fetch_bytes( fd, pos, 8))){
190       headlen = 8;
191       boxlen = (Byte8_t)big4(data);
192       boxtype = (char *)(data+4);
193
194       if( boxlen == 1){
195         Byte_t *data2;
196         headlen = 16;
197         // read XLBox
198         if((data2 = fetch_bytes( fd, pos+8, 8))){
199           boxlen = big8(data2);
200           free(data2);
201         }
202         else{
203           fprintf( FCGI_stderr, "Error: error in gene_boxbyType( %d, %lld, %lld, %s)\n", fd, offset, length, TBox);
204           return NULL;
205         }
206       }
207       if( strncmp ( boxtype, TBox, 4) == 0){
208         foundbox = (box_param_t *)malloc( sizeof( box_param_t));
209         foundbox->fd = fd;
210         foundbox->offset = pos;
211         foundbox->headlen = headlen;
212         foundbox->length = boxlen;
213         strncpy( foundbox->type, TBox, 4);
214         foundbox->next = NULL;
215         free( data);
216         return foundbox;
217       }
218       free( data);
219     }
220     else{
221       fprintf( FCGI_stderr, "Error: error in gene_boxbyType( %d, %lld, %lld, %s)\n", fd, offset, length, TBox);
222       return NULL;
223     }
224     pos+= boxlen;
225   }
226   fprintf( FCGI_stderr, "Error: Box %s not found\n", TBox);
227
228   return NULL;
229 }
230
231 box_param_t * gene_boxbyTypeinStream( Byte_t *stream, Byte8_t offset, Byte8_t length, char TBox[])
232 {
233   Byte8_t pos;
234   Byte_t *data;
235   Byte8_t boxlen, headlen;
236   char *boxtype;
237   box_param_t *foundbox;
238
239   
240   if( length<=0){ // set the max length
241     fprintf( FCGI_stderr, "func gene_boxbyTypeinStream(), max length must be more than 0\n");
242     return NULL;
243   }
244   
245   pos = offset;
246   while( pos < offset+length-7){ // LBox+TBox-1=7
247     
248     // read LBox and TBox
249     data = stream + pos;
250     headlen = 8;
251     boxlen = (Byte8_t)big4(data);
252     boxtype = (char *)(data+4);
253    
254     if( boxlen == 1){
255       // read XLBox
256       headlen = 16;
257       boxlen = big8( data+8);
258     }
259
260     if( strncmp ( boxtype, TBox, 4) == 0){
261       foundbox = (box_param_t *)malloc( sizeof( box_param_t));
262       foundbox->fd = -1;
263       foundbox->offset = pos;
264       foundbox->headlen = headlen;
265       foundbox->length = boxlen;
266       strncpy( foundbox->type, TBox, 4);
267       foundbox->next = NULL;
268       return foundbox;
269     }
270     pos+= boxlen;
271   }
272   fprintf( FCGI_stderr, "Error: Box %s not found\n", TBox);
273   
274   return NULL;
275 }
276
277 box_param_t * gene_childboxbyOffset( box_param_t *superbox, Byte8_t offset)
278 {
279   return gene_boxbyOffset( superbox->fd, get_DBoxoff( superbox)+offset);
280 }
281
282 box_param_t * gene_childboxbyType( box_param_t *superbox, Byte8_t offset, char TBox[])
283 {
284   return gene_boxbyType( superbox->fd, get_DBoxoff( superbox)+offset, get_DBoxlen( superbox)-offset, TBox);
285 }
286
287 Byte8_t get_DBoxoff( box_param_t *box)
288 {
289   return box->offset+box->headlen;
290 }
291
292 Byte8_t get_DBoxlen( box_param_t *box)
293 {
294   return box->length-box->headlen;
295 }
296
297 Byte_t * fetch_headbytes( box_param_t *box)
298 {
299   return fetch_bytes( box->fd, box->offset, box->headlen);
300 }
301
302 Byte_t * fetch_DBoxbytes( box_param_t *box, long offset, int size)
303 {
304   return fetch_bytes( box->fd, get_DBoxoff( box)+offset, size);
305 }
306
307 Byte_t fetch_DBox1byte( box_param_t *box, long offset)
308 {
309   return fetch_1byte( box->fd, get_DBoxoff( box)+offset);
310 }
311
312 Byte2_t fetch_DBox2bytebigendian( box_param_t *box, long offset)
313 {
314   return fetch_2bytebigendian( box->fd, get_DBoxoff( box)+offset);
315 }
316
317 Byte4_t fetch_DBox4bytebigendian( box_param_t *box, long offset)
318 {
319   return fetch_4bytebigendian( box->fd, get_DBoxoff( box)+offset);
320 }
321
322 Byte8_t fetch_DBox8bytebigendian( box_param_t *box, long offset)
323 {
324   return fetch_8bytebigendian( box->fd, get_DBoxoff( box)+offset);
325 }
326
327 box_param_t * search_box( char type[], boxlist_param_t *boxlist)
328 {
329   box_param_t *foundbox;
330
331   foundbox = boxlist->first;
332   
333   while( foundbox != NULL){
334     
335     if( strncmp( type, foundbox->type, 4) == 0)
336       return foundbox;
337       
338     foundbox = foundbox->next;
339   }
340   fprintf( FCGI_stderr, "Error: Box %s not found\n", type);
341
342   return NULL;
343 }
344
345 void print_box( box_param_t *box)
346 {
347   fprintf( logstream, "box info:\n"
348            "\t type: %.4s\n"
349            "\t offset: %lld %#llx\n" 
350            "\t header length: %d\n"
351            "\t length: %lld %#llx\n", box->type, box->offset, box->offset, box->headlen, box->length, box->length);
352 }
353
354 void print_allbox( boxlist_param_t *boxlist)
355 {
356   box_param_t *ptr;
357
358   if( !boxlist)
359     return;
360
361   ptr = boxlist->first;
362   if( !ptr)
363     fprintf( logstream, "no box\n");
364
365   fprintf( logstream, "all box info: \n");
366   while( ptr != NULL){
367     print_box( ptr);
368     ptr=ptr->next;
369   }
370 }
371
372 void delete_box_in_list( box_param_t **box, boxlist_param_t *boxlist)
373 {
374   box_param_t *ptr;
375
376   if( *box == boxlist->first)
377     boxlist->first = (*box)->next;
378   else{
379     ptr = boxlist->first;
380     while( ptr->next != *box){
381       ptr=ptr->next;
382     }
383     ptr->next = (*box)->next;
384     
385     if( *box == boxlist->last)
386       boxlist->last = ptr;
387   }
388   free( *box);
389 }
390
391 void delete_box_in_list_by_type( char type[], boxlist_param_t *boxlist)
392 {
393   box_param_t *box;
394
395   box = search_box( type, boxlist);
396   delete_box_in_list( &box, boxlist);
397 }
398
399 void delete_boxlist( boxlist_param_t **boxlist)
400 {
401   box_param_t *boxPtr, *boxNext;
402
403   if(!(*boxlist))
404     return;
405   
406   boxPtr = (*boxlist)->first;
407   while( boxPtr != NULL){
408     boxNext=boxPtr->next;
409     free( boxPtr);
410     boxPtr=boxNext;
411   }
412   free( *boxlist);
413 }
414
415 void insert_box_into_list( box_param_t *box, boxlist_param_t *boxlist)
416 {
417   if( boxlist->first)
418     boxlist->last->next = box;
419   else
420     boxlist->first = box;
421   boxlist->last = box;
422 }