! : changed
+ : added
+November 30, 2011
++ [kaori] TCP return (http-tcp) implemented
+
November 16, 2011
* [kaori] fixed Region of Interest option, and memory leak of opj_dec_server
+ [kaori] new feature to target JP2 files from www (libcurl required)
Version 2.1 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
% ../opj_dec_server
2. Open image viewers (as many as needed)
- % java -jar opj_viewer.jar http://hostname/myFCGI path/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)
- path/filename.jp2 is the server local path or URL of a JP2 file
- 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
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
----------
${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
+${CMAKE_CURRENT_SOURCE_DIR}/auxtrans_manager.c
)
SET(LOCAL_SRCS
cachemodel_manager.c \
j2kheader_manager.c \
jp2k_encoder.c \
+sock_manager.c \
+auxtrans_manager.c \
openjpip.h \
bool.h \
boxheader_manager.h \
channel_manager.h \
session_manager.h \
jpip_parser.h \
-jp2k_decoder.h
+jp2k_decoder.h \
+sock_manager.h \
+auxtrans_manager.h
LOCAL_SRC = jp2k_decoder.c \
imgsock_manager.c \
--- /dev/null
+/*
+ * $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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "auxtrans_manager.h"
+
+#ifdef __linux__
+#include <pthread.h>
+#else
+#include <process.h>
+#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<maxLenOfBody?remlen:maxLenOfBody;
+ chunklen += headlen;
+
+ chunk[0] = (chunklen >> 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;
+}
--- /dev/null
+/*
+ * $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_ */
#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; i<target->codeidx->SIZ.XTnum*target->codeidx->SIZ.YTnum; i++){
+ if( !cachemodel.th_model[i])
+ return false;
+
+ for( j=0; j<target->codeidx->SIZ.Csiz; j++){
+ Pmax = get_nmax( target->codeidx->precpacket[j]);
+ for( k=0; k<Pmax; k++)
+ if( !cachemodel.pp_model[j][i*Pmax+k])
+ return false;
+ }
+ }
+ return true;
+ }
+ else{
+ for( i=0, n=0; i<target->codeidx->SIZ.YTnum; i++)
+ for( j=0; j<target->codeidx->SIZ.XTnum; j++)
+ for( k=0; k<TPnum; k++)
+ if( !cachemodel.tp_model[n++])
+ return false;
+ return true;
+ }
+}
cachemodel_param_t * search_cachemodel( target_param_t *target, cachemodellist_param_t *cachemodellist);
+/**
+ * check if all data has been sent
+ *
+ * @param[in] cachemodel cache model
+ * @return true if sent all, false otherwise
+ */
+bool is_allsent( cachemodel_param_t cachemodel);
+
+
/**
* delete a cache model
*
return channellist;
}
-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)
{
channel_param_t *channel;
+ char transport[4][10] = { "non", "http", "http-tcp", "http-udp"};
if( !cachemodel){
fprintf( FCGI_stdout, "Status: 404\r\n");
// set channel ID and get present time
snprintf( channel->cid, 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);
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;
}
#include <time.h>
#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
* 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
mhixbox_manager.o marker_manager.o codestream_manager.o faixbox_manager.o index_manager.o \
msgqueue_manager.o metadata_manager.o placeholder_manager.o ihdrbox_manager.o imgreg_manager.o \
cachemodel_manager.o j2kheader_manager.o jp2k_encoder.o query_parser.o channel_manager.o \
- session_manager.o jpip_parser.o
+ session_manager.o jpip_parser.o sock_manager.o auxtrans_manager.o
ar r $@ $^
else
$(LIBNAME): openjpip.o target_manager.o byte_manager.o box_manager.o boxheader_manager.o manfbox_manager.o \
msgqueue_manager.o metadata_manager.o placeholder_manager.o ihdrbox_manager.o imgreg_manager.o \
cachemodel_manager.o j2kheader_manager.o jp2k_encoder.o query_parser.o channel_manager.o \
session_manager.o jpip_parser.o jp2k_decoder.o imgsock_manager.o jpipstream_manager.o cache_manager.o \
- dec_clientmsg_handler.o
+ dec_clientmsg_handler.o sock_manager.o auxtrans_manager.o
ar r $@ $^
endif
clean:
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);
* POSSIBILITY OF SUCH DAMAGE.
*/
-#ifdef _WIN32
-#include <windows.h>
-#define strcasecmp _stricmp
-#else
-#include <strings.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/uio.h>
-#include <sys/param.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#endif
-
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
-#include <unistd.h>
#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;
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;
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];
send_stream( connected_socket, responce, 9);
}
-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;
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);
}
#include "bool.h"
#include "byte_manager.h"
-
-#ifdef _WIN32
-#include <winsock2.h>
-#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 9
typedef enum eMSGTYPE{ JPIPSTREAM, PNMREQ, XMLREQ, TIDREQ, CIDREQ, CIDDST, SIZREQ, JP2SAVE, QUIT, MSGERROR} msgtype_t;
*/
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
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;
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)
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;
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
}
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; i<query_param.numOfcclose; i++, cclose += (strlen(cclose)+1)){
// In case of the first entry of close cid
if( *cursession == NULL){
- if( !search_session_and_channel( query_param.cclose[i], sessionlist, cursession, curchannel))
+ if( !search_session_and_channel( cclose, sessionlist, cursession, curchannel))
return false;
}
else // second or more entry of close cid
- if( !(*curchannel=search_channel( query_param.cclose[i], (*cursession)->channellist))){
- 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; i<query_param.numOfcclose; i++, cclose += (strlen(cclose)+1)){
+ *curchannel = search_channel( cclose, (*cursession)->channellist);
delete_channel( curchannel, (*cursession)->channellist);
- i++;
}
if( (*cursession)->channellist->first == NULL || (*cursession)->channellist->last == NULL)
*
* @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
*/
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);
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;
}
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;
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;
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;
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( !(data = fetch_bytes( fd, msg->res_offset, msg->length))){
- fprintf( FCGI_stderr, "Error: fetch_bytes in emit_body()\n");
+ fprintf( FCGI_stderr, "Error: fetch_bytes in add_body_stream()\n");
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;
n = bytelength - 1;
while( n >= 0) {
seg = ( code >> (n*8)) & 0xff;
- fputc(( Byte4_t)seg, FCGI_stdout);
+ write( tmpfd, ( Byte4_t *)&seg, 1);
n--;
}
}
/**
- * 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);
/**
#include "openjpip.h"
#include "jpip_parser.h"
#include "channel_manager.h"
+#include "byte_manager.h"
+#include "auxtrans_manager.h"
#include <stdio.h>
#include "dec_clientmsg_handler.h"
#include <unistd.h>
#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);
}
qr = (QR_t *)malloc( sizeof(QR_t));
qr->query = parse_query( query_string);
-
qr->msgqueue = NULL;
+ qr->channel = NULL;
return 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)
+{
+ 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)
{
- // Currently HTTP support only, find a way for TCP, UDP case
- emit_stream_from_msgqueue( qr->msgqueue);
+ 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)
#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));
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;
}
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;
#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"
#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
/*
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
/**
* 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;
/**
* 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
*/
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)
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);
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);
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;
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; i<MAX_NUMOFBOX; i++){
void print_queryparam( query_param_t query_param)
{
int i;
+ char *cclose;
fprintf( logstream, "query parameters:\n");
- fprintf( logstream, "\t target: %s\n", query_param.target);
- fprintf( logstream, "\t tid: %s\n", query_param.tid);
+
+ if( query_param.target)
+ fprintf( logstream, "\t target: %s\n", query_param.target);
+
+ if( query_param.tid)
+ fprintf( logstream, "\t tid: %s\n", query_param.tid);
+
fprintf( logstream, "\t fx,fy: %d, %d\n", query_param.fx, query_param.fy);
fprintf( logstream, "\t rx,ry: %d, %d \t rw,rh: %d, %d\n", query_param.rx, query_param.ry, query_param.rw, query_param.rh);
fprintf( logstream, "\t layers: %d\n", query_param.layers);
fprintf( logstream, "\t components: ");
+
if( query_param.lastcomp == -1)
fprintf( logstream, "ALL\n");
else{
fprintf( logstream, "\n");
}
fprintf( logstream, "\t cnew: %d\n", query_param.cnew);
- fprintf( logstream, "\t cid: %s\n", query_param.cid);
- fprintf( logstream, "\t cclose: ");
- for( i=0; query_param.cclose[i][0]!=0 && i<MAX_NUMOFCCLOSE; i++)
- fprintf( logstream, "%s ", query_param.cclose[i]);
- fprintf(logstream, "\n");
+ if( query_param.cid)
+ fprintf( logstream, "\t cid: %s\n", query_param.cid);
+ if( query_param.cclose){
+ fprintf( logstream, "\t cclose: ");
+
+ for( i=0, cclose=query_param.cclose; i<query_param.numOfcclose; i++){
+ fprintf( logstream, "%s ", cclose);
+ cclose += (strlen(cclose)+1);
+ }
+ fprintf(logstream, "\n");
+ }
+
fprintf( logstream, "\t req-box-prop\n");
for( i=0; query_param.box_type[i][0]!=0 && i<MAX_NUMOFBOX; i++){
fprintf( logstream, "\t\t box_type: %.4s limit: %d w:%d s:%d g:%d a:%d priority:%d\n", query_param.box_type[i], query_param.limit[i], query_param.w[i], query_param.s[i], query_param.g[i], query_param.a[i], query_param.priority[i]);
fprintf( logstream, "\t len: %d\n", query_param.len);
}
-void str2cclose( char *src, char cclose[][MAX_LENOFCID])
+void parse_cclose( char *src, query_param_t *query_param)
{
- int i, u, v;
-
- size_t len = strlen( src);
+ int i;
+ size_t len;
- for( i=0, u=0, v=0; i<len; i++){
- if( src[i]==','){
- u++;
- v=0;
+ len = strlen( src);
+ query_param->cclose = strdup( src);
+
+ for( i=0; i<len; i++)
+ if( query_param->cclose[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);
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);
}
#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
--- /dev/null
+/*
+ * $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 <windows.h>
+#else
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#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
+}
--- /dev/null
+/*
+ * $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 <winsock2.h>
+#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_ */
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
-#include <curl/curl.h>
#include "target_manager.h"
#ifdef SERVER
+#include <curl/curl.h>
#include "fcgi_stdio.h"
#define logstream FCGI_stdout
#else
#define logstream stderr
#endif //SERVER
-
targetlist_param_t * gene_targetlist()
{
targetlist_param_t *targetlist;
snprintf( target->tid, MAX_LENOFTID, "%x-%x", (unsigned int)time(NULL), (unsigned int)rand());
target->targetname = 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;
{
close( (*target)->fd);
+#ifdef SERVER
if( (*target)->tmpfname){
fprintf( FCGI_stderr, "Temporal file %s is deleted\n", (*target)->tmpfname);
remove( (*target)->tmpfname);
}
+#endif
if( (*target)->codeidx)
delete_index ( &(*target)->codeidx);
return NULL;
}
-static size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream);
+int open_remotefile( char filepath[], char tmpfname[]);
int open_jp2file( char filepath[], char tmpfname[])
{
int fd;
char *data;
- CURL *curl_handle;
// download remote target file to local storage
if( strncmp( filepath, "http://", 7) == 0){
- 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);
+ if( (fd = open_remotefile( filepath, tmpfname)) == -1)
return -1;
- }
- curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, &fd);
- curl_easy_perform(curl_handle);
- curl_easy_cleanup(curl_handle);
}
else{
tmpfname[0] = 0;
return fd;
}
+#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;
return written;
}
+#endif //SERVER
//! target parameters
typedef struct target_param{
char tid[MAX_LENOFTID]; //!< taregt identifier
- char *targetname; //!< local file path or URL
+ 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
SLIBFNAME = $(JPIPLIBDIR)/libopenjpip_server.a
SCFLAGS = -O3 -Wall -m32 -I$(JPIPLIBDIR) -DSERVER -DQUIT_SIGNAL=\"quitJPIP\"
-SLDFLAGS = -L$(JPIPLIBDIR) -lm -lfcgi -lcurl -lopenjpip_server
+SLDFLAGS = -L$(JPIPLIBDIR) -lm -lfcgi -lcurl -lpthread -lopenjpip_server
J2KINCDIR = ../../../libopenjpeg
J2KLIBDIR = $(J2KINCDIR)/.libs
LIBFNAME = $(JPIPLIBDIR)/libopenjpip_local.a $(J2KLIBDIR)/libopenjpeg.a
CFLAGS = -O3 -Wall -I$(JPIPLIBDIR)
-LDFLAGS = -L$(JPIPLIBDIR) -L$(J2KLIBDIR) -lm -lcurl -lopenjpip_local
+LDFLAGS = -L$(JPIPLIBDIR) -L$(J2KLIBDIR) -lm -lpthread -lopenjpip_local
ALL = opj_server opj_dec_server jpip_to_jp2 jpip_to_j2k test_index addXMLinJP2
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))
#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
local_log( true, true, parse_status, false, qr, server_record);
#endif
- fprintf( FCGI_stdout, "\r\n");
-
if( parse_status)
- send_responsedata( qr);
+ send_responsedata( server_record, qr);
else
fprintf( FCGI_stderr, "Error: JPIP request failed\n");
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;
}
-opj_viewer-20111116.jar
\ No newline at end of file
+opj_viewer-20111130.jar
\ No newline at end of file
}
public int getOrigHeight(){ return origheight;}
- 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();
// 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){
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;
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));
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();
{
String j2kfilename, uri;
boolean session, jppstream;
+ int aux; // 0: none, 1: tcp, 2: udp
if(s.length >= 2){
uri = s[0];
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);
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());
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;
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];
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];
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];
java.awt.Dimension dim = 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[3];
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());
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)
{
rw = rh = -1;
cid = null;
tid = null;
- JPTstream = false;
- JPPstream = false;
+ JPTstream = JPPstream = aux = false;
+ port = 0;
}
public int getFw(){ return fw;}
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,
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);
}
private byte[] GETrequest( String urlstring)
{
- int buflen = 0;
URL url = null;
HttpURLConnection urlconn = null;
byte[] jpipstream = null;
urlconn.setRequestMethod("GET");
urlconn.setInstanceFollowRedirects(false);
urlconn.connect();
+
+ set_responseheader( urlconn);
- Map<String,java.util.List<String>> headers = urlconn.getHeaderFields();
- java.util.List<String> hvaluelist;
- String hvalueline;
-
- String status = headers.get(null).get(0);
+ if( !aux){
+ jpipstream = receive_httpchunk( urlconn);
+ urlconn.disconnect();
+ }
+ else{
+ urlconn.disconnect();
+ jpipstream = receive_tcpaux( comURL.substring( 7, comURL.indexOf('/', 7)), port, cid);
+ }
+ }
+ catch ( MalformedURLException e){
+ e.printStackTrace();
+ }
+ catch ( ProtocolException e){
+ e.printStackTrace();
+ }
+ catch( ClassCastException e){
+ e.printStackTrace();
+ }
+ catch( NullPointerException e){
+ e.printStackTrace();
+ }
+ catch( UnknownServiceException e){
+ e.printStackTrace();
+ }
+ catch ( IOException e){
+ e.printStackTrace();
+ }
+
+ return jpipstream;
+ }
+
+ private void set_responseheader( HttpURLConnection urlconn)
+ {
+ Map<String,java.util.List<String>> headers = urlconn.getHeaderFields();
+ java.util.List<String> hvaluelist;
+ String hvalueline;
+
+ String status = headers.get(null).get(0);
- System.err.println( status);
- if( !status.contains("OK"))
- System.err.println( headers.get("Reason"));
+ 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(( 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( 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();
+ 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);
- }
+ 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-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-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-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(( hvaluelist = headers.get("JPIP-tid")) != null){
- hvalueline = hvaluelist.get(0);
- tid = hvalueline.substring( hvalueline.indexOf('=')+1);
- System.err.println("tid: " + tid);
+ if( transport.matches("http-tcp")){
+ aux = true;
+ tcp = true;
}
-
- InputStream input = urlconn.getInputStream();
- buflen = input.available();
+ 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( buflen > 0){
+ 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...");
-
- 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();
+ chunk = tmpstream.toByteArray();
+ buf = null;
tmpstream = null;
-
+
System.err.println("jpiplen: " + buflen);
- System.err.println(" succeeded");
+ System.err.println(" succeeded");
}
else{
System.err.println("No new jpipstream");
}
input.close();
}
- catch ( MalformedURLException e){
- e.printStackTrace();
- }
- catch ( ProtocolException e){
- e.printStackTrace();
- }
- catch( ClassCastException e){
+ catch ( IOException e){
e.printStackTrace();
}
- catch( NullPointerException e){
- e.printStackTrace();
- }
- catch( UnknownServiceException 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();
}
- urlconn.disconnect();
-
- return jpipstream;
+ 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,
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;
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( "&");
-opj_viewer_xerces-20111116.jar
\ No newline at end of file
+opj_viewer_xerces-20111130.jar
\ No newline at end of file
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;
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);
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);
{
String j2kfilename, uri;
boolean session, jppstream;
+ int aux; // 0: none, 1: tcp, 2: udp
if(s.length >= 2){
uri = s[0];
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);