[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[Libvir] Updated patch for hvm guests



Attached is an updated patch providing some support for HVM guests. I have tested listing info on running guests and creating guests. cdrom support for HVM guests still needs some work, as does graphics options. Guests using graphics type 'sdl' still need some work. Using type 'vnc' is functional, but you must then manually use e.g. "vncviewer localhost:<dom_id>" to view.

I've also included a patch that backs out some optimizations done xend_internal.c. There is a bug in xend (from testing - I think Anthony fixed it and patch got applied to unstable) that does not close the connection after initial create op causing libvirt to block indefinitely. Backing out the optimizations allowed me to use the hvm patch on _testing branch of xen. I've included it for anyone else that may want to experiment with the hvm patch on _testing xen.

Finally, the attached archive contains: 1. a sample xml input file for hvm guest, 2. corresponding s-expr sent to xend, and 3. s-expr returned from xend when getting info on the running guest.

I will be on vacation and not have access to network until July 9. I will improve this work after returning.

Enjoy,
Jim
Index: src/xend_internal.c
===================================================================
RCS file: /data/cvs/libvirt/src/xend_internal.c,v
retrieving revision 1.39
diff -u -r1.39 xend_internal.c
--- src/xend_internal.c	29 Jun 2006 23:53:31 -0000	1.39
+++ src/xend_internal.c	30 Jun 2006 22:08:55 -0000
@@ -1323,10 +1323,77 @@
  ******
  *****************************************************************/
 #ifndef XEN_RO
+
+/**
+ * xend_parse_sexp_desc_os:
+ * @node: the root of the parsed S-Expression
+ * @buf: output buffer object
+ * @hvm: true or 1 if no contains HVM S-Expression 
+ *
+ * Parse the xend sexp for description of os and append it to buf.
+ *
+ * Returns nothing
+ */
+static void
+xend_parse_sexp_desc_os(struct sexpr *node, virBufferPtr buf, int hvm)
+{
+    const char *tmp;
+
+    if (node == NULL || buf == NULL) {
+       return;
+    }
+    
+    tmp = sexpr_node(node, hvm ? "domain/image/hvm/kernel" :
+                                 "domain/image/linux/kernel");
+    if (tmp == NULL) {
+        /*
+         * TODO: we will need some fallback here for other guest OSes
+         */
+        virXendError(NULL, VIR_ERR_INTERNAL_ERROR,
+                     "domain informations incomplete, missing kernel");
+        return;
+    }
+
+    virBufferAdd(buf, "  <os>\n", 7);
+    virBufferVSprintf(buf, hvm ? "    <type>hvm</type>\n" :
+                                 "    <type>linux</type>\n");
+    virBufferVSprintf(buf, "    <kernel>%s</kernel>\n", tmp);
+    if (hvm) {
+        tmp = sexpr_node(node, "domain/image/hvm/device_model");
+        if ((tmp != NULL) && (tmp[0] != 0))
+            virBufferVSprintf(buf, "    <device_model>%s</device_model>\n", tmp);
+        tmp = sexpr_node(node, "domain/image/hvm/boot");
+        if ((tmp != NULL) && (tmp[0] != 0)) {
+           // FIXME:
+           // Figure out how to map the 'a', 'b', 'c' nonsense to a
+           // device.
+           if (tmp[0] == 'a')
+               virBufferAdd(buf, "    <boot dev='/dev/fd0'/>\n", 25 );
+           else if (tmp[0] == 'c')
+              // Don't know what to put here.  Say the vm has been given 3
+              // disks - hda, hdb, hdc.  How does one identify the boot disk?
+               virBufferAdd(buf, "    <boot dev='hda'/>\n", 22 );
+           else if (strcmp(tmp, "d") == 0)
+               virBufferAdd(buf, "    <boot dev='/dev/cdrom'/>\n", 24 );
+        }
+    }
+    else {
+        tmp = sexpr_node(node, "domain/image/linux/ramdisk");
+        if ((tmp != NULL) && (tmp[0] != 0))
+           virBufferVSprintf(buf, "    <initrd>%s</initrd>\n", tmp);
+        tmp = sexpr_node(node, "domain/image/linux/root");
+        if ((tmp != NULL) && (tmp[0] != 0))
+           virBufferVSprintf(buf, "    <root>%s</root>\n", tmp);
+        tmp = sexpr_node(node, "domain/image/linux/args");
+        if ((tmp != NULL) && (tmp[0] != 0))
+           virBufferVSprintf(buf, "    <cmdline>%s</cmdline>\n", tmp);
+    }
+    virBufferAdd(buf, "  </os>\n", 8);
+}
+
 /**
  * xend_parse_sexp_desc:
  * @root: the root of the parsed S-Expression
- * @name: output name of the domain
  *
  * Parse the xend sexp description and turn it into the XML format similar
  * to the one unsed for creation.
@@ -1341,6 +1408,7 @@
     struct sexpr *cur, *node;
     const char *tmp;
     virBuffer buf;
+    int hvm;
 
     if (root == NULL) {
         /* ERROR */
@@ -1380,30 +1448,12 @@
     tmp = sexpr_node(root, "domain/bootloader");
     if (tmp != NULL)
 	virBufferVSprintf(&buf, "  <bootloader>%s</bootloader>\n", tmp);
+
     if (sexpr_lookup(root, "domain/image")) {
-        tmp = sexpr_node(root, "domain/image/linux/kernel");
-        if (tmp == NULL) {
-           /*
-            * TODO: we will need some fallback here for other guest OSes
-            */
-           virXendError(NULL, VIR_ERR_INTERNAL_ERROR,
-                        "domain informations incomplete, missing kernel");
-           goto error;
-        }
-        virBufferAdd(&buf, "  <os>\n", 7);
-        virBufferVSprintf(&buf, "    <type>linux</type>\n");
-        virBufferVSprintf(&buf, "    <kernel>%s</kernel>\n", tmp);
-        tmp = sexpr_node(root, "domain/image/linux/ramdisk");
-        if ((tmp != NULL) && (tmp[0] != 0))
-           virBufferVSprintf(&buf, "    <initrd>%s</initrd>\n", tmp);
-        tmp = sexpr_node(root, "domain/image/linux/root");
-        if ((tmp != NULL) && (tmp[0] != 0))
-           virBufferVSprintf(&buf, "    <root>%s</root>\n", tmp);
-        tmp = sexpr_node(root, "domain/image/linux/args");
-        if ((tmp != NULL) && (tmp[0] != 0))
-           virBufferVSprintf(&buf, "    <cmdline>%s</cmdline>\n", tmp);
-        virBufferAdd(&buf, "  </os>\n", 8);
+        hvm = sexpr_lookup(root, "domain/image/hvm") ? 1 : 0;
+        xend_parse_sexp_desc_os(root, &buf, hvm);
     }
+
     virBufferVSprintf(&buf, "  <memory>%d</memory>\n",
                       (int) (sexpr_u64(root, "domain/maxmem") << 10));
     virBufferVSprintf(&buf, "  <vcpu>%d</vcpu>\n",
@@ -1496,9 +1546,32 @@
                 virBufferVSprintf(&buf, "<!-- Failed to parse vif: %s -->\n",
                                   serial);
             }
+        }
+    }
 
+    if (hvm) {
+        /* Graphics device */
+        /* TODO:
+         * Support for some additional attributes for graphics device?
+         */
+        tmp = sexpr_node(root, "domain/image/hvm/vnc");
+        if (tmp != NULL) {
+            if (tmp[0] == '1')
+                virBufferAdd(&buf, "    <graphics type='vnc'/>\n", 27 );
+        }
+        
+        tmp = sexpr_node(root, "domain/image/hvm/sdl");
+        if (tmp != NULL) {
+           if (tmp[0] == '1')
+               virBufferAdd(&buf, "    <graphics type='sdl'/>\n", 27 );
         }
+
+        /*
+         * TODO:
+         * Device for cdrom
+         */
     }
+    
     virBufferAdd(&buf, "  </devices>\n", 13);
     virBufferAdd(&buf, "</domain>\n", 10);
 
Index: src/xml.c
===================================================================
RCS file: /data/cvs/libvirt/src/xml.c,v
retrieving revision 1.21
diff -u -r1.21 xml.c
--- src/xml.c	26 Jun 2006 15:02:19 -0000	1.21
+++ src/xml.c	30 Jun 2006 22:08:55 -0000
@@ -563,21 +563,146 @@
 #endif
 
 /**
- * virDomainParseXMLOSDesc:
- * @xmldesc: string with the XML description
+ * virDomainParseXMLDescHVM:
+ * @ctxt: a path context representing the XML description
  * @buf: a buffer for the result S-Expr
- * @bootloader: indocate if a bootloader script was provided
  *
- * Parse the OS part of the XML description and add it to the S-Expr in buf
- * This is a temporary interface as the S-Expr interface
+ * Parse the OS part of the XML description for an HVM domain and add it to
+ * the S-Expr in buf. This is a temporary interface as the S-Expr interface
  * will be replaced by XML-RPC in the future. However the XML format should
  * stay valid over time.
  *
  * Returns 0 in case of success, -1 in case of error.
  */
 static int
-virDomainParseXMLOSDesc(xmlNodePtr node, virBufferPtr buf, int bootloader)
+virDomainParseXMLDescHVM(xmlXPathContextPtr ctxt, virBufferPtr buf)
+{
+    xmlXPathObjectPtr obj = NULL;
+    xmlNodePtr cur, txt;
+    const xmlChar *type = NULL;
+    const xmlChar *kernel = NULL;
+    const xmlChar *dev_model = NULL;
+    const xmlChar *boot_dev = NULL;
+    xmlChar *graphics_type = NULL;
+
+    virBufferAdd(buf, "(image ", 7);
+    obj = xmlXPathEval(BAD_CAST "/domain/os[1]", ctxt);
+    if ((obj == NULL) || (obj->type != XPATH_NODESET) ||
+        (obj->nodesetval == NULL) || (obj->nodesetval->nodeNr != 1)) {
+        virXMLError(VIR_ERR_NO_OS, "", 0);
+        return (-1);
+    }
+
+    cur = obj->nodesetval->nodeTab[0]->children;
+    while (cur != NULL) {
+        if (cur->type == XML_ELEMENT_NODE) {
+            if ((type == NULL)
+                && (xmlStrEqual(cur->name, BAD_CAST "type"))) {
+                txt = cur->children;
+                if ((txt->type == XML_TEXT_NODE) && (txt->next == NULL))
+                    type = txt->content;
+            } else if ((kernel == NULL) &&
+                       (xmlStrEqual(cur->name, BAD_CAST "kernel"))) {
+                txt = cur->children;
+                if ((txt->type == XML_TEXT_NODE) && (txt->next == NULL))
+                    kernel = txt->content;
+            } else if ((dev_model == NULL) &&
+                       (xmlStrEqual(cur->name, BAD_CAST "device_model"))) {
+                txt = cur->children;
+                if ((txt->type == XML_TEXT_NODE) && (txt->next == NULL))
+                    dev_model = txt->content;
+            } else if ((boot_dev == NULL) &&
+                       (xmlStrEqual(cur->name, BAD_CAST "boot"))) {
+                boot_dev = xmlGetProp(cur, BAD_CAST "dev");
+            }
+        }
+        cur = cur->next;
+    }
+    if ((type == NULL) || (!xmlStrEqual(type, BAD_CAST "hvm"))) {
+        /* VIR_ERR_OS_TYPE */
+        virXMLError(VIR_ERR_OS_TYPE, (const char *) type, 0);
+        return (-1);
+    }
+    virBufferAdd(buf, "(hvm ", 5);
+    if (kernel == NULL) {
+       virXMLError(VIR_ERR_NO_KERNEL, NULL, 0);
+       return (-1);
+    } else {
+       virBufferVSprintf(buf, "(kernel '%s')", (const char *) kernel);
+    }
+    if (dev_model == NULL) {
+       virXMLError(VIR_ERR_NO_KERNEL, NULL, 0); // need error
+       return (-1);
+    } else {
+       virBufferVSprintf(buf, "(device_model '%s')", (const char *) dev_model);
+    }
+    if (boot_dev) {
+       /* TODO:
+        * Have to figure out the naming used here.
+        */
+       if (xmlStrEqual(type, BAD_CAST "hda")) {
+          virBufferVSprintf(buf, "(boot a)", (const char *) boot_dev);
+       } else if (xmlStrEqual(type, BAD_CAST "hdd")) {
+          virBufferVSprintf(buf, "(boot d)", (const char *) boot_dev);
+       } else {
+          /* Force hd[b|c] if boot_dev specified but not floppy or cdrom? */
+          virBufferVSprintf(buf, "(boot c)", (const char *) boot_dev);
+       }
+    }
+    xmlXPathFreeObject(obj);
+
+    /* TODO:
+     * Is a cdrom disk device specified?
+     * Kind of ugly since it is buried in the devices/diskk node.
+     */
+    
+    /* Is a graphics device specified? */
+    obj = xmlXPathEval(BAD_CAST "/domain/devices/graphics[1]", ctxt);
+    if ((obj == NULL) || (obj->type != XPATH_NODESET) ||
+        (obj->nodesetval == NULL) || (obj->nodesetval->nodeNr != 1)) {
+        virXMLError(VIR_ERR_NO_OS, "", 0); // need error
+        return (-1);
+    }
+
+    graphics_type = xmlGetProp(obj->nodesetval->nodeTab[0], BAD_CAST "type");
+    if (graphics_type != NULL) {
+        if (xmlStrEqual(graphics_type, BAD_CAST "sdl")) {
+            virBufferAdd(buf, "(sdl 1)", 7);
+            // TODO:
+            // Need to understand sdl options
+            //
+            //virBufferAdd(buf, "(display localhost:10.0)", 24);
+            //virBufferAdd(buf, "(xauthority /root/.Xauthority)", 30);
+        }
+        else if (xmlStrEqual(graphics_type, BAD_CAST "vnc"))
+            virBufferAdd(buf, "(vnc 1)", 7);
+        xmlFree(graphics_type);
+    }
+    xmlXPathFreeObject(obj);
+
+    virBufferAdd(buf, ")", 1); /* terminates (hvm */
+    virBufferAdd(buf, ")", 1); /* terminates (image */
+
+    return (0);
+}
+
+/**
+ * virDomainParseXMLDescPV:
+ * @ctxt: a path context representing the XML description
+ * @buf: a buffer for the result S-Expr
+ * @bootloader: indocate if a bootloader script was provided
+ *
+ * Parse the OS part of the XML description for a paravirtualized domain
+ * and add it to the S-Expr in buf.  This is a temporary interface as the
+ * S-Expr interface will be replaced by XML-RPC in the future. However
+ * the XML format should stay valid over time.
+ *
+ * Returns 0 in case of success, -1 in case of error.
+ */
+static int
+virDomainParseXMLDescPV(xmlXPathContextPtr ctxt, virBufferPtr buf, int bootloader)
 {
+    xmlXPathObjectPtr obj = NULL;
     xmlNodePtr cur, txt;
     const xmlChar *type = NULL;
     const xmlChar *root = NULL;
@@ -585,7 +710,15 @@
     const xmlChar *initrd = NULL;
     const xmlChar *cmdline = NULL;
 
-    cur = node->children;
+    virBufferAdd(buf, "(image ", 7);
+    obj = xmlXPathEval(BAD_CAST "/domain/os[1]", ctxt);
+    if ((obj == NULL) || (obj->type != XPATH_NODESET) ||
+        (obj->nodesetval == NULL) || (obj->nodesetval->nodeNr != 1)) {
+        virXMLError(VIR_ERR_NO_OS, "", 0);
+        return (-1);
+    }
+
+    cur = obj->nodesetval->nodeTab[0]->children;
     while (cur != NULL) {
         if (cur->type == XML_ELEMENT_NODE) {
             if ((type == NULL)
@@ -617,19 +750,19 @@
         }
         cur = cur->next;
     }
-    if ((type != NULL) && (!xmlStrEqual(type, BAD_CAST "linux"))) {
+    if ((type == NULL) || (!xmlStrEqual(type, BAD_CAST "linux"))) {
         /* VIR_ERR_OS_TYPE */
         virXMLError(VIR_ERR_OS_TYPE, (const char *) type, 0);
         return (-1);
     }
     virBufferAdd(buf, "(linux ", 7);
     if (kernel == NULL) {
-	if (bootloader == 0) {
-	    virXMLError(VIR_ERR_NO_KERNEL, NULL, 0);
-	    return (-1);
-	}
+        if (bootloader == 0) {
+            virXMLError(VIR_ERR_NO_KERNEL, NULL, 0);
+            return (-1);
+        }
     } else {
-	virBufferVSprintf(buf, "(kernel '%s')", (const char *) kernel);
+        virBufferVSprintf(buf, "(kernel '%s')", (const char *) kernel);
     }
     if (initrd != NULL)
         virBufferVSprintf(buf, "(ramdisk '%s')", (const char *) initrd);
@@ -637,13 +770,21 @@
         virBufferVSprintf(buf, "(root '%s')", (const char *) root);
     if (cmdline != NULL)
         virBufferVSprintf(buf, "(args '%s')", (const char *) cmdline);
-    virBufferAdd(buf, ")", 1);
+
+    /* TODO:
+     * Can this be freed earlier?
+     */
+    xmlXPathFreeObject(obj);
+
+    virBufferAdd(buf, ")", 1); /* terminates (linux */
+    virBufferAdd(buf, ")", 1); /* terminates (image */
+
     return (0);
 }
-
+    
 /**
  * virDomainParseXMLDiskDesc:
- * @xmldesc: string with the XML description
+ * @node: node containing disk description
  * @buf: a buffer for the result S-Expr
  *
  * Parse the one disk in the XML description and add it to the S-Expr in buf
@@ -705,10 +846,7 @@
         return (-1);
     }
     virBufferAdd(buf, "(vbd ", 5);
-    if (target[0] == '/')
         virBufferVSprintf(buf, "(dev '%s')", (const char *) target);
-    else
-        virBufferVSprintf(buf, "(dev '/dev/%s')", (const char *) target);
     if (typ == 0)
         virBufferVSprintf(buf, "(uname 'file:%s')", source);
     else if (typ == 1) {
@@ -730,7 +868,7 @@
 
 /**
  * virDomainParseXMLIfDesc:
- * @xmldesc: string with the XML description
+ * @node: node containing the interface description
  * @buf: a buffer for the result S-Expr
  *
  * Parse the one interface the XML description and add it to the S-Expr in buf
@@ -818,7 +956,7 @@
 {
     xmlDocPtr xml = NULL;
     xmlNodePtr node;
-    char *ret = NULL, *nam = NULL;
+    char *ret = NULL, *nam = NULL, *type = NULL;
     virBuffer buf;
     xmlChar *prop;
     xmlXPathObjectPtr obj = NULL;
@@ -859,7 +997,7 @@
         goto error;
     }
     /*
-     * extract soem of the basics, name, memory, cpus ...
+     * extract some of the basics, name, memory, cpus ...
      */
     obj = xmlXPathEval(BAD_CAST "string(/domain/name[1])", ctxt);
     if ((obj == NULL) || (obj->type != XPATH_STRING) ||
@@ -909,7 +1047,6 @@
     if ((obj != NULL) && (obj->type == XPATH_STRING) &&
         (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
 	virBufferVSprintf(&buf, "(on_poweroff '%s')", obj->stringval);
-	bootloader = 1;
     }
     xmlXPathFreeObject(obj);
 
@@ -917,7 +1054,6 @@
     if ((obj != NULL) && (obj->type == XPATH_STRING) &&
         (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
 	virBufferVSprintf(&buf, "(on_reboot '%s')", obj->stringval);
-	bootloader = 1;
     }
     xmlXPathFreeObject(obj);
 
@@ -925,26 +1061,28 @@
     if ((obj != NULL) && (obj->type == XPATH_STRING) &&
         (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
 	virBufferVSprintf(&buf, "(on_crash '%s')", obj->stringval);
-	bootloader = 1;
     }
     xmlXPathFreeObject(obj);
 
-    /* analyze of the os description */
-    virBufferAdd(&buf, "(image ", 7);
-    obj = xmlXPathEval(BAD_CAST "/domain/os[1]", ctxt);
-    if ((obj == NULL) || (obj->type != XPATH_NODESET) ||
-        (obj->nodesetval == NULL) || (obj->nodesetval->nodeNr != 1)) {
-        virXMLError(VIR_ERR_NO_OS, nam, 0);
+    /* Analyze of the os description, based on HVM or PV. */
+    obj = xmlXPathEval(BAD_CAST "string(/domain/os/type[1])", ctxt);
+    if ((obj == NULL) || (obj->type != XPATH_STRING) ||
+        (obj->stringval == NULL) || (obj->stringval[0] == 0)) {
+        virXMLError(VIR_ERR_OS_TYPE, (const char *) type, 0);
         goto error;
     }
-    res = virDomainParseXMLOSDesc(obj->nodesetval->nodeTab[0], &buf,
-                                  bootloader);
+    if (xmlStrEqual(obj->stringval, BAD_CAST "hvm")) {
+        res = virDomainParseXMLDescHVM(ctxt, &buf);
+    }
+    else {
+        res = virDomainParseXMLDescPV(ctxt, &buf, bootloader);
+    }
+    
     if (res != 0) {
         goto error;
     }
     xmlXPathFreeObject(obj);
-    virBufferAdd(&buf, ")", 1);
-
+    
     /* analyze of the devices */
     obj = xmlXPathEval(BAD_CAST "/domain/devices/disk", ctxt);
     if ((obj == NULL) || (obj->type != XPATH_NODESET) ||
@@ -976,7 +1114,6 @@
     }
     xmlXPathFreeObject(obj);
 
-
     virBufferAdd(&buf, ")", 1); /* closes (vm */
     buf.content[buf.use] = 0;
 
Index: xend_internal.c
===================================================================
RCS file: /data/cvs/libvirt/src/xend_internal.c,v
retrieving revision 1.39
diff -u -r1.39 xend_internal.c
--- xend_internal.c	29 Jun 2006 23:53:31 -0000	1.39
+++ xend_internal.c	30 Jun 2006 22:18:52 -0000
@@ -303,6 +303,42 @@
     return swrite(fd, string, strlen(string));
 }
 
+/**
+ * sreads:
+ * @fd:  the file descriptor
+ * @buffer: the I/O buffer
+ * @n_buffer: the size of the I/O buffer
+ *
+ * Internal routine to do a synchronous read of a line
+ *
+ * Returns the number of bytes read, or -1 in case of error
+ */
+static ssize_t
+sreads(int fd, char *buffer, size_t n_buffer)
+{
+    size_t offset;
+
+    if (n_buffer < 1)
+        return (-1);
+
+    for (offset = 0; offset < (n_buffer - 1); offset++) {
+        ssize_t ret;
+
+        ret = sread(fd, buffer + offset, 1);
+        if (ret == 0)
+            break;
+        else if (ret == -1)
+            return ret;
+
+        if (buffer[offset] == '\n') {
+            offset++;
+            break;
+        }
+    }
+    buffer[offset] = 0;
+
+    return offset;
+}
 
 static int
 istartswith(const char *haystack, const char *needle)
@@ -325,95 +361,31 @@
 xend_req(int fd, char *content, size_t n_content)
 {
     char buffer[4096];
-    int nbuf = -1;
     int content_length = -1;
     int retcode = 0;
 
-    /*
-     * Fill buffer with as much as possible to get 
-     * process going
-     */
-    nbuf = sread(fd, buffer, sizeof(buffer));
-
-    /*
-     * Extract lines from the buffer, until the 
-     * end of header is found
-     */
-    while (nbuf > -1) {
-        /* Seach for offset of first \r\n pair */
-        int i, offset = -1;
-
-        for (i = 0; i < (nbuf - 1); i++) {
-            if (buffer[i] == '\r' && buffer[i + 1] == '\n') {
-                offset = i;
-                break;
-            }
-        }
-
-        if (offset == -1) { /* No newline found, so try to fill more data */
-
-            if (nbuf == sizeof(buffer)) {
-                /* Already have 4096 bytes of data & no newline, 
-                 * get the hell out of this game */
-                break;
-            }
-
-            /* Fill remainder of buffer with more data */
-            int extra = sread(fd, buffer + nbuf, sizeof(buffer) - nbuf);
-
-            if (extra < 1) {
-                /* Couldn't get more, so quit trying */
-                break;
-            }
-            nbuf += extra;
-        } else if (!offset) { /* Immediate newline, indicates end of header */
-            /* Overwrite the \r\n pair */
-            offset += 2;
-            nbuf -= offset;
-            memmove(buffer, buffer + offset, nbuf);
+    while (sreads(fd, buffer, sizeof(buffer)) > 0) {
+        if (strcmp(buffer, "\r\n") == 0)
             break;
-        } else { /* We have a single line */
-            buffer[offset] = '\0';
 
-            if (istartswith(buffer, "Content-Length: "))
-                content_length = atoi(buffer + 16);
-            else if (istartswith(buffer, "HTTP/1.1 "))
-                retcode = atoi(buffer + 9);
-
-            /*
-	     * Now move buffer, overwriting first line, to make room for
-             * more data on next iteration of loop (if needed)
-	     */
-            offset += 2;
-            nbuf -= offset;
-            memmove(buffer, buffer + offset, nbuf);
-        }
+        if (istartswith(buffer, "Content-Length: "))
+            content_length = atoi(buffer + 16);
+        else if (istartswith(buffer, "HTTP/1.1 "))
+            retcode = atoi(buffer + 9);
     }
 
-    if (content_length > -1) {  /* Read the header, now get body */
+    if (content_length > -1) {
+        ssize_t ret;
+
         if ((unsigned int) content_length > (n_content + 1))
             content_length = n_content - 1;
 
-        /*
-	 * Copy across any data left in buffer after
-         * reading header
-	 */
-        if (nbuf > content_length) {
-            nbuf = content_length;
-        }
-        memmove(content, buffer, nbuf);
-
-        if (nbuf < content_length) { /* Still need more data for body */
-            size_t ret = sread(fd, content + nbuf, content_length - nbuf);
-
-            if (0 > (int) ret)
-                return -1;
+        ret = sread(fd, content, content_length);
+        if (ret < 0)
+            return -1;
 
-            content[nbuf + ret] = 0;
-        } else {
-            content[nbuf] = 0;
-        }
-    } else { /* Unable to complete reading header */
+        content[ret] = 0;
+    } else {
         content[0] = 0;
     }
 

Attachment: config.tar.bz2
Description: application/bzip


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]