[libvirt PATCH 3/5] util: Add util methods required by ch networking

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

 



virSocketSendMsgWithFDs method send fds along with payload using
SCM_RIGHTS. virSocketRecvHttpResponse method polls, receives http response
on the input socket and returns the http response code.

These methods are required to add network suppport in ch driver.

Signed-off-by: Praveen K Paladugu <prapal@xxxxxxxxxxxxxxxxxxx>
---
 po/POTFILES              |   1 +
 src/libvirt_private.syms |   2 +
 src/util/virsocket.c     | 109 +++++++++++++++++++++++++++++++++++++++
 src/util/virsocket.h     |   3 ++
 4 files changed, 115 insertions(+)

diff --git a/po/POTFILES b/po/POTFILES
index 023c041f61..b594a8dd39 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -326,6 +326,7 @@ src/util/virscsi.c
 src/util/virscsihost.c
 src/util/virscsivhost.c
 src/util/virsecret.c
+src/util/virsocket.c
 src/util/virsocketaddr.c
 src/util/virstoragefile.c
 src/util/virstring.c
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 680a90034a..e643cea774 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -3371,7 +3371,9 @@ virSecureEraseString;
 
 # util/virsocket.h
 virSocketRecvFD;
+virSocketRecvHttpResponse;
 virSocketSendFD;
+virSocketSendMsgWithFDs;
 
 
 # util/virsocketaddr.h
diff --git a/src/util/virsocket.c b/src/util/virsocket.c
index cd6f7ecd1b..b11e53a215 100644
--- a/src/util/virsocket.c
+++ b/src/util/virsocket.c
@@ -22,8 +22,14 @@
 #include "virsocket.h"
 #include "virutil.h"
 #include "virfile.h"
+#include "virlog.h"
 
 #include <fcntl.h>
+#include <poll.h>
+
+#define PKT_TIMEOUT_MS 500 /* ms */
+
+VIR_LOG_INIT("util.virsocket");
 
 #ifdef WIN32
 
@@ -482,6 +488,109 @@ virSocketRecvFD(int sock, int fdflags)
 
     return fd;
 }
+
+/**
+ * virSocketSendMsgWithFDs:
+ * @sock: socket to send payload and fds to
+ * @payload: payload to send
+ * @fds: array of fds to send
+ * @fds_len: len of fds array
+
+ * Send @fds along with @payload to @sock using SCM_RIGHTS.
+ * Return number of bytes sent on success, or -1 on error.
+ */
+int
+virSocketSendMsgWithFDs(int sock, const char *payload, int *fds, size_t fds_len)
+{
+    struct msghdr msg;
+    struct iovec iov[1]; /* Send a single payload, so set vector len to 1 */
+    int ret;
+    char control[CMSG_SPACE(sizeof(int)*fds_len)];
+    struct cmsghdr *cmsg;
+
+    memset(&msg, 0, sizeof(msg));
+    memset(control, 0, sizeof(control));
+
+    iov[0].iov_base = (void *) payload;
+    iov[0].iov_len = strlen(payload);
+
+    msg.msg_iov = iov;
+    msg.msg_iovlen = 1;
+
+    msg.msg_control = control;
+    msg.msg_controllen = sizeof(control);
+
+    cmsg = CMSG_FIRSTHDR(&msg);
+    if (!cmsg) {
+        VIR_ERROR(_("Couldn't fit control msg header in msg"));
+        return -1;
+    }
+    cmsg->cmsg_len = CMSG_LEN(sizeof(int) * fds_len);
+    cmsg->cmsg_level = SOL_SOCKET;
+    cmsg->cmsg_type = SCM_RIGHTS;
+    memcpy(CMSG_DATA(cmsg), fds, sizeof(int) * fds_len);
+
+    do {
+        ret = sendmsg(sock, &msg, 0);
+    } while (ret < 0 && errno == EINTR);
+
+    if (ret < 0)
+      return -1;
+
+    return ret;
+}
+
+/**
+ * virSocketRecvHttpResponse:
+ * @sock: socket to receive http response on
+ *
+ * This function polls @sock for HTTP response
+ * Returns HTTP response code from received message, or -1 on error.
+ */
+int virSocketRecvHttpResponse(int sock)
+{
+    struct pollfd pfds[1];
+    /* This is only used for responses from ch guests, which fit within
+     * 1024 buffer
+     */
+    char buf[1024];
+    int response_code, ret;
+
+    pfds[0].fd = sock;
+    pfds[0].events = POLLIN;
+
+    do {
+        ret = poll(pfds, G_N_ELEMENTS(pfds), PKT_TIMEOUT_MS);
+    } while (ret < 0 && errno == EINTR);
+
+    if (ret <= 0) {
+        if (ret < 0) {
+            VIR_ERROR(_("Poll on sock %1$d failed"), sock);
+        } else if (ret == 0) {
+            VIR_ERROR(_("Poll on sock %1$d timed out"), sock);
+        }
+        return -1;
+    }
+
+    do {
+        ret = recv(sock, buf, sizeof(buf), 0);
+    } while (ret < 0 && errno == EINTR);
+
+    if (ret < 0) {
+      VIR_ERROR(_("recv on sock %1$d failed"), sock);
+      return -1;
+   }
+
+    /* Parse the HTTP response code */
+    ret = sscanf(buf, "HTTP/1.%*d %d", &response_code);
+    if (ret != 1) {
+        VIR_ERROR(_("Failed to parse HTTP response code"));
+        return -1;
+    }
+
+    return response_code;
+}
+
 #else /* WIN32 */
 int
 virSocketSendFD(int sock G_GNUC_UNUSED, int fd G_GNUC_UNUSED)
diff --git a/src/util/virsocket.h b/src/util/virsocket.h
index 419da8b3ae..9190a6a569 100644
--- a/src/util/virsocket.h
+++ b/src/util/virsocket.h
@@ -22,6 +22,9 @@
 
 int virSocketSendFD(int sock, int fd);
 int virSocketRecvFD(int sock, int fdflags);
+int virSocketSendMsgWithFDs(int sock, const char *payload, int *fds,
+                            size_t fd_len);
+int virSocketRecvHttpResponse(int sock);
 
 #ifdef WIN32
 
-- 
2.41.0
_______________________________________________
Devel mailing list -- devel@xxxxxxxxxxxxxxxxx
To unsubscribe send an email to devel-leave@xxxxxxxxxxxxxxxxx




[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]

  Powered by Linux