mirror of
https://github.com/golang/go
synced 2024-11-25 14:07:56 -07:00
add network listening & tests
R=r,presotto OCL=15410 CL=15440
This commit is contained in:
parent
a456463891
commit
9350ef4eea
@ -4,17 +4,7 @@
|
|||||||
|
|
||||||
package io
|
package io
|
||||||
import os "os"
|
import os "os"
|
||||||
|
import syscall "syscall"
|
||||||
export func StringToBytes(b *[]byte, s string) bool {
|
|
||||||
if len(s) >= len(b) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
for i := 0; i < len(s); i++ {
|
|
||||||
b[i] = s[i]
|
|
||||||
}
|
|
||||||
b[len(s)] = '\000'; // not necessary - memory is zeroed - but be explicit
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
export type Read interface {
|
export type Read interface {
|
||||||
Read(p *[]byte) (n int, err *os.Error);
|
Read(p *[]byte) (n int, err *os.Error);
|
||||||
@ -24,13 +14,17 @@ export type Write interface {
|
|||||||
Write(p *[]byte) (n int, err *os.Error);
|
Write(p *[]byte) (n int, err *os.Error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type ReadWrite interface {
|
||||||
|
Read(p *[]byte) (n int, err *os.Error);
|
||||||
|
Write(p *[]byte) (n int, err *os.Error);
|
||||||
|
}
|
||||||
|
|
||||||
export func WriteString(w Write, s string) (n int, err *os.Error) {
|
export func WriteString(w Write, s string) (n int, err *os.Error) {
|
||||||
b := new([]byte, len(s)+1)
|
b := new([]byte, len(s)+1)
|
||||||
if !StringToBytes(b, s) {
|
if !syscall.StringToBytes(b, s) {
|
||||||
return -1, os.EINVAL
|
return -1, os.EINVAL
|
||||||
}
|
}
|
||||||
// BUG return w.Write(b[0:len(s)])
|
// BUG return w.Write(b[0:len(s)])
|
||||||
r, e := w.Write(b[0:len(s)])
|
r, e := w.Write(b[0:len(s)])
|
||||||
return r, e
|
return r, e
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,3 +22,10 @@ do
|
|||||||
6g -o $GOROOT/pkg/$base.6 $i
|
6g -o $GOROOT/pkg/$base.6 $i
|
||||||
done
|
done
|
||||||
|
|
||||||
|
for i in net
|
||||||
|
do
|
||||||
|
echo; echo; echo %%%% making lib/$i %%%%; echo
|
||||||
|
cd $i
|
||||||
|
make install
|
||||||
|
cd ..
|
||||||
|
done
|
||||||
|
@ -336,6 +336,10 @@ func ParseIPv6(s string) *[]byte {
|
|||||||
if len(s) >= 2 && s[0] == ':' && s[1] == ':' {
|
if len(s) >= 2 && s[0] == ':' && s[1] == ':' {
|
||||||
ellipsis = 0;
|
ellipsis = 0;
|
||||||
i = 2
|
i = 2
|
||||||
|
// Might be only ellipsis
|
||||||
|
if i == len(s) {
|
||||||
|
return p
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loop, parsing hex numbers followed by colon.
|
// Loop, parsing hex numbers followed by colon.
|
||||||
@ -343,12 +347,12 @@ func ParseIPv6(s string) *[]byte {
|
|||||||
L: for j < IPv6len {
|
L: for j < IPv6len {
|
||||||
// Hex number.
|
// Hex number.
|
||||||
n, i1, ok := xtoi(s, i)
|
n, i1, ok := xtoi(s, i)
|
||||||
if !ok || n >= 0xFFFF {
|
if !ok || n > 0xFFFF {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// If followed by dot, might be in trailing IPv4.
|
// If followed by dot, might be in trailing IPv4.
|
||||||
if s[i1] == '.' {
|
if i1 < len(s) && s[i1] == '.' {
|
||||||
if ellipsis < 0 && j != IPv6len - IPv4len {
|
if ellipsis < 0 && j != IPv6len - IPv4len {
|
||||||
// Not the right place.
|
// Not the right place.
|
||||||
return nil
|
return nil
|
||||||
@ -389,7 +393,7 @@ L: for j < IPv6len {
|
|||||||
i++
|
i++
|
||||||
|
|
||||||
// Look for ellipsis.
|
// Look for ellipsis.
|
||||||
if s[i+1] == ':' {
|
if s[i] == ':' {
|
||||||
if ellipsis >= 0 { // already have one
|
if ellipsis >= 0 { // already have one
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -411,7 +415,7 @@ L: for j < IPv6len {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
n := IPv6len - j
|
n := IPv6len - j
|
||||||
for k := j; k >= ellipsis; k-- {
|
for k := j-1; k >= ellipsis; k-- {
|
||||||
p[k+n] = p[k]
|
p[k+n] = p[k]
|
||||||
}
|
}
|
||||||
for k := ellipsis+n-1; k>=ellipsis; k-- {
|
for k := ellipsis+n-1; k>=ellipsis; k-- {
|
||||||
|
@ -19,7 +19,8 @@ func NewError(s string) *os.Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export var (
|
export var (
|
||||||
BadAddress = NewError("malformed addres");
|
BadAddress = NewError("malformed address");
|
||||||
|
MissingAddress = NewError("missing address");
|
||||||
UnknownNetwork = NewError("unknown network");
|
UnknownNetwork = NewError("unknown network");
|
||||||
UnknownHost = NewError("unknown host");
|
UnknownHost = NewError("unknown host");
|
||||||
UnknownPort = NewError("unknown port");
|
UnknownPort = NewError("unknown port");
|
||||||
@ -39,10 +40,10 @@ func SplitHostPort(hostport string) (host, port string, err *os.Error) {
|
|||||||
if i < 0 {
|
if i < 0 {
|
||||||
return "", "", BadAddress
|
return "", "", BadAddress
|
||||||
}
|
}
|
||||||
|
|
||||||
host = hostport[0:i];
|
host = hostport[0:i];
|
||||||
port = hostport[i+1:len(hostport)];
|
port = hostport[i+1:len(hostport)];
|
||||||
|
|
||||||
// Can put brackets around host ...
|
// Can put brackets around host ...
|
||||||
if host[0] == '[' && host[len(host)-1] == ']' {
|
if host[0] == '[' && host[len(host)-1] == ']' {
|
||||||
host = host[1:len(host)-1]
|
host = host[1:len(host)-1]
|
||||||
@ -69,6 +70,20 @@ func JoinHostPort(host, port string) string {
|
|||||||
return host + ":" + port
|
return host + ":" + port
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func dtoi(s string) (n int, ok bool) {
|
||||||
|
if s == "" || s[0] < '0' || s[0] > '9' {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
n = 0;
|
||||||
|
for i := 0; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ {
|
||||||
|
n = n*10 + int(s[i] - '0')
|
||||||
|
if n >= 1000000 { // bigger than we need
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return n, true
|
||||||
|
}
|
||||||
|
|
||||||
// Convert "host:port" into IP address and port.
|
// Convert "host:port" into IP address and port.
|
||||||
// For now, host and port must be numeric literals.
|
// For now, host and port must be numeric literals.
|
||||||
// Eventually, we'll have name resolution.
|
// Eventually, we'll have name resolution.
|
||||||
@ -78,22 +93,21 @@ func HostPortToIP(net string, hostport string) (ip *[]byte, iport int, err *os.E
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Resolve host.
|
// TODO: Resolve host.
|
||||||
|
|
||||||
addr := ip.ParseIP(host);
|
addr := ip.ParseIP(host);
|
||||||
if addr == nil {
|
if addr == nil {
|
||||||
print("Failed to parse: ", host, "\n");
|
|
||||||
return nil, 0, UnknownHost
|
return nil, 0, UnknownHost
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Resolve port.
|
// TODO: Resolve port.
|
||||||
|
|
||||||
p, ok := strings.atoi(port);
|
p, ok := dtoi(port);
|
||||||
if !ok || p < 0 || p > 0xFFFF {
|
if !ok || p < 0 || p > 0xFFFF {
|
||||||
return nil, 0, UnknownPort
|
return nil, 0, UnknownPort
|
||||||
}
|
}
|
||||||
|
|
||||||
return addr, p, nil
|
return addr, p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,7 +131,7 @@ func SockaddrToHostPort(sa *socket.Sockaddr) (hostport string, err *os.Error) {
|
|||||||
func boolint(b bool) int {
|
func boolint(b bool) int {
|
||||||
if b {
|
if b {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,7 +141,10 @@ func Socket(f, p, t int64, la, ra *socket.Sockaddr) (fd int64, err *os.Error) {
|
|||||||
if e != nil {
|
if e != nil {
|
||||||
return -1, e
|
return -1, e
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Allow reuse of recently-used addresses.
|
||||||
|
socket.setsockopt_int(s, socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
|
|
||||||
var r int64
|
var r int64
|
||||||
if la != nil {
|
if la != nil {
|
||||||
r, e = socket.bind(s, la)
|
r, e = socket.bind(s, la)
|
||||||
@ -136,7 +153,7 @@ func Socket(f, p, t int64, la, ra *socket.Sockaddr) (fd int64, err *os.Error) {
|
|||||||
return -1, e
|
return -1, e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ra != nil {
|
if ra != nil {
|
||||||
r, e = socket.connect(s, ra)
|
r, e = socket.connect(s, ra)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
@ -144,7 +161,7 @@ func Socket(f, p, t int64, la, ra *socket.Sockaddr) (fd int64, err *os.Error) {
|
|||||||
return -1, e
|
return -1, e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,11 +273,18 @@ func (c *ConnBase) SetLinger(sec int) *os.Error {
|
|||||||
// PreferIPv4 here should fall back to the IPv4 socket interface when possible.
|
// PreferIPv4 here should fall back to the IPv4 socket interface when possible.
|
||||||
const PreferIPv4 = false
|
const PreferIPv4 = false
|
||||||
|
|
||||||
func DialInternet(net, laddr, raddr string, proto int64) (fd int64, err *os.Error) {
|
func InternetSocket(net, laddr, raddr string, proto int64) (fd int64, err *os.Error) {
|
||||||
// Parse addresses (unless they are empty).
|
// Parse addresses (unless they are empty).
|
||||||
var lip, rip *[]byte
|
var lip, rip *[]byte
|
||||||
var lport, rport int
|
var lport, rport int
|
||||||
var lerr, rerr *os.Error
|
var lerr, rerr *os.Error
|
||||||
|
// BUG 6g doesn't zero var lists
|
||||||
|
lip = nil;
|
||||||
|
rip = nil;
|
||||||
|
lport = 0;
|
||||||
|
rport = 0;
|
||||||
|
lerr = nil;
|
||||||
|
rerr = nil
|
||||||
if laddr != "" {
|
if laddr != "" {
|
||||||
lip, lport, lerr = HostPortToIP(net, laddr)
|
lip, lport, lerr = HostPortToIP(net, laddr)
|
||||||
if lerr != nil {
|
if lerr != nil {
|
||||||
@ -274,7 +298,7 @@ func DialInternet(net, laddr, raddr string, proto int64) (fd int64, err *os.Erro
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Figure out IP version.
|
// Figure out IP version.
|
||||||
// If network has a suffix like "tcp4", obey it.
|
// If network has a suffix like "tcp4", obey it.
|
||||||
vers := 0;
|
vers := 0;
|
||||||
switch net[len(net)-1] {
|
switch net[len(net)-1] {
|
||||||
@ -303,8 +327,11 @@ func DialInternet(net, laddr, raddr string, proto int64) (fd int64, err *os.Erro
|
|||||||
cvt = &socket.IPv6ToSockaddr;
|
cvt = &socket.IPv6ToSockaddr;
|
||||||
family = socket.AF_INET6
|
family = socket.AF_INET6
|
||||||
}
|
}
|
||||||
|
|
||||||
var la, ra *socket.Sockaddr;
|
var la, ra *socket.Sockaddr;
|
||||||
|
// BUG
|
||||||
|
la = nil;
|
||||||
|
ra = nil
|
||||||
if lip != nil {
|
if lip != nil {
|
||||||
la, lerr = cvt(lip, lport);
|
la, lerr = cvt(lip, lport);
|
||||||
if lerr != nil {
|
if lerr != nil {
|
||||||
@ -388,15 +415,23 @@ func (c *ConnTCP) SetKeepAlive(keepalive bool) *os.Error {
|
|||||||
return (&c.base).SetKeepAlive(keepalive)
|
return (&c.base).SetKeepAlive(keepalive)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewConnTCP(fd int64, raddr string) *ConnTCP {
|
||||||
|
c := new(ConnTCP);
|
||||||
|
c.base.fd = os.NewFD(fd);
|
||||||
|
c.base.raddr = raddr;
|
||||||
|
c.SetNoDelay(true);
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
export func DialTCP(net, laddr, raddr string) (c *ConnTCP, err *os.Error) {
|
export func DialTCP(net, laddr, raddr string) (c *ConnTCP, err *os.Error) {
|
||||||
fd, e := DialInternet(net, laddr, raddr, socket.SOCK_STREAM)
|
if raddr == "" {
|
||||||
|
return nil, MissingAddress
|
||||||
|
}
|
||||||
|
fd, e := InternetSocket(net, laddr, raddr, socket.SOCK_STREAM)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
return nil, e
|
return nil, e
|
||||||
}
|
}
|
||||||
c = new(ConnTCP);
|
return NewConnTCP(fd, raddr), nil
|
||||||
c.base.fd = os.NewFD(fd);
|
|
||||||
c.SetNoDelay(true)
|
|
||||||
return c, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -481,3 +516,83 @@ export func Dial(net, laddr, raddr string) (c Conn, err *os.Error) {
|
|||||||
return nil, UnknownNetwork
|
return nil, UnknownNetwork
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export type Listener interface {
|
||||||
|
Accept() (c Conn, raddr string, err *os.Error);
|
||||||
|
Close() *os.Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
type NoListener struct { unused int }
|
||||||
|
func (l *NoListener) Accept() (c Conn, raddr string, err *os.Error) {
|
||||||
|
return &noconn, "", os.EINVAL
|
||||||
|
}
|
||||||
|
func (l *NoListener) Close() *os.Error { return os.EINVAL }
|
||||||
|
|
||||||
|
var nolistener NoListener
|
||||||
|
|
||||||
|
export type ListenerTCP struct {
|
||||||
|
fd *os.FD;
|
||||||
|
laddr string
|
||||||
|
}
|
||||||
|
|
||||||
|
export func ListenTCP(net, laddr string) (l *ListenerTCP, err *os.Error) {
|
||||||
|
fd, e := InternetSocket(net, laddr, "", socket.SOCK_STREAM)
|
||||||
|
if e != nil {
|
||||||
|
return nil, e
|
||||||
|
}
|
||||||
|
r, e1 := socket.listen(fd, socket.ListenBacklog())
|
||||||
|
if e1 != nil {
|
||||||
|
syscall.close(fd)
|
||||||
|
return nil, e1
|
||||||
|
}
|
||||||
|
l = new(ListenerTCP);
|
||||||
|
l.fd = os.NewFD(fd);
|
||||||
|
return l, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *ListenerTCP) AcceptTCP() (c *ConnTCP, raddr string, err *os.Error) {
|
||||||
|
if l == nil || l.fd == nil || l.fd.fd < 0 {
|
||||||
|
return nil, "", os.EINVAL
|
||||||
|
}
|
||||||
|
var sa socket.Sockaddr;
|
||||||
|
fd, e := socket.accept(l.fd.fd, &sa)
|
||||||
|
if e != nil {
|
||||||
|
return nil, "", e
|
||||||
|
}
|
||||||
|
raddr, e = SockaddrToHostPort(&sa)
|
||||||
|
if e != nil {
|
||||||
|
syscall.close(fd)
|
||||||
|
return nil, "", e
|
||||||
|
}
|
||||||
|
return NewConnTCP(fd, raddr), raddr, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *ListenerTCP) Accept() (c Conn, raddr string, err *os.Error) {
|
||||||
|
c1, r1, e1 := l.AcceptTCP()
|
||||||
|
if e1 != nil {
|
||||||
|
return &noconn, "", e1
|
||||||
|
}
|
||||||
|
return c1, r1, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *ListenerTCP) Close() *os.Error {
|
||||||
|
if l == nil || l.fd == nil {
|
||||||
|
return os.EINVAL
|
||||||
|
}
|
||||||
|
return l.fd.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
export func Listen(net, laddr string) (l Listener, err *os.Error) {
|
||||||
|
switch net {
|
||||||
|
case "tcp", "tcp4", "tcp6":
|
||||||
|
l, err := ListenTCP(net, laddr)
|
||||||
|
if err != nil {
|
||||||
|
return &nolistener, err
|
||||||
|
}
|
||||||
|
return l, nil
|
||||||
|
/*
|
||||||
|
more here
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
return nil, UnknownNetwork
|
||||||
|
}
|
||||||
|
@ -53,6 +53,8 @@ export const (
|
|||||||
IPPROTO_UDP = 17;
|
IPPROTO_UDP = 17;
|
||||||
|
|
||||||
TCP_NODELAY = 0x01;
|
TCP_NODELAY = 0x01;
|
||||||
|
|
||||||
|
SOMAXCONN = 128;
|
||||||
)
|
)
|
||||||
|
|
||||||
export type SockaddrUnix struct {
|
export type SockaddrUnix struct {
|
||||||
@ -127,7 +129,7 @@ export func listen(fd, n int64) (ret int64, err *os.Error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export func accept(fd int64, sa *Sockaddr) (ret int64, err *os.Error) {
|
export func accept(fd int64, sa *Sockaddr) (ret int64, err *os.Error) {
|
||||||
n := int32(sa.len);
|
n := SizeofSockaddr;
|
||||||
r1, r2, e := syscall.Syscall(ACCEPT, fd, SockaddrPtr(sa), Int32Ptr(&n));
|
r1, r2, e := syscall.Syscall(ACCEPT, fd, SockaddrPtr(sa), Int32Ptr(&n));
|
||||||
return r1, os.ErrnoToError(e)
|
return r1, os.ErrnoToError(e)
|
||||||
}
|
}
|
||||||
@ -229,3 +231,6 @@ export func SockaddrToIP(sa1 *Sockaddr) (p *[]byte, port int, err *os.Error) {
|
|||||||
return nil, 0, nil // not reached
|
return nil, 0, nil // not reached
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export func ListenBacklog() int64 {
|
||||||
|
return SOMAXCONN
|
||||||
|
}
|
||||||
|
@ -63,6 +63,8 @@ export const (
|
|||||||
IPPROTO_UDP = 17;
|
IPPROTO_UDP = 17;
|
||||||
|
|
||||||
TCP_NODELAY = 0x01;
|
TCP_NODELAY = 0x01;
|
||||||
|
|
||||||
|
SOMAXCONN = 128;
|
||||||
)
|
)
|
||||||
|
|
||||||
export type SockaddrUnix struct {
|
export type SockaddrUnix struct {
|
||||||
@ -145,7 +147,7 @@ export func listen(fd, n int64) (ret int64, err *os.Error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export func accept(fd int64, sa *Sockaddr) (ret int64, err *os.Error) {
|
export func accept(fd int64, sa *Sockaddr) (ret int64, err *os.Error) {
|
||||||
n := int32(sa.Len());
|
n := SizeofSockaddr;
|
||||||
r1, r2, e := syscall.Syscall(ACCEPT, fd, SockaddrPtr(sa), Int32Ptr(&n));
|
r1, r2, e := syscall.Syscall(ACCEPT, fd, SockaddrPtr(sa), Int32Ptr(&n));
|
||||||
return r1, os.ErrnoToError(e)
|
return r1, os.ErrnoToError(e)
|
||||||
}
|
}
|
||||||
@ -208,11 +210,21 @@ export func IPv4ToSockaddr(p *[]byte, port int) (sa1 *Sockaddr, err *os.Error) {
|
|||||||
return SockaddrInet4ToSockaddr(sa), nil
|
return SockaddrInet4ToSockaddr(sa), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var IPv6zero [ip.IPv6len]byte;
|
||||||
|
|
||||||
export func IPv6ToSockaddr(p *[]byte, port int) (sa1 *Sockaddr, err *os.Error) {
|
export func IPv6ToSockaddr(p *[]byte, port int) (sa1 *Sockaddr, err *os.Error) {
|
||||||
p = ip.ToIPv6(p)
|
p = ip.ToIPv6(p)
|
||||||
if p == nil || port < 0 || port > 0xFFFF {
|
if p == nil || port < 0 || port > 0xFFFF {
|
||||||
return nil, os.EINVAL
|
return nil, os.EINVAL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IPv4 callers use 0.0.0.0 to mean "announce on any available address".
|
||||||
|
// In IPv6 mode, Linux treats that as meaning "announce on 0.0.0.0",
|
||||||
|
// which it refuses to do. Rewrite to the IPv6 all zeros.
|
||||||
|
if p4 := ip.ToIPv4(p); p4 != nil && p4[0] == 0 && p4[1] == 0 && p4[2] == 0 && p4[3] == 0 {
|
||||||
|
p = &IPv6zero;
|
||||||
|
}
|
||||||
|
|
||||||
sa := new(SockaddrInet6);
|
sa := new(SockaddrInet6);
|
||||||
sa.family = AF_INET6;
|
sa.family = AF_INET6;
|
||||||
sa.port[0] = byte(port>>8);
|
sa.port[0] = byte(port>>8);
|
||||||
@ -245,3 +257,10 @@ export func SockaddrToIP(sa1 *Sockaddr) (p *[]byte, port int, err *os.Error) {
|
|||||||
return nil, 0, nil // not reached
|
return nil, 0, nil // not reached
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export func ListenBacklog() int64 {
|
||||||
|
// TODO: maybe /proc/sys/net/core/somaxconn
|
||||||
|
// and read the limit out of there, to take advantage of kernels
|
||||||
|
// that have increased the limit
|
||||||
|
|
||||||
|
return SOMAXCONN
|
||||||
|
}
|
||||||
|
@ -78,7 +78,7 @@ schedinit(void)
|
|||||||
byte *p;
|
byte *p;
|
||||||
|
|
||||||
sched.mmax = 1;
|
sched.mmax = 1;
|
||||||
p = getenv("gomaxprocs");
|
p = getenv("GOMAXPROCS");
|
||||||
if(p != nil && (n = atoi(p)) != 0)
|
if(p != nil && (n = atoi(p)) != 0)
|
||||||
sched.mmax = n;
|
sched.mmax = n;
|
||||||
sched.mcount = 1;
|
sched.mcount = 1;
|
||||||
|
@ -37,7 +37,6 @@ TEXT syscall·Syscall6(SB),7,$-8
|
|||||||
MOVQ 48(SP), R8
|
MOVQ 48(SP), R8
|
||||||
MOVQ 56(SP), R9
|
MOVQ 56(SP), R9
|
||||||
MOVQ 8(SP), AX // syscall entry
|
MOVQ 8(SP), AX // syscall entry
|
||||||
ADDQ $0x2000000, AX
|
|
||||||
SYSCALL
|
SYSCALL
|
||||||
JLS 6(PC)
|
JLS 6(PC)
|
||||||
MOVQ $-1, 64(SP) // r1
|
MOVQ $-1, 64(SP) // r1
|
||||||
|
96
test/dialgoogle.go
Normal file
96
test/dialgoogle.go
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// $G $F.go && $L $F.$A && ./$A.out
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net";
|
||||||
|
"flag";
|
||||||
|
"os";
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
// If an IPv6 tunnel is running (see go/stubl), we can try dialing a real IPv6 address.
|
||||||
|
var ipv6 = false
|
||||||
|
var ipv6_flag = flag.Bool("ipv6", false, &ipv6, "assume ipv6 tunnel is present")
|
||||||
|
|
||||||
|
func StringToBuf(s string) *[]byte
|
||||||
|
{
|
||||||
|
l := len(s);
|
||||||
|
b := new([]byte, l);
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
b[i] = s[i];
|
||||||
|
}
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// fd is already connected to www.google.com port 80.
|
||||||
|
// Run an HTTP request to fetch the main page.
|
||||||
|
func FetchGoogle(fd net.Conn) {
|
||||||
|
req := StringToBuf("GET / HTTP/1.0\r\nHost: www.google.com\r\n\r\n");
|
||||||
|
n, errno := fd.Write(req);
|
||||||
|
|
||||||
|
buf := new([1000]byte);
|
||||||
|
n, errno = fd.Read(buf);
|
||||||
|
|
||||||
|
fd.Close();
|
||||||
|
if n < 1000 {
|
||||||
|
panic("short http read");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDial(network, addr string) {
|
||||||
|
fd, err := net.Dial(network, "", addr)
|
||||||
|
if err != nil {
|
||||||
|
panic("net.Dial ", network, " ", addr, ": ", err.String())
|
||||||
|
}
|
||||||
|
FetchGoogle(fd)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDialTCP(network, addr string) {
|
||||||
|
fd, err := net.DialTCP(network, "", addr)
|
||||||
|
if err != nil {
|
||||||
|
panic("net.DialTCP ", network, " ", addr, ": ", err.String())
|
||||||
|
}
|
||||||
|
FetchGoogle(fd)
|
||||||
|
}
|
||||||
|
|
||||||
|
var addrs = []string {
|
||||||
|
"74.125.19.99:80",
|
||||||
|
"074.125.019.099:0080",
|
||||||
|
"[::ffff:74.125.19.99]:80",
|
||||||
|
"[::ffff:4a7d:1363]:80",
|
||||||
|
"[0:0:0:0:0000:ffff:74.125.19.99]:80",
|
||||||
|
"[0:0:0:0:000000:ffff:74.125.19.99]:80",
|
||||||
|
"[0:0:0:0:0:ffff::74.125.19.99]:80",
|
||||||
|
"[2001:4860:0:2001::68]:80" // ipv6.google.com; removed if ipv6 flag not set
|
||||||
|
}
|
||||||
|
|
||||||
|
func main()
|
||||||
|
{
|
||||||
|
flag.Parse()
|
||||||
|
// If no ipv6 tunnel, don't try the last address.
|
||||||
|
if !ipv6 {
|
||||||
|
addrs[len(addrs)-1] = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < len(addrs); i++ {
|
||||||
|
addr := addrs[i]
|
||||||
|
if addr == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// print(addr, "\n");
|
||||||
|
TestDial("tcp", addr);
|
||||||
|
TestDialTCP("tcp", addr)
|
||||||
|
if addr[0] != '[' {
|
||||||
|
TestDial("tcp4", addr);
|
||||||
|
TestDialTCP("tcp4", addr)
|
||||||
|
}
|
||||||
|
TestDial("tcp6", addr);
|
||||||
|
TestDialTCP("tcp6", addr)
|
||||||
|
}
|
||||||
|
}
|
99
test/tcpserver.go
Normal file
99
test/tcpserver.go
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// $G $F.go && $L $F.$A && GOMAXPROCS=3 ./$A.out
|
||||||
|
// # TODO(rsc): GOMAXPROCS will go away eventually.
|
||||||
|
// # 3 is one for Echo, one for Serve, one for Connect.
|
||||||
|
|
||||||
|
package main
|
||||||
|
import (
|
||||||
|
"os";
|
||||||
|
"io";
|
||||||
|
"net";
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
func StringToBuf(s string) *[]byte {
|
||||||
|
l := len(s);
|
||||||
|
b := new([]byte, l);
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
b[i] = s[i];
|
||||||
|
}
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
func Echo(fd io.ReadWrite, done *chan<- int) {
|
||||||
|
var buf [1024]byte;
|
||||||
|
|
||||||
|
for {
|
||||||
|
n, err := fd.Read(&buf);
|
||||||
|
if err != nil || n == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fd.Write((&buf)[0:n])
|
||||||
|
}
|
||||||
|
done <- 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func Serve(network, addr string, listening, done *chan<- int) {
|
||||||
|
l, err := net.Listen(network, addr);
|
||||||
|
if err != nil {
|
||||||
|
panic("listen: "+err.String());
|
||||||
|
}
|
||||||
|
listening <- 1;
|
||||||
|
|
||||||
|
for {
|
||||||
|
fd, addr, err := l.Accept();
|
||||||
|
if err != nil {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
echodone := new(chan int)
|
||||||
|
go Echo(fd, echodone);
|
||||||
|
<-echodone; // make sure Echo stops
|
||||||
|
l.Close();
|
||||||
|
}
|
||||||
|
done <- 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func Connect(network, addr string) {
|
||||||
|
fd, err := net.Dial(network, "", addr);
|
||||||
|
if err != nil {
|
||||||
|
panic("connect: "+err.String());
|
||||||
|
}
|
||||||
|
|
||||||
|
b := StringToBuf("hello, world\n");
|
||||||
|
var b1 [100]byte;
|
||||||
|
|
||||||
|
n, errno := fd.Write(b);
|
||||||
|
if n != len(b) {
|
||||||
|
panic("syscall.write in connect");
|
||||||
|
}
|
||||||
|
|
||||||
|
n, errno = fd.Read(&b1);
|
||||||
|
if n != len(b) {
|
||||||
|
panic("syscall.read in connect");
|
||||||
|
}
|
||||||
|
|
||||||
|
// os.Stdout.Write((&b1)[0:n]);
|
||||||
|
fd.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test(network, listenaddr, dialaddr string) {
|
||||||
|
// print("Test ", network, " ", listenaddr, " ", dialaddr, "\n");
|
||||||
|
listening := new(chan int);
|
||||||
|
done := new(chan int);
|
||||||
|
go Serve(network, listenaddr, listening, done);
|
||||||
|
<-listening; // wait for server to start
|
||||||
|
Connect(network, dialaddr);
|
||||||
|
<-done; // make sure server stopped
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
Test("tcp", "0.0.0.0:9999", "127.0.0.1:9999");
|
||||||
|
Test("tcp", "[::]:9999", "[::ffff:127.0.0.1]:9999");
|
||||||
|
Test("tcp", "[::]:9999", "127.0.0.1:9999");
|
||||||
|
Test("tcp", "0.0.0.0:9999", "[::ffff:127.0.0.1]:9999");
|
||||||
|
sys.exit(0); // supposed to happen on return, doesn't
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user