Mercurial > hg > nginx
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 |