shithub: mc

Download patch

ref: a832e3d49570feddfe89fc31f3c08f73126fa04e
parent: 8303e07068b39bb6de362eafff89c7a3a53206cc
author: Ori Bernstein <ori@eigenstate.org>
date: Mon Apr 25 18:51:55 EDT 2016

Add listen/accept impl.

	Works on FreeBSD, at least.

--- a/lib/std/bld.sub
+++ b/lib/std/bld.sub
@@ -77,19 +77,21 @@
 	memops-impl+plan9-x64.s
 
 	# platform specific files
-	env+plan9.myr
-	env+posixy.myr
-	errno+plan9.myr
+	dial+plan9.myr
+	dial+posixy.myr
+	dialparse+posixy.myr
 	dir+freebsd.myr
 	dir+linux.myr
 	dir+osx.myr
 	dir+plan9.myr
-	wait+posixy.myr
-	wait+plan9.myr
-	dial+posixy.myr
-	dial+plan9.myr
-	resolve+posixy.myr
+	env+plan9.myr
+	env+posixy.myr
+	errno+plan9.myr
+	listen+posixy.myr
 	resolve+plan9.myr
+	resolve+posixy.myr
+	wait+plan9.myr
+	wait+posixy.myr
 
 	# relatively generic syscall wrappers
 	syswrap+plan9.myr
--- a/lib/std/dial+posixy.myr
+++ b/lib/std/dial+posixy.myr
@@ -2,13 +2,10 @@
 
 use "alloc"
 use "chartype"
+use "dialparse"
 use "die"
 use "endian"
-use "hasprefix"
-use "intparse"
-use "ipparse"
 use "option"
-use "resolve"
 use "result"
 use "slcp"
 use "sleq"
@@ -18,7 +15,7 @@
 use "utf"
 
 pkg std =
-	const dial	: (dialstr : byte[:] -> result(fd, byte[:]))
+	const dial	: (ds : byte[:] -> result(fd, byte[:]))
 ;;
 
 /*
@@ -33,9 +30,6 @@
 /* takes a plan 9 style dial string */
 const dial = {ds
 	match nameseg(ds)
-	/*
-	| `Some ("net", str):	-> guessdial(str)
-	*/
 	| `Some ("tcp", str):	-> dialsock(sys.Sockstream, str)
 	| `Some ("udp", str):	-> dialsock(sys.Sockdgram, str)
 	| `Some ("unix", u):	-> dialunix(u)
@@ -48,14 +42,15 @@
 	var sa4 : sys.sockaddr_in
 	var sa6 : sys.sockaddr_in6
 	var sa	: sys.sockaddr#
-	var host, portstr, port
+	var hoststr, portstr, port
 	var sock, sz
+	var err
 
 	match nameseg(str)
 	| `None:	-> `Fail "required host!port for ip dial"
 	| `Some ("", _):	-> `Fail "empty host"
-	| `Some (_, ""):	-> `Fail "empty host"
-	| `Some segs:	(host, portstr) = segs
+	| `Some (_, ""):	-> `Fail "empty port"
+	| `Some segs:	(hoststr, portstr) = segs
 	;;
 
 	match parseport(portstr)
@@ -63,7 +58,7 @@
 	| `None:	-> `Fail("invalid port")
 	;;
 
-	match getaddr(host)
+	match getaddr(hoststr)
 	| `Ok `Ipv4 bits:
 		sa4=[.fam=sys.Afinet, .addr=bits, .port=hosttonet(port)]
 		sa = &sa4 castto(sys.sockaddr#)
@@ -76,11 +71,10 @@
 		-> `Fail m
 	;;
 	sock = sys.socket(sa.fam, proto, 0)
-
 	if sock < 0
 		-> `Fail "failed to create socket"
 	;;
-	var err
+
 	err = sys.connect(sock, sa, sz)
 	if err < 0
 		sys.close(sock)
@@ -104,59 +98,8 @@
 		-> `Fail "failed to create socket"
 	;;
 	slcp(sa.path[:path.len], path)
-	if sys.bind(sock, &sa castto(sys.sockaddr#), sizeof(sys.sockaddr_un)) < 0
+	if sys.connect(sock, &sa castto(sys.sockaddr#), sizeof(sys.sockaddr_un)) < 0
 		-> `Fail "failed to bind address"
 	;;
 	-> `Ok (sock castto(fd))
 }
-
-const parseport = {port
-	match intparse(port)
-	| `Some n:	-> `Some n
-	| `None:
-		/* a small number of hardcoded ports */
-		if sleq(port, "http")
-			-> `Some 80
-		elif sleq(port, "https")
-			-> `Some 443
-		elif sleq(port, "ircd")
-			-> `Some 6667
-		elif sleq(port, "dns")
-			-> `Some 53
-		;;
-	;;
-	-> `None
-}
-
-const getaddr = {addr
-	var ip
-
-	match ipparse(addr)
-	| `Some a:
-		ip = a
-	| `None:
-		match resolve(addr)
-		| `Ok hi:
-			if hi.len > 0
-				ip = hi[0].addr
-				slfree(hi)
-			else
-				slfree(hi)
-				-> `Fail "no hosts resolved for addr"
-			;;
-		| `Fail m:
-			-> `Fail "could not get host info"
-		;;
-	;;
-	-> `Ok ip
-}
-
-const nameseg = {str
-	match strfind(str, "!")
-	| `Some idx:
-		-> `Some (str[:idx], str[idx+1:])
-	| `None:
-		-> `None
-	;;
-}
-
--- /dev/null
+++ b/lib/std/dialparse+posixy.myr
@@ -1,0 +1,69 @@
+use "alloc"
+use "chartype"
+use "hasprefix"
+use "intparse"
+use "slcp"
+use "sleq"
+use "strfind"
+use "striter"
+use "option"
+use "result"
+use "ipparse"
+use "resolve"
+
+pkg std =
+	pkglocal const parseport	: (port : byte[:] -> option(uint16))
+	pkglocal const getaddr	: (addr : byte[:] -> result(netaddr, byte[:]))
+	pkglocal const nameseg	: (str : byte[:] -> option((byte[:], byte[:])))
+;;
+
+const parseport = {port
+	match intparse(port)
+	| `Some n:	-> `Some n
+	| `None:
+		/* a small number of hardcoded ports */
+		if sleq(port, "http")
+			-> `Some 80
+		elif sleq(port, "https")
+			-> `Some 443
+		elif sleq(port, "ircd")
+			-> `Some 6667
+		elif sleq(port, "dns")
+			-> `Some 53
+		;;
+	;;
+	-> `None
+}
+
+const getaddr = {addr
+	var ip
+
+	match ipparse(addr)
+	| `Some a:
+		ip = a
+	| `None:
+		match resolve(addr)
+		| `Ok hi:
+			if hi.len > 0
+				ip = hi[0].addr
+				slfree(hi)
+			else
+				slfree(hi)
+				-> `Fail "no hosts resolved for addr"
+			;;
+		| `Fail m:
+			-> `Fail "could not get host info"
+		;;
+	;;
+	-> `Ok ip
+}
+
+const nameseg = {str
+	match strfind(str, "!")
+	| `Some idx:
+		-> `Some (str[:idx], str[idx+1:])
+	| `None:
+		-> `None
+	;;
+}
+
--- /dev/null
+++ b/lib/std/listen+posixy.myr
@@ -1,0 +1,125 @@
+use sys
+
+use "alloc"
+use "chartype"
+use "dialparse"
+use "die"
+use "endian"
+use "option"
+use "resolve"
+use "result"
+use "slcp"
+use "sleq"
+use "strfind"
+use "striter"
+use "syswrap"
+use "utf"
+
+pkg std =
+	const announce	: (ds : byte[:] -> result(fd, byte[:]))
+	const listen	: (sock : fd -> result(fd, byte[:]))
+	const accept	: (lfd : fd -> result(fd, byte[:]))
+;;
+
+const announce = {ds
+	match nameseg(ds)
+	| `Some ("tcp", str):	-> announcesock(sys.Sockstream, str)
+	| `Some ("udp", str):	-> announcesock(sys.Sockdgram, str)
+	| `Some ("unix", str):	-> announceunix(str)
+	| `Some (proto, str):	-> `Fail "unknown protocol"
+	| `None:	-> `Fail "missing protocol"
+	;;
+}
+
+const announcesock = {proto, str
+	var sa4 : sys.sockaddr_in
+	var sa6 : sys.sockaddr_in6
+	var sa	: sys.sockaddr#
+	var hoststr, portstr, port
+	var sock, sz
+	var yes
+
+	match nameseg(str)
+	| `None:	-> `Fail "required addr!port for ip listen"
+	| `Some ("", _):	-> `Fail "empty host"
+	| `Some (_, ""):	-> `Fail "empty port"
+	| `Some segs:	(hoststr, portstr) = segs
+	;;
+
+	match parseport(portstr)
+	| `Some p:	port = p
+	| `None:	-> `Fail("invalid port")
+	;;
+
+	if std.sleq(hoststr, "*")
+		sa6=[.fam=sys.Afinet6, .port=hosttonet(port)]
+		sa = &sa6 castto(sys.sockaddr#)
+		sz = sizeof(sys.sockaddr_in6)
+	else
+		match getaddr(hoststr)
+		| `Ok `Ipv4 bits:
+			sa4=[.fam=sys.Afinet, .addr=bits, .port=hosttonet(port)]
+			sa = &sa4 castto(sys.sockaddr#)
+			sz = sizeof(sys.sockaddr_in)
+		| `Ok `Ipv6 bits:
+			sa6=[.fam=sys.Afinet6, .addr=bits, .port=hosttonet(port)]
+			sa = &sa6 castto(sys.sockaddr#)
+			sz = sizeof(sys.sockaddr_in6)
+		| `Fail m:
+			-> `Fail m
+		;;
+	;;
+	sock = sys.socket(sa.fam, proto, 0)
+	if sock < 0
+		-> `Fail "failed to create socket"
+	;;
+	yes = 1
+	if sys.setsockopt(sock, sys.Solsock, sys.Soreuseaddr, &yes castto(void#), sizeof(int)) < 0
+		-> `Fail "failed to set sock opts"
+	;;
+	if sys.bind(sock, sa, sz) < 0
+		-> `Fail "failed to bind socket"
+	;;
+	-> `Ok sock castto(fd)
+}
+
+const announceunix = {path
+	var sa : sys.sockaddr_un
+	var sock
+	
+	sa = [.fam = sys.Afunix]
+	if path.len >= sa.path.len
+		-> `Fail "path too long"
+	;;
+
+	slcp(sa.path[:path.len], path)
+	sock = sys.socket(sys.Afunix, sys.Sockstream, 0)
+	if sock < 0
+		-> `Fail "failed to create socket"
+	;;
+	if sys.bind(sock, &sa castto(sys.sockaddr#), sizeof(sys.sockaddr_un)) < 0
+		-> `Fail "failed to bind address"
+	;;
+	-> `Ok (sock castto(fd))
+
+}
+
+const listen = {sock : std.fd -> result(fd, byte[:])
+	if sys.listen(sock castto(sys.fd), 10) < 0
+		-> `Fail "unable to listen on socket"
+	;;
+	-> `Ok (sys.dup(sock castto(sys.fd)) castto(fd))
+}
+
+const accept = {lfd
+	var sa : sys.sockaddr_storage
+	var len : sys.size
+	var fd
+
+	fd = sys.accept(lfd castto(sys.fd), 0 castto(sys.sockaddr#), 0 castto(sys.size#))
+	if fd < 0
+		-> `Fail "unable to accept socket"
+	;;
+	-> `Ok (fd castto(fd))
+}
+
--- a/lib/sys/sys+freebsd-x64.myr
+++ b/lib/sys/sys+freebsd-x64.myr
@@ -9,6 +9,7 @@
 	type mprot	= int64	/* memory protection */
 	type mopt	= int64	/* memory mapping options */
 	type socktype	= int64	/* socket type */
+	type sockopt	= int64	/* socket option */
 	type sockproto	= int64	/* socket protocol */
 	type sockfam	= uint8	/* socket family */
 	type filemode	= uint16
@@ -218,7 +219,26 @@
 	const Sockraw		: socktype = 3
 	const Sockrdm		: socktype = 4
 	const Sockseqpacket	: socktype = 5
+	const Solsock	: socktype =	0xffff
 
+	/* socket options */
+	const Sodebug	: sockopt = 0x0001		/* turn on debugging info recording */
+	const Soacceptconn	: sockopt = 0x0002	/* socket has had listen() */
+	const Soreuseaddr	: sockopt = 0x0004	/* allow local address reuse */
+	const Sokeepalive	: sockopt = 0x0008	/* keep connections alive */
+	const Sodontroute	: sockopt = 0x0010	/* just use interface addresses */
+	const Sobroadcast	: sockopt = 0x0020	/* permit sending of broadcast msgs */
+	const Souseloopback	: sockopt = 0x0040	/* bypass hardware when possible */
+	const Solinger		: sockopt = 0x0080	/* linger on close if data present */
+	const Sooobinline	: sockopt = 0x0100	/* leave received OOB data in line */
+	const Soreuseport	: sockopt = 0x0200	/* allow local address & port reuse */
+	const Sotimestamp	: sockopt = 0x0400	/* timestamp received dgram traffic */
+	const Sonosigpipe	: sockopt = 0x0800	/* no SIGPIPE from EPIPE */
+	const Soacceptfilter	: sockopt = 0x1000	/* there is an accept filter */
+	const Sobintime		: sockopt = 0x2000	/* timestamp received dgram traffic */
+	const Sonooffload	: sockopt = 0x4000	/* socket cannot be offloaded */
+	const Sonoddp		: sockopt = 0x8000	/* disable direct data placement */
+
 	/* network protocols */
 	const Ipproto_ip	: sockproto = 0
 	const Ipproto_icmp	: sockproto = 1
@@ -744,6 +764,8 @@
 	const accept	: (sock : fd, addr : sockaddr#, len : size# -> fd)
 	const listen	: (sock : fd, backlog : int	-> int)
 	const bind	: (sock : fd, addr : sockaddr#, len : size -> int)
+	const setsockopt	: (sock : fd, lev : socktype, opt : sockopt, val : void#, len : size -> int)
+	const getsockopt	: (sock : fd, lev : socktype, opt : sockopt, val : void#, len : size# -> int)
 
 	/* memory mapping */
 	const munmap	: (addr:byte#, len:size -> int64)
@@ -866,6 +888,8 @@
 const accept	= {sock, addr, len;	-> syscall(Sysaccept, a(sock), a(addr), a(len)) castto(fd)}
 const listen	= {sock, backlog;	-> syscall(Syslisten, a(sock), a(backlog)) castto(int)}
 const bind	= {sock, addr, len;	-> syscall(Sysbind, a(sock), a(addr), a(len)) castto(int)}
+const setsockopt	= {sock, lev, opt, val, len;	-> syscall(Syssetsockopt, a(sock), a(lev), a(opt), a(val), a(len)) castto(int)}
+const getsockopt	= {sock, lev, opt, val, len;	-> syscall(Syssetsockopt, a(sock), a(lev), a(opt), a(val), a(len)) castto(int)}
 
 /* memory management */
 const munmap	= {addr, len;		-> syscall(Sysmunmap, a(addr), a(len))}
--- a/lib/sys/sys+linux-x64.myr
+++ b/lib/sys/sys+linux-x64.myr
@@ -220,7 +220,33 @@
 	const Sockseqpacket	: socktype = 5	/* sequenced, reliable packets */
 	const Sockdccp		: socktype = 6	/* data congestion control protocol */
 	const Sockpack		: socktype = 10	/* linux specific packet */
+	const Solsock	: socktype =	1
 
+	/* socket options */
+	const Sodebug		: sockopt = 1
+	const Soreuseaddr	: sockopt = 2
+	const Sotype		: sockopt = 3
+	const Soerror		: sockopt = 4
+	const Sodontroute	: sockopt = 5
+	const Sobroadcast	: sockopt = 6
+	const Sosndbuf		: sockopt = 7
+	const Sorcvbuf		: sockopt = 8
+	const Sosndbufforce	: sockopt = 32
+	const Sorcvbufforce	: sockopt = 33
+	const Sokeepalive	: sockopt = 9
+	const Sooobinline	: sockopt = 10
+	const Sono_check	: sockopt = 11
+	const Sopriority	: sockopt = 12
+	const Solinger		: sockopt = 13
+	const Sobsdcompat	: sockopt = 14
+	const Soreuseport	: sockopt = 15
+	const Sopasscred	: sockopt = 16
+	const Sopeercred	: sockopt = 17
+	const Sorcvlowat	: sockopt = 18
+	const Sosndlowat	: sockopt = 19
+	const Sorcvtimeo	: sockopt = 20
+	const Sosndtimeo	: sockopt = 21
+
 	/* network protocols */
 	const Ipproto_ip	: sockproto = 0
 	const Ipproto_icmp	: sockproto = 1
@@ -673,6 +699,8 @@
 	const accept	: (sock : fd, addr : sockaddr#, len : size# -> fd)
 	const listen	: (sock : fd, backlog : int	-> int)
 	const bind	: (sock : fd, addr : sockaddr#, len : size -> int)
+	const setsockopt	: (sock : fd, lev : socktype, opt : sockopt, val : void#, len : size -> int)
+	const getsockopt	: (sock : fd, lev : socktype, opt : sockopt, val : void#, len : size# -> int)
 
 	/* memory mapping */
 	const munmap	: (addr:byte#, len:size -> int64)