/* * $Id: opj_dec_server.c 46 2011-02-17 14:50:55Z kaori $ * * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium * Copyright (c) 2002-2011, Professor Benoit Macq * Copyright (c) 2010-2011, Kaori Hagihara * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /*! \file * \brief opj_dec_server is a server to decode JPT-stream and communicate locally with JPIP client, which is coded in java. * * \section impinst Implementing instructions * Launch opj_dec_server from a terminal in the same machine as JPIP client image viewers. \n * % ./opj_dec_server \n * Keep it alive as long as image viewers are open.\n * * To quite the opj_dec_server, send a message "quit" through the telnet.\n * % telnet localhost 5000\n * quit\n * Be sure all image viewers are closed.\n * Cache file in JPT format is stored in the working directly before it quites. * */ #include #include #include #include #include #include #include #include "byte_manager.h" #include "msgqueue_manager.h" #include "ihdrbox_manager.h" #include "imgsock_manager.h" #include "jptstream_manager.h" #include "cache_manager.h" //! maximum length of target name #define MAX_LENOFTARGET 128 //! maximum length of channel identifier #define MAX_LENOFCID 30 /** * handle JPTstream message * * @param[in] connected_socket socket descriptor * @param[in] cachelist cache list pointer * @param[in,out] jptstream address of jptstream pointer * @param[in,out] jptlen address of jptstream length * @param[in,out] msgqueue message queue pointer */ void handle_JPTstreamMSG( int connected_socket, cachelist_param_t *cachelist, Byte_t **jptstream, int *jptlen, msgqueue_param_t *msgqueue); /** * handle PNM request message * * @param[in] connected_socket socket descriptor * @param[in] jptstream jptstream pointer * @param[in] msgqueue message queue pointer * @param[in] cachelist cache list pointer */ void handle_PNMreqMSG( int connected_socket, Byte_t *jptstream, msgqueue_param_t *msgqueue, cachelist_param_t *cachelist); /** * handle XML request message * * @param[in] connected_socket socket descriptor * @param[in] jptstream address of caching jptstream pointer * @param[in] cachelist cache list pointer */ void handle_XMLreqMSG( int connected_socket, Byte_t *jptstream, cachelist_param_t *cachelist); /** * handle ChannelID request message * * @param[in] connected_socket socket descriptor * @param[in] cachelist cache list pointer */ void handle_CIDreqMSG( int connected_socket, cachelist_param_t *cachelist); /** * handle distroy ChannelID message * * @param[in] connected_socket socket descriptor * @param[in,out] cachelist cache list pointer */ void handle_dstCIDreqMSG( int connected_socket, cachelist_param_t *cachelist); /** * handle saving JP2 file request message * * @param[in] connected_socket socket descriptor * @param[in] cachelist cache list pointer * @param[in] msgqueue message queue pointer * @param[in] jptstream address of caching jptstream pointer */ void handle_JP2saveMSG( int connected_socket, cachelist_param_t *cachelist, msgqueue_param_t *msgqueue, Byte_t *jptstream); int main(int argc, char *argv[]){ int connected_socket; struct sockaddr_in peer_sin; Byte_t *jptstream = NULL; int jptlen = 0; msgqueue_param_t *msgqueue = gene_msgqueue( true, NULL); bool quit = false; int listening_socket = open_listeningsocket(); socklen_t addrlen = sizeof(peer_sin); cachelist_param_t *cachelist = gene_cachelist(); while(( connected_socket = accept(listening_socket, (struct sockaddr *)&peer_sin, &addrlen))!=-1 ){ msgtype_t msgtype = identify_clientmsg( connected_socket); switch( msgtype){ case JPTSTREAM: handle_JPTstreamMSG( connected_socket, cachelist, &jptstream, &jptlen, msgqueue); break; case PNMREQ: handle_PNMreqMSG( connected_socket, jptstream, msgqueue, cachelist); break; case XMLREQ: handle_XMLreqMSG( connected_socket, jptstream, cachelist); break; case CIDREQ: handle_CIDreqMSG( connected_socket, cachelist); break; case CIDDST: handle_dstCIDreqMSG( connected_socket, cachelist); break; case JP2SAVE: handle_JP2saveMSG( connected_socket, cachelist, msgqueue, jptstream); break; case QUIT: quit = true; break; case ERROR: break; } printf("cut the connection. listening to port\n"); if( close(connected_socket) == -1 ){ perror("close"); return -1; } if( quit) break; } if( close(listening_socket) == -1 ){ perror("close"); return -1; } delete_cachelist( &cachelist); if( msgqueue) delete_msgqueue( &msgqueue); save_codestream( jptstream, jptlen, "jpt"); free( jptstream); return 0; } void handle_JPTstreamMSG( int connected_socket, cachelist_param_t *cachelist, Byte_t **jptstream, int *jptlen, msgqueue_param_t *msgqueue) { Byte_t *newjptstream; int newjptlen = 0; cache_param_t *cache; char target[MAX_LENOFTARGET], cid[MAX_LENOFCID]; metadatalist_param_t *metadatalist; newjptstream = receive_JPTstream( connected_socket, target, cid, &newjptlen); parse_stream( newjptstream, newjptlen, *jptlen, msgqueue); *jptstream = update_JPTstream( newjptstream, newjptlen, *jptstream, jptlen); free( newjptstream); metadatalist = gene_metadatalist(); parse_metamsg( msgqueue, *jptstream, *jptlen, metadatalist); // cid registration if( target[0] != 0 && cid[0] != 0){ if((cache = search_cache( target, cachelist))) add_cachecid( cid, cache); else{ cache = gene_cache( target, msgqueue->last->csn, cid); insert_cache_into_list( cache, cachelist); } } else cache = search_cacheBycsn( msgqueue->last->csn, cachelist); if( cache->metadatalist) delete_metadatalist( &cache->metadatalist); cache->metadatalist = metadatalist; response_signal( connected_socket, true); } void handle_PNMreqMSG( int connected_socket, Byte_t *jptstream, msgqueue_param_t *msgqueue, cachelist_param_t *cachelist) { Byte_t *pnmstream; ihdrbox_param_t *ihdrbox; char cid[MAX_LENOFCID], tmp[10]; cache_param_t *cache; int fw, fh; read_line( connected_socket, cid); if(!(cache = search_cacheBycid( cid, cachelist))) return; read_line( connected_socket, tmp); fw = atoi( tmp); read_line( connected_socket, tmp); fh = atoi( tmp); pnmstream = jpt_to_pnm( jptstream, msgqueue, cache->csn, fw, fh, &cache->ihdrbox); ihdrbox = cache->ihdrbox; send_PNMstream( connected_socket, pnmstream, ihdrbox->width, ihdrbox->height, ihdrbox->nc, ihdrbox->bpc > 8 ? 255 : (1 << ihdrbox->bpc) - 1); free( pnmstream); } void handle_XMLreqMSG( int connected_socket, Byte_t *jptstream, cachelist_param_t *cachelist) { char cid[MAX_LENOFCID]; cache_param_t *cache; read_line( connected_socket, cid); if(!(cache = search_cacheBycid( cid, cachelist))) return; boxcontents_param_t *boxcontents = cache->metadatalist->last->boxcontents; Byte_t *xmlstream = (Byte_t *)malloc( boxcontents->length); memcpy( xmlstream, jptstream+boxcontents->offset, boxcontents->length); send_XMLstream( connected_socket, xmlstream, boxcontents->length); free( xmlstream); } void handle_CIDreqMSG( int connected_socket, cachelist_param_t *cachelist) { char target[MAX_LENOFTARGET], *cid = NULL; cache_param_t *cache; int cidlen = 0; read_line( connected_socket, target); cache = search_cache( target, cachelist); if( cache){ if( cache->numOfcid > 0){ cid = cache->cid[ cache->numOfcid-1]; cidlen = strlen(cid); } } send_CIDstream( connected_socket, cid, cidlen); } void handle_dstCIDreqMSG( int connected_socket, cachelist_param_t *cachelist) { char cid[MAX_LENOFCID]; read_line( connected_socket, cid); remove_cachecid( cid, cachelist); response_signal( connected_socket, true); } void handle_JP2saveMSG( int connected_socket, cachelist_param_t *cachelist, msgqueue_param_t *msgqueue, Byte_t *jptstream) { char cid[MAX_LENOFCID]; cache_param_t *cache; Byte_t *jp2stream; Byte8_t jp2len; read_line( connected_socket, cid); if(!(cache = search_cacheBycid( cid, cachelist))) return; jp2stream = recons_jp2( msgqueue, jptstream, cache->csn, &jp2len); if( jp2stream){ save_codestream( jp2stream, jp2len, "jp2"); free( jp2stream); } }