/[jscoverage]/trunk/http-connection.c
ViewVC logotype

Annotation of /trunk/http-connection.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 505 - (hide annotations)
Sat Jan 2 04:55:54 2010 UTC (10 years, 1 month ago) by siliconforks
File MIME type: text/plain
File size: 5270 byte(s)
Update copyright year.

1 siliconforks 116 /*
2     http-connection.c - TCP connection between HTTP client and server
3 siliconforks 505 Copyright (C) 2008, 2009, 2010 siliconforks.com
4 siliconforks 116
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9    
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13     GNU General Public License for more details.
14    
15     You should have received a copy of the GNU General Public License along
16     with this program; if not, write to the Free Software Foundation, Inc.,
17     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18     */
19    
20     #include <config.h>
21    
22     #include "http-server.h"
23    
24     #include <assert.h>
25     #include <string.h>
26    
27     #include "util.h"
28    
29     #define CONNECTION_BUFFER_CAPACITY 8192
30    
31 siliconforks 304 #ifdef _WIN32
32     #define ERRNO (WSAGetLastError())
33     #else
34     #include <errno.h>
35     #define ERRNO errno
36     #endif
37    
38 siliconforks 116 struct HTTPConnection {
39     SOCKET s;
40     uint8_t input_buffer[CONNECTION_BUFFER_CAPACITY];
41     size_t input_buffer_offset;
42     size_t input_buffer_length;
43     uint8_t output_buffer[CONNECTION_BUFFER_CAPACITY];
44     size_t output_buffer_offset;
45     size_t output_buffer_length;
46     };
47    
48     static HTTPConnection * HTTPConnection_new(SOCKET s) {
49     HTTPConnection * connection = xmalloc(sizeof(HTTPConnection));
50     connection->s = s;
51     connection->input_buffer_offset = 0;
52     connection->input_buffer_length = 0;
53     connection->output_buffer_offset = 0;
54     connection->output_buffer_length = 0;
55     return connection;
56     }
57    
58     HTTPConnection * HTTPConnection_new_client(const char * host, uint16_t port) {
59     struct in_addr ip_address;
60     if (! inet_aton(host, &ip_address)) {
61     /* it's a host name */
62     if (xgethostbyname(host, &ip_address) != 0) {
63     return NULL;
64     }
65     }
66    
67     SOCKET s = socket(PF_INET, SOCK_STREAM, 0);
68 siliconforks 125 if (s == INVALID_SOCKET) {
69 siliconforks 116 return NULL;
70     }
71    
72     struct sockaddr_in a;
73     a.sin_family = AF_INET;
74     a.sin_port = htons(port);
75     a.sin_addr = ip_address;
76    
77     if (connect(s, (struct sockaddr *) &a, sizeof(a)) < 0) {
78     closesocket(s);
79     return NULL;
80     }
81    
82     return HTTPConnection_new(s);
83     }
84    
85     HTTPConnection * HTTPConnection_new_server(SOCKET s) {
86     return HTTPConnection_new(s);
87     }
88    
89     int HTTPConnection_delete(HTTPConnection * connection) {
90     int result = 0;
91     if (closesocket(connection->s) == -1) {
92 siliconforks 304 result = ERRNO;
93     assert(result != 0);
94 siliconforks 116 }
95     free(connection);
96     return result;
97     }
98    
99     int HTTPConnection_get_peer(HTTPConnection * connection, struct sockaddr_in * peer) {
100     int result = 0;
101     socklen_t length = sizeof(struct sockaddr_in);
102     if (getpeername(connection->s, (struct sockaddr *) peer, &length) == -1) {
103 siliconforks 304 result = ERRNO;
104     assert(result != 0);
105 siliconforks 116 }
106     return result;
107     }
108    
109     int HTTPConnection_read_octet(HTTPConnection * connection, int * octet) {
110     if (connection->input_buffer_offset >= connection->input_buffer_length) {
111     ssize_t bytes_received = recv(connection->s, connection->input_buffer, CONNECTION_BUFFER_CAPACITY, 0);
112     if (bytes_received == -1) {
113 siliconforks 304 int result = ERRNO;
114     assert(result != 0);
115     return result;
116 siliconforks 116 }
117     else if (bytes_received == 0) {
118     /* orderly shutdown */
119     *octet = -1;
120     return 0;
121     }
122     else {
123     connection->input_buffer_offset = 0;
124     connection->input_buffer_length = bytes_received;
125     }
126     }
127     *octet = connection->input_buffer[connection->input_buffer_offset];
128     connection->input_buffer_offset++;
129     return 0;
130     }
131    
132     int HTTPConnection_peek_octet(HTTPConnection * connection, int * octet) {
133     int result = HTTPConnection_read_octet(connection, octet);
134    
135     /* check for error */
136     if (result != 0) {
137     return result;
138     }
139    
140     /* check for end */
141     if (*octet == -1) {
142     return 0;
143     }
144    
145     /* reset input buffer */
146     connection->input_buffer_offset--;
147     return 0;
148     }
149    
150     int HTTPConnection_write(HTTPConnection * connection, const void * p, size_t size) {
151     while (size > 0) {
152     if (connection->output_buffer_length == CONNECTION_BUFFER_CAPACITY) {
153     /* buffer full */
154     ssize_t bytes_sent = send(connection->s, connection->output_buffer, CONNECTION_BUFFER_CAPACITY, 0);
155     if (bytes_sent == -1) {
156 siliconforks 304 int result = ERRNO;
157     assert(result != 0);
158     return result;
159 siliconforks 116 }
160     connection->output_buffer_length = 0;
161     }
162    
163     size_t buffer_remaining = CONNECTION_BUFFER_CAPACITY - connection->output_buffer_length;
164     size_t bytes_to_copy;
165     if (size <= buffer_remaining) {
166     bytes_to_copy = size;
167     }
168     else {
169     bytes_to_copy = buffer_remaining;
170     }
171    
172     memcpy(connection->output_buffer + connection->output_buffer_length, p, bytes_to_copy);
173     connection->output_buffer_length += bytes_to_copy;
174     p += bytes_to_copy;
175     size -= bytes_to_copy;
176     }
177    
178     return 0;
179     }
180    
181     int HTTPConnection_flush(HTTPConnection * connection) {
182     if (connection->output_buffer_length > 0) {
183     ssize_t bytes_sent = send(connection->s, connection->output_buffer, connection->output_buffer_length, 0);
184     if (bytes_sent == -1) {
185 siliconforks 304 int result = ERRNO;
186     assert(result != 0);
187     return result;
188 siliconforks 116 }
189     connection->output_buffer_length = 0;
190     }
191     return 0;
192     }

  ViewVC Help
Powered by ViewVC 1.1.24