* @file nat/test_stun.c
* @brief Testcase for STUN library
* @author Bruno Souza Cabral
-
- *
+ * @author Christian Grothoff
*/
* The port the test service is running on (default 7895)
*/
static unsigned long port = 7895;
+
static int ret = 1;
-static char *stun_server = "stun.ekiga.net";
+static const char *stun_server = "stun.gnunet.org";
+
static int stun_port = 3478;
/**
*/
static struct GNUNET_NETWORK_Handle *lsock4;
-
/**
* The listen task ID for IPv4
*/
-static struct GNUNET_SCHEDULER_Task * ltask4;
-
+static struct GNUNET_SCHEDULER_Task *ltask4;
+/**
+ * Handle for the STUN request.
+ */
+static struct GNUNET_NAT_STUN_Handle *rh;
static void
print_answer(struct sockaddr_in* answer)
{
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,"External IP is: %s , with port %d\n", inet_ntoa(answer->sin_addr), ntohs(answer->sin_port));
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "External IP is: %s , with port %d\n",
+ inet_ntoa (answer->sin_addr),
+ ntohs (answer->sin_port));
+}
+
+
+/**
+ * Function that terminates the test.
+ */
+static void
+stop ()
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Stopping NAT and quitting...\n");
+ if (NULL != ltask4)
+ {
+ GNUNET_SCHEDULER_cancel (ltask4);
+ ltask4 = NULL;
+ }
+ if(NULL != lsock4)
+ {
+ GNUNET_NETWORK_socket_close(lsock4);
+ lsock4 = NULL;
+ }
+ if (NULL != rh)
+ {
+ GNUNET_NAT_stun_make_request_cancel (rh);
+ rh = NULL;
+ }
}
* Activity on our incoming socket. Read data from the
* incoming connection.
*
- * @param cls
+ * @param cls
* @param tc scheduler context
*/
static void
do_udp_read (void *cls,
const struct GNUNET_SCHEDULER_TaskContext *tc)
{
- //struct GNUNET_NAT_Test *tst = cls;
- unsigned char reply_buf[1024];
- ssize_t rlen;
- struct sockaddr_in answer;
-
- if ((0 != (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY)) &&
- (GNUNET_NETWORK_fdset_isset (tc->read_ready,
- lsock4)))
- {
- rlen = GNUNET_NETWORK_socket_recv (lsock4, reply_buf, sizeof (reply_buf));
-
-
- //Lets handle the packet
- memset(&answer, 0, sizeof(struct sockaddr_in));
- GNUNET_NAT_stun_handle_packet(reply_buf,rlen, &answer);
-
- //Print the answer
- ret = 0;
- print_answer(&answer);
-
- //Destroy the connection
- GNUNET_NETWORK_socket_close(lsock4);
-
- }
-
-
+ //struct GNUNET_NAT_Test *tst = cls;
+ unsigned char reply_buf[1024];
+ ssize_t rlen;
+ struct sockaddr_in answer;
+
+ ltask4 = NULL;
+ if ( (0 == (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY)) ||
+ (! GNUNET_NETWORK_fdset_isset (tc->read_ready,
+ lsock4)) )
+ {
+ fprintf (stderr,
+ "Timeout waiting for STUN response\n");
+ stop();
+ }
+ rlen = GNUNET_NETWORK_socket_recv (lsock4,
+ reply_buf,
+ sizeof (reply_buf));
+ memset (&answer,
+ 0,
+ sizeof(struct sockaddr_in));
+ if (GNUNET_OK !=
+ GNUNET_NAT_stun_handle_packet (reply_buf,
+ rlen,
+ &answer))
+ {
+ fprintf (stderr,
+ "Unexpected UDP packet, trying to read more\n");
+ ltask4 = GNUNET_SCHEDULER_add_read_net (TIMEOUT,
+ lsock4,
+ &do_udp_read, NULL);
+ return;
+ }
+ ret = 0;
+ print_answer (&answer);
+ stop ();
}
static struct GNUNET_NETWORK_Handle *
bind_v4 ()
{
- struct GNUNET_NETWORK_Handle *ls;
- struct sockaddr_in sa4;
- int eno;
+ struct GNUNET_NETWORK_Handle *ls;
+ struct sockaddr_in sa4;
+ int eno;
- memset (&sa4, 0, sizeof (sa4));
- sa4.sin_family = AF_INET;
- sa4.sin_port = htons (port);
+ memset (&sa4, 0, sizeof (sa4));
+ sa4.sin_family = AF_INET;
+ sa4.sin_port = htons (port);
#if HAVE_SOCKADDR_IN_SIN_LEN
- sa4.sin_len = sizeof (sa4);
-#endif
- ls = GNUNET_NETWORK_socket_create (AF_INET,
- SOCK_DGRAM,
- 0);
- if (NULL == ls)
- return NULL;
- if (GNUNET_OK !=
- GNUNET_NETWORK_socket_bind (ls, (const struct sockaddr *) &sa4,
- sizeof (sa4)))
- {
- eno = errno;
- GNUNET_NETWORK_socket_close (ls);
- errno = eno;
- return NULL;
- }
- return ls;
+ sa4.sin_len = sizeof (sa4);
+#endif
+ ls = GNUNET_NETWORK_socket_create (AF_INET,
+ SOCK_DGRAM,
+ 0);
+ if (NULL == ls)
+ return NULL;
+ if (GNUNET_OK !=
+ GNUNET_NETWORK_socket_bind (ls,
+ (const struct sockaddr *) &sa4,
+ sizeof (sa4)))
+ {
+ eno = errno;
+ GNUNET_NETWORK_socket_close (ls);
+ errno = eno;
+ return NULL;
+ }
+ return ls;
}
+
/**
- * Function that terminates the test.
+ * Function called with the result of the STUN request transmission attempt.
+ *
+ * @param cls unused
+ * @param error status code from STUN
*/
static void
-stop ()
+request_callback (void *cls,
+ enum GNUNET_NAT_StatusCode error)
{
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stopping NAT and quitting...\n");
-
- //Clean task
- if(NULL != ltask4)
- GNUNET_SCHEDULER_cancel (ltask4);
-
- //Clean socket
- if(NULL != ltask4)
- GNUNET_NETWORK_socket_close (lsock4);
-
+ rh = NULL;
+ if (GNUNET_NAT_ERROR_SUCCESS == error)
+ {
+ /* all good, start to receive */
+ ltask4 = GNUNET_SCHEDULER_add_read_net (TIMEOUT,
+ lsock4,
+ &do_udp_read,
+ NULL);
+ return;
+ }
+ if (error == GNUNET_NAT_ERROR_NOT_ONLINE)
+ {
+ ret = 77; /* report 'skip' */
+ fprintf (stderr,
+ "System is offline, cannot test STUN request.\n");
+ }
+ else
+ {
+ ret = error;
+ }
+ stop();
}
-static void request_callback(void *cls,
-enum GNUNET_NAT_StatusCode result)
-{
- ret = result;
- stop();
-};
-
-
/**
* Main function run with scheduler.
*/
static void
-run (void *cls, char *const *args, const char *cfgfile,
+run (void *cls,
+ char *const *args,
+ const char *cfgfile,
const struct GNUNET_CONFIGURATION_Handle *cfg)
{
-
-
- //Lets create the socket
- lsock4 = bind_v4 ();
- if (NULL == lsock4)
- {
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind");
- GNUNET_SCHEDULER_shutdown ();
- return;
- }
- else
- {
- //Lets call our function now when it accepts
- ltask4 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
- lsock4, &do_udp_read, NULL);
- /* So you read once and what will happen if you get an irregular message? Repeat and add timeout */
-
- }
-
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Service listens on port %u\n",
- port);
- GNUNET_NAT_stun_make_request(stun_server, stun_port, lsock4, &request_callback, NULL);
-
- //GNUNET_SCHEDULER_add_delayed (TIMEOUT, &stop, NULL);
-
+ //Lets create the socket
+ lsock4 = bind_v4 ();
+ if (NULL == lsock4)
+ {
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
+ "bind");
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Service listens on port %u\n",
+ port);
+ rh = GNUNET_NAT_stun_make_request (stun_server,
+ stun_port,
+ lsock4,
+ &request_callback, NULL);
+ GNUNET_SCHEDULER_add_delayed (TIMEOUT,
+ &stop, NULL);
}
int
main (int argc, char *const argv[])
{
- struct GNUNET_GETOPT_CommandLineOption options[] = {
- GNUNET_GETOPT_OPTION_END
- };
-
- char *const argv_prog[] = {
- "test-stun",
- "-c",
- "test_stun.conf",
- NULL
- };
- GNUNET_log_setup ("test-stun",
- "WARNING",
- NULL);
-
- /* Lets start resolver */
- char *fn;
- struct GNUNET_OS_Process *proc;
-
- fn = GNUNET_OS_get_libexec_binary_path ("gnunet-service-resolver");
- proc = GNUNET_OS_start_process (GNUNET_YES,
- GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
- NULL, NULL, NULL,
- fn,
- "gnunet-service-resolver",
- "-c", "test_stun.conf", NULL);
- GNUNET_assert (NULL != proc);
-
- GNUNET_PROGRAM_run (3, argv_prog, "test-stun", "nohelp", options, &run, NULL);
-
- /* Now kill the resolver */
- if (0 != GNUNET_OS_process_kill (proc, GNUNET_TERM_SIG))
- {
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
- }
- GNUNET_OS_process_wait (proc);
- GNUNET_OS_process_destroy (proc);
- proc = NULL;
-
-
- return ret;
+ struct GNUNET_GETOPT_CommandLineOption options[] = {
+ GNUNET_GETOPT_OPTION_END
+ };
+ char *const argv_prog[] = {
+ "test-stun",
+ "-c",
+ "test_stun.conf",
+ NULL
+ };
+ char *fn;
+ struct GNUNET_OS_Process *proc;
+
+ GNUNET_log_setup ("test-stun",
+ "WARNING",
+ NULL);
+
+ /* Lets start resolver */
+ fn = GNUNET_OS_get_libexec_binary_path ("gnunet-service-resolver");
+ proc = GNUNET_OS_start_process (GNUNET_YES,
+ GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+ NULL, NULL, NULL,
+ fn,
+ "gnunet-service-resolver",
+ "-c", "test_stun.conf", NULL);
+
+ if (NULL == proc)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "This test was unable to start gnunet-service-resolver, and it is required to run ...\n");
+ exit(1);
+ }
+
+ GNUNET_PROGRAM_run (3, argv_prog,
+ "test-stun", "nohelp",
+ options,
+ &run, NULL);
+
+ /* Now kill the resolver */
+ if (0 != GNUNET_OS_process_kill (proc, GNUNET_TERM_SIG))
+ {
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
+ }
+ GNUNET_OS_process_wait (proc);
+ GNUNET_OS_process_destroy (proc);
+ proc = NULL;
+ GNUNET_free (fn);
+
+ return ret;
}
/* end of test_stun.c */