• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Feel free to use this example code in any way
2    you see fit (Public Domain) */
3 
4 #include <sys/types.h>
5 #ifndef _WIN32
6 #include <sys/select.h>
7 #include <sys/socket.h>
8 #else
9 #include <winsock2.h>
10 #endif
11 #include <microhttpd.h>
12 #include <stdio.h>
13 #include <string.h>
14 #include <stdlib.h>
15 
16 #define PORT            8888
17 #define POSTBUFFERSIZE  512
18 #define MAXNAMESIZE     20
19 #define MAXANSWERSIZE   512
20 
21 #define GET             0
22 #define POST            1
23 
24 struct connection_info_struct
25 {
26   int connectiontype;
27   char *answerstring;
28   struct MHD_PostProcessor *postprocessor;
29 };
30 
31 const char *askpage = "<html><body>\
32                        What's your name, Sir?<br>\
33                        <form action=\"/namepost\" method=\"post\">\
34                        <input name=\"name\" type=\"text\"\
35                        <input type=\"submit\" value=\" Send \"></form>\
36                        </body></html>";
37 
38 const char *greetingpage =
39   "<html><body><h1>Welcome, %s!</center></h1></body></html>";
40 
41 const char *errorpage =
42   "<html><body>This doesn't seem to be right.</body></html>";
43 
44 
45 static int
send_page(struct MHD_Connection * connection,const char * page)46 send_page (struct MHD_Connection *connection, const char *page)
47 {
48   int ret;
49   struct MHD_Response *response;
50 
51 
52   response =
53     MHD_create_response_from_buffer (strlen (page), (void *) page,
54 				     MHD_RESPMEM_PERSISTENT);
55   if (!response)
56     return MHD_NO;
57 
58   ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
59   MHD_destroy_response (response);
60 
61   return ret;
62 }
63 
64 
65 static int
iterate_post(void * coninfo_cls,enum MHD_ValueKind kind,const char * key,const char * filename,const char * content_type,const char * transfer_encoding,const char * data,uint64_t off,size_t size)66 iterate_post (void *coninfo_cls, enum MHD_ValueKind kind, const char *key,
67               const char *filename, const char *content_type,
68               const char *transfer_encoding, const char *data, uint64_t off,
69               size_t size)
70 {
71   struct connection_info_struct *con_info = coninfo_cls;
72 
73   if (0 == strcmp (key, "name"))
74     {
75       if ((size > 0) && (size <= MAXNAMESIZE))
76         {
77           char *answerstring;
78           answerstring = malloc (MAXANSWERSIZE);
79           if (!answerstring)
80             return MHD_NO;
81 
82           snprintf (answerstring, MAXANSWERSIZE, greetingpage, data);
83           con_info->answerstring = answerstring;
84         }
85       else
86         con_info->answerstring = NULL;
87 
88       return MHD_NO;
89     }
90 
91   return MHD_YES;
92 }
93 
94 static void
request_completed(void * cls,struct MHD_Connection * connection,void ** con_cls,enum MHD_RequestTerminationCode toe)95 request_completed (void *cls, struct MHD_Connection *connection,
96                    void **con_cls, enum MHD_RequestTerminationCode toe)
97 {
98   struct connection_info_struct *con_info = *con_cls;
99 
100   if (NULL == con_info)
101     return;
102 
103   if (con_info->connectiontype == POST)
104     {
105       MHD_destroy_post_processor (con_info->postprocessor);
106       if (con_info->answerstring)
107         free (con_info->answerstring);
108     }
109 
110   free (con_info);
111   *con_cls = NULL;
112 }
113 
114 
115 static int
answer_to_connection(void * cls,struct MHD_Connection * connection,const char * url,const char * method,const char * version,const char * upload_data,size_t * upload_data_size,void ** con_cls)116 answer_to_connection (void *cls, struct MHD_Connection *connection,
117                       const char *url, const char *method,
118                       const char *version, const char *upload_data,
119                       size_t *upload_data_size, void **con_cls)
120 {
121   if (NULL == *con_cls)
122     {
123       struct connection_info_struct *con_info;
124 
125       con_info = malloc (sizeof (struct connection_info_struct));
126       if (NULL == con_info)
127         return MHD_NO;
128       con_info->answerstring = NULL;
129 
130       if (0 == strcmp (method, "POST"))
131         {
132           con_info->postprocessor =
133             MHD_create_post_processor (connection, POSTBUFFERSIZE,
134                                        iterate_post, (void *) con_info);
135 
136           if (NULL == con_info->postprocessor)
137             {
138               free (con_info);
139               return MHD_NO;
140             }
141 
142           con_info->connectiontype = POST;
143         }
144       else
145         con_info->connectiontype = GET;
146 
147       *con_cls = (void *) con_info;
148 
149       return MHD_YES;
150     }
151 
152   if (0 == strcmp (method, "GET"))
153     {
154       return send_page (connection, askpage);
155     }
156 
157   if (0 == strcmp (method, "POST"))
158     {
159       struct connection_info_struct *con_info = *con_cls;
160 
161       if (*upload_data_size != 0)
162         {
163           MHD_post_process (con_info->postprocessor, upload_data,
164                             *upload_data_size);
165           *upload_data_size = 0;
166 
167           return MHD_YES;
168         }
169       else if (NULL != con_info->answerstring)
170         return send_page (connection, con_info->answerstring);
171     }
172 
173   return send_page (connection, errorpage);
174 }
175 
176 int
main()177 main ()
178 {
179   struct MHD_Daemon *daemon;
180 
181   daemon = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY, PORT, NULL, NULL,
182                              &answer_to_connection, NULL,
183                              MHD_OPTION_NOTIFY_COMPLETED, request_completed,
184                              NULL, MHD_OPTION_END);
185   if (NULL == daemon)
186     return 1;
187 
188   (void) getchar ();
189 
190   MHD_stop_daemon (daemon);
191 
192   return 0;
193 }
194