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

Contents of /trunk/http-connection.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 116 - (show annotations)
Sat May 31 21:42:36 2008 UTC (11 years, 3 months ago) by siliconforks
File MIME type: text/plain
File size: 4970 byte(s)
Add jscoverage-server.

1 /*
2 http-connection.c - TCP connection between HTTP client and server
3 Copyright (C) 2008 siliconforks.com
4
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 <errno.h>
26 #include <string.h>
27
28 #include <arpa/inet.h>
29
30 #include "util.h"
31
32 #define CONNECTION_BUFFER_CAPACITY 8192
33
34 struct HTTPConnection {
35 SOCKET s;
36 uint8_t input_buffer[CONNECTION_BUFFER_CAPACITY];
37 size_t input_buffer_offset;
38 size_t input_buffer_length;
39 uint8_t output_buffer[CONNECTION_BUFFER_CAPACITY];
40 size_t output_buffer_offset;
41 size_t output_buffer_length;
42 };
43
44 static HTTPConnection * HTTPConnection_new(SOCKET s) {
45 HTTPConnection * connection = xmalloc(sizeof(HTTPConnection));
46 connection->s = s;
47 connection->input_buffer_offset = 0;
48 connection->input_buffer_length = 0;
49 connection->output_buffer_offset = 0;
50 connection->output_buffer_length = 0;
51 return connection;
52 }
53
54 HTTPConnection * HTTPConnection_new_client(const char * host, uint16_t port) {
55 struct in_addr ip_address;
56 if (! inet_aton(host, &ip_address)) {
57 /* it's a host name */
58 if (xgethostbyname(host, &ip_address) != 0) {
59 return NULL;
60 }
61 }
62
63 SOCKET s = socket(PF_INET, SOCK_STREAM, 0);
64 if (s < 0) {
65 return NULL;
66 }
67
68 struct sockaddr_in a;
69 a.sin_family = AF_INET;
70 a.sin_port = htons(port);
71 a.sin_addr = ip_address;
72
73 if (connect(s, (struct sockaddr *) &a, sizeof(a)) < 0) {
74 closesocket(s);
75 return NULL;
76 }
77
78 return HTTPConnection_new(s);
79 }
80
81 HTTPConnection * HTTPConnection_new_server(SOCKET s) {
82 return HTTPConnection_new(s);
83 }
84
85 int HTTPConnection_delete(HTTPConnection * connection) {
86 int result = 0;
87 if (closesocket(connection->s) == -1) {
88 result = errno;
89 }
90 free(connection);
91 return result;
92 }
93
94 int HTTPConnection_get_peer(HTTPConnection * connection, struct sockaddr_in * peer) {
95 int result = 0;
96 socklen_t length = sizeof(struct sockaddr_in);
97 if (getpeername(connection->s, (struct sockaddr *) peer, &length) == -1) {
98 result = errno;
99 }
100 return result;
101 }
102
103 int HTTPConnection_read_octet(HTTPConnection * connection, int * octet) {
104 if (connection->input_buffer_offset >= connection->input_buffer_length) {
105 ssize_t bytes_received = recv(connection->s, connection->input_buffer, CONNECTION_BUFFER_CAPACITY, 0);
106 if (bytes_received == -1) {
107 return errno;
108 }
109 else if (bytes_received == 0) {
110 /* orderly shutdown */
111 *octet = -1;
112 return 0;
113 }
114 else {
115 connection->input_buffer_offset = 0;
116 connection->input_buffer_length = bytes_received;
117 }
118 }
119 *octet = connection->input_buffer[connection->input_buffer_offset];
120 connection->input_buffer_offset++;
121 return 0;
122 }
123
124 int HTTPConnection_peek_octet(HTTPConnection * connection, int * octet) {
125 int result = HTTPConnection_read_octet(connection, octet);
126
127 /* check for error */
128 if (result != 0) {
129 return result;
130 }
131
132 /* check for end */
133 if (*octet == -1) {
134 return 0;
135 }
136
137 /* reset input buffer */
138 connection->input_buffer_offset--;
139 return 0;
140 }
141
142 int HTTPConnection_write(HTTPConnection * connection, const void * p, size_t size) {
143 while (size > 0) {
144 if (connection->output_buffer_length == CONNECTION_BUFFER_CAPACITY) {
145 /* buffer full */
146 ssize_t bytes_sent = send(connection->s, connection->output_buffer, CONNECTION_BUFFER_CAPACITY, 0);
147 if (bytes_sent == -1) {
148 return errno;
149 }
150 connection->output_buffer_length = 0;
151 }
152
153 size_t buffer_remaining = CONNECTION_BUFFER_CAPACITY - connection->output_buffer_length;
154 size_t bytes_to_copy;
155 if (size <= buffer_remaining) {
156 bytes_to_copy = size;
157 }
158 else {
159 bytes_to_copy = buffer_remaining;
160 }
161
162 memcpy(connection->output_buffer + connection->output_buffer_length, p, bytes_to_copy);
163 connection->output_buffer_length += bytes_to_copy;
164 p += bytes_to_copy;
165 size -= bytes_to_copy;
166 }
167
168 return 0;
169 }
170
171 int HTTPConnection_flush(HTTPConnection * connection) {
172 if (connection->output_buffer_length > 0) {
173 ssize_t bytes_sent = send(connection->s, connection->output_buffer, connection->output_buffer_length, 0);
174 if (bytes_sent == -1) {
175 return errno;
176 }
177 connection->output_buffer_length = 0;
178 }
179 return 0;
180 }

  ViewVC Help
Powered by ViewVC 1.1.24