OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [redboot/] [current/] [src/] [net/] [http_client.c] - Blame information for rev 786

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.