1*6236dae4SAndroid Build Coastguard Worker /***************************************************************************
2*6236dae4SAndroid Build Coastguard Worker * _ _ ____ _
3*6236dae4SAndroid Build Coastguard Worker * Project ___| | | | _ \| |
4*6236dae4SAndroid Build Coastguard Worker * / __| | | | |_) | |
5*6236dae4SAndroid Build Coastguard Worker * | (__| |_| | _ <| |___
6*6236dae4SAndroid Build Coastguard Worker * \___|\___/|_| \_\_____|
7*6236dae4SAndroid Build Coastguard Worker *
8*6236dae4SAndroid Build Coastguard Worker * Copyright (C) Daniel Stenberg, <[email protected]>, et al.
9*6236dae4SAndroid Build Coastguard Worker *
10*6236dae4SAndroid Build Coastguard Worker * This software is licensed as described in the file COPYING, which
11*6236dae4SAndroid Build Coastguard Worker * you should have received as part of this distribution. The terms
12*6236dae4SAndroid Build Coastguard Worker * are also available at https://curl.se/docs/copyright.html.
13*6236dae4SAndroid Build Coastguard Worker *
14*6236dae4SAndroid Build Coastguard Worker * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15*6236dae4SAndroid Build Coastguard Worker * copies of the Software, and permit persons to whom the Software is
16*6236dae4SAndroid Build Coastguard Worker * furnished to do so, under the terms of the COPYING file.
17*6236dae4SAndroid Build Coastguard Worker *
18*6236dae4SAndroid Build Coastguard Worker * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19*6236dae4SAndroid Build Coastguard Worker * KIND, either express or implied.
20*6236dae4SAndroid Build Coastguard Worker *
21*6236dae4SAndroid Build Coastguard Worker * SPDX-License-Identifier: curl
22*6236dae4SAndroid Build Coastguard Worker *
23*6236dae4SAndroid Build Coastguard Worker ***************************************************************************/
24*6236dae4SAndroid Build Coastguard Worker #include "server_setup.h"
25*6236dae4SAndroid Build Coastguard Worker
26*6236dae4SAndroid Build Coastguard Worker /*
27*6236dae4SAndroid Build Coastguard Worker * curl's test suite Real Time Streaming Protocol (RTSP) server.
28*6236dae4SAndroid Build Coastguard Worker *
29*6236dae4SAndroid Build Coastguard Worker * This source file was started based on curl's HTTP test suite server.
30*6236dae4SAndroid Build Coastguard Worker */
31*6236dae4SAndroid Build Coastguard Worker
32*6236dae4SAndroid Build Coastguard Worker #include <signal.h>
33*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_NETINET_IN_H
34*6236dae4SAndroid Build Coastguard Worker #include <netinet/in.h>
35*6236dae4SAndroid Build Coastguard Worker #endif
36*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_NETINET_IN6_H
37*6236dae4SAndroid Build Coastguard Worker #include <netinet/in6.h>
38*6236dae4SAndroid Build Coastguard Worker #endif
39*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_ARPA_INET_H
40*6236dae4SAndroid Build Coastguard Worker #include <arpa/inet.h>
41*6236dae4SAndroid Build Coastguard Worker #endif
42*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_NETDB_H
43*6236dae4SAndroid Build Coastguard Worker #include <netdb.h>
44*6236dae4SAndroid Build Coastguard Worker #endif
45*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_NETINET_TCP_H
46*6236dae4SAndroid Build Coastguard Worker #include <netinet/tcp.h> /* for TCP_NODELAY */
47*6236dae4SAndroid Build Coastguard Worker #endif
48*6236dae4SAndroid Build Coastguard Worker
49*6236dae4SAndroid Build Coastguard Worker #include "curlx.h" /* from the private lib dir */
50*6236dae4SAndroid Build Coastguard Worker #include "getpart.h"
51*6236dae4SAndroid Build Coastguard Worker #include "util.h"
52*6236dae4SAndroid Build Coastguard Worker #include "server_sockaddr.h"
53*6236dae4SAndroid Build Coastguard Worker
54*6236dae4SAndroid Build Coastguard Worker /* include memdebug.h last */
55*6236dae4SAndroid Build Coastguard Worker #include "memdebug.h"
56*6236dae4SAndroid Build Coastguard Worker
57*6236dae4SAndroid Build Coastguard Worker #ifdef USE_WINSOCK
58*6236dae4SAndroid Build Coastguard Worker #undef EINTR
59*6236dae4SAndroid Build Coastguard Worker #define EINTR 4 /* errno.h value */
60*6236dae4SAndroid Build Coastguard Worker #undef ERANGE
61*6236dae4SAndroid Build Coastguard Worker #define ERANGE 34 /* errno.h value */
62*6236dae4SAndroid Build Coastguard Worker #endif
63*6236dae4SAndroid Build Coastguard Worker
64*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
65*6236dae4SAndroid Build Coastguard Worker static bool use_ipv6 = FALSE;
66*6236dae4SAndroid Build Coastguard Worker #endif
67*6236dae4SAndroid Build Coastguard Worker static const char *ipv_inuse = "IPv4";
68*6236dae4SAndroid Build Coastguard Worker static int serverlogslocked = 0;
69*6236dae4SAndroid Build Coastguard Worker
70*6236dae4SAndroid Build Coastguard Worker #define REQBUFSIZ 150000
71*6236dae4SAndroid Build Coastguard Worker #define REQBUFSIZ_TXT "149999"
72*6236dae4SAndroid Build Coastguard Worker
73*6236dae4SAndroid Build Coastguard Worker static long prevtestno = -1; /* previous test number we served */
74*6236dae4SAndroid Build Coastguard Worker static long prevpartno = -1; /* previous part number we served */
75*6236dae4SAndroid Build Coastguard Worker static bool prevbounce = FALSE; /* instructs the server to increase the part
76*6236dae4SAndroid Build Coastguard Worker number for a test in case the identical
77*6236dae4SAndroid Build Coastguard Worker testno+partno request shows up again */
78*6236dae4SAndroid Build Coastguard Worker
79*6236dae4SAndroid Build Coastguard Worker #define RCMD_NORMALREQ 0 /* default request, use the tests file normally */
80*6236dae4SAndroid Build Coastguard Worker #define RCMD_IDLE 1 /* told to sit idle */
81*6236dae4SAndroid Build Coastguard Worker #define RCMD_STREAM 2 /* told to stream */
82*6236dae4SAndroid Build Coastguard Worker
83*6236dae4SAndroid Build Coastguard Worker typedef enum {
84*6236dae4SAndroid Build Coastguard Worker RPROT_NONE = 0,
85*6236dae4SAndroid Build Coastguard Worker RPROT_RTSP = 1,
86*6236dae4SAndroid Build Coastguard Worker RPROT_HTTP = 2
87*6236dae4SAndroid Build Coastguard Worker } reqprot_t;
88*6236dae4SAndroid Build Coastguard Worker
89*6236dae4SAndroid Build Coastguard Worker #define SET_RTP_PKT_CHN(p,c) ((p)[1] = (char)((c) & 0xFF))
90*6236dae4SAndroid Build Coastguard Worker
91*6236dae4SAndroid Build Coastguard Worker #define SET_RTP_PKT_LEN(p,l) (((p)[2] = (char)(((l) >> 8) & 0xFF)), \
92*6236dae4SAndroid Build Coastguard Worker ((p)[3] = (char)((l) & 0xFF)))
93*6236dae4SAndroid Build Coastguard Worker
94*6236dae4SAndroid Build Coastguard Worker struct httprequest {
95*6236dae4SAndroid Build Coastguard Worker char reqbuf[REQBUFSIZ]; /* buffer area for the incoming request */
96*6236dae4SAndroid Build Coastguard Worker size_t checkindex; /* where to start checking of the request */
97*6236dae4SAndroid Build Coastguard Worker size_t offset; /* size of the incoming request */
98*6236dae4SAndroid Build Coastguard Worker long testno; /* test number found in the request */
99*6236dae4SAndroid Build Coastguard Worker long partno; /* part number found in the request */
100*6236dae4SAndroid Build Coastguard Worker bool open; /* keep connection open info, as found in the request */
101*6236dae4SAndroid Build Coastguard Worker bool auth_req; /* authentication required, don't wait for body unless
102*6236dae4SAndroid Build Coastguard Worker there's an Authorization header */
103*6236dae4SAndroid Build Coastguard Worker bool auth; /* Authorization header present in the incoming request */
104*6236dae4SAndroid Build Coastguard Worker size_t cl; /* Content-Length of the incoming request */
105*6236dae4SAndroid Build Coastguard Worker bool digest; /* Authorization digest header found */
106*6236dae4SAndroid Build Coastguard Worker bool ntlm; /* Authorization NTLM header found */
107*6236dae4SAndroid Build Coastguard Worker int pipe; /* if non-zero, expect this many requests to do a "piped"
108*6236dae4SAndroid Build Coastguard Worker request/response */
109*6236dae4SAndroid Build Coastguard Worker int skip; /* if non-zero, the server is instructed to not read this
110*6236dae4SAndroid Build Coastguard Worker many bytes from a PUT/POST request. Ie the client sends N
111*6236dae4SAndroid Build Coastguard Worker bytes said in Content-Length, but the server only reads N
112*6236dae4SAndroid Build Coastguard Worker - skip bytes. */
113*6236dae4SAndroid Build Coastguard Worker int rcmd; /* doing a special command, see defines above */
114*6236dae4SAndroid Build Coastguard Worker reqprot_t protocol; /* request protocol, HTTP or RTSP */
115*6236dae4SAndroid Build Coastguard Worker int prot_version; /* HTTP or RTSP version (major*10 + minor) */
116*6236dae4SAndroid Build Coastguard Worker bool pipelining; /* true if request is pipelined */
117*6236dae4SAndroid Build Coastguard Worker char *rtp_buffer;
118*6236dae4SAndroid Build Coastguard Worker size_t rtp_buffersize;
119*6236dae4SAndroid Build Coastguard Worker };
120*6236dae4SAndroid Build Coastguard Worker
121*6236dae4SAndroid Build Coastguard Worker static int ProcessRequest(struct httprequest *req);
122*6236dae4SAndroid Build Coastguard Worker static void storerequest(char *reqbuf, size_t totalsize);
123*6236dae4SAndroid Build Coastguard Worker
124*6236dae4SAndroid Build Coastguard Worker #define DEFAULT_PORT 8999
125*6236dae4SAndroid Build Coastguard Worker
126*6236dae4SAndroid Build Coastguard Worker #ifndef DEFAULT_LOGFILE
127*6236dae4SAndroid Build Coastguard Worker #define DEFAULT_LOGFILE "log/rtspd.log"
128*6236dae4SAndroid Build Coastguard Worker #endif
129*6236dae4SAndroid Build Coastguard Worker
130*6236dae4SAndroid Build Coastguard Worker const char *serverlogfile = DEFAULT_LOGFILE;
131*6236dae4SAndroid Build Coastguard Worker static const char *logdir = "log";
132*6236dae4SAndroid Build Coastguard Worker static char loglockfile[256];
133*6236dae4SAndroid Build Coastguard Worker
134*6236dae4SAndroid Build Coastguard Worker #define RTSPDVERSION "curl test suite RTSP server/0.1"
135*6236dae4SAndroid Build Coastguard Worker
136*6236dae4SAndroid Build Coastguard Worker #define REQUEST_DUMP "server.input"
137*6236dae4SAndroid Build Coastguard Worker #define RESPONSE_DUMP "server.response"
138*6236dae4SAndroid Build Coastguard Worker
139*6236dae4SAndroid Build Coastguard Worker /* very-big-path support */
140*6236dae4SAndroid Build Coastguard Worker #define MAXDOCNAMELEN 140000
141*6236dae4SAndroid Build Coastguard Worker #define MAXDOCNAMELEN_TXT "139999"
142*6236dae4SAndroid Build Coastguard Worker
143*6236dae4SAndroid Build Coastguard Worker #define REQUEST_KEYWORD_SIZE 256
144*6236dae4SAndroid Build Coastguard Worker #define REQUEST_KEYWORD_SIZE_TXT "255"
145*6236dae4SAndroid Build Coastguard Worker
146*6236dae4SAndroid Build Coastguard Worker #define CMD_AUTH_REQUIRED "auth_required"
147*6236dae4SAndroid Build Coastguard Worker
148*6236dae4SAndroid Build Coastguard Worker /* 'idle' means that it will accept the request fine but never respond
149*6236dae4SAndroid Build Coastguard Worker any data. Just keep the connection alive. */
150*6236dae4SAndroid Build Coastguard Worker #define CMD_IDLE "idle"
151*6236dae4SAndroid Build Coastguard Worker
152*6236dae4SAndroid Build Coastguard Worker /* 'stream' means to send a never-ending stream of data */
153*6236dae4SAndroid Build Coastguard Worker #define CMD_STREAM "stream"
154*6236dae4SAndroid Build Coastguard Worker
155*6236dae4SAndroid Build Coastguard Worker #define END_OF_HEADERS "\r\n\r\n"
156*6236dae4SAndroid Build Coastguard Worker
157*6236dae4SAndroid Build Coastguard Worker enum {
158*6236dae4SAndroid Build Coastguard Worker DOCNUMBER_NOTHING = -7,
159*6236dae4SAndroid Build Coastguard Worker DOCNUMBER_QUIT = -6,
160*6236dae4SAndroid Build Coastguard Worker DOCNUMBER_BADCONNECT = -5,
161*6236dae4SAndroid Build Coastguard Worker DOCNUMBER_INTERNAL = -4,
162*6236dae4SAndroid Build Coastguard Worker DOCNUMBER_CONNECT = -3,
163*6236dae4SAndroid Build Coastguard Worker DOCNUMBER_WERULEZ = -2,
164*6236dae4SAndroid Build Coastguard Worker DOCNUMBER_404 = -1
165*6236dae4SAndroid Build Coastguard Worker };
166*6236dae4SAndroid Build Coastguard Worker
167*6236dae4SAndroid Build Coastguard Worker
168*6236dae4SAndroid Build Coastguard Worker /* sent as reply to a QUIT */
169*6236dae4SAndroid Build Coastguard Worker static const char *docquit =
170*6236dae4SAndroid Build Coastguard Worker "HTTP/1.1 200 Goodbye" END_OF_HEADERS;
171*6236dae4SAndroid Build Coastguard Worker
172*6236dae4SAndroid Build Coastguard Worker /* sent as reply to a CONNECT */
173*6236dae4SAndroid Build Coastguard Worker static const char *docconnect =
174*6236dae4SAndroid Build Coastguard Worker "HTTP/1.1 200 Mighty fine indeed" END_OF_HEADERS;
175*6236dae4SAndroid Build Coastguard Worker
176*6236dae4SAndroid Build Coastguard Worker /* sent as reply to a "bad" CONNECT */
177*6236dae4SAndroid Build Coastguard Worker static const char *docbadconnect =
178*6236dae4SAndroid Build Coastguard Worker "HTTP/1.1 501 Forbidden you fool" END_OF_HEADERS;
179*6236dae4SAndroid Build Coastguard Worker
180*6236dae4SAndroid Build Coastguard Worker /* send back this on HTTP 404 file not found */
181*6236dae4SAndroid Build Coastguard Worker static const char *doc404_HTTP = "HTTP/1.1 404 Not Found\r\n"
182*6236dae4SAndroid Build Coastguard Worker "Server: " RTSPDVERSION "\r\n"
183*6236dae4SAndroid Build Coastguard Worker "Connection: close\r\n"
184*6236dae4SAndroid Build Coastguard Worker "Content-Type: text/html"
185*6236dae4SAndroid Build Coastguard Worker END_OF_HEADERS
186*6236dae4SAndroid Build Coastguard Worker "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n"
187*6236dae4SAndroid Build Coastguard Worker "<HTML><HEAD>\n"
188*6236dae4SAndroid Build Coastguard Worker "<TITLE>404 Not Found</TITLE>\n"
189*6236dae4SAndroid Build Coastguard Worker "</HEAD><BODY>\n"
190*6236dae4SAndroid Build Coastguard Worker "<H1>Not Found</H1>\n"
191*6236dae4SAndroid Build Coastguard Worker "The requested URL was not found on this server.\n"
192*6236dae4SAndroid Build Coastguard Worker "<P><HR><ADDRESS>" RTSPDVERSION "</ADDRESS>\n" "</BODY></HTML>\n";
193*6236dae4SAndroid Build Coastguard Worker
194*6236dae4SAndroid Build Coastguard Worker /* send back this on RTSP 404 file not found */
195*6236dae4SAndroid Build Coastguard Worker static const char *doc404_RTSP = "RTSP/1.0 404 Not Found\r\n"
196*6236dae4SAndroid Build Coastguard Worker "Server: " RTSPDVERSION
197*6236dae4SAndroid Build Coastguard Worker END_OF_HEADERS;
198*6236dae4SAndroid Build Coastguard Worker
199*6236dae4SAndroid Build Coastguard Worker /* Default size to send away fake RTP data */
200*6236dae4SAndroid Build Coastguard Worker #define RTP_DATA_SIZE 12
201*6236dae4SAndroid Build Coastguard Worker static const char *RTP_DATA = "$_1234\n\0Rsdf";
202*6236dae4SAndroid Build Coastguard Worker
ProcessRequest(struct httprequest * req)203*6236dae4SAndroid Build Coastguard Worker static int ProcessRequest(struct httprequest *req)
204*6236dae4SAndroid Build Coastguard Worker {
205*6236dae4SAndroid Build Coastguard Worker char *line = &req->reqbuf[req->checkindex];
206*6236dae4SAndroid Build Coastguard Worker bool chunked = FALSE;
207*6236dae4SAndroid Build Coastguard Worker static char request[REQUEST_KEYWORD_SIZE];
208*6236dae4SAndroid Build Coastguard Worker static char doc[MAXDOCNAMELEN];
209*6236dae4SAndroid Build Coastguard Worker static char prot_str[5];
210*6236dae4SAndroid Build Coastguard Worker int prot_major, prot_minor;
211*6236dae4SAndroid Build Coastguard Worker char *end = strstr(line, END_OF_HEADERS);
212*6236dae4SAndroid Build Coastguard Worker
213*6236dae4SAndroid Build Coastguard Worker logmsg("ProcessRequest() called with testno %ld and line [%s]",
214*6236dae4SAndroid Build Coastguard Worker req->testno, line);
215*6236dae4SAndroid Build Coastguard Worker
216*6236dae4SAndroid Build Coastguard Worker /* try to figure out the request characteristics as soon as possible, but
217*6236dae4SAndroid Build Coastguard Worker only once! */
218*6236dae4SAndroid Build Coastguard Worker if((req->testno == DOCNUMBER_NOTHING) &&
219*6236dae4SAndroid Build Coastguard Worker sscanf(line,
220*6236dae4SAndroid Build Coastguard Worker "%" REQUEST_KEYWORD_SIZE_TXT"s %" MAXDOCNAMELEN_TXT "s %4s/%d.%d",
221*6236dae4SAndroid Build Coastguard Worker request,
222*6236dae4SAndroid Build Coastguard Worker doc,
223*6236dae4SAndroid Build Coastguard Worker prot_str,
224*6236dae4SAndroid Build Coastguard Worker &prot_major,
225*6236dae4SAndroid Build Coastguard Worker &prot_minor) == 5) {
226*6236dae4SAndroid Build Coastguard Worker char *ptr;
227*6236dae4SAndroid Build Coastguard Worker char logbuf[256];
228*6236dae4SAndroid Build Coastguard Worker
229*6236dae4SAndroid Build Coastguard Worker if(!strcmp(prot_str, "HTTP")) {
230*6236dae4SAndroid Build Coastguard Worker req->protocol = RPROT_HTTP;
231*6236dae4SAndroid Build Coastguard Worker }
232*6236dae4SAndroid Build Coastguard Worker else if(!strcmp(prot_str, "RTSP")) {
233*6236dae4SAndroid Build Coastguard Worker req->protocol = RPROT_RTSP;
234*6236dae4SAndroid Build Coastguard Worker }
235*6236dae4SAndroid Build Coastguard Worker else {
236*6236dae4SAndroid Build Coastguard Worker req->protocol = RPROT_NONE;
237*6236dae4SAndroid Build Coastguard Worker logmsg("got unknown protocol %s", prot_str);
238*6236dae4SAndroid Build Coastguard Worker return 1;
239*6236dae4SAndroid Build Coastguard Worker }
240*6236dae4SAndroid Build Coastguard Worker
241*6236dae4SAndroid Build Coastguard Worker req->prot_version = prot_major*10 + prot_minor;
242*6236dae4SAndroid Build Coastguard Worker
243*6236dae4SAndroid Build Coastguard Worker /* find the last slash */
244*6236dae4SAndroid Build Coastguard Worker ptr = strrchr(doc, '/');
245*6236dae4SAndroid Build Coastguard Worker
246*6236dae4SAndroid Build Coastguard Worker /* get the number after it */
247*6236dae4SAndroid Build Coastguard Worker if(ptr) {
248*6236dae4SAndroid Build Coastguard Worker FILE *stream;
249*6236dae4SAndroid Build Coastguard Worker if((strlen(doc) + strlen(request)) < 200)
250*6236dae4SAndroid Build Coastguard Worker msnprintf(logbuf, sizeof(logbuf), "Got request: %s %s %s/%d.%d",
251*6236dae4SAndroid Build Coastguard Worker request, doc, prot_str, prot_major, prot_minor);
252*6236dae4SAndroid Build Coastguard Worker else
253*6236dae4SAndroid Build Coastguard Worker msnprintf(logbuf, sizeof(logbuf), "Got a *HUGE* request %s/%d.%d",
254*6236dae4SAndroid Build Coastguard Worker prot_str, prot_major, prot_minor);
255*6236dae4SAndroid Build Coastguard Worker logmsg("%s", logbuf);
256*6236dae4SAndroid Build Coastguard Worker
257*6236dae4SAndroid Build Coastguard Worker if(!strncmp("/verifiedserver", ptr, 15)) {
258*6236dae4SAndroid Build Coastguard Worker logmsg("Are-we-friendly question received");
259*6236dae4SAndroid Build Coastguard Worker req->testno = DOCNUMBER_WERULEZ;
260*6236dae4SAndroid Build Coastguard Worker return 1; /* done */
261*6236dae4SAndroid Build Coastguard Worker }
262*6236dae4SAndroid Build Coastguard Worker
263*6236dae4SAndroid Build Coastguard Worker if(!strncmp("/quit", ptr, 5)) {
264*6236dae4SAndroid Build Coastguard Worker logmsg("Request-to-quit received");
265*6236dae4SAndroid Build Coastguard Worker req->testno = DOCNUMBER_QUIT;
266*6236dae4SAndroid Build Coastguard Worker return 1; /* done */
267*6236dae4SAndroid Build Coastguard Worker }
268*6236dae4SAndroid Build Coastguard Worker
269*6236dae4SAndroid Build Coastguard Worker ptr++; /* skip the slash */
270*6236dae4SAndroid Build Coastguard Worker
271*6236dae4SAndroid Build Coastguard Worker /* skip all non-numericals following the slash */
272*6236dae4SAndroid Build Coastguard Worker while(*ptr && !ISDIGIT(*ptr))
273*6236dae4SAndroid Build Coastguard Worker ptr++;
274*6236dae4SAndroid Build Coastguard Worker
275*6236dae4SAndroid Build Coastguard Worker req->testno = strtol(ptr, &ptr, 10);
276*6236dae4SAndroid Build Coastguard Worker
277*6236dae4SAndroid Build Coastguard Worker if(req->testno > 10000) {
278*6236dae4SAndroid Build Coastguard Worker req->partno = req->testno % 10000;
279*6236dae4SAndroid Build Coastguard Worker req->testno /= 10000;
280*6236dae4SAndroid Build Coastguard Worker }
281*6236dae4SAndroid Build Coastguard Worker else
282*6236dae4SAndroid Build Coastguard Worker req->partno = 0;
283*6236dae4SAndroid Build Coastguard Worker
284*6236dae4SAndroid Build Coastguard Worker msnprintf(logbuf, sizeof(logbuf), "Requested test number %ld part %ld",
285*6236dae4SAndroid Build Coastguard Worker req->testno, req->partno);
286*6236dae4SAndroid Build Coastguard Worker logmsg("%s", logbuf);
287*6236dae4SAndroid Build Coastguard Worker
288*6236dae4SAndroid Build Coastguard Worker stream = test2fopen(req->testno, logdir);
289*6236dae4SAndroid Build Coastguard Worker
290*6236dae4SAndroid Build Coastguard Worker if(!stream) {
291*6236dae4SAndroid Build Coastguard Worker int error = errno;
292*6236dae4SAndroid Build Coastguard Worker logmsg("fopen() failed with error: %d %s", error, strerror(error));
293*6236dae4SAndroid Build Coastguard Worker logmsg("Couldn't open test file %ld", req->testno);
294*6236dae4SAndroid Build Coastguard Worker req->open = FALSE; /* closes connection */
295*6236dae4SAndroid Build Coastguard Worker return 1; /* done */
296*6236dae4SAndroid Build Coastguard Worker }
297*6236dae4SAndroid Build Coastguard Worker else {
298*6236dae4SAndroid Build Coastguard Worker char *cmd = NULL;
299*6236dae4SAndroid Build Coastguard Worker size_t cmdsize = 0;
300*6236dae4SAndroid Build Coastguard Worker int num = 0;
301*6236dae4SAndroid Build Coastguard Worker
302*6236dae4SAndroid Build Coastguard Worker int rtp_channel = 0;
303*6236dae4SAndroid Build Coastguard Worker int rtp_size = 0;
304*6236dae4SAndroid Build Coastguard Worker int rtp_size_err = 0;
305*6236dae4SAndroid Build Coastguard Worker int rtp_partno = -1;
306*6236dae4SAndroid Build Coastguard Worker char *rtp_scratch = NULL;
307*6236dae4SAndroid Build Coastguard Worker
308*6236dae4SAndroid Build Coastguard Worker /* get the custom server control "commands" */
309*6236dae4SAndroid Build Coastguard Worker int error = getpart(&cmd, &cmdsize, "reply", "servercmd", stream);
310*6236dae4SAndroid Build Coastguard Worker fclose(stream);
311*6236dae4SAndroid Build Coastguard Worker if(error) {
312*6236dae4SAndroid Build Coastguard Worker logmsg("getpart() failed with error: %d", error);
313*6236dae4SAndroid Build Coastguard Worker req->open = FALSE; /* closes connection */
314*6236dae4SAndroid Build Coastguard Worker return 1; /* done */
315*6236dae4SAndroid Build Coastguard Worker }
316*6236dae4SAndroid Build Coastguard Worker ptr = cmd;
317*6236dae4SAndroid Build Coastguard Worker
318*6236dae4SAndroid Build Coastguard Worker if(cmdsize) {
319*6236dae4SAndroid Build Coastguard Worker logmsg("Found a reply-servercmd section!");
320*6236dae4SAndroid Build Coastguard Worker do {
321*6236dae4SAndroid Build Coastguard Worker rtp_size_err = 0;
322*6236dae4SAndroid Build Coastguard Worker if(!strncmp(CMD_AUTH_REQUIRED, ptr, strlen(CMD_AUTH_REQUIRED))) {
323*6236dae4SAndroid Build Coastguard Worker logmsg("instructed to require authorization header");
324*6236dae4SAndroid Build Coastguard Worker req->auth_req = TRUE;
325*6236dae4SAndroid Build Coastguard Worker }
326*6236dae4SAndroid Build Coastguard Worker else if(!strncmp(CMD_IDLE, ptr, strlen(CMD_IDLE))) {
327*6236dae4SAndroid Build Coastguard Worker logmsg("instructed to idle");
328*6236dae4SAndroid Build Coastguard Worker req->rcmd = RCMD_IDLE;
329*6236dae4SAndroid Build Coastguard Worker req->open = TRUE;
330*6236dae4SAndroid Build Coastguard Worker }
331*6236dae4SAndroid Build Coastguard Worker else if(!strncmp(CMD_STREAM, ptr, strlen(CMD_STREAM))) {
332*6236dae4SAndroid Build Coastguard Worker logmsg("instructed to stream");
333*6236dae4SAndroid Build Coastguard Worker req->rcmd = RCMD_STREAM;
334*6236dae4SAndroid Build Coastguard Worker }
335*6236dae4SAndroid Build Coastguard Worker else if(1 == sscanf(ptr, "pipe: %d", &num)) {
336*6236dae4SAndroid Build Coastguard Worker logmsg("instructed to allow a pipe size of %d", num);
337*6236dae4SAndroid Build Coastguard Worker if(num < 0)
338*6236dae4SAndroid Build Coastguard Worker logmsg("negative pipe size ignored");
339*6236dae4SAndroid Build Coastguard Worker else if(num > 0)
340*6236dae4SAndroid Build Coastguard Worker req->pipe = num-1; /* decrease by one since we don't count the
341*6236dae4SAndroid Build Coastguard Worker first request in this number */
342*6236dae4SAndroid Build Coastguard Worker }
343*6236dae4SAndroid Build Coastguard Worker else if(1 == sscanf(ptr, "skip: %d", &num)) {
344*6236dae4SAndroid Build Coastguard Worker logmsg("instructed to skip this number of bytes %d", num);
345*6236dae4SAndroid Build Coastguard Worker req->skip = num;
346*6236dae4SAndroid Build Coastguard Worker }
347*6236dae4SAndroid Build Coastguard Worker else if(3 <= sscanf(ptr,
348*6236dae4SAndroid Build Coastguard Worker "rtp: part %d channel %d size %d size_err %d",
349*6236dae4SAndroid Build Coastguard Worker &rtp_partno, &rtp_channel, &rtp_size,
350*6236dae4SAndroid Build Coastguard Worker &rtp_size_err)) {
351*6236dae4SAndroid Build Coastguard Worker
352*6236dae4SAndroid Build Coastguard Worker if(rtp_partno == req->partno) {
353*6236dae4SAndroid Build Coastguard Worker int i = 0;
354*6236dae4SAndroid Build Coastguard Worker logmsg("RTP: part %d channel %d size %d size_err %d",
355*6236dae4SAndroid Build Coastguard Worker rtp_partno, rtp_channel, rtp_size, rtp_size_err);
356*6236dae4SAndroid Build Coastguard Worker
357*6236dae4SAndroid Build Coastguard Worker /* Make our scratch buffer enough to fit all the
358*6236dae4SAndroid Build Coastguard Worker * desired data and one for padding */
359*6236dae4SAndroid Build Coastguard Worker rtp_scratch = malloc(rtp_size + 4 + RTP_DATA_SIZE);
360*6236dae4SAndroid Build Coastguard Worker
361*6236dae4SAndroid Build Coastguard Worker /* RTP is signalled with a $ */
362*6236dae4SAndroid Build Coastguard Worker rtp_scratch[0] = '$';
363*6236dae4SAndroid Build Coastguard Worker
364*6236dae4SAndroid Build Coastguard Worker /* The channel follows and is one byte */
365*6236dae4SAndroid Build Coastguard Worker SET_RTP_PKT_CHN(rtp_scratch, rtp_channel);
366*6236dae4SAndroid Build Coastguard Worker
367*6236dae4SAndroid Build Coastguard Worker /* Length follows and is a two byte short in network order */
368*6236dae4SAndroid Build Coastguard Worker SET_RTP_PKT_LEN(rtp_scratch, rtp_size + rtp_size_err);
369*6236dae4SAndroid Build Coastguard Worker
370*6236dae4SAndroid Build Coastguard Worker /* Fill it with junk data */
371*6236dae4SAndroid Build Coastguard Worker for(i = 0; i < rtp_size; i += RTP_DATA_SIZE) {
372*6236dae4SAndroid Build Coastguard Worker memcpy(rtp_scratch + 4 + i, RTP_DATA, RTP_DATA_SIZE);
373*6236dae4SAndroid Build Coastguard Worker }
374*6236dae4SAndroid Build Coastguard Worker
375*6236dae4SAndroid Build Coastguard Worker if(!req->rtp_buffer) {
376*6236dae4SAndroid Build Coastguard Worker req->rtp_buffer = rtp_scratch;
377*6236dae4SAndroid Build Coastguard Worker req->rtp_buffersize = rtp_size + 4;
378*6236dae4SAndroid Build Coastguard Worker }
379*6236dae4SAndroid Build Coastguard Worker else {
380*6236dae4SAndroid Build Coastguard Worker req->rtp_buffer = realloc(req->rtp_buffer,
381*6236dae4SAndroid Build Coastguard Worker req->rtp_buffersize +
382*6236dae4SAndroid Build Coastguard Worker rtp_size + 4);
383*6236dae4SAndroid Build Coastguard Worker memcpy(req->rtp_buffer + req->rtp_buffersize, rtp_scratch,
384*6236dae4SAndroid Build Coastguard Worker rtp_size + 4);
385*6236dae4SAndroid Build Coastguard Worker req->rtp_buffersize += rtp_size + 4;
386*6236dae4SAndroid Build Coastguard Worker free(rtp_scratch);
387*6236dae4SAndroid Build Coastguard Worker }
388*6236dae4SAndroid Build Coastguard Worker logmsg("rtp_buffersize is %zu, rtp_size is %d.",
389*6236dae4SAndroid Build Coastguard Worker req->rtp_buffersize, rtp_size);
390*6236dae4SAndroid Build Coastguard Worker }
391*6236dae4SAndroid Build Coastguard Worker }
392*6236dae4SAndroid Build Coastguard Worker else {
393*6236dae4SAndroid Build Coastguard Worker logmsg("funny instruction found: %s", ptr);
394*6236dae4SAndroid Build Coastguard Worker }
395*6236dae4SAndroid Build Coastguard Worker
396*6236dae4SAndroid Build Coastguard Worker ptr = strchr(ptr, '\n');
397*6236dae4SAndroid Build Coastguard Worker if(ptr)
398*6236dae4SAndroid Build Coastguard Worker ptr++;
399*6236dae4SAndroid Build Coastguard Worker else
400*6236dae4SAndroid Build Coastguard Worker ptr = NULL;
401*6236dae4SAndroid Build Coastguard Worker } while(ptr && *ptr);
402*6236dae4SAndroid Build Coastguard Worker logmsg("Done parsing server commands");
403*6236dae4SAndroid Build Coastguard Worker }
404*6236dae4SAndroid Build Coastguard Worker free(cmd);
405*6236dae4SAndroid Build Coastguard Worker }
406*6236dae4SAndroid Build Coastguard Worker }
407*6236dae4SAndroid Build Coastguard Worker else {
408*6236dae4SAndroid Build Coastguard Worker if(sscanf(req->reqbuf, "CONNECT %" MAXDOCNAMELEN_TXT "s HTTP/%d.%d",
409*6236dae4SAndroid Build Coastguard Worker doc, &prot_major, &prot_minor) == 3) {
410*6236dae4SAndroid Build Coastguard Worker msnprintf(logbuf, sizeof(logbuf),
411*6236dae4SAndroid Build Coastguard Worker "Received a CONNECT %s HTTP/%d.%d request",
412*6236dae4SAndroid Build Coastguard Worker doc, prot_major, prot_minor);
413*6236dae4SAndroid Build Coastguard Worker logmsg("%s", logbuf);
414*6236dae4SAndroid Build Coastguard Worker
415*6236dae4SAndroid Build Coastguard Worker if(req->prot_version == 10)
416*6236dae4SAndroid Build Coastguard Worker req->open = FALSE; /* HTTP 1.0 closes connection by default */
417*6236dae4SAndroid Build Coastguard Worker
418*6236dae4SAndroid Build Coastguard Worker if(!strncmp(doc, "bad", 3))
419*6236dae4SAndroid Build Coastguard Worker /* if the host name starts with bad, we fake an error here */
420*6236dae4SAndroid Build Coastguard Worker req->testno = DOCNUMBER_BADCONNECT;
421*6236dae4SAndroid Build Coastguard Worker else if(!strncmp(doc, "test", 4)) {
422*6236dae4SAndroid Build Coastguard Worker /* if the host name starts with test, the port number used in the
423*6236dae4SAndroid Build Coastguard Worker CONNECT line will be used as test number! */
424*6236dae4SAndroid Build Coastguard Worker char *portp = strchr(doc, ':');
425*6236dae4SAndroid Build Coastguard Worker if(portp && (*(portp + 1) != '\0') && ISDIGIT(*(portp + 1)))
426*6236dae4SAndroid Build Coastguard Worker req->testno = strtol(portp + 1, NULL, 10);
427*6236dae4SAndroid Build Coastguard Worker else
428*6236dae4SAndroid Build Coastguard Worker req->testno = DOCNUMBER_CONNECT;
429*6236dae4SAndroid Build Coastguard Worker }
430*6236dae4SAndroid Build Coastguard Worker else
431*6236dae4SAndroid Build Coastguard Worker req->testno = DOCNUMBER_CONNECT;
432*6236dae4SAndroid Build Coastguard Worker }
433*6236dae4SAndroid Build Coastguard Worker else {
434*6236dae4SAndroid Build Coastguard Worker logmsg("Did not find test number in PATH");
435*6236dae4SAndroid Build Coastguard Worker req->testno = DOCNUMBER_404;
436*6236dae4SAndroid Build Coastguard Worker }
437*6236dae4SAndroid Build Coastguard Worker }
438*6236dae4SAndroid Build Coastguard Worker }
439*6236dae4SAndroid Build Coastguard Worker
440*6236dae4SAndroid Build Coastguard Worker if(!end) {
441*6236dae4SAndroid Build Coastguard Worker /* we don't have a complete request yet! */
442*6236dae4SAndroid Build Coastguard Worker logmsg("ProcessRequest returned without a complete request");
443*6236dae4SAndroid Build Coastguard Worker return 0; /* not complete yet */
444*6236dae4SAndroid Build Coastguard Worker }
445*6236dae4SAndroid Build Coastguard Worker logmsg("ProcessRequest found a complete request");
446*6236dae4SAndroid Build Coastguard Worker
447*6236dae4SAndroid Build Coastguard Worker if(req->pipe)
448*6236dae4SAndroid Build Coastguard Worker /* we do have a full set, advance the checkindex to after the end of the
449*6236dae4SAndroid Build Coastguard Worker headers, for the pipelining case mostly */
450*6236dae4SAndroid Build Coastguard Worker req->checkindex += (end - line) + strlen(END_OF_HEADERS);
451*6236dae4SAndroid Build Coastguard Worker
452*6236dae4SAndroid Build Coastguard Worker /* **** Persistence ****
453*6236dae4SAndroid Build Coastguard Worker *
454*6236dae4SAndroid Build Coastguard Worker * If the request is an HTTP/1.0 one, we close the connection unconditionally
455*6236dae4SAndroid Build Coastguard Worker * when we're done.
456*6236dae4SAndroid Build Coastguard Worker *
457*6236dae4SAndroid Build Coastguard Worker * If the request is an HTTP/1.1 one, we MUST check for a "Connection:"
458*6236dae4SAndroid Build Coastguard Worker * header that might say "close". If it does, we close a connection when
459*6236dae4SAndroid Build Coastguard Worker * this request is processed. Otherwise, we keep the connection alive for X
460*6236dae4SAndroid Build Coastguard Worker * seconds.
461*6236dae4SAndroid Build Coastguard Worker */
462*6236dae4SAndroid Build Coastguard Worker
463*6236dae4SAndroid Build Coastguard Worker do {
464*6236dae4SAndroid Build Coastguard Worker if(got_exit_signal)
465*6236dae4SAndroid Build Coastguard Worker return 1; /* done */
466*6236dae4SAndroid Build Coastguard Worker
467*6236dae4SAndroid Build Coastguard Worker if((req->cl == 0) && strncasecompare("Content-Length:", line, 15)) {
468*6236dae4SAndroid Build Coastguard Worker /* If we don't ignore content-length, we read it and we read the whole
469*6236dae4SAndroid Build Coastguard Worker request including the body before we return. If we've been told to
470*6236dae4SAndroid Build Coastguard Worker ignore the content-length, we will return as soon as all headers
471*6236dae4SAndroid Build Coastguard Worker have been received */
472*6236dae4SAndroid Build Coastguard Worker char *endptr;
473*6236dae4SAndroid Build Coastguard Worker char *ptr = line + 15;
474*6236dae4SAndroid Build Coastguard Worker unsigned long clen = 0;
475*6236dae4SAndroid Build Coastguard Worker while(*ptr && ISSPACE(*ptr))
476*6236dae4SAndroid Build Coastguard Worker ptr++;
477*6236dae4SAndroid Build Coastguard Worker endptr = ptr;
478*6236dae4SAndroid Build Coastguard Worker errno = 0;
479*6236dae4SAndroid Build Coastguard Worker clen = strtoul(ptr, &endptr, 10);
480*6236dae4SAndroid Build Coastguard Worker if((ptr == endptr) || !ISSPACE(*endptr) || (ERANGE == errno)) {
481*6236dae4SAndroid Build Coastguard Worker /* this assumes that a zero Content-Length is valid */
482*6236dae4SAndroid Build Coastguard Worker logmsg("Found invalid Content-Length: (%s) in the request", ptr);
483*6236dae4SAndroid Build Coastguard Worker req->open = FALSE; /* closes connection */
484*6236dae4SAndroid Build Coastguard Worker return 1; /* done */
485*6236dae4SAndroid Build Coastguard Worker }
486*6236dae4SAndroid Build Coastguard Worker req->cl = clen - req->skip;
487*6236dae4SAndroid Build Coastguard Worker
488*6236dae4SAndroid Build Coastguard Worker logmsg("Found Content-Length: %lu in the request", clen);
489*6236dae4SAndroid Build Coastguard Worker if(req->skip)
490*6236dae4SAndroid Build Coastguard Worker logmsg("... but will abort after %zu bytes", req->cl);
491*6236dae4SAndroid Build Coastguard Worker break;
492*6236dae4SAndroid Build Coastguard Worker }
493*6236dae4SAndroid Build Coastguard Worker else if(strncasecompare("Transfer-Encoding: chunked", line,
494*6236dae4SAndroid Build Coastguard Worker strlen("Transfer-Encoding: chunked"))) {
495*6236dae4SAndroid Build Coastguard Worker /* chunked data coming in */
496*6236dae4SAndroid Build Coastguard Worker chunked = TRUE;
497*6236dae4SAndroid Build Coastguard Worker }
498*6236dae4SAndroid Build Coastguard Worker
499*6236dae4SAndroid Build Coastguard Worker if(chunked) {
500*6236dae4SAndroid Build Coastguard Worker if(strstr(req->reqbuf, "\r\n0\r\n\r\n"))
501*6236dae4SAndroid Build Coastguard Worker /* end of chunks reached */
502*6236dae4SAndroid Build Coastguard Worker return 1; /* done */
503*6236dae4SAndroid Build Coastguard Worker else
504*6236dae4SAndroid Build Coastguard Worker return 0; /* not done */
505*6236dae4SAndroid Build Coastguard Worker }
506*6236dae4SAndroid Build Coastguard Worker
507*6236dae4SAndroid Build Coastguard Worker line = strchr(line, '\n');
508*6236dae4SAndroid Build Coastguard Worker if(line)
509*6236dae4SAndroid Build Coastguard Worker line++;
510*6236dae4SAndroid Build Coastguard Worker
511*6236dae4SAndroid Build Coastguard Worker } while(line);
512*6236dae4SAndroid Build Coastguard Worker
513*6236dae4SAndroid Build Coastguard Worker if(!req->auth && strstr(req->reqbuf, "Authorization:")) {
514*6236dae4SAndroid Build Coastguard Worker req->auth = TRUE; /* Authorization: header present! */
515*6236dae4SAndroid Build Coastguard Worker if(req->auth_req)
516*6236dae4SAndroid Build Coastguard Worker logmsg("Authorization header found, as required");
517*6236dae4SAndroid Build Coastguard Worker }
518*6236dae4SAndroid Build Coastguard Worker
519*6236dae4SAndroid Build Coastguard Worker if(!req->digest && strstr(req->reqbuf, "Authorization: Digest")) {
520*6236dae4SAndroid Build Coastguard Worker /* If the client is passing this Digest-header, we set the part number
521*6236dae4SAndroid Build Coastguard Worker to 1000. Not only to spice up the complexity of this, but to make
522*6236dae4SAndroid Build Coastguard Worker Digest stuff to work in the test suite. */
523*6236dae4SAndroid Build Coastguard Worker req->partno += 1000;
524*6236dae4SAndroid Build Coastguard Worker req->digest = TRUE; /* header found */
525*6236dae4SAndroid Build Coastguard Worker logmsg("Received Digest request, sending back data %ld", req->partno);
526*6236dae4SAndroid Build Coastguard Worker }
527*6236dae4SAndroid Build Coastguard Worker else if(!req->ntlm &&
528*6236dae4SAndroid Build Coastguard Worker strstr(req->reqbuf, "Authorization: NTLM TlRMTVNTUAAD")) {
529*6236dae4SAndroid Build Coastguard Worker /* If the client is passing this type-3 NTLM header */
530*6236dae4SAndroid Build Coastguard Worker req->partno += 1002;
531*6236dae4SAndroid Build Coastguard Worker req->ntlm = TRUE; /* NTLM found */
532*6236dae4SAndroid Build Coastguard Worker logmsg("Received NTLM type-3, sending back data %ld", req->partno);
533*6236dae4SAndroid Build Coastguard Worker if(req->cl) {
534*6236dae4SAndroid Build Coastguard Worker logmsg(" Expecting %zu POSTed bytes", req->cl);
535*6236dae4SAndroid Build Coastguard Worker }
536*6236dae4SAndroid Build Coastguard Worker }
537*6236dae4SAndroid Build Coastguard Worker else if(!req->ntlm &&
538*6236dae4SAndroid Build Coastguard Worker strstr(req->reqbuf, "Authorization: NTLM TlRMTVNTUAAB")) {
539*6236dae4SAndroid Build Coastguard Worker /* If the client is passing this type-1 NTLM header */
540*6236dae4SAndroid Build Coastguard Worker req->partno += 1001;
541*6236dae4SAndroid Build Coastguard Worker req->ntlm = TRUE; /* NTLM found */
542*6236dae4SAndroid Build Coastguard Worker logmsg("Received NTLM type-1, sending back data %ld", req->partno);
543*6236dae4SAndroid Build Coastguard Worker }
544*6236dae4SAndroid Build Coastguard Worker else if((req->partno >= 1000) &&
545*6236dae4SAndroid Build Coastguard Worker strstr(req->reqbuf, "Authorization: Basic")) {
546*6236dae4SAndroid Build Coastguard Worker /* If the client is passing this Basic-header and the part number is
547*6236dae4SAndroid Build Coastguard Worker already >=1000, we add 1 to the part number. This allows simple Basic
548*6236dae4SAndroid Build Coastguard Worker authentication negotiation to work in the test suite. */
549*6236dae4SAndroid Build Coastguard Worker req->partno += 1;
550*6236dae4SAndroid Build Coastguard Worker logmsg("Received Basic request, sending back data %ld", req->partno);
551*6236dae4SAndroid Build Coastguard Worker }
552*6236dae4SAndroid Build Coastguard Worker if(strstr(req->reqbuf, "Connection: close"))
553*6236dae4SAndroid Build Coastguard Worker req->open = FALSE; /* close connection after this request */
554*6236dae4SAndroid Build Coastguard Worker
555*6236dae4SAndroid Build Coastguard Worker if(!req->pipe &&
556*6236dae4SAndroid Build Coastguard Worker req->open &&
557*6236dae4SAndroid Build Coastguard Worker req->prot_version >= 11 &&
558*6236dae4SAndroid Build Coastguard Worker req->reqbuf + req->offset > end + strlen(END_OF_HEADERS) &&
559*6236dae4SAndroid Build Coastguard Worker (!strncmp(req->reqbuf, "GET", strlen("GET")) ||
560*6236dae4SAndroid Build Coastguard Worker !strncmp(req->reqbuf, "HEAD", strlen("HEAD")))) {
561*6236dae4SAndroid Build Coastguard Worker /* If we have a persistent connection, HTTP version >= 1.1
562*6236dae4SAndroid Build Coastguard Worker and GET/HEAD request, enable pipelining. */
563*6236dae4SAndroid Build Coastguard Worker req->checkindex = (end - req->reqbuf) + strlen(END_OF_HEADERS);
564*6236dae4SAndroid Build Coastguard Worker req->pipelining = TRUE;
565*6236dae4SAndroid Build Coastguard Worker }
566*6236dae4SAndroid Build Coastguard Worker
567*6236dae4SAndroid Build Coastguard Worker while(req->pipe) {
568*6236dae4SAndroid Build Coastguard Worker if(got_exit_signal)
569*6236dae4SAndroid Build Coastguard Worker return 1; /* done */
570*6236dae4SAndroid Build Coastguard Worker /* scan for more header ends within this chunk */
571*6236dae4SAndroid Build Coastguard Worker line = &req->reqbuf[req->checkindex];
572*6236dae4SAndroid Build Coastguard Worker end = strstr(line, END_OF_HEADERS);
573*6236dae4SAndroid Build Coastguard Worker if(!end)
574*6236dae4SAndroid Build Coastguard Worker break;
575*6236dae4SAndroid Build Coastguard Worker req->checkindex += (end - line) + strlen(END_OF_HEADERS);
576*6236dae4SAndroid Build Coastguard Worker req->pipe--;
577*6236dae4SAndroid Build Coastguard Worker }
578*6236dae4SAndroid Build Coastguard Worker
579*6236dae4SAndroid Build Coastguard Worker /* If authentication is required and no auth was provided, end now. This
580*6236dae4SAndroid Build Coastguard Worker makes the server NOT wait for PUT/POST data and you can then make the
581*6236dae4SAndroid Build Coastguard Worker test case send a rejection before any such data has been sent. Test case
582*6236dae4SAndroid Build Coastguard Worker 154 uses this.*/
583*6236dae4SAndroid Build Coastguard Worker if(req->auth_req && !req->auth)
584*6236dae4SAndroid Build Coastguard Worker return 1; /* done */
585*6236dae4SAndroid Build Coastguard Worker
586*6236dae4SAndroid Build Coastguard Worker if(req->cl > 0) {
587*6236dae4SAndroid Build Coastguard Worker if(req->cl <= req->offset - (end - req->reqbuf) - strlen(END_OF_HEADERS))
588*6236dae4SAndroid Build Coastguard Worker return 1; /* done */
589*6236dae4SAndroid Build Coastguard Worker else
590*6236dae4SAndroid Build Coastguard Worker return 0; /* not complete yet */
591*6236dae4SAndroid Build Coastguard Worker }
592*6236dae4SAndroid Build Coastguard Worker
593*6236dae4SAndroid Build Coastguard Worker return 1; /* done */
594*6236dae4SAndroid Build Coastguard Worker }
595*6236dae4SAndroid Build Coastguard Worker
596*6236dae4SAndroid Build Coastguard Worker /* store the entire request in a file */
storerequest(char * reqbuf,size_t totalsize)597*6236dae4SAndroid Build Coastguard Worker static void storerequest(char *reqbuf, size_t totalsize)
598*6236dae4SAndroid Build Coastguard Worker {
599*6236dae4SAndroid Build Coastguard Worker int res;
600*6236dae4SAndroid Build Coastguard Worker int error = 0;
601*6236dae4SAndroid Build Coastguard Worker size_t written;
602*6236dae4SAndroid Build Coastguard Worker size_t writeleft;
603*6236dae4SAndroid Build Coastguard Worker FILE *dump;
604*6236dae4SAndroid Build Coastguard Worker char dumpfile[256];
605*6236dae4SAndroid Build Coastguard Worker
606*6236dae4SAndroid Build Coastguard Worker msnprintf(dumpfile, sizeof(dumpfile), "%s/%s", logdir, REQUEST_DUMP);
607*6236dae4SAndroid Build Coastguard Worker
608*6236dae4SAndroid Build Coastguard Worker if(!reqbuf)
609*6236dae4SAndroid Build Coastguard Worker return;
610*6236dae4SAndroid Build Coastguard Worker if(totalsize == 0)
611*6236dae4SAndroid Build Coastguard Worker return;
612*6236dae4SAndroid Build Coastguard Worker
613*6236dae4SAndroid Build Coastguard Worker do {
614*6236dae4SAndroid Build Coastguard Worker dump = fopen(dumpfile, "ab");
615*6236dae4SAndroid Build Coastguard Worker } while(!dump && ((error = errno) == EINTR));
616*6236dae4SAndroid Build Coastguard Worker if(!dump) {
617*6236dae4SAndroid Build Coastguard Worker logmsg("Error opening file %s error: %d %s",
618*6236dae4SAndroid Build Coastguard Worker dumpfile, error, strerror(error));
619*6236dae4SAndroid Build Coastguard Worker logmsg("Failed to write request input to %s", dumpfile);
620*6236dae4SAndroid Build Coastguard Worker return;
621*6236dae4SAndroid Build Coastguard Worker }
622*6236dae4SAndroid Build Coastguard Worker
623*6236dae4SAndroid Build Coastguard Worker writeleft = totalsize;
624*6236dae4SAndroid Build Coastguard Worker do {
625*6236dae4SAndroid Build Coastguard Worker written = fwrite(&reqbuf[totalsize-writeleft],
626*6236dae4SAndroid Build Coastguard Worker 1, writeleft, dump);
627*6236dae4SAndroid Build Coastguard Worker if(got_exit_signal)
628*6236dae4SAndroid Build Coastguard Worker goto storerequest_cleanup;
629*6236dae4SAndroid Build Coastguard Worker if(written > 0)
630*6236dae4SAndroid Build Coastguard Worker writeleft -= written;
631*6236dae4SAndroid Build Coastguard Worker } while((writeleft > 0) && ((error = errno) == EINTR));
632*6236dae4SAndroid Build Coastguard Worker
633*6236dae4SAndroid Build Coastguard Worker if(writeleft == 0)
634*6236dae4SAndroid Build Coastguard Worker logmsg("Wrote request (%zu bytes) input to %s", totalsize, dumpfile);
635*6236dae4SAndroid Build Coastguard Worker else if(writeleft > 0) {
636*6236dae4SAndroid Build Coastguard Worker logmsg("Error writing file %s error: %d %s",
637*6236dae4SAndroid Build Coastguard Worker dumpfile, error, strerror(error));
638*6236dae4SAndroid Build Coastguard Worker logmsg("Wrote only (%zu bytes) of (%zu bytes) request input to %s",
639*6236dae4SAndroid Build Coastguard Worker totalsize-writeleft, totalsize, dumpfile);
640*6236dae4SAndroid Build Coastguard Worker }
641*6236dae4SAndroid Build Coastguard Worker
642*6236dae4SAndroid Build Coastguard Worker storerequest_cleanup:
643*6236dae4SAndroid Build Coastguard Worker
644*6236dae4SAndroid Build Coastguard Worker do {
645*6236dae4SAndroid Build Coastguard Worker res = fclose(dump);
646*6236dae4SAndroid Build Coastguard Worker } while(res && ((error = errno) == EINTR));
647*6236dae4SAndroid Build Coastguard Worker if(res)
648*6236dae4SAndroid Build Coastguard Worker logmsg("Error closing file %s error: %d %s",
649*6236dae4SAndroid Build Coastguard Worker dumpfile, error, strerror(error));
650*6236dae4SAndroid Build Coastguard Worker }
651*6236dae4SAndroid Build Coastguard Worker
652*6236dae4SAndroid Build Coastguard Worker /* return 0 on success, non-zero on failure */
get_request(curl_socket_t sock,struct httprequest * req)653*6236dae4SAndroid Build Coastguard Worker static int get_request(curl_socket_t sock, struct httprequest *req)
654*6236dae4SAndroid Build Coastguard Worker {
655*6236dae4SAndroid Build Coastguard Worker int error;
656*6236dae4SAndroid Build Coastguard Worker int fail = 0;
657*6236dae4SAndroid Build Coastguard Worker int done_processing = 0;
658*6236dae4SAndroid Build Coastguard Worker char *reqbuf = req->reqbuf;
659*6236dae4SAndroid Build Coastguard Worker ssize_t got = 0;
660*6236dae4SAndroid Build Coastguard Worker
661*6236dae4SAndroid Build Coastguard Worker char *pipereq = NULL;
662*6236dae4SAndroid Build Coastguard Worker size_t pipereq_length = 0;
663*6236dae4SAndroid Build Coastguard Worker
664*6236dae4SAndroid Build Coastguard Worker if(req->pipelining) {
665*6236dae4SAndroid Build Coastguard Worker pipereq = reqbuf + req->checkindex;
666*6236dae4SAndroid Build Coastguard Worker pipereq_length = req->offset - req->checkindex;
667*6236dae4SAndroid Build Coastguard Worker }
668*6236dae4SAndroid Build Coastguard Worker
669*6236dae4SAndroid Build Coastguard Worker /*** Init the httprequest structure properly for the upcoming request ***/
670*6236dae4SAndroid Build Coastguard Worker
671*6236dae4SAndroid Build Coastguard Worker req->checkindex = 0;
672*6236dae4SAndroid Build Coastguard Worker req->offset = 0;
673*6236dae4SAndroid Build Coastguard Worker req->testno = DOCNUMBER_NOTHING;
674*6236dae4SAndroid Build Coastguard Worker req->partno = 0;
675*6236dae4SAndroid Build Coastguard Worker req->open = TRUE;
676*6236dae4SAndroid Build Coastguard Worker req->auth_req = FALSE;
677*6236dae4SAndroid Build Coastguard Worker req->auth = FALSE;
678*6236dae4SAndroid Build Coastguard Worker req->cl = 0;
679*6236dae4SAndroid Build Coastguard Worker req->digest = FALSE;
680*6236dae4SAndroid Build Coastguard Worker req->ntlm = FALSE;
681*6236dae4SAndroid Build Coastguard Worker req->pipe = 0;
682*6236dae4SAndroid Build Coastguard Worker req->skip = 0;
683*6236dae4SAndroid Build Coastguard Worker req->rcmd = RCMD_NORMALREQ;
684*6236dae4SAndroid Build Coastguard Worker req->protocol = RPROT_NONE;
685*6236dae4SAndroid Build Coastguard Worker req->prot_version = 0;
686*6236dae4SAndroid Build Coastguard Worker req->pipelining = FALSE;
687*6236dae4SAndroid Build Coastguard Worker req->rtp_buffer = NULL;
688*6236dae4SAndroid Build Coastguard Worker req->rtp_buffersize = 0;
689*6236dae4SAndroid Build Coastguard Worker
690*6236dae4SAndroid Build Coastguard Worker /*** end of httprequest init ***/
691*6236dae4SAndroid Build Coastguard Worker
692*6236dae4SAndroid Build Coastguard Worker while(!done_processing && (req->offset < REQBUFSIZ-1)) {
693*6236dae4SAndroid Build Coastguard Worker if(pipereq_length && pipereq) {
694*6236dae4SAndroid Build Coastguard Worker memmove(reqbuf, pipereq, pipereq_length);
695*6236dae4SAndroid Build Coastguard Worker got = curlx_uztosz(pipereq_length);
696*6236dae4SAndroid Build Coastguard Worker pipereq_length = 0;
697*6236dae4SAndroid Build Coastguard Worker }
698*6236dae4SAndroid Build Coastguard Worker else {
699*6236dae4SAndroid Build Coastguard Worker if(req->skip)
700*6236dae4SAndroid Build Coastguard Worker /* we are instructed to not read the entire thing, so we make sure to
701*6236dae4SAndroid Build Coastguard Worker only read what we're supposed to and NOT read the enire thing the
702*6236dae4SAndroid Build Coastguard Worker client wants to send! */
703*6236dae4SAndroid Build Coastguard Worker got = sread(sock, reqbuf + req->offset, req->cl);
704*6236dae4SAndroid Build Coastguard Worker else
705*6236dae4SAndroid Build Coastguard Worker got = sread(sock, reqbuf + req->offset, REQBUFSIZ-1 - req->offset);
706*6236dae4SAndroid Build Coastguard Worker }
707*6236dae4SAndroid Build Coastguard Worker if(got_exit_signal)
708*6236dae4SAndroid Build Coastguard Worker return 1;
709*6236dae4SAndroid Build Coastguard Worker if(got == 0) {
710*6236dae4SAndroid Build Coastguard Worker logmsg("Connection closed by client");
711*6236dae4SAndroid Build Coastguard Worker fail = 1;
712*6236dae4SAndroid Build Coastguard Worker }
713*6236dae4SAndroid Build Coastguard Worker else if(got < 0) {
714*6236dae4SAndroid Build Coastguard Worker error = SOCKERRNO;
715*6236dae4SAndroid Build Coastguard Worker logmsg("recv() returned error: (%d) %s", error, sstrerror(error));
716*6236dae4SAndroid Build Coastguard Worker fail = 1;
717*6236dae4SAndroid Build Coastguard Worker }
718*6236dae4SAndroid Build Coastguard Worker if(fail) {
719*6236dae4SAndroid Build Coastguard Worker /* dump the request received so far to the external file */
720*6236dae4SAndroid Build Coastguard Worker reqbuf[req->offset] = '\0';
721*6236dae4SAndroid Build Coastguard Worker storerequest(reqbuf, req->offset);
722*6236dae4SAndroid Build Coastguard Worker return 1;
723*6236dae4SAndroid Build Coastguard Worker }
724*6236dae4SAndroid Build Coastguard Worker
725*6236dae4SAndroid Build Coastguard Worker logmsg("Read %zd bytes", got);
726*6236dae4SAndroid Build Coastguard Worker
727*6236dae4SAndroid Build Coastguard Worker req->offset += (size_t)got;
728*6236dae4SAndroid Build Coastguard Worker reqbuf[req->offset] = '\0';
729*6236dae4SAndroid Build Coastguard Worker
730*6236dae4SAndroid Build Coastguard Worker done_processing = ProcessRequest(req);
731*6236dae4SAndroid Build Coastguard Worker if(got_exit_signal)
732*6236dae4SAndroid Build Coastguard Worker return 1;
733*6236dae4SAndroid Build Coastguard Worker if(done_processing && req->pipe) {
734*6236dae4SAndroid Build Coastguard Worker logmsg("Waiting for another piped request");
735*6236dae4SAndroid Build Coastguard Worker done_processing = 0;
736*6236dae4SAndroid Build Coastguard Worker req->pipe--;
737*6236dae4SAndroid Build Coastguard Worker }
738*6236dae4SAndroid Build Coastguard Worker }
739*6236dae4SAndroid Build Coastguard Worker
740*6236dae4SAndroid Build Coastguard Worker if((req->offset == REQBUFSIZ-1) && (got > 0)) {
741*6236dae4SAndroid Build Coastguard Worker logmsg("Request would overflow buffer, closing connection");
742*6236dae4SAndroid Build Coastguard Worker /* dump request received so far to external file anyway */
743*6236dae4SAndroid Build Coastguard Worker reqbuf[REQBUFSIZ-1] = '\0';
744*6236dae4SAndroid Build Coastguard Worker fail = 1;
745*6236dae4SAndroid Build Coastguard Worker }
746*6236dae4SAndroid Build Coastguard Worker else if(req->offset > REQBUFSIZ-1) {
747*6236dae4SAndroid Build Coastguard Worker logmsg("Request buffer overflow, closing connection");
748*6236dae4SAndroid Build Coastguard Worker /* dump request received so far to external file anyway */
749*6236dae4SAndroid Build Coastguard Worker reqbuf[REQBUFSIZ-1] = '\0';
750*6236dae4SAndroid Build Coastguard Worker fail = 1;
751*6236dae4SAndroid Build Coastguard Worker }
752*6236dae4SAndroid Build Coastguard Worker else
753*6236dae4SAndroid Build Coastguard Worker reqbuf[req->offset] = '\0';
754*6236dae4SAndroid Build Coastguard Worker
755*6236dae4SAndroid Build Coastguard Worker /* dump the request to an external file */
756*6236dae4SAndroid Build Coastguard Worker storerequest(reqbuf, req->pipelining ? req->checkindex : req->offset);
757*6236dae4SAndroid Build Coastguard Worker if(got_exit_signal)
758*6236dae4SAndroid Build Coastguard Worker return 1;
759*6236dae4SAndroid Build Coastguard Worker
760*6236dae4SAndroid Build Coastguard Worker return fail; /* return 0 on success */
761*6236dae4SAndroid Build Coastguard Worker }
762*6236dae4SAndroid Build Coastguard Worker
763*6236dae4SAndroid Build Coastguard Worker /* returns -1 on failure */
send_doc(curl_socket_t sock,struct httprequest * req)764*6236dae4SAndroid Build Coastguard Worker static int send_doc(curl_socket_t sock, struct httprequest *req)
765*6236dae4SAndroid Build Coastguard Worker {
766*6236dae4SAndroid Build Coastguard Worker ssize_t written;
767*6236dae4SAndroid Build Coastguard Worker size_t count;
768*6236dae4SAndroid Build Coastguard Worker const char *buffer;
769*6236dae4SAndroid Build Coastguard Worker char *ptr = NULL;
770*6236dae4SAndroid Build Coastguard Worker char *cmd = NULL;
771*6236dae4SAndroid Build Coastguard Worker size_t cmdsize = 0;
772*6236dae4SAndroid Build Coastguard Worker FILE *dump;
773*6236dae4SAndroid Build Coastguard Worker bool persistent = TRUE;
774*6236dae4SAndroid Build Coastguard Worker bool sendfailure = FALSE;
775*6236dae4SAndroid Build Coastguard Worker size_t responsesize;
776*6236dae4SAndroid Build Coastguard Worker int error = 0;
777*6236dae4SAndroid Build Coastguard Worker int res;
778*6236dae4SAndroid Build Coastguard Worker static char weare[256];
779*6236dae4SAndroid Build Coastguard Worker char responsedump[256];
780*6236dae4SAndroid Build Coastguard Worker
781*6236dae4SAndroid Build Coastguard Worker msnprintf(responsedump, sizeof(responsedump), "%s/%s",
782*6236dae4SAndroid Build Coastguard Worker logdir, RESPONSE_DUMP);
783*6236dae4SAndroid Build Coastguard Worker
784*6236dae4SAndroid Build Coastguard Worker logmsg("Send response number %ld part %ld", req->testno, req->partno);
785*6236dae4SAndroid Build Coastguard Worker
786*6236dae4SAndroid Build Coastguard Worker switch(req->rcmd) {
787*6236dae4SAndroid Build Coastguard Worker default:
788*6236dae4SAndroid Build Coastguard Worker case RCMD_NORMALREQ:
789*6236dae4SAndroid Build Coastguard Worker break; /* continue with business as usual */
790*6236dae4SAndroid Build Coastguard Worker case RCMD_STREAM:
791*6236dae4SAndroid Build Coastguard Worker #define STREAMTHIS "a string to stream 01234567890\n"
792*6236dae4SAndroid Build Coastguard Worker count = strlen(STREAMTHIS);
793*6236dae4SAndroid Build Coastguard Worker for(;;) {
794*6236dae4SAndroid Build Coastguard Worker written = swrite(sock, STREAMTHIS, count);
795*6236dae4SAndroid Build Coastguard Worker if(got_exit_signal)
796*6236dae4SAndroid Build Coastguard Worker return -1;
797*6236dae4SAndroid Build Coastguard Worker if(written != (ssize_t)count) {
798*6236dae4SAndroid Build Coastguard Worker logmsg("Stopped streaming");
799*6236dae4SAndroid Build Coastguard Worker break;
800*6236dae4SAndroid Build Coastguard Worker }
801*6236dae4SAndroid Build Coastguard Worker }
802*6236dae4SAndroid Build Coastguard Worker return -1;
803*6236dae4SAndroid Build Coastguard Worker case RCMD_IDLE:
804*6236dae4SAndroid Build Coastguard Worker /* Do nothing. Sit idle. Pretend it rains. */
805*6236dae4SAndroid Build Coastguard Worker return 0;
806*6236dae4SAndroid Build Coastguard Worker }
807*6236dae4SAndroid Build Coastguard Worker
808*6236dae4SAndroid Build Coastguard Worker req->open = FALSE;
809*6236dae4SAndroid Build Coastguard Worker
810*6236dae4SAndroid Build Coastguard Worker if(req->testno < 0) {
811*6236dae4SAndroid Build Coastguard Worker size_t msglen;
812*6236dae4SAndroid Build Coastguard Worker char msgbuf[64];
813*6236dae4SAndroid Build Coastguard Worker
814*6236dae4SAndroid Build Coastguard Worker switch(req->testno) {
815*6236dae4SAndroid Build Coastguard Worker case DOCNUMBER_QUIT:
816*6236dae4SAndroid Build Coastguard Worker logmsg("Replying to QUIT");
817*6236dae4SAndroid Build Coastguard Worker buffer = docquit;
818*6236dae4SAndroid Build Coastguard Worker break;
819*6236dae4SAndroid Build Coastguard Worker case DOCNUMBER_WERULEZ:
820*6236dae4SAndroid Build Coastguard Worker /* we got a "friends?" question, reply back that we sure are */
821*6236dae4SAndroid Build Coastguard Worker logmsg("Identifying ourselves as friends");
822*6236dae4SAndroid Build Coastguard Worker msnprintf(msgbuf, sizeof(msgbuf), "RTSP_SERVER WE ROOLZ: %"
823*6236dae4SAndroid Build Coastguard Worker CURL_FORMAT_CURL_OFF_T "\r\n", our_getpid());
824*6236dae4SAndroid Build Coastguard Worker msglen = strlen(msgbuf);
825*6236dae4SAndroid Build Coastguard Worker msnprintf(weare, sizeof(weare),
826*6236dae4SAndroid Build Coastguard Worker "HTTP/1.1 200 OK\r\nContent-Length: %zu\r\n\r\n%s",
827*6236dae4SAndroid Build Coastguard Worker msglen, msgbuf);
828*6236dae4SAndroid Build Coastguard Worker buffer = weare;
829*6236dae4SAndroid Build Coastguard Worker break;
830*6236dae4SAndroid Build Coastguard Worker case DOCNUMBER_INTERNAL:
831*6236dae4SAndroid Build Coastguard Worker logmsg("Bailing out due to internal error");
832*6236dae4SAndroid Build Coastguard Worker return -1;
833*6236dae4SAndroid Build Coastguard Worker case DOCNUMBER_CONNECT:
834*6236dae4SAndroid Build Coastguard Worker logmsg("Replying to CONNECT");
835*6236dae4SAndroid Build Coastguard Worker buffer = docconnect;
836*6236dae4SAndroid Build Coastguard Worker break;
837*6236dae4SAndroid Build Coastguard Worker case DOCNUMBER_BADCONNECT:
838*6236dae4SAndroid Build Coastguard Worker logmsg("Replying to a bad CONNECT");
839*6236dae4SAndroid Build Coastguard Worker buffer = docbadconnect;
840*6236dae4SAndroid Build Coastguard Worker break;
841*6236dae4SAndroid Build Coastguard Worker case DOCNUMBER_404:
842*6236dae4SAndroid Build Coastguard Worker default:
843*6236dae4SAndroid Build Coastguard Worker logmsg("Replying to with a 404");
844*6236dae4SAndroid Build Coastguard Worker if(req->protocol == RPROT_HTTP) {
845*6236dae4SAndroid Build Coastguard Worker buffer = doc404_HTTP;
846*6236dae4SAndroid Build Coastguard Worker }
847*6236dae4SAndroid Build Coastguard Worker else {
848*6236dae4SAndroid Build Coastguard Worker buffer = doc404_RTSP;
849*6236dae4SAndroid Build Coastguard Worker }
850*6236dae4SAndroid Build Coastguard Worker break;
851*6236dae4SAndroid Build Coastguard Worker }
852*6236dae4SAndroid Build Coastguard Worker
853*6236dae4SAndroid Build Coastguard Worker count = strlen(buffer);
854*6236dae4SAndroid Build Coastguard Worker }
855*6236dae4SAndroid Build Coastguard Worker else {
856*6236dae4SAndroid Build Coastguard Worker FILE *stream = test2fopen(req->testno, logdir);
857*6236dae4SAndroid Build Coastguard Worker char partbuf[80]="data";
858*6236dae4SAndroid Build Coastguard Worker if(0 != req->partno)
859*6236dae4SAndroid Build Coastguard Worker msnprintf(partbuf, sizeof(partbuf), "data%ld", req->partno);
860*6236dae4SAndroid Build Coastguard Worker if(!stream) {
861*6236dae4SAndroid Build Coastguard Worker error = errno;
862*6236dae4SAndroid Build Coastguard Worker logmsg("fopen() failed with error: %d %s", error, strerror(error));
863*6236dae4SAndroid Build Coastguard Worker logmsg("Couldn't open test file");
864*6236dae4SAndroid Build Coastguard Worker return 0;
865*6236dae4SAndroid Build Coastguard Worker }
866*6236dae4SAndroid Build Coastguard Worker else {
867*6236dae4SAndroid Build Coastguard Worker error = getpart(&ptr, &count, "reply", partbuf, stream);
868*6236dae4SAndroid Build Coastguard Worker fclose(stream);
869*6236dae4SAndroid Build Coastguard Worker if(error) {
870*6236dae4SAndroid Build Coastguard Worker logmsg("getpart() failed with error: %d", error);
871*6236dae4SAndroid Build Coastguard Worker return 0;
872*6236dae4SAndroid Build Coastguard Worker }
873*6236dae4SAndroid Build Coastguard Worker buffer = ptr;
874*6236dae4SAndroid Build Coastguard Worker }
875*6236dae4SAndroid Build Coastguard Worker
876*6236dae4SAndroid Build Coastguard Worker if(got_exit_signal) {
877*6236dae4SAndroid Build Coastguard Worker free(ptr);
878*6236dae4SAndroid Build Coastguard Worker return -1;
879*6236dae4SAndroid Build Coastguard Worker }
880*6236dae4SAndroid Build Coastguard Worker
881*6236dae4SAndroid Build Coastguard Worker /* re-open the same file again */
882*6236dae4SAndroid Build Coastguard Worker stream = test2fopen(req->testno, logdir);
883*6236dae4SAndroid Build Coastguard Worker if(!stream) {
884*6236dae4SAndroid Build Coastguard Worker error = errno;
885*6236dae4SAndroid Build Coastguard Worker logmsg("fopen() failed with error: %d %s", error, strerror(error));
886*6236dae4SAndroid Build Coastguard Worker logmsg("Couldn't open test file");
887*6236dae4SAndroid Build Coastguard Worker free(ptr);
888*6236dae4SAndroid Build Coastguard Worker return 0;
889*6236dae4SAndroid Build Coastguard Worker }
890*6236dae4SAndroid Build Coastguard Worker else {
891*6236dae4SAndroid Build Coastguard Worker /* get the custom server control "commands" */
892*6236dae4SAndroid Build Coastguard Worker error = getpart(&cmd, &cmdsize, "reply", "postcmd", stream);
893*6236dae4SAndroid Build Coastguard Worker fclose(stream);
894*6236dae4SAndroid Build Coastguard Worker if(error) {
895*6236dae4SAndroid Build Coastguard Worker logmsg("getpart() failed with error: %d", error);
896*6236dae4SAndroid Build Coastguard Worker free(ptr);
897*6236dae4SAndroid Build Coastguard Worker return 0;
898*6236dae4SAndroid Build Coastguard Worker }
899*6236dae4SAndroid Build Coastguard Worker }
900*6236dae4SAndroid Build Coastguard Worker }
901*6236dae4SAndroid Build Coastguard Worker
902*6236dae4SAndroid Build Coastguard Worker if(got_exit_signal) {
903*6236dae4SAndroid Build Coastguard Worker free(ptr);
904*6236dae4SAndroid Build Coastguard Worker free(cmd);
905*6236dae4SAndroid Build Coastguard Worker return -1;
906*6236dae4SAndroid Build Coastguard Worker }
907*6236dae4SAndroid Build Coastguard Worker
908*6236dae4SAndroid Build Coastguard Worker /* If the word 'swsclose' is present anywhere in the reply chunk, the
909*6236dae4SAndroid Build Coastguard Worker connection will be closed after the data has been sent to the requesting
910*6236dae4SAndroid Build Coastguard Worker client... */
911*6236dae4SAndroid Build Coastguard Worker if(strstr(buffer, "swsclose") || !count) {
912*6236dae4SAndroid Build Coastguard Worker persistent = FALSE;
913*6236dae4SAndroid Build Coastguard Worker logmsg("connection close instruction \"swsclose\" found in response");
914*6236dae4SAndroid Build Coastguard Worker }
915*6236dae4SAndroid Build Coastguard Worker if(strstr(buffer, "swsbounce")) {
916*6236dae4SAndroid Build Coastguard Worker prevbounce = TRUE;
917*6236dae4SAndroid Build Coastguard Worker logmsg("enable \"swsbounce\" in the next request");
918*6236dae4SAndroid Build Coastguard Worker }
919*6236dae4SAndroid Build Coastguard Worker else
920*6236dae4SAndroid Build Coastguard Worker prevbounce = FALSE;
921*6236dae4SAndroid Build Coastguard Worker
922*6236dae4SAndroid Build Coastguard Worker dump = fopen(responsedump, "ab");
923*6236dae4SAndroid Build Coastguard Worker if(!dump) {
924*6236dae4SAndroid Build Coastguard Worker error = errno;
925*6236dae4SAndroid Build Coastguard Worker logmsg("fopen() failed with error: %d %s", error, strerror(error));
926*6236dae4SAndroid Build Coastguard Worker logmsg("Error opening file: %s", responsedump);
927*6236dae4SAndroid Build Coastguard Worker logmsg("couldn't create logfile: %s", responsedump);
928*6236dae4SAndroid Build Coastguard Worker free(ptr);
929*6236dae4SAndroid Build Coastguard Worker free(cmd);
930*6236dae4SAndroid Build Coastguard Worker return -1;
931*6236dae4SAndroid Build Coastguard Worker }
932*6236dae4SAndroid Build Coastguard Worker
933*6236dae4SAndroid Build Coastguard Worker responsesize = count;
934*6236dae4SAndroid Build Coastguard Worker do {
935*6236dae4SAndroid Build Coastguard Worker /* Ok, we send no more than 200 bytes at a time, just to make sure that
936*6236dae4SAndroid Build Coastguard Worker larger chunks are split up so that the client will need to do multiple
937*6236dae4SAndroid Build Coastguard Worker recv() calls to get it and thus we exercise that code better */
938*6236dae4SAndroid Build Coastguard Worker size_t num = count;
939*6236dae4SAndroid Build Coastguard Worker if(num > 200)
940*6236dae4SAndroid Build Coastguard Worker num = 200;
941*6236dae4SAndroid Build Coastguard Worker written = swrite(sock, buffer, num);
942*6236dae4SAndroid Build Coastguard Worker if(written < 0) {
943*6236dae4SAndroid Build Coastguard Worker sendfailure = TRUE;
944*6236dae4SAndroid Build Coastguard Worker break;
945*6236dae4SAndroid Build Coastguard Worker }
946*6236dae4SAndroid Build Coastguard Worker else {
947*6236dae4SAndroid Build Coastguard Worker logmsg("Sent off %zd bytes", written);
948*6236dae4SAndroid Build Coastguard Worker }
949*6236dae4SAndroid Build Coastguard Worker /* write to file as well */
950*6236dae4SAndroid Build Coastguard Worker fwrite(buffer, 1, (size_t)written, dump);
951*6236dae4SAndroid Build Coastguard Worker if(got_exit_signal)
952*6236dae4SAndroid Build Coastguard Worker break;
953*6236dae4SAndroid Build Coastguard Worker
954*6236dae4SAndroid Build Coastguard Worker count -= written;
955*6236dae4SAndroid Build Coastguard Worker buffer += written;
956*6236dae4SAndroid Build Coastguard Worker } while(count > 0);
957*6236dae4SAndroid Build Coastguard Worker
958*6236dae4SAndroid Build Coastguard Worker /* Send out any RTP data */
959*6236dae4SAndroid Build Coastguard Worker if(req->rtp_buffer) {
960*6236dae4SAndroid Build Coastguard Worker logmsg("About to write %zu RTP bytes", req->rtp_buffersize);
961*6236dae4SAndroid Build Coastguard Worker count = req->rtp_buffersize;
962*6236dae4SAndroid Build Coastguard Worker do {
963*6236dae4SAndroid Build Coastguard Worker size_t num = count;
964*6236dae4SAndroid Build Coastguard Worker if(num > 200)
965*6236dae4SAndroid Build Coastguard Worker num = 200;
966*6236dae4SAndroid Build Coastguard Worker written = swrite(sock, req->rtp_buffer + (req->rtp_buffersize - count),
967*6236dae4SAndroid Build Coastguard Worker num);
968*6236dae4SAndroid Build Coastguard Worker if(written < 0) {
969*6236dae4SAndroid Build Coastguard Worker sendfailure = TRUE;
970*6236dae4SAndroid Build Coastguard Worker break;
971*6236dae4SAndroid Build Coastguard Worker }
972*6236dae4SAndroid Build Coastguard Worker count -= written;
973*6236dae4SAndroid Build Coastguard Worker } while(count > 0);
974*6236dae4SAndroid Build Coastguard Worker
975*6236dae4SAndroid Build Coastguard Worker free(req->rtp_buffer);
976*6236dae4SAndroid Build Coastguard Worker req->rtp_buffersize = 0;
977*6236dae4SAndroid Build Coastguard Worker }
978*6236dae4SAndroid Build Coastguard Worker
979*6236dae4SAndroid Build Coastguard Worker do {
980*6236dae4SAndroid Build Coastguard Worker res = fclose(dump);
981*6236dae4SAndroid Build Coastguard Worker } while(res && ((error = errno) == EINTR));
982*6236dae4SAndroid Build Coastguard Worker if(res)
983*6236dae4SAndroid Build Coastguard Worker logmsg("Error closing file %s error: %d %s",
984*6236dae4SAndroid Build Coastguard Worker responsedump, error, strerror(error));
985*6236dae4SAndroid Build Coastguard Worker
986*6236dae4SAndroid Build Coastguard Worker if(got_exit_signal) {
987*6236dae4SAndroid Build Coastguard Worker free(ptr);
988*6236dae4SAndroid Build Coastguard Worker free(cmd);
989*6236dae4SAndroid Build Coastguard Worker return -1;
990*6236dae4SAndroid Build Coastguard Worker }
991*6236dae4SAndroid Build Coastguard Worker
992*6236dae4SAndroid Build Coastguard Worker if(sendfailure) {
993*6236dae4SAndroid Build Coastguard Worker logmsg("Sending response failed. Only (%zu bytes) of "
994*6236dae4SAndroid Build Coastguard Worker "(%zu bytes) were sent",
995*6236dae4SAndroid Build Coastguard Worker responsesize-count, responsesize);
996*6236dae4SAndroid Build Coastguard Worker free(ptr);
997*6236dae4SAndroid Build Coastguard Worker free(cmd);
998*6236dae4SAndroid Build Coastguard Worker return -1;
999*6236dae4SAndroid Build Coastguard Worker }
1000*6236dae4SAndroid Build Coastguard Worker
1001*6236dae4SAndroid Build Coastguard Worker logmsg("Response sent (%zu bytes) and written to %s",
1002*6236dae4SAndroid Build Coastguard Worker responsesize, responsedump);
1003*6236dae4SAndroid Build Coastguard Worker free(ptr);
1004*6236dae4SAndroid Build Coastguard Worker
1005*6236dae4SAndroid Build Coastguard Worker if(cmdsize > 0) {
1006*6236dae4SAndroid Build Coastguard Worker char command[32];
1007*6236dae4SAndroid Build Coastguard Worker int quarters;
1008*6236dae4SAndroid Build Coastguard Worker int num;
1009*6236dae4SAndroid Build Coastguard Worker ptr = cmd;
1010*6236dae4SAndroid Build Coastguard Worker do {
1011*6236dae4SAndroid Build Coastguard Worker if(2 == sscanf(ptr, "%31s %d", command, &num)) {
1012*6236dae4SAndroid Build Coastguard Worker if(!strcmp("wait", command)) {
1013*6236dae4SAndroid Build Coastguard Worker logmsg("Told to sleep for %d seconds", num);
1014*6236dae4SAndroid Build Coastguard Worker quarters = num * 4;
1015*6236dae4SAndroid Build Coastguard Worker while(quarters > 0) {
1016*6236dae4SAndroid Build Coastguard Worker quarters--;
1017*6236dae4SAndroid Build Coastguard Worker res = wait_ms(250);
1018*6236dae4SAndroid Build Coastguard Worker if(got_exit_signal)
1019*6236dae4SAndroid Build Coastguard Worker break;
1020*6236dae4SAndroid Build Coastguard Worker if(res) {
1021*6236dae4SAndroid Build Coastguard Worker /* should not happen */
1022*6236dae4SAndroid Build Coastguard Worker error = errno;
1023*6236dae4SAndroid Build Coastguard Worker logmsg("wait_ms() failed with error: (%d) %s",
1024*6236dae4SAndroid Build Coastguard Worker error, strerror(error));
1025*6236dae4SAndroid Build Coastguard Worker break;
1026*6236dae4SAndroid Build Coastguard Worker }
1027*6236dae4SAndroid Build Coastguard Worker }
1028*6236dae4SAndroid Build Coastguard Worker if(!quarters)
1029*6236dae4SAndroid Build Coastguard Worker logmsg("Continuing after sleeping %d seconds", num);
1030*6236dae4SAndroid Build Coastguard Worker }
1031*6236dae4SAndroid Build Coastguard Worker else
1032*6236dae4SAndroid Build Coastguard Worker logmsg("Unknown command in reply command section");
1033*6236dae4SAndroid Build Coastguard Worker }
1034*6236dae4SAndroid Build Coastguard Worker ptr = strchr(ptr, '\n');
1035*6236dae4SAndroid Build Coastguard Worker if(ptr)
1036*6236dae4SAndroid Build Coastguard Worker ptr++;
1037*6236dae4SAndroid Build Coastguard Worker else
1038*6236dae4SAndroid Build Coastguard Worker ptr = NULL;
1039*6236dae4SAndroid Build Coastguard Worker } while(ptr && *ptr);
1040*6236dae4SAndroid Build Coastguard Worker }
1041*6236dae4SAndroid Build Coastguard Worker free(cmd);
1042*6236dae4SAndroid Build Coastguard Worker req->open = persistent;
1043*6236dae4SAndroid Build Coastguard Worker
1044*6236dae4SAndroid Build Coastguard Worker prevtestno = req->testno;
1045*6236dae4SAndroid Build Coastguard Worker prevpartno = req->partno;
1046*6236dae4SAndroid Build Coastguard Worker
1047*6236dae4SAndroid Build Coastguard Worker return 0;
1048*6236dae4SAndroid Build Coastguard Worker }
1049*6236dae4SAndroid Build Coastguard Worker
1050*6236dae4SAndroid Build Coastguard Worker
main(int argc,char * argv[])1051*6236dae4SAndroid Build Coastguard Worker int main(int argc, char *argv[])
1052*6236dae4SAndroid Build Coastguard Worker {
1053*6236dae4SAndroid Build Coastguard Worker srvr_sockaddr_union_t me;
1054*6236dae4SAndroid Build Coastguard Worker curl_socket_t sock = CURL_SOCKET_BAD;
1055*6236dae4SAndroid Build Coastguard Worker curl_socket_t msgsock = CURL_SOCKET_BAD;
1056*6236dae4SAndroid Build Coastguard Worker int wrotepidfile = 0;
1057*6236dae4SAndroid Build Coastguard Worker int wroteportfile = 0;
1058*6236dae4SAndroid Build Coastguard Worker int flag;
1059*6236dae4SAndroid Build Coastguard Worker unsigned short port = DEFAULT_PORT;
1060*6236dae4SAndroid Build Coastguard Worker const char *pidname = ".rtsp.pid";
1061*6236dae4SAndroid Build Coastguard Worker const char *portname = NULL; /* none by default */
1062*6236dae4SAndroid Build Coastguard Worker struct httprequest req;
1063*6236dae4SAndroid Build Coastguard Worker int rc;
1064*6236dae4SAndroid Build Coastguard Worker int error;
1065*6236dae4SAndroid Build Coastguard Worker int arg = 1;
1066*6236dae4SAndroid Build Coastguard Worker
1067*6236dae4SAndroid Build Coastguard Worker memset(&req, 0, sizeof(req));
1068*6236dae4SAndroid Build Coastguard Worker
1069*6236dae4SAndroid Build Coastguard Worker while(argc > arg) {
1070*6236dae4SAndroid Build Coastguard Worker if(!strcmp("--version", argv[arg])) {
1071*6236dae4SAndroid Build Coastguard Worker printf("rtspd IPv4%s"
1072*6236dae4SAndroid Build Coastguard Worker "\n"
1073*6236dae4SAndroid Build Coastguard Worker ,
1074*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
1075*6236dae4SAndroid Build Coastguard Worker "/IPv6"
1076*6236dae4SAndroid Build Coastguard Worker #else
1077*6236dae4SAndroid Build Coastguard Worker ""
1078*6236dae4SAndroid Build Coastguard Worker #endif
1079*6236dae4SAndroid Build Coastguard Worker );
1080*6236dae4SAndroid Build Coastguard Worker return 0;
1081*6236dae4SAndroid Build Coastguard Worker }
1082*6236dae4SAndroid Build Coastguard Worker else if(!strcmp("--pidfile", argv[arg])) {
1083*6236dae4SAndroid Build Coastguard Worker arg++;
1084*6236dae4SAndroid Build Coastguard Worker if(argc > arg)
1085*6236dae4SAndroid Build Coastguard Worker pidname = argv[arg++];
1086*6236dae4SAndroid Build Coastguard Worker }
1087*6236dae4SAndroid Build Coastguard Worker else if(!strcmp("--portfile", argv[arg])) {
1088*6236dae4SAndroid Build Coastguard Worker arg++;
1089*6236dae4SAndroid Build Coastguard Worker if(argc > arg)
1090*6236dae4SAndroid Build Coastguard Worker portname = argv[arg++];
1091*6236dae4SAndroid Build Coastguard Worker }
1092*6236dae4SAndroid Build Coastguard Worker else if(!strcmp("--logfile", argv[arg])) {
1093*6236dae4SAndroid Build Coastguard Worker arg++;
1094*6236dae4SAndroid Build Coastguard Worker if(argc > arg)
1095*6236dae4SAndroid Build Coastguard Worker serverlogfile = argv[arg++];
1096*6236dae4SAndroid Build Coastguard Worker }
1097*6236dae4SAndroid Build Coastguard Worker else if(!strcmp("--logdir", argv[arg])) {
1098*6236dae4SAndroid Build Coastguard Worker arg++;
1099*6236dae4SAndroid Build Coastguard Worker if(argc > arg)
1100*6236dae4SAndroid Build Coastguard Worker logdir = argv[arg++];
1101*6236dae4SAndroid Build Coastguard Worker }
1102*6236dae4SAndroid Build Coastguard Worker else if(!strcmp("--ipv4", argv[arg])) {
1103*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
1104*6236dae4SAndroid Build Coastguard Worker ipv_inuse = "IPv4";
1105*6236dae4SAndroid Build Coastguard Worker use_ipv6 = FALSE;
1106*6236dae4SAndroid Build Coastguard Worker #endif
1107*6236dae4SAndroid Build Coastguard Worker arg++;
1108*6236dae4SAndroid Build Coastguard Worker }
1109*6236dae4SAndroid Build Coastguard Worker else if(!strcmp("--ipv6", argv[arg])) {
1110*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
1111*6236dae4SAndroid Build Coastguard Worker ipv_inuse = "IPv6";
1112*6236dae4SAndroid Build Coastguard Worker use_ipv6 = TRUE;
1113*6236dae4SAndroid Build Coastguard Worker #endif
1114*6236dae4SAndroid Build Coastguard Worker arg++;
1115*6236dae4SAndroid Build Coastguard Worker }
1116*6236dae4SAndroid Build Coastguard Worker else if(!strcmp("--port", argv[arg])) {
1117*6236dae4SAndroid Build Coastguard Worker arg++;
1118*6236dae4SAndroid Build Coastguard Worker if(argc > arg) {
1119*6236dae4SAndroid Build Coastguard Worker char *endptr;
1120*6236dae4SAndroid Build Coastguard Worker unsigned long ulnum = strtoul(argv[arg], &endptr, 10);
1121*6236dae4SAndroid Build Coastguard Worker port = curlx_ultous(ulnum);
1122*6236dae4SAndroid Build Coastguard Worker arg++;
1123*6236dae4SAndroid Build Coastguard Worker }
1124*6236dae4SAndroid Build Coastguard Worker }
1125*6236dae4SAndroid Build Coastguard Worker else if(!strcmp("--srcdir", argv[arg])) {
1126*6236dae4SAndroid Build Coastguard Worker arg++;
1127*6236dae4SAndroid Build Coastguard Worker if(argc > arg) {
1128*6236dae4SAndroid Build Coastguard Worker path = argv[arg];
1129*6236dae4SAndroid Build Coastguard Worker arg++;
1130*6236dae4SAndroid Build Coastguard Worker }
1131*6236dae4SAndroid Build Coastguard Worker }
1132*6236dae4SAndroid Build Coastguard Worker else {
1133*6236dae4SAndroid Build Coastguard Worker puts("Usage: rtspd [option]\n"
1134*6236dae4SAndroid Build Coastguard Worker " --version\n"
1135*6236dae4SAndroid Build Coastguard Worker " --logfile [file]\n"
1136*6236dae4SAndroid Build Coastguard Worker " --logdir [directory]\n"
1137*6236dae4SAndroid Build Coastguard Worker " --pidfile [file]\n"
1138*6236dae4SAndroid Build Coastguard Worker " --portfile [file]\n"
1139*6236dae4SAndroid Build Coastguard Worker " --ipv4\n"
1140*6236dae4SAndroid Build Coastguard Worker " --ipv6\n"
1141*6236dae4SAndroid Build Coastguard Worker " --port [port]\n"
1142*6236dae4SAndroid Build Coastguard Worker " --srcdir [path]");
1143*6236dae4SAndroid Build Coastguard Worker return 0;
1144*6236dae4SAndroid Build Coastguard Worker }
1145*6236dae4SAndroid Build Coastguard Worker }
1146*6236dae4SAndroid Build Coastguard Worker
1147*6236dae4SAndroid Build Coastguard Worker msnprintf(loglockfile, sizeof(loglockfile), "%s/%s/rtsp-%s.lock",
1148*6236dae4SAndroid Build Coastguard Worker logdir, SERVERLOGS_LOCKDIR, ipv_inuse);
1149*6236dae4SAndroid Build Coastguard Worker
1150*6236dae4SAndroid Build Coastguard Worker #ifdef _WIN32
1151*6236dae4SAndroid Build Coastguard Worker win32_init();
1152*6236dae4SAndroid Build Coastguard Worker atexit(win32_cleanup);
1153*6236dae4SAndroid Build Coastguard Worker #endif
1154*6236dae4SAndroid Build Coastguard Worker
1155*6236dae4SAndroid Build Coastguard Worker install_signal_handlers(false);
1156*6236dae4SAndroid Build Coastguard Worker
1157*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
1158*6236dae4SAndroid Build Coastguard Worker if(!use_ipv6)
1159*6236dae4SAndroid Build Coastguard Worker #endif
1160*6236dae4SAndroid Build Coastguard Worker sock = socket(AF_INET, SOCK_STREAM, 0);
1161*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
1162*6236dae4SAndroid Build Coastguard Worker else
1163*6236dae4SAndroid Build Coastguard Worker sock = socket(AF_INET6, SOCK_STREAM, 0);
1164*6236dae4SAndroid Build Coastguard Worker #endif
1165*6236dae4SAndroid Build Coastguard Worker
1166*6236dae4SAndroid Build Coastguard Worker if(CURL_SOCKET_BAD == sock) {
1167*6236dae4SAndroid Build Coastguard Worker error = SOCKERRNO;
1168*6236dae4SAndroid Build Coastguard Worker logmsg("Error creating socket: (%d) %s", error, sstrerror(error));
1169*6236dae4SAndroid Build Coastguard Worker goto server_cleanup;
1170*6236dae4SAndroid Build Coastguard Worker }
1171*6236dae4SAndroid Build Coastguard Worker
1172*6236dae4SAndroid Build Coastguard Worker flag = 1;
1173*6236dae4SAndroid Build Coastguard Worker if(0 != setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
1174*6236dae4SAndroid Build Coastguard Worker (void *)&flag, sizeof(flag))) {
1175*6236dae4SAndroid Build Coastguard Worker error = SOCKERRNO;
1176*6236dae4SAndroid Build Coastguard Worker logmsg("setsockopt(SO_REUSEADDR) failed with error: (%d) %s",
1177*6236dae4SAndroid Build Coastguard Worker error, sstrerror(error));
1178*6236dae4SAndroid Build Coastguard Worker goto server_cleanup;
1179*6236dae4SAndroid Build Coastguard Worker }
1180*6236dae4SAndroid Build Coastguard Worker
1181*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
1182*6236dae4SAndroid Build Coastguard Worker if(!use_ipv6) {
1183*6236dae4SAndroid Build Coastguard Worker #endif
1184*6236dae4SAndroid Build Coastguard Worker memset(&me.sa4, 0, sizeof(me.sa4));
1185*6236dae4SAndroid Build Coastguard Worker me.sa4.sin_family = AF_INET;
1186*6236dae4SAndroid Build Coastguard Worker me.sa4.sin_addr.s_addr = INADDR_ANY;
1187*6236dae4SAndroid Build Coastguard Worker me.sa4.sin_port = htons(port);
1188*6236dae4SAndroid Build Coastguard Worker rc = bind(sock, &me.sa, sizeof(me.sa4));
1189*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
1190*6236dae4SAndroid Build Coastguard Worker }
1191*6236dae4SAndroid Build Coastguard Worker else {
1192*6236dae4SAndroid Build Coastguard Worker memset(&me.sa6, 0, sizeof(me.sa6));
1193*6236dae4SAndroid Build Coastguard Worker me.sa6.sin6_family = AF_INET6;
1194*6236dae4SAndroid Build Coastguard Worker me.sa6.sin6_addr = in6addr_any;
1195*6236dae4SAndroid Build Coastguard Worker me.sa6.sin6_port = htons(port);
1196*6236dae4SAndroid Build Coastguard Worker rc = bind(sock, &me.sa, sizeof(me.sa6));
1197*6236dae4SAndroid Build Coastguard Worker }
1198*6236dae4SAndroid Build Coastguard Worker #endif /* USE_IPV6 */
1199*6236dae4SAndroid Build Coastguard Worker if(0 != rc) {
1200*6236dae4SAndroid Build Coastguard Worker error = SOCKERRNO;
1201*6236dae4SAndroid Build Coastguard Worker logmsg("Error binding socket on port %hu: (%d) %s",
1202*6236dae4SAndroid Build Coastguard Worker port, error, sstrerror(error));
1203*6236dae4SAndroid Build Coastguard Worker goto server_cleanup;
1204*6236dae4SAndroid Build Coastguard Worker }
1205*6236dae4SAndroid Build Coastguard Worker
1206*6236dae4SAndroid Build Coastguard Worker if(!port) {
1207*6236dae4SAndroid Build Coastguard Worker /* The system was supposed to choose a port number, figure out which
1208*6236dae4SAndroid Build Coastguard Worker port we actually got and update the listener port value with it. */
1209*6236dae4SAndroid Build Coastguard Worker curl_socklen_t la_size;
1210*6236dae4SAndroid Build Coastguard Worker srvr_sockaddr_union_t localaddr;
1211*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
1212*6236dae4SAndroid Build Coastguard Worker if(!use_ipv6)
1213*6236dae4SAndroid Build Coastguard Worker #endif
1214*6236dae4SAndroid Build Coastguard Worker la_size = sizeof(localaddr.sa4);
1215*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
1216*6236dae4SAndroid Build Coastguard Worker else
1217*6236dae4SAndroid Build Coastguard Worker la_size = sizeof(localaddr.sa6);
1218*6236dae4SAndroid Build Coastguard Worker #endif
1219*6236dae4SAndroid Build Coastguard Worker memset(&localaddr.sa, 0, (size_t)la_size);
1220*6236dae4SAndroid Build Coastguard Worker if(getsockname(sock, &localaddr.sa, &la_size) < 0) {
1221*6236dae4SAndroid Build Coastguard Worker error = SOCKERRNO;
1222*6236dae4SAndroid Build Coastguard Worker logmsg("getsockname() failed with error: (%d) %s",
1223*6236dae4SAndroid Build Coastguard Worker error, sstrerror(error));
1224*6236dae4SAndroid Build Coastguard Worker sclose(sock);
1225*6236dae4SAndroid Build Coastguard Worker goto server_cleanup;
1226*6236dae4SAndroid Build Coastguard Worker }
1227*6236dae4SAndroid Build Coastguard Worker switch(localaddr.sa.sa_family) {
1228*6236dae4SAndroid Build Coastguard Worker case AF_INET:
1229*6236dae4SAndroid Build Coastguard Worker port = ntohs(localaddr.sa4.sin_port);
1230*6236dae4SAndroid Build Coastguard Worker break;
1231*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
1232*6236dae4SAndroid Build Coastguard Worker case AF_INET6:
1233*6236dae4SAndroid Build Coastguard Worker port = ntohs(localaddr.sa6.sin6_port);
1234*6236dae4SAndroid Build Coastguard Worker break;
1235*6236dae4SAndroid Build Coastguard Worker #endif
1236*6236dae4SAndroid Build Coastguard Worker default:
1237*6236dae4SAndroid Build Coastguard Worker break;
1238*6236dae4SAndroid Build Coastguard Worker }
1239*6236dae4SAndroid Build Coastguard Worker if(!port) {
1240*6236dae4SAndroid Build Coastguard Worker /* Real failure, listener port shall not be zero beyond this point. */
1241*6236dae4SAndroid Build Coastguard Worker logmsg("Apparently getsockname() succeeded, with listener port zero.");
1242*6236dae4SAndroid Build Coastguard Worker logmsg("A valid reason for this failure is a binary built without");
1243*6236dae4SAndroid Build Coastguard Worker logmsg("proper network library linkage. This might not be the only");
1244*6236dae4SAndroid Build Coastguard Worker logmsg("reason, but double check it before anything else.");
1245*6236dae4SAndroid Build Coastguard Worker sclose(sock);
1246*6236dae4SAndroid Build Coastguard Worker goto server_cleanup;
1247*6236dae4SAndroid Build Coastguard Worker }
1248*6236dae4SAndroid Build Coastguard Worker }
1249*6236dae4SAndroid Build Coastguard Worker logmsg("Running %s version on port %d", ipv_inuse, (int)port);
1250*6236dae4SAndroid Build Coastguard Worker
1251*6236dae4SAndroid Build Coastguard Worker /* start accepting connections */
1252*6236dae4SAndroid Build Coastguard Worker rc = listen(sock, 5);
1253*6236dae4SAndroid Build Coastguard Worker if(0 != rc) {
1254*6236dae4SAndroid Build Coastguard Worker error = SOCKERRNO;
1255*6236dae4SAndroid Build Coastguard Worker logmsg("listen() failed with error: (%d) %s",
1256*6236dae4SAndroid Build Coastguard Worker error, sstrerror(error));
1257*6236dae4SAndroid Build Coastguard Worker goto server_cleanup;
1258*6236dae4SAndroid Build Coastguard Worker }
1259*6236dae4SAndroid Build Coastguard Worker
1260*6236dae4SAndroid Build Coastguard Worker /*
1261*6236dae4SAndroid Build Coastguard Worker ** As soon as this server writes its pid file the test harness will
1262*6236dae4SAndroid Build Coastguard Worker ** attempt to connect to this server and initiate its verification.
1263*6236dae4SAndroid Build Coastguard Worker */
1264*6236dae4SAndroid Build Coastguard Worker
1265*6236dae4SAndroid Build Coastguard Worker wrotepidfile = write_pidfile(pidname);
1266*6236dae4SAndroid Build Coastguard Worker if(!wrotepidfile)
1267*6236dae4SAndroid Build Coastguard Worker goto server_cleanup;
1268*6236dae4SAndroid Build Coastguard Worker
1269*6236dae4SAndroid Build Coastguard Worker if(portname) {
1270*6236dae4SAndroid Build Coastguard Worker wroteportfile = write_portfile(portname, port);
1271*6236dae4SAndroid Build Coastguard Worker if(!wroteportfile)
1272*6236dae4SAndroid Build Coastguard Worker goto server_cleanup;
1273*6236dae4SAndroid Build Coastguard Worker }
1274*6236dae4SAndroid Build Coastguard Worker
1275*6236dae4SAndroid Build Coastguard Worker for(;;) {
1276*6236dae4SAndroid Build Coastguard Worker msgsock = accept(sock, NULL, NULL);
1277*6236dae4SAndroid Build Coastguard Worker
1278*6236dae4SAndroid Build Coastguard Worker if(got_exit_signal)
1279*6236dae4SAndroid Build Coastguard Worker break;
1280*6236dae4SAndroid Build Coastguard Worker if(CURL_SOCKET_BAD == msgsock) {
1281*6236dae4SAndroid Build Coastguard Worker error = SOCKERRNO;
1282*6236dae4SAndroid Build Coastguard Worker logmsg("MAJOR ERROR: accept() failed with error: (%d) %s",
1283*6236dae4SAndroid Build Coastguard Worker error, sstrerror(error));
1284*6236dae4SAndroid Build Coastguard Worker break;
1285*6236dae4SAndroid Build Coastguard Worker }
1286*6236dae4SAndroid Build Coastguard Worker
1287*6236dae4SAndroid Build Coastguard Worker /*
1288*6236dae4SAndroid Build Coastguard Worker ** As soon as this server accepts a connection from the test harness it
1289*6236dae4SAndroid Build Coastguard Worker ** must set the server logs advisor read lock to indicate that server
1290*6236dae4SAndroid Build Coastguard Worker ** logs should not be read until this lock is removed by this server.
1291*6236dae4SAndroid Build Coastguard Worker */
1292*6236dae4SAndroid Build Coastguard Worker
1293*6236dae4SAndroid Build Coastguard Worker set_advisor_read_lock(loglockfile);
1294*6236dae4SAndroid Build Coastguard Worker serverlogslocked = 1;
1295*6236dae4SAndroid Build Coastguard Worker
1296*6236dae4SAndroid Build Coastguard Worker logmsg("====> Client connect");
1297*6236dae4SAndroid Build Coastguard Worker
1298*6236dae4SAndroid Build Coastguard Worker #ifdef TCP_NODELAY
1299*6236dae4SAndroid Build Coastguard Worker /*
1300*6236dae4SAndroid Build Coastguard Worker * Disable the Nagle algorithm to make it easier to send out a large
1301*6236dae4SAndroid Build Coastguard Worker * response in many small segments to torture the clients more.
1302*6236dae4SAndroid Build Coastguard Worker */
1303*6236dae4SAndroid Build Coastguard Worker flag = 1;
1304*6236dae4SAndroid Build Coastguard Worker if(setsockopt(msgsock, IPPROTO_TCP, TCP_NODELAY,
1305*6236dae4SAndroid Build Coastguard Worker (void *)&flag, sizeof(flag)) == -1) {
1306*6236dae4SAndroid Build Coastguard Worker logmsg("====> TCP_NODELAY failed");
1307*6236dae4SAndroid Build Coastguard Worker }
1308*6236dae4SAndroid Build Coastguard Worker #endif
1309*6236dae4SAndroid Build Coastguard Worker
1310*6236dae4SAndroid Build Coastguard Worker /* initialization of httprequest struct is done in get_request(), but due
1311*6236dae4SAndroid Build Coastguard Worker to pipelining treatment the pipelining struct field must be initialized
1312*6236dae4SAndroid Build Coastguard Worker previously to FALSE every time a new connection arrives. */
1313*6236dae4SAndroid Build Coastguard Worker
1314*6236dae4SAndroid Build Coastguard Worker req.pipelining = FALSE;
1315*6236dae4SAndroid Build Coastguard Worker
1316*6236dae4SAndroid Build Coastguard Worker do {
1317*6236dae4SAndroid Build Coastguard Worker if(got_exit_signal)
1318*6236dae4SAndroid Build Coastguard Worker break;
1319*6236dae4SAndroid Build Coastguard Worker
1320*6236dae4SAndroid Build Coastguard Worker if(get_request(msgsock, &req))
1321*6236dae4SAndroid Build Coastguard Worker /* non-zero means error, break out of loop */
1322*6236dae4SAndroid Build Coastguard Worker break;
1323*6236dae4SAndroid Build Coastguard Worker
1324*6236dae4SAndroid Build Coastguard Worker if(prevbounce) {
1325*6236dae4SAndroid Build Coastguard Worker /* bounce treatment requested */
1326*6236dae4SAndroid Build Coastguard Worker if((req.testno == prevtestno) &&
1327*6236dae4SAndroid Build Coastguard Worker (req.partno == prevpartno)) {
1328*6236dae4SAndroid Build Coastguard Worker req.partno++;
1329*6236dae4SAndroid Build Coastguard Worker logmsg("BOUNCE part number to %ld", req.partno);
1330*6236dae4SAndroid Build Coastguard Worker }
1331*6236dae4SAndroid Build Coastguard Worker else {
1332*6236dae4SAndroid Build Coastguard Worker prevbounce = FALSE;
1333*6236dae4SAndroid Build Coastguard Worker prevtestno = -1;
1334*6236dae4SAndroid Build Coastguard Worker prevpartno = -1;
1335*6236dae4SAndroid Build Coastguard Worker }
1336*6236dae4SAndroid Build Coastguard Worker }
1337*6236dae4SAndroid Build Coastguard Worker
1338*6236dae4SAndroid Build Coastguard Worker send_doc(msgsock, &req);
1339*6236dae4SAndroid Build Coastguard Worker if(got_exit_signal)
1340*6236dae4SAndroid Build Coastguard Worker break;
1341*6236dae4SAndroid Build Coastguard Worker
1342*6236dae4SAndroid Build Coastguard Worker if((req.testno < 0) && (req.testno != DOCNUMBER_CONNECT)) {
1343*6236dae4SAndroid Build Coastguard Worker logmsg("special request received, no persistency");
1344*6236dae4SAndroid Build Coastguard Worker break;
1345*6236dae4SAndroid Build Coastguard Worker }
1346*6236dae4SAndroid Build Coastguard Worker if(!req.open) {
1347*6236dae4SAndroid Build Coastguard Worker logmsg("instructed to close connection after server-reply");
1348*6236dae4SAndroid Build Coastguard Worker break;
1349*6236dae4SAndroid Build Coastguard Worker }
1350*6236dae4SAndroid Build Coastguard Worker
1351*6236dae4SAndroid Build Coastguard Worker if(req.open)
1352*6236dae4SAndroid Build Coastguard Worker logmsg("=> persistent connection request ended, awaits new request");
1353*6236dae4SAndroid Build Coastguard Worker /* if we got a CONNECT, loop and get another request as well! */
1354*6236dae4SAndroid Build Coastguard Worker } while(req.open || (req.testno == DOCNUMBER_CONNECT));
1355*6236dae4SAndroid Build Coastguard Worker
1356*6236dae4SAndroid Build Coastguard Worker if(got_exit_signal)
1357*6236dae4SAndroid Build Coastguard Worker break;
1358*6236dae4SAndroid Build Coastguard Worker
1359*6236dae4SAndroid Build Coastguard Worker logmsg("====> Client disconnect");
1360*6236dae4SAndroid Build Coastguard Worker sclose(msgsock);
1361*6236dae4SAndroid Build Coastguard Worker msgsock = CURL_SOCKET_BAD;
1362*6236dae4SAndroid Build Coastguard Worker
1363*6236dae4SAndroid Build Coastguard Worker if(serverlogslocked) {
1364*6236dae4SAndroid Build Coastguard Worker serverlogslocked = 0;
1365*6236dae4SAndroid Build Coastguard Worker clear_advisor_read_lock(loglockfile);
1366*6236dae4SAndroid Build Coastguard Worker }
1367*6236dae4SAndroid Build Coastguard Worker
1368*6236dae4SAndroid Build Coastguard Worker if(req.testno == DOCNUMBER_QUIT)
1369*6236dae4SAndroid Build Coastguard Worker break;
1370*6236dae4SAndroid Build Coastguard Worker }
1371*6236dae4SAndroid Build Coastguard Worker
1372*6236dae4SAndroid Build Coastguard Worker server_cleanup:
1373*6236dae4SAndroid Build Coastguard Worker
1374*6236dae4SAndroid Build Coastguard Worker if((msgsock != sock) && (msgsock != CURL_SOCKET_BAD))
1375*6236dae4SAndroid Build Coastguard Worker sclose(msgsock);
1376*6236dae4SAndroid Build Coastguard Worker
1377*6236dae4SAndroid Build Coastguard Worker if(sock != CURL_SOCKET_BAD)
1378*6236dae4SAndroid Build Coastguard Worker sclose(sock);
1379*6236dae4SAndroid Build Coastguard Worker
1380*6236dae4SAndroid Build Coastguard Worker if(got_exit_signal)
1381*6236dae4SAndroid Build Coastguard Worker logmsg("signalled to die");
1382*6236dae4SAndroid Build Coastguard Worker
1383*6236dae4SAndroid Build Coastguard Worker if(wrotepidfile)
1384*6236dae4SAndroid Build Coastguard Worker unlink(pidname);
1385*6236dae4SAndroid Build Coastguard Worker if(wroteportfile)
1386*6236dae4SAndroid Build Coastguard Worker unlink(portname);
1387*6236dae4SAndroid Build Coastguard Worker
1388*6236dae4SAndroid Build Coastguard Worker if(serverlogslocked) {
1389*6236dae4SAndroid Build Coastguard Worker serverlogslocked = 0;
1390*6236dae4SAndroid Build Coastguard Worker clear_advisor_read_lock(loglockfile);
1391*6236dae4SAndroid Build Coastguard Worker }
1392*6236dae4SAndroid Build Coastguard Worker
1393*6236dae4SAndroid Build Coastguard Worker restore_signal_handlers(false);
1394*6236dae4SAndroid Build Coastguard Worker
1395*6236dae4SAndroid Build Coastguard Worker if(got_exit_signal) {
1396*6236dae4SAndroid Build Coastguard Worker logmsg("========> %s rtspd (port: %d pid: %ld) exits with signal (%d)",
1397*6236dae4SAndroid Build Coastguard Worker ipv_inuse, (int)port, (long)getpid(), exit_signal);
1398*6236dae4SAndroid Build Coastguard Worker /*
1399*6236dae4SAndroid Build Coastguard Worker * To properly set the return status of the process we
1400*6236dae4SAndroid Build Coastguard Worker * must raise the same signal SIGINT or SIGTERM that we
1401*6236dae4SAndroid Build Coastguard Worker * caught and let the old handler take care of it.
1402*6236dae4SAndroid Build Coastguard Worker */
1403*6236dae4SAndroid Build Coastguard Worker raise(exit_signal);
1404*6236dae4SAndroid Build Coastguard Worker }
1405*6236dae4SAndroid Build Coastguard Worker
1406*6236dae4SAndroid Build Coastguard Worker logmsg("========> rtspd quits");
1407*6236dae4SAndroid Build Coastguard Worker return 0;
1408*6236dae4SAndroid Build Coastguard Worker }
1409