milter 2.0.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +593 -121
- package/dist/constants.cjs +105 -0
- package/dist/constants.cjs.map +1 -0
- package/dist/constants.d.cts +63 -0
- package/dist/constants.d.ts +63 -0
- package/dist/constants.js +73 -0
- package/dist/constants.js.map +1 -0
- package/dist/index.cjs +976 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +187 -0
- package/dist/index.d.ts +187 -0
- package/dist/index.js +914 -0
- package/dist/index.js.map +1 -0
- package/package.json +116 -22
- package/res/maail-logo.svg +11 -0
- package/res/milterjs-logo.svg +79 -0
- package/.npmignore +0 -7
- package/binding.gyp +0 -13
- package/lib/milter.js +0 -1
- package/src/envelope.cc +0 -602
- package/src/envelope.h +0 -94
- package/src/events.cc +0 -429
- package/src/events.h +0 -303
- package/src/forward.h +0 -10
- package/src/milter.cc +0 -732
- package/src/milter.h +0 -76
package/src/milter.cc
DELETED
|
@@ -1,732 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* node bindings for milter
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
#include <string.h>
|
|
6
|
-
#include <node/uv.h>
|
|
7
|
-
#include <node.h>
|
|
8
|
-
#include <v8.h>
|
|
9
|
-
#include <arpa/inet.h>
|
|
10
|
-
#include "libmilter/mfapi.h"
|
|
11
|
-
#include "forward.h"
|
|
12
|
-
#include "events.h"
|
|
13
|
-
#include "envelope.h"
|
|
14
|
-
|
|
15
|
-
using namespace v8;
|
|
16
|
-
using namespace node;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
/** globals *******************************************************************/
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* the name the milter registers with to the MTA.
|
|
24
|
-
*/
|
|
25
|
-
static const char *g_name = "node-bindings";
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* the libmilter implementation and other application globals.
|
|
30
|
-
*/
|
|
31
|
-
bindings_t app;
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
/** demultiplexer *************************************************************/
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* all queued events reach node.js from this point; this task is queued on the
|
|
39
|
-
* libuv side, in a loop, via uv_async_send
|
|
40
|
-
*/
|
|
41
|
-
void trigger_event (uv_async_t *h)
|
|
42
|
-
{
|
|
43
|
-
bindings *local = (bindings *)h->data;
|
|
44
|
-
Isolate *isolate = Isolate::GetCurrent();
|
|
45
|
-
Locker locker (isolate);
|
|
46
|
-
HandleScope scope (isolate);
|
|
47
|
-
MilterEvent *ev;
|
|
48
|
-
|
|
49
|
-
#ifdef DEBUG_ASYNC
|
|
50
|
-
fprintf(stderr, "trigger_event: begin scope\n");
|
|
51
|
-
#endif
|
|
52
|
-
|
|
53
|
-
// grab the queue lock
|
|
54
|
-
if (pthread_mutex_lock(&local->lck_queue))
|
|
55
|
-
{
|
|
56
|
-
fprintf(stderr, "trigger_event: queue lock failed\n");
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// dequeue one event
|
|
61
|
-
ev = local->first;
|
|
62
|
-
if (NULL == ev)
|
|
63
|
-
{
|
|
64
|
-
pthread_mutex_unlock(&local->lck_queue);
|
|
65
|
-
fprintf(stderr, "trigger_event: spurious wakeup\n");
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
local->first = ev->Next();
|
|
69
|
-
if (NULL == local->first)
|
|
70
|
-
local->last = NULL;
|
|
71
|
-
ev->Detatch();
|
|
72
|
-
|
|
73
|
-
if (!ev->Lock())
|
|
74
|
-
{
|
|
75
|
-
fprintf(stderr, "trigger_event: event lock failed\n");
|
|
76
|
-
|
|
77
|
-
if (pthread_mutex_unlock(&local->lck_queue))
|
|
78
|
-
{
|
|
79
|
-
fprintf(stderr, "trigger_event: queue unlocked failed\n");
|
|
80
|
-
}
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// XXX: for top speed, move queue unlock to this point (with or without event lock success)
|
|
85
|
-
if (pthread_mutex_unlock(&local->lck_queue))
|
|
86
|
-
{
|
|
87
|
-
fprintf(stderr, "trigger_event: queue unlock failed\n");
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// launch the appropriate node.js callback for the given event
|
|
91
|
-
ev->Fire(isolate, local);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
/** multiplexer ***************************************************************/
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* queue an event from the libmilter side.
|
|
100
|
-
*/
|
|
101
|
-
int generate_event (SMFICTX *context, bindings_t *local, MilterEvent *event)
|
|
102
|
-
{
|
|
103
|
-
int retval;
|
|
104
|
-
|
|
105
|
-
// lock the queue
|
|
106
|
-
if (pthread_mutex_lock(&local->lck_queue))
|
|
107
|
-
{
|
|
108
|
-
fprintf(stderr, "generate_event: queue lock failed\n");
|
|
109
|
-
return SMFIS_TEMPFAIL;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// lock the event
|
|
113
|
-
if (!event->Lock())
|
|
114
|
-
{
|
|
115
|
-
if (pthread_mutex_unlock(&local->lck_queue))
|
|
116
|
-
{
|
|
117
|
-
fprintf(stderr, "generate_event: queue unlock failed\n");
|
|
118
|
-
// TODO: handle error?
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
fprintf(stderr, "generate_event: event lock failed\n");
|
|
122
|
-
return SMFIS_TEMPFAIL;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// enqueue the event while holding both locks
|
|
126
|
-
if (NULL == local->last)
|
|
127
|
-
{
|
|
128
|
-
local->first = event;
|
|
129
|
-
local->last = event;
|
|
130
|
-
}
|
|
131
|
-
else
|
|
132
|
-
{
|
|
133
|
-
local->last->Append(event);
|
|
134
|
-
local->last = event;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// unlock the queue to allow other libmilter threads to append events to it
|
|
138
|
-
if (pthread_mutex_unlock(&local->lck_queue))
|
|
139
|
-
{
|
|
140
|
-
// TODO: handle error?
|
|
141
|
-
fprintf(stderr, "generate_event: queue unlock failed\n");
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// give the event control of the libmilter context
|
|
145
|
-
event->SetMilterContext(context);
|
|
146
|
-
|
|
147
|
-
for (;;)
|
|
148
|
-
{
|
|
149
|
-
// let the node loop know we await a result
|
|
150
|
-
#ifdef DEBUG_ASYNC
|
|
151
|
-
fprintf(stderr, "generated_event: uv_async_send\n");
|
|
152
|
-
#endif
|
|
153
|
-
uv_async_send(&local->trigger);
|
|
154
|
-
|
|
155
|
-
// wait on the event's return condition
|
|
156
|
-
event->Wait();
|
|
157
|
-
#ifdef DEBUG_ASYNC
|
|
158
|
-
fprintf(stderr, "generate_event: wakeup!\n");
|
|
159
|
-
#endif
|
|
160
|
-
// TODO: check error condition
|
|
161
|
-
if (event->IsDone()) break;
|
|
162
|
-
fprintf(stderr, "generate_event: incomplete task, spurious wakeup\n");
|
|
163
|
-
}
|
|
164
|
-
// retrieve return code
|
|
165
|
-
retval = event->Result();
|
|
166
|
-
|
|
167
|
-
if (!event->Unlock())
|
|
168
|
-
{
|
|
169
|
-
// TODO: handle error?
|
|
170
|
-
fprintf(stderr, "generate_event: event unlock failed\n");
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
return retval;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
/** callbacks provided to libmilter *******************************************/
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* complicated MTA-to-milter bullshit nobody needs to fiddle with right now
|
|
182
|
-
*
|
|
183
|
-
* http://www-01.ibm.com/support/knowledgecenter/ssw_aix_71/com.ibm.aix.networkcomm/libmilter_xxfi_negotiate.htm
|
|
184
|
-
*/
|
|
185
|
-
sfsistat fi_negotiate (SMFICTX *context,
|
|
186
|
-
unsigned long f0,
|
|
187
|
-
unsigned long f1,
|
|
188
|
-
unsigned long f2,
|
|
189
|
-
unsigned long f3,
|
|
190
|
-
unsigned long *pf0,
|
|
191
|
-
unsigned long *pf1,
|
|
192
|
-
unsigned long *pf2,
|
|
193
|
-
unsigned long *pf3)
|
|
194
|
-
{
|
|
195
|
-
int retval = SMFIS_ALL_OPTS;
|
|
196
|
-
|
|
197
|
-
// envelope initializer
|
|
198
|
-
// links future events in this thread to the same envelope in node.js
|
|
199
|
-
envelope_t *env = new envelope_t(&app);
|
|
200
|
-
smfi_setpriv(context, env);
|
|
201
|
-
|
|
202
|
-
MilterNegotiate *event = new MilterNegotiate(env, f0, f1, f2, f3, pf0, pf1, pf2, pf3);
|
|
203
|
-
#ifdef DEBUG_MILTEREVENT
|
|
204
|
-
fprintf(stderr, "negotiate %lu %lu %lu %lu\n", f0, f1, f2, f3);
|
|
205
|
-
#endif
|
|
206
|
-
retval = generate_event(context, &app, event);
|
|
207
|
-
delete event;
|
|
208
|
-
return retval;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
/**
|
|
213
|
-
* an incoming connection from the MTA has occurred.
|
|
214
|
-
*/
|
|
215
|
-
sfsistat fi_connect (SMFICTX *context, char *host, _SOCK_ADDR *sa)
|
|
216
|
-
{
|
|
217
|
-
envelope_t *env = (envelope_t *)smfi_getpriv(context);
|
|
218
|
-
int retval;
|
|
219
|
-
|
|
220
|
-
MilterConnect *event = new MilterConnect(env, host, (sockaddr_in *)sa);
|
|
221
|
-
#ifdef DEBUG_MILTEREVENT
|
|
222
|
-
fprintf(stderr, "connect \"%s\" \"%s\"\n", event->Host(), event->Address());
|
|
223
|
-
#endif
|
|
224
|
-
retval = generate_event(context, env->local, event);
|
|
225
|
-
delete event;
|
|
226
|
-
return retval;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
/**
|
|
231
|
-
*/
|
|
232
|
-
sfsistat fi_unknown (SMFICTX *context, const char *command)
|
|
233
|
-
{
|
|
234
|
-
envelope_t *env = (envelope_t *)smfi_getpriv(context);
|
|
235
|
-
int retval;
|
|
236
|
-
MilterUnknown *event = new MilterUnknown(env, command);
|
|
237
|
-
#ifdef DEBUG_MILTEREVENT
|
|
238
|
-
fprintf(stderr, "unknown \"%s\"\n", command);
|
|
239
|
-
#endif
|
|
240
|
-
retval = generate_event(context, env->local, event);
|
|
241
|
-
delete event;
|
|
242
|
-
return retval;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
/**
|
|
247
|
-
*/
|
|
248
|
-
sfsistat fi_helo (SMFICTX *context, char *helo)
|
|
249
|
-
{
|
|
250
|
-
envelope_t *env = (envelope_t *)smfi_getpriv(context);
|
|
251
|
-
int retval;
|
|
252
|
-
MilterHELO *event = new MilterHELO(env, helo);
|
|
253
|
-
#ifdef DEBUG_MILTEREVENT
|
|
254
|
-
fprintf(stderr, "helo \"%s\"\n", helo);
|
|
255
|
-
#endif
|
|
256
|
-
retval = generate_event(context, env->local, event);
|
|
257
|
-
delete event;
|
|
258
|
-
return retval;
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
/**
|
|
263
|
-
* client "MAIL FROM" command
|
|
264
|
-
*/
|
|
265
|
-
sfsistat fi_envfrom (SMFICTX *context, char **argv)
|
|
266
|
-
{
|
|
267
|
-
envelope_t *env = (envelope_t *)smfi_getpriv(context);
|
|
268
|
-
int retval;
|
|
269
|
-
MilterMAILFROM *event = new MilterMAILFROM(env, argv);
|
|
270
|
-
#ifdef DEBUG_MILTEREVENT
|
|
271
|
-
fprintf(stderr, "envfrom \"%s\"\n", argv[0]); // argv[0] is guaranteed
|
|
272
|
-
#endif
|
|
273
|
-
retval = generate_event(context, env->local, event);
|
|
274
|
-
delete event;
|
|
275
|
-
return retval;
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
/**
|
|
280
|
-
* client "RCPT TO" command
|
|
281
|
-
*/
|
|
282
|
-
sfsistat fi_envrcpt (SMFICTX *context, char **argv)
|
|
283
|
-
{
|
|
284
|
-
envelope_t *env = (envelope_t *)smfi_getpriv(context);
|
|
285
|
-
int retval;
|
|
286
|
-
MilterRCPTTO *event = new MilterRCPTTO(env, argv);
|
|
287
|
-
#ifdef DEBUG_MILTEREVENT
|
|
288
|
-
fprintf(stderr, "envrcpt \"%s\"\n", argv[0]); // argv[0] is guaranteed
|
|
289
|
-
#endif
|
|
290
|
-
retval = generate_event(context, env->local, event);
|
|
291
|
-
delete event;
|
|
292
|
-
return retval;
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
/**
|
|
297
|
-
* client "DATA" command
|
|
298
|
-
*/
|
|
299
|
-
sfsistat fi_data (SMFICTX *context)
|
|
300
|
-
{
|
|
301
|
-
envelope_t *env = (envelope_t *)smfi_getpriv(context);
|
|
302
|
-
int retval;
|
|
303
|
-
MilterDATA *event = new MilterDATA(env);
|
|
304
|
-
#ifdef DEBUG_MILTEREVENT
|
|
305
|
-
fprintf(stderr, "data\n");
|
|
306
|
-
#endif
|
|
307
|
-
retval = generate_event(context, env->local, event);
|
|
308
|
-
delete event;
|
|
309
|
-
return retval;
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
/**
|
|
314
|
-
* detected a valid message header
|
|
315
|
-
*/
|
|
316
|
-
sfsistat fi_header (SMFICTX *context, char *name, char *value)
|
|
317
|
-
{
|
|
318
|
-
envelope_t *env = (envelope_t *)smfi_getpriv(context);
|
|
319
|
-
int retval;
|
|
320
|
-
MilterHeader *event = new MilterHeader(env, name, value);
|
|
321
|
-
#ifdef DEBUG_MILTEREVENT_HEADERS_TOO
|
|
322
|
-
fprintf(stderr, "header \"%s\" \"%s\"\n", name, value);
|
|
323
|
-
#endif
|
|
324
|
-
retval = generate_event(context, env->local, event);
|
|
325
|
-
delete event;
|
|
326
|
-
return retval;
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
/**
|
|
331
|
-
* detected CRLFCRLF in data stream
|
|
332
|
-
*/
|
|
333
|
-
sfsistat fi_eoh (SMFICTX *context)
|
|
334
|
-
{
|
|
335
|
-
envelope_t *env = (envelope_t *)smfi_getpriv(context);
|
|
336
|
-
int retval;
|
|
337
|
-
MilterEndHeaders *event = new MilterEndHeaders(env);
|
|
338
|
-
#ifdef DEBUG_MILTEREVENT
|
|
339
|
-
fprintf(stderr, "eoh\n");
|
|
340
|
-
#endif
|
|
341
|
-
retval = generate_event(context, env->local, event);
|
|
342
|
-
delete event;
|
|
343
|
-
return retval;
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
/**
|
|
348
|
-
* nota bene: segment is a byte buffer of unspecified encoding! don't
|
|
349
|
-
* assume it isn't utf-8 just because smtp doesn't truly support that yet!
|
|
350
|
-
*/
|
|
351
|
-
sfsistat fi_body (SMFICTX *context, unsigned char *segment, size_t len)
|
|
352
|
-
{
|
|
353
|
-
envelope_t *env = (envelope_t *)smfi_getpriv(context);
|
|
354
|
-
int retval;
|
|
355
|
-
MilterMessageData *event = new MilterMessageData(env, segment, len);
|
|
356
|
-
#ifdef DEBUG_MILTEREVENT
|
|
357
|
-
fprintf(stderr, "message-data (%lu bytes)\n", len);
|
|
358
|
-
#endif
|
|
359
|
-
retval = generate_event(context, env->local, event);
|
|
360
|
-
delete event;
|
|
361
|
-
return retval;
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
/**
|
|
366
|
-
* client "." command
|
|
367
|
-
*/
|
|
368
|
-
sfsistat fi_eom (SMFICTX *context)
|
|
369
|
-
{
|
|
370
|
-
envelope_t *env = (envelope_t *)smfi_getpriv(context);
|
|
371
|
-
int retval;
|
|
372
|
-
MilterEndMessage *event = new MilterEndMessage(env);
|
|
373
|
-
#ifdef DEBUG_MILTEREVENT
|
|
374
|
-
fprintf(stderr, "eom\n");
|
|
375
|
-
#endif
|
|
376
|
-
retval = generate_event(context, env->local, event);
|
|
377
|
-
delete event;
|
|
378
|
-
return retval;
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
/**
|
|
383
|
-
* probably triggered on client "RSET" or any other connection loss
|
|
384
|
-
*
|
|
385
|
-
* fi_close will still be called afterward, but fi_abort implies the client
|
|
386
|
-
* definitely changed their mind about sending mail
|
|
387
|
-
*/
|
|
388
|
-
sfsistat fi_abort (SMFICTX *context)
|
|
389
|
-
{
|
|
390
|
-
envelope_t *env = (envelope_t *)smfi_getpriv(context);
|
|
391
|
-
int retval;
|
|
392
|
-
MilterAbort *event = new MilterAbort(env);
|
|
393
|
-
#ifdef DEBUG_MILTEREVENT
|
|
394
|
-
fprintf(stderr, "abort\n");
|
|
395
|
-
#endif
|
|
396
|
-
retval = generate_event(context, env->local, event);
|
|
397
|
-
delete event;
|
|
398
|
-
return retval;
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
/**
|
|
403
|
-
*/
|
|
404
|
-
sfsistat fi_close (SMFICTX *context)
|
|
405
|
-
{
|
|
406
|
-
envelope_t *env = (envelope_t *)smfi_getpriv(context);
|
|
407
|
-
int retval;
|
|
408
|
-
MilterClose *event = new MilterClose(env);
|
|
409
|
-
#ifdef DEBUG_MILTEREVENT
|
|
410
|
-
fprintf(stderr, "close\n");
|
|
411
|
-
#endif
|
|
412
|
-
retval = generate_event(context, env->local, event);
|
|
413
|
-
delete event;
|
|
414
|
-
|
|
415
|
-
// final teardown sequence
|
|
416
|
-
delete env;
|
|
417
|
-
smfi_setpriv(context, NULL);
|
|
418
|
-
|
|
419
|
-
return retval;
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
/**
|
|
424
|
-
* run async version of smfi_main, which is blocking
|
|
425
|
-
*/
|
|
426
|
-
void milter_worker (uv_work_t *request)
|
|
427
|
-
{
|
|
428
|
-
int r;
|
|
429
|
-
r = smfi_main();
|
|
430
|
-
fprintf(stderr, "milter_worker finishing\n");
|
|
431
|
-
// TODO: any concurrency issues here?
|
|
432
|
-
app.retval = r;
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
/**
|
|
437
|
-
* cleanup after smfi_main finally stops.
|
|
438
|
-
*/
|
|
439
|
-
void milter_cleanup (uv_work_t *request, int status)
|
|
440
|
-
{
|
|
441
|
-
Isolate *isolate = Isolate::GetCurrent();
|
|
442
|
-
Locker locker (isolate);
|
|
443
|
-
HandleScope scope (isolate);
|
|
444
|
-
|
|
445
|
-
fprintf(stderr, "milter_cleanup started\n");
|
|
446
|
-
|
|
447
|
-
// immediately stop event delivery
|
|
448
|
-
uv_close((uv_handle_t *)&(app.trigger), NULL);
|
|
449
|
-
|
|
450
|
-
app.fcall.negotiate.Reset();
|
|
451
|
-
app.fcall.connect.Reset();
|
|
452
|
-
app.fcall.unknown.Reset();
|
|
453
|
-
app.fcall.helo.Reset();
|
|
454
|
-
app.fcall.envfrom.Reset();
|
|
455
|
-
app.fcall.envrcpt.Reset();
|
|
456
|
-
app.fcall.data.Reset();
|
|
457
|
-
app.fcall.header.Reset();
|
|
458
|
-
app.fcall.eoh.Reset();
|
|
459
|
-
app.fcall.body.Reset();
|
|
460
|
-
app.fcall.eom.Reset();
|
|
461
|
-
app.fcall.abort.Reset();
|
|
462
|
-
app.fcall.close.Reset();
|
|
463
|
-
|
|
464
|
-
// TODO: call a "end" callback provided during instantiation? unsure how to do this, probably with a persistent function
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
/**
|
|
469
|
-
*/
|
|
470
|
-
void milter_start (const FunctionCallbackInfo<Value> &args)
|
|
471
|
-
{
|
|
472
|
-
Isolate *isolate = Isolate::GetCurrent();
|
|
473
|
-
Locker locker (isolate);
|
|
474
|
-
HandleScope scope(isolate);
|
|
475
|
-
|
|
476
|
-
struct smfiDesc desc;
|
|
477
|
-
|
|
478
|
-
desc.xxfi_name =(char *)g_name;
|
|
479
|
-
desc.xxfi_version = SMFI_VERSION;
|
|
480
|
-
desc.xxfi_flags = 0;
|
|
481
|
-
desc.xxfi_negotiate = fi_negotiate;
|
|
482
|
-
desc.xxfi_connect = fi_connect;
|
|
483
|
-
desc.xxfi_unknown = fi_unknown;
|
|
484
|
-
desc.xxfi_helo = fi_helo;
|
|
485
|
-
desc.xxfi_envfrom = fi_envfrom;
|
|
486
|
-
desc.xxfi_envrcpt = fi_envrcpt;
|
|
487
|
-
desc.xxfi_data = fi_data;
|
|
488
|
-
desc.xxfi_header = fi_header;
|
|
489
|
-
desc.xxfi_eoh = fi_eoh;
|
|
490
|
-
desc.xxfi_body = fi_body;
|
|
491
|
-
desc.xxfi_eom = fi_eom;
|
|
492
|
-
desc.xxfi_abort = fi_abort;
|
|
493
|
-
desc.xxfi_close = fi_close;
|
|
494
|
-
#if 0
|
|
495
|
-
// signal handler is not implemented yet
|
|
496
|
-
desc.xxfi_signal = fi_signal;
|
|
497
|
-
#endif
|
|
498
|
-
|
|
499
|
-
// connect libuv
|
|
500
|
-
app.request.data = &app;
|
|
501
|
-
app.trigger.data = &app;
|
|
502
|
-
|
|
503
|
-
if (args.Length() < 14)
|
|
504
|
-
{
|
|
505
|
-
isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, "Wrong number of arguments")));
|
|
506
|
-
return;
|
|
507
|
-
}
|
|
508
|
-
if (!args[0]->IsString())
|
|
509
|
-
{
|
|
510
|
-
isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, "Invalid argument: expected string")));
|
|
511
|
-
return;
|
|
512
|
-
}
|
|
513
|
-
if (!args[1]->IsNumber())
|
|
514
|
-
{
|
|
515
|
-
isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, "Invalid argument: expected number")));
|
|
516
|
-
return;
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
desc.xxfi_flags = args[1]->IntegerValue();
|
|
520
|
-
|
|
521
|
-
// ya dats lazy
|
|
522
|
-
for (int i = 2; i < 15; i++)
|
|
523
|
-
if (!args[i]->IsFunction())
|
|
524
|
-
{
|
|
525
|
-
isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, "Invalid argument: expected function")));
|
|
526
|
-
return;
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
Local<String> connstr = args[0]->ToString();
|
|
530
|
-
char *c_connstr = new char[connstr->Utf8Length()+1];
|
|
531
|
-
connstr->WriteUtf8(c_connstr);
|
|
532
|
-
|
|
533
|
-
app.fcall.negotiate.Reset (isolate, Local<Function>::Cast(args[2]));
|
|
534
|
-
app.fcall.connect.Reset (isolate, Local<Function>::Cast(args[3]));
|
|
535
|
-
app.fcall.unknown.Reset (isolate, Local<Function>::Cast(args[4]));
|
|
536
|
-
app.fcall.helo.Reset (isolate, Local<Function>::Cast(args[5]));
|
|
537
|
-
app.fcall.envfrom.Reset (isolate, Local<Function>::Cast(args[6]));
|
|
538
|
-
app.fcall.envrcpt.Reset (isolate, Local<Function>::Cast(args[7]));
|
|
539
|
-
app.fcall.data.Reset (isolate, Local<Function>::Cast(args[8]));
|
|
540
|
-
app.fcall.header.Reset (isolate, Local<Function>::Cast(args[9]));
|
|
541
|
-
app.fcall.eoh.Reset (isolate, Local<Function>::Cast(args[10]));
|
|
542
|
-
app.fcall.body.Reset (isolate, Local<Function>::Cast(args[11]));
|
|
543
|
-
app.fcall.eom.Reset (isolate, Local<Function>::Cast(args[12]));
|
|
544
|
-
app.fcall.abort.Reset (isolate, Local<Function>::Cast(args[13]));
|
|
545
|
-
app.fcall.close.Reset (isolate, Local<Function>::Cast(args[14]));
|
|
546
|
-
|
|
547
|
-
bool ok = false;
|
|
548
|
-
if (MI_SUCCESS == smfi_register(desc))
|
|
549
|
-
{
|
|
550
|
-
if (MI_SUCCESS == smfi_setconn(c_connstr))
|
|
551
|
-
{
|
|
552
|
-
app.loop = uv_default_loop();
|
|
553
|
-
uv_async_init(app.loop, &app.trigger, trigger_event);
|
|
554
|
-
uv_queue_work(app.loop, &app.request, milter_worker, milter_cleanup);
|
|
555
|
-
ok = true;
|
|
556
|
-
}
|
|
557
|
-
}
|
|
558
|
-
delete c_connstr;
|
|
559
|
-
|
|
560
|
-
if (!ok)
|
|
561
|
-
{
|
|
562
|
-
app.fcall.negotiate.Reset();
|
|
563
|
-
app.fcall.connect.Reset();
|
|
564
|
-
app.fcall.unknown.Reset();
|
|
565
|
-
app.fcall.helo.Reset();
|
|
566
|
-
app.fcall.envfrom.Reset();
|
|
567
|
-
app.fcall.envrcpt.Reset();
|
|
568
|
-
app.fcall.data.Reset();
|
|
569
|
-
app.fcall.header.Reset();
|
|
570
|
-
app.fcall.eoh.Reset();
|
|
571
|
-
app.fcall.body.Reset();
|
|
572
|
-
app.fcall.eom.Reset();
|
|
573
|
-
app.fcall.abort.Reset();
|
|
574
|
-
app.fcall.close.Reset();
|
|
575
|
-
// TODO: throw exception?
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
args.GetReturnValue().Set(Boolean::New(isolate, ok));
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
/**
|
|
583
|
-
*/
|
|
584
|
-
void milter_setbacklog (const FunctionCallbackInfo<Value> &args)
|
|
585
|
-
{
|
|
586
|
-
Isolate *isolate = Isolate::GetCurrent();
|
|
587
|
-
HandleScope scope(isolate);
|
|
588
|
-
if (args.Length() < 1)
|
|
589
|
-
{
|
|
590
|
-
isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, "Wrong number of arguments")));
|
|
591
|
-
return;
|
|
592
|
-
}
|
|
593
|
-
if (!args[0]->IsNumber())
|
|
594
|
-
{
|
|
595
|
-
isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, "Invalid argument: expected number")));
|
|
596
|
-
return;
|
|
597
|
-
}
|
|
598
|
-
int n = args[0]->IntegerValue();
|
|
599
|
-
int r = smfi_setbacklog(n);
|
|
600
|
-
args.GetReturnValue().Set(Number::New(isolate, r));
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
/**
|
|
605
|
-
*/
|
|
606
|
-
void milter_setdbg (const FunctionCallbackInfo<Value> &args)
|
|
607
|
-
{
|
|
608
|
-
Isolate *isolate = Isolate::GetCurrent();
|
|
609
|
-
HandleScope scope(isolate);
|
|
610
|
-
if (args.Length() < 1)
|
|
611
|
-
{
|
|
612
|
-
isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, "Wrong number of arguments")));
|
|
613
|
-
return;
|
|
614
|
-
}
|
|
615
|
-
if (!args[0]->IsNumber())
|
|
616
|
-
{
|
|
617
|
-
isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, "Invalid argument: expected number")));
|
|
618
|
-
return;
|
|
619
|
-
}
|
|
620
|
-
int f = args[0]->IntegerValue();
|
|
621
|
-
int r = smfi_setdbg(f);
|
|
622
|
-
args.GetReturnValue().Set(Number::New(isolate, r));
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
/**
|
|
627
|
-
*/
|
|
628
|
-
void milter_settimeout (const FunctionCallbackInfo<Value> &args)
|
|
629
|
-
{
|
|
630
|
-
Isolate *isolate = Isolate::GetCurrent();
|
|
631
|
-
HandleScope scope(isolate);
|
|
632
|
-
if (args.Length() < 1)
|
|
633
|
-
{
|
|
634
|
-
isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, "Wrong number of arguments")));
|
|
635
|
-
return;
|
|
636
|
-
}
|
|
637
|
-
if (!args[0]->IsNumber())
|
|
638
|
-
{
|
|
639
|
-
isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, "Invalid argument: expected number")));
|
|
640
|
-
return;
|
|
641
|
-
}
|
|
642
|
-
int timeo = args[0]->IntegerValue();
|
|
643
|
-
int r = smfi_settimeout(timeo);
|
|
644
|
-
args.GetReturnValue().Set(Number::New(isolate, r));
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
/**
|
|
649
|
-
*/
|
|
650
|
-
void milter_stop (const FunctionCallbackInfo<Value> &args)
|
|
651
|
-
{
|
|
652
|
-
Isolate *isolate = Isolate::GetCurrent();
|
|
653
|
-
HandleScope scope(isolate);
|
|
654
|
-
int r = smfi_stop();
|
|
655
|
-
args.GetReturnValue().Set(Number::New(isolate, r));
|
|
656
|
-
}
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
/**
|
|
660
|
-
*/
|
|
661
|
-
void milter_version (const FunctionCallbackInfo<Value> &args)
|
|
662
|
-
{
|
|
663
|
-
Isolate *isolate = Isolate::GetCurrent();
|
|
664
|
-
HandleScope scope (isolate);
|
|
665
|
-
unsigned int major, minor, patchlevel;
|
|
666
|
-
|
|
667
|
-
smfi_version(&major, &minor, &patchlevel);
|
|
668
|
-
|
|
669
|
-
Local<Array> r = Array::New(isolate);
|
|
670
|
-
r->Set(0, Number::New(isolate, major));
|
|
671
|
-
r->Set(1, Number::New(isolate, minor));
|
|
672
|
-
r->Set(2, Number::New(isolate, patchlevel));
|
|
673
|
-
args.GetReturnValue().Set(r);
|
|
674
|
-
}
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
/**
|
|
678
|
-
* module initialization
|
|
679
|
-
*/
|
|
680
|
-
void init (Handle<Object> target, Handle<Value> module, Handle<Context> context)
|
|
681
|
-
{
|
|
682
|
-
Isolate *isolate = Isolate::GetCurrent();
|
|
683
|
-
|
|
684
|
-
// return values from envelope functions
|
|
685
|
-
target->Set(String::NewFromUtf8(isolate, "MI_SUCCESS", String::kInternalizedString), Number::New(isolate, MI_SUCCESS));
|
|
686
|
-
target->Set(String::NewFromUtf8(isolate, "MI_FAILURE", String::kInternalizedString), Number::New(isolate, MI_FAILURE));
|
|
687
|
-
|
|
688
|
-
// macro contexts/locations
|
|
689
|
-
target->Set(String::NewFromUtf8(isolate, "SMFIM_CONNECT", String::kInternalizedString), Number::New(isolate, SMFIM_CONNECT));
|
|
690
|
-
target->Set(String::NewFromUtf8(isolate, "SMFIM_HELO", String::kInternalizedString), Number::New(isolate, SMFIM_HELO));
|
|
691
|
-
target->Set(String::NewFromUtf8(isolate, "SMFIM_ENVFROM", String::kInternalizedString), Number::New(isolate, SMFIM_ENVFROM));
|
|
692
|
-
target->Set(String::NewFromUtf8(isolate, "SMFIM_ENVRCPT", String::kInternalizedString), Number::New(isolate, SMFIM_ENVRCPT));
|
|
693
|
-
target->Set(String::NewFromUtf8(isolate, "SMFIM_DATA", String::kInternalizedString), Number::New(isolate, SMFIM_DATA));
|
|
694
|
-
target->Set(String::NewFromUtf8(isolate, "SMFIM_EOM", String::kInternalizedString), Number::New(isolate, SMFIM_EOM));
|
|
695
|
-
target->Set(String::NewFromUtf8(isolate, "SMFIM_EOH", String::kInternalizedString), Number::New(isolate, SMFIM_EOH));
|
|
696
|
-
|
|
697
|
-
// negotiate flags
|
|
698
|
-
target->Set(String::NewFromUtf8(isolate, "SMFIF_NONE", String::kInternalizedString), Number::New(isolate, SMFIF_NONE));
|
|
699
|
-
target->Set(String::NewFromUtf8(isolate, "SMFIF_ADDHDRS", String::kInternalizedString), Number::New(isolate, SMFIF_ADDHDRS));
|
|
700
|
-
target->Set(String::NewFromUtf8(isolate, "SMFIF_CHGBODY", String::kInternalizedString), Number::New(isolate, SMFIF_CHGBODY));
|
|
701
|
-
target->Set(String::NewFromUtf8(isolate, "SMFIF_MODBODY", String::kInternalizedString), Number::New(isolate, SMFIF_MODBODY));
|
|
702
|
-
target->Set(String::NewFromUtf8(isolate, "SMFIF_ADDRCPT", String::kInternalizedString), Number::New(isolate, SMFIF_ADDRCPT));
|
|
703
|
-
target->Set(String::NewFromUtf8(isolate, "SMFIF_DELRCPT", String::kInternalizedString), Number::New(isolate, SMFIF_DELRCPT));
|
|
704
|
-
target->Set(String::NewFromUtf8(isolate, "SMFIF_CHGHDRS", String::kInternalizedString), Number::New(isolate, SMFIF_CHGHDRS));
|
|
705
|
-
target->Set(String::NewFromUtf8(isolate, "SMFIF_QUARANTINE", String::kInternalizedString), Number::New(isolate, SMFIF_QUARANTINE));
|
|
706
|
-
target->Set(String::NewFromUtf8(isolate, "SMFIF_CHGFROM", String::kInternalizedString), Number::New(isolate, SMFIF_CHGFROM));
|
|
707
|
-
target->Set(String::NewFromUtf8(isolate, "SMFIF_ADDRCPT_PAR", String::kInternalizedString), Number::New(isolate, SMFIF_ADDRCPT_PAR));
|
|
708
|
-
target->Set(String::NewFromUtf8(isolate, "SMFIF_SETSYMLIST", String::kInternalizedString), Number::New(isolate, SMFIF_SETSYMLIST));
|
|
709
|
-
|
|
710
|
-
// normal callback return values
|
|
711
|
-
target->Set(String::NewFromUtf8(isolate, "SMFIS_CONTINUE", String::kInternalizedString), Number::New(isolate, SMFIS_CONTINUE));
|
|
712
|
-
target->Set(String::NewFromUtf8(isolate, "SMFIS_REJECT", String::kInternalizedString), Number::New(isolate, SMFIS_REJECT));
|
|
713
|
-
target->Set(String::NewFromUtf8(isolate, "SMFIS_DISCARD", String::kInternalizedString), Number::New(isolate, SMFIS_DISCARD));
|
|
714
|
-
target->Set(String::NewFromUtf8(isolate, "SMFIS_ACCEPT", String::kInternalizedString), Number::New(isolate, SMFIS_ACCEPT));
|
|
715
|
-
target->Set(String::NewFromUtf8(isolate, "SMFIS_TEMPFAIL", String::kInternalizedString), Number::New(isolate, SMFIS_TEMPFAIL));
|
|
716
|
-
target->Set(String::NewFromUtf8(isolate, "SMFIS_NOREPLY", String::kInternalizedString), Number::New(isolate, SMFIS_NOREPLY));
|
|
717
|
-
target->Set(String::NewFromUtf8(isolate, "SMFIS_SKIP", String::kInternalizedString), Number::New(isolate, SMFIS_SKIP));
|
|
718
|
-
|
|
719
|
-
// callback return val for negotiate only
|
|
720
|
-
target->Set(String::NewFromUtf8(isolate, "SMFIS_ALL_OPTS", String::kInternalizedString), Number::New(isolate, SMFIS_ALL_OPTS));
|
|
721
|
-
|
|
722
|
-
Envelope::Init(target);
|
|
723
|
-
|
|
724
|
-
NODE_SET_METHOD(target, "start", milter_start);
|
|
725
|
-
NODE_SET_METHOD(target, "setbacklog", milter_setbacklog);
|
|
726
|
-
NODE_SET_METHOD(target, "setdbg", milter_setdbg);
|
|
727
|
-
NODE_SET_METHOD(target, "settimeout", milter_settimeout);
|
|
728
|
-
NODE_SET_METHOD(target, "stop", milter_stop);
|
|
729
|
-
NODE_SET_METHOD(target, "version", milter_version);
|
|
730
|
-
}
|
|
731
|
-
|
|
732
|
-
NODE_MODULE_CONTEXT_AWARE(milter, init)
|