Changeset 3ce68b7 in mainline
- Timestamp:
- 2013-09-26T09:01:36Z (11 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- b623b68
- Parents:
- c17469e
- Location:
- uspace/lib/http
- Files:
-
- 1 added
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/http/headers.c
rc17469e r3ce68b7 40 40 41 41 #include "http.h" 42 #include "http-ctype.h" 42 43 43 44 #define HTTP_HEADER_LINE "%s: %s\r\n" 44 45 static char *cut_str(const char *start, const char *end)46 {47 size_t size = end - start;48 return str_ndup(start, size);49 }50 45 51 46 void http_header_init(http_header_t *header) … … 98 93 } 99 94 100 int http_header_parse(const char *line, http_header_t *header) 101 { 102 const char *pos = line; 103 while (*pos != 0 && *pos != ':') pos++; 104 if (*pos != ':') 95 int http_header_receive_name(receive_buffer_t *rb, char **out_name) 96 { 97 receive_buffer_mark_t name_start; 98 receive_buffer_mark_t name_end; 99 100 recv_mark(rb, &name_start); 101 recv_mark(rb, &name_end); 102 103 char c = 0; 104 do { 105 recv_mark_update(rb, &name_end); 106 107 int rc = recv_char(rb, &c, true); 108 if (rc != EOK) { 109 recv_unmark(rb, &name_start); 110 recv_unmark(rb, &name_end); 111 return rc; 112 } 113 } while (is_token(c)); 114 115 if (c != ':') { 116 recv_unmark(rb, &name_start); 117 recv_unmark(rb, &name_end); 105 118 return EINVAL; 106 107 char *name = cut_str(line, pos); 108 if (name == NULL) 109 return ENOMEM; 110 111 pos++; 112 113 while (*pos == ' ') pos++; 114 115 char *value = str_dup(pos); 116 if (value == NULL) { 119 } 120 121 char *name = NULL; 122 int rc = recv_cut_str(rb, &name_start, &name_end, &name); 123 recv_unmark(rb, &name_start); 124 recv_unmark(rb, &name_end); 125 if (rc != EOK) 126 return rc; 127 128 *out_name = name; 129 return EOK; 130 } 131 132 int http_header_receive_value(receive_buffer_t *rb, char **out_value) 133 { 134 int rc = EOK; 135 char c = 0; 136 137 receive_buffer_mark_t value_start; 138 recv_mark(rb, &value_start); 139 140 /* Ignore any inline LWS */ 141 while (true) { 142 recv_mark_update(rb, &value_start); 143 rc = recv_char(rb, &c, false); 144 if (rc != EOK) 145 goto error; 146 147 if (c != ' ' && c != '\t') 148 break; 149 150 rc = recv_char(rb, &c, true); 151 if (rc != EOK) 152 goto error; 153 } 154 155 receive_buffer_mark_t value_end; 156 recv_mark(rb, &value_end); 157 158 while (true) { 159 recv_mark_update(rb, &value_end); 160 161 rc = recv_char(rb, &c, true); 162 if (rc != EOK) 163 goto error_end; 164 165 if (c != '\r' && c != '\n') 166 continue; 167 168 rc = recv_discard(rb, (c == '\r' ? '\n' : '\r')); 169 if (rc < 0) 170 goto error_end; 171 172 rc = recv_char(rb, &c, false); 173 if (rc != EOK) 174 goto error_end; 175 176 if (c != ' ' && c != '\t') 177 break; 178 179 /* Ignore the char */ 180 rc = recv_char(rb, &c, true); 181 if (rc != EOK) 182 goto error_end; 183 } 184 185 char *value = NULL; 186 rc = recv_cut_str(rb, &value_start, &value_end, &value); 187 recv_unmark(rb, &value_start); 188 recv_unmark(rb, &value_end); 189 if (rc != EOK) 190 return rc; 191 192 *out_value = value; 193 return EOK; 194 error_end: 195 recv_unmark(rb, &value_end); 196 error: 197 recv_unmark(rb, &value_start); 198 return rc; 199 } 200 201 int http_header_receive(receive_buffer_t *rb, http_header_t *header) 202 { 203 char *name = NULL; 204 int rc = http_header_receive_name(rb, &name); 205 if (rc != EOK) { 206 printf("Failed receiving header name\n"); 207 return rc; 208 } 209 210 char *value = NULL; 211 rc = http_header_receive_value(rb, &value); 212 if (rc != EOK) { 117 213 free(name); 118 return ENOMEM;214 return rc; 119 215 } 120 216 121 217 header->name = name; 122 218 header->value = value; 123 124 219 return EOK; 125 220 } 126 221 222 /** Normalize HTTP header value 223 * 224 * @see RFC2616 section 4.2 225 */ 226 void http_header_normalize_value(char *value) 227 { 228 size_t read_index = 0; 229 size_t write_index = 0; 230 231 while (is_lws(value[read_index])) read_index++; 232 233 while (value[read_index] != 0) { 234 if (is_lws(value[read_index])) { 235 while (is_lws(value[read_index])) read_index++; 236 237 if (value[read_index] != 0) 238 value[write_index++] = ' '; 239 240 continue; 241 } 242 243 value[write_index++] = value[read_index++]; 244 } 245 246 value[write_index] = 0; 247 } 248 127 249 /** @} 128 250 */ -
uspace/lib/http/http.h
rc17469e r3ce68b7 84 84 extern void http_header_init(http_header_t *); 85 85 extern http_header_t *http_header_create(const char *, const char *); 86 extern int http_header_parse(const char *, http_header_t *); 86 extern int http_header_receive_name(receive_buffer_t *, char **); 87 extern int http_header_receive_value(receive_buffer_t *, char **); 88 extern int http_header_receive(receive_buffer_t *, http_header_t *); 89 extern void http_header_normalize_value(char *); 87 90 ssize_t http_header_encode(http_header_t *, char *, size_t); 88 91 extern void http_header_destroy(http_header_t *); -
uspace/lib/http/receive-buffer.c
rc17469e r3ce68b7 39 39 #include <errno.h> 40 40 #include <macros.h> 41 #include <adt/list.h> 41 42 42 43 #include "receive-buffer.h" … … 51 52 rb->out = 0; 52 53 rb->size = buffer_size; 54 55 list_initialize(&rb->marks); 56 53 57 rb->buffer = malloc(buffer_size); 54 58 if (rb->buffer == NULL) … … 57 61 } 58 62 63 static ssize_t dummy_receive(void *unused, void *buf, size_t buf_size) 64 { 65 return 0; 66 } 67 68 int recv_buffer_init_const(receive_buffer_t *rb, void *buf, size_t size) 69 { 70 int rc = recv_buffer_init(rb, size, dummy_receive, NULL); 71 if (rc != EOK) 72 return rc; 73 74 memcpy(rb->buffer, buf, size); 75 rb->in = size; 76 return EOK; 77 } 78 59 79 void recv_buffer_fini(receive_buffer_t *rb) 60 80 { … … 68 88 } 69 89 90 void recv_mark(receive_buffer_t *rb, receive_buffer_mark_t *mark) 91 { 92 link_initialize(&mark->link); 93 list_append(&mark->link, &rb->marks); 94 recv_mark_update(rb, mark); 95 } 96 97 void recv_unmark(receive_buffer_t *rb, receive_buffer_mark_t *mark) 98 { 99 list_remove(&mark->link); 100 } 101 102 void recv_mark_update(receive_buffer_t *rb, receive_buffer_mark_t *mark) 103 { 104 mark->offset = rb->out; 105 } 106 107 int recv_cut(receive_buffer_t *rb, receive_buffer_mark_t *a, receive_buffer_mark_t *b, void **out_buf, size_t *out_size) 108 { 109 if (a->offset > b->offset) 110 return EINVAL; 111 112 size_t size = b->offset - a->offset; 113 void *buf = malloc(size); 114 if (buf == NULL) 115 return ENOMEM; 116 117 memcpy(buf, rb->buffer + a->offset, size); 118 *out_buf = buf; 119 *out_size = size; 120 return EOK; 121 } 122 123 int recv_cut_str(receive_buffer_t *rb, receive_buffer_mark_t *a, receive_buffer_mark_t *b, char **out_buf) 124 { 125 if (a->offset > b->offset) 126 return EINVAL; 127 128 size_t size = b->offset - a->offset; 129 char *buf = malloc(size + 1); 130 if (buf == NULL) 131 return ENOMEM; 132 133 memcpy(buf, rb->buffer + a->offset, size); 134 buf[size] = 0; 135 for (size_t i = 0; i < size; i++) { 136 if (buf[i] == 0) { 137 free(buf); 138 return EIO; 139 } 140 } 141 *out_buf = buf; 142 return EOK; 143 } 144 145 70 146 /** Receive one character (with buffering) */ 71 147 int recv_char(receive_buffer_t *rb, char *c, bool consume) 72 148 { 73 149 if (rb->out == rb->in) { 74 recv_reset(rb); 150 size_t free = rb->size - rb->in; 151 if (free == 0) { 152 size_t min_mark = rb->size; 153 list_foreach(rb->marks, link, receive_buffer_mark_t, mark) { 154 min_mark = min(min_mark, mark->offset); 155 } 156 157 if (min_mark == 0) 158 return ELIMIT; 159 160 size_t new_in = rb->in - min_mark; 161 memmove(rb->buffer, rb->buffer + min_mark, new_in); 162 rb->out = rb->in = new_in; 163 free = rb->size - rb->in; 164 list_foreach(rb->marks, link, receive_buffer_mark_t, mark) { 165 mark->offset -= min_mark; 166 } 167 } 75 168 76 ssize_t rc = rb->receive(rb->client_data, rb->buffer , rb->size);169 ssize_t rc = rb->receive(rb->client_data, rb->buffer + rb->in, free); 77 170 if (rc <= 0) 78 171 return rc; … … 100 193 } 101 194 102 /** Receive a character and if it is c, discard it from input buffer */ 103 int recv_discard(receive_buffer_t *rb, char discard) 195 /** Receive a character and if it is c, discard it from input buffer 196 * @return number of characters discarded (0 or 1) or negative error code 197 */ 198 ssize_t recv_discard(receive_buffer_t *rb, char discard) 104 199 { 105 200 char c = 0; … … 108 203 return rc; 109 204 if (c != discard) 110 return EOK; 111 return recv_char(rb, &c, true); 205 return 0; 206 rc = recv_char(rb, &c, true); 207 if (rc != EOK) 208 return rc; 209 return 1; 210 } 211 212 /** Receive an end of line, either CR, LF, CRLF or LFCR 213 * 214 * @return number of bytes read (0 if no newline is present in the stream) 215 * or negative error code 216 */ 217 ssize_t recv_eol(receive_buffer_t *rb) 218 { 219 char c = 0; 220 int rc = recv_char(rb, &c, false); 221 if (rc != EOK) 222 return rc; 223 224 if (c != '\r' && c != '\n') 225 return 0; 226 227 rc = recv_char(rb, &c, true); 228 if (rc != EOK) 229 return rc; 230 231 ssize_t rc2 = recv_discard(rb, (c == '\r' ? '\n' : '\r')); 232 if (rc2 < 0) 233 return rc2; 234 235 return 1 + rc2; 112 236 } 113 237 -
uspace/lib/http/receive-buffer.h
rc17469e r3ce68b7 37 37 #define HTTP_RECEIVE_BUFFER_H_ 38 38 39 #include <adt/list.h> 39 40 40 41 /** Receive data. … … 55 56 void *client_data; 56 57 receive_func_t receive; 58 59 list_t marks; 57 60 } receive_buffer_t; 58 61 62 typedef struct { 63 link_t link; 64 size_t offset; 65 } receive_buffer_mark_t; 66 59 67 extern int recv_buffer_init(receive_buffer_t *, size_t, receive_func_t, void *); 68 extern int recv_buffer_init_const(receive_buffer_t *, void *, size_t); 60 69 extern void recv_buffer_fini(receive_buffer_t *); 61 70 extern void recv_reset(receive_buffer_t *); 71 extern void recv_mark(receive_buffer_t *, receive_buffer_mark_t *); 72 extern void recv_unmark(receive_buffer_t *, receive_buffer_mark_t *); 73 extern void recv_mark_update(receive_buffer_t *, receive_buffer_mark_t *); 74 extern int recv_cut(receive_buffer_t *, receive_buffer_mark_t *, 75 receive_buffer_mark_t *, void **, size_t *); 76 extern int recv_cut_str(receive_buffer_t *, receive_buffer_mark_t *, 77 receive_buffer_mark_t *, char **); 62 78 extern int recv_char(receive_buffer_t *, char *, bool); 63 79 extern ssize_t recv_buffer(receive_buffer_t *, char *, size_t); 64 extern int recv_discard(receive_buffer_t *, char); 80 extern ssize_t recv_discard(receive_buffer_t *, char); 81 extern ssize_t recv_eol(receive_buffer_t *); 65 82 extern ssize_t recv_line(receive_buffer_t *, char *, size_t); 66 83 -
uspace/lib/http/response.c
rc17469e r3ce68b7 116 116 117 117 while (true) { 118 rc = recv_ line(&http->recv_buffer, line, http->buffer_size);118 rc = recv_eol(&http->recv_buffer); 119 119 if (rc < 0) 120 120 goto error; 121 if (*line == 0) 121 122 /* Empty line ends header part */ 123 if (rc > 0) 122 124 break; 123 125 … … 129 131 http_header_init(header); 130 132 131 rc = http_header_parse(line, header); 132 if (rc != EOK) 133 rc = http_header_receive(&http->recv_buffer, header); 134 if (rc != EOK) { 135 free(header); 133 136 goto error; 137 } 134 138 135 139 list_append(&header->link, &resp->headers);
Note:
See TracChangeset
for help on using the changeset viewer.