GNUnet  0.10.x
Data Structures | Macros | Functions | Variables
plugin_transport_smtp.c File Reference

Implementation of the SMTP transport service. More...

#include "platform.h"
#include "gnunet_util.h"
#include "gnunet_constants.h"
#include "gnunet_protocols.h"
#include "gnunet_transport.h"
#include "gnunet_stats_service.h"
#include <libesmtp.h>
#include <signal.h>
Include dependency graph for plugin_transport_smtp.c:

Go to the source code of this file.

Data Structures

struct  EmailAddress
 Host-Address in a SMTP network. More...
 
struct  SMTPMessage
 Encapsulation of a GNUnet message in the SMTP mail body (before base64 encoding). More...
 
struct  GetMessageClosure
 

Macros

#define SMTP_MESSAGE_SIZE   65528
 The default maximum size of each outbound SMTP message. More...
 
#define DEBUG_SMTP   GNUNET_EXTRA_LOGGING
 
#define FILTER_STRING_SIZE   64
 
#define MAX_CHAR_PER_LINE   76
 
#define EBUF_LEN   128
 
#define strAUTOncmp(a, b)   strncmp(a,b,strlen(b))
 
#define READLINE(l, limit)
 
#define EBUF_LEN   128
 

Functions

static void * listenAndDistribute (void *unused)
 Listen to the pipe, decode messages and send to core. More...
 
static int api_verify_hello (const GNUNET_MessageHello *hello)
 Verify that a hello-Message is correct (a node is reachable at that address). More...
 
static GNUNET_MessageHello * api_create_hello ()
 Create a hello-Message for the current node. More...
 
static const char * get_message (void **buf, int *len, void *cls)
 
static int api_send (GNUNET_TSession *tsession, const void *msg, const unsigned int size, int important)
 Send a message to the specified remote node. More...
 
static int api_connect (const GNUNET_MessageHello *hello, GNUNET_TSession **tsessionPtr, int may_reuse)
 Establish a connection to a remote node. More...
 
static int api_disconnect (GNUNET_TSession *tsession)
 Disconnect from a remote node. More...
 
static int api_start_transport_server ()
 Start the server process to receive inbound traffic. More...
 
static int api_stop_transport_server ()
 Shutdown the server process (stop receiving inbound traffic). More...
 
static int api_hello_to_address (const GNUNET_MessageHello *hello, void **sa, unsigned int *sa_len)
 Convert SMTP hello to an IP address (always fails). More...
 
static int api_associate (GNUNET_TSession *tsession)
 Always fails. More...
 
static int api_test_would_try (GNUNET_TSession *tsession, unsigned int size, int important)
 Always succeeds (for now; we should look at adding frequency limits to SMTP in the future!). More...
 
GNUNET_TransportAPI * inittransport_smtp (struct GNUNET_CoreAPIForTransport *core)
 The exported method. More...
 
void donetransport_smtp ()
 

Variables

static GNUNET_NETWORK_STRUCT_END GNUNET_CoreAPIForTransport * core_api
 apis (our advertised API and the core api ) More...
 
static struct GNUNET_GE_Context * ectx
 
static struct GNUNET_ThreadHandle * dispatchThread
 Thread that listens for inbound messages. More...
 
static int smtp_shutdown = GNUNET_YES
 Flag to indicate that server has been shut down. More...
 
static char * smtp_server_name
 Set to the SMTP server hostname (and port) for outgoing messages. More...
 
static char * pipename
 
static struct GNUNET_Mutex * lock
 Lock for uses of libesmtp (not thread-safe). More...
 
static struct sigaction old_handler
 Old handler for SIGPIPE (kept to be able to restore). More...
 
static char * email
 
static GNUNET_TransportAPI smtpAPI
 
static GNUNET_Stats_ServiceAPI * stats
 
static int stat_bytesReceived
 
static int stat_bytesSent
 
static int stat_bytesDropped
 
static unsigned long long rate_limit
 How many e-mails are we allowed to send per hour? More...
 
static GNUNET_CronTime last_transmission
 

Detailed Description

Implementation of the SMTP transport service.

Author
Christian Grothoff
Renaldo Ferreira

Definition in file plugin_transport_smtp.c.

Macro Definition Documentation

◆ SMTP_MESSAGE_SIZE

#define SMTP_MESSAGE_SIZE   65528

The default maximum size of each outbound SMTP message.

Definition at line 41 of file plugin_transport_smtp.c.

Referenced by inittransport_smtp().

◆ DEBUG_SMTP

#define DEBUG_SMTP   GNUNET_EXTRA_LOGGING

Definition at line 43 of file plugin_transport_smtp.c.

◆ FILTER_STRING_SIZE

#define FILTER_STRING_SIZE   64

Definition at line 45 of file plugin_transport_smtp.c.

Referenced by api_create_hello(), and api_verify_hello().

◆ MAX_CHAR_PER_LINE

#define MAX_CHAR_PER_LINE   76

Definition at line 49 of file plugin_transport_smtp.c.

Referenced by listenAndDistribute().

◆ EBUF_LEN [1/2]

#define EBUF_LEN   128

Definition at line 51 of file plugin_transport_smtp.c.

Referenced by api_send().

◆ strAUTOncmp

#define strAUTOncmp (   a,
 
)    strncmp(a,b,strlen(b))

Definition at line 151 of file plugin_transport_smtp.c.

◆ READLINE

#define READLINE (   l,
  limit 
)
Value:
do { retl = fgets(l, (limit), fdes); \
if ( (retl == NULL) || (smtp_shutdown == GNUNET_YES)) {\
goto END; \
}\
if (core_api->load_monitor != NULL) \
GNUNET_network_monitor_notify_transmission(core_api->load_monitor, GNUNET_ND_DOWNLOAD, strlen(retl)); \
} while (0)
We&#39;re done processing.
static GNUNET_NETWORK_STRUCT_END GNUNET_CoreAPIForTransport * core_api
apis (our advertised API and the core api )
static struct LoggingHandle * l
static int smtp_shutdown
Flag to indicate that server has been shut down.
#define GNUNET_YES
Definition: gnunet_common.h:80

Referenced by listenAndDistribute().

◆ EBUF_LEN [2/2]

#define EBUF_LEN   128

Definition at line 51 of file plugin_transport_smtp.c.

Function Documentation

◆ listenAndDistribute()

static void* listenAndDistribute ( void *  unused)
static

Listen to the pipe, decode messages and send to core.

Definition at line 157 of file plugin_transport_smtp.c.

References _, core_api, ectx, END, GNUNET_free, GNUNET_malloc, GNUNET_new, GNUNET_NO, GNUNET_STRINGS_base64_decode(), SMTPMessage::header, line, MAX_CHAR_PER_LINE, OPEN, pipename, READLINE, SMTPMessage::sender, size, GNUNET_MessageHeader::size, smtp_shutdown, stat_bytesReceived, and stats.

Referenced by api_start_transport_server().

158 {
159  char *line;
160  unsigned int linesize;
161  SMTPMessage *mp;
162  FILE *fdes;
163  char *retl;
164  char *out;
165  unsigned int size;
166  GNUNET_TransportPacket *coreMP;
167  int fd;
168  unsigned int pos;
169 
170  linesize = ((GNUNET_MAX_BUFFER_SIZE * 4 / 3) + 8) * (MAX_CHAR_PER_LINE + 2) / MAX_CHAR_PER_LINE; /* maximum size of a line supported */
171  line = GNUNET_malloc (linesize + 2); /* 2 bytes for off-by-one errors, just to be safe... */
172 
173 #define READLINE(l,limit) \
174  do { retl = fgets(l, (limit), fdes); \
175  if ( (retl == NULL) || (smtp_shutdown == GNUNET_YES)) {\
176  goto END; \
177  }\
178  if (core_api->load_monitor != NULL) \
179  GNUNET_network_monitor_notify_transmission(core_api->load_monitor, GNUNET_ND_DOWNLOAD, strlen(retl)); \
180  } while (0)
181 
182 
183  while (smtp_shutdown == GNUNET_NO)
184  {
185  fd = OPEN (pipename, O_RDONLY | O_ASYNC);
186  if (fd == -1)
187  {
188  if (smtp_shutdown == GNUNET_NO)
189  GNUNET_thread_sleep (5 * GNUNET_CRON_SECONDS);
190  continue;
191  }
192  fdes = fdopen (fd, "r");
193  while (smtp_shutdown == GNUNET_NO)
194  {
195  /* skip until end of header */
196  do
197  {
198  READLINE (line, linesize);
199  }
200  while ((line[0] != '\r') && (line[0] != '\n')); /* expect newline */
201  READLINE (line, linesize); /* read base64 encoded message; decode, process */
202  pos = 0;
203  while (1)
204  {
205  pos = strlen (line) - 1; /* ignore new line */
206  READLINE (&line[pos], linesize - pos); /* read base64 encoded message; decode, process */
207  if ((line[pos] == '\r') || (line[pos] == '\n'))
208  break; /* empty line => end of message! */
209  }
210  size = GNUNET_STRINGS_base64_decode (line, pos, &out);
211  if (size < sizeof (SMTPMessage))
212  {
213  GNUNET_GE_BREAK (ectx, 0);
214  GNUNET_free (out);
215  goto END;
216  }
217 
218  mp = (SMTPMessage *) &out[size - sizeof (SMTPMessage)];
219  if (ntohs (mp->header.size) != size)
220  {
221  GNUNET_GE_LOG (ectx,
222  GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER,
223  _("Received malformed message via %s. Ignored.\n"),
224  "SMTP");
225 #if DEBUG_SMTP
226  GNUNET_GE_LOG (ectx,
227  GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
228  "Size returned by base64=%d, in the msg=%d.\n", size,
229  ntohl (mp->size));
230 #endif
231  GNUNET_free (out);
232  goto END;
233  }
234  if (stats != NULL)
235  stats->change (stat_bytesReceived, size);
236  coreMP = GNUNET_new (GNUNET_TransportPacket);
237  coreMP->msg = out;
238  coreMP->size = size - sizeof (SMTPMessage);
239  coreMP->tsession = NULL;
240  coreMP->sender = mp->sender;
241 #if DEBUG_SMTP
242  GNUNET_GE_LOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
243  "SMTP message passed to the core.\n");
244 #endif
245 
246  core_api->receive (coreMP);
247  }
248 END:
249 #if DEBUG_SMTP
250  GNUNET_GE_LOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
251  "SMTP message processed.\n");
252 #endif
253  if (fdes != NULL)
254  fclose (fdes);
255  }
256  GNUNET_free (line);
257  return NULL;
258 }
#define OPEN
Definition: plibc.h:651
static char * pipename
static GNUNET_Stats_ServiceAPI * stats
We&#39;re done processing.
#define GNUNET_NO
Definition: gnunet_common.h:81
#define GNUNET_new(type)
Allocate a struct or union of the given type.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
#define _(String)
GNU gettext support macro.
Definition: platform.h:208
static GNUNET_NETWORK_STRUCT_END GNUNET_CoreAPIForTransport * core_api
apis (our advertised API and the core api )
#define READLINE(l, limit)
static char * line
Desired phone line (string to be converted to a hash).
static struct GNUNET_GE_Context * ectx
size_t GNUNET_STRINGS_base64_decode(const char *data, size_t len, void **output)
Decode from Base64.
Definition: strings.c:2067
static unsigned int size
Size of the "table".
Definition: peer.c:67
static int smtp_shutdown
Flag to indicate that server has been shut down.
GNUNET_MessageHeader header
GNUNET_PeerIdentity sender
What is the identity of the sender (GNUNET_hash of public key)
Encapsulation of a GNUnet message in the SMTP mail body (before base64 encoding). ...
static int stat_bytesReceived
#define MAX_CHAR_PER_LINE
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ api_verify_hello()

static int api_verify_hello ( const GNUNET_MessageHello *  hello)
static

Verify that a hello-Message is correct (a node is reachable at that address).

Since the reply will be asynchronous, a method must be called on success.

Parameters
hellothe hello message to verify (the signature/crc have been verified before)
Returns
GNUNET_OK on success, GNUNET_SYSERR on error

Definition at line 272 of file plugin_transport_smtp.c.

References ectx, EmailAddress::filter, FILTER_STRING_SIZE, GNUNET_OK, GNUNET_SYSERR, and EmailAddress::senderAddress.

Referenced by api_create_hello(), and inittransport_smtp().

273 {
274  const EmailAddress *maddr;
275 
276  maddr = (const EmailAddress *) &hello[1];
277  if ((ntohs (hello->header.size) !=
278  sizeof (GNUNET_MessageHello) + ntohs (hello->senderAddressSize)) ||
279  (maddr->senderAddress
280  [ntohs (hello->senderAddressSize) - 1 - FILTER_STRING_SIZE] != '\0'))
281  {
282  GNUNET_GE_BREAK (ectx, 0);
283  return GNUNET_SYSERR; /* obviously invalid */
284  }
285  if (NULL == strstr (maddr->filter, ": "))
286  return GNUNET_SYSERR;
287  return GNUNET_OK;
288 }
char filter[64]
Filter line that every sender must include in the E-mails such that the receiver can effectively filt...
char senderAddress[0]
Claimed E-mail address of the sender.
Host-Address in a SMTP network.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
static struct GNUNET_GE_Context * ectx
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
#define FILTER_STRING_SIZE
Here is the caller graph for this function:

◆ api_create_hello()

static GNUNET_MessageHello* api_create_hello ( )
static

Create a hello-Message for the current node.

The hello is created without signature and without a timestamp. The GNUnet core will GNUNET_RSA_sign the message and add an expiration time.

Returns
hello on success, NULL on error

Definition at line 298 of file plugin_transport_smtp.c.

References _, api_verify_hello(), core_api, ectx, email, EmailAddress::filter, filter, FILTER_STRING_SIZE, GNUNET_free, GNUNET_malloc, GNUNET_memcpy, GNUNET_SYSERR, msg, EmailAddress::senderAddress, and smtpAPI.

Referenced by inittransport_smtp().

299 {
300  GNUNET_MessageHello *msg;
301  char *filter;
302  EmailAddress *haddr;
303  int i;
304 
305  GNUNET_GC_get_configuration_value_string (core_api->cfg, "SMTP", "FILTER",
306  "X-mailer: GNUnet", &filter);
307  if (NULL == strstr (filter, ": "))
308  {
309  GNUNET_GE_LOG (ectx, GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER,
310  _("SMTP filter string to invalid, lacks ': '\n"));
311  GNUNET_free (filter);
312  return NULL;
313  }
314 
315  if (strlen (filter) > FILTER_STRING_SIZE)
316  {
317  filter[FILTER_STRING_SIZE] = '\0';
318  GNUNET_GE_LOG (ectx, GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER,
319  _("SMTP filter string to long, capped to `%s'\n"), filter);
320  }
321  i = (strlen (email) + 8) & (~7); /* make multiple of 8 */
322  msg =
323  GNUNET_malloc (sizeof (GNUNET_MessageHello) + sizeof (EmailAddress) + i);
324  memset (msg, 0, sizeof (GNUNET_MessageHello) + sizeof (EmailAddress) + i);
325  haddr = (EmailAddress *) &msg[1];
326  memset (&haddr->filter[0], 0, FILTER_STRING_SIZE);
327  strcpy (&haddr->filter[0], filter);
328  GNUNET_memcpy (&haddr->senderAddress[0], email, strlen (email) + 1);
329  msg->senderAddressSize = htons (strlen (email) + 1 + sizeof (EmailAddress));
330  msg->protocol = htons (GNUNET_TRANSPORT_PROTOCOL_NUMBER_SMTP);
331  msg->MTU = htonl (smtpAPI.mtu);
332  msg->header.size = htons (GNUNET_sizeof_hello (msg));
333  if (api_verify_hello (msg) == GNUNET_SYSERR)
334  GNUNET_GE_ASSERT (ectx, 0);
335  GNUNET_free (filter);
336  return msg;
337 }
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
char filter[64]
Filter line that every sender must include in the E-mails such that the receiver can effectively filt...
char senderAddress[0]
Claimed E-mail address of the sender.
Host-Address in a SMTP network.
#define _(String)
GNU gettext support macro.
Definition: platform.h:208
static GNUNET_NETWORK_STRUCT_END GNUNET_CoreAPIForTransport * core_api
apis (our advertised API and the core api )
static GNUNET_TransportAPI smtpAPI
static char * email
#define GNUNET_memcpy(dst, src, n)
static struct GNUNET_GE_Context * ectx
static struct GNUNET_CONTAINER_BloomFilter * filter
Bloomfilter to quickly tell if we don&#39;t have the content.
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
#define FILTER_STRING_SIZE
static int api_verify_hello(const GNUNET_MessageHello *hello)
Verify that a hello-Message is correct (a node is reachable at that address).
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_message()

static const char* get_message ( void **  buf,
int *  len,
void *  cls 
)
static

Definition at line 347 of file plugin_transport_smtp.c.

References GetMessageClosure::ebody, GetMessageClosure::esize, and GetMessageClosure::pos.

Referenced by api_send().

348 {
349  struct GetMessageClosure *gmc = cls;
350 
351  *buf = NULL;
352  if (len == NULL)
353  {
354  gmc->pos = 0;
355  return NULL;
356  }
357  if (gmc->pos == gmc->esize)
358  return NULL; /* done */
359  *len = gmc->esize;
360  gmc->pos = gmc->esize;
361  return gmc->ebody;
362 }
static char buf[2048]
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
Here is the caller graph for this function:

◆ api_send()

static int api_send ( GNUNET_TSession *  tsession,
const void *  msg,
const unsigned int  size,
int  important 
)
static

Send a message to the specified remote node.

Parameters
tsessionthe GNUNET_MessageHello identifying the remote node
msgwhat to send
sizethe size of the message
importantis this message important enough to override typical limits?
Returns
GNUNET_SYSERR on error, GNUNET_OK on success

Definition at line 374 of file plugin_transport_smtp.c.

References _, core_api, GetMessageClosure::ebody, EBUF_LEN, ectx, email, GetMessageClosure::esize, EmailAddress::filter, filter, get_message(), GNUNET_free, GNUNET_malloc, GNUNET_memcpy, GNUNET_NO, GNUNET_OK, GNUNET_strdup, GNUNET_STRINGS_base64_encode(), GNUNET_SYSERR, GNUNET_YES, SMTPMessage::header, last_transmission, lock, m, GetMessageClosure::pos, rate_limit, SMTPMessage::sender, EmailAddress::senderAddress, GNUNET_MessageHeader::size, smtp_server_name, smtp_shutdown, smtpAPI, stat_bytesSent, stats, and GNUNET_MessageHeader::type.

Referenced by inittransport_smtp().

376 {
377  const GNUNET_MessageHello *hello;
378  const EmailAddress *haddr;
379  char *m;
380  char *filter;
381  char *fvalue;
382  SMTPMessage *mp;
383  struct GetMessageClosure gm_cls;
384  smtp_session_t session;
385  smtp_message_t message;
386  smtp_recipient_t recipient;
387 
388 #define EBUF_LEN 128
389  char ebuf[EBUF_LEN];
390  GNUNET_CronTime now;
391 
392  if (smtp_shutdown == GNUNET_YES)
393  return GNUNET_SYSERR;
394  if ((size == 0) || (size > smtpAPI.mtu))
395  {
396  GNUNET_GE_BREAK (ectx, 0);
397  return GNUNET_SYSERR;
398  }
399  now = GNUNET_get_time ();
400  if ((important != GNUNET_YES) &&
401  ((now - last_transmission) * rate_limit) < GNUNET_CRON_HOURS)
402  return GNUNET_NO; /* rate too high */
403  last_transmission = now;
404 
405  hello = (const GNUNET_MessageHello *) tsession->internal;
406  if (hello == NULL)
407  return GNUNET_SYSERR;
408  GNUNET_mutex_lock (lock);
409  session = smtp_create_session ();
410  if (session == NULL)
411  {
412  GNUNET_GE_LOG (ectx,
413  GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_USER |
414  GNUNET_GE_IMMEDIATE, _("SMTP: `%s' failed: %s.\n"),
415  "smtp_create_session", smtp_strerror (smtp_errno (), ebuf,
416  EBUF_LEN));
417  GNUNET_mutex_unlock (lock);
418  return GNUNET_SYSERR;
419  }
420  if (0 == smtp_set_server (session, smtp_server_name))
421  {
422  GNUNET_GE_LOG (ectx,
423  GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_USER |
424  GNUNET_GE_IMMEDIATE, _("SMTP: `%s' failed: %s.\n"),
425  "smtp_set_server", smtp_strerror (smtp_errno (), ebuf,
426  EBUF_LEN));
427  smtp_destroy_session (session);
428  GNUNET_mutex_unlock (lock);
429  return GNUNET_SYSERR;
430  }
431  haddr = (const EmailAddress *) &hello[1];
432  message = smtp_add_message (session);
433  if (message == NULL)
434  {
435  GNUNET_GE_LOG (ectx,
436  GNUNET_GE_WARNING | GNUNET_GE_ADMIN | GNUNET_GE_USER |
437  GNUNET_GE_BULK, _("SMTP: `%s' failed: %s.\n"),
438  "smtp_add_message", smtp_strerror (smtp_errno (), ebuf,
439  EBUF_LEN));
440  smtp_destroy_session (session);
441  GNUNET_mutex_unlock (lock);
442  return GNUNET_SYSERR;
443  }
444  smtp_set_header (message, "To", NULL, haddr->senderAddress);
445  smtp_set_header (message, "From", NULL, email);
446 
447  filter = GNUNET_strdup (haddr->filter);
448  fvalue = strstr (filter, ": ");
449  GNUNET_GE_ASSERT (NULL, NULL != fvalue);
450  fvalue[0] = '\0';
451  fvalue += 2;
452  if (0 == smtp_set_header (message, filter, fvalue))
453  {
454  GNUNET_GE_LOG (ectx,
455  GNUNET_GE_WARNING | GNUNET_GE_ADMIN | GNUNET_GE_USER |
456  GNUNET_GE_BULK, _("SMTP: `%s' failed: %s.\n"),
457  "smtp_set_header", smtp_strerror (smtp_errno (), ebuf,
458  EBUF_LEN));
459  smtp_destroy_session (session);
460  GNUNET_mutex_unlock (lock);
461  GNUNET_free (filter);
462  return GNUNET_SYSERR;
463  }
464  GNUNET_free (filter);
465  m = GNUNET_malloc (size + sizeof (SMTPMessage));
466  GNUNET_memcpy (m, msg, size);
467  mp = (SMTPMessage *) &m[size];
468  mp->header.size = htons (size + sizeof (SMTPMessage));
469  mp->header.type = htons (0);
470  mp->sender = *core_api->my_identity;
471  gm_cls.ebody = NULL;
472  gm_cls.pos = 0;
473  gm_cls.esize = GNUNET_STRINGS_base64_encode (m, size + sizeof (SMTPMessage), &gm_cls.ebody);
474  GNUNET_free (m);
475  if (0 == smtp_size_set_estimate (message, gm_cls.esize))
476  {
477  GNUNET_GE_LOG (ectx,
478  GNUNET_GE_WARNING | GNUNET_GE_ADMIN | GNUNET_GE_USER |
479  GNUNET_GE_BULK, _("SMTP: `%s' failed: %s.\n"),
480  "smtp_size_set_estimate", smtp_strerror (smtp_errno (), ebuf,
481  EBUF_LEN));
482  }
483  if (0 == smtp_set_messagecb (message, &get_message, &gm_cls))
484  {
485  GNUNET_GE_LOG (ectx,
486  GNUNET_GE_WARNING | GNUNET_GE_ADMIN | GNUNET_GE_USER |
487  GNUNET_GE_BULK, _("SMTP: `%s' failed: %s.\n"),
488  "smtp_set_messagecb", smtp_strerror (smtp_errno (), ebuf,
489  EBUF_LEN));
490  smtp_destroy_session (session);
491  GNUNET_mutex_unlock (lock);
492  GNUNET_free (gm_cls.ebody);
493  return GNUNET_SYSERR;
494  }
495  recipient = smtp_add_recipient (message, haddr->senderAddress);
496  if (recipient == NULL)
497  {
498  GNUNET_GE_LOG (ectx,
499  GNUNET_GE_WARNING | GNUNET_GE_ADMIN | GNUNET_GE_USER |
500  GNUNET_GE_BULK, _("SMTP: `%s' failed: %s.\n"),
501  "smtp_add_recipient", smtp_strerror (smtp_errno (), ebuf,
502  EBUF_LEN));
503  smtp_destroy_session (session);
504  GNUNET_mutex_unlock (lock);
505  return GNUNET_SYSERR;
506  }
507  if (0 == smtp_start_session (session))
508  {
509  GNUNET_GE_LOG (ectx,
510  GNUNET_GE_WARNING | GNUNET_GE_ADMIN | GNUNET_GE_USER |
511  GNUNET_GE_BULK, _("SMTP: `%s' failed: %s.\n"),
512  "smtp_start_session", smtp_strerror (smtp_errno (), ebuf,
513  EBUF_LEN));
514  smtp_destroy_session (session);
515  GNUNET_mutex_unlock (lock);
516  GNUNET_free (gm_cls.ebody);
517  return GNUNET_SYSERR;
518  }
519  if (stats != NULL)
520  stats->change (stat_bytesSent, size);
521  if (core_api->load_monitor != NULL)
522  GNUNET_network_monitor_notify_transmission (core_api->load_monitor,
523  GNUNET_ND_UPLOAD, gm_cls.esize);
524  smtp_message_reset_status (message); /* this is needed to plug a 28-byte/message memory leak in libesmtp */
525  smtp_destroy_session (session);
526  GNUNET_mutex_unlock (lock);
527  GNUNET_free (gm_cls.ebody);
528  return GNUNET_OK;
529 }
static unsigned long long rate_limit
How many e-mails are we allowed to send per hour?
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
char filter[64]
Filter line that every sender must include in the E-mails such that the receiver can effectively filt...
char senderAddress[0]
Claimed E-mail address of the sender.
static GNUNET_Stats_ServiceAPI * stats
static GNUNET_CronTime last_transmission
static char * smtp_server_name
Set to the SMTP server hostname (and port) for outgoing messages.
Host-Address in a SMTP network.
#define GNUNET_NO
Definition: gnunet_common.h:81
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define _(String)
GNU gettext support macro.
Definition: platform.h:208
static GNUNET_NETWORK_STRUCT_END GNUNET_CoreAPIForTransport * core_api
apis (our advertised API and the core api )
static GNUNET_TransportAPI smtpAPI
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition: gnunet-arm.c:99
static char * email
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
#define GNUNET_memcpy(dst, src, n)
static struct GNUNET_GE_Context * ectx
static struct GNUNET_CONTAINER_BloomFilter * filter
Bloomfilter to quickly tell if we don&#39;t have the content.
size_t GNUNET_STRINGS_base64_encode(const void *in, size_t len, char **output)
Encode into Base64.
Definition: strings.c:2004
#define EBUF_LEN
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
static const char * get_message(void **buf, int *len, void *cls)
static unsigned int size
Size of the "table".
Definition: peer.c:67
static struct GNUNET_Mutex * lock
Lock for uses of libesmtp (not thread-safe).
static int smtp_shutdown
Flag to indicate that server has been shut down.
GNUNET_MessageHeader header
#define GNUNET_YES
Definition: gnunet_common.h:80
GNUNET_PeerIdentity sender
What is the identity of the sender (GNUNET_hash of public key)
Encapsulation of a GNUnet message in the SMTP mail body (before base64 encoding). ...
static int stat_bytesSent
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ api_connect()

static int api_connect ( const GNUNET_MessageHello *  hello,
GNUNET_TSession **  tsessionPtr,
int  may_reuse 
)
static

Establish a connection to a remote node.

Parameters
hellothe hello-Message for the target node
tsessionPtrthe session handle that is to be set
may_reusecan we re-use an existing connection?
Returns
GNUNET_OK on success, GNUNET_SYSERR if the operation failed

Definition at line 539 of file plugin_transport_smtp.c.

References GNUNET_malloc, GNUNET_memcpy, GNUNET_new, GNUNET_OK, and smtpAPI.

Referenced by inittransport_smtp().

541 {
542  GNUNET_TSession *tsession;
543 
544  tsession = GNUNET_new (GNUNET_TSession);
545  tsession->internal = GNUNET_malloc (GNUNET_sizeof_hello (hello));
546  tsession->peer = hello->senderIdentity;
547  GNUNET_memcpy (tsession->internal, hello, GNUNET_sizeof_hello (hello));
548  tsession->ttype = smtpAPI.protocol_number;
549  (*tsessionPtr) = tsession;
550  return GNUNET_OK;
551 }
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
#define GNUNET_new(type)
Allocate a struct or union of the given type.
static GNUNET_TransportAPI smtpAPI
#define GNUNET_memcpy(dst, src, n)
#define GNUNET_malloc(size)
Wrapper around malloc.
Here is the caller graph for this function:

◆ api_disconnect()

static int api_disconnect ( GNUNET_TSession *  tsession)
static

Disconnect from a remote node.

Parameters
tsessionthe session that is closed
Returns
GNUNET_OK on success, GNUNET_SYSERR if the operation failed

Definition at line 560 of file plugin_transport_smtp.c.

References GNUNET_free, and GNUNET_OK.

Referenced by inittransport_smtp().

561 {
562  if (tsession != NULL)
563  {
564  if (tsession->internal != NULL)
565  GNUNET_free (tsession->internal);
566  GNUNET_free (tsession);
567  }
568  return GNUNET_OK;
569 }
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
#define GNUNET_free(ptr)
Wrapper around free.
Here is the caller graph for this function:

◆ api_start_transport_server()

static int api_start_transport_server ( )
static

Start the server process to receive inbound traffic.

Returns
GNUNET_OK on success, GNUNET_SYSERR if the operation failed

Definition at line 576 of file plugin_transport_smtp.c.

References dispatchThread, ectx, GNUNET_NO, GNUNET_OK, GNUNET_SYSERR, listenAndDistribute(), and smtp_shutdown.

Referenced by inittransport_smtp().

577 {
579  /* initialize SMTP network */
580  dispatchThread = GNUNET_thread_create (&listenAndDistribute, NULL, 1024 * 4);
581  if (dispatchThread == NULL)
582  {
583  GNUNET_GE_DIE_STRERROR (ectx,
584  GNUNET_GE_ADMIN | GNUNET_GE_BULK | GNUNET_GE_FATAL,
585  "pthread_create");
586  return GNUNET_SYSERR;
587  }
588  return GNUNET_OK;
589 }
static void * listenAndDistribute(void *unused)
Listen to the pipe, decode messages and send to core.
#define GNUNET_NO
Definition: gnunet_common.h:81
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
static struct GNUNET_GE_Context * ectx
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
static int smtp_shutdown
Flag to indicate that server has been shut down.
static struct GNUNET_ThreadHandle * dispatchThread
Thread that listens for inbound messages.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ api_stop_transport_server()

static int api_stop_transport_server ( )
static

Shutdown the server process (stop receiving inbound traffic).

Maybe restarted later!

Definition at line 596 of file plugin_transport_smtp.c.

References dispatchThread, GNUNET_OK, GNUNET_YES, and smtp_shutdown.

Referenced by inittransport_smtp().

597 {
598  void *unused;
599 
601  GNUNET_thread_stop_sleep (dispatchThread);
602  GNUNET_thread_join (dispatchThread, &unused);
603  return GNUNET_OK;
604 }
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
static int smtp_shutdown
Flag to indicate that server has been shut down.
static struct GNUNET_ThreadHandle * dispatchThread
Thread that listens for inbound messages.
#define GNUNET_YES
Definition: gnunet_common.h:80
Here is the caller graph for this function:

◆ api_hello_to_address()

static int api_hello_to_address ( const GNUNET_MessageHello *  hello,
void **  sa,
unsigned int *  sa_len 
)
static

Convert SMTP hello to an IP address (always fails).

Definition at line 610 of file plugin_transport_smtp.c.

References GNUNET_SYSERR.

Referenced by inittransport_smtp().

612 {
613  return GNUNET_SYSERR;
614 }
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
Here is the caller graph for this function:

◆ api_associate()

static int api_associate ( GNUNET_TSession *  tsession)
static

Always fails.

Definition at line 620 of file plugin_transport_smtp.c.

References GNUNET_SYSERR.

Referenced by inittransport_smtp().

621 {
622  return GNUNET_SYSERR; /* SMTP connections can never be associated */
623 }
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
Here is the caller graph for this function:

◆ api_test_would_try()

static int api_test_would_try ( GNUNET_TSession *  tsession,
unsigned int  size,
int  important 
)
static

Always succeeds (for now; we should look at adding frequency limits to SMTP in the future!).

Definition at line 630 of file plugin_transport_smtp.c.

References GNUNET_OK.

Referenced by inittransport_smtp().

632 {
633  return GNUNET_OK; /* we always try... */
634 }
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
Here is the caller graph for this function:

◆ inittransport_smtp()

GNUNET_TransportAPI* inittransport_smtp ( struct GNUNET_CoreAPIForTransport *  core)

The exported method.

Makes the core api available via a global and returns the smtp transport API.

Definition at line 641 of file plugin_transport_smtp.c.

References _, api_associate(), api_connect(), api_create_hello(), api_disconnect(), api_hello_to_address(), api_send(), api_start_transport_server(), api_stop_transport_server(), api_test_would_try(), api_verify_hello(), core, core_api, ectx, email, gettext_noop, GNUNET_free, GNUNET_NO, lock, old_handler, pipename, rate_limit, SMTP_MESSAGE_SIZE, smtp_server_name, smtpAPI, stat_bytesDropped, stat_bytesReceived, stat_bytesSent, stats, and UNLINK.

642 {
643  unsigned long long mtu;
644  struct sigaction sa;
645 
646  core_api = core;
647  ectx = core->ectx;
648  if (!GNUNET_GC_have_configuration_value (core_api->cfg, "SMTP", "EMAIL"))
649  {
650  GNUNET_GE_LOG (ectx, GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
651  _
652  ("No email-address specified, can not start SMTP transport.\n"));
653  return NULL;
654  }
655  GNUNET_GC_get_configuration_value_number (core_api->cfg, "SMTP", "MTU", 1200,
657  SMTP_MESSAGE_SIZE, &mtu);
658  GNUNET_GC_get_configuration_value_number (core_api->cfg, "SMTP", "RATELIMIT",
659  0, 0, 1024 * 1024, &rate_limit);
660  stats = core_api->service_request ("stats");
661  if (stats != NULL)
662  {
664  stats->create (gettext_noop ("# bytes received via SMTP"));
665  stat_bytesSent = stats->create (gettext_noop ("# bytes sent via SMTP"));
667  stats->create (gettext_noop ("# bytes dropped by SMTP (outgoing)"));
668  }
669  GNUNET_GC_get_configuration_value_filename (core_api->cfg, "SMTP", "PIPE", &pipename);
670  UNLINK (pipename);
671  if (0 != mkfifo (pipename, S_IWUSR | S_IRUSR | S_IWGRP | S_IWOTH))
672  {
673  GNUNET_GE_LOG_STRERROR (ectx,
674  GNUNET_GE_ADMIN | GNUNET_GE_BULK | GNUNET_GE_FATAL,
675  "mkfifo");
677  core_api->service_release (stats);
678  stats = NULL;
679  return NULL;
680  }
681  /* we need to allow the mailer program to send us messages;
682  * easiest done by giving it write permissions (see Mantis #1142) */
683  if (0 != chmod (pipename, S_IWUSR | S_IRUSR | S_IWGRP | S_IWOTH))
684  GNUNET_GE_LOG_STRERROR (ectx,
685  GNUNET_GE_ADMIN | GNUNET_GE_BULK |
686  GNUNET_GE_WARNING, "chmod");
687  GNUNET_GC_get_configuration_value_string (core_api->cfg, "SMTP", "EMAIL", NULL,
688  &email);
689  lock = GNUNET_mutex_create (GNUNET_NO);
690  GNUNET_GC_get_configuration_value_string (core_api->cfg, "SMTP", "SERVER",
691  "localhost:25", &smtp_server_name);
692  sa.sa_handler = SIG_IGN;
693  sigemptyset (&sa.sa_mask);
694  sa.sa_flags = 0;
695  sigaction (SIGPIPE, &sa, &old_handler);
696 
697  smtpAPI.protocol_number = GNUNET_TRANSPORT_PROTOCOL_NUMBER_SMTP;
698  smtpAPI.mtu = mtu - sizeof (SMTPMessage);
699  smtpAPI.cost = 50;
700  smtpAPI.hello_verify = &api_verify_hello;
701  smtpAPI.hello_create = &api_create_hello;
702  smtpAPI.connect = &api_connect;
703  smtpAPI.send = &api_send;
704  smtpAPI.associate = &api_associate;
705  smtpAPI.disconnect = &api_disconnect;
706  smtpAPI.server_start = &api_start_transport_server;
707  smtpAPI.server_stop = &api_stop_transport_server;
708  smtpAPI.hello_to_address = &api_hello_to_address;
709  smtpAPI.send_now_test = &api_test_would_try;
710  return &smtpAPI;
711 }
static unsigned long long rate_limit
How many e-mails are we allowed to send per hour?
static char * pipename
static GNUNET_Stats_ServiceAPI * stats
static char * smtp_server_name
Set to the SMTP server hostname (and port) for outgoing messages.
static int api_test_would_try(GNUNET_TSession *tsession, unsigned int size, int important)
Always succeeds (for now; we should look at adding frequency limits to SMTP in the future!)...
static int api_stop_transport_server()
Shutdown the server process (stop receiving inbound traffic).
static int stat_bytesDropped
#define GNUNET_NO
Definition: gnunet_common.h:81
static int api_disconnect(GNUNET_TSession *tsession)
Disconnect from a remote node.
#define UNLINK(f)
Definition: plibc.h:666
#define _(String)
GNU gettext support macro.
Definition: platform.h:208
static GNUNET_NETWORK_STRUCT_END GNUNET_CoreAPIForTransport * core_api
apis (our advertised API and the core api )
static int api_associate(GNUNET_TSession *tsession)
Always fails.
static GNUNET_TransportAPI smtpAPI
static char * email
static struct sigaction old_handler
Old handler for SIGPIPE (kept to be able to restore).
static struct GNUNET_GE_Context * ectx
static int api_start_transport_server()
Start the server process to receive inbound traffic.
static int api_hello_to_address(const GNUNET_MessageHello *hello, void **sa, unsigned int *sa_len)
Convert SMTP hello to an IP address (always fails).
static int api_send(GNUNET_TSession *tsession, const void *msg, const unsigned int size, int important)
Send a message to the specified remote node.
#define SMTP_MESSAGE_SIZE
The default maximum size of each outbound SMTP message.
static int api_connect(const GNUNET_MessageHello *hello, GNUNET_TSession **tsessionPtr, int may_reuse)
Establish a connection to a remote node.
static struct GNUNET_Mutex * lock
Lock for uses of libesmtp (not thread-safe).
static int api_verify_hello(const GNUNET_MessageHello *hello)
Verify that a hello-Message is correct (a node is reachable at that address).
Encapsulation of a GNUnet message in the SMTP mail body (before base64 encoding). ...
static int stat_bytesReceived
static GNUNET_MessageHello * api_create_hello()
Create a hello-Message for the current node.
static int stat_bytesSent
static struct GNUNET_CORE_Handle * core
Handle to the CORE service.
#define GNUNET_free(ptr)
Wrapper around free.
#define gettext_noop(String)
Definition: gettext.h:69
Here is the call graph for this function:

◆ donetransport_smtp()

void donetransport_smtp ( )

Definition at line 714 of file plugin_transport_smtp.c.

References core_api, email, GNUNET_free, lock, old_handler, pipename, smtp_server_name, stats, and UNLINK.

715 {
716  sigaction (SIGPIPE, &old_handler, NULL);
718  if (stats != NULL)
719  {
720  core_api->service_release (stats);
721  stats = NULL;
722  }
723  GNUNET_mutex_destroy (lock);
724  lock = NULL;
725  UNLINK (pipename);
727  pipename = NULL;
728  GNUNET_free (email);
729  email = NULL;
730 }
static char * pipename
static GNUNET_Stats_ServiceAPI * stats
static char * smtp_server_name
Set to the SMTP server hostname (and port) for outgoing messages.
#define UNLINK(f)
Definition: plibc.h:666
static GNUNET_NETWORK_STRUCT_END GNUNET_CoreAPIForTransport * core_api
apis (our advertised API and the core api )
static char * email
static struct sigaction old_handler
Old handler for SIGPIPE (kept to be able to restore).
static struct GNUNET_Mutex * lock
Lock for uses of libesmtp (not thread-safe).
#define GNUNET_free(ptr)
Wrapper around free.

Variable Documentation

◆ core_api

GNUNET_NETWORK_STRUCT_END GNUNET_CoreAPIForTransport* core_api
static

apis (our advertised API and the core api )

Definition at line 98 of file plugin_transport_smtp.c.

Referenced by api_create_hello(), api_send(), donetransport_smtp(), inittransport_smtp(), and listenAndDistribute().

◆ ectx

struct GNUNET_GE_Context* ectx
static

◆ dispatchThread

struct GNUNET_ThreadHandle* dispatchThread
static

Thread that listens for inbound messages.

Definition at line 105 of file plugin_transport_smtp.c.

Referenced by api_start_transport_server(), and api_stop_transport_server().

◆ smtp_shutdown

int smtp_shutdown = GNUNET_YES
static

Flag to indicate that server has been shut down.

Definition at line 110 of file plugin_transport_smtp.c.

Referenced by api_send(), api_start_transport_server(), api_stop_transport_server(), and listenAndDistribute().

◆ smtp_server_name

char* smtp_server_name
static

Set to the SMTP server hostname (and port) for outgoing messages.

Definition at line 115 of file plugin_transport_smtp.c.

Referenced by api_send(), donetransport_smtp(), and inittransport_smtp().

◆ pipename

char* pipename
static

◆ lock

struct GNUNET_Mutex* lock
static

Lock for uses of libesmtp (not thread-safe).

Definition at line 122 of file plugin_transport_smtp.c.

Referenced by api_send(), donetransport_smtp(), and inittransport_smtp().

◆ old_handler

struct sigaction old_handler
static

Old handler for SIGPIPE (kept to be able to restore).

Definition at line 127 of file plugin_transport_smtp.c.

Referenced by donetransport_smtp(), and inittransport_smtp().

◆ email

char* email
static

◆ smtpAPI

GNUNET_TransportAPI smtpAPI
static

◆ stats

GNUNET_Stats_ServiceAPI* stats
static

◆ stat_bytesReceived

int stat_bytesReceived
static

Definition at line 135 of file plugin_transport_smtp.c.

Referenced by inittransport_smtp(), and listenAndDistribute().

◆ stat_bytesSent

int stat_bytesSent
static

Definition at line 137 of file plugin_transport_smtp.c.

Referenced by api_send(), and inittransport_smtp().

◆ stat_bytesDropped

int stat_bytesDropped
static

Definition at line 139 of file plugin_transport_smtp.c.

Referenced by inittransport_smtp().

◆ rate_limit

unsigned long long rate_limit
static

How many e-mails are we allowed to send per hour?

Definition at line 144 of file plugin_transport_smtp.c.

Referenced by api_send(), and inittransport_smtp().

◆ last_transmission

GNUNET_CronTime last_transmission
static

Definition at line 146 of file plugin_transport_smtp.c.

Referenced by api_send().