source: mainline/uspace/lib/http/http.c@ f9a2831

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since f9a2831 was f9a2831, checked in by Martin Sucha <sucha14@…>, 12 years ago

Split the HTTP library into several files

  • Property mode set to 100644
File size: 4.8 KB
Line 
1/*
2 * Copyright (c) 2013 Martin Sucha
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup http
30 * @{
31 */
32/**
33 * @file
34 */
35
36#include <stdio.h>
37#include <stdlib.h>
38#include <str.h>
39#include <macros.h>
40
41#include <net/socket.h>
42#include <inet/dnsr.h>
43
44#include "http.h"
45
46void recv_reset(http_t *http)
47{
48 http->recv_buffer_in = 0;
49 http->recv_buffer_out = 0;
50}
51
52/** Receive one character (with buffering) */
53int recv_char(http_t *http, char *c, bool consume)
54{
55 if (http->recv_buffer_out == http->recv_buffer_in) {
56 recv_reset(http);
57
58 ssize_t rc = recv(http->conn_sd, http->recv_buffer, http->buffer_size, 0);
59 if (rc <= 0)
60 return rc;
61
62 http->recv_buffer_in = rc;
63 }
64
65 *c = http->recv_buffer[http->recv_buffer_out];
66 if (consume)
67 http->recv_buffer_out++;
68 return EOK;
69}
70
71ssize_t recv_buffer(http_t *http, char *buf, size_t buf_size)
72{
73 /* Flush any buffered data*/
74 if (http->recv_buffer_out != http->recv_buffer_in) {
75 size_t size = min(http->recv_buffer_in - http->recv_buffer_out, buf_size);
76 memcpy(buf, http->recv_buffer + http->recv_buffer_out, size);
77 http->recv_buffer_out += size;
78 return size;
79 }
80
81 return recv(http->conn_sd, buf, buf_size, 0);
82}
83
84/** Receive a character and if it is c, discard it from input buffer */
85int recv_discard(http_t *http, char discard)
86{
87 char c = 0;
88 int rc = recv_char(http, &c, false);
89 if (rc != EOK)
90 return rc;
91 if (c != discard)
92 return EOK;
93 return recv_char(http, &c, true);
94}
95
96/* Receive a single line */
97ssize_t recv_line(http_t *http, char *line, size_t size)
98{
99 size_t written = 0;
100
101 while (written < size) {
102 char c = 0;
103 int rc = recv_char(http, &c, true);
104 if (rc != EOK)
105 return rc;
106 if (c == '\n') {
107 recv_discard(http, '\r');
108 line[written++] = 0;
109 return written;
110 }
111 else if (c == '\r') {
112 recv_discard(http, '\n');
113 line[written++] = 0;
114 return written;
115 }
116 line[written++] = c;
117 }
118
119 return ELIMIT;
120}
121
122http_t *http_create(const char *host, uint16_t port)
123{
124 http_t *http = malloc(sizeof(http_t));
125 if (http == NULL)
126 return NULL;
127
128 http->host = str_dup(host);
129 if (http->host == NULL) {
130 free(http);
131 return NULL;
132 }
133 http->port = port;
134
135 http->buffer_size = 4096;
136 http->recv_buffer = malloc(http->buffer_size);
137 if (http->recv_buffer == NULL) {
138 free(http->host);
139 free(http);
140 return NULL;
141 }
142
143 return http;
144}
145
146int http_connect(http_t *http)
147{
148 if (http->connected)
149 return EBUSY;
150
151 /* Interpret as address */
152 int rc = inet_addr_parse(http->host, &http->addr);
153
154 if (rc != EOK) {
155 /* Interpret as a host name */
156 dnsr_hostinfo_t *hinfo = NULL;
157 rc = dnsr_name2host(http->host, &hinfo, AF_NONE);
158
159 if (rc != EOK)
160 return rc;
161
162 http->addr = hinfo->addr;
163 dnsr_hostinfo_destroy(hinfo);
164 }
165
166 struct sockaddr_in addr;
167 struct sockaddr_in6 addr6;
168 uint16_t af = inet_addr_sockaddr_in(&http->addr, &addr, &addr6);
169
170 http->conn_sd = socket(PF_INET, SOCK_STREAM, 0);
171 if (http->conn_sd < 0)
172 return http->conn_sd;
173
174 switch (af) {
175 case AF_INET:
176 addr.sin_port = htons(http->port);
177 rc = connect(http->conn_sd, (struct sockaddr *) &addr, sizeof(addr));
178 break;
179 case AF_INET6:
180 addr6.sin6_port = htons(http->port);
181 rc = connect(http->conn_sd, (struct sockaddr *) &addr6, sizeof(addr6));
182 break;
183 default:
184 return ENOTSUP;
185 }
186
187 return rc;
188}
189
190int http_close(http_t *http)
191{
192 if (!http->connected)
193 return EINVAL;
194
195 return closesocket(http->conn_sd);
196}
197
198void http_destroy(http_t *http)
199{
200 free(http->recv_buffer);
201 free(http);
202}
203
204/** @}
205 */
Note: See TracBrowser for help on using the repository browser.