[1.5][JPIP] added get_filesize()
[openjpeg.git] / applications / jpip / libopenjpip / openjpip.c
1 /*
2  * $Id$
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 <stdlib.h>
32 #include "openjpip.h"
33 #include "jpip_parser.h"
34 #include "channel_manager.h"
35
36 #include <stdio.h>
37 #include "dec_clientmsg_handler.h"
38 #include "jpipstream_manager.h"
39
40 #include <string.h>
41 #include <sys/types.h>
42 #include <sys/stat.h>
43 #include <fcntl.h>
44 #include <unistd.h>
45 #include "jp2k_encoder.h"
46
47 server_record_t * init_JPIPserver()
48 {
49   server_record_t *record = (server_record_t *)malloc( sizeof(server_record_t));
50   
51   record->sessionlist = gene_sessionlist();
52   record->targetlist  = gene_targetlist();
53   
54   return record;
55 }
56
57 void terminate_JPIPserver( server_record_t **rec)
58 {
59   delete_sessionlist( &(*rec)->sessionlist);
60   delete_targetlist( &(*rec)->targetlist);
61
62   free( *rec);
63 }
64
65 QR_t * parse_querystring( char *query_string)
66 {
67   QR_t *qr;
68
69   qr = (QR_t *)malloc( sizeof(QR_t));
70     
71   qr->query = parse_query( query_string);
72   
73   qr->msgqueue = NULL;
74
75   return qr;
76 }
77
78 bool process_JPIPrequest( server_record_t *rec, QR_t *qr)
79 {
80   target_param_t *target = NULL;
81   session_param_t *cursession = NULL;
82   channel_param_t *curchannel = NULL;
83
84   if( qr->query->target[0] != '\0' || qr->query->tid[0] != '\0'){
85     if( !identify_target( *(qr->query), rec->targetlist, &target))
86       return false;
87   }
88
89   if( qr->query->cid[0] != '\0'){
90     if( !associate_channel( *(qr->query), rec->sessionlist, &cursession, &curchannel))
91       return false;
92   }
93
94   if( qr->query->cnew){
95     if( !open_channel( *(qr->query), rec->sessionlist, target, &cursession, &curchannel))
96       return false;
97   }
98   if( qr->query->cclose[0][0] != '\0')
99     if( !close_channel( *(qr->query), rec->sessionlist, &cursession, &curchannel))
100       return false;
101   
102   if( (qr->query->fx > 0 && qr->query->fy > 0) || qr->query->box_type[0][0] != 0)
103     if( !gene_JPIPstream( *(qr->query), target, cursession, curchannel, &qr->msgqueue))
104       return false;
105   
106   return true;
107 }
108
109 void send_responsedata( QR_t *qr)
110 {
111   // Currently HTTP support only, find a way for TCP, UDP case
112   emit_stream_from_msgqueue( qr->msgqueue);
113 }
114
115 void end_QRprocess( server_record_t *rec, QR_t **qr)
116 {
117   // TODO: record client preferences if necessary
118   
119   delete_query( &((*qr)->query));
120   delete_msgqueue( &((*qr)->msgqueue));
121   free( *qr);
122 }
123
124 void local_log( bool query, bool messages, bool sessions, bool targets, QR_t *qr, server_record_t *rec)
125 {
126   if( query)
127     print_queryparam( *qr->query);
128
129   if( messages)
130     print_msgqueue( qr->msgqueue);
131
132   if( sessions)
133     print_allsession( rec->sessionlist);
134   
135   if( targets)
136     print_alltarget( rec->targetlist);
137 }
138
139 #ifndef SERVER
140
141 dec_server_record_t * init_dec_server()
142 {
143   dec_server_record_t *record = (dec_server_record_t *)malloc( sizeof(dec_server_record_t));
144
145   record->cachelist = gene_cachelist();
146   record->jpipstream = NULL;
147   record->jpipstreamlen = 0;
148   record->msgqueue = gene_msgqueue( true, NULL);
149   record->listening_socket = open_listeningsocket();
150
151   return record;
152 }
153
154 void terminate_dec_server( dec_server_record_t **rec)
155 {
156   delete_cachelist( &(*rec)->cachelist);  
157   free( (*rec)->jpipstream);
158   
159   if( (*rec)->msgqueue)
160     delete_msgqueue( &((*rec)->msgqueue));
161
162   if( close_socket( (*rec)->listening_socket) != 0)
163     perror("close");
164   
165   free( *rec);
166 }
167
168 client_t accept_connection( dec_server_record_t *rec)
169 {
170   client_t client;
171   
172   client = accept_socket( rec->listening_socket);
173   if( client == -1)
174     fprintf( stderr, "error: failed to connect to client\n");
175   
176   return client;
177 }
178
179 bool handle_clientreq( client_t client, dec_server_record_t *rec)
180 {
181   bool quit = false;
182   msgtype_t msgtype = identify_clientmsg( client);
183   
184   switch( msgtype){
185   case JPIPSTREAM:
186     handle_JPIPstreamMSG( client, rec->cachelist, &rec->jpipstream, &rec->jpipstreamlen, rec->msgqueue);
187     break;
188       
189   case PNMREQ:
190     handle_PNMreqMSG( client, rec->jpipstream, rec->msgqueue, rec->cachelist);
191     break;
192     
193   case XMLREQ:
194     handle_XMLreqMSG( client, rec->jpipstream, rec->cachelist);
195     break;
196
197   case TIDREQ:
198     handle_TIDreqMSG( client, rec->cachelist);
199     break;
200                                                 
201   case CIDREQ:
202     handle_CIDreqMSG( client, rec->cachelist);
203     break;
204
205   case CIDDST:
206     handle_dstCIDreqMSG( client, rec->cachelist);
207     break;
208     
209   case SIZREQ:
210     handle_SIZreqMSG( client, rec->jpipstream, rec->msgqueue, rec->cachelist);
211     break;
212
213   case JP2SAVE:
214     handle_JP2saveMSG( client, rec->cachelist, rec->msgqueue, rec->jpipstream);
215     break;
216
217   case QUIT:
218     quit = true;
219     save_codestream( rec->jpipstream, rec->jpipstreamlen, "jpt");
220     break;
221   case MSGERROR:
222     break;
223   }
224         
225   fprintf( stderr, "\t end of the connection\n\n");
226   if( close_socket(client) != 0){
227     perror("close");
228     return false;
229   }
230   if( quit)
231     return false;
232
233   return true;
234 }
235
236
237 jpip_dec_param_t * init_jpipdecoder( bool jp2)
238 {
239   jpip_dec_param_t *dec;
240   
241   dec = (jpip_dec_param_t *)calloc( 1, sizeof(jpip_dec_param_t));
242
243   dec->msgqueue = gene_msgqueue( true, NULL);
244   
245   if( jp2)
246     dec->metadatalist = gene_metadatalist();
247
248   return dec;
249 }
250
251
252 bool fread_jpip( char fname[], jpip_dec_param_t *dec)
253 {
254   int infd;
255
256   if(( infd = open( fname, O_RDONLY)) == -1){
257     fprintf( stderr, "file %s not exist\n", fname);
258     return false;
259   }
260   
261   if(!(dec->jpiplen = get_filesize(infd)))
262     return false;
263   
264   dec->jpipstream = (Byte_t *)malloc( dec->jpiplen);
265
266   if( read( infd, dec->jpipstream, dec->jpiplen) != dec->jpiplen){
267     fprintf( stderr, "file reading error\n");
268     free( dec->jpipstream);
269     return false;
270   }
271
272   close(infd);
273
274   return true;
275 }
276
277 void decode_jpip( jpip_dec_param_t *dec)
278 {
279   parse_JPIPstream( dec->jpipstream, dec->jpiplen, 0, dec->msgqueue);
280
281   if( dec->metadatalist){ // JP2 encoding
282     parse_metamsg( dec->msgqueue, dec->jpipstream, dec->jpiplen, dec->metadatalist);
283     dec->ihdrbox = gene_ihdrbox( dec->metadatalist, dec->jpipstream);
284     
285     dec->jp2kstream = recons_jp2( dec->msgqueue, dec->jpipstream, dec->msgqueue->first->csn, &dec->jp2klen);
286   }
287   else // J2k encoding  
288     // Notice: arguments fw, fh need to be set for LRCP, PCRL, CPRL
289     dec->jp2kstream = recons_j2k( dec->msgqueue, dec->jpipstream, dec->msgqueue->first->csn, 0, 0, &dec->jp2klen);  
290 }
291
292 bool fwrite_jp2k( char fname[], jpip_dec_param_t *dec)
293 {
294   int outfd;
295   
296 #ifdef _WIN32
297   if(( outfd = open( fname, O_WRONLY|O_CREAT, _S_IREAD | _S_IWRITE)) == -1){
298 #else
299  if(( outfd = open( fname, O_WRONLY|O_CREAT, S_IRWXU|S_IRWXG)) == -1){
300 #endif
301    fprintf( stderr, "file %s open error\n", fname);
302    return false;
303  }
304   
305  if( write( outfd, dec->jp2kstream, dec->jp2klen) != dec->jp2klen)
306    fprintf( stderr, "j2k file write error\n");
307
308  close(outfd);
309
310  return true;
311 }
312
313 void output_log( bool messages, bool metadata, bool ihdrbox, jpip_dec_param_t *dec)
314 {
315   if( messages)
316     print_msgqueue( dec->msgqueue);
317
318   if( metadata)
319     print_allmetadata( dec->metadatalist);
320
321   if( ihdrbox){
322     printf("W*H: %d*%d\n", dec->ihdrbox->height, dec->ihdrbox->width);
323     printf("NC: %d, bpc: %d\n", dec->ihdrbox->nc, dec->ihdrbox->bpc);
324   }
325 }
326
327 void destroy_jpipdecoder( jpip_dec_param_t **dec)
328 {
329   free( (*dec)->jpipstream);
330   delete_msgqueue( &(*dec)->msgqueue);
331   if( (*dec)->metadatalist){
332     delete_metadatalist( &(*dec)->metadatalist);
333     free( (*dec)->ihdrbox);
334   }
335
336   free( (*dec)->jp2kstream);
337   free( *dec);
338 }
339
340 index_t * get_index_from_JP2file( int fd)
341 {
342   char *data;
343  
344   // Check resource is a JP family file.
345   if( lseek( fd, 0, SEEK_SET)==-1){
346     fprintf( stderr, "Error: File broken (lseek error)\n");
347     return NULL;
348   }
349   
350   data = (char *)malloc( 12); // size of header
351   if( read( fd, data, 12) != 12){
352     free( data);
353     fprintf( stderr, "Error: File broken (read error)\n");
354     return NULL;
355   }
356     
357   if( *data || *(data + 1) || *(data + 2) ||
358       *(data + 3) != 12 || strncmp (data + 4, "jP  \r\n\x87\n", 8)){
359     free( data);
360     fprintf( stderr, "Error: No JPEG 2000 Signature box in this file\n");
361     return NULL;
362   }
363   free( data);
364   
365   return parse_jp2file( fd);
366 }
367
368 void destroy_index( index_t **idx)
369 {
370   delete_index( idx);
371 }
372
373 void output_index( index_t *index)
374 {
375   print_index( *index);
376 }
377
378 #endif //SERVER