/*
This file is part of GNUnet.
Copyright (C) 2012, 2017 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published
by the Free Software Foundation, either version 3 of the License,
or (at your option) any later version.
GNUnet is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Affero General Public License for more details.
*/
/**
* @file cadet/gnunet-cadet.c
* @brief Print information about cadet tunnels and peers.
* @author Bartlomiej Polot
* @author Christian Grothoff
*/
#include "platform.h"
#include "gnunet_util_lib.h"
#include "gnunet_cadet_service.h"
#include "cadet.h"
/**
* Option -P.
*/
static int request_peers;
/**
* Option --peer
*/
static char *peer_id;
/**
* Option -T.
*/
static int request_tunnels;
/**
* Option --tunnel
*/
static char *tunnel_id;
/**
* Option --connection
*/
static char *conn_id;
/**
* Option --channel
*/
static char *channel_id;
/**
* Port to listen on (-o).
*/
static char *listen_port;
/**
* Request echo service
*/
static int echo;
/**
* Request a debug dump
*/
static int dump;
/**
* Time of last echo request.
*/
static struct GNUNET_TIME_Absolute echo_time;
/**
* Task for next echo request.
*/
static struct GNUNET_SCHEDULER_Task *echo_task;
/**
* Peer to connect to.
*/
static char *target_id;
/**
* Port to connect to
*/
static char *target_port = "default";
/**
* Cadet handle.
*/
static struct GNUNET_CADET_Handle *mh;
/**
* Channel handle.
*/
static struct GNUNET_CADET_Channel *ch;
/**
* HashCode of the given port string
*/
static struct GNUNET_HashCode porthash;
/**
* Data structure for ongoing reception of incoming virtual circuits.
*/
struct GNUNET_CADET_Port *lp;
/**
* Task for reading from stdin.
*/
static struct GNUNET_SCHEDULER_Task *rd_task;
/**
* Task for main job.
*/
static struct GNUNET_SCHEDULER_Task *job;
/**
* Wait for input on STDIO and send it out over the #ch.
*/
static void
listen_stdio (void);
/**
* Convert encryption status to human readable string.
*
* @param status Encryption status.
*
* @return Human readable string.
*/
static const char *
enc_2s (uint16_t status)
{
switch (status)
{
case 0:
return "NULL ";
case 1:
return "KSENT";
case 2:
return "KRECV";
case 3:
return "READY";
default:
return "";
}
}
/**
* Convert connection status to human readable string.
*
* @param status Connection status.
*
* @return Human readable string.
*/
static const char *
conn_2s (uint16_t status)
{
switch (status)
{
case 0:
return "NEW ";
case 1:
return "SRCH ";
case 2:
return "WAIT ";
case 3:
return "READY";
case 4:
return "SHUTD";
default:
return "";
}
}
/**
* Task to shut down this application.
*
* @param cls Closure (unused).
*/
static void
shutdown_task (void *cls)
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Shutdown\n");
if (NULL != ch)
{
GNUNET_CADET_channel_destroy (ch);
ch = NULL;
}
if (NULL != mh)
{
GNUNET_CADET_disconnect (mh);
mh = NULL;
}
if (NULL != rd_task)
{
GNUNET_SCHEDULER_cancel (rd_task);
rd_task = NULL;
}
if (NULL != echo_task)
{
GNUNET_SCHEDULER_cancel (echo_task);
echo_task = NULL;
}
if (NULL != job)
{
GNUNET_SCHEDULER_cancel (job);
job = NULL;
}
}
/**
* Task run in stdio mode, after some data is available at stdin.
*
* @param cls Closure (unused).
*/
static void
read_stdio (void *cls)
{
struct GNUNET_MQ_Envelope *env;
struct GNUNET_MessageHeader *msg;
char buf[60000];
ssize_t data_size;
rd_task = NULL;
data_size = read (0,
buf,
60000);
if (data_size < 1)
{
GNUNET_SCHEDULER_shutdown();
return;
}
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Read %u bytes from stdio\n",
(unsigned int) data_size);
env = GNUNET_MQ_msg_extra (msg,
data_size,
GNUNET_MESSAGE_TYPE_CADET_CLI);
GNUNET_memcpy (&msg[1],
buf,
data_size);
GNUNET_MQ_send (GNUNET_CADET_get_mq (ch),
env);
if (GNUNET_NO == echo)
{
listen_stdio ();
}
else
{
echo_time = GNUNET_TIME_absolute_get ();
}
}
/**
* Wait for input on STDIO and send it out over the #ch.
*/
static void
listen_stdio ()
{
struct GNUNET_NETWORK_FDSet *rs;
/* FIXME: why use 'rs' here, seems overly complicated... */
rs = GNUNET_NETWORK_fdset_create ();
GNUNET_NETWORK_fdset_set_native (rs,
0