Postfix3.3.1
memcache_proto.c
[詳解]
1 /*++
2 /* NAME
3 /* memcache_proto 3
4 /* SUMMARY
5 /* memcache low-level protocol
6 /* SYNOPSIS
7 /* #include <memcache_proto.h>
8 /*
9 /* int memcache_get(fp, buf, len)
10 /* VSTREAM *fp;
11 /* VSTRING *buf;
12 /* ssize_t len;
13 /*
14 /* int memcache_printf(fp, format, ...)
15 /* VSTREAM *fp;
16 /* const char *format;
17 /*
18 /* int memcache_vprintf(fp, format, ap)
19 /* VSTREAM *fp;
20 /* const char *format;
21 /* va_list ap;
22 /*
23 /* int memcache_fread(fp, buf, len)
24 /* VSTREAM *fp;
25 /* VSTRING *buf;
26 /* ssize_t len;
27 /*
28 /* int memcache_fwrite(fp, buf, len)
29 /* VSTREAM *fp;
30 /* const char *buf;
31 /* ssize_t len;
32 /* DESCRIPTION
33 /* This module implements the low-level memcache protocol.
34 /* All functions return -1 on error and 0 on succcess.
35 /* SEE ALSO
36 /* smtp_proto(3) SMTP low-level protocol.
37 /* AUTHOR(S)
38 /* Wietse Venema
39 /* IBM T.J. Watson Research
40 /* P.O. Box 704
41 /* Yorktown Heights, NY 10598, USA
42 /*--*/
43 
44 #include <sys_defs.h>
45 
46 /* Utility library. */
47 
48 #include <msg.h>
49 #include <vstream.h>
50 #include <vstring.h>
51 #include <vstring_vstream.h>
52 #include <compat_va_copy.h>
53 
54 /* Application-specific. */
55 
56 #include <memcache_proto.h>
57 
58 #define STR(x) vstring_str(x)
59 #define LEN(x) VSTRING_LEN(x)
60 
61 /* memcache_get - read one line from peer */
62 
63 int memcache_get(VSTREAM *stream, VSTRING *vp, ssize_t bound)
64 {
65  int last_char;
66  int next_char;
67 
68  last_char = (bound == 0 ? vstring_get(vp, stream) :
69  vstring_get_bound(vp, stream, bound));
70 
71  switch (last_char) {
72 
73  /*
74  * Do some repair in the rare case that we stopped reading in the
75  * middle of the CRLF record terminator.
76  */
77  case '\r':
78  if ((next_char = VSTREAM_GETC(stream)) == '\n') {
79  VSTRING_ADDCH(vp, '\n');
80  /* FALLTRHOUGH */
81  } else {
82  if (next_char != VSTREAM_EOF)
83  vstream_ungetc(stream, next_char);
84 
85  /*
86  * Input too long, or EOF
87  */
88  default:
89  if (msg_verbose)
90  msg_info("%s got %s", VSTREAM_PATH(stream),
91  LEN(vp) < bound ? "EOF" : "input too long");
92  return (-1);
93  }
94 
95  /*
96  * Strip off the record terminator: either CRLF or just bare LF.
97  */
98  case '\n':
99  vstring_truncate(vp, VSTRING_LEN(vp) - 1);
100  if (VSTRING_LEN(vp) > 0 && vstring_end(vp)[-1] == '\r')
101  vstring_truncate(vp, VSTRING_LEN(vp) - 1);
102  VSTRING_TERMINATE(vp);
103  if (msg_verbose)
104  msg_info("%s got: %s", VSTREAM_PATH(stream), STR(vp));
105  return (0);
106  }
107 }
108 
109 /* memcache_fwrite - write one blob to peer */
110 
111 int memcache_fwrite(VSTREAM *stream, const char *cp, ssize_t todo)
112 {
113 
114  /*
115  * Sanity check.
116  */
117  if (todo < 0)
118  msg_panic("memcache_fwrite: negative todo %ld", (long) todo);
119 
120  /*
121  * Do the I/O.
122  */
123  if (msg_verbose)
124  msg_info("%s write: %.*s", VSTREAM_PATH(stream), (int) todo, cp);
125  if (vstream_fwrite(stream, cp, todo) != todo
126  || vstream_fputs("\r\n", stream) == VSTREAM_EOF)
127  return (-1);
128  else
129  return (0);
130 }
131 
132 /* memcache_fread - read one blob from peer */
133 
134 int memcache_fread(VSTREAM *stream, VSTRING *buf, ssize_t todo)
135 {
136 
137  /*
138  * Sanity check.
139  */
140  if (todo < 0)
141  msg_panic("memcache_fread: negative todo %ld", (long) todo);
142 
143  /*
144  * Do the I/O.
145  */
146  VSTRING_SPACE(buf, todo);
147  VSTRING_AT_OFFSET(buf, todo);
148  if (vstream_fread(stream, STR(buf), todo) != todo
149  || VSTREAM_GETC(stream) != '\r'
150  || VSTREAM_GETC(stream) != '\n') {
151  if (msg_verbose)
152  msg_info("%s read: error", VSTREAM_PATH(stream));
153  return (-1);
154  } else {
155  vstring_truncate(buf, todo);
156  VSTRING_TERMINATE(buf);
157  if (msg_verbose)
158  msg_info("%s read: %s", VSTREAM_PATH(stream), STR(buf));
159  return (0);
160  }
161 }
162 
163 /* memcache_vprintf - write one line to peer */
164 
165 int memcache_vprintf(VSTREAM *stream, const char *fmt, va_list ap)
166 {
167 
168  /*
169  * Do the I/O.
170  */
171  vstream_vfprintf(stream, fmt, ap);
172  vstream_fputs("\r\n", stream);
173  if (vstream_ferror(stream))
174  return (-1);
175  else
176  return (0);
177 }
178 
179 /* memcache_printf - write one line to peer */
180 
181 int memcache_printf(VSTREAM *stream, const char *fmt,...)
182 {
183  va_list ap;
184  int ret;
185 
186  va_start(ap, fmt);
187 
188  if (msg_verbose) {
189  VSTRING *buf = vstring_alloc(100);
190  va_list ap2;
191 
192  VA_COPY(ap2, ap);
193  vstring_vsprintf(buf, fmt, ap2);
194  va_end(ap2);
195  msg_info("%s write: %s", VSTREAM_PATH(stream), STR(buf));
196  vstring_free(buf);
197  }
198 
199  /*
200  * Do the I/O.
201  */
202  ret = memcache_vprintf(stream, fmt, ap);
203  va_end(ap);
204  return (ret);
205 }
int msg_verbose
Definition: msg.c:177
int memcache_vprintf(VSTREAM *stream, const char *fmt, va_list ap)
#define VSTREAM_EOF
Definition: vstream.h:110
NORETURN msg_panic(const char *fmt,...)
Definition: msg.c:295
VSTREAM * vstream_vfprintf(VSTREAM *vp, const char *format, va_list ap)
Definition: vstream.c:1531
#define VSTREAM_GETC(vp)
Definition: vstream.h:108
int vstring_get(VSTRING *vp, VSTREAM *fp)
VSTRING * vstring_truncate(VSTRING *vp, ssize_t len)
Definition: vstring.c:415
#define VSTREAM_PATH(vp)
Definition: vstream.h:126
#define LEN(x)
#define VSTRING_LEN(vp)
Definition: vstring.h:72
#define VA_COPY(dest, src)
#define VSTRING_TERMINATE(vp)
Definition: vstring.h:74
int const char * fmt
#define vstring_end(vp)
Definition: vstring.h:73
#define VSTRING_ADDCH(vp, ch)
Definition: vstring.h:81
VSTRING * vstring_vsprintf(VSTRING *vp, const char *format, va_list ap)
Definition: vstring.c:614
#define STR(x)
#define vstream_ungetc(vp, ch)
Definition: vstream.h:109
int memcache_fwrite(VSTREAM *stream, const char *cp, ssize_t todo)
int memcache_printf(VSTREAM *stream, const char *fmt,...)
VSTRING * vstring_alloc(ssize_t len)
Definition: vstring.c:353
#define vstream_fread(v, b, n)
Definition: vstream.h:104
#define vstream_fwrite(v, b, n)
Definition: vstream.h:105
#define VSTRING_SPACE(vp, len)
Definition: vstring.h:70
VSTRING * vstring_free(VSTRING *vp)
Definition: vstring.c:380
int memcache_fread(VSTREAM *stream, VSTRING *buf, ssize_t todo)
#define VSTRING_AT_OFFSET(vp, offset)
Definition: vstring.h:92
int memcache_get(VSTREAM *stream, VSTRING *vp, ssize_t bound)
#define vstream_ferror(vp)
Definition: vstream.h:120
int vstring_get_bound(VSTRING *vp, VSTREAM *fp, ssize_t bound)
int vstream_fputs(const char *str, VSTREAM *stream)
Definition: vstream.c:1360
void msg_info(const char *fmt,...)
Definition: msg.c:199