core: pxe: Add general support for pluggable url handlers.
authorEric W. Biederman <ebiederm@xmission.com>
Mon, 11 Apr 2011 11:16:03 +0000 (04:16 -0700)
committerEric W. Biederman <ebiederm@xmission.com>
Tue, 12 Apr 2011 21:41:13 +0000 (14:41 -0700)
In preparation for adding http support (and possibly others)
add support for looking up a url scheme by name in a table
and calling the appropriate open function.

This also adds a struct netbuf pointer to the pxe inode allowing
for some easy to implement and nice to use streaming abstractions
like pxe_getc.

Cleanup the includes of lwip headers.  We want <> brackets
(no point in searching in the current directory first)
and the ifdefs around them can go.

Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
core/fs/pxe/pxe.c
core/fs/pxe/pxe.h

index af580c6..c173cd0 100644 (file)
@@ -6,10 +6,8 @@
 #include <minmax.h>
 #include <sys/cpu.h>
 #include "pxe.h"
-#if 1
-#include "lwip/api.h"
-#include "lwip/dns.h"
-#endif
+#include <lwip/api.h>
+#include <lwip/dns.h>
 
 static uint16_t real_base_mem;    /* Amount of DOS memory after freeing */
 
@@ -33,6 +31,13 @@ bool have_uuid = false;
 /* Common receive buffer */
 __lowmem char packet_buf[PKTBUF_SIZE] __aligned(16);
 
+static struct url_open {
+    const char *scheme;
+    void (*open)(struct inode *inode, const char *url);
+} url_table[] = {
+    { NULL, NULL },
+};
+
 /*
  * Allocate a local UDP port structure and assign it a local port number.
  * Return the inode pointer if success, or null if failure
@@ -184,7 +189,7 @@ static int gendotquad(char *dst, uint32_t ip)
  * return the the string address after the ip string
  *
  */
-static const char *parse_dotquad(const char *ip_str, uint32_t *res)
+const char *parse_dotquad(const char *ip_str, uint32_t *res)
 {
     const char *p = ip_str;
     uint8_t part = 0;
@@ -322,6 +327,30 @@ static void pxe_mangle_name(char *dst, const char *src)
 }
 
 /*
+ * Read a single character from the specified pxe inode.
+ * Very useful for stepping through http streams and
+ * parsing their headers.
+ */
+int pxe_getc(struct inode *inode)
+{
+    struct pxe_pvt_inode *socket = PVT(inode);
+    unsigned char byte;
+
+    while (!socket->tftp_bytesleft) {
+       if (socket->tftp_goteof)
+           return -1;
+
+       socket->fill_buffer(inode);
+    }
+
+    byte = *socket->tftp_dataptr;
+    socket->tftp_bytesleft -= 1;
+    socket->tftp_dataptr += 1;
+
+    return byte;
+}
+
+/*
  * Get a fresh packet if the buffer is drained, and we haven't hit
  * EOF yet.  The buffer should be filled immediately after draining!
  */
@@ -487,6 +516,21 @@ static void __pxe_searchdir(const char *filename, struct file *file)
     if (!inode)
        return;                 /* Allocation failure */
 
+    if (path_type == PXE_URL) {
+       struct url_open *entry;
+       np = strchr(filename, ':');
+       
+       for (entry = url_table; entry->scheme; entry++) {
+           int scheme_len = strlen(entry->scheme);
+           if (scheme_len != (np - filename))
+               continue;
+           if (memcmp(entry->scheme, filename, scheme_len) != 0)
+               continue;
+           entry->open(inode, filename);
+           goto done;
+       }
+    }
+
 #if GPXE
     if (path_type == PXE_URL) {
        if (has_gpxe) {
index dd1d31f..59661bc 100644 (file)
@@ -150,11 +150,13 @@ struct bootp_t {
 } __attribute__ ((packed));
 
 struct netconn;
+struct netbuf;
 /*
  * Our inode private information -- this includes the packet buffer!
  */
 struct pxe_pvt_inode {
     struct netconn *conn;      /* lwip network connection */
+    struct netbuf *buf;               /* lwip cached buffer */
     uint16_t tftp_localport;   /* Local port number  (0=not in us)*/
     uint16_t tftp_remoteport;  /* Remote port number */
     uint32_t tftp_remoteip;    /* Remote IP address */
@@ -242,6 +244,8 @@ void pxe_poll(void);
 bool ip_ok(uint32_t);
 int pxe_call(int, void *);
 extern __lowmem char packet_buf[PKTBUF_SIZE] __aligned(16);
+const char *parse_dotquad(const char *ip_str, uint32_t *res);
+int pxe_getc(struct inode *inode);
 
 /* dhcp_options.c */
 void parse_dhcp(int);