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 146 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:77

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 152 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, pipename, READLINE, SMTPMessage::sender, size, GNUNET_MessageHeader::size, smtp_shutdown, stat_bytesReceived, and stats.

Referenced by api_start_transport_server().

153 {
154  char *line;
155  unsigned int linesize;
156  SMTPMessage *mp;
157  FILE *fdes;
158  char *retl;
159  char *out;
160  unsigned int size;
161  GNUNET_TransportPacket *coreMP;
162  int fd;
163  unsigned int pos;
164 
165  linesize = ((GNUNET_MAX_BUFFER_SIZE * 4 / 3) + 8) * (MAX_CHAR_PER_LINE + 2) / MAX_CHAR_PER_LINE; /* maximum size of a line supported */
166  line = GNUNET_malloc(linesize + 2); /* 2 bytes for off-by-one errors, just to be safe... */
167 
168 #define READLINE(l, limit) \
169  do { retl = fgets(l, (limit), fdes); \
170  if ((retl == NULL) || (smtp_shutdown == GNUNET_YES)) { \
171  goto END; \
172  } \
173  if (core_api->load_monitor != NULL) \
174  GNUNET_network_monitor_notify_transmission (core_api->load_monitor, GNUNET_ND_DOWNLOAD, strlen(retl)); \
175  } while (0)
176 
177 
178  while (smtp_shutdown == GNUNET_NO)
179  {
180  fd = OPEN(pipename, O_RDONLY | O_ASYNC);
181  if (fd == -1)
182  {
183  if (smtp_shutdown == GNUNET_NO)
184  GNUNET_thread_sleep(5 * GNUNET_CRON_SECONDS);
185  continue;
186  }
187  fdes = fdopen(fd, "r");
188  while (smtp_shutdown == GNUNET_NO)
189  {
190  /* skip until end of header */
191  do
192  {
193  READLINE(line, linesize);
194  }
195  while ((line[0] != '\r') && (line[0] != '\n')); /* expect newline */
196  READLINE(line, linesize); /* read base64 encoded message; decode, process */
197  pos = 0;
198  while (1)
199  {
200  pos = strlen(line) - 1; /* ignore new line */
201  READLINE(&line[pos], linesize - pos); /* read base64 encoded message; decode, process */
202  if ((line[pos] == '\r') || (line[pos] == '\n'))
203  break; /* empty line => end of message! */
204  }
205  size = GNUNET_STRINGS_base64_decode(line, pos, &out);
206  if (size < sizeof(SMTPMessage))
207  {
208  GNUNET_GE_BREAK(ectx, 0);
209  GNUNET_free(out);
210  goto END;
211  }
212 
213  mp = (SMTPMessage *)&out[size - sizeof(SMTPMessage)];
214  if (ntohs(mp->header.size) != size)
215  {
216  GNUNET_GE_LOG(ectx,
217  GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER,
218  _("Received malformed message via %s. Ignored.\n"),
219  "SMTP");
220 #if DEBUG_SMTP
221  GNUNET_GE_LOG(ectx,
222  GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
223  "Size returned by base64=%d, in the msg=%d.\n", size,
224  ntohl(mp->size));
225 #endif
226  GNUNET_free(out);
227  goto END;
228  }
229  if (stats != NULL)
230  stats->change(stat_bytesReceived, size);
231  coreMP = GNUNET_new(GNUNET_TransportPacket);
232  coreMP->msg = out;
233  coreMP->size = size - sizeof(SMTPMessage);
234  coreMP->tsession = NULL;
235  coreMP->sender = mp->sender;
236 #if DEBUG_SMTP
237  GNUNET_GE_LOG(ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
238  "SMTP message passed to the core.\n");
239 #endif
240 
241  core_api->receive(coreMP);
242  }
243 END:
244 #if DEBUG_SMTP
245  GNUNET_GE_LOG(ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
246  "SMTP message processed.\n");
247 #endif
248  if (fdes != NULL)
249  fclose(fdes);
250  }
251  GNUNET_free(line);
252  return NULL;
253 }
static char * pipename
static GNUNET_Stats_ServiceAPI * stats
We&#39;re done processing.
#define GNUNET_NO
Definition: gnunet_common.h:78
#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:181
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:1920
static unsigned int size
Size of the "table".
Definition: peer.c:66
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 267 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().

268 {
269  const EmailAddress *maddr;
270 
271  maddr = (const EmailAddress *)&hello[1];
272  if ((ntohs(hello->header.size) !=
273  sizeof(GNUNET_MessageHello) + ntohs(hello->senderAddressSize)) ||
274  (maddr->senderAddress
275  [ntohs(hello->senderAddressSize) - 1 - FILTER_STRING_SIZE] != '\0'))
276  {
277  GNUNET_GE_BREAK(ectx, 0);
278  return GNUNET_SYSERR; /* obviously invalid */
279  }
280  if (NULL == strstr(maddr->filter, ": "))
281  return GNUNET_SYSERR;
282  return GNUNET_OK;
283 }
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:75
static struct GNUNET_GE_Context * ectx
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
#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 293 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().

294 {
295  GNUNET_MessageHello *msg;
296  char *filter;
297  EmailAddress *haddr;
298  int i;
299 
300  GNUNET_GC_get_configuration_value_string(core_api->cfg, "SMTP", "FILTER",
301  "X-mailer: GNUnet", &filter);
302  if (NULL == strstr(filter, ": "))
303  {
304  GNUNET_GE_LOG(ectx, GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER,
305  _("SMTP filter string to invalid, lacks ': '\n"));
306  GNUNET_free(filter);
307  return NULL;
308  }
309 
310  if (strlen(filter) > FILTER_STRING_SIZE)
311  {
312  filter[FILTER_STRING_SIZE] = '\0';
313  GNUNET_GE_LOG(ectx, GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER,
314  _("SMTP filter string to long, capped to `%s'\n"), filter);
315  }
316  i = (strlen(email) + 8) & (~7); /* make multiple of 8 */
317  msg =
318  GNUNET_malloc(sizeof(GNUNET_MessageHello) + sizeof(EmailAddress) + i);
319  memset(msg, 0, sizeof(GNUNET_MessageHello) + sizeof(EmailAddress) + i);
320  haddr = (EmailAddress *)&msg[1];
321  memset(&haddr->filter[0], 0, FILTER_STRING_SIZE);
322  strcpy(&haddr->filter[0], filter);
323  GNUNET_memcpy(&haddr->senderAddress[0], email, strlen(email) + 1);
324  msg->senderAddressSize = htons(strlen(email) + 1 + sizeof(EmailAddress));
325  msg->protocol = htons(GNUNET_TRANSPORT_PROTOCOL_NUMBER_SMTP);
326  msg->MTU = htonl(smtpAPI.mtu);
327  msg->header.size = htons(GNUNET_sizeof_hello(msg));
328  if (api_verify_hello(msg) == GNUNET_SYSERR)
329  GNUNET_GE_ASSERT(ectx, 0);
330  GNUNET_free(filter);
331  return msg;
332 }
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 GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
static GNUNET_NETWORK_STRUCT_END GNUNET_CoreAPIForTransport * core_api
apis (our advertised API and the core api )
static GNUNET_TransportAPI smtpAPI
static char * email
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:76
#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 341 of file plugin_transport_smtp.c.

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

Referenced by api_send().

342 {
343  struct GetMessageClosure *gmc = cls;
344 
345  *buf = NULL;
346  if (len == NULL)
347  {
348  gmc->pos = 0;
349  return NULL;
350  }
351  if (gmc->pos == gmc->esize)
352  return NULL; /* done */
353  *len = gmc->esize;
354  gmc->pos = gmc->esize;
355  return gmc->ebody;
356 }
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 368 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().

370 {
371  const GNUNET_MessageHello *hello;
372  const EmailAddress *haddr;
373  char *m;
374  char *filter;
375  char *fvalue;
376  SMTPMessage *mp;
377  struct GetMessageClosure gm_cls;
378  smtp_session_t session;
379  smtp_message_t message;
380  smtp_recipient_t recipient;
381 
382 #define EBUF_LEN 128
383  char ebuf[EBUF_LEN];
384  GNUNET_CronTime now;
385 
386  if (smtp_shutdown == GNUNET_YES)
387  return GNUNET_SYSERR;
388  if ((size == 0) || (size > smtpAPI.mtu))
389  {
390  GNUNET_GE_BREAK(ectx, 0);
391  return GNUNET_SYSERR;
392  }
393  now = GNUNET_get_time();
394  if ((important != GNUNET_YES) &&
395  ((now - last_transmission) * rate_limit) < GNUNET_CRON_HOURS)
396  return GNUNET_NO; /* rate too high */
397  last_transmission = now;
398 
399  hello = (const GNUNET_MessageHello *)tsession->internal;
400  if (hello == NULL)
401  return GNUNET_SYSERR;
402  GNUNET_mutex_lock(lock);
403  session = smtp_create_session();
404  if (session == NULL)
405  {
406  GNUNET_GE_LOG(ectx,
407  GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_USER |
408  GNUNET_GE_IMMEDIATE, _("SMTP: `%s' failed: %s.\n"),
409  "smtp_create_session", smtp_strerror(smtp_errno(), ebuf,
410  EBUF_LEN));
411  GNUNET_mutex_unlock(lock);
412  return GNUNET_SYSERR;
413  }
414  if (0 == smtp_set_server(session, smtp_server_name))
415  {
416  GNUNET_GE_LOG(ectx,
417  GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_USER |
418  GNUNET_GE_IMMEDIATE, _("SMTP: `%s' failed: %s.\n"),
419  "smtp_set_server", smtp_strerror(smtp_errno(), ebuf,
420  EBUF_LEN));
421  smtp_destroy_session(session);
422  GNUNET_mutex_unlock(lock);
423  return GNUNET_SYSERR;
424  }
425  haddr = (const EmailAddress *)&hello[1];
426  message = smtp_add_message(session);
427  if (message == NULL)
428  {
429  GNUNET_GE_LOG(ectx,
430  GNUNET_GE_WARNING | GNUNET_GE_ADMIN | GNUNET_GE_USER |
431  GNUNET_GE_BULK, _("SMTP: `%s' failed: %s.\n"),
432  "smtp_add_message", smtp_strerror(smtp_errno(), ebuf,
433  EBUF_LEN));
434  smtp_destroy_session(session);
435  GNUNET_mutex_unlock(lock);
436  return GNUNET_SYSERR;
437  }
438  smtp_set_header(message, "To", NULL, haddr->senderAddress);
439  smtp_set_header(message, "From", NULL, email);
440 
441  filter = GNUNET_strdup(haddr->filter);
442  fvalue = strstr(filter, ": ");
443  GNUNET_GE_ASSERT(NULL, NULL != fvalue);
444  fvalue[0] = '\0';
445  fvalue += 2;
446  if (0 == smtp_set_header(message, filter, fvalue))
447  {
448  GNUNET_GE_LOG(ectx,
449  GNUNET_GE_WARNING | GNUNET_GE_ADMIN | GNUNET_GE_USER |
450  GNUNET_GE_BULK, _("SMTP: `%s' failed: %s.\n"),
451  "smtp_set_header", smtp_strerror(smtp_errno(), ebuf,
452  EBUF_LEN));
453  smtp_destroy_session(session);
454  GNUNET_mutex_unlock(lock);
455  GNUNET_free(filter);
456  return GNUNET_SYSERR;
457  }
458  GNUNET_free(filter);
459  m = GNUNET_malloc(size + sizeof(SMTPMessage));
460  GNUNET_memcpy(m, msg, size);
461  mp = (SMTPMessage *)&m[size];
462  mp->header.size = htons(size + sizeof(SMTPMessage));
463  mp->header.type = htons(0);
464  mp->sender = *core_api->my_identity;
465  gm_cls.ebody = NULL;
466  gm_cls.pos = 0;
467  gm_cls.esize = GNUNET_STRINGS_base64_encode(m, size + sizeof(SMTPMessage), &gm_cls.ebody);
468  GNUNET_free(m);
469  if (0 == smtp_size_set_estimate(message, gm_cls.esize))
470  {
471  GNUNET_GE_LOG(ectx,
472  GNUNET_GE_WARNING | GNUNET_GE_ADMIN | GNUNET_GE_USER |
473  GNUNET_GE_BULK, _("SMTP: `%s' failed: %s.\n"),
474  "smtp_size_set_estimate", smtp_strerror(smtp_errno(), ebuf,
475  EBUF_LEN));
476  }
477  if (0 == smtp_set_messagecb(message, &get_message, &gm_cls))
478  {
479  GNUNET_GE_LOG(ectx,
480  GNUNET_GE_WARNING | GNUNET_GE_ADMIN | GNUNET_GE_USER |
481  GNUNET_GE_BULK, _("SMTP: `%s' failed: %s.\n"),
482  "smtp_set_messagecb", smtp_strerror(smtp_errno(), ebuf,
483  EBUF_LEN));
484  smtp_destroy_session(session);
485  GNUNET_mutex_unlock(lock);
486  GNUNET_free(gm_cls.ebody);
487  return GNUNET_SYSERR;
488  }
489  recipient = smtp_add_recipient(message, haddr->senderAddress);
490  if (recipient == NULL)
491  {
492  GNUNET_GE_LOG(ectx,
493  GNUNET_GE_WARNING | GNUNET_GE_ADMIN | GNUNET_GE_USER |
494  GNUNET_GE_BULK, _("SMTP: `%s' failed: %s.\n"),
495  "smtp_add_recipient", smtp_strerror(smtp_errno(), ebuf,
496  EBUF_LEN));
497  smtp_destroy_session(session);
498  GNUNET_mutex_unlock(lock);
499  return GNUNET_SYSERR;
500  }
501  if (0 == smtp_start_session(session))
502  {
503  GNUNET_GE_LOG(ectx,
504  GNUNET_GE_WARNING | GNUNET_GE_ADMIN | GNUNET_GE_USER |
505  GNUNET_GE_BULK, _("SMTP: `%s' failed: %s.\n"),
506  "smtp_start_session", smtp_strerror(smtp_errno(), ebuf,
507  EBUF_LEN));
508  smtp_destroy_session(session);
509  GNUNET_mutex_unlock(lock);
510  GNUNET_free(gm_cls.ebody);
511  return GNUNET_SYSERR;
512  }
513  if (stats != NULL)
514  stats->change(stat_bytesSent, size);
515  if (core_api->load_monitor != NULL)
516  GNUNET_network_monitor_notify_transmission(core_api->load_monitor,
517  GNUNET_ND_UPLOAD, gm_cls.esize);
518  smtp_message_reset_status(message); /* this is needed to plug a 28-byte/message memory leak in libesmtp */
519  smtp_destroy_session(session);
520  GNUNET_mutex_unlock(lock);
521  GNUNET_free(gm_cls.ebody);
522  return GNUNET_OK;
523 }
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_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
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:181
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.
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:1856
#define EBUF_LEN
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
static const char * get_message(void **buf, int *len, void *cls)
static unsigned int size
Size of the "table".
Definition: peer.c:66
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:77
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 533 of file plugin_transport_smtp.c.

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

Referenced by inittransport_smtp().

535 {
536  GNUNET_TSession *tsession;
537 
538  tsession = GNUNET_new(GNUNET_TSession);
539  tsession->internal = GNUNET_malloc(GNUNET_sizeof_hello(hello));
540  tsession->peer = hello->senderIdentity;
541  GNUNET_memcpy(tsession->internal, hello, GNUNET_sizeof_hello(hello));
542  tsession->ttype = smtpAPI.protocol_number;
543  (*tsessionPtr) = tsession;
544  return GNUNET_OK;
545 }
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_new(type)
Allocate a struct or union of the given type.
static GNUNET_TransportAPI smtpAPI
#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 554 of file plugin_transport_smtp.c.

References GNUNET_free, and GNUNET_OK.

Referenced by inittransport_smtp().

555 {
556  if (tsession != NULL)
557  {
558  if (tsession->internal != NULL)
559  GNUNET_free(tsession->internal);
560  GNUNET_free(tsession);
561  }
562  return GNUNET_OK;
563 }
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#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 570 of file plugin_transport_smtp.c.

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

Referenced by inittransport_smtp().

571 {
573  /* initialize SMTP network */
574  dispatchThread = GNUNET_thread_create(&listenAndDistribute, NULL, 1024 * 4);
575  if (dispatchThread == NULL)
576  {
577  GNUNET_GE_DIE_STRERROR(ectx,
578  GNUNET_GE_ADMIN | GNUNET_GE_BULK | GNUNET_GE_FATAL,
579  "pthread_create");
580  return GNUNET_SYSERR;
581  }
582  return GNUNET_OK;
583 }
static void * listenAndDistribute(void *unused)
Listen to the pipe, decode messages and send to core.
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
static struct GNUNET_GE_Context * ectx
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
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 590 of file plugin_transport_smtp.c.

References dispatchThread, GNUNET_OK, GNUNET_YES, and smtp_shutdown.

Referenced by inittransport_smtp().

591 {
592  void *unused;
593 
595  GNUNET_thread_stop_sleep(dispatchThread);
596  GNUNET_thread_join(dispatchThread, &unused);
597  return GNUNET_OK;
598 }
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
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:77
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 604 of file plugin_transport_smtp.c.

References GNUNET_SYSERR.

Referenced by inittransport_smtp().

606 {
607  return GNUNET_SYSERR;
608 }
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
Here is the caller graph for this function:

◆ api_associate()

static int api_associate ( GNUNET_TSession *  tsession)
static

Always fails.

Definition at line 614 of file plugin_transport_smtp.c.

References GNUNET_SYSERR.

Referenced by inittransport_smtp().

615 {
616  return GNUNET_SYSERR; /* SMTP connections can never be associated */
617 }
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
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 624 of file plugin_transport_smtp.c.

References GNUNET_OK.

Referenced by inittransport_smtp().

626 {
627  return GNUNET_OK; /* we always try... */
628 }
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
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 635 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, and stats.

636 {
637  unsigned long long mtu;
638  struct sigaction sa;
639 
640  core_api = core;
641  ectx = core->ectx;
642  if (!GNUNET_GC_have_configuration_value(core_api->cfg, "SMTP", "EMAIL"))
643  {
644  GNUNET_GE_LOG(ectx, GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
645  _
646  ("No email-address specified, can not start SMTP transport.\n"));
647  return NULL;
648  }
649  GNUNET_GC_get_configuration_value_number(core_api->cfg, "SMTP", "MTU", 1200,
651  SMTP_MESSAGE_SIZE, &mtu);
652  GNUNET_GC_get_configuration_value_number(core_api->cfg, "SMTP", "RATELIMIT",
653  0, 0, 1024 * 1024, &rate_limit);
654  stats = core_api->service_request("stats");
655  if (stats != NULL)
656  {
658  stats->create(gettext_noop("# bytes received via SMTP"));
659  stat_bytesSent = stats->create(gettext_noop("# bytes sent via SMTP"));
661  stats->create(gettext_noop("# bytes dropped by SMTP (outgoing)"));
662  }
663  GNUNET_GC_get_configuration_value_filename(core_api->cfg, "SMTP", "PIPE", &pipename);
664  unlink(pipename);
665  if (0 != mkfifo(pipename, S_IWUSR | S_IRUSR | S_IWGRP | S_IWOTH))
666  {
667  GNUNET_GE_LOG_STRERROR(ectx,
668  GNUNET_GE_ADMIN | GNUNET_GE_BULK | GNUNET_GE_FATAL,
669  "mkfifo");
671  core_api->service_release(stats);
672  stats = NULL;
673  return NULL;
674  }
675  /* we need to allow the mailer program to send us messages;
676  * easiest done by giving it write permissions (see Mantis #1142) */
677  if (0 != chmod(pipename, S_IWUSR | S_IRUSR | S_IWGRP | S_IWOTH))
678  GNUNET_GE_LOG_STRERROR(ectx,
679  GNUNET_GE_ADMIN | GNUNET_GE_BULK |
680  GNUNET_GE_WARNING, "chmod");
681  GNUNET_GC_get_configuration_value_string(core_api->cfg, "SMTP", "EMAIL", NULL,
682  &email);
683  lock = GNUNET_mutex_create(GNUNET_NO);
684  GNUNET_GC_get_configuration_value_string(core_api->cfg, "SMTP", "SERVER",
685  "localhost:25", &smtp_server_name);
686  sa.sa_handler = SIG_IGN;
687  sigemptyset(&sa.sa_mask);
688  sa.sa_flags = 0;
689  sigaction(SIGPIPE, &sa, &old_handler);
690 
691  smtpAPI.protocol_number = GNUNET_TRANSPORT_PROTOCOL_NUMBER_SMTP;
692  smtpAPI.mtu = mtu - sizeof(SMTPMessage);
693  smtpAPI.cost = 50;
694  smtpAPI.hello_verify = &api_verify_hello;
695  smtpAPI.hello_create = &api_create_hello;
696  smtpAPI.connect = &api_connect;
697  smtpAPI.send = &api_send;
698  smtpAPI.associate = &api_associate;
699  smtpAPI.disconnect = &api_disconnect;
700  smtpAPI.server_start = &api_start_transport_server;
701  smtpAPI.server_stop = &api_stop_transport_server;
702  smtpAPI.hello_to_address = &api_hello_to_address;
703  smtpAPI.send_now_test = &api_test_would_try;
704  return &smtpAPI;
705 }
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:78
static int api_disconnect(GNUNET_TSession *tsession)
Disconnect from a remote node.
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
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 708 of file plugin_transport_smtp.c.

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

709 {
710  sigaction(SIGPIPE, &old_handler, NULL);
712  if (stats != NULL)
713  {
714  core_api->service_release(stats);
715  stats = NULL;
716  }
717  GNUNET_mutex_destroy(lock);
718  lock = NULL;
719  unlink(pipename);
721  pipename = NULL;
723  email = NULL;
724 }
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 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 93 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 100 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 105 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 110 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 117 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 122 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 130 of file plugin_transport_smtp.c.

Referenced by inittransport_smtp(), and listenAndDistribute().

◆ stat_bytesSent

int stat_bytesSent
static

Definition at line 132 of file plugin_transport_smtp.c.

Referenced by api_send(), and inittransport_smtp().

◆ stat_bytesDropped

int stat_bytesDropped
static

Definition at line 134 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 139 of file plugin_transport_smtp.c.

Referenced by api_send(), and inittransport_smtp().

◆ last_transmission

GNUNET_CronTime last_transmission
static

Definition at line 141 of file plugin_transport_smtp.c.

Referenced by api_send().