Postfix3.3.1
qmqp-source.c
[詳解]
1 /*++
2 /* NAME
3 /* qmqp-source 1
4 /* SUMMARY
5 /* parallelized QMQP test generator
6 /* SYNOPSIS
7 /* .fi
8 /* \fBqmqp-source\fR [\fIoptions\fR] [\fBinet:\fR]\fIhost\fR[:\fIport\fR]
9 /*
10 /* \fBqmqp-source\fR [\fIoptions\fR] \fBunix:\fIpathname\fR
11 /* DESCRIPTION
12 /* \fBqmqp-source\fR connects to the named host and TCP port (default 628)
13 /* and sends one or more messages to it, either sequentially
14 /* or in parallel. The program speaks the QMQP protocol.
15 /* Connections can be made to UNIX-domain and IPv4 or IPv6 servers.
16 /* IPv4 and IPv6 are the default.
17 /*
18 /* Note: this is an unsupported test program. No attempt is made
19 /* to maintain compatibility between successive versions.
20 /*
21 /* Arguments:
22 /* .IP \fB-4\fR
23 /* Connect to the server with IPv4. This option has no effect when
24 /* Postfix is built without IPv6 support.
25 /* .IP \fB-6\fR
26 /* Connect to the server with IPv6. This option is not available when
27 /* Postfix is built without IPv6 support.
28 /* .IP \fB-c\fR
29 /* Display a running counter that is incremented each time
30 /* a delivery completes.
31 /* .IP "\fB-C \fIcount\fR"
32 /* When a host sends RESET instead of SYN|ACK, try \fIcount\fR times
33 /* before giving up. The default count is 1. Specify a larger count in
34 /* order to work around a problem with TCP/IP stacks that send RESET
35 /* when the listen queue is full.
36 /* .IP "\fB-f \fIfrom\fR"
37 /* Use the specified sender address (default: <foo@myhostname>).
38 /* .IP "\fB-l \fIlength\fR"
39 /* Send \fIlength\fR bytes as message payload. The length
40 /* includes the message headers.
41 /* .IP "\fB-m \fImessage_count\fR"
42 /* Send the specified number of messages (default: 1).
43 /* .IP "\fB-M \fImyhostname\fR"
44 /* Use the specified hostname or [address] in the default
45 /* sender and recipient addresses, instead of the machine
46 /* hostname.
47 /* .IP "\fB-r \fIrecipient_count\fR"
48 /* Send the specified number of recipients per transaction (default: 1).
49 /* Recipient names are generated by prepending a number to the
50 /* recipient address.
51 /* .IP "\fB-s \fIsession_count\fR"
52 /* Run the specified number of QMQP sessions in parallel (default: 1).
53 /* .IP "\fB-t \fIto\fR"
54 /* Use the specified recipient address (default: <foo@myhostname>).
55 /* .IP "\fB-R \fIinterval\fR"
56 /* Wait for a random period of time 0 <= n <= interval between messages.
57 /* Suspending one thread does not affect other delivery threads.
58 /* .IP \fB-v\fR
59 /* Make the program more verbose, for debugging purposes.
60 /* .IP "\fB-w \fIinterval\fR"
61 /* Wait a fixed time between messages.
62 /* Suspending one thread does not affect other delivery threads.
63 /* SEE ALSO
64 /* qmqp-sink(1), QMQP message dump
65 /* LICENSE
66 /* .ad
67 /* .fi
68 /* The Secure Mailer license must be distributed with this software.
69 /* AUTHOR(S)
70 /* Wietse Venema
71 /* IBM T.J. Watson Research
72 /* P.O. Box 704
73 /* Yorktown Heights, NY 10598, USA
74 /*
75 /* Wietse Venema
76 /* Google, Inc.
77 /* 111 8th Avenue
78 /* New York, NY 10011, USA
79 /*--*/
80 
81 /* System library. */
82 
83 #include <sys_defs.h>
84 #include <sys/socket.h>
85 #include <sys/wait.h>
86 #include <netinet/in.h>
87 #include <sys/un.h>
88 #include <stdlib.h>
89 #include <unistd.h>
90 #include <signal.h>
91 #include <errno.h>
92 #include <string.h>
93 
94 /* Utility library. */
95 
96 #include <msg.h>
97 #include <msg_vstream.h>
98 #include <vstring.h>
99 #include <vstream.h>
100 #include <get_hostname.h>
101 #include <split_at.h>
102 #include <connect.h>
103 #include <mymalloc.h>
104 #include <events.h>
105 #include <iostuff.h>
106 #include <netstring.h>
107 #include <sane_connect.h>
108 #include <host_port.h>
109 #include <myaddrinfo.h>
110 #include <inet_proto.h>
111 #include <valid_hostname.h>
112 #include <valid_mailhost_addr.h>
113 
114 /* Global library. */
115 
116 #include <mail_date.h>
117 #include <qmqp_proto.h>
118 #include <mail_version.h>
119 
120 /* Application-specific. */
121 
122  /*
123  * Per-session data structure with state.
124  *
125  * This software can maintain multiple parallel connections to the same QMQP
126  * server. However, it makes no more than one connection request at a time
127  * to avoid overwhelming the server with SYN packets and having to back off.
128  * Back-off would screw up the benchmark. Pending connection requests are
129  * kept in a linear list.
130  */
131 typedef struct SESSION {
132  int xfer_count; /* # of xfers in session */
133  int rcpt_done; /* # of recipients done */
134  int rcpt_count; /* # of recipients to go */
135  VSTREAM *stream; /* open connection */
136  int connect_count; /* # of connect()s to retry */
137  struct SESSION *next; /* connect() queue linkage */
138 } SESSION;
139 
140 static SESSION *last_session; /* connect() queue tail */
141 
142 static VSTRING *buffer;
143 static int var_line_limit = 10240;
144 static int var_timeout = 300;
145 static const char *var_myhostname;
146 static int session_count;
147 static int message_count = 1;
148 static struct sockaddr_storage ss;
149 
150 #undef sun
151 static struct sockaddr_un sun;
152 static struct sockaddr *sa;
153 static int sa_length;
154 static int recipients = 1;
155 static char *defaddr;
156 static char *recipient;
157 static char *sender;
158 static int message_length = 1024;
159 static int count = 0;
160 static int counter = 0;
161 static int connect_count = 1;
162 static int random_delay = 0;
163 static int fixed_delay = 0;
164 static const char *mydate;
165 static int mypid;
166 
167 static void enqueue_connect(SESSION *);
168 static void start_connect(SESSION *);
169 static void connect_done(int, void *);
170 
171 static void send_data(SESSION *);
172 static void receive_reply(int, void *);
173 
174 static VSTRING *message_buffer;
175 static VSTRING *sender_buffer;
176 static VSTRING *recipient_buffer;
177 
178 /* Silly little macros. */
179 
180 #define STR(x) vstring_str(x)
181 #define LEN(x) VSTRING_LEN(x)
182 
183 /* random_interval - generate a random value in 0 .. (small) interval */
184 
185 static int random_interval(int interval)
186 {
187  return (rand() % (interval + 1));
188 }
189 
190 /* socket_error - look up and reset the last socket error */
191 
192 static int socket_error(int sock)
193 {
194  int error;
195  SOCKOPT_SIZE error_len;
196 
197  /*
198  * Some Solaris 2 versions have getsockopt() itself return the error,
199  * instead of returning it via the parameter list.
200  */
201  error = 0;
202  error_len = sizeof(error);
203  if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void *) &error, &error_len) < 0)
204  return (-1);
205  if (error) {
206  errno = error;
207  return (-1);
208  }
209 
210  /*
211  * No problems.
212  */
213  return (0);
214 }
215 
216 /* exception_text - translate exceptions from the netstring module */
217 
218 static char *exception_text(int except)
219 {
220  ;
221 
222  switch (except) {
223  case NETSTRING_ERR_EOF:
224  return ("lost connection");
225  case NETSTRING_ERR_TIME:
226  return ("timeout");
228  return ("netstring format error");
229  case NETSTRING_ERR_SIZE:
230  return ("netstring size exceeds limit");
231  default:
232  msg_panic("exception_text: unknown exception %d", except);
233  }
234  /* NOTREACHED */
235 }
236 
237 /* startup - connect to server but do not wait */
238 
239 static void startup(SESSION *session)
240 {
241  if (message_count-- <= 0) {
242  myfree((void *) session);
243  session_count--;
244  return;
245  }
246  enqueue_connect(session);
247 }
248 
249 /* start_event - invoke startup from timer context */
250 
251 static void start_event(int unused_event, void *context)
252 {
253  SESSION *session = (SESSION *) context;
254 
255  startup(session);
256 }
257 
258 /* start_another - start another session */
259 
260 static void start_another(SESSION *session)
261 {
262  if (random_delay > 0) {
263  event_request_timer(start_event, (void *) session,
264  random_interval(random_delay));
265  } else if (fixed_delay > 0) {
266  event_request_timer(start_event, (void *) session, fixed_delay);
267  } else {
268  startup(session);
269  }
270 }
271 
272 /* enqueue_connect - queue a connection request */
273 
274 static void enqueue_connect(SESSION *session)
275 {
276  session->next = 0;
277  if (last_session == 0) {
278  last_session = session;
279  start_connect(session);
280  } else {
281  last_session->next = session;
282  last_session = session;
283  }
284 }
285 
286 /* dequeue_connect - connection request completed */
287 
288 static void dequeue_connect(SESSION *session)
289 {
290  if (session == last_session) {
291  if (session->next != 0)
292  msg_panic("dequeue_connect: queue ends after last");
293  last_session = 0;
294  } else {
295  if (session->next == 0)
296  msg_panic("dequeue_connect: queue ends before last");
297  start_connect(session->next);
298  }
299 }
300 
301 /* fail_connect - handle failed startup */
302 
303 static void fail_connect(SESSION *session)
304 {
305  if (session->connect_count-- == 1)
306  msg_fatal("connect: %m");
307  msg_warn("connect: %m");
309  vstream_fclose(session->stream);
310  session->stream = 0;
311 #ifdef MISSING_USLEEP
312  doze(10);
313 #else
314  usleep(10);
315 #endif
316  start_connect(session);
317 }
318 
319 /* start_connect - start TCP handshake */
320 
321 static void start_connect(SESSION *session)
322 {
323  int fd;
324  struct linger linger;
325 
326  /*
327  * Some systems don't set the socket error when connect() fails early
328  * (loopback) so we must deal with the error immediately, rather than
329  * retrieving it later with getsockopt(). We can't use MSG_PEEK to
330  * distinguish between server disconnect and connection refused.
331  */
332  if ((fd = socket(sa->sa_family, SOCK_STREAM, 0)) < 0)
333  msg_fatal("socket: %m");
334  (void) non_blocking(fd, NON_BLOCKING);
335  linger.l_onoff = 1;
336  linger.l_linger = 0;
337  if (setsockopt(fd, SOL_SOCKET, SO_LINGER, (void *) &linger,
338  sizeof(linger)) < 0)
339  msg_warn("setsockopt SO_LINGER %d: %m", linger.l_linger);
340  session->stream = vstream_fdopen(fd, O_RDWR);
341  event_enable_write(fd, connect_done, (void *) session);
342  netstring_setup(session->stream, var_timeout);
343  if (sane_connect(fd, sa, sa_length) < 0 && errno != EINPROGRESS)
344  fail_connect(session);
345 }
346 
347 /* connect_done - send message sender info */
348 
349 static void connect_done(int unused_event, void *context)
350 {
351  SESSION *session = (SESSION *) context;
352  int fd = vstream_fileno(session->stream);
353 
354  /*
355  * Try again after some delay when the connection failed, in case they
356  * run a Mickey Mouse protocol stack.
357  */
358  if (socket_error(fd) < 0) {
359  fail_connect(session);
360  } else {
361  dequeue_connect(session);
362  non_blocking(fd, BLOCKING);
364  /* Avoid poor performance when TCP MSS > VSTREAM_BUFSIZE. */
365  if (sa->sa_family == AF_INET
366 #ifdef AF_INET6
367  || sa->sa_family == AF_INET6
368 #endif
369  )
370  vstream_tweak_tcp(session->stream);
371  send_data(session);
372  }
373 }
374 
375 /* send_data - send message+sender+recipients */
376 
377 static void send_data(SESSION *session)
378 {
379  int fd = vstream_fileno(session->stream);
380  int except;
381 
382  /*
383  * Prepare for disaster.
384  */
385  if ((except = vstream_setjmp(session->stream)) != 0)
386  msg_fatal("%s while sending message", exception_text(except));
387 
388  /*
389  * Send the message content, by wrapping three netstrings into an
390  * over-all netstring.
391  *
392  * XXX This should be done more carefully to avoid blocking when sending
393  * large messages over slow networks.
394  */
395  netstring_put_multi(session->stream,
396  STR(message_buffer), LEN(message_buffer),
397  STR(sender_buffer), LEN(sender_buffer),
398  STR(recipient_buffer), LEN(recipient_buffer),
399  (char *) 0);
400  netstring_fflush(session->stream);
401 
402  /*
403  * Wake me up when the server replies or when something bad happens.
404  */
405  event_enable_read(fd, receive_reply, (void *) session);
406 }
407 
408 /* receive_reply - read server reply */
409 
410 static void receive_reply(int unused_event, void *context)
411 {
412  SESSION *session = (SESSION *) context;
413  int except;
414 
415  /*
416  * Prepare for disaster.
417  */
418  if ((except = vstream_setjmp(session->stream)) != 0)
419  msg_fatal("%s while receiving server reply", exception_text(except));
420 
421  /*
422  * Receive and process the server reply.
423  */
424  netstring_get(session->stream, buffer, var_line_limit);
425  if (msg_verbose)
426  vstream_printf("<< %.*s\n", (int) LEN(buffer), STR(buffer));
427  if (STR(buffer)[0] != QMQP_STAT_OK)
428  msg_fatal("%s error: %.*s",
429  STR(buffer)[0] == QMQP_STAT_RETRY ? "recoverable" :
430  STR(buffer)[0] == QMQP_STAT_HARD ? "unrecoverable" :
431  "unknown", (int) LEN(buffer) - 1, STR(buffer) + 1);
432 
433  /*
434  * Update the optional running counter.
435  */
436  if (count) {
437  counter++;
438  vstream_printf("%d\r", counter);
440  }
441 
442  /*
443  * Finish this session. QMQP sends only one message per session.
444  */
446  vstream_fclose(session->stream);
447  session->stream = 0;
448  start_another(session);
449 }
450 
451 /* usage - explain */
452 
453 static void usage(char *myname)
454 {
455  msg_fatal("usage: %s -cv -s sess -l msglen -m msgs -C count -M myhostname -f from -t to -R delay -w delay host[:port]", myname);
456 }
457 
459 
460 /* main - parse JCL and start the machine */
461 
462 int main(int argc, char **argv)
463 {
464  SESSION *session;
465  char *host;
466  char *port;
467  char *path;
468  int path_len;
469  int sessions = 1;
470  int ch;
471  ssize_t len;
472  int n;
473  int i;
474  char *buf;
475  const char *parse_err;
476  struct addrinfo *res;
477  int aierr;
478  const char *protocols = INET_PROTO_NAME_ALL;
479 
480  /*
481  * Fingerprint executables and core dumps.
482  */
484 
485  signal(SIGPIPE, SIG_IGN);
486  msg_vstream_init(argv[0], VSTREAM_ERR);
487 
488  /*
489  * Parse JCL.
490  */
491  while ((ch = GETOPT(argc, argv, "46cC:f:l:m:M:r:R:s:t:vw:")) > 0) {
492  switch (ch) {
493  case '4':
494  protocols = INET_PROTO_NAME_IPV4;
495  break;
496  case '6':
497  protocols = INET_PROTO_NAME_IPV6;
498  break;
499  case 'c':
500  count++;
501  break;
502  case 'C':
503  if ((connect_count = atoi(optarg)) <= 0)
504  usage(argv[0]);
505  break;
506  case 'f':
507  sender = optarg;
508  break;
509  case 'l':
510  if ((message_length = atoi(optarg)) <= 0)
511  usage(argv[0]);
512  break;
513  case 'm':
514  if ((message_count = atoi(optarg)) <= 0)
515  usage(argv[0]);
516  break;
517  case 'M':
518  if (*optarg == '[') {
519  if (!valid_mailhost_literal(optarg, DO_GRIPE))
520  msg_fatal("bad address literal: %s", optarg);
521  } else {
522  if (!valid_hostname(optarg, DO_GRIPE))
523  msg_fatal("bad hostname: %s", optarg);
524  }
525  var_myhostname = optarg;
526  break;
527  case 'r':
528  if ((recipients = atoi(optarg)) <= 0)
529  usage(argv[0]);
530  break;
531  case 'R':
532  if (fixed_delay > 0 || (random_delay = atoi(optarg)) <= 0)
533  usage(argv[0]);
534  break;
535  case 's':
536  if ((sessions = atoi(optarg)) <= 0)
537  usage(argv[0]);
538  break;
539  case 't':
540  recipient = optarg;
541  break;
542  case 'v':
543  msg_verbose++;
544  break;
545  case 'w':
546  if (random_delay > 0 || (fixed_delay = atoi(optarg)) <= 0)
547  usage(argv[0]);
548  break;
549  default:
550  usage(argv[0]);
551  }
552  }
553  if (argc - optind != 1)
554  usage(argv[0]);
555 
556  if (random_delay > 0)
557  srand(getpid());
558 
559  /*
560  * Translate endpoint address to internal form.
561  */
562  (void) inet_proto_init("protocols", protocols);
563  if (strncmp(argv[optind], "unix:", 5) == 0) {
564  path = argv[optind] + 5;
565  path_len = strlen(path);
566  if (path_len >= (int) sizeof(sun.sun_path))
567  msg_fatal("unix-domain name too long: %s", path);
568  memset((void *) &sun, 0, sizeof(sun));
569  sun.sun_family = AF_UNIX;
570 #ifdef HAS_SUN_LEN
571  sun.sun_len = path_len + 1;
572 #endif
573  memcpy(sun.sun_path, path, path_len);
574  sa = (struct sockaddr *) &sun;
575  sa_length = sizeof(sun);
576  } else {
577  if (strncmp(argv[optind], "inet:", 5) == 0)
578  argv[optind] += 5;
579  buf = mystrdup(argv[optind]);
580  if ((parse_err = host_port(buf, &host, (char *) 0, &port, "628")) != 0)
581  msg_fatal("%s: %s", argv[optind], parse_err);
582  if ((aierr = hostname_to_sockaddr(host, port, SOCK_STREAM, &res)) != 0)
583  msg_fatal("%s: %s", argv[optind], MAI_STRERROR(aierr));
584  myfree(buf);
585  sa = (struct sockaddr *) &ss;
586  if (res->ai_addrlen > sizeof(ss))
587  msg_fatal("address length %d > buffer length %d",
588  (int) res->ai_addrlen, (int) sizeof(ss));
589  memcpy((void *) sa, res->ai_addr, res->ai_addrlen);
590  sa_length = res->ai_addrlen;
591 #ifdef HAS_SA_LEN
592  sa->sa_len = sa_length;
593 #endif
594  freeaddrinfo(res);
595  }
596 
597  /*
598  * Allocate space for temporary buffer.
599  */
600  buffer = vstring_alloc(100);
601 
602  /*
603  * Make sure we have sender and recipient addresses.
604  */
605  if (var_myhostname == 0)
607  if (sender == 0 || recipient == 0) {
608  vstring_sprintf(buffer, "foo@%s", var_myhostname);
609  defaddr = mystrdup(vstring_str(buffer));
610  if (sender == 0)
611  sender = defaddr;
612  if (recipient == 0)
613  recipient = defaddr;
614  }
615 
616  /*
617  * Prepare some results that may be used multiple times: the message
618  * content netstring, the sender netstring, and the recipient netstrings.
619  */
620  mydate = mail_date(time((time_t *) 0));
621  mypid = getpid();
622 
623  message_buffer = vstring_alloc(message_length + 200);
624  vstring_sprintf(buffer,
625  "From: <%s>\nTo: <%s>\nDate: %s\nMessage-Id: <%d@%s>\n\n",
626  sender, recipient, mydate, mypid, var_myhostname);
627  for (n = 1; LEN(buffer) < message_length; n++) {
628  for (i = 0; i < n && i < 79; i++)
629  VSTRING_ADDCH(buffer, 'X');
630  VSTRING_ADDCH(buffer, '\n');
631  }
632  STR(buffer)[message_length - 1] = '\n';
633  netstring_memcpy(message_buffer, STR(buffer), message_length);
634 
635  len = strlen(sender);
636  sender_buffer = vstring_alloc(len);
637  netstring_memcpy(sender_buffer, sender, len);
638 
639  if (recipients == 1) {
640  len = strlen(recipient);
641  recipient_buffer = vstring_alloc(len);
642  netstring_memcpy(recipient_buffer, recipient, len);
643  } else {
644  recipient_buffer = vstring_alloc(100);
645  for (n = 0; n < recipients; n++) {
646  vstring_sprintf(buffer, "%d%s", n, recipient);
647  netstring_memcat(recipient_buffer, STR(buffer), LEN(buffer));
648  }
649  }
650 
651  /*
652  * Start sessions.
653  */
654  while (sessions-- > 0) {
655  session = (SESSION *) mymalloc(sizeof(*session));
656  session->stream = 0;
657  session->xfer_count = 0;
658  session->connect_count = connect_count;
659  session->next = 0;
660  session_count++;
661  startup(session);
662  }
663  for (;;) {
664  event_loop(-1);
665  if (session_count <= 0 && message_count <= 0) {
666  if (count) {
667  VSTREAM_PUTC('\n', VSTREAM_OUT);
669  }
670  exit(0);
671  }
672  }
673 }
int msg_verbose
Definition: msg.c:177
void event_enable_read(int fd, EVENT_NOTIFY_RDWR_FN callback, void *context)
Definition: events.c:729
void myfree(void *ptr)
Definition: mymalloc.c:207
void netstring_fflush(VSTREAM *stream)
Definition: netstring.c:342
void freeaddrinfo(struct addrinfo *ai)
Definition: myaddrinfo.c:742
char * mystrdup(const char *str)
Definition: mymalloc.c:225
const char * mail_date(time_t when)
Definition: mail_date.c:54
#define NETSTRING_ERR_FORMAT
Definition: netstring.h:25
NORETURN msg_panic(const char *fmt,...)
Definition: msg.c:295
VSTRING * netstring_get(VSTREAM *stream, VSTRING *buf, ssize_t limit)
Definition: netstring.c:268
#define vstring_str(vp)
Definition: vstring.h:71
#define VSTREAM_OUT
Definition: vstream.h:67
int sane_connect(int sock, struct sockaddr *sa, SOCKADDR_SIZE len)
Definition: sane_connect.c:44
INET_PROTO_INFO * inet_proto_init(const char *context, const char *protocols)
Definition: inet_proto.c:180
VSTRING * netstring_memcpy(VSTRING *buf, const char *src, ssize_t len)
Definition: netstring.c:351
#define hostname_to_sockaddr(host, serv, sock, res)
Definition: myaddrinfo.h:171
void netstring_setup(VSTREAM *stream, int timeout)
Definition: netstring.c:182
#define INET_PROTO_NAME_ALL
Definition: mail_params.h:992
void event_enable_write(int fd, EVENT_NOTIFY_RDWR_FN callback, void *context)
Definition: events.c:784
#define vstream_setjmp(stream)
Definition: vstream.h:248
int xfer_count
Definition: qmqp-source.c:132
int main(int argc, char **argv)
Definition: qmqp-source.c:462
int valid_hostname(const char *name, int gripe)
#define NETSTRING_ERR_SIZE
Definition: netstring.h:26
#define VSTRING_ADDCH(vp, ch)
Definition: vstring.h:81
#define SOCKOPT_SIZE
Definition: sys_defs.h:1415
int valid_mailhost_literal(const char *addr, int gripe)
VSTRING * netstring_memcat(VSTRING *buf, const char *src, ssize_t len)
Definition: netstring.c:361
int vstream_fclose(VSTREAM *stream)
Definition: vstream.c:1268
void event_loop(int delay)
Definition: events.c:998
VSTREAM * vstream_printf(const char *fmt,...)
Definition: vstream.c:1335
void msg_warn(const char *fmt,...)
Definition: msg.c:215
VSTRING * vstring_alloc(ssize_t len)
Definition: vstring.c:353
#define MAIL_VERSION_STAMP_ALLOCATE
Definition: mail_version.h:67
VSTRING * vstring_sprintf(VSTRING *vp, const char *format,...)
Definition: vstring.c:602
int rcpt_done
Definition: qmqp-source.c:133
void netstring_put_multi(VSTREAM *stream,...)
Definition: netstring.c:295
VSTREAM * stream
Definition: qmqp-source.c:135
void doze(unsigned delay)
Definition: doze.c:44
#define INET_PROTO_NAME_IPV6
Definition: mail_params.h:991
int var_line_limit
Definition: mail_params.c:263
struct SESSION SESSION
NORETURN msg_fatal(const char *fmt,...)
Definition: msg.c:249
MAIL_VERSION_STAMP_DECLARE
Definition: qmqp-source.c:458
int vstream_fflush(VSTREAM *stream)
Definition: vstream.c:1257
int rcpt_count
Definition: qmqp-source.c:134
#define GETOPT(argc, argv, str)
Definition: sys_defs.h:1313
int vstream_tweak_tcp(VSTREAM *)
Definition: vstream_tweak.c:86
#define NETSTRING_ERR_EOF
Definition: netstring.h:23
#define NON_BLOCKING
Definition: iostuff.h:49
int int
Definition: smtpd_proxy.h:21
#define NETSTRING_ERR_TIME
Definition: netstring.h:24
#define LEN(x)
Definition: qmqp-source.c:181
int non_blocking(int, int)
Definition: non_blocking.c:55
const char * host_port(char *buf, char **host, char *def_host, char **port, char *def_service)
Definition: host_port.c:115
time_t event_request_timer(EVENT_NOTIFY_TIME_FN callback, void *context, int delay)
Definition: events.c:894
struct SESSION * next
Definition: qmqp-source.c:137
#define DO_GRIPE
Definition: haproxy_srvr.h:30
#define vstream_fileno(vp)
Definition: vstream.h:115
#define MAI_STRERROR(e)
Definition: myaddrinfo.h:169
void msg_vstream_init(const char *name, VSTREAM *vp)
Definition: msg_vstream.c:77
int connect_count
Definition: qmqp-source.c:136
#define QMQP_STAT_RETRY
Definition: qmqp_proto.h:15
#define VSTREAM_PUTC(ch, vp)
Definition: vstream.h:107
const char * get_hostname(void)
Definition: get_hostname.c:55
char * var_myhostname
Definition: mail_params.c:223
#define QMQP_STAT_OK
Definition: qmqp_proto.h:14
void event_disable_readwrite(int fd)
Definition: events.c:839
#define INET_PROTO_NAME_IPV4
Definition: mail_params.h:990
#define BLOCKING
Definition: iostuff.h:48
#define STR(x)
Definition: qmqp-source.c:180
#define QMQP_STAT_HARD
Definition: qmqp_proto.h:16
#define VSTREAM_ERR
Definition: vstream.h:68
VSTREAM * vstream_fdopen(int fd, int flags)
Definition: vstream.c:1204
void * mymalloc(ssize_t len)
Definition: mymalloc.c:150