comparison src/context.cpp @ 314:ef5a6099cbe7 stable-6-0-46

enable smtp verify logging
author Carl Byington <carl@five-ten-sg.com>
date Mon, 19 Sep 2016 13:15:02 -0700
parents f5547e7b3a09
children f7c5cfb76e86
comparison
equal deleted inserted replaced
313:68af9ca42ead 314:ef5a6099cbe7
90 const time_t ERROR_SMTP_SOCKET_TIME = 600; // number of seconds between attempts to open a socket to an smtp server 90 const time_t ERROR_SMTP_SOCKET_TIME = 600; // number of seconds between attempts to open a socket to an smtp server
91 91
92 92
93 int SMTP::writer() { 93 int SMTP::writer() {
94 #ifdef VERIFY_DEBUG 94 #ifdef VERIFY_DEBUG
95 log("writer() sees buffer with %s", buffer); 95 log("writer(%d) sees buffer with %s", buffer);
96 log("writer() sees error %d", (int)error); 96 log("writer(%d) sees error %d", (int)error);
97 #endif 97 #endif
98 int rs = 0; 98 int rs = 0;
99 if (!error) { 99 if (!error) {
100 int len = strlen(buffer); 100 int len = strlen(buffer);
101 while (rs < len) { 101 while (rs < len) {
117 117
118 int SMTP::reader() { 118 int SMTP::reader() {
119 // read some bytes terminated by lf or end of buffer. 119 // read some bytes terminated by lf or end of buffer.
120 // we may have a multi line response or part thereof in the buffer. 120 // we may have a multi line response or part thereof in the buffer.
121 #ifdef VERIFY_DEBUG 121 #ifdef VERIFY_DEBUG
122 log("reader() sees error %d", (int)error); 122 log("reader(%d) sees error %d", (int)error);
123 #endif 123 #endif
124 if (error) return 0; 124 if (error) return 0;
125 int len = maxlen-1; // room for null terminator 125 int len = maxlen-1; // room for null terminator
126 while (pending < len) { 126 while (pending < len) {
127 int ws = read(fd, buffer+pending, len-pending); 127 int ws = read(fd, buffer+pending, len-pending);
136 break; 136 break;
137 } 137 }
138 } 138 }
139 buffer[pending] = '\0'; 139 buffer[pending] = '\0';
140 #ifdef VERIFY_DEBUG 140 #ifdef VERIFY_DEBUG
141 log("reader() sees buffer with %s", buffer); 141 log("reader(%d) sees buffer with %s", buffer);
142 #endif 142 #endif
143 return pending; 143 return pending;
144 } 144 }
145 145
146 146
165 pending = 0; 165 pending = 0;
166 buffer[pending] = '\0'; 166 buffer[pending] = '\0';
167 while (true) { 167 while (true) {
168 int r = read_line(); 168 int r = read_line();
169 #ifdef VERIFY_DEBUG 169 #ifdef VERIFY_DEBUG
170 log("read_response() sees line with %s", buffer); 170 log("read_response(%d) sees line with %s", buffer);
171 log("read_response() sees line length %d", r); 171 log("read_response(%d) sees line length %d", r);
172 #endif 172 #endif
173 if (r == 0) return 0; // failed to read any bytes 173 if (r == 0) return 0; // failed to read any bytes
174 if ((r > 4) && (buffer[3] == '-')) { 174 if ((r > 4) && (buffer[3] == '-')) {
175 flush_line(r); 175 flush_line(r);
176 continue; 176 continue;
177 } 177 }
178 log("read_response() sees line with %s", buffer); 178 log("verify::read_response(%d) sees line with %s", buffer);
179 return atoi(buffer); 179 return atoi(buffer);
180 } 180 }
181 return 0; 181 return 0;
182 } 182 }
183 183
248 } 248 }
249 249
250 250
251 void SMTP::log(const char *m, int v) { 251 void SMTP::log(const char *m, int v) {
252 char buf[maxlen]; 252 char buf[maxlen];
253 snprintf(buf, maxlen, m, v); 253 snprintf(buf, maxlen, m, get_fd(), v);
254 my_syslog(queueid, buf); 254 my_syslog(queueid, buf);
255 } 255 }
256 256
257 257
258 void SMTP::log(const char *m, const char *v) { 258 void SMTP::log(const char *m, const char *v) {
259 char buf[maxlen]; 259 char buf[maxlen];
260 snprintf(buf, maxlen, m, v); 260 snprintf(buf, maxlen, m, get_fd(), v);
261 my_syslog(queueid, buf); 261 my_syslog(queueid, buf);
262 } 262 }
263 263
264 264
265 //////////////////////////////////////////////// 265 ////////////////////////////////////////////////
294 } 294 }
295 pthread_mutex_unlock(&mutex); 295 pthread_mutex_unlock(&mutex);
296 // avoid doing this work inside the mutex lock 296 // avoid doing this work inside the mutex lock
297 if (conn) { 297 if (conn) {
298 #ifdef VERIFY_DEBUG 298 #ifdef VERIFY_DEBUG
299 conn->log("closer() closes ancient %d", conn->get_fd()); 299 conn->log("closer(%d) closes ancient socket %s", "");
300 #endif 300 #endif
301 delete conn; 301 delete conn;
302 } 302 }
303 } 303 }
304 } 304 }
305 305
306 306
307 SMTP* VERIFY::get_connection(const char *queueid) { 307 SMTP* VERIFY::get_connection(const char *queueid) {
308 SMTP *conn = NULL; 308 SMTP *conn = NULL;
309 pthread_mutex_lock(&mutex); 309 pthread_mutex_lock(&mutex);
310 if (!connections.empty()) { 310 while (!connections.empty()) {
311 conn = connections.front(); 311 conn = connections.front();
312 conn->set_id(queueid); 312 time_t now = time(NULL);
313 connections.pop_front(); 313 if ((now - conn->get_stamp()) > maxsmtp_age) {
314 #ifdef VERIFY_DEBUG 314 // this connection is ancient, remove it
315 conn->log("get_connection() %d from cache", conn->get_fd()); 315 conn->log("verify::get_connection(%d) closes ancient socket %s", "");
316 #endif 316 connections.pop_front();
317 delete conn;
318 conn = NULL;
319 }
320 else {
321 conn->set_id(queueid);
322 connections.pop_front();
323 #ifdef VERIFY_DEBUG
324 conn->log("verify::get_connection(%d) from cache %s", "");
325 #endif
326 break;
327 }
317 } 328 }
318 pthread_mutex_unlock(&mutex); 329 pthread_mutex_unlock(&mutex);
319 if (conn) return conn; 330 if (conn) return conn;
320 int sock = NULL_SOCKET; 331 int sock = NULL_SOCKET;
321 if ((time(NULL) - last_err) > ERROR_SMTP_SOCKET_TIME) { 332 if ((time(NULL) - last_err) > ERROR_SMTP_SOCKET_TIME) {
339 else last_err = time(NULL); 350 else last_err = time(NULL);
340 } 351 }
341 else last_err = time(NULL); 352 else last_err = time(NULL);
342 } 353 }
343 if (sock != NULL_SOCKET) { 354 if (sock != NULL_SOCKET) {
355 struct timeval tv;
356 tv.tv_sec = 15;
357 tv.tv_usec = 0;
358 setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval));
344 conn = new SMTP(sock); 359 conn = new SMTP(sock);
345 conn->set_id(queueid); 360 conn->set_id(queueid);
346 #ifdef VERIFY_DEBUG 361 #ifdef VERIFY_DEBUG
347 conn->log("get_connection() %d new socket", conn->get_fd()); 362 conn->log("get_connection(%d) new socket %s", "");
348 #endif 363 #endif
349 int rc = conn->helo(); 364 int rc = conn->helo();
350 conn->log("verify::get_connection() helo sees %d", rc); 365 conn->log("verify::get_connection(%d) helo sees %d", rc);
351 if (rc == 250) return conn; 366 if (rc == 250) return conn;
352 delete conn; 367 delete conn;
353 } 368 }
354 return NULL; 369 return NULL;
355 } 370 }
356 371
357 372
358 void VERIFY::put_connection(SMTP *conn) { 373 void VERIFY::put_connection(SMTP *conn) {
359 if (conn->err()) { 374 if (conn->err()) {
360 #ifdef VERIFY_DEBUG 375 #ifdef VERIFY_DEBUG
361 conn->log("put_socket() %d with error, close it", conn->get_fd()); 376 conn->log("put_socket(%d) with error %s", "");
362 #endif 377 #endif
363 delete conn; 378 delete conn;
364 last_err = time(NULL);
365 } 379 }
366 else { 380 else {
367 #ifdef VERIFY_DEBUG 381 #ifdef VERIFY_DEBUG
368 conn->log("put_socket() %d", conn->get_fd()); 382 conn->log("put_socket(%d) no error %s", "");
369 #endif 383 #endif
370 conn->now(); 384 conn->now();
371 pthread_mutex_lock(&mutex); 385 pthread_mutex_lock(&mutex);
372 connections.push_back(conn); 386 connections.push_back(conn);
373 pthread_mutex_unlock(&mutex); 387 pthread_mutex_unlock(&mutex);
379 if (host == token_myhostname) return true; 393 if (host == token_myhostname) return true;
380 SMTP *conn = get_connection(queueid); 394 SMTP *conn = get_connection(queueid);
381 if (!conn) return true; // cannot verify right now, we have socket errors 395 if (!conn) return true; // cannot verify right now, we have socket errors
382 int rc; 396 int rc;
383 rc = conn->from(from); 397 rc = conn->from(from);
384 conn->log("verify::ok() from sees %d", rc); 398 conn->log("verify::ok(%d) from sees %d", rc);
385 if (rc != 250) { 399 if (rc != 250) {
386 put_connection(conn); 400 put_connection(conn);
387 return (rc >= 500) ? false : true; 401 return (rc >= 500) ? false : true;
388 } 402 }
389 rc = conn->rcpt(to); 403 rc = conn->rcpt(to);
390 conn->log("verify::ok() rcpt sees %d", rc); 404 conn->log("verify::ok(%d) rcpt sees %d", rc);
391 put_connection(conn); 405 put_connection(conn);
392 return (rc >= 500) ? false : true; 406 return (rc >= 500) ? false : true;
393 } 407 }
394 408
395 409