Add to git.
[pthrlib.git] / examples / pthr_eg1_echo.c
1 /* Pseudothread echo example.
2  * - by Richard W.M. Jones <rich@annexia.org>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the Free
16  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  *
18  * $Id: pthr_eg1_echo.c,v 1.6 2002/12/01 14:57:36 rich Exp $
19  */
20
21 #include "config.h"
22
23 #include <stdio.h>
24
25 #ifdef HAVE_SYS_SOCKET_H
26 #include <sys/socket.h>
27 #endif
28
29 #ifdef HAVE_SYSLOG_H
30 #include <syslog.h>
31 #endif
32
33 #include <pool.h>
34
35 #include "src/pthr_pseudothread.h"
36 #include "src/pthr_iolib.h"
37 #include "src/pthr_http.h"
38 #include "src/pthr_cgi.h"
39 #include "pthr_eg1_echo.h"
40
41 struct eg1_echo_processor
42 {
43   /* Pseudothread handle. */
44   pseudothread pth;
45
46   /* Socket. */
47   int sock;
48 };
49
50 static void run (void *vp);
51
52 eg1_echo_processor
53 new_eg1_echo_processor (int sock)
54 {
55   pool pool;
56   eg1_echo_processor p;
57
58   pool = new_pool ();
59   p = pmalloc (pool, sizeof *p);
60
61   p->sock = sock;
62   p->pth = new_pseudothread (pool, run, p, "eg1_echo_processor");
63
64   pth_start (p->pth);
65
66   return p;
67 }
68
69 static void
70 run (void *vp)
71 {
72   eg1_echo_processor p = (eg1_echo_processor) vp;
73   int close = 0;
74   http_request http_request;
75   cgi cgi;
76   http_response http_response;
77   pool pool = pth_get_pool (p->pth);
78   io_handle io;
79   int i;
80
81   io = io_fdopen (p->sock);
82
83   /* Sit in a loop reading HTTP requests. */
84   while (!close)
85     {
86       vector headers, params;
87       struct http_header header;
88       const char *name, *value;
89
90       /* ----- HTTP request ----- */
91       http_request = new_http_request (pool, io);
92       if (http_request == 0)    /* Normal end of file. */
93         break;
94
95       cgi = new_cgi (pool, http_request, io);
96       if (cgi == 0)             /* XXX Should send an error here. */
97         break;
98
99       /* ----- HTTP response ----- */
100       http_response = new_http_response (pool, http_request,
101                                          io,
102                                          200, "OK");
103       http_response_send_header (http_response,
104                                  "Content-Type", "text/plain");
105       close = http_response_end_headers (http_response);
106
107       if (!http_request_is_HEAD (http_request))
108         {
109           io_fprintf (io, "Hello. This is your server.\r\n\r\n");
110           io_fprintf (io, "Your browser sent the following headers:\r\n");
111
112           headers = http_request_get_headers (http_request);
113           for (i = 0; i < vector_size (headers); ++i)
114             {
115               vector_get (headers, i, header);
116               io_fprintf (io, "\t%s: %s\r\n", header.key, header.value);
117             }
118
119           io_fprintf (io, "----- end of headers -----\r\n");
120
121           io_fprintf (io, "The URL was: %s\r\n",
122                       http_request_get_url (http_request));
123           io_fprintf (io, "The path component was: %s\r\n",
124                       http_request_path (http_request));
125           io_fprintf (io, "The query string was: %s\r\n",
126                       http_request_query_string (http_request));
127           io_fprintf (io, "The query arguments were:\r\n");
128
129           params = cgi_params (cgi);
130           for (i = 0; i < vector_size (params); ++i)
131             {
132               vector_get (params, i, name);
133               value = cgi_param (cgi, name);
134               io_fprintf (io, "\t%s=%s\r\n", name, value);
135             }
136
137           io_fprintf (io, "----- end of parameters -----\r\n");
138         }
139     }
140
141   io_fclose (io);
142
143   pth_exit ();
144 }