Browse Source

Updated to use new URL parser and new protocol API.

Sort of works; the HTTP stuff is fine but the TCP code seems to be
broken; it doesn't ACK the packets and just hands us the retransmitted
packets instead.
tags/v0.9.3
Michael Brown 19 years ago
parent
commit
4ed412f1c2
1 changed files with 70 additions and 75 deletions
  1. 70
    75
      src/proto/http.c

+ 70
- 75
src/proto/http.c View File

1
+#include "proto.h"
2
+#include "tcp.h"
3
+#include "url.h"
1
 #include "etherboot.h"
4
 #include "etherboot.h"
2
-#include "http.h"
3
-
4
-#ifdef DOWNLOAD_PROTO_HTTP
5
 
5
 
6
 /* The block size is currently chosen to be 512 bytes. This means, we can
6
 /* The block size is currently chosen to be 512 bytes. This means, we can
7
    allocate the receive buffer on the stack, but it results in a noticeable
7
    allocate the receive buffer on the stack, but it results in a noticeable
17
 SEND_TCP_CALLBACK - Send data using TCP
17
 SEND_TCP_CALLBACK - Send data using TCP
18
 **************************************************************************/
18
 **************************************************************************/
19
 struct send_recv_state {
19
 struct send_recv_state {
20
-	int (*fnc)(unsigned char *data, int block, int len, int eof);
20
+	int ( * process ) ( unsigned char *data,
21
+			    unsigned int blocknum,
22
+			    unsigned int len, int eof );
21
 	char *send_buffer;
23
 	char *send_buffer;
22
 	char *recv_buffer;
24
 	char *recv_buffer;
23
 	int send_length;
25
 	int send_length;
27
 	int bytes_received;
29
 	int bytes_received;
28
 	enum { RESULT_CODE, HEADER, DATA, ERROR, MOVED } recv_state;
30
 	enum { RESULT_CODE, HEADER, DATA, ERROR, MOVED } recv_state;
29
 	int rc;
31
 	int rc;
30
-	char location[MAX_URL+1];
32
+	char *url;
31
 };
33
 };
32
 
34
 
33
 static int send_tcp_request(int length, void *buffer, void *ptr) {
35
 static int send_tcp_request(int length, void *buffer, void *ptr) {
56
 				int rc = strtoul(ptr, &ptr, 10);
58
 				int rc = strtoul(ptr, &ptr, 10);
57
 				if (ptr >= (const char *)buffer + length) {
59
 				if (ptr >= (const char *)buffer + length) {
58
 					state->recv_state = ERROR;
60
 					state->recv_state = ERROR;
61
+					DBG ( "HTTP got bad result code\n" );
59
 					return 0;
62
 					return 0;
60
 				}
63
 				}
61
 				state->rc = rc;
64
 				state->rc = rc;
62
 				state->recv_state = HEADER;
65
 				state->recv_state = HEADER;
66
+				DBG ( "HTTP got result code %d\n", rc );
63
 				goto header;
67
 				goto header;
64
 			}
68
 			}
65
 			++(const char *)buffer;
69
 			++(const char *)buffer;
66
 			length--;
70
 			length--;
67
 		}
71
 		}
68
 		state->recv_state = ERROR;
72
 		state->recv_state = ERROR;
73
+		DBG ( "HTTP got no result code\n" );
69
 		return 0;
74
 		return 0;
70
 	}
75
 	}
71
 	if (state->recv_state == HEADER) {
76
 	if (state->recv_state == HEADER) {
73
 			/* Check for HTTP redirect */
78
 			/* Check for HTTP redirect */
74
 			if (state->rc >= 300 && state->rc < 400 &&
79
 			if (state->rc >= 300 && state->rc < 400 &&
75
 			    !memcmp(buffer, "Location: ", 10)) {
80
 			    !memcmp(buffer, "Location: ", 10)) {
76
-				char *ptr = state->location;
77
-				int i;
78
-				memcpy(ptr, buffer + 10, MAX_URL);
79
-				for (i = 0; i < MAX_URL && *ptr > ' ';
80
-				     i++, ptr++);
81
-				*ptr = '\000';
81
+				char *p;
82
+				
83
+				state->url = p = ( char * ) buffer + 10;
84
+				while ( *p > ' ' ) {
85
+					p++;
86
+				}
87
+				*p = '\0';
82
 				state->recv_state = MOVED;
88
 				state->recv_state = MOVED;
89
+				DBG ( "HTTP got redirect to %s\n",
90
+				      state->url );
83
 				return 1;
91
 				return 1;
84
 			}
92
 			}
85
 			/* Find beginning of line */
93
 			/* Find beginning of line */
99
 	}
107
 	}
100
 	if (state->recv_state == DATA) {
108
 	if (state->recv_state == DATA) {
101
 		state->bytes_received += length;
109
 		state->bytes_received += length;
110
+		DBG2 ( "HTTP received %d bytes\n", length );
102
 		while (length > 0) {
111
 		while (length > 0) {
103
 			int copy_length = BLOCKSIZE - state->recv_length;
112
 			int copy_length = BLOCKSIZE - state->recv_length;
104
 			if (copy_length > length)
113
 			if (copy_length > length)
106
 			memcpy(state->recv_buffer + state->recv_length,
115
 			memcpy(state->recv_buffer + state->recv_length,
107
 			       buffer, copy_length);
116
 			       buffer, copy_length);
108
 			if ((state->recv_length += copy_length) == BLOCKSIZE) {
117
 			if ((state->recv_length += copy_length) == BLOCKSIZE) {
109
-				if (!state->fnc(state->recv_buffer,
110
-						++state->block, BLOCKSIZE, 0))
111
-					return 0;
118
+				DBG2 ( "HTTP processing %d bytes\n",
119
+				      BLOCKSIZE );
120
+				if (!state->process(state->recv_buffer,
121
+						    ++state->block,
122
+						    BLOCKSIZE, 0))
112
 				state->recv_length = 0;
123
 				state->recv_length = 0;
113
 			}
124
 			}
114
 			length -= copy_length;
125
 			length -= copy_length;
121
 /**************************************************************************
132
 /**************************************************************************
122
 HTTP_GET - Get data using HTTP
133
 HTTP_GET - Get data using HTTP
123
 **************************************************************************/
134
 **************************************************************************/
124
-int http(const char *url,
125
-		int (*fnc)(unsigned char *, unsigned int, unsigned int, int)) {
135
+static int http ( char *url,
136
+		  struct sockaddr_in *server __unused,
137
+		  char *file __unused,
138
+		  int ( * process ) ( unsigned char *data,
139
+				      unsigned int blocknum,
140
+				      unsigned int len, int eof ) ) {
141
+	struct protocol *proto;
142
+	struct sockaddr_in http_server = *server;
143
+	char *filename;
126
 	static const char GET[] = "GET /%s HTTP/1.0\r\n\r\n";
144
 	static const char GET[] = "GET /%s HTTP/1.0\r\n\r\n";
127
 	static char recv_buffer[BLOCKSIZE];
145
 	static char recv_buffer[BLOCKSIZE];
128
-	in_addr destip;
129
-	int port;
130
-	int length;
131
 	struct send_recv_state state;
146
 	struct send_recv_state state;
147
+	int length;
132
 
148
 
133
-	state.fnc = fnc;
134
 	state.rc = -1;
149
 	state.rc = -1;
135
 	state.block = 0;
150
 	state.block = 0;
136
 	state.recv_buffer = recv_buffer;
151
 	state.recv_buffer = recv_buffer;
137
-	length = strlen(url);
138
-	if (length <= MAX_URL) {
139
-		memcpy(state.location, url, length+1);
140
-		destip = arptable[ARP_SERVER].ipaddr;
141
-		port = url_port;
142
-		if (port == -1)
143
-		  port = 80;
144
-		goto first_time;
145
-
146
-		do {
147
-			state.rc = -1;
148
-			state.block = 0;
149
-			url = state.location;
150
-			if (memcmp("http://", url, 7))
151
-				break;
152
-			url += 7;
153
-			length = inet_aton(url, &destip);
154
-			if (!length) {
155
-				/* As we do not have support for DNS, assume*/
156
-				/* that HTTP redirects always point to the */
157
-				/* same machine */
158
-				if (state.recv_state == MOVED) {
159
-					while (*url &&
160
-					*url != ':' && *url != '/') url++;
161
-				} else {
162
-					break;
163
-				}
164
-			}
165
-			if (*(url += length) == ':') {
166
-				port = strtoul(url, &url, 10);
167
-			} else {
168
-				port = 80;
169
-			}
170
-			if (!*url)
171
-				url = "/";
172
-			if (*url != '/')
173
-				break;
174
-			url++;
152
+	state.url = url;
153
+	state.process = process;
154
+	while ( 1 ) {
155
+		length = strlen ( filename ) + strlen ( GET );
156
+		{
157
+			char send_buf[length];
175
 
158
 
176
-		first_time:
177
-			length = strlen(url);
178
-			state.send_length = sizeof(GET) - 3 + length;
179
-			
180
-			{ char buf[state.send_length + 1];
181
-			sprintf(state.send_buffer = buf, GET, url);
159
+			sprintf ( send_buf, GET, filename );
160
+			state.send_buffer = send_buf;
161
+			state.send_length = strlen ( send_buf );
182
 			state.bytes_sent = 0;
162
 			state.bytes_sent = 0;
183
 			
163
 			
184
 			state.bytes_received = 0;
164
 			state.bytes_received = 0;
185
 			state.recv_state = RESULT_CODE;
165
 			state.recv_state = RESULT_CODE;
186
 			
166
 			
187
 			state.recv_length = 0;
167
 			state.recv_length = 0;
188
-			tcp_transaction(destip.s_addr, 80, &state,
189
-					send_tcp_request, recv_tcp_request);
168
+			tcp_transaction ( server->sin_addr.s_addr,
169
+					  server->sin_port, &state,
170
+					  send_tcp_request, recv_tcp_request );
171
+		}
172
+
173
+		if ( state.recv_state == MOVED ) {
174
+			if ( ! parse_url ( state.url, &proto,
175
+					   &http_server, &filename ) ) {
176
+				printf ( "Invalid redirect URL %s\n",
177
+					 state.url );
178
+				return 0;
190
 			}
179
 			}
191
-		} while (state.recv_state == MOVED);
192
-	} else {
193
-		memcpy(state.location, url, MAX_URL);
194
-		state.location[MAX_URL] = '\000';
180
+			continue;
181
+		}
182
+		
183
+		break;
195
 	}
184
 	}
196
 
185
 
197
-	if (state.rc == 200) {
198
-		return fnc(recv_buffer, ++state.block, state.recv_length, 1);
186
+	if ( state.rc == 200 ) {
187
+		DBG2 ( "HTTP processing %d bytes\n", state.recv_length );
188
+		return process ( recv_buffer, ++state.block,
189
+				 state.recv_length, 1 );
199
 	} else {
190
 	} else {
200
-		printf("Failed to download %s (rc = %d)\n",
201
-		       state.location, state.rc);
191
+		printf ( "Failed to download %s (rc = %d)\n",
192
+			 state.url, state.rc );
202
 		return 0;
193
 		return 0;
203
 	}
194
 	}
204
 }
195
 }
205
 
196
 
206
-#endif /* DOWNLOAD_PROTO_HTTP */
197
+static struct protocol http_protocol __protocol = {
198
+	.name = "http",
199
+	.default_port = 80,
200
+	.load = http,
201
+};

Loading…
Cancel
Save