[1.5][JPIP] backport r1037 to branch 1.5
[openjpeg.git] / applications / jpip / libopenjpip / imgsock_manager.c
1 /*
2  * $Id: imgsock_manager.c 54 2011-05-10 13:22:47Z kaori $
3  *
4  * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
5  * Copyright (c) 2002-2011, Professor Benoit Macq
6  * Copyright (c) 2010-2011, Kaori Hagihara
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #ifdef _WIN32
32 #include <windows.h>
33 #define strcasecmp  _stricmp
34 #else
35 #include <strings.h>
36 #include <sys/types.h>
37 #include <sys/socket.h>
38 #include <sys/uio.h>
39 #include <sys/param.h>
40 #include <netinet/in.h>
41 #include <arpa/inet.h>
42 #include <netdb.h>
43 #endif
44
45 #include <stdio.h>
46 #include <string.h>
47 #include <stdlib.h>
48 #include <unistd.h>
49 #include "imgsock_manager.h"
50
51 #define BUF_LEN 256
52
53 SOCKET open_listeningsocket()
54 {
55   SOCKET listening_socket;
56   struct sockaddr_in sin;
57   int sock_optval = 1;
58   int port = 5000;
59   
60   listening_socket = socket(AF_INET, SOCK_STREAM, 0);
61   if ( listening_socket == -1 ){
62     perror("socket");
63     exit(1);
64   }
65   
66   if ( setsockopt(listening_socket, SOL_SOCKET, SO_REUSEADDR,
67                   &sock_optval, sizeof(sock_optval)) == -1 ){
68     perror("setsockopt");
69     exit(1);
70   }
71
72   memset(&sin, 0, sizeof(sin));
73   sin.sin_family = AF_INET;
74   sin.sin_port = htons(port);
75   sin.sin_addr.s_addr = htonl(INADDR_ANY);
76
77   if ( bind(listening_socket, (struct sockaddr *)&sin, sizeof(sin)) < 0 ){
78     perror("bind");
79     close_socket(listening_socket);
80     exit(1);
81   }
82
83   if( listen(listening_socket, SOMAXCONN) == -1){
84     perror("listen");
85     close_socket(listening_socket);
86     exit(1);
87   }
88   printf("port %d is listened\n", port);
89
90   return listening_socket;
91 }
92
93 SOCKET accept_socket( SOCKET listening_socket)
94 {
95   struct sockaddr_in peer_sin;
96   unsigned int addrlen = sizeof(peer_sin);
97
98   return accept( listening_socket, (struct sockaddr *)&peer_sin, &addrlen);
99 }
100
101 msgtype_t identify_clientmsg( SOCKET connected_socket)
102 {
103   int receive_size;
104   char buf[BUF_LEN];
105   char *magicid[] = { "JPIP-stream", "PNM request", "XML request", "TID request", "CID request", "CID destroy", "JP2 save", "QUIT"};
106   int i;
107   
108   receive_size = receive_line( connected_socket, buf);
109
110   if( receive_size == 0){ 
111     fprintf( stderr, "Error to receive the header of client message\n");
112     return MSGERROR;
113   }
114
115   for( i=0; i<NUM_OF_MSGTYPES; i++){
116     if( strncasecmp( magicid[i], buf, strlen(magicid[i])) == 0){
117       printf("%s\n", magicid[i]);
118       return i;
119     }
120   }
121   
122   fprintf( stderr, "Cannot identify client message type %s\n", buf);
123   return MSGERROR;
124 }
125
126 Byte_t * receive_JPIPstream( SOCKET connected_socket, char **target, char **tid, char **cid, int *streamlen)
127 {
128   Byte_t *jpipstream=NULL, *ptr;
129   char buf[BUF_LEN], versionstring[] = "version 1.2";
130   int linelen, redlen, remlen;
131   
132   *target = *cid = *tid = NULL;
133   
134   if((linelen = receive_line( connected_socket, buf)) == 0)
135     return NULL;
136   if( strncmp( versionstring, buf, strlen(versionstring))!=0){
137     fprintf( stderr, "Wrong format\n");
138     return NULL;
139   }
140   
141   if((linelen = receive_line( connected_socket, buf)) == 0)
142     return NULL;
143
144   if( strstr( buf, "jp2")){ 
145     // register cid option
146     *target = strdup( buf);
147     
148     if((linelen = receive_line( connected_socket, buf)) == 0)
149       return NULL;
150     if( strcmp( buf, "0") != 0)
151       *tid = strdup( buf);
152
153     if((linelen = receive_line( connected_socket, buf)) == 0)
154       return NULL;
155     if( strcmp( buf, "0") != 0)
156       *cid = strdup( buf);
157     
158     if((linelen = receive_line( connected_socket, buf)) == 0)
159       return NULL;
160   }
161
162   *streamlen = atoi( buf);
163   fprintf( stderr, "Receive Data: %d Bytes\n", *streamlen);
164   
165   jpipstream = (unsigned  char *)malloc( (*streamlen));
166   ptr = jpipstream;
167   remlen = (*streamlen);
168   while( remlen > 0){
169     redlen = recv( connected_socket, ptr, remlen, 0);
170     if( redlen == -1){
171       fprintf( stderr, "receive JPT- JPP- stream error\n");
172       break;
173     }
174     remlen -= redlen;
175     ptr = ptr + redlen;
176   }
177     
178   return jpipstream;
179 }
180
181 void send_stream( SOCKET connected_socket, void *stream, int length);
182
183 void send_XMLstream( SOCKET connected_socket, Byte_t *xmlstream, int length)
184 {
185   Byte_t header[5];
186   
187   header[0] = 'X';
188   header[1] = 'M';
189   header[2] = 'L';
190   header[3] = (length >> 8) & 0xff;
191   header[4] = length & 0xff;
192
193   send_stream( connected_socket, header, 5);
194   send_stream( connected_socket, xmlstream, length);
195 }
196
197 void send_IDstream(  SOCKET connected_socket, char *id, int idlen, char *label);
198
199 void send_CIDstream( SOCKET connected_socket, char *cid, int cidlen)
200 {
201   send_IDstream( connected_socket, cid, cidlen, "CID");
202 }
203
204 void send_TIDstream( SOCKET connected_socket, char *tid, int tidlen)
205 {
206   send_IDstream( connected_socket, tid, tidlen, "TID");
207 }
208
209 void send_IDstream(  SOCKET connected_socket, char *id, int idlen, char *label)
210 {
211   Byte_t header[4];
212
213   header[0] = label[0];
214   header[1] = label[1];
215   header[2] = label[2];
216   header[3] = idlen & 0xff;
217
218   send_stream( connected_socket, header, 4);
219   send_stream( connected_socket, id, idlen);
220 }
221
222 void send_PNMstream( SOCKET connected_socket, Byte_t *pnmstream, unsigned int width, unsigned int height, unsigned int numofcomp, Byte_t maxval)
223
224   int pnmlen = 0;
225   Byte_t header[7];
226
227   pnmlen = width*height*numofcomp;
228   
229   header[0] = 'P';
230   header[1] = numofcomp==3 ? 6:5;
231   header[2] = (width >> 8) & 0xff;
232   header[3] = width & 0xff;
233   header[4] = (height >> 8) & 0xff;
234   header[5] = height & 0xff;
235   header[6] = maxval;
236
237   send_stream( connected_socket, header, 7);
238   send_stream( connected_socket, pnmstream, pnmlen);
239 }
240
241 void send_stream( SOCKET connected_socket, void *stream, int length)
242 {
243   void *ptr = stream;
244   int remlen = length;
245
246   while( remlen > 0){
247     int sentlen = send( connected_socket, ptr, remlen, 0);
248     if( sentlen == -1){
249       fprintf( stderr, "sending stream error\n");
250       break;
251     }
252     remlen = remlen - sentlen;
253     ptr = ptr + sentlen;
254   }
255 }
256
257 int receive_line(SOCKET connected_socket, char *p)
258 {
259   int len = 0;
260   while (1){
261     int ret;
262     ret = recv( connected_socket, p, 1, 0);
263     if ( ret == -1 ){
264       perror("receive");
265       exit(1);
266     } else if ( ret == 0 ){
267       break;
268     }
269     if ( *p == '\n' )
270       break;
271     p++;
272     len++;
273   }
274   *p = '\0';
275
276   if( len == 0)
277     fprintf( stderr, "Header receive error\n");
278
279   return len;
280 }
281
282 char * receive_string( SOCKET connected_socket)
283 {
284   char buf[BUF_LEN];
285   
286   receive_line( connected_socket, buf);
287     
288   return strdup(buf);
289 }
290
291 void response_signal( SOCKET connected_socket, bool succeed)
292 {
293   Byte_t code;
294
295   if( succeed)
296     code = 1;
297   else
298     code = 0;
299
300   if( send( connected_socket, &code, 1, 0) != 1)
301     fprintf( stderr, "Response signalling error\n");
302 }
303
304 int close_socket( SOCKET sock)
305 {
306 #ifdef _WIN32
307   return closesocket( sock);
308 #else
309   return close( sock);
310 #endif
311 }