• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2      This file is part of libmicrohttpd
3      Copyright (C) 2007, 2009, 2011 Christian Grothoff
4 
5      libmicrohttpd is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 2, or (at your
8      option) any later version.
9 
10      libmicrohttpd is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14 
15      You should have received a copy of the GNU General Public License
16      along with libmicrohttpd; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20 
21 /**
22  * @file daemontest_urlparse.c
23  * @brief  Testcase for libmicrohttpd url parsing
24  * @author Christian Grothoff
25  */
26 
27 #include "MHD_config.h"
28 #include "platform.h"
29 #include <curl/curl.h>
30 #include <microhttpd.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <time.h>
34 
35 #ifdef _WIN32
36 #ifndef WIN32_LEAN_AND_MEAN
37 #define WIN32_LEAN_AND_MEAN 1
38 #endif /* !WIN32_LEAN_AND_MEAN */
39 #include <windows.h>
40 #endif
41 
42 #ifndef WINDOWS
43 #include <unistd.h>
44 #include <sys/socket.h>
45 #endif
46 
47 static int oneone;
48 
49 static int matches;
50 
51 struct CBC
52 {
53   char *buf;
54   size_t pos;
55   size_t size;
56 };
57 
58 static size_t
copyBuffer(void * ptr,size_t size,size_t nmemb,void * ctx)59 copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
60 {
61   struct CBC *cbc = ctx;
62 
63   if (cbc->pos + size * nmemb > cbc->size)
64     return 0;                   /* overflow */
65   memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
66   cbc->pos += size * nmemb;
67   return size * nmemb;
68 }
69 
70 static int
test_values(void * cls,enum MHD_ValueKind kind,const char * key,const char * value)71 test_values (void *cls,
72 	     enum MHD_ValueKind kind,
73 	     const char *key,
74 	     const char *value)
75 {
76   if ( (0 == strcmp (key, "a")) &&
77        (0 == strcmp (value, "b")) )
78     matches += 1;
79   if ( (0 == strcmp (key, "c")) &&
80        (0 == strcmp (value, "")) )
81     matches += 2;
82   if ( (0 == strcmp (key, "d")) &&
83        (NULL == value) )
84     matches += 4;
85   return MHD_YES;
86 }
87 
88 static int
ahc_echo(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 ** unused)89 ahc_echo (void *cls,
90           struct MHD_Connection *connection,
91           const char *url,
92           const char *method,
93           const char *version,
94           const char *upload_data, size_t *upload_data_size,
95           void **unused)
96 {
97   static int ptr;
98   const char *me = cls;
99   struct MHD_Response *response;
100   int ret;
101 
102   if (0 != strcmp (me, method))
103     return MHD_NO;              /* unexpected method */
104   if (&ptr != *unused)
105     {
106       *unused = &ptr;
107       return MHD_YES;
108     }
109   MHD_get_connection_values (connection,
110 			     MHD_GET_ARGUMENT_KIND,
111 			     &test_values,
112 			     NULL);
113   *unused = NULL;
114   response = MHD_create_response_from_buffer (strlen (url),
115 					      (void *) url,
116 					      MHD_RESPMEM_MUST_COPY);
117   ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
118   MHD_destroy_response (response);
119   if (ret == MHD_NO)
120     abort ();
121   return ret;
122 }
123 
124 
125 static int
testInternalGet(int poll_flag)126 testInternalGet (int poll_flag)
127 {
128   struct MHD_Daemon *d;
129   CURL *c;
130   char buf[2048];
131   struct CBC cbc;
132   CURLcode errornum;
133 
134   cbc.buf = buf;
135   cbc.size = 2048;
136   cbc.pos = 0;
137   d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG  | poll_flag,
138                         11080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
139   if (d == NULL)
140     return 1;
141   c = curl_easy_init ();
142   curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1:11080/hello_world?a=b&c=&d");
143   curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
144   curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
145   curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
146   curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
147   curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
148   if (oneone)
149     curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
150   else
151     curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
152   /* NOTE: use of CONNECTTIMEOUT without also
153      setting NOSIGNAL results in really weird
154      crashes on my system!*/
155   curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
156   if (CURLE_OK != (errornum = curl_easy_perform (c)))
157     {
158       fprintf (stderr,
159                "curl_easy_perform failed: `%s'\n",
160                curl_easy_strerror (errornum));
161       curl_easy_cleanup (c);
162       MHD_stop_daemon (d);
163       return 2;
164     }
165   curl_easy_cleanup (c);
166   MHD_stop_daemon (d);
167   if (cbc.pos != strlen ("/hello_world"))
168     return 4;
169   if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
170     return 8;
171   if (matches != 7)
172     return 16;
173   return 0;
174 }
175 
176 
177 int
main(int argc,char * const * argv)178 main (int argc, char *const *argv)
179 {
180   unsigned int errorCount = 0;
181 
182   oneone = (NULL != strrchr (argv[0], (int) '/')) ?
183     (NULL != strstr (strrchr (argv[0], (int) '/'), "11")) : 0;
184   if (0 != curl_global_init (CURL_GLOBAL_WIN32))
185     return 2;
186   errorCount += testInternalGet (0);
187   if (errorCount != 0)
188     fprintf (stderr, "Error (code: %u)\n", errorCount);
189   curl_global_cleanup ();
190   return errorCount != 0;       /* 0 == pass */
191 }
192