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
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
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.
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.
34 #include "auxtrans_manager.h"
43 #include "fcgi_stdio.h"
44 #define logstream FCGI_stdout
46 #define FCGI_stdout stdout
47 #define FCGI_stderr stderr
48 #define logstream stderr
51 auxtrans_param_t init_aux_transport(int tcp_auxport, int udp_auxport)
53 auxtrans_param_t auxtrans;
55 auxtrans.tcpauxport = tcp_auxport;
56 auxtrans.udpauxport = udp_auxport;
58 if (49152 <= tcp_auxport && tcp_auxport <= 65535) {
59 auxtrans.tcplistensock = open_listeningsocket((uint16_t)tcp_auxport);
61 auxtrans.tcplistensock = -1;
64 auxtrans.udplistensock = -1;
65 /* open listening socket for udp later */
70 void close_aux_transport(auxtrans_param_t auxtrans)
72 if (auxtrans.tcplistensock != -1)
73 if (close_socket(auxtrans.tcplistensock) != 0) {
77 if (auxtrans.udplistensock != -1)
78 if (close_socket(auxtrans.udplistensock) != 0) {
84 /*!< auxiliary response parameters */
85 typedef struct aux_response_param {
86 char *cid; /*!< channel ID */
87 unsigned char *data; /*!< sending data */
88 OPJ_SIZE_T datalen; /*!< length of data */
89 OPJ_SIZE_T maxlenPerFrame; /*!< maximum data length to send per frame */
90 SOCKET listensock; /*!< listeing socket */
92 HANDLE hTh; /*!< thread handle */
94 } aux_response_param_t;
96 aux_response_param_t * gene_auxresponse(OPJ_BOOL istcp,
97 auxtrans_param_t auxtrans, const char cid[], void *data, OPJ_SIZE_T datalen,
98 OPJ_SIZE_T maxlenPerFrame);
100 void delete_auxresponse(aux_response_param_t **auxresponse);
104 unsigned __stdcall aux_streaming(void *arg);
106 void * aux_streaming(void *arg);
109 void send_responsedata_on_aux(OPJ_BOOL istcp, auxtrans_param_t auxtrans,
110 const char cid[], void *data, OPJ_SIZE_T datalen, OPJ_SIZE_T maxlenPerFrame)
112 aux_response_param_t *auxresponse;
114 unsigned int threadId;
121 if (auxtrans.tcplistensock == -1) {
123 "Error: error in send_responsedata_on_aux(), tcp listening socket no open\n");
127 auxresponse = gene_auxresponse(istcp, auxtrans, cid, data, datalen,
131 auxresponse->hTh = (HANDLE)_beginthreadex(NULL, 0, &aux_streaming, auxresponse,
133 if (auxresponse->hTh == 0) {
134 fprintf(FCGI_stderr, "ERRO: pthread_create() %s",
135 strerror((int)auxresponse->hTh));
138 status = pthread_create(&thread, NULL, &aux_streaming, auxresponse);
140 fprintf(FCGI_stderr, "ERROR: pthread_create() %s", strerror(status));
145 "Error: error in send_responsedata_on_aux(), udp not implemented\n");
149 aux_response_param_t * gene_auxresponse(OPJ_BOOL istcp,
150 auxtrans_param_t auxtrans, const char cid[], void *data, OPJ_SIZE_T datalen,
151 OPJ_SIZE_T maxlenPerFrame)
153 aux_response_param_t *auxresponse;
155 auxresponse = (aux_response_param_t *)opj_malloc(sizeof(aux_response_param_t));
157 auxresponse->cid = strdup(cid);
158 auxresponse->data = data;
159 auxresponse->datalen = datalen;
160 auxresponse->maxlenPerFrame = maxlenPerFrame;
161 auxresponse->listensock = istcp ? auxtrans.tcplistensock :
162 auxtrans.udplistensock;
167 void delete_auxresponse(aux_response_param_t **auxresponse)
169 opj_free((*auxresponse)->cid);
170 opj_free((*auxresponse)->data);
171 opj_free(*auxresponse);
175 * Identify cid sent from client
177 * @param [in] connected_socket file descriptor of the connected socket
178 * @param [in] refcid refenrece channel ID
179 * @param [in] fp file pointer for log of aux stream
180 * @return true if identified, false otherwise
182 OPJ_BOOL identify_cid(SOCKET connected_socket, char refcid[], FILE *fp);
184 OPJ_BOOL recv_ack(SOCKET connected_socket, void *data);
187 unsigned __stdcall aux_streaming(void *arg)
189 void * aux_streaming(void *arg)
192 SOCKET connected_socket;
193 unsigned char *chunk, *ptr;
194 OPJ_SIZE_T maxLenOfBody, remlen, chunklen;
195 const OPJ_SIZE_T headlen = 8;
197 aux_response_param_t *auxresponse = (aux_response_param_t *)arg;
200 CloseHandle(auxresponse->hTh);
202 pthread_detach(pthread_self());
205 chunk = (unsigned char *)opj_malloc(auxresponse->maxlenPerFrame);
206 maxLenOfBody = auxresponse->maxlenPerFrame - headlen;
207 remlen = auxresponse->datalen;
209 while ((connected_socket = accept_socket(auxresponse->listensock)) != -1) {
210 if (identify_cid(connected_socket, auxresponse->cid, FCGI_stderr)) {
211 ptr = auxresponse->data;
213 memset(chunk, 0, auxresponse->maxlenPerFrame);
215 chunklen = remlen < maxLenOfBody ? remlen : maxLenOfBody;
218 chunk[0] = (chunklen >> 8) & 0xff;
219 chunk[1] = chunklen & 0xff;
221 memcpy(chunk + headlen, ptr, chunklen - headlen);
224 send_stream(connected_socket, chunk, chunklen);
225 } while (!recv_ack(connected_socket, chunk));
227 remlen -= maxLenOfBody;
230 if (close_socket(connected_socket) != 0) {
235 if (close_socket(connected_socket) != 0) {
241 delete_auxresponse(&auxresponse);
253 OPJ_BOOL identify_cid(SOCKET connected_socket, char refcid[], FILE *fp)
258 if (!(cid = receive_string(connected_socket))) {
260 "Error: error in identify_cid(), while receiving cid from client\n");
265 if (strncmp(refcid, cid, strlen(refcid)) == 0) {
274 OPJ_BOOL recv_ack(SOCKET connected_socket, void *data)
279 header = receive_stream(connected_socket, 8);
281 if (memcmp(header, data, 8) != 0) {