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