1 #include <stdlib.h>
2 #include <string.h>
3 #include <unistd.h>
4
5 #include <bglibs/systime.h>
6 #include <bglibs/iobuf.h>
7 #include <bglibs/msg.h>
8 #include <bglibs/str.h>
9
10 #include "mailfront.h"
11 #include "qmtp.h"
12
13 static const response* resp;
14
15 static char buf[8192];
16 static str line;
17
18 static void die(const char* msg) __NORETURN__;
die(const char * msg)19 static void die(const char* msg)
20 {
21 response r = { 451, msg };
22 respond(&r);
23 exit(111);
24 }
25
get_wrapper(ibuf * in)26 static void get_wrapper(ibuf* in)
27 {
28 unsigned long wraplen;
29 switch (get_netstring_len(in, &wraplen)) {
30 case -1: exit(0);
31 case 0: die("Invalid wrapper netstring");
32 }
33 }
34
get_body(ibuf * in)35 static void get_body(ibuf* in)
36 {
37 unsigned long bodylen;
38 char nl;
39 switch (get_netstring_len(in, &bodylen)) {
40 case -1: exit(0);
41 case 0: die("Invalid message body netstring");
42 }
43 if (bodylen == 0) die("Zero length message");
44 if (response_ok(resp))
45 resp = handle_data_start();
46 while (bodylen > 0) {
47 unsigned long len = sizeof buf;
48 if (len > bodylen) len = bodylen;
49 if (!ibuf_read(in, buf, len) && in->count == 0)
50 die("EOF while reading body");
51 if (response_ok(resp))
52 handle_data_bytes(buf, in->count);
53 bodylen -= in->count;
54 }
55 if (!ibuf_getc(in, &nl)) die("EOF while reading comma");
56 if (nl != ',') die("Invalid netstring terminator");
57 }
58
get_sender(ibuf * in)59 static void get_sender(ibuf* in)
60 {
61 switch (get_netstring(in, &line)) {
62 case -1: die("EOF while reading sender address");
63 case 0: die("Invalid sender netstring");
64 }
65 msg3("sender <", line.s, ">");
66 if (response_ok(resp))
67 resp = handle_sender(&line, 0);
68 }
69
get_recips(ibuf * in)70 static void get_recips(ibuf* in)
71 {
72 char ch;
73 while (ibuf_peek(in, &ch)) {
74 if (ch == ',') return;
75 switch (get_netstring(in, &line)) {
76 case -1: die("EOF while reading recipient list");
77 case 0: die("Invalid recipient netstring");
78 }
79 msg3("recipient <", line.s, ">");
80 if (response_ok(resp))
81 resp = handle_recipient(&line, 0);
82 }
83 die("EOF before end of recipient list");
84 }
85
get_package(ibuf * in)86 static void get_package(ibuf* in)
87 {
88 resp = handle_reset();
89 get_wrapper(in);
90 get_body(in);
91 get_sender(in);
92 get_recips(in);
93 if (response_ok(resp))
94 resp = handle_message_end();
95 if (!resp) resp = &resp_accepted_message;
96 if (!respond(resp)) die("EOF while sending response");
97 }
98
mainloop(const struct command * commands)99 static int mainloop(const struct command* commands)
100 {
101 alarm(3600);
102 get_package(&inbuf);
103 return 0;
104 (void)commands;
105 }
106
107 struct protocol protocol = {
108 .version = PROTOCOL_VERSION,
109 .name = "QMQP",
110 .respond_line = qmtp_respond_line,
111 .mainloop = mainloop,
112 };
113