Index: trunk/willow/src/willow/whttp_entity.cc |
— | — | @@ -62,6 +62,9 @@ |
63 | 63 | #include <ctype.h> |
64 | 64 | #include <zlib.h> |
65 | 65 | |
| 66 | +#include <vector> |
| 67 | +using std::vector; |
| 68 | + |
66 | 69 | #include "willow.h" |
67 | 70 | #include "whttp.h" |
68 | 71 | #include "whttp_entity.h" |
— | — | @@ -175,6 +178,7 @@ |
176 | 179 | entity_send(fde *fde, http_entity *entity, header_cb cb, void *data, int flags) |
177 | 180 | { |
178 | 181 | struct header_list *hl; |
| 182 | +vector<header *>::iterator vit, vend; |
179 | 183 | int window = 15; |
180 | 184 | |
181 | 185 | errno = 0; |
— | — | @@ -212,7 +216,7 @@ |
213 | 217 | } |
214 | 218 | |
215 | 219 | if (flags & ENT_CHUNKED_OKAY) { |
216 | | - struct header_list *contlen; |
| 220 | + struct header *contlen; |
217 | 221 | entity->he_flags.chunked = 1; |
218 | 222 | if (!entity->he_h_transfer_encoding) |
219 | 223 | header_add(&entity->he_headers, wstrdup("Transfer-Encoding"), wstrdup("chunked")); |
— | — | @@ -238,8 +242,9 @@ |
239 | 243 | } |
240 | 244 | header_add(&entity->he_headers, wstrdup("Content-Encoding"), |
241 | 245 | wstrdup(ent_encodings[entity->he_encoding])); |
242 | | - for (hl = entity->he_headers.hl_next; hl; hl = hl->hl_next) |
243 | | - evbuffer_add_printf(entity->_he_tobuf->output, "%s: %s\r\n", hl->hl_name, hl->hl_value); |
| 246 | + for (vit = entity->he_headers.hl_hdrs.begin(), vend = entity->he_headers.hl_hdrs.end(); |
| 247 | + vit != vend; ++vit) |
| 248 | + evbuffer_add_printf(entity->_he_tobuf->output, "%s: %s\r\n", (*vit)->hr_name, (*vit)->hr_value); |
244 | 249 | bufferevent_write(entity->_he_tobuf, const_cast<char *>("\r\n"), 2); |
245 | 250 | } |
246 | 251 | |
— | — | @@ -739,17 +744,14 @@ |
740 | 745 | void |
741 | 746 | header_free(header_list *head) |
742 | 747 | { |
743 | | -struct header_list *next = head->hl_next; |
744 | | - |
745 | | - while (next) { |
746 | | - struct header_list *here = next; |
747 | | - next = here->hl_next; |
748 | | - wfree((char *)here->hl_name); |
749 | | - wfree((char *)here->hl_value); |
750 | | - wfree(here); |
| 748 | +vector<header *>::iterator vit, vend; |
| 749 | + for (vit = head->hl_hdrs.begin(), vend = head->hl_hdrs.end(); vit != vend; ++vit) { |
| 750 | + wfree((*vit)->hr_name); |
| 751 | + wfree((*vit)->hr_value); |
| 752 | + delete *vit; |
751 | 753 | } |
752 | | - |
753 | | - bzero(head, sizeof(*head)); |
| 754 | + head->hl_hdrs.clear(); |
| 755 | + head->hl_len = 0; |
754 | 756 | } |
755 | 757 | |
756 | 758 | #ifdef __lint |
— | — | @@ -759,67 +761,42 @@ |
760 | 762 | void |
761 | 763 | header_add(header_list *head, char *name, char *value) |
762 | 764 | { |
763 | | -struct header_list *n = head; |
764 | | - |
765 | | - head->hl_num++; |
766 | | - |
767 | | - if (head->hl_tail) |
768 | | - n = head->hl_tail; |
769 | | - else |
770 | | - while (n->hl_next) |
771 | | - n = n->hl_next; |
772 | | - n->hl_next = (header_list *)wmalloc(sizeof(*head->hl_next)); |
773 | | - head->hl_tail = n->hl_next; |
774 | | - head->hl_len += strlen(name) + strlen(value) + 4; |
775 | | - n = n->hl_next; |
776 | | - n->hl_name = name; |
777 | | - n->hl_value = value; |
778 | | - n->hl_next = n->hl_tail = NULL; |
779 | | - n->hl_flags = 0; |
| 765 | + head->append(new header(name, value)); |
780 | 766 | } |
781 | 767 | |
782 | 768 | void |
783 | 769 | header_append_last(header_list *head, const char *append) |
784 | 770 | { |
785 | | -struct header_list *last = head; |
786 | | - char *cur; |
787 | | - |
788 | | - assert(last->hl_next); |
789 | | - |
790 | | - while (last->hl_next) |
791 | | - last = last->hl_next; |
792 | | - |
793 | | - cur = last->hl_value; |
794 | | - last->hl_value = (char *)wmalloc(strlen(cur) + 1 + strlen(append) + 1); |
795 | | - sprintf(last->hl_value, "%s %s", cur, append); |
796 | | - wfree(cur); |
| 771 | +header *last; |
| 772 | +char *tmp; |
| 773 | + last = *head->hl_hdrs.rbegin(); |
| 774 | + tmp = last->hr_value; |
| 775 | + last->hr_value = (char *)wmalloc(strlen(tmp) + strlen(append) + 2); |
| 776 | + sprintf(last->hr_value, "%s %s", tmp, append); |
| 777 | + wfree(tmp); |
797 | 778 | } |
798 | | - |
799 | 779 | |
800 | 780 | void |
801 | | -header_remove(header_list *head, header_list *it) |
| 781 | +header_remove(header_list *head, header *it) |
802 | 782 | { |
803 | | -struct header_list *jt; |
| 783 | +vector<header *>::iterator vit; |
| 784 | + if ((vit = std::find(head->hl_hdrs.begin(), head->hl_hdrs.end(), it)) == head->hl_hdrs.end()) |
| 785 | + return; |
| 786 | + wfree((*vit)->hr_name); |
| 787 | + wfree((*vit)->hr_value); |
| 788 | + delete *vit; |
804 | 789 | |
805 | | - jt = head; |
806 | | - while (jt->hl_next && jt->hl_next != it) |
807 | | - jt = jt->hl_next; |
808 | | - jt->hl_next = jt->hl_next->hl_next; |
809 | | - if (it == head->hl_tail) |
810 | | - head->hl_tail = jt; |
811 | | - wfree(it->hl_name); |
812 | | - wfree(it->hl_value); |
813 | | - wfree(it); |
| 790 | + std::swap(*vit, *head->hl_hdrs.rbegin()); |
| 791 | + head->hl_hdrs.pop_back(); |
814 | 792 | } |
815 | 793 | |
816 | | -struct header_list * |
| 794 | +struct header * |
817 | 795 | header_find(header_list *head, const char *name) |
818 | 796 | { |
819 | | -struct header_list *it; |
820 | | - |
821 | | - for (it = head->hl_next; it; it = it->hl_next) |
822 | | - if (!strcasecmp(name, it->hl_name)) |
823 | | - return it; |
| 797 | +vector<header *>::iterator vit, vend; |
| 798 | + for (vit = head->hl_hdrs.begin(), vend = head->hl_hdrs.end(); vit != vend; ++vit) |
| 799 | + if (!strcasecmp(name, (*vit)->hr_name)) |
| 800 | + return *vit; |
824 | 801 | return NULL; |
825 | 802 | } |
826 | 803 | |
— | — | @@ -829,19 +806,18 @@ |
830 | 807 | char * |
831 | 808 | header_build(header_list *head) |
832 | 809 | { |
833 | | - char *buf; |
834 | | - size_t bufsz; |
835 | | - size_t buflen = 0; |
| 810 | +char *buf; |
| 811 | +size_t bufsz; |
| 812 | +size_t buflen = 0; |
| 813 | +vector<header *>::iterator vit, vend; |
836 | 814 | |
837 | 815 | bufsz = head->hl_len + 3; |
838 | 816 | if ((buf = (char *)wmalloc(bufsz)) == NULL) |
839 | 817 | outofmemory(); |
840 | 818 | |
841 | 819 | *buf = '\0'; |
842 | | - while (head->hl_next) { |
843 | | - head = head->hl_next; |
844 | | - buflen += snprintf(buf + buflen, bufsz - buflen - 1, "%s: %s\r\n", head->hl_name, head->hl_value); |
845 | | - } |
| 820 | + for (vit = head->hl_hdrs.begin(), vend = head->hl_hdrs.end(); vit != vend; ++vit) |
| 821 | + buflen += snprintf(buf + buflen, bufsz - buflen - 1, "%s: %s\r\n", (*vit)->hr_name, (*vit)->hr_value); |
846 | 822 | if (strlcat(buf, "\r\n", bufsz) >= bufsz) |
847 | 823 | abort(); |
848 | 824 | |
— | — | @@ -854,26 +830,19 @@ |
855 | 831 | void |
856 | 832 | header_dump(header_list *head, int fd) |
857 | 833 | { |
858 | | - int i = 0; |
859 | | -struct header_list *h; |
860 | | - |
861 | | - h = head->hl_next; |
862 | | - while (h) { |
863 | | - h = h->hl_next; |
864 | | - ++i; |
865 | | - } |
866 | | - |
| 834 | +vector<header *>::iterator vit, vend; |
| 835 | +int i = 0; |
| 836 | + i = head->hl_hdrs.size(); |
867 | 837 | write(fd, &i, sizeof(i)); |
868 | | - |
869 | | - while (head->hl_next) { |
| 838 | + |
| 839 | + for (vit = head->hl_hdrs.begin(), vend = head->hl_hdrs.end(); vit != vend; ++vit) { |
870 | 840 | int j, k; |
871 | | - head = head->hl_next; |
872 | | - k = strlen(head->hl_name); |
| 841 | + k = strlen((*vit)->hr_name); |
873 | 842 | write(fd, &k, sizeof(k)); |
874 | | - j = strlen(head->hl_value); |
| 843 | + j = strlen((*vit)->hr_value); |
875 | 844 | write(fd, &j, sizeof(j)); |
876 | | - write(fd, head->hl_name, k); |
877 | | - write(fd, head->hl_value, j); |
| 845 | + write(fd, (*vit)->hr_name, k); |
| 846 | + write(fd, (*vit)->hr_value, j); |
878 | 847 | } |
879 | 848 | } |
880 | 849 | |
— | — | @@ -881,11 +850,10 @@ |
882 | 851 | header_undump(header_list *head, int fd, off_t *len) |
883 | 852 | { |
884 | 853 | int i = 0, j = 0, sz = 0; |
885 | | -struct header_list *it = head; |
886 | 854 | ssize_t r; |
887 | 855 | |
888 | 856 | *len = 0; |
889 | | - bzero(head, sizeof(*head)); |
| 857 | + head->hl_hdrs.clear(); |
890 | 858 | if ((r = read(fd, &sz, sizeof(sz))) < 0) { |
891 | 859 | wlog(WLOG_WARNING, "reading cache file: %s", strerror(errno)); |
892 | 860 | return -1; /* XXX */ |
— | — | @@ -895,12 +863,9 @@ |
896 | 864 | WDEBUG((WLOG_DEBUG, "header_undump: %d entries", sz)); |
897 | 865 | |
898 | 866 | while (sz--) { |
899 | | - char *n, *v, *s; |
900 | | - int k; |
901 | | - |
902 | | - if ((it->hl_next = (header_list *)wcalloc(1, sizeof(struct header_list))) == NULL) |
903 | | - outofmemory(); |
904 | | - it = it->hl_next; |
| 867 | + char *n, *v, *s; |
| 868 | + int k; |
| 869 | + header *h; |
905 | 870 | *len += read(fd, &i, sizeof(i)); |
906 | 871 | *len += read(fd, &j, sizeof(j)); |
907 | 872 | WDEBUG((WLOG_DEBUG, "header_undump: i=%d j=%d", i, j)); |
— | — | @@ -914,12 +879,10 @@ |
915 | 880 | *len += k; |
916 | 881 | s += k; |
917 | 882 | *s = '\0'; |
918 | | - it->hl_name = n; |
919 | | - it->hl_value = wstrdup(v); |
920 | | - head->hl_len += i + j + 4; |
| 883 | + h = new header(n, wstrdup(v)); |
| 884 | + head->append(h); |
921 | 885 | } |
922 | 886 | |
923 | | - head->hl_tail = it; |
924 | 887 | return 0; |
925 | 888 | } |
926 | 889 | |
— | — | @@ -959,7 +922,7 @@ |
960 | 923 | case ENTITY_STATE_HDR: |
961 | 924 | if (isspace(*line)) { |
962 | 925 | char *s = line; |
963 | | - if (!entity->he_headers.hl_next) { |
| 926 | + if (!entity->he_headers.hl_hdrs.size()) { |
964 | 927 | error = ENT_ERR_INVHDR; |
965 | 928 | goto error; |
966 | 929 | } |
— | — | @@ -985,7 +948,7 @@ |
986 | 949 | WDEBUG((WLOG_DEBUG, "header: from [%s], [%s] = [%s]", |
987 | 950 | line, hdr[0], value)); |
988 | 951 | |
989 | | - if (++entity->he_headers.hl_num > MAX_HEADERS) { |
| 952 | + if (entity->he_headers.hl_hdrs.size() > MAX_HEADERS) { |
990 | 953 | error = ENT_ERR_2MANY; |
991 | 954 | goto error; |
992 | 955 | } |
Index: trunk/willow/src/willow/whttp.cc |
— | — | @@ -371,7 +371,8 @@ |
372 | 372 | proxy_start_backend(backend *backend, fde *e, void *data) |
373 | 373 | { |
374 | 374 | struct http_client *client = (http_client *)data; |
375 | | -struct header_list *it; |
| 375 | +struct header *hdr; |
| 376 | +vector<header *>::iterator it, end; |
376 | 377 | int error = 0; |
377 | 378 | socklen_t len = sizeof(error); |
378 | 379 | |
— | — | @@ -394,10 +395,11 @@ |
395 | 396 | return; |
396 | 397 | } |
397 | 398 | |
398 | | - for (it = client->cl_entity.he_headers.hl_next; it; it = it->hl_next) { |
399 | | - if (removable_header(it->hl_name)) { |
400 | | - header_remove(&client->cl_entity.he_headers, it); |
401 | | - it = client->cl_entity.he_headers.hl_next; |
| 399 | + for (it = client->cl_entity.he_headers.hl_hdrs.begin(), |
| 400 | + end = client->cl_entity.he_headers.hl_hdrs.end(); |
| 401 | + it != end; ++it) { |
| 402 | + if (removable_header((*it)->hr_name)) { |
| 403 | + header_remove(&client->cl_entity.he_headers, *it); |
402 | 404 | continue; |
403 | 405 | } |
404 | 406 | } |
— | — | @@ -585,8 +587,8 @@ |
586 | 588 | } |
587 | 589 | |
588 | 590 | if (client->cl_co) { |
589 | | - int complete = (res != -1); |
590 | | - struct header_list *hdr; |
| 591 | + int complete = (res != -1); |
| 592 | + struct header *hdr; |
591 | 593 | |
592 | 594 | /* |
593 | 595 | * The server may have indicated that we shouldn't cache this document. |
— | — | @@ -598,7 +600,7 @@ |
599 | 601 | */ |
600 | 602 | hdr = header_find(&client->cl_entity.he_headers, "Pragma"); |
601 | 603 | if (hdr) { |
602 | | - char **pragmas = wstrvec(hdr->hl_value, ",", 0); |
| 604 | + char **pragmas = wstrvec(hdr->hr_value, ",", 0); |
603 | 605 | char **s; |
604 | 606 | for (s = pragmas; *s; ++s) { |
605 | 607 | if (!strcasecmp(*s, "no-cache")) { |
— | — | @@ -614,7 +616,7 @@ |
615 | 617 | */ |
616 | 618 | hdr = header_find(&client->cl_entity.he_headers, "Cache-Control"); |
617 | 619 | if (hdr) { |
618 | | - char **controls = wstrvec(hdr->hl_value, ",", 0); |
| 620 | + char **controls = wstrvec(hdr->hr_value, ",", 0); |
619 | 621 | char **s; |
620 | 622 | for (s = controls; *s; ++s) { |
621 | 623 | /* |
Index: trunk/willow/src/include/whttp_entity.h |
— | — | @@ -55,14 +55,23 @@ |
56 | 56 | typedef void (*header_cb)(struct http_entity *, void *, int); |
57 | 57 | typedef void (*cache_callback)(const char *, size_t, void *); |
58 | 58 | |
| 59 | +struct header { |
| 60 | + header(char *n, char *v) |
| 61 | + : hr_name(n), hr_value(v) {} |
| 62 | + char *hr_name; |
| 63 | + char *hr_value; |
| 64 | +}; |
| 65 | + |
59 | 66 | struct header_list { |
60 | | - char *hl_name; |
61 | | - char *hl_value; |
62 | | -struct header_list *hl_next; |
63 | | -struct header_list *hl_tail; |
| 67 | + header_list() : hl_len(0) { |
| 68 | + hl_hdrs.reserve(20); /* should be enough for most requests */ |
| 69 | + } |
| 70 | + void append(header *h) { |
| 71 | + hl_hdrs.push_back(h); |
| 72 | + hl_len += strlen(h->hr_name) + strlen(h->hr_value) + 4; |
| 73 | + } |
| 74 | + vector<header *> hl_hdrs; |
64 | 75 | int hl_len; |
65 | | - int hl_num; |
66 | | - int hl_flags; |
67 | 76 | }; |
68 | 77 | |
69 | 78 | struct qvalue { |
— | — | @@ -180,10 +189,10 @@ |
181 | 190 | void header_append_last (struct header_list *, const char *); |
182 | 191 | void header_free (struct header_list *); |
183 | 192 | char *header_build (struct header_list *); |
184 | | - void header_remove (struct header_list *, struct header_list *); |
| 193 | + void header_remove (struct header_list *, struct header *); |
185 | 194 | void header_dump (struct header_list *, int); |
186 | 195 | int header_undump (struct header_list *, int, off_t *); |
187 | | -struct header_list * header_find(struct header_list *head, const char *name); |
| 196 | +struct header *header_find (struct header_list *head, const char *name); |
188 | 197 | |
189 | 198 | |
190 | 199 | #endif |