Преглед изворни кода

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 година
родитељ
комит
4ed412f1c2
1 измењених фајлова са 70 додато и 75 уклоњено
  1. 70
    75
      src/proto/http.c

+ 70
- 75
src/proto/http.c Прегледај датотеку

@@ -1,7 +1,7 @@
1
+#include "proto.h"
2
+#include "tcp.h"
3
+#include "url.h"
1 4
 #include "etherboot.h"
2
-#include "http.h"
3
-
4
-#ifdef DOWNLOAD_PROTO_HTTP
5 5
 
6 6
 /* The block size is currently chosen to be 512 bytes. This means, we can
7 7
    allocate the receive buffer on the stack, but it results in a noticeable
@@ -17,7 +17,9 @@
17 17
 SEND_TCP_CALLBACK - Send data using TCP
18 18
 **************************************************************************/
19 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 23
 	char *send_buffer;
22 24
 	char *recv_buffer;
23 25
 	int send_length;
@@ -27,7 +29,7 @@ struct send_recv_state {
27 29
 	int bytes_received;
28 30
 	enum { RESULT_CODE, HEADER, DATA, ERROR, MOVED } recv_state;
29 31
 	int rc;
30
-	char location[MAX_URL+1];
32
+	char *url;
31 33
 };
32 34
 
33 35
 static int send_tcp_request(int length, void *buffer, void *ptr) {
@@ -56,16 +58,19 @@ static int recv_tcp_request(int length, const void *buffer, void *ptr) {
56 58
 				int rc = strtoul(ptr, &ptr, 10);
57 59
 				if (ptr >= (const char *)buffer + length) {
58 60
 					state->recv_state = ERROR;
61
+					DBG ( "HTTP got bad result code\n" );
59 62
 					return 0;
60 63
 				}
61 64
 				state->rc = rc;
62 65
 				state->recv_state = HEADER;
66
+				DBG ( "HTTP got result code %d\n", rc );
63 67
 				goto header;
64 68
 			}
65 69
 			++(const char *)buffer;
66 70
 			length--;
67 71
 		}
68 72
 		state->recv_state = ERROR;
73
+		DBG ( "HTTP got no result code\n" );
69 74
 		return 0;
70 75
 	}
71 76
 	if (state->recv_state == HEADER) {
@@ -73,13 +78,16 @@ static int recv_tcp_request(int length, const void *buffer, void *ptr) {
73 78
 			/* Check for HTTP redirect */
74 79
 			if (state->rc >= 300 && state->rc < 400 &&
75 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 88
 				state->recv_state = MOVED;
89
+				DBG ( "HTTP got redirect to %s\n",
90
+				      state->url );
83 91
 				return 1;
84 92
 			}
85 93
 			/* Find beginning of line */
@@ -99,6 +107,7 @@ static int recv_tcp_request(int length, const void *buffer, void *ptr) {
99 107
 	}
100 108
 	if (state->recv_state == DATA) {
101 109
 		state->bytes_received += length;
110
+		DBG2 ( "HTTP received %d bytes\n", length );
102 111
 		while (length > 0) {
103 112
 			int copy_length = BLOCKSIZE - state->recv_length;
104 113
 			if (copy_length > length)
@@ -106,9 +115,11 @@ static int recv_tcp_request(int length, const void *buffer, void *ptr) {
106 115
 			memcpy(state->recv_buffer + state->recv_length,
107 116
 			       buffer, copy_length);
108 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 123
 				state->recv_length = 0;
113 124
 			}
114 125
 			length -= copy_length;
@@ -121,86 +132,70 @@ static int recv_tcp_request(int length, const void *buffer, void *ptr) {
121 132
 /**************************************************************************
122 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 144
 	static const char GET[] = "GET /%s HTTP/1.0\r\n\r\n";
127 145
 	static char recv_buffer[BLOCKSIZE];
128
-	in_addr destip;
129
-	int port;
130
-	int length;
131 146
 	struct send_recv_state state;
147
+	int length;
132 148
 
133
-	state.fnc = fnc;
134 149
 	state.rc = -1;
135 150
 	state.block = 0;
136 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 162
 			state.bytes_sent = 0;
183 163
 			
184 164
 			state.bytes_received = 0;
185 165
 			state.recv_state = RESULT_CODE;
186 166
 			
187 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 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 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…
Откажи
Сачувај