diff --git a/applications/jpip/CHANGES b/applications/jpip/CHANGES index d320ecfd..e60bf58b 100644 --- a/applications/jpip/CHANGES +++ b/applications/jpip/CHANGES @@ -5,6 +5,9 @@ What's New for OpenJPIP ! : changed + : added +November 30, 2011 ++ [kaori] TCP return (http-tcp) implemented + November 16, 2011 * [kaori] fixed opj_server execusion error (instant terminating) with autotool, cmake still need to be fixed diff --git a/applications/jpip/README b/applications/jpip/README index 3e7f5867..7e951469 100644 --- a/applications/jpip/README +++ b/applications/jpip/README @@ -29,7 +29,7 @@ The current implementation uses some results from the 2KAN project (http://www.2 First Version 2.0 covers: - JPT-stream (Tile) and JPP-stream (Precinct) media types - Session, channels, cache model managements - - JPIP over HTTP + - JPIP over HTTP, HTTP requests and TCP return - Indexing JPEG 2000 files - Embedding XML formatted metadata - Region Of Interest (ROI) requests @@ -103,12 +103,13 @@ Client: % ../opj_dec_server 2. Open image viewers (as many as needed) - % java -jar opj_viewer.jar http://hostname/myFCGI JP2_filename.jp2 [stateless/session] [jptstream/jppstream] + % java -jar opj_viewer.jar http://hostname/myFCGI path/filename.jp2 [stateless/session] [jptstream/jppstream] [tcp/udp] ( The arguments - http://hostname/myFCGI is the HTTP server URI (myFCGI refers to opj_server by the server setting) - JP2_filename.jp2 is the name of a JP2 file available on the server. - request type stateless for no caching, session (default) for caching - - return media type, JPT-stream tile based stream, or JPP-stream (default) precinct based stream + - return media type, JPT-stream tile based stream, or JPP-stream (default) precinct based stream + - auxiliary return protocol, tcp or udp (udp is not implemented yet), if not given, return data is filled in http chunk Image viewer GUI instructions: Scale up request: Enlarge the window ROI request: Select a region by mouse click and drag, then click inside the red frame of the selected region @@ -118,7 +119,7 @@ Client: Open a new window presenting an aligned image with a locally stored image: Click button "Image Registration" (Under Construction) 3. Quit the image decoding server through the telnet, be sure all image viewers are closed - % telnet localhost 5000 + % telnet localhost 50000 quit ---------- diff --git a/applications/jpip/libopenjpip/CMakeLists.txt b/applications/jpip/libopenjpip/CMakeLists.txt index b72c145f..56ab057d 100644 --- a/applications/jpip/libopenjpip/CMakeLists.txt +++ b/applications/jpip/libopenjpip/CMakeLists.txt @@ -31,9 +31,11 @@ SET(OPENJPIP_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/channel_manager.c ${CMAKE_CURRENT_SOURCE_DIR}/session_manager.c ${CMAKE_CURRENT_SOURCE_DIR}/jpip_parser.c + ${CMAKE_CURRENT_SOURCE_DIR}/sock_manager.c ) SET(SERVER_SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/auxtrans_manager.c ) SET(LOCAL_SRCS diff --git a/applications/jpip/libopenjpip/Makefile.am b/applications/jpip/libopenjpip/Makefile.am index cfc973c4..19832fb2 100644 --- a/applications/jpip/libopenjpip/Makefile.am +++ b/applications/jpip/libopenjpip/Makefile.am @@ -38,6 +38,7 @@ cachemodel_manager.c \ j2kheader_manager.c \ jp2k_encoder.c \ sock_manager.c \ +auxtrans_manager.c \ openjpip.h \ bool.h \ boxheader_manager.h \ @@ -63,7 +64,8 @@ channel_manager.h \ session_manager.h \ jpip_parser.h \ jp2k_decoder.h \ -sock_manager.h +sock_manager.h \ +auxtrans_manager.h SERVER_SRC = auxtrans_manager.c \ auxtrans_manager.h diff --git a/applications/jpip/libopenjpip/auxtrans_manager.c b/applications/jpip/libopenjpip/auxtrans_manager.c new file mode 100644 index 00000000..a0804a97 --- /dev/null +++ b/applications/jpip/libopenjpip/auxtrans_manager.c @@ -0,0 +1,266 @@ +/* + * $Id$ + * + * 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. + */ + +#include +#include +#include +#include "auxtrans_manager.h" + +#ifdef __linux__ +#include +#else +#include +#endif + +#ifdef SERVER +#include "fcgi_stdio.h" +#define logstream FCGI_stdout +#else +#define FCGI_stdout stdout +#define FCGI_stderr stderr +#define logstream stderr +#endif //SERVER + +auxtrans_param_t init_aux_transport( int tcp_auxport, int udp_auxport) +{ + auxtrans_param_t auxtrans; + + auxtrans.tcpauxport = tcp_auxport; + auxtrans.udpauxport = udp_auxport; + + if( 49152 <= tcp_auxport && tcp_auxport <= 65535) + auxtrans.tcplistensock = open_listeningsocket( tcp_auxport); + else + auxtrans.tcplistensock = -1; + + auxtrans.udplistensock = -1; + // open listening socket for udp later + + return auxtrans; +} + +void close_aux_transport( auxtrans_param_t auxtrans) +{ + if( auxtrans.tcplistensock != -1) + if( close_socket( auxtrans.tcplistensock) != 0) + perror("close"); + + if( auxtrans.udplistensock != -1) + if( close_socket( auxtrans.udplistensock) != 0) + perror("close"); +} + + +//!< auxiliary response parameters +typedef struct aux_response_param{ + char *cid; //!< channel ID + unsigned char *data; //!< sending data + int datalen; //!< length of data + int maxlenPerFrame; //!< maximum data length to send per frame + SOCKET listensock; //!< listeing socket +#ifdef _WIN32 + HANDLE hTh; //!< thread handle +#endif +} aux_response_param_t; + +aux_response_param_t * gene_auxresponse( bool istcp, auxtrans_param_t auxtrans, char cid[], void *data, int datalen, int maxlenPerFrame); + +void delete_auxresponse( aux_response_param_t **auxresponse); + +#ifdef __linux__ +void * aux_streaming( void *arg); +#else +unsigned __stdcall aux_streaming( void *arg); +#endif + +void send_responsedata_on_aux( bool istcp, auxtrans_param_t auxtrans, char cid[], void *data, int datalen, int maxlenPerFrame) +{ + aux_response_param_t *auxresponse; +#ifdef __linux__ + pthread_t thread; + int status; +#else + unsigned int threadId; +#endif + + if( istcp){ + if( auxtrans.tcplistensock == -1){ + fprintf( FCGI_stderr, "Error: error in send_responsedata_on_aux(), tcp listening socket no open\n"); + return; + } + + auxresponse = gene_auxresponse( istcp, auxtrans, cid, data, datalen, maxlenPerFrame); + +#ifdef __linux__ + status = pthread_create( &thread, NULL, &aux_streaming, auxresponse); + if( status != 0) + fprintf( FCGI_stderr,"ERROR: pthread_create() %s",strerror(status)); +#else + auxresponse->hTh = (HANDLE)_beginthreadex( NULL, 0, &aux_streaming, auxresponse, 0, &threadId); + if( auxresponse->hTh == 0) + fprintf( FCGI_stderr,"ERRO: pthread_create() %s", strerror( (int)auxresponse->hTh)); +#endif + } + else + fprintf( FCGI_stderr, "Error: error in send_responsedata_on_aux(), udp not implemented\n"); +} + +aux_response_param_t * gene_auxresponse( bool istcp, auxtrans_param_t auxtrans, char cid[], void *data, int datalen, int maxlenPerFrame) +{ + aux_response_param_t *auxresponse; + + auxresponse = (aux_response_param_t *)malloc( sizeof(aux_response_param_t)); + + auxresponse->cid = strdup( cid); + auxresponse->data = data; + auxresponse->datalen = datalen; + auxresponse->maxlenPerFrame = maxlenPerFrame; + auxresponse->listensock = istcp ? auxtrans.tcplistensock : auxtrans.udplistensock; + + return auxresponse; +} + +void delete_auxresponse( aux_response_param_t **auxresponse) +{ + free( (*auxresponse)->cid); + free( (*auxresponse)->data); + free( *auxresponse); +} + +/** + * Identify cid sent from client + * + * @param [in] connected_socket file descriptor of the connected socket + * @param [in] refcid refenrece channel ID + * @param [in] fp file pointer for log of aux stream + * @return true if identified, false otherwise + */ +bool identify_cid( SOCKET connected_socket, char refcid[], FILE *fp); + +bool recv_ack( SOCKET connected_socket, void *data); + +#ifdef __linux__ +void * aux_streaming( void *arg) +#else +unsigned __stdcall aux_streaming( void *arg) +#endif +{ + SOCKET connected_socket; + unsigned char *chunk, *ptr; + int maxLenOfBody, remlen, chunklen; + const int headlen = 8; + + aux_response_param_t *auxresponse = (aux_response_param_t *)arg; + +#ifdef __linux__ + pthread_detach( pthread_self()); +#else + CloseHandle( auxresponse->hTh); +#endif + + chunk = (unsigned char *)malloc( auxresponse->maxlenPerFrame); + maxLenOfBody = auxresponse->maxlenPerFrame - headlen; + remlen = auxresponse->datalen; + + while((connected_socket = accept_socket( auxresponse->listensock)) != -1){ + if( identify_cid( connected_socket, auxresponse->cid, FCGI_stderr)){ + ptr = auxresponse->data; + while( 0 < remlen){ + memset( chunk, 0, auxresponse->maxlenPerFrame); + + chunklen = remlen> 8) & 0xff; + chunk[1] = chunklen & 0xff; + + memcpy( chunk+headlen, ptr, chunklen-headlen); + + do{ + send_stream( connected_socket, chunk, chunklen); + }while( !recv_ack( connected_socket, chunk)); + + remlen -= maxLenOfBody; + ptr += maxLenOfBody; + } + if( close_socket( connected_socket) != 0) + perror("close"); + break; + } + } + free( chunk); + + delete_auxresponse( &auxresponse); + +#ifdef __linux__ + pthread_exit(0); +#else + _endthreadex(0); +#endif + + return 0; +} + + +bool identify_cid( SOCKET connected_socket, char refcid[], FILE *fp) +{ + char *cid; + bool succeed; + + if(!(cid = receive_string( connected_socket))){ + fprintf( fp, "Error: error in identify_cid(), while receiving cid from client\n"); + return false; + } + + succeed = false; + if( strncmp( refcid, cid, strlen( refcid)) == 0) + succeed = true; + + free( cid); + + return succeed; +} + +bool recv_ack( SOCKET connected_socket, void *data) +{ + char *header; + bool succeed; + + header = receive_stream( connected_socket, 8); + + if( memcmp( header, data, 8) != 0) + succeed = false; + else + succeed = true; + + free( header); + + return succeed; +} diff --git a/applications/jpip/libopenjpip/auxtrans_manager.h b/applications/jpip/libopenjpip/auxtrans_manager.h new file mode 100644 index 00000000..62107dce --- /dev/null +++ b/applications/jpip/libopenjpip/auxtrans_manager.h @@ -0,0 +1,72 @@ +/* + * $Id$ + * + * 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. + */ + +#ifndef AUXTRANS_MANAGER_H_ +# define AUXTRANS_MANAGER_H_ + +#include "sock_manager.h" + +//! auxiliary transport setting parameters +typedef struct auxtrans_param{ + int tcpauxport; //!< tcp port + int udpauxport; //!< udp port + SOCKET tcplistensock; //!< listenning socket for aux tcp (-1 if not open) + SOCKET udplistensock; //!< listenning socket for aux udp (-1 if not open) +} auxtrans_param_t; + +/** + * Initialize auxiliary transport server of JPIP server + * + * @param[in] tcp_auxport opening tcp auxiliary port ( 0 not to open, valid No. 49152–65535) + * @param[in] udp_auxport opening udp auxiliary port ( 0 not to open, valid No. 49152–65535) + * @return intialized transport parameters + */ +auxtrans_param_t init_aux_transport( int tcp_auxport, int udp_auxport); + +/** + * Close auxiliary transport server of JPIP server + * + * @param[in] auxtrans closing transport server + */ +void close_aux_transport( auxtrans_param_t auxtrans); + +/** + * Send response data on aux transport + * + * @param[in] istcp true if tcp, false if udp + * @param[in] auxtrans available transport parameters + * @param[in] cid channel ID + * @param[in] data sending data + * @param[in] length length of data + * @param[in] maxlenPerFrame maximum data length to send per frame + */ +void send_responsedata_on_aux( bool istcp, auxtrans_param_t auxtrans, char cid[], void *data, int length, int maxlenPerFrame); + +#endif /* !AUXTRANS_MANAGER_H_ */ diff --git a/applications/jpip/libopenjpip/cachemodel_manager.c b/applications/jpip/libopenjpip/cachemodel_manager.c index ba5a3ec1..70b58c87 100644 --- a/applications/jpip/libopenjpip/cachemodel_manager.c +++ b/applications/jpip/libopenjpip/cachemodel_manager.c @@ -193,3 +193,41 @@ void delete_cachemodel( cachemodel_param_t **cachemodel) #endif free( *cachemodel); } + +bool is_allsent( cachemodel_param_t cachemodel) +{ + target_param_t *target; + Byte8_t TPnum; // num of tile parts in each tile + Byte8_t Pmax; // max num of packets per tile + int i, j, k, n; + + target = cachemodel.target; + + if( !cachemodel.mhead_model) + return false; + + TPnum = get_nmax( target->codeidx->tilepart); + + if( cachemodel.jppstream){ + for( i=0; icodeidx->SIZ.XTnum*target->codeidx->SIZ.YTnum; i++){ + if( !cachemodel.th_model[i]) + return false; + + for( j=0; jcodeidx->SIZ.Csiz; j++){ + Pmax = get_nmax( target->codeidx->precpacket[j]); + for( k=0; kcodeidx->SIZ.YTnum; i++) + for( j=0; jcodeidx->SIZ.XTnum; j++) + for( k=0; kcid, MAX_LENOFCID, "%x%x", (unsigned int)time( &channel->start_tm), (unsigned int)rand()); + channel->aux = query_param.cnew; + + // only tcp implemented for now + if( channel->aux == udp) + channel->aux = tcp; + channel->next=NULL; set_channel_variable_param( query_param, channel); @@ -81,8 +88,12 @@ channel_param_t * gene_channel( query_param_t query_param, cachemodel_param_t *c channellist->last = channel; fprintf( FCGI_stdout, "JPIP-cnew: cid=%s", channel->cid); - // only http implemented for now - fprintf( FCGI_stdout, ",transport=http\r\n"); + fprintf( FCGI_stdout, ",transport=%s", transport[channel->aux]); + + if( channel->aux == tcp || channel->aux == udp) + fprintf( FCGI_stdout, ",auxport=%d", channel->aux==tcp ? auxtrans.tcpauxport : auxtrans.udpauxport); + + fprintf( FCGI_stdout, "\r\n"); return channel; } diff --git a/applications/jpip/libopenjpip/channel_manager.h b/applications/jpip/libopenjpip/channel_manager.h index b42a2eb7..fe8281fa 100644 --- a/applications/jpip/libopenjpip/channel_manager.h +++ b/applications/jpip/libopenjpip/channel_manager.h @@ -34,11 +34,16 @@ #include #include "query_parser.h" #include "cachemodel_manager.h" +#include "auxtrans_manager.h" + +//! maximum length of channel identifier +#define MAX_LENOFCID 30 //! Channel parameters typedef struct channel_param{ cachemodel_param_t *cachemodel; //!< reference pointer to the cache model char cid[MAX_LENOFCID]; //!< channel identifier + cnew_transport_t aux; //!< auxiliary transport // - a record of the client's capabilities and preferences to the extent that the server queues requests time_t start_tm; //!< starting time struct channel_param *next; //!< pointer to the next channel @@ -64,11 +69,12 @@ channellist_param_t * gene_channellist(); * generate a channel under the channel list * * @param[in] query_param query parameters + * @param[in] auxtrans auxiliary transport * @param[in] cachemodel reference cachemodel * @param[in] channellist channel list pointer * @return pointer to the generated channel */ -channel_param_t * gene_channel( query_param_t query_param, cachemodel_param_t *cachemodel, channellist_param_t *channellist); +channel_param_t * gene_channel( query_param_t query_param, auxtrans_param_t auxtrans, cachemodel_param_t *cachemodel, channellist_param_t *channellist); /** * set channel variable parameters diff --git a/applications/jpip/libopenjpip/dec_clientmsg_handler.c b/applications/jpip/libopenjpip/dec_clientmsg_handler.c index f001238f..f4d9edf3 100644 --- a/applications/jpip/libopenjpip/dec_clientmsg_handler.c +++ b/applications/jpip/libopenjpip/dec_clientmsg_handler.c @@ -48,6 +48,8 @@ void handle_JPIPstreamMSG( SOCKET connected_socket, cachelist_param_t *cachelist newjpipstream = receive_JPIPstream( connected_socket, &target, &tid, &cid, &newstreamlen); + fprintf( stderr, "newjpipstream length: %d\n", newstreamlen); + parse_JPIPstream( newjpipstream, newstreamlen, *streamlen, msgqueue); *jpipstream = update_JPIPstream( newjpipstream, newstreamlen, *jpipstream, streamlen); diff --git a/applications/jpip/libopenjpip/imgsock_manager.c b/applications/jpip/libopenjpip/imgsock_manager.c index 6caf7278..7f533873 100644 --- a/applications/jpip/libopenjpip/imgsock_manager.c +++ b/applications/jpip/libopenjpip/imgsock_manager.c @@ -28,76 +28,11 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#ifdef _WIN32 -#include -#define strcasecmp _stricmp -#else -#include -#include -#include -#include -#include -#include -#include -#include -#endif - #include #include #include -#include #include "imgsock_manager.h" -#define BUF_LEN 256 - -SOCKET open_listeningsocket() -{ - SOCKET listening_socket; - struct sockaddr_in sin; - int sock_optval = 1; - int port = 5000; - - listening_socket = socket(AF_INET, SOCK_STREAM, 0); - if ( listening_socket == -1 ){ - perror("socket"); - exit(1); - } - - if ( setsockopt(listening_socket, SOL_SOCKET, SO_REUSEADDR, - &sock_optval, sizeof(sock_optval)) == -1 ){ - perror("setsockopt"); - exit(1); - } - - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - sin.sin_port = htons(port); - sin.sin_addr.s_addr = htonl(INADDR_ANY); - - if ( bind(listening_socket, (struct sockaddr *)&sin, sizeof(sin)) < 0 ){ - perror("bind"); - close_socket(listening_socket); - exit(1); - } - - if( listen(listening_socket, SOMAXCONN) == -1){ - perror("listen"); - close_socket(listening_socket); - exit(1); - } - fprintf( stderr, "port %d is listened\n", port); - - return listening_socket; -} - -SOCKET accept_socket( SOCKET listening_socket) -{ - struct sockaddr_in peer_sin; - unsigned int addrlen = sizeof(peer_sin); - - return accept( listening_socket, (struct sockaddr *)&peer_sin, &addrlen); -} - msgtype_t identify_clientmsg( SOCKET connected_socket) { int receive_size; @@ -125,9 +60,9 @@ msgtype_t identify_clientmsg( SOCKET connected_socket) Byte_t * receive_JPIPstream( SOCKET connected_socket, char **target, char **tid, char **cid, int *streamlen) { - Byte_t *jpipstream=NULL, *ptr; char buf[BUF_LEN], versionstring[] = "version 1.2"; - int linelen, redlen, remlen; + int linelen, datalen; + Byte_t *jpipstream; *target = *cid = *tid = NULL; @@ -159,27 +94,20 @@ Byte_t * receive_JPIPstream( SOCKET connected_socket, char **target, char **tid, return NULL; } - *streamlen = atoi( buf); - fprintf( stderr, "Receive Data: %d Bytes\n", *streamlen); + datalen = atoi( buf); + fprintf( stderr, "Receive Data: %d Bytes\n", datalen); + + jpipstream = receive_stream( connected_socket, datalen); + + // check EOR + if( jpipstream[datalen-3] == 0x00 && ( jpipstream[datalen-2] == 0x01 || jpipstream[datalen-2] == 0x02)) + *streamlen = datalen -3; + else + *streamlen = datalen; - jpipstream = (unsigned char *)malloc( (*streamlen)); - ptr = jpipstream; - remlen = (*streamlen); - while( remlen > 0){ - redlen = recv( connected_socket, ptr, remlen, 0); - if( redlen == -1){ - fprintf( stderr, "receive JPT- JPP- stream error\n"); - break; - } - remlen -= redlen; - ptr = ptr + redlen; - } - return jpipstream; } -void send_stream( SOCKET connected_socket, void *stream, int length); - void send_XMLstream( SOCKET connected_socket, Byte_t *xmlstream, int length) { Byte_t header[5]; @@ -238,56 +166,6 @@ void send_PNMstream( SOCKET connected_socket, Byte_t *pnmstream, unsigned int wi send_stream( connected_socket, pnmstream, pnmlen); } -void send_stream( SOCKET connected_socket, void *stream, int length) -{ - void *ptr = stream; - int remlen = length; - - while( remlen > 0){ - int sentlen = send( connected_socket, ptr, remlen, 0); - if( sentlen == -1){ - fprintf( stderr, "sending stream error\n"); - break; - } - remlen = remlen - sentlen; - ptr = ptr + sentlen; - } -} - -int receive_line(SOCKET connected_socket, char *p) -{ - int len = 0; - while (1){ - int ret; - ret = recv( connected_socket, p, 1, 0); - if ( ret == -1 ){ - perror("receive"); - exit(1); - } else if ( ret == 0 ){ - break; - } - if ( *p == '\n' ) - break; - p++; - len++; - } - *p = '\0'; - - if( len == 0) - fprintf( stderr, "Header receive error\n"); - - return len; -} - -char * receive_string( SOCKET connected_socket) -{ - char buf[BUF_LEN]; - - receive_line( connected_socket, buf); - - return strdup(buf); -} - void response_signal( SOCKET connected_socket, bool succeed) { Byte_t code; @@ -297,15 +175,5 @@ void response_signal( SOCKET connected_socket, bool succeed) else code = 0; - if( send( connected_socket, &code, 1, 0) != 1) - fprintf( stderr, "Response signalling error\n"); -} - -int close_socket( SOCKET sock) -{ -#ifdef _WIN32 - return closesocket( sock); -#else - return close( sock); -#endif + send_stream( connected_socket, &code, 1); } diff --git a/applications/jpip/libopenjpip/imgsock_manager.h b/applications/jpip/libopenjpip/imgsock_manager.h index 5961a581..b3e68d7f 100644 --- a/applications/jpip/libopenjpip/imgsock_manager.h +++ b/applications/jpip/libopenjpip/imgsock_manager.h @@ -33,28 +33,7 @@ #include "bool.h" #include "byte_manager.h" - -#ifdef _WIN32 -#include -#else -typedef int SOCKET; -#endif //_WIN32 - -/** - * open listening socket - * - * @return new socket - */ -SOCKET open_listeningsocket(); - -/** - * accept a new connection to the listenning socket - * - * @param listening_socket listenning socket - * @return connected socket (-1 if error occurs) - */ -SOCKET accept_socket( SOCKET listening_socket); - +#include "sock_manager.h" #define NUM_OF_MSGTYPES 8 typedef enum eMSGTYPE{ JPIPSTREAM, PNMREQ, XMLREQ, TIDREQ, CIDREQ, CIDDST, JP2SAVE, QUIT, MSGERROR} msgtype_t; @@ -126,31 +105,6 @@ void send_CIDstream( SOCKET connected_socket, char *cid, int cidlen); */ void response_signal( SOCKET connected_socket, bool succeed); -/** - * receive a string line (ending with '\n') from client - * - * @param [in] connected_socket file descriptor of the connected socket - * @param [out] buf string to be stored - * @return red size - */ -int receive_line(SOCKET connected_socket, char *buf); - -/** - * receive a string line (ending with '\n') from client, return malloc string - * - * @param [in] connected_socket file descriptor of the connected socket - * @return pointer to the string (memory allocated) - */ -char * receive_string( SOCKET connected_socket); - -/** - * close socket - * - * @param [in] sock closing socket - * @return 0 if succeed, -1 if failed - */ -int close_socket( SOCKET sock); - #endif /* !IMGSOCK_MANAGER_H_ */ /*! \file diff --git a/applications/jpip/libopenjpip/jpip_parser.c b/applications/jpip/libopenjpip/jpip_parser.c index eb4e76f0..7697297d 100644 --- a/applications/jpip/libopenjpip/jpip_parser.c +++ b/applications/jpip/libopenjpip/jpip_parser.c @@ -48,17 +48,19 @@ bool identify_target( query_param_t query_param, targetlist_param_t *targetlist, target_param_t **target) { - if( query_param.tid[0] !='\0' && strcmp( query_param.tid, "0") != 0 ){ - if( query_param.cid[0] != '\0'){ - fprintf( FCGI_stdout, "Reason: Target can not be specified both through tid and cid\r\n"); - fprintf( FCGI_stdout, "Status: 400\r\n"); - return false; + if( query_param.tid){ + if( strcmp( query_param.tid, "0") != 0 ){ + if( query_param.cid[0] != '\0'){ + fprintf( FCGI_stdout, "Reason: Target can not be specified both through tid and cid\r\n"); + fprintf( FCGI_stdout, "Status: 400\r\n"); + return false; + } + if( ( *target = search_targetBytid( query_param.tid, targetlist))) + return true; } - if( ( *target = search_targetBytid( query_param.tid, targetlist))) - return true; } - if( query_param.target[0] !='\0') + if( query_param.target) if( !( *target = search_target( query_param.target, targetlist))) if(!( *target = gene_target( targetlist, query_param.target))) return false; @@ -93,6 +95,7 @@ bool associate_channel( query_param_t query_param, bool open_channel( query_param_t query_param, sessionlist_param_t *sessionlist, + auxtrans_param_t auxtrans, target_param_t *target, session_param_t **cursession, channel_param_t **curchannel) @@ -110,7 +113,7 @@ bool open_channel( query_param_t query_param, if( *curchannel) cachemodel = (*curchannel)->cachemodel; - *curchannel = gene_channel( query_param, cachemodel, (*cursession)->channellist); + *curchannel = gene_channel( query_param, auxtrans, cachemodel, (*cursession)->channellist); if( *curchannel == NULL) return false; @@ -122,7 +125,10 @@ bool close_channel( query_param_t query_param, session_param_t **cursession, channel_param_t **curchannel) { - if( query_param.cclose[0][0] =='*'){ + char *cclose; + int i; + + if( query_param.cclose[0] =='*'){ #ifndef SERVER fprintf( logstream, "local log: close all\n"); #endif @@ -132,28 +138,25 @@ bool close_channel( query_param_t query_param, } else{ // check if all entry belonging to the same session - int i=0; - while( query_param.cclose[i][0] !='\0'){ + + for( i=0, cclose=query_param.cclose; ichannellist))){ - fprintf( FCGI_stdout, "Reason: Cclose id %s is from another session\r\n", query_param.cclose[i]); + if( !(*curchannel=search_channel( cclose, (*cursession)->channellist))){ + fprintf( FCGI_stdout, "Reason: Cclose id %s is from another session\r\n", cclose); return false; } - i++; } + // delete channels - i=0; - while( query_param.cclose[i][0] !='\0'){ - - *curchannel = search_channel( query_param.cclose[i], (*cursession)->channellist); + for( i=0, cclose=query_param.cclose; ichannellist); delete_channel( curchannel, (*cursession)->channellist); - i++; } if( (*cursession)->channellist->first == NULL || (*cursession)->channellist->last == NULL) diff --git a/applications/jpip/libopenjpip/jpip_parser.h b/applications/jpip/libopenjpip/jpip_parser.h index 9f3cd8a4..8070c8a9 100644 --- a/applications/jpip/libopenjpip/jpip_parser.h +++ b/applications/jpip/libopenjpip/jpip_parser.h @@ -68,6 +68,7 @@ bool associate_channel( query_param_t query_param, * * @param[in] query_param structured query * @param[in] sessionlist session list pointer + * @param[in] auxtrans auxiliary transport * @param[in] target requested target pointer * @param[in,out] cursession address of the associated/opened session pointer * @param[in,out] curchannel address of the associated/opened channel pointer @@ -75,6 +76,7 @@ bool associate_channel( query_param_t query_param, */ bool open_channel( query_param_t query_param, sessionlist_param_t *sessionlist, + auxtrans_param_t auxtrans, target_param_t *target, session_param_t **cursession, channel_param_t **curchannel); diff --git a/applications/jpip/libopenjpip/msgqueue_manager.c b/applications/jpip/libopenjpip/msgqueue_manager.c index 295c2360..9b3f379e 100644 --- a/applications/jpip/libopenjpip/msgqueue_manager.c +++ b/applications/jpip/libopenjpip/msgqueue_manager.c @@ -383,13 +383,12 @@ void enqueue_message( message_param_t *msg, msgqueue_param_t *msgqueue) msgqueue->last = msg; } +void add_bin_id_vbas_stream( Byte_t bb, Byte_t c, Byte8_t in_class_id, int tmpfd); +void add_vbas_stream( Byte8_t code, int tmpfd); +void add_body_stream( message_param_t *msg, int fd, int tmpfd); +void add_placeholder_stream( placeholder_param_t *phld, int tmpfd); -void emit_bin_id_vbas( Byte_t bb, Byte_t c, Byte8_t in_class_id); -void emit_vbas( Byte8_t code); -void emit_body( message_param_t *msg, int fd); -void emit_placeholder( placeholder_param_t *phld); - -void emit_stream_from_msgqueue( msgqueue_param_t *msgqueue) +void recons_stream_from_msgqueue( msgqueue_param_t *msgqueue, int tmpfd) { message_param_t *msg; Byte8_t class_id, csn; @@ -417,33 +416,33 @@ void emit_stream_from_msgqueue( msgqueue_param_t *msgqueue) } c = msg->last_byte ? 1 : 0; - - emit_bin_id_vbas( bb, c, msg->in_class_id); + + add_bin_id_vbas_stream( bb, c, msg->in_class_id, tmpfd); if( bb >= 2) - emit_vbas( class_id); + add_vbas_stream( class_id, tmpfd); if (bb == 3) - emit_vbas( csn); + add_vbas_stream( csn, tmpfd); - emit_vbas( msg->bin_offset); - emit_vbas (msg->length); + add_vbas_stream( msg->bin_offset, tmpfd); + add_vbas_stream (msg->length, tmpfd); if( msg->class_id%2) // Aux is present only if the id is odd - emit_vbas( msg->aux); + add_vbas_stream( msg->aux, tmpfd); if( msg->phld) - emit_placeholder( msg->phld); + add_placeholder_stream( msg->phld, tmpfd); else - emit_body( msg, msgqueue->cachemodel->target->fd); + add_body_stream( msg, msgqueue->cachemodel->target->fd, tmpfd); msg = msg->next; } } -void emit_vbas_with_bytelen( Byte8_t code, int bytelength); +void add_vbas_with_bytelen_stream( Byte8_t code, int bytelength, int tmpfd); void print_binarycode( Byte8_t n, int segmentlen); -void emit_bin_id_vbas( Byte_t bb, Byte_t c, Byte8_t in_class_id) +void add_bin_id_vbas_stream( Byte_t bb, Byte_t c, Byte8_t in_class_id, int tmpfd) { int bytelength; Byte8_t tmp; @@ -459,10 +458,10 @@ void emit_bin_id_vbas( Byte_t bb, Byte_t c, Byte8_t in_class_id) in_class_id |= (((bb & 3) << 5) | (c & 1) << 4) << ((bytelength-1)*7); - emit_vbas_with_bytelen( in_class_id, bytelength); + add_vbas_with_bytelen_stream( in_class_id, bytelength, tmpfd); } -void emit_vbas( Byte8_t code) +void add_vbas_stream( Byte8_t code, int tmpfd) { int bytelength; Byte8_t tmp; @@ -472,10 +471,10 @@ void emit_vbas( Byte8_t code) while( tmp >>= 7) bytelength ++; - emit_vbas_with_bytelen( code, bytelength); + add_vbas_with_bytelen_stream( code, bytelength, tmpfd); } -void emit_vbas_with_bytelen( Byte8_t code, int bytelength) +void add_vbas_with_bytelen_stream( Byte8_t code, int bytelength, int tmpfd) { int n; Byte8_t seg; @@ -485,17 +484,17 @@ void emit_vbas_with_bytelen( Byte8_t code, int bytelength) seg = ( code >> (n*7)) & 0x7f; if( n) seg |= 0x80; - fputc(( Byte4_t)seg, FCGI_stdout); + write( tmpfd, ( Byte4_t *)&seg, 1); n--; } } -void emit_body( message_param_t *msg, int fd) +void add_body_stream( message_param_t *msg, int fd, int tmpfd) { Byte_t *data; - if( lseek( fd, msg->res_offset, SEEK_SET)==-1){ - fprintf( FCGI_stderr, "Error: fseek in emit_body()\n"); + if( !(data = fetch_bytes( fd, msg->res_offset, msg->length))){ + fprintf( FCGI_stderr, "Error: fetch_bytes in add_body_stream()\n"); return; } @@ -506,33 +505,33 @@ void emit_body( message_param_t *msg, int fd) return; } - if( fwrite( data, msg->length, 1, FCGI_stdout) < 1){ + if( write( tmpfd, data, msg->length) < 1){ free( data); - fprintf( FCGI_stderr, "Error: fwrite in emit_body()\n"); + fprintf( FCGI_stderr, "Error: fwrite in add_body_stream()\n"); return; } free(data); } -void emit_bigendian_bytes( Byte8_t code, int bytelength); +void add_bigendian_bytestream( Byte8_t code, int bytelength, int tmpfd); -void emit_placeholder( placeholder_param_t *phld) +void add_placeholder_stream( placeholder_param_t *phld, int tmpfd) { - emit_bigendian_bytes( phld->LBox, 4); - if( fwrite( phld->TBox, 4, 1, FCGI_stdout) < 1){ - fprintf( FCGI_stderr, "Error: fwrite in emit_placeholder()\n"); + add_bigendian_bytestream( phld->LBox, 4, tmpfd); + if( write( tmpfd, phld->TBox, 4) < 1){ + fprintf( FCGI_stderr, "Error: fwrite in add_placeholder_stream()\n"); return; } - emit_bigendian_bytes( phld->Flags, 4); - emit_bigendian_bytes( phld->OrigID, 8); + add_bigendian_bytestream( phld->Flags, 4, tmpfd); + add_bigendian_bytestream( phld->OrigID, 8, tmpfd); - if( fwrite( phld->OrigBH, phld->OrigBHlen, 1, FCGI_stdout) < 1){ - fprintf( FCGI_stderr, "Error: fwrite in emit_placeholder()\n"); + if( write( tmpfd, phld->OrigBH, phld->OrigBHlen) < 1){ + fprintf( FCGI_stderr, "Error: fwrite in add_placeholder_stream()\n"); return; } } -void emit_bigendian_bytes( Byte8_t code, int bytelength) +void add_bigendian_bytestream( Byte8_t code, int bytelength, int tmpfd) { int n; Byte8_t seg; @@ -540,7 +539,7 @@ void emit_bigendian_bytes( Byte8_t code, int bytelength) n = bytelength - 1; while( n >= 0) { seg = ( code >> (n*8)) & 0xff; - fputc(( Byte4_t)seg, FCGI_stdout); + write( tmpfd, ( Byte4_t *)&seg, 1); n--; } } diff --git a/applications/jpip/libopenjpip/msgqueue_manager.h b/applications/jpip/libopenjpip/msgqueue_manager.h index 7236d89c..23dad76b 100644 --- a/applications/jpip/libopenjpip/msgqueue_manager.h +++ b/applications/jpip/libopenjpip/msgqueue_manager.h @@ -145,11 +145,12 @@ void enqueue_metadata( int meta_id, msgqueue_param_t *msgqueue); /** - * emit stream from message queue + * reconstruct JPT/JPP-stream from message queue * * @param[in] msgqueue message queue pointer + * @param[in] tmpfd file discriptor to write JPT/JPP-stream */ -void emit_stream_from_msgqueue( msgqueue_param_t *msgqueue); +void recons_stream_from_msgqueue( msgqueue_param_t *msgqueue, int tmpfd); /** diff --git a/applications/jpip/libopenjpip/openjpip.c b/applications/jpip/libopenjpip/openjpip.c index 7bdedea0..7977bb7f 100644 --- a/applications/jpip/libopenjpip/openjpip.c +++ b/applications/jpip/libopenjpip/openjpip.c @@ -32,6 +32,8 @@ #include "openjpip.h" #include "jpip_parser.h" #include "channel_manager.h" +#include "byte_manager.h" +#include "auxtrans_manager.h" #include #include "dec_clientmsg_handler.h" @@ -44,21 +46,23 @@ #include #include "jp2k_encoder.h" -server_record_t * init_JPIPserver() +server_record_t * init_JPIPserver( int tcp_auxport, int udp_auxport) { server_record_t *record = (server_record_t *)malloc( sizeof(server_record_t)); record->sessionlist = gene_sessionlist(); record->targetlist = gene_targetlist(); - + record->auxtrans = init_aux_transport( tcp_auxport, udp_auxport); + return record; } void terminate_JPIPserver( server_record_t **rec) { delete_sessionlist( &(*rec)->sessionlist); - delete_targetlist( &(*rec)->targetlist); - + delete_targetlist( &(*rec)->targetlist); + close_aux_transport( (*rec)->auxtrans); + free( *rec); } @@ -69,8 +73,8 @@ QR_t * parse_querystring( char *query_string) qr = (QR_t *)malloc( sizeof(QR_t)); qr->query = parse_query( query_string); - qr->msgqueue = NULL; + qr->channel = NULL; return qr; } @@ -81,35 +85,83 @@ bool process_JPIPrequest( server_record_t *rec, QR_t *qr) session_param_t *cursession = NULL; channel_param_t *curchannel = NULL; - if( qr->query->target[0] != '\0' || qr->query->tid[0] != '\0'){ + if( qr->query->target || qr->query->tid){ if( !identify_target( *(qr->query), rec->targetlist, &target)) return false; } - if( qr->query->cid[0] != '\0'){ + if( qr->query->cid){ if( !associate_channel( *(qr->query), rec->sessionlist, &cursession, &curchannel)) return false; + qr->channel = curchannel; } - - if( qr->query->cnew){ - if( !open_channel( *(qr->query), rec->sessionlist, target, &cursession, &curchannel)) + + if( qr->query->cnew != non){ + if( !open_channel( *(qr->query), rec->sessionlist, rec->auxtrans, target, &cursession, &curchannel)) return false; + qr->channel = curchannel; } - if( qr->query->cclose[0][0] != '\0') + + if( qr->query->cclose) if( !close_channel( *(qr->query), rec->sessionlist, &cursession, &curchannel)) return false; if( (qr->query->fx > 0 && qr->query->fy > 0) || qr->query->box_type[0][0] != 0) if( !gene_JPIPstream( *(qr->query), target, cursession, curchannel, &qr->msgqueue)) return false; - + return true; } -void send_responsedata( QR_t *qr) +void add_EORmsg( int fd, QR_t *qr); + +void send_responsedata( server_record_t *rec, QR_t *qr) { - // Currently HTTP support only, find a way for TCP, UDP case - emit_stream_from_msgqueue( qr->msgqueue); + int fd; + char tmpfname[] = "tmpjpipstream.jpp"; + Byte_t *jpipstream; + Byte8_t len_of_jpipstream; + + if( (fd = open( tmpfname, O_RDWR|O_CREAT|O_EXCL, S_IRWXU)) == -1){ + fprintf( FCGI_stderr, "file open error %s", tmpfname); + fprintf( FCGI_stdout, "Status: 503\r\n"); + fprintf( FCGI_stdout, "Reason: Implementation failed\r\n"); + return; + } + + recons_stream_from_msgqueue( qr->msgqueue, fd); + + add_EORmsg( fd, qr); // needed at least for tcp and udp + + len_of_jpipstream = get_filesize( fd); + jpipstream = fetch_bytes( fd, 0, len_of_jpipstream); + + close( fd); + remove( tmpfname); + + fprintf( FCGI_stdout, "\r\n"); + + if( qr->channel) + if( qr->channel->aux == tcp || qr->channel->aux == udp){ + send_responsedata_on_aux( qr->channel->aux==tcp, rec->auxtrans, qr->channel->cid, jpipstream, len_of_jpipstream, 1000); // 1KB per frame + return; + } + + fwrite( jpipstream, len_of_jpipstream, 1, FCGI_stdout); + free( jpipstream); + return; +} + +void add_EORmsg( int fd, QR_t *qr) +{ + unsigned char EOR[3]; + + if( qr->channel){ + EOR[0] = 0x00; + EOR[1] = is_allsent( *(qr->channel->cachemodel)) ? 0x01 : 0x02; + EOR[2] = 0x00; + write( fd, EOR, 3); + } } void end_QRprocess( server_record_t *rec, QR_t **qr) @@ -138,7 +190,7 @@ void local_log( bool query, bool messages, bool sessions, bool targets, QR_t *qr #ifndef SERVER -dec_server_record_t * init_dec_server() +dec_server_record_t * init_dec_server( int port) { dec_server_record_t *record = (dec_server_record_t *)malloc( sizeof(dec_server_record_t)); @@ -146,7 +198,7 @@ dec_server_record_t * init_dec_server() record->jpipstream = NULL; record->jpipstreamlen = 0; record->msgqueue = gene_msgqueue( true, NULL); - record->listening_socket = open_listeningsocket(); + record->listening_socket = open_listeningsocket( port); return record; } @@ -217,12 +269,13 @@ bool handle_clientreq( client_t client, dec_server_record_t *rec) case MSGERROR: break; } - + fprintf( stderr, "\t end of the connection\n\n"); if( close_socket(client) != 0){ perror("close"); return false; } + if( quit) return false; diff --git a/applications/jpip/libopenjpip/openjpip.h b/applications/jpip/libopenjpip/openjpip.h index c4011f85..4f7941fe 100644 --- a/applications/jpip/libopenjpip/openjpip.h +++ b/applications/jpip/libopenjpip/openjpip.h @@ -36,6 +36,19 @@ #include "query_parser.h" #include "msgqueue_manager.h" #include "bool.h" +#include "sock_manager.h" +#include "auxtrans_manager.h" + +#ifdef SERVER + +#include "fcgi_stdio.h" +#define logstream FCGI_stdout + +#else + +#define FCGI_stdout stdout +#define FCGI_stderr stderr +#define logstream stderr #include "cache_manager.h" #include "byte_manager.h" @@ -45,13 +58,6 @@ #include "ihdrbox_manager.h" #include "index_manager.h" -#ifdef SERVER -#include "fcgi_stdio.h" -#define logstream FCGI_stdout -#else -#define FCGI_stdout stdout -#define FCGI_stderr stderr -#define logstream stderr #endif //SERVER /* @@ -64,20 +70,24 @@ typedef struct server_record{ sessionlist_param_t *sessionlist; //!< list of session records targetlist_param_t *targetlist; //!< list of target records + auxtrans_param_t auxtrans; } server_record_t; //! Query/response data for each client typedef struct QR{ - query_param_t *query; - msgqueue_param_t *msgqueue; + query_param_t *query; //!< query parameters + msgqueue_param_t *msgqueue; //!< message queue + channel_param_t *channel; //!< channel, (NULL if stateless) } QR_t; /** * Initialize the JPIP server * - * @return intialized server record pointer + * @param[in] tcp_auxport opening tcp auxiliary port ( 0 not to open, valid No. 49152–65535) + * @param[in] udp_auxport opening udp auxiliary port ( 0 not to open, valid No. 49152–65535) + * @return intialized server record pointer */ -server_record_t * init_JPIPserver(); +server_record_t * init_JPIPserver( int tcp_auxport, int udp_auxport); /** * Terminate the JPIP server @@ -106,9 +116,10 @@ bool process_JPIPrequest( server_record_t *rec, QR_t *qr); /** * 3rd process; send response data JPT/JPP-stream * + * @param[in] rec server static record pointer * @param[in] qr query/response data pointer */ -void send_responsedata( QR_t *qr); +void send_responsedata( server_record_t *rec, QR_t *qr); /** * 4th (last) process; @@ -158,9 +169,10 @@ typedef SOCKET client_t; /** * Initialize the image decoding server * - * @return intialized decoding server record pointer + * @param[in] port opening tcp port (valid No. 49152–65535) + * @return intialized decoding server record pointer */ -dec_server_record_t * init_dec_server(); +dec_server_record_t * init_dec_server( int port); /** * Terminate the image decoding server diff --git a/applications/jpip/libopenjpip/query_parser.c b/applications/jpip/libopenjpip/query_parser.c index 1293c0a8..f8449deb 100644 --- a/applications/jpip/libopenjpip/query_parser.c +++ b/applications/jpip/libopenjpip/query_parser.c @@ -69,14 +69,7 @@ query_param_t * get_initquery(); */ char * get_fieldparam( char *stringptr, char *fieldname, char *fieldval); -/** - * parse string to string array - * - * @param[in] src src string - * @param[out] cclose parsed string array - */ -void str2cclose( char *src, char cclose[][MAX_LENOFCID]); - +void parse_cclose( char *src, query_param_t *query_param); void parse_metareq( char *field, query_param_t *query_param); // parse the requested components (parses forms like:a; a,b; a-b; a-b,c; a,b-c) @@ -104,10 +97,10 @@ query_param_t * parse_query( char *query_string) if( fieldname[0] != '\0'){ if( strcasecmp( fieldname, "target") == 0) - strcpy( query_param->target,fieldval); + query_param->target = strdup( fieldval); else if( strcasecmp( fieldname, "tid") == 0) - strcpy( query_param->tid, fieldval); + query_param->tid = strdup( fieldval); else if( strcasecmp( fieldname, "fsiz") == 0) sscanf( fieldval, "%d,%d", &query_param->fx, &query_param->fy); @@ -122,13 +115,17 @@ query_param_t * parse_query( char *query_string) sscanf( fieldval, "%d", &query_param->layers); else if( strcasecmp( fieldname, "cid") == 0) - strcpy( query_param->cid, fieldval); + query_param->cid = strdup( fieldval); - else if( strcasecmp( fieldname, "cnew") == 0) - query_param->cnew = true; + else if( strcasecmp( fieldname, "cnew") == 0){ + if( strncasecmp( fieldval, "http-tcp", 8) == 0) + query_param->cnew = tcp; + else if( strncasecmp( fieldval, "http", 4) == 0) + query_param->cnew = http; + } else if( strcasecmp( fieldname, "cclose") == 0) - str2cclose( fieldval, query_param->cclose); + parse_cclose( fieldval, query_param); else if( strcasecmp( fieldname, "metareq") == 0) parse_metareq( fieldval, query_param); @@ -157,8 +154,8 @@ query_param_t * get_initquery() query = (query_param_t *)malloc( sizeof(query_param_t)); - query->target[0] = '\0'; - query->tid[0] = '\0'; + query->target = NULL; + query->tid = NULL; query->fx = -1; query->fy = -1; query->rx = -1; @@ -168,9 +165,10 @@ query_param_t * get_initquery() query->layers = -1; query->lastcomp = -1; query->comps = NULL; - query->cid[0] = '\0'; - query->cnew = false; - memset( query->cclose, 0, MAX_NUMOFCCLOSE*MAX_LENOFCID); + query->cid = NULL; + query->cnew = non; + query->cclose = NULL; + query->numOfcclose = 0; memset( query->box_type, 0, MAX_NUMOFBOX*4); memset( query->limit, 0, MAX_NUMOFBOX*sizeof(int)); for( i=0; icclose = strdup( src); + + for( i=0; icclose[i] == ','){ + query_param->cclose[i] = '\0'; + query_param->numOfcclose ++; } - else - cclose[u][v++] = src[i]; - } + + query_param->numOfcclose ++; } void parse_req_box_prop( char *req_box_prop, int idx, query_param_t *query_param); @@ -386,6 +399,20 @@ void parse_comps( char *field, query_param_t *query_param) void delete_query( query_param_t **query) { - free((*query)->comps); + if( (*query)->target) + free( (*query)->target); + + if( (*query)->tid) + free( (*query)->tid); + + if( (*query)->comps) + free((*query)->comps); + + if( (*query)->cid) + free( (*query)->cid); + + if( (*query)->cclose) + free( (*query)->cclose); + free( *query); } diff --git a/applications/jpip/libopenjpip/query_parser.h b/applications/jpip/libopenjpip/query_parser.h index d42385ae..7774b3d8 100644 --- a/applications/jpip/libopenjpip/query_parser.h +++ b/applications/jpip/libopenjpip/query_parser.h @@ -34,36 +34,28 @@ #include "bool.h" -//! maximum length of target name -#define MAX_LENOFTARGET 128 - -//! maximum length of target identifier -#define MAX_LENOFTID 30 - -//! maximum length of channel identifier -#define MAX_LENOFCID 30 - -//! maximum number of closing channel -#define MAX_NUMOFCCLOSE 10 - //! maximum number of meta request box #define MAX_NUMOFBOX 10 +//! cnew aux transport name +typedef enum cnew_transport { non, http, tcp, udp} cnew_transport_t; + //! image return type typedef enum image_return { JPPstream, JPTstream, UNKNOWN=-1} image_return_t; //! Query parameters typedef struct query_param{ - char target[MAX_LENOFTARGET]; //!< target name - char tid[MAX_LENOFTID]; //!< target identifier + char *target; //!< target name + char *tid; //!< target identifier int fx, fy; //!< frame size (fx,fy) int rx, ry, rw, rh; //!< roi region int layers; //!< quality layers int lastcomp; //!< last component number bool *comps; //!< components (dynamic array) for jpp-stream, null means all components - char cid[MAX_LENOFCID]; //!< channel identifier - bool cnew; //!< if there is new channel request(true) or not (false) - char cclose[MAX_NUMOFCCLOSE][MAX_LENOFCID]; //!< closing channel identifiers + char *cid; //!< channel identifier + cnew_transport_t cnew; //!< transport name if there is new channel request, else non + char *cclose; //!< list of closing channel identifiers, separated by '\0' + int numOfcclose; //!< number of closing channels char box_type[MAX_NUMOFBOX][4]; //!< interested box-types int limit[MAX_NUMOFBOX]; //!< limit value, -1: skeleton request "r", 0: entire contents bool w[MAX_NUMOFBOX]; //!< Metadata request qualifier flags diff --git a/applications/jpip/libopenjpip/sock_manager.c b/applications/jpip/libopenjpip/sock_manager.c new file mode 100644 index 00000000..b84bc981 --- /dev/null +++ b/applications/jpip/libopenjpip/sock_manager.c @@ -0,0 +1,179 @@ +/* + * $Id$ + * + * 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. + */ + +#ifdef _WIN32 +#include +#else +#include +#include +#include +#endif + +#include +#include +#include +#include +#include "sock_manager.h" + +#ifdef SERVER +#include "fcgi_stdio.h" +#define logstream FCGI_stdout +#else +#define FCGI_stdout stdout +#define FCGI_stderr stderr +#define logstream stderr +#endif //SERVER + +SOCKET open_listeningsocket( int port) +{ + SOCKET listening_socket; + struct sockaddr_in sin; + int sock_optval = 1; + + listening_socket = socket(AF_INET, SOCK_STREAM, 0); + if ( listening_socket == -1 ){ + perror("socket"); + exit(1); + } + + if ( setsockopt(listening_socket, SOL_SOCKET, SO_REUSEADDR, (const char *)&sock_optval, sizeof(sock_optval)) == -1 ){ + perror("setsockopt"); + exit(1); + } + + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_port = htons(port); + sin.sin_addr.s_addr = htonl(INADDR_ANY); + + if ( bind(listening_socket, (struct sockaddr *)&sin, sizeof(sin)) < 0 ){ + perror("bind"); + close_socket(listening_socket); + exit(1); + } + + if( listen(listening_socket, SOMAXCONN) == -1){ + perror("listen"); + close_socket(listening_socket); + exit(1); + } + fprintf( FCGI_stderr, "port %d is listened\n", port); + + return listening_socket; +} + +SOCKET accept_socket( SOCKET listening_socket) +{ + struct sockaddr_in peer_sin; + unsigned int addrlen = sizeof(peer_sin); + + return accept( listening_socket, (struct sockaddr *)&peer_sin, &addrlen); +} + +void send_stream( SOCKET connected_socket, void *stream, int length) +{ + void *ptr = stream; + int remlen = length; + + while( remlen > 0){ + int sentlen = send( connected_socket, ptr, remlen, 0); + if( sentlen == -1){ + fprintf( FCGI_stderr, "sending stream error\n"); + break; + } + remlen = remlen - sentlen; + ptr = ptr + sentlen; + } +} + +void * receive_stream( SOCKET connected_socket, int length) +{ + void *stream, *ptr; + int remlen, redlen; + + ptr = stream = malloc( length); + remlen = length; + + while( remlen > 0){ + redlen = recv( connected_socket, ptr, remlen, 0); + if( redlen == -1){ + fprintf( FCGI_stderr, "receive stream error\n"); + free( stream); + stream = NULL; + break; + } + remlen -= redlen; + ptr = ptr + redlen; + } + return stream; +} + +int receive_line(SOCKET connected_socket, char *p) +{ + int len = 0; + while (1){ + int ret; + ret = recv( connected_socket, p, 1, 0); + if ( ret == -1 ){ + perror("receive"); + exit(1); + } else if ( ret == 0 ){ + break; + } + if ( *p == '\n' ) + break; + p++; + len++; + } + *p = '\0'; + + if( len == 0) + fprintf( FCGI_stderr, "Header receive error\n"); + + return len; +} + +char * receive_string( SOCKET connected_socket) +{ + char buf[BUF_LEN]; + + receive_line( connected_socket, buf); + + return strdup(buf); +} + +int close_socket( SOCKET sock) +{ +#ifdef _WIN32 + return closesocket( sock); +#else + return close( sock); +#endif +} diff --git a/applications/jpip/libopenjpip/sock_manager.h b/applications/jpip/libopenjpip/sock_manager.h new file mode 100644 index 00000000..82591c09 --- /dev/null +++ b/applications/jpip/libopenjpip/sock_manager.h @@ -0,0 +1,105 @@ +/* + * $Id$ + * + * 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. + */ + +#ifndef SOCK_MANAGER_H_ +# define SOCK_MANAGER_H_ + +#include "bool.h" +#include "byte_manager.h" + +#ifdef _WIN32 +#include +#else +typedef int SOCKET; +#endif //_WIN32 + +#define BUF_LEN 256 + +/** + * open listening socket + * + * @param port opening port number + * @return new socket + */ +SOCKET open_listeningsocket( int port); + +/** + * accept a new connection to the listenning socket + * + * @param listening_socket listenning socket + * @return connected socket (-1 if error occurs) + */ +SOCKET accept_socket( SOCKET listening_socket); + + +/** + * receive a string line (ending with '\n') from client + * + * @param [in] connected_socket file descriptor of the connected socket + * @param [out] buf string to be stored + * @return red size + */ +int receive_line(SOCKET connected_socket, char *buf); + +/** + * receive a string line (ending with '\n') from client, return malloc string + * + * @param [in] connected_socket file descriptor of the connected socket + * @return pointer to the string (memory allocated) + */ +char * receive_string( SOCKET connected_socket); + +/** + * receive data stream to client + * + * @param [in] connected_socket file descriptor of the connected socket + * @param [in] length length of the receiving stream + * @return pointer to the data stream (memory allocated), NULL if failed + */ +void * receive_stream( SOCKET connected_socket, int length); + +/** + * send data stream to client + * + * @param [in] connected_socket file descriptor of the connected socket + * @param [in] stream data stream + * @param [in] length length of data stream + */ +void send_stream( SOCKET connected_socket, void *stream, int length); + +/** + * close socket + * + * @param [in] sock closing socket + * @return 0 if succeed, -1 if failed + */ +int close_socket( SOCKET sock); + +#endif /* !SOCK_MANAGER_H_ */ diff --git a/applications/jpip/libopenjpip/target_manager.c b/applications/jpip/libopenjpip/target_manager.c index 813c1a99..c820a085 100644 --- a/applications/jpip/libopenjpip/target_manager.c +++ b/applications/jpip/libopenjpip/target_manager.c @@ -39,6 +39,7 @@ #include "target_manager.h" #ifdef SERVER +#include #include "fcgi_stdio.h" #define logstream FCGI_stdout #else @@ -47,7 +48,6 @@ #define logstream stderr #endif //SERVER - targetlist_param_t * gene_targetlist() { targetlist_param_t *targetlist; @@ -95,6 +95,12 @@ target_param_t * gene_target( targetlist_param_t *targetlist, char *targetpath) snprintf( target->tid, MAX_LENOFTID, "%x-%x", (unsigned int)time(NULL), (unsigned int)rand()); target->filename = strdup( targetpath); target->fd = fd; +#ifdef SERVER + if( tmpfname[0]) + target->tmpfname = strdup( tmpfname); + else + target->tmpfname = NULL; +#endif target->csn = last_csn++; target->codeidx = jp2idx; target->num_of_use = 0; @@ -129,7 +135,18 @@ void unrefer_target( target_param_t *target) void delete_target( target_param_t **target) { close( (*target)->fd); +<<<<<<< .working +======= + +#ifdef SERVER + if( (*target)->tmpfname){ + fprintf( FCGI_stderr, "Temporal file %s is deleted\n", (*target)->tmpfname); + remove( (*target)->tmpfname); + } +#endif + +>>>>>>> .merge-right.r1103 if( (*target)->codeidx) delete_index ( &(*target)->codeidx); @@ -227,14 +244,28 @@ target_param_t * search_targetBytid( char tid[], targetlist_param_t *targetlist) return NULL; } +<<<<<<< .working int open_jp2file( char filename[]) +======= +int open_remotefile( char filepath[], char tmpfname[]); + +int open_jp2file( char filepath[], char tmpfname[]) +>>>>>>> .merge-right.r1103 { int fd; char *data; +<<<<<<< .working if( (fd = open( filename, O_RDONLY)) == -1){ fprintf( FCGI_stdout, "Reason: Target %s not found\r\n", filename); return -1; +======= + + // download remote target file to local storage + if( strncmp( filepath, "http://", 7) == 0){ + if( (fd = open_remotefile( filepath, tmpfname)) == -1) + return -1; +>>>>>>> .merge-right.r1103 } // Check resource is a JP family file. if( lseek( fd, 0, SEEK_SET)==-1){ @@ -261,3 +292,52 @@ int open_jp2file( char filename[]) free( data); return fd; } +<<<<<<< .working +======= + +#ifdef SERVER +static size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream); +#endif + +int open_remotefile( char filepath[], char tmpfname[]) +{ +#ifndef SERVER + + fprintf( FCGI_stderr, "Remote file can not be opened in local mode\n"); + return -1; + +#else + + CURL *curl_handle; + int fd; + + curl_handle = curl_easy_init(); + curl_easy_setopt(curl_handle, CURLOPT_URL, filepath); + curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 1L); + curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_data); + + snprintf( tmpfname, MAX_LENOFTID, "%x-%x.jp2", (unsigned int)time(NULL), (unsigned int)rand()); + fprintf( FCGI_stderr, "%s is downloaded to a temporal new file %s\n", filepath, tmpfname); + if( (fd = open( tmpfname, O_RDWR|O_CREAT|O_EXCL, S_IRWXU)) == -1){ + fprintf( FCGI_stdout, "Reason: File open error %s\r\n", tmpfname); + curl_easy_cleanup(curl_handle); + return -1; + } + curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, &fd); + curl_easy_perform(curl_handle); + curl_easy_cleanup(curl_handle); + + return fd; +#endif //SERVER +} + +#ifdef SERVER +static size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream) +{ + int *fd = (int *)stream; + int written = write( *fd, ptr, size*nmemb); + + return written; +} +#endif //SERVER +>>>>>>> .merge-right.r1103 diff --git a/applications/jpip/libopenjpip/target_manager.h b/applications/jpip/libopenjpip/target_manager.h index a5469e79..0202006d 100644 --- a/applications/jpip/libopenjpip/target_manager.h +++ b/applications/jpip/libopenjpip/target_manager.h @@ -40,8 +40,11 @@ //! target parameters typedef struct target_param{ char tid[MAX_LENOFTID]; //!< taregt identifier - char *filename; //!< file name + char *targetname; //!< local file path or URL ( URL is suported only with SERVER mode) int fd; //!< file descriptor +#ifdef SERVER + char *tmpfname; //!< temporal file name to download a remote target file +#endif int csn; //!< codestream number index_param_t *codeidx; //!< index information of codestream int num_of_use; //!< numbers of sessions refering to this target diff --git a/applications/jpip/util/opj_dec_server.c b/applications/jpip/util/opj_dec_server.c index 7eee9a84..0ad3a052 100644 --- a/applications/jpip/util/opj_dec_server.c +++ b/applications/jpip/util/opj_dec_server.c @@ -64,7 +64,7 @@ int main(int argc, char *argv[]){ printf( "Initialisation Winsock\n"); #endif //_WIN32 - server_record = init_dec_server(); + server_record = init_dec_server( 50000); while(( client = accept_connection( server_record)) != -1 ) if(!handle_clientreq( client, server_record)) diff --git a/applications/jpip/util/opj_server.c b/applications/jpip/util/opj_server.c index a2344c8b..bd29fdfd 100644 --- a/applications/jpip/util/opj_server.c +++ b/applications/jpip/util/opj_server.c @@ -54,11 +54,23 @@ #define QUIT_SIGNAL "quitJPIP" #endif +#ifdef _WIN32 +WSADATA initialisation_win32; +#endif //_WIN32 + int main(void) { server_record_t *server_record; - server_record = init_JPIPserver(); +#ifdef _WIN32 + int erreur = WSAStartup(MAKEWORD(2,2),&initialisation_win32); + if( erreur!=0) + fprintf( stderr, "Erreur initialisation Winsock error : %d %d\n",erreur,WSAGetLastError()); + else + fprintf( stderr, "Initialisation Winsock\n"); +#endif //_WIN32 + + server_record = init_JPIPserver( 60000, 0); #ifdef SERVER @@ -90,10 +102,11 @@ int main(void) local_log( true, true, parse_status, false, qr, server_record); #endif - fprintf( FCGI_stdout, "\r\n"); - - send_responsedata( qr); - + if( parse_status) + send_responsedata( server_record, qr); + else + fprintf( FCGI_stderr, "Error: JPIP request failed\n"); + end_QRprocess( server_record, &qr); } @@ -101,5 +114,13 @@ int main(void) terminate_JPIPserver( &server_record); +#ifdef _WIN32 + if( WSACleanup() != 0){ + fprintf( stderr, "\nError in WSACleanup : %d %d",erreur,WSAGetLastError()); + }else{ + fprintf( stderr, "\nWSACleanup OK\n"); + } +#endif + return 0; } diff --git a/applications/jpip/util/opj_viewer/src/ImageManager.java b/applications/jpip/util/opj_viewer/src/ImageManager.java index 5634123f..5008a4b3 100644 --- a/applications/jpip/util/opj_viewer/src/ImageManager.java +++ b/applications/jpip/util/opj_viewer/src/ImageManager.java @@ -43,7 +43,7 @@ public class ImageManager extends JPIPHttpClient public int getOrigWidth(){ return pnmimage.get_width();} public int getOrigHeight(){ return pnmimage.get_height();} - public Image getImage( String j2kfilename, int reqfw, int reqfh, boolean reqcnew, boolean reqJPP, boolean reqJPT) + public Image getImage( String j2kfilename, int reqfw, int reqfh, boolean reqcnew, int reqaux, boolean reqJPP, boolean reqJPT) { System.err.println(); @@ -52,17 +52,17 @@ public class ImageManager extends JPIPHttpClient // Todo: check if the cid is for the same stream type if( reqcnew) - refcid = ImgdecClient.query_cid( j2kfilename); + refcid = ImgdecClient.query_cid( j2kfilename); if( refcid == null){ String reftid = ImgdecClient.query_tid( j2kfilename); if( reftid == null) - jpipstream = super.requestViewWindow( j2kfilename, reqfw, reqfh, reqcnew, reqJPP, reqJPT); + jpipstream = super.requestViewWindow( j2kfilename, reqfw, reqfh, reqcnew, reqaux, reqJPP, reqJPT); else - jpipstream = super.requestViewWindow( j2kfilename, reftid, reqfw, reqfh, reqcnew, reqJPP, reqJPT); + jpipstream = super.requestViewWindow( j2kfilename, reftid, reqfw, reqfh, reqcnew, reqaux, reqJPP, reqJPT); } else - jpipstream = super.requestViewWindow( reqfw, reqfh, refcid, reqcnew, reqJPP, reqJPT); + jpipstream = super.requestViewWindow( reqfw, reqfh, refcid, reqcnew, reqaux, reqJPP, reqJPT); System.err.println( "decoding to PNM image"); if((pnmimage = ImgdecClient.decode_jpipstream( jpipstream, j2kfilename, tid, cid, fw, fh))!=null){ diff --git a/applications/jpip/util/opj_viewer/src/ImageViewer.java b/applications/jpip/util/opj_viewer/src/ImageViewer.java index dcd66141..163193b9 100644 --- a/applications/jpip/util/opj_viewer/src/ImageViewer.java +++ b/applications/jpip/util/opj_viewer/src/ImageViewer.java @@ -53,7 +53,7 @@ public class ImageViewer extends JPanel private Rectangle roirect[] = null; private String roiname[] = null; - public ImageViewer( String j2kfilename, ImageManager manager, boolean session, boolean jppstream) + public ImageViewer( String j2kfilename, ImageManager manager, boolean session, boolean jppstream, int aux) { String str; MML myMML; @@ -69,8 +69,8 @@ public class ImageViewer extends JPanel imgmanager = manager; - img = imgmanager.getImage( j2kfilename, vw, vh, session, jppstream, !jppstream); - + img = imgmanager.getImage( j2kfilename, vw, vh, session, aux, jppstream, !jppstream); + addMouseListener(myMML); addMouseMotionListener(myMML); addComponentListener( new ResizeListener(this)); diff --git a/applications/jpip/util/opj_viewer/src/ImageWindow.java b/applications/jpip/util/opj_viewer/src/ImageWindow.java index 4f44cced..5cf94db6 100644 --- a/applications/jpip/util/opj_viewer/src/ImageWindow.java +++ b/applications/jpip/util/opj_viewer/src/ImageWindow.java @@ -37,13 +37,13 @@ public class ImageWindow extends JFrame private ImageViewer imgviewer; private ImageManager imgmanager; - public ImageWindow( String uri, String j2kfilename, boolean session, boolean jppstream) + public ImageWindow( String uri, String j2kfilename, boolean session, boolean jppstream, int aux) { super( j2kfilename); imgmanager = new ImageManager( uri); - - imgviewer = new ImageViewer( j2kfilename, imgmanager, session, jppstream); + + imgviewer = new ImageViewer( j2kfilename, imgmanager, session, jppstream, aux); imgviewer.setOpaque(true); //content panes must be opaque JPanel panel = new JPanel(); @@ -68,6 +68,7 @@ public class ImageWindow extends JFrame { String j2kfilename, uri; boolean session, jppstream; + int aux; // 0: none, 1: tcp, 2: udp if(s.length >= 2){ uri = s[0]; @@ -81,12 +82,21 @@ public class ImageWindow extends JFrame jppstream = !s[3].equalsIgnoreCase( "JPT"); else jppstream = true; + + if( s.length > 4){ + if( s[4].equalsIgnoreCase("udp")) + aux = 2; + else + aux = 1; + } + else + aux = 0; } else{ - System.out.println("Usage: java -jar opj_viewer.jar HTTP_server_URI imagefile.jp2 [stateless/session] [JPT/JPP]"); + System.out.println("Usage: java -jar opj_viewer.jar HTTP_server_URI imagefile.jp2 [stateless/session] [JPT/JPP] [tcp/udp]"); return; } - ImageWindow frame = new ImageWindow( uri, j2kfilename, session, jppstream); + ImageWindow frame = new ImageWindow( uri, j2kfilename, session, jppstream, aux); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); diff --git a/applications/jpip/util/opj_viewer/src/ImgdecClient.java b/applications/jpip/util/opj_viewer/src/ImgdecClient.java index 35c97128..27750de7 100644 --- a/applications/jpip/util/opj_viewer/src/ImgdecClient.java +++ b/applications/jpip/util/opj_viewer/src/ImgdecClient.java @@ -49,7 +49,7 @@ public class ImgdecClient{ public static void send_JPIPstream( byte[] jpipstream) { try{ - Socket imgdecSocket = new Socket( "localhost", 5000); + Socket imgdecSocket = new Socket( "localhost", 50000); DataOutputStream os = new DataOutputStream( imgdecSocket.getOutputStream()); DataInputStream is = new DataInputStream( imgdecSocket.getInputStream()); @@ -74,7 +74,7 @@ public class ImgdecClient{ public static void send_JPIPstream( byte[] jpipstream, String j2kfilename, String tid, String cid) { try{ - Socket imgdecSocket = new Socket( "localhost", 5000); + Socket imgdecSocket = new Socket( "localhost", 50000); DataOutputStream os = new DataOutputStream( imgdecSocket.getOutputStream()); DataInputStream is = new DataInputStream( imgdecSocket.getInputStream()); int length = 0; @@ -114,7 +114,7 @@ public class ImgdecClient{ PnmImage pnmstream = null; try { - Socket imgdecSocket = new Socket( "localhost", 5000); + Socket imgdecSocket = new Socket( "localhost", 50000); DataOutputStream os = new DataOutputStream( imgdecSocket.getOutputStream()); DataInputStream is = new DataInputStream( imgdecSocket.getInputStream()); byte []header = new byte[7]; @@ -171,7 +171,7 @@ public class ImgdecClient{ byte []xmldata = null; try{ - Socket imgdecSocket = new Socket( "localhost", 5000); + Socket imgdecSocket = new Socket( "localhost", 50000); DataOutputStream os = new DataOutputStream( imgdecSocket.getOutputStream()); DataInputStream is = new DataInputStream( imgdecSocket.getInputStream()); byte []header = new byte[5]; @@ -222,7 +222,7 @@ public class ImgdecClient{ String id = null; try{ - Socket imgdecSocket = new Socket( "localhost", 5000); + Socket imgdecSocket = new Socket( "localhost", 50000); DataOutputStream os = new DataOutputStream( imgdecSocket.getOutputStream()); DataInputStream is = new DataInputStream( imgdecSocket.getInputStream()); byte []header = new byte[4]; @@ -253,6 +253,49 @@ public class ImgdecClient{ return id; } + + public static java.awt.Dimension query_imagesize( String cid, String tid) + { + java.awt.Dimension dim = null; + + try{ + Socket imgdecSocket = new Socket( "localhost", 50000); + DataOutputStream os = new DataOutputStream( imgdecSocket.getOutputStream()); + DataInputStream is = new DataInputStream( imgdecSocket.getInputStream()); + byte []header = new byte[3]; + + os.writeBytes( "SIZ request\n"); + if( tid == null) + os.writeBytes( "0\n"); + else + os.writeBytes( tid + "\n"); + if( cid == null) + os.writeBytes( "0\n"); + else + os.writeBytes( cid + "\n"); + + read_stream( is, header, 3); + + if( header[0] == 83 && header[1] == 73 && header[2] == 90){ + + byte []data = new byte[ 3]; + read_stream( is, data, 3); + int w = (data[0]&0xff)<<16 | (data[1]&0xff)<<8 | (data[2]&0xff); + read_stream( is, data, 3); + int h = (data[0]&0xff)<<16 | (data[1]&0xff)<<8 | (data[2]&0xff); + dim = new java.awt.Dimension( w, h); + } + else + System.err.println("Error in query_imagesize("+ cid + ", " + tid + "), wrong to start with " + header); + } + catch (UnknownHostException e) { + System.err.println("Trying to connect to unknown host: " + e); + } catch (IOException e) { + System.err.println("IOException: " + e); + } + + return dim; + } public static void read_stream( DataInputStream is, byte []stream, int length) { @@ -278,7 +321,7 @@ public class ImgdecClient{ public static void destroy_cid( String cid) { try{ - Socket imgdecSocket = new Socket( "localhost", 5000); + Socket imgdecSocket = new Socket( "localhost", 50000); DataOutputStream os = new DataOutputStream( imgdecSocket.getOutputStream()); DataInputStream is = new DataInputStream( imgdecSocket.getInputStream()); diff --git a/applications/jpip/util/opj_viewer/src/JPIPHttpClient.java b/applications/jpip/util/opj_viewer/src/JPIPHttpClient.java index e4c86a97..ce9a301d 100644 --- a/applications/jpip/util/opj_viewer/src/JPIPHttpClient.java +++ b/applications/jpip/util/opj_viewer/src/JPIPHttpClient.java @@ -43,6 +43,9 @@ public class JPIPHttpClient protected String tid; private boolean JPTstream; private boolean JPPstream; + private boolean aux; + private boolean tcp; // true: tcp, false: udp + private int port; public JPIPHttpClient( String URI) { @@ -52,8 +55,8 @@ public class JPIPHttpClient rw = rh = -1; cid = null; tid = null; - JPTstream = false; - JPPstream = false; + JPTstream = JPPstream = aux = false; + port = 0; } public int getFw(){ return fw;} @@ -77,51 +80,50 @@ public class JPIPHttpClient return requestViewWindow( reqfw, reqfh, reqrx, reqry, reqrw, reqrh, cid); else if( tid != null) - return requestViewWindow( null, tid, reqfw, reqfh, reqrx, reqry, reqrw, reqrh, null, false, false, false); + return requestViewWindow( null, tid, reqfw, reqfh, reqrx, reqry, reqrw, reqrh, null, false, 0, false, false); else return null; } public byte[] requestViewWindow( int reqfw, int reqfh, String reqcid) { - return requestViewWindow( null, null, reqfw, reqfh, -1, -1, -1, -1, reqcid, false, false, false); + return requestViewWindow( null, null, reqfw, reqfh, -1, -1, -1, -1, reqcid, false, 0, false, false); } public byte[] requestViewWindow( int reqfw, int reqfh, int reqrx, int reqry, int reqrw, int reqrh, String reqcid) { - return requestViewWindow( null, null, reqfw, reqfh, reqrx, reqry, reqrw, reqrh, reqcid, false, false, false); + return requestViewWindow( null, null, reqfw, reqfh, reqrx, reqry, reqrw, reqrh, reqcid, false, 0, false, false); } public byte[] requestViewWindow( String target, int reqfw, int reqfh) { - return requestViewWindow( target, null, reqfw, reqfh, -1, -1, -1, -1, null, false, false, false); + return requestViewWindow( target, null, reqfw, reqfh, -1, -1, -1, -1, null, false, 0, false, false); } - public byte[] requestViewWindow( String target, int reqfw, int reqfh, boolean reqcnew, boolean reqJPP, boolean reqJPT) + public byte[] requestViewWindow( String target, int reqfw, int reqfh, boolean reqcnew, int reqaux, boolean reqJPP, boolean reqJPT) { if( cid == null) // 1 channel allocation only - return requestViewWindow( target, null, reqfw, reqfh, -1, -1, -1, -1, null, reqcnew, reqJPP, reqJPT); + return requestViewWindow( target, null, reqfw, reqfh, -1, -1, -1, -1, null, reqcnew, reqaux, reqJPP, reqJPT); else return null; } - public byte[] requestViewWindow( String target, String reqtid, int reqfw, int reqfh, boolean reqcnew, boolean reqJPP, boolean reqJPT) + public byte[] requestViewWindow( String target, String reqtid, int reqfw, int reqfh, boolean reqcnew, int reqaux, boolean reqJPP, boolean reqJPT) { if( cid == null) // 1 channel allocation only - return requestViewWindow( target, reqtid, reqfw, reqfh, -1, -1, -1, -1, null, reqcnew, reqJPP, reqJPT); + return requestViewWindow( target, reqtid, reqfw, reqfh, -1, -1, -1, -1, null, reqcnew, reqaux, reqJPP, reqJPT); else return null; } public byte[] requestViewWindow( String target, int reqfw, int reqfh, int reqrx, int reqry, int reqrw, int reqrh) { - return requestViewWindow( target, null, reqfw, reqfh, reqrx, reqry, reqrw, reqrh, null, false, false, false); + return requestViewWindow( target, null, reqfw, reqfh, reqrx, reqry, reqrw, reqrh, null, false, 0, false, false); } - - public byte[] requestViewWindow( int reqfw, int reqfh, String reqcid, boolean reqcnew, boolean reqJPP, boolean reqJPT) + public byte[] requestViewWindow( int reqfw, int reqfh, String reqcid, boolean reqcnew, int reqaux, boolean reqJPP, boolean reqJPT) { - return requestViewWindow( null, null, reqfw, reqfh, -1, -1, -1, -1, reqcid, reqcnew, reqJPP, reqJPT); + return requestViewWindow( null, null, reqfw, reqfh, -1, -1, -1, -1, reqcid, reqcnew, reqaux, reqJPP, reqJPT); } public byte[] requestViewWindow( String target, @@ -129,12 +131,12 @@ public class JPIPHttpClient int reqfw, int reqfh, int reqrx, int reqry, int reqrw, int reqrh, - String reqcid, boolean reqcnew, boolean reqJPP, boolean reqJPT) + String reqcid, boolean reqcnew, int reqaux, boolean reqJPP, boolean reqJPT) { if( reqtid != null) tid = reqtid; - String urlstring = const_urlstring( target, reqtid, reqfw, reqfh, reqrx, reqry, reqrw, reqrh, reqcid, reqcnew, reqJPP, reqJPT); + String urlstring = const_urlstring( target, reqtid, reqfw, reqfh, reqrx, reqry, reqrw, reqrh, reqcid, reqcnew, reqaux, reqJPP, reqJPT); return GETrequest( urlstring); } @@ -153,7 +155,6 @@ public class JPIPHttpClient private byte[] GETrequest( String urlstring) { - int buflen = 0; URL url = null; HttpURLConnection urlconn = null; byte[] jpipstream = null; @@ -167,92 +168,17 @@ public class JPIPHttpClient urlconn.setRequestMethod("GET"); urlconn.setInstanceFollowRedirects(false); urlconn.connect(); - - Map> headers = urlconn.getHeaderFields(); - java.util.List hvaluelist; - String hvalueline; - - String status = headers.get(null).get(0); - - System.err.println( status); - if( !status.contains("OK")) - System.err.println( headers.get("Reason")); - - if(( hvaluelist = headers.get("Content-type")) == null) - hvaluelist = headers.get("Content-Type"); - hvalueline = hvaluelist.get(0); - System.err.println( hvalueline); - if( hvalueline.endsWith("jpt-stream")) - JPTstream = true; - else if( hvalueline.endsWith("jpp-stream")) - JPPstream = true; + set_responseheader( urlconn); - if(( hvaluelist = headers.get("JPIP-fsiz")) != null){ - hvalueline = hvaluelist.get(0); - fw = Integer.valueOf( hvalueline.substring( 0, hvalueline.indexOf(','))).intValue(); - fh = Integer.valueOf( hvalueline.substring( hvalueline.indexOf(',')+1 )).intValue(); - - System.err.println("fw,fh: " + fw + "," + fh); - } - - if(( hvaluelist = headers.get("JPIP-roff")) != null){ - hvalueline = hvaluelist.get(0); - rx = Integer.valueOf( hvalueline.substring( 0, hvalueline.indexOf(','))).intValue(); - ry = Integer.valueOf( hvalueline.substring( hvalueline.indexOf(',')+1 )).intValue(); - System.err.println("rx,ry: " + rx + "," + ry); - } - - if(( hvaluelist = headers.get("JPIP-rsiz")) != null){ - hvalueline = hvaluelist.get(0); - rw = Integer.valueOf( hvalueline.substring( 0, hvalueline.indexOf(','))).intValue(); - rh = Integer.valueOf( hvalueline.substring( hvalueline.indexOf(',')+1 )).intValue(); - System.err.println("rw,rh: " + rw + "," + rh); - } - - if(( hvaluelist = headers.get("JPIP-cnew")) != null){ - hvalueline = hvaluelist.get(0); - cid = hvalueline.substring( hvalueline.indexOf('=')+1, hvalueline.indexOf(',')); - System.err.println("cid: " + cid); - } - - if(( hvaluelist = headers.get("JPIP-tid")) != null){ - hvalueline = hvaluelist.get(0); - tid = hvalueline.substring( hvalueline.indexOf('=')+1); - System.err.println("tid: " + tid); - } - - InputStream input = urlconn.getInputStream(); - buflen = input.available(); - - if( buflen > 0){ - ByteArrayOutputStream tmpstream = new ByteArrayOutputStream(); - byte[] buf = new byte[ 1024]; - - System.err.println("reading jpipstream..."); - - int redlen; - do{ - redlen = input.read( buf); - - if( redlen == -1) - break; - tmpstream.write( buf, 0, redlen); - }while( redlen > 0); - - buflen = tmpstream.size(); - - jpipstream = tmpstream.toByteArray(); - - tmpstream = null; - - System.err.println("jpiplen: " + buflen); - System.err.println(" succeeded"); + if( !aux){ + jpipstream = receive_httpchunk( urlconn); + urlconn.disconnect(); } else{ - System.err.println("No new jpipstream"); + urlconn.disconnect(); + jpipstream = receive_tcpaux( comURL.substring( 7, comURL.indexOf('/', 7)), port, cid); } - input.close(); } catch ( MalformedURLException e){ e.printStackTrace(); @@ -272,18 +198,217 @@ public class JPIPHttpClient catch ( IOException e){ e.printStackTrace(); } - - urlconn.disconnect(); - + return jpipstream; } + + private void set_responseheader( HttpURLConnection urlconn) + { + Map> headers = urlconn.getHeaderFields(); + java.util.List hvaluelist; + String hvalueline; + + String status = headers.get(null).get(0); + + System.err.println( status); + if( !status.contains("OK")) + System.err.println( headers.get("Reason")); + + if(( hvaluelist = headers.get("Content-type")) == null) + hvaluelist = headers.get("Content-Type"); + hvalueline = hvaluelist.get(0); + System.err.println( hvalueline); + + if( hvalueline.endsWith("jpt-stream")) + JPTstream = true; + else if( hvalueline.endsWith("jpp-stream")) + JPPstream = true; + + if(( hvaluelist = headers.get("JPIP-fsiz")) != null){ + hvalueline = hvaluelist.get(0); + fw = Integer.valueOf( hvalueline.substring( 0, hvalueline.indexOf(','))).intValue(); + fh = Integer.valueOf( hvalueline.substring( hvalueline.indexOf(',')+1 )).intValue(); + + System.err.println("fw,fh: " + fw + "," + fh); + } + + if(( hvaluelist = headers.get("JPIP-roff")) != null){ + hvalueline = hvaluelist.get(0); + rx = Integer.valueOf( hvalueline.substring( 0, hvalueline.indexOf(','))).intValue(); + ry = Integer.valueOf( hvalueline.substring( hvalueline.indexOf(',')+1 )).intValue(); + System.err.println("rx,ry: " + rx + "," + ry); + } + + if(( hvaluelist = headers.get("JPIP-rsiz")) != null){ + hvalueline = hvaluelist.get(0); + rw = Integer.valueOf( hvalueline.substring( 0, hvalueline.indexOf(','))).intValue(); + rh = Integer.valueOf( hvalueline.substring( hvalueline.indexOf(',')+1 )).intValue(); + System.err.println("rw,rh: " + rw + "," + rh); + } + + if(( hvaluelist = headers.get("JPIP-cnew")) != null){ + hvalueline = hvaluelist.get(0); + cid = hvalueline.substring( hvalueline.indexOf('=')+1, hvalueline.indexOf(',')); + + int idxOfcid = hvalueline.indexOf("transport")+10; + int idxOfcid2 = hvalueline.indexOf(',', idxOfcid); + String transport; + if( idxOfcid2 != -1) + transport = hvalueline.substring( idxOfcid, idxOfcid2); + else + transport = hvalueline.substring( idxOfcid); + + if( transport.matches("http-tcp")){ + aux = true; + tcp = true; + } + else if( transport.matches("http-udp")){ + aux = true; + tcp = false; + } + else + aux = false; + + if( aux){ + idxOfcid = hvalueline.indexOf("auxport")+8; + port = Integer.valueOf( hvalueline.substring( idxOfcid)).intValue(); + System.err.println("cid: " + cid + ", transport: " + transport + ", auxport: " + port); + } + else + System.err.println("cid: " + cid + ", transport: " + transport); + } + + if(( hvaluelist = headers.get("JPIP-tid")) != null){ + hvalueline = hvaluelist.get(0); + tid = hvalueline.substring( hvalueline.indexOf('=')+1); + System.err.println("tid: " + tid); + } + } + + private static byte[] receive_httpchunk( HttpURLConnection urlconn) + { + byte[] chunk = null; + InputStream input; + + try{ + input = urlconn.getInputStream(); + + if( input.available() > 0){ + ByteArrayOutputStream tmpstream = new ByteArrayOutputStream(); + byte[] buf = new byte[ 1024]; + int redlen, buflen; + + System.err.println("reading jpipstream..."); + + do{ + redlen = input.read( buf); + + if( redlen == -1) + break; + tmpstream.write( buf, 0, redlen); + }while( redlen > 0); + + buflen = tmpstream.size(); + chunk = tmpstream.toByteArray(); + + buf = null; + tmpstream = null; + + System.err.println("jpiplen: " + buflen); + System.err.println(" succeeded"); + } + else{ + System.err.println("No new jpipstream"); + } + input.close(); + } + catch ( IOException e){ + e.printStackTrace(); + } + + return chunk; + } + + private static byte[] receive_tcpaux( String host, int port, String cid) + { + Socket jpipsocket; + DataOutputStream os; + DataInputStream is; + byte []auxheader; + byte []chunkbody = null; + byte []stream = null; + int chunkbodylen, streamlen, headlen = 8; + ByteArrayOutputStream tmpstream; + + try{ + jpipsocket = new Socket( host, port); + os = new DataOutputStream( jpipsocket.getOutputStream()); + is = new DataInputStream( jpipsocket.getInputStream()); + auxheader = new byte[headlen]; + tmpstream = new ByteArrayOutputStream(); + + os.writeBytes( cid + "\r\n"); + + do{ + read_stream( is, auxheader, headlen); + + chunkbodylen = ((auxheader[0]&0xff)<<8 | (auxheader[1]&0xff)) - headlen; + + chunkbody = new byte [ chunkbodylen]; + read_stream( is, chunkbody, chunkbodylen); + tmpstream.write( chunkbody, 0, chunkbodylen); + + os.write( auxheader, 0, headlen); + }while( !(chunkbody[chunkbodylen-3]==0x00 && ( chunkbody[chunkbodylen-2]==0x01 || chunkbody[chunkbodylen-2]== 0x02))); + + streamlen = tmpstream.size(); + stream = tmpstream.toByteArray(); + + System.err.println("jpiplen: " + streamlen); + System.err.println(" succeeded"); + + chunkbody = null; + tmpstream = null; + + os.close(); + is.close(); + + jpipsocket.close(); + } + catch ( IOException e){ + e.printStackTrace(); + } + + return stream; + } + + private static void read_stream( InputStream is, byte []stream, int length) + { + int remlen = length; + int off = 0; + + try{ + while( remlen > 0){ + int redlen = is.read( stream, off, remlen); + + if( redlen == -1){ + System.err.println(" failed to read_stream()"); + break; + } + off += redlen; + remlen -= redlen; + } + } catch (IOException e) { + System.err.println("IOException: " + e); + } + } private String const_urlstring( String target, String reqtid, int reqfw, int reqfh, int reqrx, int reqry, int reqrw, int reqrh, - String reqcid, boolean reqcnew, boolean reqJPP, boolean reqJPT) + String reqcid, boolean reqcnew, int reqaux, boolean reqJPP, boolean reqJPT) { String urlstring = comURL; @@ -323,9 +448,13 @@ public class JPIPHttpClient if( reqcnew){ if( !urlstring.endsWith("?")) urlstring = urlstring.concat( "&"); - urlstring = urlstring.concat( "cnew=http"); + if( reqaux == 1) + urlstring = urlstring.concat( "cnew=http-tcp"); + else if( reqaux == 2) + urlstring = urlstring.concat( "cnew=http-udp"); + else + urlstring = urlstring.concat( "cnew=http"); } - if( reqJPP && !JPTstream){ if( !urlstring.endsWith("?")) urlstring = urlstring.concat( "&"); diff --git a/applications/jpip/util/opj_viewer_xerces/src/ImageViewer.java b/applications/jpip/util/opj_viewer_xerces/src/ImageViewer.java index 0fa2a84e..52f0522a 100644 --- a/applications/jpip/util/opj_viewer_xerces/src/ImageViewer.java +++ b/applications/jpip/util/opj_viewer_xerces/src/ImageViewer.java @@ -53,7 +53,7 @@ public class ImageViewer extends JPanel private Rectangle roirect[] = null; private String roiname[] = null; - public ImageViewer( String j2kfilename, ImageManager manager, boolean session, boolean jppstream) + public ImageViewer( String j2kfilename, ImageManager manager, boolean session, boolean jppstream, int aux) { String str; MML myMML; @@ -69,7 +69,7 @@ public class ImageViewer extends JPanel imgmanager = manager; - img = imgmanager.getImage( j2kfilename, vw, vh, session, jppstream, !jppstream); + img = imgmanager.getImage( j2kfilename, vw, vh, session, aux, jppstream, !jppstream); addMouseListener(myMML); addMouseMotionListener(myMML); diff --git a/applications/jpip/util/opj_viewer_xerces/src/ImageWindow.java b/applications/jpip/util/opj_viewer_xerces/src/ImageWindow.java index cbf546cc..a7c8abd9 100644 --- a/applications/jpip/util/opj_viewer_xerces/src/ImageWindow.java +++ b/applications/jpip/util/opj_viewer_xerces/src/ImageWindow.java @@ -38,13 +38,13 @@ public class ImageWindow extends JFrame private OptionPanel optpanel; private ImageManager imgmanager; - public ImageWindow( String uri, String j2kfilename, boolean session, boolean jppstream) + public ImageWindow( String uri, String j2kfilename, boolean session, boolean jppstream, int aux) { super( j2kfilename); imgmanager = new ImageManager( uri); - imgviewer = new ImageViewer( j2kfilename, imgmanager, session, jppstream); + imgviewer = new ImageViewer( j2kfilename, imgmanager, session, jppstream, aux); imgviewer.setOpaque(true); //content panes must be opaque optpanel = new OptionPanel( imgmanager, imgviewer); @@ -72,6 +72,7 @@ public class ImageWindow extends JFrame { String j2kfilename, uri; boolean session, jppstream; + int aux; // 0: none, 1: tcp, 2: udp if(s.length >= 2){ uri = s[0]; @@ -85,12 +86,21 @@ public class ImageWindow extends JFrame jppstream = !s[3].equalsIgnoreCase( "JPT"); else jppstream = true; + + if( s.length > 4){ + if( s[4].equalsIgnoreCase("udp")) + aux = 2; + else + aux = 1; + } + else + aux = 0; } else{ - System.out.println("Usage: java -jar opj_viewer.jar HTTP_server_URI imagefile.jp2 [stateless/session] [JPT/JPP]"); + System.out.println("Usage: java -jar opj_viewer.jar HTTP_server_URI imagefile.jp2 [stateless/session] [JPT/JPP] [tcp/udp]"); return; } - ImageWindow frame = new ImageWindow( uri, j2kfilename, session, jppstream); + ImageWindow frame = new ImageWindow( uri, j2kfilename, session, jppstream, aux); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);