summaryrefslogtreecommitdiffstats
path: root/common/sys
diff options
context:
space:
mode:
authorpiaip <piaip@63ad8ddf-47c3-0310-b6dd-a9e9d9715204>2009-06-07 16:41:13 +0800
committerpiaip <piaip@63ad8ddf-47c3-0310-b6dd-a9e9d9715204>2009-06-07 16:41:13 +0800
commit1e065cdd0fb3c48d26baeceef9cc8573137d820f (patch)
tree448dc722eb4ad2bb34aa4b79eb8e0d5a5c4ffa13 /common/sys
parent4d0d4eb9117c6557b701725643935dea97d05682 (diff)
downloadpttbbs-1e065cdd0fb3c48d26baeceef9cc8573137d820f.tar
pttbbs-1e065cdd0fb3c48d26baeceef9cc8573137d820f.tar.gz
pttbbs-1e065cdd0fb3c48d26baeceef9cc8573137d820f.tar.bz2
pttbbs-1e065cdd0fb3c48d26baeceef9cc8573137d820f.tar.lz
pttbbs-1e065cdd0fb3c48d26baeceef9cc8573137d820f.tar.xz
pttbbs-1e065cdd0fb3c48d26baeceef9cc8573137d820f.tar.zst
pttbbs-1e065cdd0fb3c48d26baeceef9cc8573137d820f.zip
* improve tobind() with customizable parameters
* add ancillary remote fd API git-svn-id: http://opensvn.csie.org/pttbbs/trunk/pttbbs@4507 63ad8ddf-47c3-0310-b6dd-a9e9d9715204
Diffstat (limited to 'common/sys')
-rw-r--r--common/sys/net.c106
1 files changed, 102 insertions, 4 deletions
diff --git a/common/sys/net.c b/common/sys/net.c
index ba08ff7f..883b4d48 100644
--- a/common/sys/net.c
+++ b/common/sys/net.c
@@ -9,9 +9,12 @@
#include <unistd.h>
#include <ctype.h>
#include <assert.h>
+#include <errno.h>
#include "cmsys.h"
+#define DEFAULT_TCP_QLEN (10)
+
uint32_t
ipstr2int(const char *ip)
{
@@ -40,9 +43,10 @@ ipstr2int(const char *ip)
// *:port (bind to addr_any, allow remote connect)
// all others formats are UNIX domain socket path.
-int tobind(const char * addr)
+int tobindex(const char *addr, int qlen, int (*_setsock)(int), int do_listen)
{
- int sockfd, val = 1;
+ const int v_on = 1;
+ int sockfd;
assert(addr && *addr);
@@ -57,6 +61,12 @@ int tobind(const char * addr)
servaddr.sun_family = AF_UNIX;
strlcpy(servaddr.sun_path, addr, sizeof(servaddr.sun_path));
+ setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
+ (void *)&v_on, sizeof(v_on));
+
+ if (_setsock)
+ _setsock(sockfd);
+
// remove the file first if it exists.
unlink(servaddr.sun_path);
@@ -81,7 +91,10 @@ int tobind(const char * addr)
assert(port && atoi(port) != 0);
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
- (char *)&val, sizeof(val));
+ (void *)&v_on, sizeof(v_on));
+
+ if (_setsock)
+ _setsock(sockfd);
if (!buf[0])
servaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
@@ -101,7 +114,7 @@ int tobind(const char * addr)
}
}
- if (listen(sockfd, 10) < 0) {
+ if (do_listen && listen(sockfd, qlen) < 0) {
perror("listen()");
exit(1);
}
@@ -109,6 +122,11 @@ int tobind(const char * addr)
return sockfd;
}
+int tobind(const char * addr)
+{
+ return tobindex(addr, DEFAULT_TCP_QLEN, NULL, 1);
+}
+
int toconnect(const char *addr)
{
int sock;
@@ -194,3 +212,83 @@ int towrite(int fd, const void *buf, int len)
}
return l;
}
+
+/**
+ * fd sharing by piaip
+ */
+
+// return: -1 if error, otherwise success.
+int send_remote_fd(int tunnel, int fd)
+{
+ struct msghdr msg = {0};
+ struct iovec vec = {0};
+ struct cmsghdr *cmsg;
+ char ccmsg [CMSG_SPACE(sizeof(fd))];
+ char dummy = 0;
+ int rv;
+
+ vec.iov_base = &dummy; // must send/receive at least one byte
+ vec.iov_len = 1;
+ msg.msg_iov = &vec;
+ msg.msg_iovlen = 1;
+ msg.msg_control = ccmsg;
+ msg.msg_controllen = sizeof(ccmsg);
+
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
+ *(int*)CMSG_DATA(cmsg) = fd;
+
+ // adjust msg again
+ msg.msg_controllen = cmsg->cmsg_len;
+ msg.msg_flags = 0;
+
+ do {
+ // ignore EINTR
+ rv = sendmsg(tunnel, &msg, 0);
+ } while (rv == -1 && errno == EINTR);
+
+ if (rv == -1) {
+ perror("sendmsg");
+ return rv;
+ }
+
+ return 0;
+}
+
+// return: remote fd (-1 if error)
+int recv_remote_fd(int tunnel)
+{
+ struct msghdr msg;
+ struct iovec iov;
+ char dummy;
+ int rv;
+ int connfd = -1;
+ char ccmsg[CMSG_SPACE(sizeof(connfd))];
+ struct cmsghdr *cmsg;
+
+ iov.iov_base = &dummy;
+ iov.iov_len = 1;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = ccmsg;
+ msg.msg_controllen = sizeof(ccmsg);
+
+ do {
+ // ignore EINTR
+ rv = recvmsg(tunnel, &msg, 0);
+ } while (rv == -1 && errno == EINTR);
+
+ if (rv == -1) {
+ perror("recvmsg");
+ return -1;
+ }
+
+ cmsg = CMSG_FIRSTHDR(&msg);
+ assert(cmsg->cmsg_type == SCM_RIGHTS);
+ if (cmsg->cmsg_type != SCM_RIGHTS)
+ return -1;
+
+ return *(int*)CMSG_DATA(cmsg);
+}