1/*
2    This file is part of libmicrospdy
3    Copyright Copyright (C) 2013 Andrey Uzunov
4
5    This program is free software: you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation, either version 3 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.
17*/
18
19/**
20 * @file test_proxies.c
21 * @brief  test curl > mhd2spdylay > microspdy2http > mhd
22 * @author Andrey Uzunov
23 */
24
25#include "platform.h"
26#include "microspdy.h"
27#include "common.h"
28#include <sys/wait.h>
29#include <stdio.h>   /* printf, stderr, fprintf */
30#include <sys/types.h> /* pid_t */
31#include <unistd.h>  /* _exit, fork */
32#include <stdlib.h>  /* exit */
33#include <errno.h>   /* errno */
34#include <sys/wait.h> /* pid_t */
35#include "common.h"
36
37#ifdef _WIN32
38#ifndef WIN32_LEAN_AND_MEAN
39#define WIN32_LEAN_AND_MEAN 1
40#endif /* !WIN32_LEAN_AND_MEAN */
41#include <windows.h>
42#endif
43
44#define EXPECTED_BODY "<html><head><title>libmicrohttpd demo</title></head><body>libmicrohttpd demo</body></html>"
45
46
47pid_t parent;
48	pid_t child_mhd;
49	pid_t child_spdy2http;
50	pid_t child_mhd2spdy;
51	pid_t child_curl;
52
53	uint16_t mhd_port;
54	uint16_t spdy2http_port;
55	uint16_t mhd2spdy_port;
56
57void
58killproc(int pid, const char *message)
59{
60	printf("%s\nkilling %i\n",message,pid);
61	kill(pid, SIGKILL);
62}
63
64
65void killchildren()
66{
67    if(0 != child_mhd)
68      killproc(child_mhd,"kill mhd\n");
69    if(0 != child_spdy2http)
70      killproc(child_spdy2http,"kill spdy2http\n");
71    if(0 != child_mhd2spdy)
72      killproc(child_mhd2spdy,"kill mhd2spdy\n");
73    if(0 != child_curl)
74      killproc(child_curl,"kill curl\n");
75}
76
77pid_t au_fork()
78{
79  pid_t child = fork();
80	if (child == -1)
81	{
82    killchildren();
83
84		killproc(parent,"fork failed\n");
85	}
86
87	return child;
88}
89
90
91int main()
92{
93  //pid_t child;
94	int childstatus;
95	pid_t wpid;
96
97	parent = getpid();
98	mhd_port = get_port(4000);
99	spdy2http_port = get_port(4100);
100	mhd2spdy_port = get_port(4200);
101
102	child_mhd = au_fork();
103	if (child_mhd == 0)
104	{
105    //run MHD
106		pid_t devnull;
107    char *port_s;
108
109		close(1);
110		devnull = open("/dev/null", O_WRONLY);
111                if (-1 == devnull)
112                  abort();
113		if (1 != devnull)
114		{
115			dup2(devnull, 1);
116			close(devnull);
117		}
118    asprintf(&port_s, "%i", mhd_port);
119		execlp ("../examples/minimal_example", "minimal_example", port_s, NULL);
120		fprintf(stderr, "executing mhd failed\nFor this test 'make' must be run before 'make check'!\n");
121    //killchildren();
122    _exit(1);
123	}
124
125
126	child_spdy2http = au_fork();
127	if (child_spdy2http == 0)
128	{
129    //run spdy2http
130		pid_t devnull;
131    char *port_s;
132    //char *url;
133
134		close(1);
135		devnull = open("/dev/null", O_WRONLY);
136                if (-1 == devnull)
137                  abort();
138		if (1 != devnull)
139		{
140			dup2(devnull, 1);
141			close(devnull);
142		}
143    //asprintf(&url, "127.0.0.1:%i", mhd_port);
144    asprintf(&port_s, "%i", spdy2http_port);
145    sleep(1);
146		execlp ("../spdy2http/microspdy2http", "microspdy2http", "-v4rtT", "10", "-p", port_s, NULL);
147		fprintf(stderr, "executing microspdy2http failed\n");
148    //killchildren();
149    _exit(1);
150	}
151
152	child_mhd2spdy = au_fork();
153	if (child_mhd2spdy == 0)
154	{
155    //run MHD2sdpy
156		pid_t devnull;
157    char *port_s;
158    char *url;
159
160		close(1);
161		devnull = open("/dev/null", O_WRONLY);
162                if (-1 == devnull)
163                  abort();
164		if (1 != devnull)
165		{
166			dup2(devnull, 1);
167			close(devnull);
168		}
169    asprintf(&url, "http://127.0.0.1:%i", spdy2http_port);
170    asprintf(&port_s, "%i", mhd2spdy_port);
171    sleep(2);
172		execlp ("../examples/mhd2spdy", "mhd2spdy", "-vosb", url, "-p", port_s, NULL);
173		fprintf(stderr, "executing mhd2spdy failed\n");
174    //killchildren();
175    _exit(1);
176	}
177
178	child_curl = au_fork();
179	if (child_curl == 0)
180	{
181    //run curl
182    FILE *p;
183		pid_t devnull;
184		char *cmd;
185    unsigned int i;
186    int retc;
187    char buf[strlen(EXPECTED_BODY) + 1];
188
189		close(1);
190		devnull = open("/dev/null", O_WRONLY);
191                if (-1 == devnull)
192                  abort ();
193		if (1 != devnull)
194		{
195			dup2(devnull, 1);
196			close(devnull);
197		}
198
199		asprintf (&cmd, "curl --proxy http://127.0.0.1:%i http://127.0.0.1:%i/", mhd2spdy_port, mhd_port);
200    sleep(3);
201    p = popen(cmd, "r");
202    if (p != NULL)
203    {
204      for (i = 0; i < strlen(EXPECTED_BODY) && !feof(p); i++)
205      {
206          retc = fgetc (p);
207          if (EOF == retc)
208            abort (); /* what did feof(p) do there!? */
209          buf[i] = (char) retc;
210      }
211
212      pclose(p);
213      buf[i] = 0;
214      _exit(strcmp(EXPECTED_BODY, buf));
215    }
216		fprintf(stderr, "executing curl failed\n");
217    //killchildren();
218    _exit(1);
219	}
220
221  do
222  {
223    wpid = waitpid(child_mhd,&childstatus,WNOHANG);
224    if(wpid == child_mhd)
225    {
226      fprintf(stderr, "mhd died unexpectedly\n");
227      killchildren();
228      return 1;
229    }
230
231    wpid = waitpid(child_spdy2http,&childstatus,WNOHANG);
232    if(wpid == child_spdy2http)
233    {
234      fprintf(stderr, "spdy2http died unexpectedly\n");
235      killchildren();
236      return 1;
237    }
238
239    wpid = waitpid(child_mhd2spdy,&childstatus,WNOHANG);
240    if(wpid == child_mhd2spdy)
241    {
242      fprintf(stderr, "mhd2spdy died unexpectedly\n");
243      killchildren();
244      return 1;
245    }
246
247    if(waitpid(child_curl,&childstatus,WNOHANG) == child_curl)
248    {
249      killchildren();
250      return WEXITSTATUS(childstatus);
251    }
252    sleep(1);
253  }
254	while(true);
255}
256