Changeset f9a2831 in mainline
- Timestamp:
- 2013-09-17T20:35:01Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- ff364f1
- Parents:
- b9f7848b
- Location:
- uspace/lib/http
- Files:
-
- 3 added
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/http/Makefile
rb9f7848b rf9a2831 34 34 35 35 SOURCES = \ 36 http.c 36 http.c \ 37 headers.c \ 38 request.c \ 39 response.c 37 40 38 41 include $(USPACE_PREFIX)/Makefile.common -
uspace/lib/http/http.c
rb9f7848b rf9a2831 44 44 #include "http.h" 45 45 46 #define HTTP_METHOD_LINE "%s %s HTTP/1.1\r\n" 47 #define HTTP_HEADER_LINE "%s: %s\r\n" 48 #define HTTP_REQUEST_LINE "\r\n" 49 50 static char *cut_str(const char *start, const char *end) 51 { 52 size_t size = end - start; 53 return str_ndup(start, size); 54 } 55 56 static void recv_reset(http_t *http) 46 void recv_reset(http_t *http) 57 47 { 58 48 http->recv_buffer_in = 0; … … 61 51 62 52 /** Receive one character (with buffering) */ 63 staticint recv_char(http_t *http, char *c, bool consume)53 int recv_char(http_t *http, char *c, bool consume) 64 54 { 65 55 if (http->recv_buffer_out == http->recv_buffer_in) { … … 79 69 } 80 70 81 s tatic ssize_t recv_buffer(http_t *http, char *buf, size_t buf_size)71 ssize_t recv_buffer(http_t *http, char *buf, size_t buf_size) 82 72 { 83 73 /* Flush any buffered data*/ … … 93 83 94 84 /** Receive a character and if it is c, discard it from input buffer */ 95 staticint recv_discard(http_t *http, char discard)85 int recv_discard(http_t *http, char discard) 96 86 { 97 87 char c = 0; … … 105 95 106 96 /* Receive a single line */ 107 s tatic ssize_t recv_line(http_t *http, char *line, size_t size)97 ssize_t recv_line(http_t *http, char *line, size_t size) 108 98 { 109 99 size_t written = 0; … … 198 188 } 199 189 200 http_header_t *http_header_create(const char *name, const char *value)201 {202 char *dname = str_dup(name);203 if (dname == NULL)204 return NULL;205 206 char *dvalue = str_dup(value);207 if (dvalue == NULL) {208 free(dname);209 return NULL;210 }211 212 return http_header_create_no_copy(dname, dvalue);213 }214 215 http_header_t *http_header_create_no_copy(char *name, char *value)216 {217 http_header_t *header = malloc(sizeof(http_header_t));218 if (header == NULL)219 return NULL;220 221 link_initialize(&header->link);222 header->name = name;223 header->value = value;224 225 return header;226 }227 228 void http_header_destroy(http_header_t *header)229 {230 free(header->name);231 free(header->value);232 free(header);233 }234 235 http_request_t *http_request_create(const char *method, const char *path)236 {237 http_request_t *req = malloc(sizeof(http_request_t));238 if (req == NULL)239 return NULL;240 241 req->method = str_dup(method);242 if (req->method == NULL) {243 free(req);244 return NULL;245 }246 247 req->path = str_dup(path);248 if (req->path == NULL) {249 free(req->method);250 free(req);251 return NULL;252 }253 254 list_initialize(&req->headers);255 256 return req;257 }258 259 void http_request_destroy(http_request_t *req)260 {261 free(req->method);262 free(req->path);263 link_t *link = req->headers.head.next;264 while (link != &req->headers.head) {265 link_t *next = link->next;266 http_header_t *header = list_get_instance(link, http_header_t, link);267 http_header_destroy(header);268 link = next;269 }270 free(req);271 }272 273 static ssize_t http_encode_method(char *buf, size_t buf_size,274 const char *method, const char *path)275 {276 if (buf == NULL) {277 return printf_size(HTTP_METHOD_LINE, method, path);278 }279 else {280 return snprintf(buf, buf_size, HTTP_METHOD_LINE, method, path);281 }282 }283 284 static ssize_t http_encode_header(char *buf, size_t buf_size,285 http_header_t *header)286 {287 /* TODO properly split long header values */288 if (buf == NULL) {289 return printf_size(HTTP_HEADER_LINE, header->name, header->value);290 }291 else {292 return snprintf(buf, buf_size,293 HTTP_HEADER_LINE, header->name, header->value);294 }295 }296 297 int http_request_format(http_request_t *req, char **out_buf,298 size_t *out_buf_size)299 {300 /* Compute the size of the request */301 ssize_t meth_size = http_encode_method(NULL, 0, req->method, req->path);302 if (meth_size < 0)303 return meth_size;304 size_t size = meth_size;305 306 list_foreach(req->headers, link, http_header_t, header) {307 ssize_t header_size = http_encode_header(NULL, 0, header);308 if (header_size < 0)309 return header_size;310 size += header_size;311 }312 size += str_length(HTTP_REQUEST_LINE);313 314 char *buf = malloc(size);315 if (buf == NULL)316 return ENOMEM;317 318 char *pos = buf;319 size_t pos_size = size;320 ssize_t written = http_encode_method(pos, pos_size, req->method, req->path);321 if (written < 0) {322 free(buf);323 return written;324 }325 pos += written;326 pos_size -= written;327 328 list_foreach(req->headers, link, http_header_t, header) {329 written = http_encode_header(pos, pos_size, header);330 if (written < 0) {331 free(buf);332 return written;333 }334 pos += written;335 pos_size -= written;336 }337 338 size_t rlsize = str_size(HTTP_REQUEST_LINE);339 memcpy(pos, HTTP_REQUEST_LINE, rlsize);340 pos_size -= rlsize;341 assert(pos_size == 0);342 343 *out_buf = buf;344 *out_buf_size = size;345 return EOK;346 }347 348 int http_send_request(http_t *http, http_request_t *req)349 {350 char *buf;351 size_t buf_size;352 353 int rc = http_request_format(req, &buf, &buf_size);354 if (rc != EOK)355 return rc;356 357 rc = send(http->conn_sd, buf, buf_size, 0);358 free(buf);359 360 return rc;361 }362 363 int http_parse_status(const char *line, http_version_t *out_version,364 uint16_t *out_status, char **out_message)365 {366 http_version_t version;367 uint16_t status;368 char *message = NULL;369 370 if (!str_test_prefix(line, "HTTP/"))371 return EINVAL;372 373 const char *pos_version = line + 5;374 const char *pos = pos_version;375 376 int rc = str_uint8_t(pos_version, &pos, 10, false, &version.major);377 if (rc != EOK)378 return rc;379 if (*pos != '.')380 return EINVAL;381 pos++;382 383 pos_version = pos;384 rc = str_uint8_t(pos_version, &pos, 10, false, &version.minor);385 if (rc != EOK)386 return rc;387 if (*pos != ' ')388 return EINVAL;389 pos++;390 391 const char *pos_status = pos;392 rc = str_uint16_t(pos_status, &pos, 10, false, &status);393 if (rc != EOK)394 return rc;395 if (*pos != ' ')396 return EINVAL;397 pos++;398 399 if (out_message) {400 message = str_dup(pos);401 if (message == NULL)402 return ENOMEM;403 }404 405 if (out_version)406 *out_version = version;407 if (out_status)408 *out_status = status;409 if (out_message)410 *out_message = message;411 return EOK;412 }413 414 int http_parse_header(const char *line, char **out_name, char **out_value)415 {416 const char *pos = line;417 while (*pos != 0 && *pos != ':') pos++;418 if (*pos != ':')419 return EINVAL;420 421 char *name = cut_str(line, pos);422 if (name == NULL)423 return ENOMEM;424 425 pos++;426 427 while (*pos == ' ') pos++;428 429 char *value = str_dup(pos);430 if (value == NULL) {431 free(name);432 return ENOMEM;433 }434 435 *out_name = name;436 *out_value = value;437 438 return EOK;439 }440 441 int http_receive_response(http_t *http, http_response_t **out_response)442 {443 http_response_t *resp = malloc(sizeof(http_response_t));444 if (resp == NULL)445 return ENOMEM;446 memset(resp, 0, sizeof(http_response_t));447 list_initialize(&resp->headers);448 449 char *line = malloc(http->buffer_size);450 if (line == NULL) {451 free(resp);452 return ENOMEM;453 }454 455 int rc = recv_line(http, line, http->buffer_size);456 if (rc < 0)457 goto error;458 459 rc = http_parse_status(line, &resp->version, &resp->status,460 &resp->message);461 if (rc != EOK)462 goto error;463 464 while (true) {465 rc = recv_line(http, line, http->buffer_size);466 if (rc < 0)467 goto error;468 if (*line == 0)469 break;470 471 char *name = NULL;472 char *value = NULL;473 rc = http_parse_header(line, &name, &value);474 if (rc != EOK)475 goto error;476 477 http_header_t *header = http_header_create_no_copy(name, value);478 if (header == NULL) {479 free(name);480 free(value);481 rc = ENOMEM;482 goto error;483 }484 485 list_append(&header->link, &resp->headers);486 }487 488 *out_response = resp;489 490 return EOK;491 error:492 free(line);493 http_response_destroy(resp);494 return rc;495 }496 497 int http_receive_body(http_t *http, void *buf, size_t buf_size)498 {499 return recv_buffer(http, buf, buf_size);500 }501 502 void http_response_destroy(http_response_t *resp)503 {504 free(resp->message);505 link_t *link = resp->headers.head.next;506 while (link != &resp->headers.head) {507 link_t *next = link->next;508 http_header_t *header = list_get_instance(link, http_header_t, link);509 http_header_destroy(header);510 link = next;511 }512 free(resp);513 }514 515 190 int http_close(http_t *http) 516 191 { -
uspace/lib/http/http.h
rb9f7848b rf9a2831 91 91 char **); 92 92 extern int http_parse_header(const char *, char **, char **); 93 ssize_t http_encode_header(char *, size_t, http_header_t *); 93 94 extern int http_receive_response(http_t *, http_response_t **); 94 95 extern int http_receive_body(http_t *, void *, size_t); … … 97 98 extern void http_destroy(http_t *); 98 99 100 extern void recv_reset(http_t *); 101 extern int recv_char(http_t *, char *, bool); 102 extern ssize_t recv_buffer(http_t *, char *, size_t); 103 extern int recv_discard(http_t *, char); 104 extern ssize_t recv_line(http_t *, char *, size_t); 105 99 106 #endif 100 107
Note:
See TracChangeset
for help on using the changeset viewer.