29 #include "gnunet_util.h"
32 #include "gnunet_transport.h"
33 #include "gnunet_stats_service.h"
41 #define SMTP_MESSAGE_SIZE 65528
43 #define DEBUG_SMTP GNUNET_EXTRA_LOGGING
45 #define FILTER_STRING_SIZE 64
49 #define MAX_CHAR_PER_LINE 76
70 char senderAddress[0];
97 static struct GNUNET_GE_Context *
ectx;
119 static struct GNUNET_Mutex *
lock;
130 static GNUNET_Stats_ServiceAPI *
stats;
148 #define strAUTOncmp(a, b) strncmp (a, b, strlen (b))
157 unsigned int linesize;
163 GNUNET_TransportPacket *coreMP;
171 #define READLINE(l, limit) \
172 do { retl = fgets (l, (limit), fdes); \
173 if ((retl == NULL) || (smtp_shutdown == GNUNET_YES)) { \
176 if (core_api->load_monitor != NULL) \
177 GNUNET_network_monitor_notify_transmission (core_api->load_monitor, \
178 GNUNET_ND_DOWNLOAD, \
185 fd = OPEN (
pipename, O_RDONLY | O_ASYNC);
189 GNUNET_thread_sleep (5 * GNUNET_CRON_SECONDS);
192 fdes = fdopen (fd,
"r");
200 while ((
line[0] !=
'\r') && (
line[0] !=
'\n'));
205 pos = strlen (
line) - 1;
207 if ((
line[pos] ==
'\r') || (
line[pos] ==
'\n'))
213 GNUNET_GE_BREAK (
ectx, 0);
222 GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER,
223 _ (
"Received malformed message via %s. Ignored.\n"),
227 GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
228 "Size returned by base64=%d, in the msg=%d.\n",
size,
239 coreMP->tsession = NULL;
240 coreMP->sender = mp->
sender;
242 GNUNET_GE_LOG (
ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
243 "SMTP message passed to the core.\n");
250 GNUNET_GE_LOG (
ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
251 "SMTP message processed.\n");
278 if ((ntohs (hello->header.size) !=
279 sizeof(GNUNET_MessageHello) + ntohs (hello->senderAddressSize)) ||
283 GNUNET_GE_BREAK (
ectx, 0);
286 if (NULL == strstr (maddr->
filter,
": "))
299 static GNUNET_MessageHello *
302 GNUNET_MessageHello *
msg;
307 GNUNET_GC_get_configuration_value_string (
core_api->cfg,
"SMTP",
"FILTER",
308 "X-mailer: GNUnet", &
filter);
309 if (NULL == strstr (
filter,
": "))
311 GNUNET_GE_LOG (
ectx, GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER,
312 _ (
"SMTP filter string to invalid, lacks ': '\n"));
320 GNUNET_GE_LOG (
ectx, GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER,
321 _ (
"SMTP filter string to long, capped to `%s'\n"),
filter);
323 i = (strlen (
email) + 8) & (~7);
326 memset (
msg, 0,
sizeof(GNUNET_MessageHello) +
sizeof(
EmailAddress) + i);
332 msg->protocol = htons (GNUNET_TRANSPORT_PROTOCOL_NUMBER_SMTP);
334 msg->header.
size = htons (GNUNET_sizeof_hello (
msg));
336 GNUNET_GE_ASSERT (
ectx, 0);
381 const GNUNET_MessageHello *hello;
388 smtp_session_t session;
389 smtp_message_t message;
390 smtp_recipient_t recipient;
400 GNUNET_GE_BREAK (
ectx, 0);
403 now = GNUNET_get_time ();
409 hello = (
const GNUNET_MessageHello *) tsession->internal;
412 GNUNET_mutex_lock (
lock);
413 session = smtp_create_session ();
417 GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_USER
418 | GNUNET_GE_IMMEDIATE,
_ (
"SMTP: `%s' failed: %s.\n"),
419 "smtp_create_session", smtp_strerror (smtp_errno (), ebuf,
421 GNUNET_mutex_unlock (
lock);
427 GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_USER
428 | GNUNET_GE_IMMEDIATE,
_ (
"SMTP: `%s' failed: %s.\n"),
429 "smtp_set_server", smtp_strerror (smtp_errno (), ebuf,
431 smtp_destroy_session (session);
432 GNUNET_mutex_unlock (
lock);
436 message = smtp_add_message (session);
440 GNUNET_GE_WARNING | GNUNET_GE_ADMIN | GNUNET_GE_USER
441 | GNUNET_GE_BULK,
_ (
"SMTP: `%s' failed: %s.\n"),
442 "smtp_add_message", smtp_strerror (smtp_errno (), ebuf,
444 smtp_destroy_session (session);
445 GNUNET_mutex_unlock (
lock);
449 smtp_set_header (message,
"From", NULL,
email);
452 fvalue = strstr (
filter,
": ");
453 GNUNET_GE_ASSERT (NULL, NULL != fvalue);
456 if (0 == smtp_set_header (message,
filter, fvalue))
459 GNUNET_GE_WARNING | GNUNET_GE_ADMIN | GNUNET_GE_USER
460 | GNUNET_GE_BULK,
_ (
"SMTP: `%s' failed: %s.\n"),
461 "smtp_set_header", smtp_strerror (smtp_errno (), ebuf,
463 smtp_destroy_session (session);
464 GNUNET_mutex_unlock (
lock);
480 if (0 == smtp_size_set_estimate (message, gm_cls.
esize))
483 GNUNET_GE_WARNING | GNUNET_GE_ADMIN | GNUNET_GE_USER
484 | GNUNET_GE_BULK,
_ (
"SMTP: `%s' failed: %s.\n"),
485 "smtp_size_set_estimate", smtp_strerror (smtp_errno (), ebuf,
488 if (0 == smtp_set_messagecb (message, &
get_message, &gm_cls))
491 GNUNET_GE_WARNING | GNUNET_GE_ADMIN | GNUNET_GE_USER
492 | GNUNET_GE_BULK,
_ (
"SMTP: `%s' failed: %s.\n"),
493 "smtp_set_messagecb", smtp_strerror (smtp_errno (), ebuf,
495 smtp_destroy_session (session);
496 GNUNET_mutex_unlock (
lock);
500 recipient = smtp_add_recipient (message, haddr->
senderAddress);
501 if (recipient == NULL)
504 GNUNET_GE_WARNING | GNUNET_GE_ADMIN | GNUNET_GE_USER
505 | GNUNET_GE_BULK,
_ (
"SMTP: `%s' failed: %s.\n"),
506 "smtp_add_recipient", smtp_strerror (smtp_errno (), ebuf,
508 smtp_destroy_session (session);
509 GNUNET_mutex_unlock (
lock);
512 if (0 == smtp_start_session (session))
515 GNUNET_GE_WARNING | GNUNET_GE_ADMIN | GNUNET_GE_USER
516 | GNUNET_GE_BULK,
_ (
"SMTP: `%s' failed: %s.\n"),
517 "smtp_start_session", smtp_strerror (smtp_errno (), ebuf,
519 smtp_destroy_session (session);
520 GNUNET_mutex_unlock (
lock);
527 GNUNET_network_monitor_notify_transmission (
core_api->load_monitor,
528 GNUNET_ND_UPLOAD, gm_cls.
esize);
529 smtp_message_reset_status (message);
530 smtp_destroy_session (session);
531 GNUNET_mutex_unlock (
lock);
545 api_connect (
const GNUNET_MessageHello *hello, GNUNET_TSession **tsessionPtr,
548 GNUNET_TSession *tsession;
551 tsession->internal =
GNUNET_malloc (GNUNET_sizeof_hello (hello));
552 tsession->peer = hello->senderIdentity;
553 GNUNET_memcpy (tsession->internal, hello, GNUNET_sizeof_hello (hello));
554 tsession->ttype =
smtpAPI.protocol_number;
555 (*tsessionPtr) = tsession;
569 if (tsession != NULL)
571 if (tsession->internal != NULL)
591 GNUNET_GE_DIE_STRERROR (
ectx,
592 GNUNET_GE_ADMIN | GNUNET_GE_BULK | GNUNET_GE_FATAL,
621 unsigned int *sa_len)
653 GNUNET_TransportAPI *
656 unsigned long long mtu;
661 if (! GNUNET_GC_have_configuration_value (
core_api->cfg,
"SMTP",
"EMAIL"))
663 GNUNET_GE_LOG (
ectx, GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
666 "No email-address specified, can not start SMTP transport.\n"));
669 GNUNET_GC_get_configuration_value_number (
core_api->cfg,
"SMTP",
"MTU", 1200,
672 GNUNET_GC_get_configuration_value_number (
core_api->cfg,
"SMTP",
"RATELIMIT",
683 GNUNET_GC_get_configuration_value_filename (
core_api->cfg,
"SMTP",
"PIPE",
686 if (0 != mkfifo (
pipename, S_IWUSR | S_IRUSR | S_IWGRP | S_IWOTH))
688 GNUNET_GE_LOG_STRERROR (
ectx,
689 GNUNET_GE_ADMIN | GNUNET_GE_BULK | GNUNET_GE_FATAL,
698 if (0 != chmod (
pipename, S_IWUSR | S_IRUSR | S_IWGRP | S_IWOTH))
699 GNUNET_GE_LOG_STRERROR (
ectx,
700 GNUNET_GE_ADMIN | GNUNET_GE_BULK
701 | GNUNET_GE_WARNING,
"chmod");
702 GNUNET_GC_get_configuration_value_string (
core_api->cfg,
"SMTP",
"EMAIL",
706 GNUNET_GC_get_configuration_value_string (
core_api->cfg,
"SMTP",
"SERVER",
708 sa.sa_handler = SIG_IGN;
709 sigemptyset (&sa.sa_mask);
713 smtpAPI.protocol_number = GNUNET_TRANSPORT_PROTOCOL_NUMBER_SMTP;
740 GNUNET_mutex_destroy (
lock);
struct GNUNET_MessageHeader * msg
#define gettext_noop(String)
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
static char * line
Desired phone line (string to be converted to a hash).
@ END
We're done processing.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
static struct GNUNET_CORE_Handle * core
Handle to the CORE service.
static struct GNUNET_CONTAINER_BloomFilter * filter
Bloomfilter to quickly tell if we don't have the content.
Constants for network protocols.
#define GNUNET_NETWORK_STRUCT_BEGIN
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32.
#define GNUNET_NETWORK_STRUCT_END
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32;.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
size_t GNUNET_STRINGS_base64_decode(const char *data, size_t len, void **output)
Decode from Base64.
size_t GNUNET_STRINGS_base64_encode(const void *in, size_t len, char **output)
Encode into Base64.
static unsigned int size
Size of the "table".
static unsigned long long rate_limit
How many e-mails are we allowed to send per hour?
static int api_associate(GNUNET_TSession *tsession)
Always fails.
static struct sigaction old_handler
Old handler for SIGPIPE (kept to be able to restore).
static int api_disconnect(GNUNET_TSession *tsession)
Disconnect from a remote node.
static char * smtp_server_name
Set to the SMTP server hostname (and port) for outgoing messages.
static int api_connect(const GNUNET_MessageHello *hello, GNUNET_TSession **tsessionPtr, int may_reuse)
Establish a connection to a remote node.
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 stat_bytesReceived
static struct GNUNET_Mutex * lock
Lock for uses of libesmtp (not thread-safe).
static void * listenAndDistribute(void *unused)
Listen to the pipe, decode messages and send to core.
static GNUNET_NETWORK_STRUCT_END GNUNET_CoreAPIForTransport * core_api
apis (our advertised API and the core api )
#define READLINE(l, limit)
GNUNET_TransportAPI * inittransport_smtp(struct GNUNET_CoreAPIForTransport *core)
The exported method.
static GNUNET_TransportAPI smtpAPI
static const char * get_message(void **buf, int *len, void *cls)
void donetransport_smtp()
static int smtp_shutdown
Flag to indicate that server has been shut down.
static GNUNET_Stats_ServiceAPI * stats
static int api_send(GNUNET_TSession *tsession, const void *msg, const unsigned int size, int important)
Send a message to the specified remote node.
static int api_stop_transport_server()
Shutdown the server process (stop receiving inbound traffic).
static int api_start_transport_server()
Start the server process to receive inbound traffic.
static GNUNET_CronTime last_transmission
#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).
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).
#define MAX_CHAR_PER_LINE
static struct GNUNET_GE_Context * ectx
static struct GNUNET_ThreadHandle * dispatchThread
Thread that listens for inbound messages.
static GNUNET_MessageHello * api_create_hello()
Create a hello-Message for the current node.
static int stat_bytesDropped
static int stat_bytesSent
#define SMTP_MESSAGE_SIZE
The default maximum size of each outbound SMTP message.
Host-Address in a SMTP network.
char senderAddress[0]
Claimed E-mail address of the sender.
char filter[64]
Filter line that every sender must include in the E-mails such that the receiver can effectively filt...
The identity of the host (wraps the signing key of the peer).
Encapsulation of a GNUnet message in the SMTP mail body (before base64 encoding).
GNUNET_MessageHeader header
GNUNET_PeerIdentity sender
What is the identity of the sender (GNUNET_hash of public key)