5634556d403c5a1443cf8d3673f63c90a8912032
[openjpeg.git] / src / lib / openjpip / sock_manager.c
1 /*
2  * $Id$
3  *
4  * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium
5  * Copyright (c) 2002-2014, Professor Benoit Macq
6  * Copyright (c) 2010-2011, Kaori Hagihara
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #ifdef _WIN32
32 #include <windows.h>
33 typedef SSIZE_T ssize_t;
34 #else
35 #include <sys/types.h>
36 #include <sys/socket.h>
37 #include <arpa/inet.h>
38 #include <unistd.h>
39 #endif
40
41 #include <stdio.h>
42 #include <string.h>
43 #include <stdlib.h>
44 #include "sock_manager.h"
45
46 #ifdef SERVER
47 #include "fcgi_stdio.h"
48 #define logstream FCGI_stdout
49 #else
50 #define FCGI_stdout stdout
51 #define FCGI_stderr stderr
52 #define logstream stderr
53 #endif /*SERVER*/
54
55 SOCKET open_listeningsocket( uint16_t port)
56 {
57   SOCKET listening_socket;
58   struct sockaddr_in sin;
59   int sock_optval = 1;
60   
61   listening_socket = socket(AF_INET, SOCK_STREAM, 0);
62   if ( listening_socket == -1 ){
63     perror("socket");
64     exit(1);
65   }
66   
67   if ( setsockopt(listening_socket, SOL_SOCKET, SO_REUSEADDR, (const char *)&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   fprintf( FCGI_stderr, "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 void send_stream( SOCKET connected_socket, const void *stream, OPJ_SIZE_T length)
102 {
103   char *ptr = (char*)stream;
104   OPJ_SIZE_T remlen = length;
105
106   while( remlen > 0){
107     ssize_t sentlen = send( connected_socket, ptr, remlen, 0);
108     if( sentlen == -1){
109       fprintf( FCGI_stderr, "sending stream error\n");
110       break;
111     }
112     remlen = remlen - (OPJ_SIZE_T)sentlen;
113     ptr = ptr + sentlen;
114   }
115 }
116
117 void * receive_stream( SOCKET connected_socket, OPJ_SIZE_T length)
118 {
119   char *stream, *ptr;
120   OPJ_SIZE_T remlen;
121
122   ptr = stream = malloc( length);
123   remlen = length;
124
125   while( remlen > 0){
126     ssize_t redlen = recv( connected_socket, ptr, remlen, 0);
127     if( redlen == -1){
128       fprintf( FCGI_stderr, "receive stream error\n");
129       free( stream);
130       stream = NULL;
131       break;
132     }
133     remlen -= (OPJ_SIZE_T)redlen;
134     ptr = ptr + redlen;
135   }
136   return stream;
137 }
138
139 OPJ_SIZE_T receive_line(SOCKET connected_socket, char *p)
140 {
141   OPJ_SIZE_T len = 0;
142   while (1){
143     ssize_t ret;
144     ret = recv( connected_socket, p, 1, 0);
145     if ( ret == -1 ){
146       perror("receive");
147       exit(1);
148     } else if ( ret == 0 ){
149       break;
150     }
151     if ( *p == '\n' )
152       break;
153     p++;
154     len++;
155   }
156   *p = '\0';
157
158   if( len == 0)
159     fprintf( FCGI_stderr, "Header receive error\n");
160
161   return len;
162 }
163
164 char * receive_string( SOCKET connected_socket)
165 {
166   char buf[BUF_LEN];
167   
168   /* MM FIXME: there is a nasty bug here, size of buf if BUF_LEN which is never
169   indicated to downstream receive_line */
170   receive_line( connected_socket, buf);
171     
172   return strdup(buf);
173 }
174
175 int close_socket( SOCKET sock)
176 {
177 #ifdef _WIN32
178   return closesocket( sock);
179 #else
180   return close( sock);
181 #endif
182 }