root/ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/http_client.c

Revision 12368, 6.6 kB (checked in by BrainSlayer, 5 months ago)

tftp server added, supports wiligear, ubiquiti and dd-wrt webflash format

Line 
1 //==========================================================================
2 //
3 //      net/http_client.c
4 //
5 //      Stand-alone HTTP support for RedBoot
6 //
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 // Copyright (C) 2002, 2003 Gary Thomas
13 //
14 // eCos is free software; you can redistribute it and/or modify it under
15 // the terms of the GNU General Public License as published by the Free
16 // Software Foundation; either version 2 or (at your option) any later version.
17 //
18 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
19 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
21 // for more details.
22 //
23 // You should have received a copy of the GNU General Public License along
24 // with eCos; if not, write to the Free Software Foundation, Inc.,
25 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 //
27 // As a special exception, if other files instantiate templates or use macros
28 // or inline functions from this file, or you compile this file and link it
29 // with other works to produce a work based on this file, this file does not
30 // by itself cause the resulting work to be covered by the GNU General Public
31 // License. However the source code for this file must still be made available
32 // in accordance with section (3) of the GNU General Public License.
33 //
34 // This exception does not invalidate any other reasons why a work based on
35 // this file might be covered by the GNU General Public License.
36 //
37 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
38 // at http://sources.redhat.com/ecos/ecos-license/
39 // -------------------------------------------
40 //####ECOSGPLCOPYRIGHTEND####
41 //==========================================================================
42 //#####DESCRIPTIONBEGIN####
43 //
44 // Author(s):    gthomas
45 // Contributors: gthomas
46 // Date:         2002-05-22
47 // Purpose:     
48 // Description: 
49 //             
50 // This code is part of RedBoot (tm).
51 //
52 //####DESCRIPTIONEND####
53 //
54 //==========================================================================
55
56 // HTTP client support
57
58 #include <redboot.h>            // have_net
59 #include <net/net.h>
60 #include <net/http.h>
61
62 // So we remember which ports have been used
63 static int get_port = 7800;
64
65 static struct _stream {
66         bool open;
67         int avail, actual_len, pos, filelen;
68         char data[4096];
69         char *bufp;
70         tcp_socket_t sock;
71 } http_stream;
72
73 static __inline__ int min(int a, int b)
74 {
75         if (a < b)
76                 return a;
77         else
78                 return b;
79 }
80
81 int http_stream_open(connection_info_t * info, int *err)
82 {
83         int res;
84         struct _stream *s = &http_stream;
85
86         if (!info->server->sin_port)
87                 info->server->sin_port = 80;    // HTTP port
88         if ((res =
89              __tcp_open(&s->sock, info->server, get_port++, 5000, err)) < 0) {
90                 *err = HTTP_OPEN;
91                 return -1;
92         }
93         diag_sprintf(s->data, "GET %s HTTP/1.0\r\n\r\n", info->filename);
94         __tcp_write_block(&s->sock, s->data, strlen(s->data));
95         s->avail = 0;
96         s->open = true;
97         s->pos = 0;
98         return 0;
99 }
100
101 void http_stream_close(int *err)
102 {
103         struct _stream *s = &http_stream;
104
105         if (s->open) {
106                 __tcp_abort(&s->sock, 1);
107                 s->open = false;
108         }
109 }
110
111 int http_stream_read(char *buf, int len, int *err)
112 {
113         struct _stream *s = &http_stream;
114         int total = 0;
115         int cnt, code;
116
117         if (!s->open) {
118                 return -1;      // Shouldn't happen, but...
119         }
120         while (len) {
121                 while (s->avail == 0) {
122                         // Need to wait for some data to arrive
123                         __tcp_poll();
124                         if (s->sock.state != _ESTABLISHED) {
125                                 if (s->sock.state == _CLOSE_WAIT) {
126                                         // This connection is breaking
127                                         if (s->sock.data_bytes == 0
128                                             && s->sock.rxcnt == 0) {
129                                                 __tcp_close(&s->sock);
130                                                 return total;
131                                         }
132                                 } else if (s->sock.state == _CLOSED) {
133                                         // The connection is gone
134                                         s->open = false;
135                                         return -1;
136                                 } else {
137                                         *err = HTTP_IO;
138                                         return -1;
139                                 }
140                         }
141                         s->actual_len =
142                             __tcp_read(&s->sock, s->data, sizeof(s->data));
143                         if (s->actual_len > 0) {
144                                 s->bufp = s->data;
145                                 s->avail = s->actual_len;
146                                 if (s->pos == 0) {
147                                         // First data - need to scan HTTP response header
148                                         if (strncmp(s->bufp, "HTTP/", 5) == 0) {
149                                                 // Should look like "HTTP/1.1 200 OK"
150                                                 s->bufp += 5;
151                                                 s->avail -= 5;
152                                                 // Find first space
153                                                 while ((s->avail > 0)
154                                                        && (*s->bufp != ' ')) {
155                                                         s->bufp++;
156                                                         s->avail--;
157                                                 }
158                                                 // Now the integer response
159                                                 code = 0;
160                                                 while ((s->avail > 0)
161                                                        && (*s->bufp == ' ')) {
162                                                         s->bufp++;
163                                                         s->avail--;
164                                                 }
165                                                 while ((s->avail > 0)
166                                                        && isdigit(*s->bufp)) {
167                                                         code =
168                                                             (code * 10) +
169                                                             (*s->bufp - '0');
170                                                         s->bufp++;
171                                                         s->avail--;
172                                                 }
173                                                 // Make sure it says OK
174                                                 while ((s->avail > 0)
175                                                        && (*s->bufp == ' ')) {
176                                                         s->bufp++;
177                                                         s->avail--;
178                                                 }
179                                                 if (strncmp(s->bufp, "OK", 2)) {
180                                                         switch (code) {
181                                                         case 400:
182                                                                 *err =
183                                                                     HTTP_BADREQ;
184                                                                 break;
185                                                         case 404:
186                                                                 *err =
187                                                                     HTTP_NOFILE;
188                                                                 break;
189                                                         default:
190                                                                 *err =
191                                                                     HTTP_BADHDR;
192                                                                 break;
193                                                         }
194                                                         return -1;
195                                                 }
196                                                 // Find \r\n\r\n - end of HTTP preamble
197                                                 while (s->avail >= 4) {
198                                                         // This could be done faster, but not simpler
199                                                         if (strncmp
200                                                             (s->bufp,
201                                                              "\r\n\r\n",
202                                                              4) == 0) {
203                                                                 s->bufp += 4;
204                                                                 s->avail -= 4;
205 #if 0                           // DEBUG - show header
206                                                                 *(s->bufp - 2) =
207                                                                     '\0';
208                                                                 diag_printf
209                                                                     (s->data);
210 #endif
211                                                                 break;
212                                                         }
213                                                         s->avail--;
214                                                         s->bufp++;
215                                                 }
216                                                 s->pos++;
217                                         } else {
218                                                 // Unrecognized response
219                                                 *err = HTTP_BADHDR;
220                                                 return -1;
221                                         }
222                                 }
223                         } else if (s->actual_len < 0) {
224                                 *err = HTTP_IO;
225                                 return -1;
226                         }
227                 }
228                 cnt = min(len, s->avail);
229                 memcpy(buf, s->bufp, cnt);
230                 s->avail -= cnt;
231                 s->bufp += cnt;
232                 buf += cnt;
233                 total += cnt;
234                 len -= cnt;
235         }
236         return total;
237 }
238
239 char *http_error(int err)
240 {
241         char *errmsg = "Unknown error";
242
243         switch (err) {
244         case HTTP_NOERR:
245                 return "";
246         case HTTP_BADHDR:
247                 return "Unrecognized HTTP response";
248         case HTTP_BADREQ:
249                 return "Bad HTTP request (check file name)";
250         case HTTP_NOFILE:
251                 return "No such file";
252         case HTTP_OPEN:
253                 return "Can't connect to host";
254         case HTTP_IO:
255                 return "I/O error";
256         }
257         return errmsg;
258 }
259
260 //
261 // RedBoot interface
262 //
263 GETC_IO_FUNCS(http_io, http_stream_open, http_stream_close,
264               0, http_stream_read, http_error);
265 RedBoot_load(http, http_io, true, true, 0);
Note: See TracBrowser for help on using the browser.