comparison src/mail/ngx_mail_smtp_handler.c @ 436:9b19e26b2660

Mail: smtp pipelining support. Basically, this does the following two changes (and corresponding modifications of related code): 1. Does not reset session buffer unless it's reached it's end, and always wait for LF to terminate command (even if we detected invalid command). 2. Record command name as the first argument to make it available for handlers (since now we can't assume that command starts from s->buffer->start).
author Maxim Dounin <mdounin@mdounin.ru>
date Thu, 11 Sep 2008 15:26:25 +0400
parents e2df123bbbe2
children d67e93e97b4a
comparison
equal deleted inserted replaced
435:e2df123bbbe2 436:9b19e26b2660
465 rc = ngx_mail_auth_cram_md5(s, c); 465 rc = ngx_mail_auth_cram_md5(s, c);
466 break; 466 break;
467 } 467 }
468 } 468 }
469 469
470 if (s->buffer->pos < s->buffer->last) {
471 s->blocked = 1;
472 }
473
470 switch (rc) { 474 switch (rc) {
471 475
472 case NGX_DONE: 476 case NGX_DONE:
473 ngx_mail_auth(s, c); 477 ngx_mail_auth(s, c);
474 return; 478 return;
486 490
487 /* fall through */ 491 /* fall through */
488 492
489 case NGX_OK: 493 case NGX_OK:
490 s->args.nelts = 0; 494 s->args.nelts = 0;
491 s->buffer->pos = s->buffer->start; 495
492 s->buffer->last = s->buffer->start; 496 if (s->buffer->pos == s->buffer->last) {
497 s->buffer->pos = s->buffer->start;
498 s->buffer->last = s->buffer->start;
499 }
493 500
494 if (s->state) { 501 if (s->state) {
495 s->arg_start = s->buffer->start; 502 s->arg_start = s->buffer->pos;
496 } 503 }
497 504
498 ngx_mail_send(c->write); 505 ngx_mail_send(c->write);
499 } 506 }
500 } 507 }
504 ngx_mail_smtp_helo(ngx_mail_session_t *s, ngx_connection_t *c) 511 ngx_mail_smtp_helo(ngx_mail_session_t *s, ngx_connection_t *c)
505 { 512 {
506 ngx_str_t *arg; 513 ngx_str_t *arg;
507 ngx_mail_smtp_srv_conf_t *sscf; 514 ngx_mail_smtp_srv_conf_t *sscf;
508 515
509 if (s->args.nelts != 1) { 516 if (s->args.nelts != 2) {
510 s->out.len = sizeof(smtp_invalid_argument) - 1; 517 s->out.len = sizeof(smtp_invalid_argument) - 1;
511 s->out.data = smtp_invalid_argument; 518 s->out.data = smtp_invalid_argument;
512 s->state = 0; 519 s->state = 0;
513 return NGX_OK; 520 return NGX_OK;
514 } 521 }
515 522
516 arg = s->args.elts; 523 arg = s->args.elts;
517 524
518 s->smtp_helo.len = arg[0].len; 525 s->smtp_helo.len = arg[1].len;
519 526
520 s->smtp_helo.data = ngx_pnalloc(c->pool, arg[0].len); 527 s->smtp_helo.data = ngx_pnalloc(c->pool, arg[1].len);
521 if (s->smtp_helo.data == NULL) { 528 if (s->smtp_helo.data == NULL) {
522 return NGX_ERROR; 529 return NGX_ERROR;
523 } 530 }
524 531
525 ngx_memcpy(s->smtp_helo.data, arg[0].data, arg[0].len); 532 ngx_memcpy(s->smtp_helo.data, arg[1].data, arg[1].len);
526 533
527 s->smtp_from.len = 0; 534 s->smtp_from.len = 0;
528 s->smtp_from.data = NULL; 535 s->smtp_from.data = NULL;
529 s->smtp_to.len = 0; 536 s->smtp_to.len = 0;
530 s->smtp_to.data = NULL; 537 s->smtp_to.data = NULL;
574 if (ngx_mail_starttls_only(s, c)) { 581 if (ngx_mail_starttls_only(s, c)) {
575 return NGX_MAIL_PARSE_INVALID_COMMAND; 582 return NGX_MAIL_PARSE_INVALID_COMMAND;
576 } 583 }
577 #endif 584 #endif
578 585
579 if (s->args.nelts == 0) { 586 if (s->args.nelts < 2) {
580 s->out.len = sizeof(smtp_invalid_argument) - 1; 587 s->out.len = sizeof(smtp_invalid_argument) - 1;
581 s->out.data = smtp_invalid_argument; 588 s->out.data = smtp_invalid_argument;
582 s->state = 0; 589 s->state = 0;
583 return NGX_OK; 590 return NGX_OK;
584 } 591 }
632 639
633 640
634 static ngx_int_t 641 static ngx_int_t
635 ngx_mail_smtp_mail(ngx_mail_session_t *s, ngx_connection_t *c) 642 ngx_mail_smtp_mail(ngx_mail_session_t *s, ngx_connection_t *c)
636 { 643 {
637 u_char ch; 644 ngx_str_t *arg, *end, cmd;
638 ngx_str_t l;
639 ngx_uint_t i;
640 ngx_mail_smtp_srv_conf_t *sscf; 645 ngx_mail_smtp_srv_conf_t *sscf;
641 646
642 sscf = ngx_mail_get_module_srv_conf(s, ngx_mail_smtp_module); 647 sscf = ngx_mail_get_module_srv_conf(s, ngx_mail_smtp_module);
643 648
644 if (!(sscf->auth_methods & NGX_MAIL_AUTH_NONE_ENABLED)) { 649 if (!(sscf->auth_methods & NGX_MAIL_AUTH_NONE_ENABLED)) {
657 s->out.len = sizeof(smtp_bad_sequence) - 1; 662 s->out.len = sizeof(smtp_bad_sequence) - 1;
658 s->out.data = smtp_bad_sequence; 663 s->out.data = smtp_bad_sequence;
659 return NGX_OK; 664 return NGX_OK;
660 } 665 }
661 666
662 l.len = s->buffer->last - s->buffer->start; 667 arg = s->args.elts;
663 l.data = s->buffer->start; 668 end = arg + s->args.nelts - 1;
664 669
665 for (i = 0; i < l.len; i++) { 670 cmd.len = end->data + end->len - arg->data;
666 ch = l.data[i]; 671 cmd.data = arg->data;
667 672
668 if (ch != CR && ch != LF) { 673 s->smtp_from.len = cmd.len;
669 continue; 674
670 } 675 s->smtp_from.data = ngx_palloc(c->pool, cmd.len);
671
672 l.data[i] = ' ';
673 }
674
675 while (i) {
676 if (l.data[i - 1] != ' ') {
677 break;
678 }
679
680 i--;
681 }
682
683 l.len = i;
684
685 s->smtp_from.len = l.len;
686
687 s->smtp_from.data = ngx_palloc(c->pool, l.len);
688 if (s->smtp_from.data == NULL) { 676 if (s->smtp_from.data == NULL) {
689 return NGX_ERROR; 677 return NGX_ERROR;
690 } 678 }
691 679
692 ngx_memcpy(s->smtp_from.data, l.data, l.len); 680 ngx_memcpy(s->smtp_from.data, cmd.data, cmd.len);
693 681
694 s->out.len = sizeof(smtp_ok) - 1; 682 s->out.len = sizeof(smtp_ok) - 1;
695 s->out.data = smtp_ok; 683 s->out.data = smtp_ok;
696 684
697 return NGX_OK; 685 return NGX_OK;
699 687
700 688
701 static ngx_int_t 689 static ngx_int_t
702 ngx_mail_smtp_rcpt(ngx_mail_session_t *s, ngx_connection_t *c) 690 ngx_mail_smtp_rcpt(ngx_mail_session_t *s, ngx_connection_t *c)
703 { 691 {
704 u_char ch; 692 ngx_str_t *arg, *end, cmd;
705 ngx_str_t l;
706 ngx_uint_t i;
707 693
708 if (s->smtp_from.len == 0) { 694 if (s->smtp_from.len == 0) {
709 s->out.len = sizeof(smtp_bad_sequence) - 1; 695 s->out.len = sizeof(smtp_bad_sequence) - 1;
710 s->out.data = smtp_bad_sequence; 696 s->out.data = smtp_bad_sequence;
711 return NGX_OK; 697 return NGX_OK;
712 } 698 }
713 699
714 l.len = s->buffer->last - s->buffer->start; 700 arg = s->args.elts;
715 l.data = s->buffer->start; 701 end = arg + s->args.nelts - 1;
716 702
717 for (i = 0; i < l.len; i++) { 703 cmd.len = end->data + end->len - arg->data;
718 ch = l.data[i]; 704 cmd.data = arg->data;
719 705
720 if (ch != CR && ch != LF) { 706 s->smtp_to.len = cmd.len;
721 continue; 707
722 } 708 s->smtp_to.data = ngx_palloc(c->pool, cmd.len);
723
724 l.data[i] = ' ';
725 }
726
727 while (i) {
728 if (l.data[i - 1] != ' ') {
729 break;
730 }
731
732 i--;
733 }
734
735 l.len = i;
736
737 s->smtp_to.len = l.len;
738
739 s->smtp_to.data = ngx_palloc(c->pool, l.len);
740 if (s->smtp_to.data == NULL) { 709 if (s->smtp_to.data == NULL) {
741 return NGX_ERROR; 710 return NGX_ERROR;
742 } 711 }
743 712
744 ngx_memcpy(s->smtp_to.data, l.data, l.len); 713 ngx_memcpy(s->smtp_to.data, cmd.data, cmd.len);
745 714
746 s->auth_method = NGX_MAIL_AUTH_NONE; 715 s->auth_method = NGX_MAIL_AUTH_NONE;
747 716
748 return NGX_DONE; 717 return NGX_DONE;
749 } 718 }