preparations for fixing #4065
[oweals/gnunet.git] / src / util / test_socks.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2009 Christian Grothoff Jeff Burdges, and other contributing authors
4
5      GNUnet 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 3, or (at your
8      option) any later version.
9
10      GNUnet 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 GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18      Boston, MA 02110-1301, USA.
19 */
20 /**
21  * @file util/test_socks.c
22  * @brief tests for socks.c
23  */
24 #include "platform.h"
25 #include "gnunet_util_lib.h"
26
27
28 #define PORT 35124
29
30 #define MYNAME "test_sockst"
31
32 static struct GNUNET_CLIENT_Connection *client;
33
34 static struct GNUNET_SERVER_Handle *server;
35
36 static struct GNUNET_CONFIGURATION_Handle *cfg;
37
38 #define MY_TYPE 130
39
40 struct CopyContext
41 {
42   struct GNUNET_SERVER_Client *client;
43   struct GNUNET_MessageHeader *cpy;
44 };
45
46 static size_t
47 copy_msg (void *cls, size_t size, void *buf)
48 {
49   struct CopyContext *ctx = cls;
50   struct GNUNET_MessageHeader *cpy = ctx->cpy;
51
52   GNUNET_assert (sizeof (struct GNUNET_MessageHeader) == ntohs (cpy->size));
53   GNUNET_assert (size >= ntohs (cpy->size));
54   memcpy (buf, cpy, ntohs (cpy->size));
55   GNUNET_SERVER_receive_done (ctx->client, GNUNET_OK);
56   GNUNET_free (cpy);
57   GNUNET_free (ctx);
58   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Message bounced back to client\n");
59   return sizeof (struct GNUNET_MessageHeader);
60 }
61
62
63 /**
64  * Callback that just bounces the message back to the sender.
65  */
66 static void
67 echo_cb (void *cls, struct GNUNET_SERVER_Client *client,
68          const struct GNUNET_MessageHeader *message)
69 {
70   struct CopyContext *cc;
71   struct GNUNET_MessageHeader *cpy;
72
73   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
74               "Receiving message from client, bouncing back\n");
75   GNUNET_assert (sizeof (struct GNUNET_MessageHeader) == ntohs (message->size));
76   cc = GNUNET_new (struct CopyContext);
77   cc->client = client;
78   cpy = GNUNET_malloc (ntohs (message->size));
79   memcpy (cpy, message, ntohs (message->size));
80   cc->cpy = cpy;
81   GNUNET_assert (NULL !=
82                  GNUNET_SERVER_notify_transmit_ready (client,
83                                                       ntohs (message->size),
84                                                       GNUNET_TIME_UNIT_SECONDS,
85                                                       &copy_msg, cc));
86 }
87
88
89 static struct GNUNET_SERVER_MessageHandler handlers[] = {
90   {&echo_cb, NULL, MY_TYPE, sizeof (struct GNUNET_MessageHeader)},
91   {NULL, NULL, 0, 0}
92 };
93
94
95 static void
96 recv_bounce (void *cls, const struct GNUNET_MessageHeader *got)
97 {
98   int *ok = cls;
99   struct GNUNET_MessageHeader msg;
100
101   GNUNET_assert (got != NULL);  /* timeout */
102   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
103               "Receiving bounce, checking content\n");
104   msg.type = htons (MY_TYPE);
105   msg.size = htons (sizeof (struct GNUNET_MessageHeader));
106   GNUNET_assert (0 == memcmp (got, &msg, sizeof (struct GNUNET_MessageHeader)));
107   GNUNET_CLIENT_disconnect (client);
108   client = NULL;
109   GNUNET_SERVER_destroy (server);
110   server = NULL;
111   *ok = 0;
112 }
113
114
115 static size_t
116 make_msg (void *cls, size_t size, void *buf)
117 {
118   struct GNUNET_MessageHeader *msg = buf;
119
120   GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader));
121   msg->type = htons (MY_TYPE);
122   msg->size = htons (sizeof (struct GNUNET_MessageHeader));
123   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating message for transmission\n");
124   return sizeof (struct GNUNET_MessageHeader);
125 }
126
127
128 static void
129 task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
130 {
131   struct sockaddr_in sa;
132   struct sockaddr *sap[2];
133   socklen_t slens[2];
134
135   /* test that ill-configured client fails instantly */
136   GNUNET_assert (NULL == GNUNET_CLIENT_connect ("invalid-service", cfg));
137
138   /* test IPC between client and server */
139   sap[0] = (struct sockaddr *) &sa;
140   slens[0] = sizeof (sa);
141   sap[1] = NULL;
142   slens[1] = 0;
143   memset (&sa, 0, sizeof (sa));
144 #if HAVE_SOCKADDR_IN_SIN_LEN
145   sa.sin_len = sizeof (sa);
146 #endif
147   sa.sin_family = AF_INET;
148   sa.sin_port = htons (PORT);
149   server =
150       GNUNET_SERVER_create (NULL, NULL, sap, slens,
151                             GNUNET_TIME_relative_multiply
152                             (GNUNET_TIME_UNIT_MILLISECONDS, 10000), GNUNET_NO);
153   GNUNET_assert (server != NULL);
154   handlers[0].callback_cls = cls;
155   handlers[1].callback_cls = cls;
156   GNUNET_SERVER_add_handlers (server, handlers);
157   client = GNUNET_CLIENT_connect (MYNAME, cfg);
158   GNUNET_assert (client != NULL);
159   GNUNET_assert (NULL !=
160                  GNUNET_CLIENT_notify_transmit_ready (client,
161                                                       sizeof (struct
162                                                               GNUNET_MessageHeader),
163                                                       GNUNET_TIME_relative_multiply
164                                                       (GNUNET_TIME_UNIT_SECONDS,5),
165                                                       GNUNET_NO, &make_msg,
166                                                       NULL));
167   GNUNET_CLIENT_receive (client, &recv_bounce, cls,
168                          GNUNET_TIME_relative_multiply
169                          (GNUNET_TIME_UNIT_MILLISECONDS, 10000));
170 }
171
172
173 int
174 main (int argc, char *argv[])
175 {
176   int ok;
177   int status;
178   const char *socksport = "1081";
179
180   GNUNET_log_setup ("test_client",
181                     "WARNING",
182                     NULL);
183
184   pid_t pid = fork();
185   GNUNET_assert (pid >= 0);
186   if (pid == 0) 
187   {
188     execlp ("ssh",
189             "ssh","-D",socksport,
190             "-o","BatchMode yes",
191             "-o","UserKnownHostsFile /tmp/gnunet_test_socks_ssh_garbage",
192             "-o","StrictHostKeyChecking no",
193             "127.0.0.1","-N",(char*)NULL);
194     perror ("execlp (\"ssh\",\"ssh\",...,\"-D\",\"1081\",\"127.0.0.1\",\"-N\") ");
195     printf (""
196 "Please ensure you have ssh installed and have sshd installed and running :\n"
197 "\tsudo apt-get install openssh-client openssh-server\n"
198 "If you run Tor as a network proxy then Tor might prevent ssh from connecting\n"
199 "to localhost.  Please either run  make check  from an unproxied user, or else\n"
200 "add these lines to the beginning of your ~/.ssh/config file :"
201 "\tHost 127.0.0.1 localhost\n"
202 "\t  CheckHostIP no\n"
203 "\t  Protocol 2\n"
204 "\t  ProxyCommand nc 127.0.0.1 22\n");
205     kill (getppid(), SIGALRM);
206     return 1;
207   }
208   if (0 != sleep (1))
209   {
210     /* sleep interrupted, likely SIGALRM, failure to
211        launch child, terminate */
212     printf (""
213 "Please ensure you have ssh installed and have sshd installed and running :\n"
214 "\tsudo apt-get install openssh-client openssh-server\n"
215 "If you run Tor as a network proxy then Tor might prevent ssh from connecting\n"
216 "to localhost.  Please either run  make check  from an unproxied user, or else\n"
217 "add these lines to the beginning of your ~/.ssh/config file :"
218 "\tHost 127.0.0.1 localhost\n"
219 "\t  CheckHostIP no\n"
220 "\t  Protocol 2\n"
221 "\t  ProxyCommand nc 127.0.0.1 22\n");
222     return 77;
223   }
224   /* check if child exec()ed but died */
225   if (0 != waitpid (pid, &status, WNOHANG))
226   {
227     printf (""
228 "If you run Tor as a network proxy then Tor might prevent ssh from connecting\n"
229 "to localhost.  Please either run  make check  from an unproxied user, or else\n"
230 "add these lines to the beginning of your ~/.ssh/config file :"
231 "\tHost 127.0.0.1 localhost\n"
232 "\t  CheckHostIP no\n"
233 "\t  Protocol 2\n"
234 "\t  ProxyCommand nc 127.0.0.1 22\n");
235     return 77;
236   }
237
238   cfg = GNUNET_CONFIGURATION_create ();
239   GNUNET_CONFIGURATION_set_value_string (cfg, MYNAME, "SOCKSHOST", "127.0.0.1");
240   GNUNET_CONFIGURATION_set_value_string (cfg, MYNAME, "SOCKSPORT", socksport);
241   GNUNET_CONFIGURATION_set_value_number (cfg, MYNAME, "PORT", PORT);
242   GNUNET_CONFIGURATION_set_value_string (cfg, MYNAME, "HOSTNAME", "127.0.0.1");
243   ok = 1;
244   GNUNET_SCHEDULER_run (&task, &ok);
245   GNUNET_CONFIGURATION_destroy (cfg);
246
247   GNUNET_break (0 == kill (pid, SIGTERM));
248   GNUNET_break (pid == waitpid (pid, &status, 0));
249   return ok;
250 }
251
252 /* end of test_socks.c */