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