summaryrefslogtreecommitdiffstats
path: root/cfe/cfe/main/cfe_httpfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'cfe/cfe/main/cfe_httpfs.c')
-rw-r--r--cfe/cfe/main/cfe_httpfs.c396
1 files changed, 396 insertions, 0 deletions
diff --git a/cfe/cfe/main/cfe_httpfs.c b/cfe/cfe/main/cfe_httpfs.c
new file mode 100644
index 0000000..4ebad4c
--- /dev/null
+++ b/cfe/cfe/main/cfe_httpfs.c
@@ -0,0 +1,396 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * "HTTP" file system File: cfe_httpfs.c
+ *
+ * This filesystem driver lets you read files from an HTTP
+ * server.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_error.h"
+#include "cfe_fileops.h"
+#include "cfe_iocb.h"
+#include "cfe_devfuncs.h"
+#include "cfe_console.h"
+
+#include "cfe.h"
+
+#include "bsp_config.h"
+
+#if (CFG_TCP) && (CFG_HTTPFS)
+
+#include "net_ebuf.h"
+#include "net_api.h"
+
+
+/* *********************************************************************
+ * HTTP context
+ ********************************************************************* */
+
+/*
+ * File system context - describes overall file system info,
+ * such as the handle to the underlying device.
+ */
+
+typedef struct http_fsctx_s {
+ int http_tmp; /* context not really needed */
+} http_fsctx_t;
+
+/*
+ * File context - describes an open file on the file system.
+ */
+
+#define HTTP_BUFSIZE 1024
+typedef struct http_file_s {
+ http_fsctx_t *http_fsctx;
+ int http_socket;
+ uint8_t http_buffer[HTTP_BUFSIZE];
+ uint8_t *http_bptr;
+ int http_blen;
+ int http_offset;
+ char *http_filename;
+} http_file_t;
+
+/* *********************************************************************
+ * Prototypes
+ ********************************************************************* */
+
+static int http_fileop_init(void **fsctx,void *devicename);
+static int http_fileop_open(void **ref,void *fsctx,char *filename,int mode);
+static int http_fileop_read(void *ref,uint8_t *buf,int len);
+static int http_fileop_write(void *ref,uint8_t *buf,int len);
+static int http_fileop_seek(void *ref,int offset,int how);
+static void http_fileop_close(void *ref);
+static void http_fileop_uninit(void *fsctx);
+
+/* *********************************************************************
+ * RAW fileio dispatch table
+ ********************************************************************* */
+
+const fileio_dispatch_t http_fileops = {
+ "http",
+ FSYS_TYPE_NETWORK,
+ http_fileop_init,
+ http_fileop_open,
+ http_fileop_read,
+ http_fileop_write,
+ http_fileop_seek,
+ http_fileop_close,
+ http_fileop_uninit
+};
+
+static int http_fileop_init(void **newfsctx,void *dev)
+{
+ http_fsctx_t *fsctx;
+
+ *newfsctx = NULL;
+
+ fsctx = KMALLOC(sizeof(http_fsctx_t),0);
+ if (!fsctx) {
+ return CFE_ERR_NOMEM;
+ }
+
+ fsctx->http_tmp = 0;
+ *newfsctx = fsctx;
+
+ return 0;
+}
+
+static int http_fileop_open(void **ref,void *fsctx_arg,char *filename,int mode)
+{
+ http_fsctx_t *fsctx;
+ http_file_t *file;
+ char temp[200];
+ char *hostname, *filen;
+ int hlen;
+ int termidx;
+ int res;
+ int err = 0;
+ char *hptr;
+ char *tok;
+ uint8_t hostaddr[IP_ADDR_LEN];
+ uint8_t termstr[4];
+ uint8_t b;
+
+ if (mode != FILE_MODE_READ) return CFE_ERR_UNSUPPORTED;
+
+ fsctx = (http_fsctx_t *) fsctx_arg;
+
+ file = KMALLOC(sizeof(http_file_t),0);
+ if (!file) {
+ return CFE_ERR_NOMEM;
+ }
+
+ file->http_filename = lib_strdup(filename);
+ if (!file->http_filename) {
+ KFREE(file);
+ return CFE_ERR_NOMEM;
+ }
+
+ lib_chop_filename(file->http_filename,&hostname,&filen);
+
+ /*
+ * Look up remote host
+ */
+
+ res = dns_lookup(hostname,hostaddr);
+ if (res < 0) {
+ KFREE(file);
+ return res;
+ }
+
+ file->http_socket = tcp_socket();
+ if (file->http_socket < 0) {
+ KFREE(file->http_filename);
+ KFREE(file);
+ return -1;
+ }
+
+ /*
+ * Connect to remote host.
+ */
+
+ tcp_setflags(file->http_socket,0); /* set socket to blocking */
+ res = tcp_connect(file->http_socket,hostaddr,80);
+
+ if (res < 0) {
+ tcp_close(file->http_socket);
+ KFREE(file->http_filename);
+ KFREE(file);
+ return res;
+ }
+
+ /*
+ * Send GET command. Supply the hostname (for HTTP 1.1 requirements)
+ * and set the connection to close as soon as all the data is received.
+ */
+
+ hlen = sprintf(temp,"GET /%s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n",filen,hostname);
+
+ res = tcp_send(file->http_socket,temp,hlen);
+ if (res < 0) {
+ tcp_close(file->http_socket);
+ KFREE(file->http_filename);
+ KFREE(file);
+ return res;
+ }
+
+ /*
+ * Read bytes until we either reach EOF or we see "\r\n\r\n"
+ * This is the server's status string.
+ */
+
+ termstr[0] = '\r'; termstr[1] = '\n';
+ termstr[2] = '\r'; termstr[3] = '\n';
+ termidx = 0;
+
+ file->http_offset = 0;
+ file->http_blen = 0;
+ file->http_bptr = file->http_buffer;
+
+ res = 0;
+ for (;;) {
+ res = tcp_recv(file->http_socket,&b,1);
+ if (res < 0) break;
+ if (b == termstr[termidx]) {
+ termidx++;
+ if (termidx == 4) break;
+ }
+ else {
+ termidx = 0;
+ }
+
+ /*
+ * Save the bytes from the header up to our buffer
+ * size. It's okay if we don't save it all,
+ * since all we want is the result code which comes
+ * first.
+ */
+
+ if (file->http_blen < (HTTP_BUFSIZE-1)) {
+ *(file->http_bptr) = b;
+ file->http_bptr++;
+ file->http_blen++;
+ }
+ }
+
+ /*
+ * Premature EOFs are not good, bail now.
+ */
+
+ if (res < 0) {
+ err = CFE_ERR_EOF;
+ goto protocolerr;
+ }
+
+ /*
+ * Skip past the HTTP response header and grab the result code.
+ * Sanity check it a little.
+ */
+
+ *(file->http_bptr) = 0;
+
+ hptr = file->http_buffer;
+ tok = lib_gettoken(&hptr);
+ if (!tok || (memcmp(tok,"HTTP",4) != 0)) {
+ err = CFE_ERR_PROTOCOLERR;
+ goto protocolerr;
+ }
+
+ tok = lib_gettoken(&hptr);
+ if (!tok) {
+ err = CFE_ERR_PROTOCOLERR;
+ goto protocolerr;
+ }
+
+ switch (lib_atoi(tok)) {
+ case 200:
+ err = 0;
+ break;
+ case 404:
+ err = CFE_ERR_FILENOTFOUND;
+ break;
+
+ }
+
+ /*
+ * If we get to here, the file is okay and we're about to receive data.
+ */
+
+ if (err == 0) {
+ *ref = file;
+ return 0;
+ }
+
+protocolerr:
+ tcp_close(file->http_socket);
+ KFREE(file->http_filename);
+ KFREE(file);
+ *ref = NULL;
+ return err;
+}
+
+static int http_fileop_read(void *ref,uint8_t *buf,int len)
+{
+ http_file_t *file = (http_file_t *) ref;
+ int res;
+
+ res = tcp_recv(file->http_socket,buf,len);
+
+ if (res > 0) {
+ file->http_offset += res;
+ return res;
+ }
+
+ return 0; /* Any error becomes "EOF" */
+}
+
+static int http_fileop_write(void *ref,uint8_t *buf,int len)
+{
+ return CFE_ERR_UNSUPPORTED;
+}
+
+static int http_fileop_seek(void *ref,int offset,int how)
+{
+ http_file_t *file = (http_file_t *) ref;
+ int newoffset;
+ int res;
+ int buflen;
+
+ switch (how) {
+ case FILE_SEEK_BEGINNING:
+ newoffset = offset;
+ break;
+ case FILE_SEEK_CURRENT:
+ newoffset = file->http_offset + offset;
+ break;
+ default:
+ newoffset = offset;
+ break;
+ }
+
+ /*
+ * Can't seek backwards.
+ */
+ if (newoffset < file->http_offset) {
+ return CFE_ERR_UNSUPPORTED;
+ }
+
+ /*
+ * Eat data till offset reaches where we want.
+ */
+
+ while (file->http_offset != newoffset) {
+ buflen = HTTP_BUFSIZE;
+ if (buflen > (newoffset - file->http_offset)) buflen = (newoffset-file->http_offset);
+ res = tcp_recv(file->http_socket,file->http_buffer,buflen);
+ if (res < 0) break;
+ file->http_offset += res;
+ }
+
+ return file->http_offset;
+}
+
+
+static void http_fileop_close(void *ref)
+{
+ http_file_t *file = (http_file_t *) ref;
+
+ tcp_close(file->http_socket);
+ KFREE(file->http_filename);
+ KFREE(file);
+}
+
+static void http_fileop_uninit(void *fsctx_arg)
+{
+ http_fsctx_t *fsctx = (http_fsctx_t *) fsctx_arg;
+
+ KFREE(fsctx);
+}
+
+#endif