comparison src/mail/ngx_mail_parse.c @ 5398:04e43d03e153

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 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 Mon, 30 Sep 2013 22:09:57 +0400
parents b6562f98bfd8
children bcb107bb89cd
comparison
equal deleted inserted replaced
5397:ae73d7a4fcde 5398:04e43d03e153
624 { 624 {
625 u_char ch, *p, *c, c0, c1, c2, c3; 625 u_char ch, *p, *c, c0, c1, c2, c3;
626 ngx_str_t *arg; 626 ngx_str_t *arg;
627 enum { 627 enum {
628 sw_start = 0, 628 sw_start = 0,
629 sw_command,
630 sw_invalid,
629 sw_spaces_before_argument, 631 sw_spaces_before_argument,
630 sw_argument, 632 sw_argument,
631 sw_almost_done 633 sw_almost_done
632 } state; 634 } state;
633 635
638 640
639 switch (state) { 641 switch (state) {
640 642
641 /* SMTP command */ 643 /* SMTP command */
642 case sw_start: 644 case sw_start:
645 s->cmd_start = p;
646 state = sw_command;
647
648 /* fall through */
649
650 case sw_command:
643 if (ch == ' ' || ch == CR || ch == LF) { 651 if (ch == ' ' || ch == CR || ch == LF) {
644 c = s->buffer->start; 652 c = s->cmd_start;
645 653
646 if (p - c == 4) { 654 if (p - c == 4) {
647 655
648 c0 = ngx_toupper(c[0]); 656 c0 = ngx_toupper(c[0]);
649 c1 = ngx_toupper(c[1]); 657 c1 = ngx_toupper(c[1]);
717 #endif 725 #endif
718 } else { 726 } else {
719 goto invalid; 727 goto invalid;
720 } 728 }
721 729
730 s->cmd.data = s->cmd_start;
731 s->cmd.len = p - s->cmd_start;
732
722 switch (ch) { 733 switch (ch) {
723 case ' ': 734 case ' ':
724 state = sw_spaces_before_argument; 735 state = sw_spaces_before_argument;
725 break; 736 break;
726 case CR: 737 case CR:
735 if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z')) { 746 if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z')) {
736 goto invalid; 747 goto invalid;
737 } 748 }
738 749
739 break; 750 break;
751
752 case sw_invalid:
753 goto invalid;
740 754
741 case sw_spaces_before_argument: 755 case sw_spaces_before_argument:
742 switch (ch) { 756 switch (ch) {
743 case ' ': 757 case ' ':
744 break; 758 break;
822 836
823 return NGX_OK; 837 return NGX_OK;
824 838
825 invalid: 839 invalid:
826 840
827 s->state = sw_start; 841 s->state = sw_invalid;
828 s->arg_start = NULL; 842 s->arg_start = NULL;
843
844 /* skip invalid command till LF */
845
846 for (p = s->buffer->pos; p < s->buffer->last; p++) {
847 if (*p == LF) {
848 s->state = sw_start;
849 p++;
850 break;
851 }
852 }
853
854 s->buffer->pos = p;
829 855
830 return NGX_MAIL_PARSE_INVALID_COMMAND; 856 return NGX_MAIL_PARSE_INVALID_COMMAND;
831 } 857 }
832 858
833 859