1 /* $NetBSD: file_http.cpp,v 1.11 2006/03/05 04:05:39 uwe Exp $ */
4 * Copyright (c) 2001, 2002, 2004 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 #include <file_http.h>
35 #include <libsa_string.h>
37 #define wcsicmp _wcsicmp
38 static int WCE210_WSAStartup(WORD
, LPWSADATA
);
39 static int WCE210_WSACleanup(void);
41 HttpFile::HttpFile(Console
*&cons
)
45 _req_host(" HTTP/1.0\r\nHOST: "),
46 _req_ua("\r\nUser-Agent: HPCBOOT/ZERO(1st impact; Windows CE; "
61 _server_name
[0] = '\0';
64 // _memory_cache = FALSE; // not recomended.
67 DPRINTF((TEXT("FileManager: HTTP\n")));
70 _wsa_startup
= WCE210_WSAStartup
;
71 _wsa_cleanup
= WCE210_WSACleanup
;
73 if (WinCEVersion
.dwMajorVersion
> 3 ||
74 (WinCEVersion
.dwMajorVersion
> 2) &&
75 (WinCEVersion
.dwMinorVersion
>= 11)) {
76 _wsa_startup
= WSAStartup
;
77 _wsa_cleanup
= WSACleanup
;
79 _wsa_startup
= WCE210_WSAStartup
;
80 _wsa_cleanup
= WCE210_WSACleanup
;
86 WCE210_WSAStartup(WORD ver
, LPWSADATA data
)
90 data
->wHighVersion
= ver
;
91 data
->szDescription
[0] = '\0';
92 data
->szSystemStatus
[0] = '\0';
93 data
->iMaxSockets
= 10;
95 data
->lpVendorInfo
= NULL
;
107 HttpFile::~HttpFile(void)
115 HttpFile::_reset_state(void)
117 _ascii_filename
[0] = '\0';
127 HttpFile::setRoot(TCHAR
*server
)
132 // parse server name and its port #
133 TCHAR sep
[] = TEXT(":/");
135 TCHAR
*token
= wcstok(server
, sep
);
136 for (int i
= 0; i
< 3 && token
; i
++, token
= wcstok(0, sep
)) {
139 if (wcsicmp(token
, TEXT("http"))) {
144 if (!_to_ascii(_server_name
, token
, MAX_PATH
))
154 WORD version
= MAKEWORD(1, 1);
155 ret
= _wsa_startup(version
, &_winsock
);
157 DPRINTF((TEXT("WinSock initialize failed.\n")));
160 if (LOBYTE(_winsock
.wVersion
) != 1 ||
161 HIBYTE(_winsock
.wVersion
) != 1) {
162 DPRINTF((TEXT("can't use WinSock DLL.\n")));
166 h
= socket(AF_INET
, SOCK_STREAM
, 0);
167 if (h
== INVALID_SOCKET
) {
168 DPRINTF((TEXT("can't open socket. cause=%d\n"),
173 memset(&_sockaddr
, 0, sizeof(sockaddr_in
));
174 _sockaddr
.sin_family
= AF_INET
;
175 _sockaddr
.sin_port
= htons(port
);
177 struct hostent
*entry
= gethostbyname(_server_name
);
179 _sockaddr
.sin_addr
.S_un
.S_addr
= inet_addr(_server_name
);
180 if (_sockaddr
.sin_addr
.S_un
.S_addr
== INADDR_NONE
) {
181 DPRINTF((TEXT("can't get host by name.\n")));
184 uint8_t *b
= &_sockaddr
.sin_addr
.S_un
.S_un_b
.s_b1
;
185 DPRINTF((TEXT("%d.%d.%d.%d "), b
[0], b
[1], b
[2], b
[3]));
186 if (connect(h
,(const struct sockaddr
*)&_sockaddr
,
187 sizeof(struct sockaddr_in
)) == 0)
190 for (uint8_t **addr_list
=(uint8_t **)entry
->h_addr_list
;
191 *addr_list
; addr_list
++) {
192 uint8_t *b
= &_sockaddr
.sin_addr
.S_un
.S_un_b
.s_b1
;
193 for (int i
= 0; i
< 4; i
++)
194 b
[i
] = addr_list
[0][i
];
196 DPRINTF((TEXT("%d.%d.%d.%d "), b
[0], b
[1], b
[2],b
[3]));
197 if (connect(h
,(const struct sockaddr
*)&_sockaddr
,
198 sizeof(struct sockaddr_in
)) == 0)
202 DPRINTF((TEXT("can't connect server.\n")));
206 DPRINTF((TEXT("(%S) connected.\n"), _server_name
));
213 HttpFile::open(const TCHAR
*name
, uint32_t flag
)
218 return _to_ascii(_ascii_filename
, name
, MAX_PATH
);
222 HttpFile::_read_from_cache(void *buf
, size_t bytes
, off_t ofs
)
226 if (ofs
>= _buffer_size
)
229 transfer
= ofs
+ bytes
> _buffer_size
? _buffer_size
- ofs
: bytes
;
231 memcpy(buf
, &_buffer
[ofs
], transfer
);
237 HttpFile::seek(off_t offset
)
245 HttpFile::read(void *buf
, size_t bytes
, off_t offset
)
257 if (_memory_cache
&& _cached
)
258 return _read_from_cache(buf
, bytes
, ofs
);
260 // HEAD request(get header size).
261 if (_header_size
== 0)
262 _buffer_size
= _parse_header(_header_size
);
265 Socket
sock(_sockaddr
);
267 if ((h
= sock
) == INVALID_SOCKET
)
271 strcpy(_request
, _req_get
);
273 send(h
, _request
, strlen(_request
), 0);
276 b
= static_cast <char *>(malloc(_header_size
));
277 _recv_buffer(h
, b
, _header_size
);
283 _buffer
= static_cast <char *>(malloc(_buffer_size
));
284 _recv_buffer(h
, _buffer
, _buffer_size
);
286 return _read_from_cache(buf
, bytes
, ofs
);
288 int i
, n
= ofs
/ bytes
;
289 b
= static_cast <char *>(buf
);
291 for (readed
= 0, i
= 0; i
< n
; i
++)
292 readed
+= _recv_buffer(h
, b
, bytes
);
293 if ((n
=(ofs
% bytes
)))
294 readed
+= _recv_buffer(h
, b
, n
);
295 DPRINTF((TEXT("skip contents %d byte.\n"), readed
));
297 readed
= _recv_buffer(h
, b
, bytes
);
303 HttpFile::_parse_header(size_t &header_size
)
310 Socket
sock(_sockaddr
);
312 if ((h
= sock
) == INVALID_SOCKET
) {
313 DPRINTF((TEXT("can't open socket.\n")));
318 strcpy(_request
, _req_head
);
320 send(h
, _request
, strlen(_request
), 0);
322 // Receive and search Content-Length: field.
323 if ((buf
= static_cast<char *>(malloc(TMP_BUFFER_SIZE
))) == 0) {
324 DPRINTF((TEXT("can't allocate receive buffer.\n")));
329 for (cnt
= 0; ret
= _recv_buffer(h
, buf
, TMP_BUFFER_SIZE
- 1);
332 char sep
[] = " :\r\n";
333 char *token
= libsa::strtok(buf
, sep
);
335 DPRINTFN(2, (TEXT("+token: %S\n"), token
));
336 if (libsa::stricmp(token
, "content-length") == 0) {
337 DPRINTFN(2, (TEXT("*token: %S\n"), token
));
338 token
= libsa::strtok(0, sep
);
341 DPRINTFN(2, (TEXT("*content-length=%d\n"), sz
));
343 token
= libsa::strtok(0, sep
);
350 DPRINTF((TEXT("No Content-Length.\n")));
353 ("open http://%S%S - header %d byte contents %d byte\n"),
354 _server_name
, _ascii_filename
, header_size
, sz
));
362 HttpFile::_recv_buffer(SOCKET h
, char *buf
, size_t size
)
364 size_t cnt
, total
= 0;
367 cnt
= recv(h
, buf
+ total
, size
- total
, 0);
369 DPRINTFN(2,(TEXT("size %d readed %d byte(+%d)\n"),
371 } while (total
< size
&& cnt
> 0);
373 DPRINTFN(1,(TEXT("total read %d byte\n"), total
));
378 HttpFile::_set_request(void)
381 strcat(_request
, _ascii_filename
);
382 strcat(_request
, _req_host
);
383 strcat(_request
, _server_name
);
384 strcat(_request
, _req_ua
);
387 Socket::Socket(struct sockaddr_in
&sock
)
391 _socket
= socket(AF_INET
, SOCK_STREAM
, 0);
392 if (_socket
!= INVALID_SOCKET
)
394 reinterpret_cast <const struct sockaddr
*>(&_sockaddr
),
395 sizeof(struct sockaddr_in
));
398 Socket::~Socket(void)
401 if (_socket
!= INVALID_SOCKET
)
402 closesocket(_socket
);