diff options
Diffstat (limited to 'libgo/go/net')
46 files changed, 788 insertions, 379 deletions
diff --git a/libgo/go/net/dialgoogle_test.go b/libgo/go/net/dialgoogle_test.go index 81750a3d739..14356da4ce3 100644 --- a/libgo/go/net/dialgoogle_test.go +++ b/libgo/go/net/dialgoogle_test.go @@ -14,7 +14,7 @@ import ( ) // If an IPv6 tunnel is running, we can try dialing a real IPv6 address. -var ipv6 = flag.Bool("ipv6", false, "assume ipv6 tunnel is present") +var testIPv6 = flag.Bool("ipv6", false, "assume ipv6 tunnel is present") // fd is already connected to the destination, port 80. // Run an HTTP request to fetch the appropriate page. @@ -130,7 +130,7 @@ func TestDialGoogleIPv6(t *testing.T) { return } // Only run tcp6 if the kernel will take it. - if !*ipv6 || !supportsIPv6 { + if !*testIPv6 || !supportsIPv6 { return } diff --git a/libgo/go/net/fd.go b/libgo/go/net/fd.go index bf0a387775d..ae1bf2614a2 100644 --- a/libgo/go/net/fd.go +++ b/libgo/go/net/fd.go @@ -252,7 +252,9 @@ func (s *pollServer) Run() { } else { netfd := s.LookupFD(fd, mode) if netfd == nil { - print("pollServer: unexpected wakeup for fd=", fd, " mode=", string(mode), "\n") + // This can happen because the WaitFD runs without + // holding s's lock, so there might be a pending wakeup + // for an fd that has been evicted. No harm done. continue } s.WakeFD(netfd, mode, nil) @@ -506,7 +508,7 @@ func (fd *netFD) Write(p []byte) (int, error) { } defer fd.decref() if fd.sysfile == nil { - return 0, os.EINVAL + return 0, syscall.EINVAL } var err error diff --git a/libgo/go/net/fd_windows.go b/libgo/go/net/fd_windows.go index efd846e5d8c..45f5c2d882f 100644 --- a/libgo/go/net/fd_windows.go +++ b/libgo/go/net/fd_windows.go @@ -335,7 +335,7 @@ func (fd *netFD) Close() error { func (fd *netFD) shutdown(how int) error { if fd == nil || fd.sysfd == syscall.InvalidHandle { - return os.EINVAL + return syscall.EINVAL } err := syscall.Shutdown(fd.sysfd, how) if err != nil { @@ -369,7 +369,7 @@ func (o *readOp) Name() string { func (fd *netFD) Read(buf []byte) (int, error) { if fd == nil { - return 0, os.EINVAL + return 0, syscall.EINVAL } fd.rio.Lock() defer fd.rio.Unlock() @@ -378,7 +378,7 @@ func (fd *netFD) Read(buf []byte) (int, error) { } defer fd.decref() if fd.sysfd == syscall.InvalidHandle { - return 0, os.EINVAL + return 0, syscall.EINVAL } var o readOp o.Init(fd, buf, 'r') @@ -408,7 +408,7 @@ func (o *readFromOp) Name() string { func (fd *netFD) ReadFrom(buf []byte) (n int, sa syscall.Sockaddr, err error) { if fd == nil { - return 0, nil, os.EINVAL + return 0, nil, syscall.EINVAL } if len(buf) == 0 { return 0, nil, nil @@ -447,7 +447,7 @@ func (o *writeOp) Name() string { func (fd *netFD) Write(buf []byte) (int, error) { if fd == nil { - return 0, os.EINVAL + return 0, syscall.EINVAL } fd.wio.Lock() defer fd.wio.Unlock() @@ -478,7 +478,7 @@ func (o *writeToOp) Name() string { func (fd *netFD) WriteTo(buf []byte, sa syscall.Sockaddr) (int, error) { if fd == nil { - return 0, os.EINVAL + return 0, syscall.EINVAL } if len(buf) == 0 { return 0, nil @@ -490,7 +490,7 @@ func (fd *netFD) WriteTo(buf []byte, sa syscall.Sockaddr) (int, error) { } defer fd.decref() if fd.sysfd == syscall.InvalidHandle { - return 0, os.EINVAL + return 0, syscall.EINVAL } var o writeToOp o.Init(fd, buf, 'w') @@ -578,10 +578,12 @@ func (fd *netFD) dup() (*os.File, error) { return nil, os.NewSyscallError("dup", syscall.EWINDOWS) } +var errNoSupport = errors.New("address family not supported") + func (fd *netFD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) { - return 0, 0, 0, nil, os.EAFNOSUPPORT + return 0, 0, 0, nil, errNoSupport } func (fd *netFD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) { - return 0, 0, os.EAFNOSUPPORT + return 0, 0, errNoSupport } diff --git a/libgo/go/net/file.go b/libgo/go/net/file.go index f9546dc930d..c95d16d64e7 100644 --- a/libgo/go/net/file.go +++ b/libgo/go/net/file.go @@ -28,7 +28,7 @@ func newFileFD(f *os.File) (*netFD, error) { switch sa.(type) { default: closesocket(fd) - return nil, os.EINVAL + return nil, syscall.EINVAL case *syscall.SockaddrInet4: family = syscall.AF_INET if proto == syscall.SOCK_DGRAM { @@ -84,7 +84,7 @@ func FileConn(f *os.File) (c Conn, err error) { return newIPConn(fd), nil } fd.Close() - return nil, os.EINVAL + return nil, syscall.EINVAL } // FileListener returns a copy of the network listener corresponding @@ -103,7 +103,7 @@ func FileListener(f *os.File) (l Listener, err error) { return &UnixListener{fd, laddr.Name}, nil } fd.Close() - return nil, os.EINVAL + return nil, syscall.EINVAL } // FilePacketConn returns a copy of the packet network connection @@ -122,5 +122,5 @@ func FilePacketConn(f *os.File) (c PacketConn, err error) { return newUnixConn(fd), nil } fd.Close() - return nil, os.EINVAL + return nil, syscall.EINVAL } diff --git a/libgo/go/net/file_plan9.go b/libgo/go/net/file_plan9.go index 06d7cc89846..04f7ee0401b 100644 --- a/libgo/go/net/file_plan9.go +++ b/libgo/go/net/file_plan9.go @@ -6,6 +6,7 @@ package net import ( "os" + "syscall" ) // FileConn returns a copy of the network connection corresponding to @@ -13,7 +14,7 @@ import ( // finished. Closing c does not affect f, and closing f does not // affect c. func FileConn(f *os.File) (c Conn, err error) { - return nil, os.EPLAN9 + return nil, syscall.EPLAN9 } // FileListener returns a copy of the network listener corresponding @@ -21,7 +22,7 @@ func FileConn(f *os.File) (c Conn, err error) { // when finished. Closing c does not affect l, and closing l does not // affect c. func FileListener(f *os.File) (l Listener, err error) { - return nil, os.EPLAN9 + return nil, syscall.EPLAN9 } // FilePacketConn returns a copy of the packet network connection @@ -29,5 +30,5 @@ func FileListener(f *os.File) (l Listener, err error) { // responsibility to close f when finished. Closing c does not affect // f, and closing f does not affect c. func FilePacketConn(f *os.File) (c PacketConn, err error) { - return nil, os.EPLAN9 + return nil, syscall.EPLAN9 } diff --git a/libgo/go/net/hosts_test.go b/libgo/go/net/hosts_test.go index 1bd00541c6d..064e7e43282 100644 --- a/libgo/go/net/hosts_test.go +++ b/libgo/go/net/hosts_test.go @@ -34,7 +34,7 @@ var hosttests = []hostTest{ func TestLookupStaticHost(t *testing.T) { p := hostsPath - hostsPath = "hosts_testdata" + hostsPath = "testdata/hosts" for i := 0; i < len(hosttests); i++ { tt := hosttests[i] ips := lookupStaticHost(tt.host) diff --git a/libgo/go/net/http/cookie_test.go b/libgo/go/net/http/cookie_test.go index 712350dfcef..1e9186a0581 100644 --- a/libgo/go/net/http/cookie_test.go +++ b/libgo/go/net/http/cookie_test.go @@ -128,6 +128,34 @@ var readSetCookiesTests = []struct { Raw: "NID=99=YsDT5i3E-CXax-; expires=Wed, 23-Nov-2011 01:05:03 GMT; path=/; domain=.google.ch; HttpOnly", }}, }, + { + Header{"Set-Cookie": {".ASPXAUTH=7E3AA; expires=Wed, 07-Mar-2012 14:25:06 GMT; path=/; HttpOnly"}}, + []*Cookie{{ + Name: ".ASPXAUTH", + Value: "7E3AA", + Path: "/", + Expires: time.Date(2012, 3, 7, 14, 25, 6, 0, time.UTC), + RawExpires: "Wed, 07-Mar-2012 14:25:06 GMT", + HttpOnly: true, + Raw: ".ASPXAUTH=7E3AA; expires=Wed, 07-Mar-2012 14:25:06 GMT; path=/; HttpOnly", + }}, + }, + { + Header{"Set-Cookie": {"ASP.NET_SessionId=foo; path=/; HttpOnly"}}, + []*Cookie{{ + Name: "ASP.NET_SessionId", + Value: "foo", + Path: "/", + HttpOnly: true, + Raw: "ASP.NET_SessionId=foo; path=/; HttpOnly", + }}, + }, + + // TODO(bradfitz): users have reported seeing this in the + // wild, but do browsers handle it? RFC 6265 just says "don't + // do that" (section 3) and then never mentions header folding + // again. + // Header{"Set-Cookie": {"ASP.NET_SessionId=foo; path=/; HttpOnly, .ASPXAUTH=7E3AA; expires=Wed, 07-Mar-2012 14:25:06 GMT; path=/; HttpOnly"}}, } func toJSON(v interface{}) string { diff --git a/libgo/go/net/http/example_test.go b/libgo/go/net/http/example_test.go new file mode 100644 index 00000000000..2584afc439e --- /dev/null +++ b/libgo/go/net/http/example_test.go @@ -0,0 +1,51 @@ +// Copyright 2012 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. + +package http_test + +import ( + "fmt" + "io/ioutil" + "log" + "net/http" +) + +func ExampleHijacker() { + http.HandleFunc("/hijack", func(w http.ResponseWriter, r *http.Request) { + hj, ok := w.(http.Hijacker) + if !ok { + http.Error(w, "webserver doesn't support hijacking", http.StatusInternalServerError) + return + } + conn, bufrw, err := hj.Hijack() + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + // Don't forget to close the connection: + defer conn.Close() + bufrw.WriteString("Now we're speaking raw TCP. Say hi: ") + bufrw.Flush() + s, err := bufrw.ReadString('\n') + if err != nil { + log.Printf("error reading string: %v", err) + return + } + fmt.Fprintf(bufrw, "You said: %q\nBye.\n", s) + bufrw.Flush() + }) +} + +func ExampleGet() { + res, err := http.Get("http://www.google.com/robots.txt") + if err != nil { + log.Fatal(err) + } + robots, err := ioutil.ReadAll(res.Body) + if err != nil { + log.Fatal(err) + } + res.Body.Close() + fmt.Printf("%s", robots) +} diff --git a/libgo/go/net/http/fs_test.go b/libgo/go/net/http/fs_test.go index 143617e95fc..0409008b675 100644 --- a/libgo/go/net/http/fs_test.go +++ b/libgo/go/net/http/fs_test.go @@ -6,6 +6,7 @@ package http_test import ( "bytes" + "errors" "fmt" "io" "io/ioutil" @@ -131,7 +132,7 @@ func TestFileServerCleans(t *testing.T) { ch := make(chan string, 1) fs := FileServer(&testFileSystem{func(name string) (File, error) { ch <- name - return nil, os.ENOENT + return nil, errors.New("file does not exist") }}) tests := []struct { reqPath, openArg string @@ -398,11 +399,15 @@ func TestLinuxSendfile(t *testing.T) { return } - _, err = Get(fmt.Sprintf("http://%s/", ln.Addr())) + res, err := Get(fmt.Sprintf("http://%s/", ln.Addr())) if err != nil { - t.Errorf("http client error: %v", err) - return + t.Fatalf("http client error: %v", err) + } + _, err = io.Copy(ioutil.Discard, res.Body) + if err != nil { + t.Fatalf("client body read error: %v", err) } + res.Body.Close() // Force child to exit cleanly. Get(fmt.Sprintf("http://%s/quit", ln.Addr())) diff --git a/libgo/go/net/http/httputil/persist.go b/libgo/go/net/http/httputil/persist.go index c065ccfb499..32f4662cc0e 100644 --- a/libgo/go/net/http/httputil/persist.go +++ b/libgo/go/net/http/httputil/persist.go @@ -13,12 +13,12 @@ import ( "net" "net/http" "net/textproto" - "os" "sync" ) var ( ErrPersistEOF = &http.ProtocolError{ErrorString: "persistent connection closed"} + ErrClosed = &http.ProtocolError{ErrorString: "connection closed by user"} ErrPipeline = &http.ProtocolError{ErrorString: "pipeline error"} ) @@ -191,7 +191,7 @@ func (sc *ServerConn) Write(req *http.Request, resp *http.Response) error { } if sc.c == nil { // connection closed by user in the meantime defer sc.lk.Unlock() - return os.EBADF + return ErrClosed } c := sc.c if sc.nread <= sc.nwritten { diff --git a/libgo/go/net/http/pprof/pprof.go b/libgo/go/net/http/pprof/pprof.go index 0fe41b7d31b..06fcde1447f 100644 --- a/libgo/go/net/http/pprof/pprof.go +++ b/libgo/go/net/http/pprof/pprof.go @@ -22,9 +22,9 @@ // // go tool pprof http://localhost:6060/debug/pprof/profile // -// Or to look at the thread creation profile: +// Or to view all available profiles: // -// go tool pprof http://localhost:6060/debug/pprof/thread +// go tool pprof http://localhost:6060/debug/pprof/ // // For a study of the facility in action, visit // @@ -36,7 +36,9 @@ import ( "bufio" "bytes" "fmt" + "html/template" "io" + "log" "net/http" "os" "runtime" @@ -47,11 +49,10 @@ import ( ) func init() { + http.Handle("/debug/pprof/", http.HandlerFunc(Index)) http.Handle("/debug/pprof/cmdline", http.HandlerFunc(Cmdline)) http.Handle("/debug/pprof/profile", http.HandlerFunc(Profile)) - http.Handle("/debug/pprof/heap", http.HandlerFunc(Heap)) http.Handle("/debug/pprof/symbol", http.HandlerFunc(Symbol)) - http.Handle("/debug/pprof/thread", http.HandlerFunc(Thread)) } // Cmdline responds with the running program's @@ -62,20 +63,6 @@ func Cmdline(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, strings.Join(os.Args, "\x00")) } -// Heap responds with the pprof-formatted heap profile. -// The package initialization registers it as /debug/pprof/heap. -func Heap(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "text/plain; charset=utf-8") - pprof.WriteHeapProfile(w) -} - -// Thread responds with the pprof-formatted thread creation profile. -// The package initialization registers it as /debug/pprof/thread. -func Thread(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "text/plain; charset=utf-8") - pprof.WriteThreadProfile(w) -} - // Profile responds with the pprof-formatted cpu profile. // The package initialization registers it as /debug/pprof/profile. func Profile(w http.ResponseWriter, r *http.Request) { @@ -147,3 +134,61 @@ func Symbol(w http.ResponseWriter, r *http.Request) { w.Write(buf.Bytes()) } + +// Handler returns an HTTP handler that serves the named profile. +func Handler(name string) http.Handler { + return handler(name) +} + +type handler string + +func (name handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "text/plain; charset=utf-8") + debug, _ := strconv.Atoi(r.FormValue("debug")) + p := pprof.Lookup(string(name)) + if p == nil { + w.WriteHeader(404) + fmt.Fprintf(w, "Unknown profile: %s\n", name) + return + } + p.WriteTo(w, debug) + return +} + +// Index responds with the pprof-formatted profile named by the request. +// For example, "/debug/pprof/heap" serves the "heap" profile. +// Index responds to a request for "/debug/pprof/" with an HTML page +// listing the available profiles. +func Index(w http.ResponseWriter, r *http.Request) { + if strings.HasPrefix(r.URL.Path, "/debug/pprof/") { + name := r.URL.Path[len("/debug/pprof/"):] + if name != "" { + handler(name).ServeHTTP(w, r) + return + } + } + + profiles := pprof.Profiles() + if err := indexTmpl.Execute(w, profiles); err != nil { + log.Print(err) + } +} + +var indexTmpl = template.Must(template.New("index").Parse(`<html> +<head> +<title>/debug/pprof/</title> +</head> +/debug/pprof/<br> +<br> +<body> +profiles:<br> +<table> +{{range .}} +<tr><td align=right>{{.Count}}<td><a href="/debug/pprof/{{.Name}}?debug=1">{{.Name}}</a> +{{end}} +</table> +<br> +<a href="/debug/pprof/goroutine?debug=2">full goroutine stack dump</a><br> +</body> +</html> +`)) diff --git a/libgo/go/net/http/request.go b/libgo/go/net/http/request.go index 0bbec53be71..5277657805d 100644 --- a/libgo/go/net/http/request.go +++ b/libgo/go/net/http/request.go @@ -186,7 +186,7 @@ func (r *Request) Cookies() []*Cookie { return readCookies(r.Header, "") } -var ErrNoCookie = errors.New("http: named cookied not present") +var ErrNoCookie = errors.New("http: named cookie not present") // Cookie returns the named cookie provided in the request or // ErrNoCookie if not found. @@ -486,7 +486,7 @@ func ReadRequest(b *bufio.Reader) (req *Request, err error) { rawurl = "http://" + rawurl } - if req.URL, err = url.ParseRequest(rawurl); err != nil { + if req.URL, err = url.ParseRequestURI(rawurl); err != nil { return nil, err } diff --git a/libgo/go/net/http/serve_test.go b/libgo/go/net/http/serve_test.go index e2860c3edcf..b6a6b4c77d1 100644 --- a/libgo/go/net/http/serve_test.go +++ b/libgo/go/net/http/serve_test.go @@ -245,8 +245,7 @@ func TestServerTimeouts(t *testing.T) { fmt.Fprintf(res, "req=%d", reqNum) }) - const second = 1000000000 /* nanos */ - server := &Server{Handler: handler, ReadTimeout: 0.25 * second, WriteTimeout: 0.25 * second} + server := &Server{Handler: handler, ReadTimeout: 250 * time.Millisecond, WriteTimeout: 250 * time.Millisecond} go server.Serve(l) url := fmt.Sprintf("http://%s/", addr) @@ -277,7 +276,7 @@ func TestServerTimeouts(t *testing.T) { if n != 0 || err != io.EOF { t.Errorf("Read = %v, %v, wanted %v, %v", n, err, 0, io.EOF) } - if latency < 200*time.Millisecond /* fudge from 0.25 above */ { + if latency < 200*time.Millisecond /* fudge from 250 ms above */ { t.Errorf("got EOF after %s, want >= %s", latency, 200*time.Millisecond) } diff --git a/libgo/go/net/http/server.go b/libgo/go/net/http/server.go index e715c73cb6e..fa0df54a236 100644 --- a/libgo/go/net/http/server.go +++ b/libgo/go/net/http/server.go @@ -12,7 +12,6 @@ package http import ( "bufio" "bytes" - "crypto/rand" "crypto/tls" "errors" "fmt" @@ -985,6 +984,7 @@ type Server struct { ReadTimeout time.Duration // maximum duration before timing out read of the request WriteTimeout time.Duration // maximum duration before timing out write of the response MaxHeaderBytes int // maximum size of request headers, DefaultMaxHeaderBytes if 0 + TLSConfig *tls.Config // optional TLS config, used by ListenAndServeTLS } // ListenAndServe listens on the TCP network address srv.Addr and then @@ -1121,9 +1121,12 @@ func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error { if addr == "" { addr = ":https" } - config := &tls.Config{ - Rand: rand.Reader, - NextProtos: []string{"http/1.1"}, + config := &tls.Config{} + if srv.TLSConfig != nil { + *config = *srv.TLSConfig + } + if config.NextProtos == nil { + config.NextProtos = []string{"http/1.1"} } var err error diff --git a/libgo/go/net/http/transport_test.go b/libgo/go/net/http/transport_test.go index a36571a4446..1a629c1727c 100644 --- a/libgo/go/net/http/transport_test.go +++ b/libgo/go/net/http/transport_test.go @@ -648,7 +648,7 @@ func TestTransportPersistConnLeak(t *testing.T) { tr := &Transport{} c := &Client{Transport: tr} - n0 := runtime.Goroutines() + n0 := runtime.NumGoroutine() const numReq = 25 didReqCh := make(chan bool) @@ -669,7 +669,7 @@ func TestTransportPersistConnLeak(t *testing.T) { <-gotReqCh } - nhigh := runtime.Goroutines() + nhigh := runtime.NumGoroutine() // Tell all handlers to unblock and reply. for i := 0; i < numReq; i++ { @@ -685,7 +685,7 @@ func TestTransportPersistConnLeak(t *testing.T) { time.Sleep(100 * time.Millisecond) runtime.GC() runtime.GC() // even more. - nfinal := runtime.Goroutines() + nfinal := runtime.NumGoroutine() growth := nfinal - n0 diff --git a/libgo/go/net/interface_linux.go b/libgo/go/net/interface_linux.go index 21038c629b1..15c2f3781b1 100644 --- a/libgo/go/net/interface_linux.go +++ b/libgo/go/net/interface_linux.go @@ -166,13 +166,13 @@ func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) { return nil, err } } - ifmat4 := parseProcNetIGMP(ifi) - ifmat6 := parseProcNetIGMP6(ifi) + ifmat4 := parseProcNetIGMP("/proc/net/igmp", ifi) + ifmat6 := parseProcNetIGMP6("/proc/net/igmp6", ifi) return append(ifmat4, ifmat6...), nil } -func parseProcNetIGMP(ifi *Interface) []Addr { - fd, err := open("/proc/net/igmp") +func parseProcNetIGMP(path string, ifi *Interface) []Addr { + fd, err := open(path) if err != nil { return nil } @@ -185,23 +185,26 @@ func parseProcNetIGMP(ifi *Interface) []Addr { fd.readLine() // skip first line b := make([]byte, IPv4len) for l, ok := fd.readLine(); ok; l, ok = fd.readLine() { - f := getFields(l) - switch len(f) { - case 4: + f := splitAtBytes(l, " :\r\t\n") + if len(f) < 4 { + continue + } + switch { + case l[0] != ' ' && l[0] != '\t': // new interface line + name = f[1] + case len(f[0]) == 8: if ifi == nil || name == ifi.Name { fmt.Sscanf(f[0], "%08x", &b) ifma := IPAddr{IP: IPv4(b[3], b[2], b[1], b[0])} ifmat = append(ifmat, ifma.toAddr()) } - case 5: - name = f[1] } } return ifmat } -func parseProcNetIGMP6(ifi *Interface) []Addr { - fd, err := open("/proc/net/igmp6") +func parseProcNetIGMP6(path string, ifi *Interface) []Addr { + fd, err := open(path) if err != nil { return nil } @@ -210,7 +213,10 @@ func parseProcNetIGMP6(ifi *Interface) []Addr { var ifmat []Addr b := make([]byte, IPv6len) for l, ok := fd.readLine(); ok; l, ok = fd.readLine() { - f := getFields(l) + f := splitAtBytes(l, " \r\t\n") + if len(f) < 6 { + continue + } if ifi == nil || f[1] == ifi.Name { fmt.Sscanf(f[2], "%32x", &b) ifma := IPAddr{IP: IP{b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15]}} diff --git a/libgo/go/net/interface_test.go b/libgo/go/net/interface_test.go index 4ce01dc9061..769414e0eef 100644 --- a/libgo/go/net/interface_test.go +++ b/libgo/go/net/interface_test.go @@ -31,17 +31,17 @@ func TestInterfaces(t *testing.T) { for _, ifi := range ift { ifxi, err := InterfaceByIndex(ifi.Index) if err != nil { - t.Fatalf("InterfaceByIndex(%#q) failed: %v", ifi.Index, err) + t.Fatalf("InterfaceByIndex(%q) failed: %v", ifi.Index, err) } if !sameInterface(ifxi, &ifi) { - t.Fatalf("InterfaceByIndex(%#q) = %v, want %v", ifi.Index, *ifxi, ifi) + t.Fatalf("InterfaceByIndex(%q) = %v, want %v", ifi.Index, *ifxi, ifi) } ifxn, err := InterfaceByName(ifi.Name) if err != nil { - t.Fatalf("InterfaceByName(%#q) failed: %v", ifi.Name, err) + t.Fatalf("InterfaceByName(%q) failed: %v", ifi.Name, err) } if !sameInterface(ifxn, &ifi) { - t.Fatalf("InterfaceByName(%#q) = %v, want %v", ifi.Name, *ifxn, ifi) + t.Fatalf("InterfaceByName(%q) = %v, want %v", ifi.Name, *ifxn, ifi) } t.Logf("%q: flags %q, ifindex %v, mtu %v\n", ifi.Name, ifi.Flags.String(), ifi.Index, ifi.MTU) t.Logf("\thardware address %q", ifi.HardwareAddr.String()) diff --git a/libgo/go/net/ipraw_test.go b/libgo/go/net/ipraw_test.go index f9401c1104e..6136202727c 100644 --- a/libgo/go/net/ipraw_test.go +++ b/libgo/go/net/ipraw_test.go @@ -7,6 +7,7 @@ package net import ( "bytes" "os" + "syscall" "testing" "time" ) @@ -15,7 +16,7 @@ var icmpTests = []struct { net string laddr string raddr string - ipv6 bool + ipv6 bool // test with underlying AF_INET6 socket }{ {"ip4:icmp", "", "127.0.0.1", false}, {"ip6:icmp", "", "::1", true}, @@ -34,15 +35,15 @@ func TestICMP(t *testing.T) { } id := os.Getpid() & 0xffff seqnum++ - echo := newICMPEchoRequest(tt.ipv6, id, seqnum, 128, []byte("Go Go Gadget Ping!!!")) - exchangeICMPEcho(t, tt.net, tt.laddr, tt.raddr, tt.ipv6, echo) + echo := newICMPEchoRequest(tt.net, id, seqnum, 128, []byte("Go Go Gadget Ping!!!")) + exchangeICMPEcho(t, tt.net, tt.laddr, tt.raddr, echo) } } -func exchangeICMPEcho(t *testing.T, net, laddr, raddr string, ipv6 bool, echo []byte) { +func exchangeICMPEcho(t *testing.T, net, laddr, raddr string, echo []byte) { c, err := ListenPacket(net, laddr) if err != nil { - t.Errorf("ListenPacket(%#q, %#q) failed: %v", net, laddr, err) + t.Errorf("ListenPacket(%q, %q) failed: %v", net, laddr, err) return } c.SetDeadline(time.Now().Add(100 * time.Millisecond)) @@ -50,12 +51,12 @@ func exchangeICMPEcho(t *testing.T, net, laddr, raddr string, ipv6 bool, echo [] ra, err := ResolveIPAddr(net, raddr) if err != nil { - t.Errorf("ResolveIPAddr(%#q, %#q) failed: %v", net, raddr, err) + t.Errorf("ResolveIPAddr(%q, %q) failed: %v", net, raddr, err) return } waitForReady := make(chan bool) - go icmpEchoTransponder(t, net, raddr, ipv6, waitForReady) + go icmpEchoTransponder(t, net, raddr, waitForReady) <-waitForReady _, err = c.WriteTo(echo, ra) @@ -71,11 +72,15 @@ func exchangeICMPEcho(t *testing.T, net, laddr, raddr string, ipv6 bool, echo [] t.Errorf("ReadFrom failed: %v", err) return } - if !ipv6 && reply[0] != ICMP4_ECHO_REPLY { - continue - } - if ipv6 && reply[0] != ICMP6_ECHO_REPLY { - continue + switch c.(*IPConn).fd.family { + case syscall.AF_INET: + if reply[0] != ICMP4_ECHO_REPLY { + continue + } + case syscall.AF_INET6: + if reply[0] != ICMP6_ECHO_REPLY { + continue + } } xid, xseqnum := parseICMPEchoReply(echo) rid, rseqnum := parseICMPEchoReply(reply) @@ -87,11 +92,11 @@ func exchangeICMPEcho(t *testing.T, net, laddr, raddr string, ipv6 bool, echo [] } } -func icmpEchoTransponder(t *testing.T, net, raddr string, ipv6 bool, waitForReady chan bool) { +func icmpEchoTransponder(t *testing.T, net, raddr string, waitForReady chan bool) { c, err := Dial(net, raddr) if err != nil { waitForReady <- true - t.Errorf("Dial(%#q, %#q) failed: %v", net, raddr, err) + t.Errorf("Dial(%q, %q) failed: %v", net, raddr, err) return } c.SetDeadline(time.Now().Add(100 * time.Millisecond)) @@ -106,18 +111,23 @@ func icmpEchoTransponder(t *testing.T, net, raddr string, ipv6 bool, waitForRead t.Errorf("Read failed: %v", err) return } - if !ipv6 && echo[0] != ICMP4_ECHO_REQUEST { - continue - } - if ipv6 && echo[0] != ICMP6_ECHO_REQUEST { - continue + switch c.(*IPConn).fd.family { + case syscall.AF_INET: + if echo[0] != ICMP4_ECHO_REQUEST { + continue + } + case syscall.AF_INET6: + if echo[0] != ICMP6_ECHO_REQUEST { + continue + } } break } - if !ipv6 { + switch c.(*IPConn).fd.family { + case syscall.AF_INET: echo[0] = ICMP4_ECHO_REPLY - } else { + case syscall.AF_INET6: echo[0] = ICMP6_ECHO_REPLY } @@ -135,11 +145,15 @@ const ( ICMP6_ECHO_REPLY = 129 ) -func newICMPEchoRequest(ipv6 bool, id, seqnum, msglen int, filler []byte) []byte { - if !ipv6 { +func newICMPEchoRequest(net string, id, seqnum, msglen int, filler []byte) []byte { + afnet, _, _ := parseDialNetwork(net) + switch afnet { + case "ip4": return newICMPv4EchoRequest(id, seqnum, msglen, filler) + case "ip6": + return newICMPv6EchoRequest(id, seqnum, msglen, filler) } - return newICMPv6EchoRequest(id, seqnum, msglen, filler) + return nil } func newICMPv4EchoRequest(id, seqnum, msglen int, filler []byte) []byte { diff --git a/libgo/go/net/iprawsock_plan9.go b/libgo/go/net/iprawsock_plan9.go index 382a4402770..43719fc99cd 100644 --- a/libgo/go/net/iprawsock_plan9.go +++ b/libgo/go/net/iprawsock_plan9.go @@ -7,7 +7,7 @@ package net import ( - "os" + "syscall" "time" ) @@ -17,34 +17,34 @@ type IPConn bool // SetDeadline implements the Conn SetDeadline method. func (c *IPConn) SetDeadline(t time.Time) error { - return os.EPLAN9 + return syscall.EPLAN9 } // SetReadDeadline implements the Conn SetReadDeadline method. func (c *IPConn) SetReadDeadline(t time.Time) error { - return os.EPLAN9 + return syscall.EPLAN9 } // SetWriteDeadline implements the Conn SetWriteDeadline method. func (c *IPConn) SetWriteDeadline(t time.Time) error { - return os.EPLAN9 + return syscall.EPLAN9 } // Implementation of the Conn interface - see Conn for documentation. // Read implements the Conn Read method. func (c *IPConn) Read(b []byte) (int, error) { - return 0, os.EPLAN9 + return 0, syscall.EPLAN9 } // Write implements the Conn Write method. func (c *IPConn) Write(b []byte) (int, error) { - return 0, os.EPLAN9 + return 0, syscall.EPLAN9 } // Close closes the IP connection. func (c *IPConn) Close() error { - return os.EPLAN9 + return syscall.EPLAN9 } // LocalAddr returns the local network address. @@ -67,12 +67,12 @@ func (c *IPConn) RemoteAddr() Addr { // Timeout() == true after a fixed time limit; see SetDeadline and // SetReadDeadline. func (c *IPConn) ReadFromIP(b []byte) (int, *IPAddr, error) { - return 0, nil, os.EPLAN9 + return 0, nil, syscall.EPLAN9 } // ReadFrom implements the PacketConn ReadFrom method. func (c *IPConn) ReadFrom(b []byte) (int, Addr, error) { - return 0, nil, os.EPLAN9 + return 0, nil, syscall.EPLAN9 } // WriteToIP writes a IP packet to addr via c, copying the payload from b. @@ -82,18 +82,18 @@ func (c *IPConn) ReadFrom(b []byte) (int, Addr, error) { // see SetDeadline and SetWriteDeadline. // On packet-oriented connections, write timeouts are rare. func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (int, error) { - return 0, os.EPLAN9 + return 0, syscall.EPLAN9 } // WriteTo implements the PacketConn WriteTo method. func (c *IPConn) WriteTo(b []byte, addr Addr) (int, error) { - return 0, os.EPLAN9 + return 0, syscall.EPLAN9 } // DialIP connects to the remote address raddr on the network protocol netProto, // which must be "ip", "ip4", or "ip6" followed by a colon and a protocol number or name. func DialIP(netProto string, laddr, raddr *IPAddr) (*IPConn, error) { - return nil, os.EPLAN9 + return nil, syscall.EPLAN9 } // ListenIP listens for incoming IP packets addressed to the @@ -101,5 +101,5 @@ func DialIP(netProto string, laddr, raddr *IPAddr) (*IPConn, error) { // and WriteTo methods can be used to receive and send IP // packets with per-packet addressing. func ListenIP(netProto string, laddr *IPAddr) (*IPConn, error) { - return nil, os.EPLAN9 + return nil, syscall.EPLAN9 } diff --git a/libgo/go/net/iprawsock_posix.go b/libgo/go/net/iprawsock_posix.go index c34ffeb121d..9caa86985a5 100644 --- a/libgo/go/net/iprawsock_posix.go +++ b/libgo/go/net/iprawsock_posix.go @@ -66,7 +66,7 @@ func (c *IPConn) Read(b []byte) (int, error) { // Write implements the Conn Write method. func (c *IPConn) Write(b []byte) (int, error) { if !c.ok() { - return 0, os.EINVAL + return 0, syscall.EINVAL } return c.fd.Write(b) } @@ -74,7 +74,7 @@ func (c *IPConn) Write(b []byte) (int, error) { // Close closes the IP connection. func (c *IPConn) Close() error { if !c.ok() { - return os.EINVAL + return syscall.EINVAL } err := c.fd.Close() c.fd = nil @@ -100,7 +100,7 @@ func (c *IPConn) RemoteAddr() Addr { // SetDeadline implements the Conn SetDeadline method. func (c *IPConn) SetDeadline(t time.Time) error { if !c.ok() { - return os.EINVAL + return syscall.EINVAL } return setDeadline(c.fd, t) } @@ -108,7 +108,7 @@ func (c *IPConn) SetDeadline(t time.Time) error { // SetReadDeadline implements the Conn SetReadDeadline method. func (c *IPConn) SetReadDeadline(t time.Time) error { if !c.ok() { - return os.EINVAL + return syscall.EINVAL } return setReadDeadline(c.fd, t) } @@ -116,7 +116,7 @@ func (c *IPConn) SetReadDeadline(t time.Time) error { // SetWriteDeadline implements the Conn SetWriteDeadline method. func (c *IPConn) SetWriteDeadline(t time.Time) error { if !c.ok() { - return os.EINVAL + return syscall.EINVAL } return setWriteDeadline(c.fd, t) } @@ -125,7 +125,7 @@ func (c *IPConn) SetWriteDeadline(t time.Time) error { // receive buffer associated with the connection. func (c *IPConn) SetReadBuffer(bytes int) error { if !c.ok() { - return os.EINVAL + return syscall.EINVAL } return setReadBuffer(c.fd, bytes) } @@ -134,7 +134,7 @@ func (c *IPConn) SetReadBuffer(bytes int) error { // transmit buffer associated with the connection. func (c *IPConn) SetWriteBuffer(bytes int) error { if !c.ok() { - return os.EINVAL + return syscall.EINVAL } return setWriteBuffer(c.fd, bytes) } @@ -150,7 +150,7 @@ func (c *IPConn) SetWriteBuffer(bytes int) error { // SetReadDeadline. func (c *IPConn) ReadFromIP(b []byte) (int, *IPAddr, error) { if !c.ok() { - return 0, nil, os.EINVAL + return 0, nil, syscall.EINVAL } // TODO(cw,rsc): consider using readv if we know the family // type to avoid the header trim/copy @@ -173,7 +173,7 @@ func (c *IPConn) ReadFromIP(b []byte) (int, *IPAddr, error) { // ReadFrom implements the PacketConn ReadFrom method. func (c *IPConn) ReadFrom(b []byte) (int, Addr, error) { if !c.ok() { - return 0, nil, os.EINVAL + return 0, nil, syscall.EINVAL } n, uaddr, err := c.ReadFromIP(b) return n, uaddr.toAddr(), err @@ -187,7 +187,7 @@ func (c *IPConn) ReadFrom(b []byte) (int, Addr, error) { // On packet-oriented connections, write timeouts are rare. func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (int, error) { if !c.ok() { - return 0, os.EINVAL + return 0, syscall.EINVAL } sa, err := addr.sockaddr(c.fd.family) if err != nil { @@ -199,11 +199,11 @@ func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (int, error) { // WriteTo implements the PacketConn WriteTo method. func (c *IPConn) WriteTo(b []byte, addr Addr) (int, error) { if !c.ok() { - return 0, os.EINVAL + return 0, syscall.EINVAL } a, ok := addr.(*IPAddr) if !ok { - return 0, &OpError{"write", c.fd.net, addr, os.EINVAL} + return 0, &OpError{"write", c.fd.net, addr, syscall.EINVAL} } return c.WriteToIP(b, a) } diff --git a/libgo/go/net/ipsock_plan9.go b/libgo/go/net/ipsock_plan9.go index 597b1277544..eab0bf3e899 100644 --- a/libgo/go/net/ipsock_plan9.go +++ b/libgo/go/net/ipsock_plan9.go @@ -10,6 +10,7 @@ import ( "errors" "io" "os" + "syscall" "time" ) @@ -83,7 +84,7 @@ func (c *plan9Conn) ok() bool { return c != nil && c.ctl != nil } // Read implements the Conn Read method. func (c *plan9Conn) Read(b []byte) (n int, err error) { if !c.ok() { - return 0, os.EINVAL + return 0, syscall.EINVAL } if c.data == nil { c.data, err = os.OpenFile(c.dir+"/data", os.O_RDWR, 0) @@ -102,7 +103,7 @@ func (c *plan9Conn) Read(b []byte) (n int, err error) { // Write implements the Conn Write method. func (c *plan9Conn) Write(b []byte) (n int, err error) { if !c.ok() { - return 0, os.EINVAL + return 0, syscall.EINVAL } if c.data == nil { c.data, err = os.OpenFile(c.dir+"/data", os.O_RDWR, 0) @@ -116,7 +117,7 @@ func (c *plan9Conn) Write(b []byte) (n int, err error) { // Close closes the connection. func (c *plan9Conn) Close() error { if !c.ok() { - return os.EINVAL + return syscall.EINVAL } err := c.ctl.Close() if err != nil { @@ -148,17 +149,17 @@ func (c *plan9Conn) RemoteAddr() Addr { // SetDeadline implements the Conn SetDeadline method. func (c *plan9Conn) SetDeadline(t time.Time) error { - return os.EPLAN9 + return syscall.EPLAN9 } // SetReadDeadline implements the Conn SetReadDeadline method. func (c *plan9Conn) SetReadDeadline(t time.Time) error { - return os.EPLAN9 + return syscall.EPLAN9 } // SetWriteDeadline implements the Conn SetWriteDeadline method. func (c *plan9Conn) SetWriteDeadline(t time.Time) error { - return os.EPLAN9 + return syscall.EPLAN9 } func startPlan9(net string, addr Addr) (ctl *os.File, dest, proto, name string, err error) { @@ -280,7 +281,7 @@ func (l *plan9Listener) Accept() (c Conn, err error) { func (l *plan9Listener) Close() error { if l == nil || l.ctl == nil { - return os.EINVAL + return syscall.EINVAL } return l.ctl.Close() } diff --git a/libgo/go/net/ipsock_posix.go b/libgo/go/net/ipsock_posix.go index 4da18a5061a..4841057d6be 100644 --- a/libgo/go/net/ipsock_posix.go +++ b/libgo/go/net/ipsock_posix.go @@ -105,21 +105,20 @@ type sockaddr interface { } func internetSocket(net string, laddr, raddr sockaddr, sotype, proto int, mode string, toAddr func(syscall.Sockaddr) Addr) (fd *netFD, err error) { - var oserr error var la, ra syscall.Sockaddr family := favoriteAddrFamily(net, laddr, raddr, mode) if laddr != nil { - if la, oserr = laddr.sockaddr(family); oserr != nil { + if la, err = laddr.sockaddr(family); err != nil { goto Error } } if raddr != nil { - if ra, oserr = raddr.sockaddr(family); oserr != nil { + if ra, err = raddr.sockaddr(family); err != nil { goto Error } } - fd, oserr = socket(net, family, sotype, proto, la, ra, toAddr) - if oserr != nil { + fd, err = socket(net, family, sotype, proto, la, ra, toAddr) + if err != nil { goto Error } return fd, nil @@ -129,7 +128,7 @@ Error: if mode == "listen" { addr = laddr } - return nil, &OpError{mode, net, addr, oserr} + return nil, &OpError{mode, net, addr, err} } func ipToSockaddr(family int, ip IP, port int) (syscall.Sockaddr, error) { diff --git a/libgo/go/net/lookup_plan9.go b/libgo/go/net/lookup_plan9.go index c0bb9225a7d..b08a9fb98e0 100644 --- a/libgo/go/net/lookup_plan9.go +++ b/libgo/go/net/lookup_plan9.go @@ -7,6 +7,7 @@ package net import ( "errors" "os" + "syscall" ) func query(filename, query string, bufSize int) (res []string, err error) { @@ -71,7 +72,7 @@ func queryDNS(addr string, typ string) (res []string, err error) { func lookupProtocol(name string) (proto int, err error) { // TODO: Implement this - return 0, os.EPLAN9 + return 0, syscall.EPLAN9 } func lookupHost(host string) (addrs []string, err error) { diff --git a/libgo/go/net/lookup_test.go b/libgo/go/net/lookup_test.go index 9a39ca8a1eb..7b9ea844cd4 100644 --- a/libgo/go/net/lookup_test.go +++ b/libgo/go/net/lookup_test.go @@ -8,14 +8,14 @@ package net import ( - "runtime" + "flag" "testing" ) -var avoidMacFirewall = runtime.GOOS == "darwin" +var testExternal = flag.Bool("external", false, "allow use of external networks during test") func TestGoogleSRV(t *testing.T) { - if testing.Short() || avoidMacFirewall { + if testing.Short() || !*testExternal { t.Logf("skipping test to avoid external network") return } @@ -38,7 +38,7 @@ func TestGoogleSRV(t *testing.T) { } func TestGmailMX(t *testing.T) { - if testing.Short() || avoidMacFirewall { + if testing.Short() || !*testExternal { t.Logf("skipping test to avoid external network") return } @@ -52,7 +52,7 @@ func TestGmailMX(t *testing.T) { } func TestGmailTXT(t *testing.T) { - if testing.Short() || avoidMacFirewall { + if testing.Short() || !*testExternal { t.Logf("skipping test to avoid external network") return } @@ -66,7 +66,7 @@ func TestGmailTXT(t *testing.T) { } func TestGoogleDNSAddr(t *testing.T) { - if testing.Short() || avoidMacFirewall { + if testing.Short() || !*testExternal { t.Logf("skipping test to avoid external network") return } diff --git a/libgo/go/net/multicast_test.go b/libgo/go/net/multicast_test.go index f62580de66e..1d760c21051 100644 --- a/libgo/go/net/multicast_test.go +++ b/libgo/go/net/multicast_test.go @@ -5,30 +5,46 @@ package net import ( + "errors" "os" "runtime" + "syscall" "testing" ) -var listenMulticastUDPTests = []struct { +var multicastListenerTests = []struct { net string gaddr *UDPAddr flags Flags - ipv6 bool + ipv6 bool // test with underlying AF_INET6 socket }{ // cf. RFC 4727: Experimental Values in IPv4, IPv6, ICMPv4, ICMPv6, UDP, and TCP Headers + {"udp", &UDPAddr{IPv4(224, 0, 0, 254), 12345}, FlagUp | FlagLoopback, false}, - {"udp4", &UDPAddr{IPv4(224, 0, 0, 254), 12345}, FlagUp | FlagLoopback, false}, + {"udp", &UDPAddr{IPv4(224, 0, 0, 254), 12345}, 0, false}, {"udp", &UDPAddr{ParseIP("ff0e::114"), 12345}, FlagUp | FlagLoopback, true}, + {"udp", &UDPAddr{ParseIP("ff0e::114"), 12345}, 0, true}, + + {"udp4", &UDPAddr{IPv4(224, 0, 0, 254), 12345}, FlagUp | FlagLoopback, false}, + {"udp4", &UDPAddr{IPv4(224, 0, 0, 254), 12345}, 0, false}, + {"udp6", &UDPAddr{ParseIP("ff01::114"), 12345}, FlagUp | FlagLoopback, true}, + {"udp6", &UDPAddr{ParseIP("ff01::114"), 12345}, 0, true}, {"udp6", &UDPAddr{ParseIP("ff02::114"), 12345}, FlagUp | FlagLoopback, true}, + {"udp6", &UDPAddr{ParseIP("ff02::114"), 12345}, 0, true}, {"udp6", &UDPAddr{ParseIP("ff04::114"), 12345}, FlagUp | FlagLoopback, true}, + {"udp6", &UDPAddr{ParseIP("ff04::114"), 12345}, 0, true}, {"udp6", &UDPAddr{ParseIP("ff05::114"), 12345}, FlagUp | FlagLoopback, true}, + {"udp6", &UDPAddr{ParseIP("ff05::114"), 12345}, 0, true}, {"udp6", &UDPAddr{ParseIP("ff08::114"), 12345}, FlagUp | FlagLoopback, true}, + {"udp6", &UDPAddr{ParseIP("ff08::114"), 12345}, 0, true}, {"udp6", &UDPAddr{ParseIP("ff0e::114"), 12345}, FlagUp | FlagLoopback, true}, + {"udp6", &UDPAddr{ParseIP("ff0e::114"), 12345}, 0, true}, } -func TestListenMulticastUDP(t *testing.T) { +// TestMulticastListener tests both single and double listen to a test +// listener with same address family, same group address and same port. +func TestMulticastListener(t *testing.T) { switch runtime.GOOS { case "netbsd", "openbsd", "plan9", "windows": return @@ -38,112 +54,142 @@ func TestListenMulticastUDP(t *testing.T) { } } - for _, tt := range listenMulticastUDPTests { + for _, tt := range multicastListenerTests { if tt.ipv6 && (!supportsIPv6 || os.Getuid() != 0) { continue } - ift, err := Interfaces() + ifi, err := availMulticastInterface(t, tt.flags) if err != nil { - t.Fatalf("Interfaces failed: %v", err) - } - var ifi *Interface - for _, x := range ift { - if x.Flags&tt.flags == tt.flags { - ifi = &x - break - } - } - if ifi == nil { - t.Logf("an appropriate multicast interface not found") - return + continue } - c, err := ListenMulticastUDP(tt.net, ifi, tt.gaddr) + c1, err := ListenMulticastUDP(tt.net, ifi, tt.gaddr) if err != nil { - t.Fatalf("ListenMulticastUDP failed: %v", err) + t.Fatalf("First ListenMulticastUDP failed: %v", err) } - defer c.Close() // test to listen concurrently across multiple listeners - if !tt.ipv6 { - testIPv4MulticastSocketOptions(t, c.fd, ifi) - } else { - testIPv6MulticastSocketOptions(t, c.fd, ifi) - } - ifmat, err := ifi.MulticastAddrs() + checkMulticastListener(t, err, c1, tt.gaddr) + c2, err := ListenMulticastUDP(tt.net, ifi, tt.gaddr) if err != nil { - t.Fatalf("MulticastAddrs failed: %v", err) - } - var found bool - for _, ifma := range ifmat { - if ifma.(*IPAddr).IP.Equal(tt.gaddr.IP) { - found = true - break - } + t.Fatalf("Second ListenMulticastUDP failed: %v", err) } - if !found { - t.Fatalf("%q not found in RIB", tt.gaddr.String()) + checkMulticastListener(t, err, c2, tt.gaddr) + c2.Close() + switch c1.fd.family { + case syscall.AF_INET: + testIPv4MulticastSocketOptions(t, c1.fd, ifi) + case syscall.AF_INET6: + testIPv6MulticastSocketOptions(t, c1.fd, ifi) } + c1.Close() } } -func TestSimpleListenMulticastUDP(t *testing.T) { +func TestSimpleMulticastListener(t *testing.T) { switch runtime.GOOS { case "plan9": return } - for _, tt := range listenMulticastUDPTests { + for _, tt := range multicastListenerTests { if tt.ipv6 { continue } - tt.flags = FlagUp | FlagMulticast + tt.flags = FlagUp | FlagMulticast // for windows testing + ifi, err := availMulticastInterface(t, tt.flags) + if err != nil { + continue + } + c1, err := ListenMulticastUDP(tt.net, ifi, tt.gaddr) + if err != nil { + t.Fatalf("First ListenMulticastUDP failed: %v", err) + } + checkSimpleMulticastListener(t, err, c1, tt.gaddr) + c2, err := ListenMulticastUDP(tt.net, ifi, tt.gaddr) + if err != nil { + t.Fatalf("Second ListenMulticastUDP failed: %v", err) + } + checkSimpleMulticastListener(t, err, c2, tt.gaddr) + c2.Close() + c1.Close() + } +} + +func checkMulticastListener(t *testing.T, err error, c *UDPConn, gaddr *UDPAddr) { + if !multicastRIBContains(t, gaddr.IP) { + t.Fatalf("%q not found in RIB", gaddr.String()) + } + if c.LocalAddr().String() != gaddr.String() { + t.Fatalf("LocalAddr returns %q, expected %q", c.LocalAddr().String(), gaddr.String()) + } +} + +func checkSimpleMulticastListener(t *testing.T, err error, c *UDPConn, gaddr *UDPAddr) { + if c.LocalAddr().String() != gaddr.String() { + t.Fatalf("LocalAddr returns %q, expected %q", c.LocalAddr().String(), gaddr.String()) + } +} + +func availMulticastInterface(t *testing.T, flags Flags) (*Interface, error) { + var ifi *Interface + if flags != Flags(0) { ift, err := Interfaces() if err != nil { t.Fatalf("Interfaces failed: %v", err) } - var ifi *Interface for _, x := range ift { - if x.Flags&tt.flags == tt.flags { + if x.Flags&flags == flags { ifi = &x break } } if ifi == nil { - t.Logf("an appropriate multicast interface not found") - return + return nil, errors.New("an appropriate multicast interface not found") } - c, err := ListenMulticastUDP(tt.net, ifi, tt.gaddr) + } + return ifi, nil +} + +func multicastRIBContains(t *testing.T, ip IP) bool { + ift, err := Interfaces() + if err != nil { + t.Fatalf("Interfaces failed: %v", err) + } + for _, ifi := range ift { + ifmat, err := ifi.MulticastAddrs() if err != nil { - t.Fatalf("ListenMulticastUDP failed: %v", err) + t.Fatalf("MulticastAddrs failed: %v", err) + } + for _, ifma := range ifmat { + if ifma.(*IPAddr).IP.Equal(ip) { + return true + } } - c.Close() } + return false } func testIPv4MulticastSocketOptions(t *testing.T, fd *netFD, ifi *Interface) { - ifmc, err := ipv4MulticastInterface(fd) + _, err := ipv4MulticastInterface(fd) if err != nil { t.Fatalf("ipv4MulticastInterface failed: %v", err) } - t.Logf("IPv4 multicast interface: %v", ifmc) - err = setIPv4MulticastInterface(fd, ifi) - if err != nil { - t.Fatalf("setIPv4MulticastInterface failed: %v", err) + if ifi != nil { + err = setIPv4MulticastInterface(fd, ifi) + if err != nil { + t.Fatalf("setIPv4MulticastInterface failed: %v", err) + } } - - ttl, err := ipv4MulticastTTL(fd) + _, err = ipv4MulticastTTL(fd) if err != nil { t.Fatalf("ipv4MulticastTTL failed: %v", err) } - t.Logf("IPv4 multicast TTL: %v", ttl) err = setIPv4MulticastTTL(fd, 1) if err != nil { t.Fatalf("setIPv4MulticastTTL failed: %v", err) } - - loop, err := ipv4MulticastLoopback(fd) + _, err = ipv4MulticastLoopback(fd) if err != nil { t.Fatalf("ipv4MulticastLoopback failed: %v", err) } - t.Logf("IPv4 multicast loopback: %v", loop) err = setIPv4MulticastLoopback(fd, false) if err != nil { t.Fatalf("setIPv4MulticastLoopback failed: %v", err) @@ -151,31 +197,28 @@ func testIPv4MulticastSocketOptions(t *testing.T, fd *netFD, ifi *Interface) { } func testIPv6MulticastSocketOptions(t *testing.T, fd *netFD, ifi *Interface) { - ifmc, err := ipv6MulticastInterface(fd) + _, err := ipv6MulticastInterface(fd) if err != nil { t.Fatalf("ipv6MulticastInterface failed: %v", err) } - t.Logf("IPv6 multicast interface: %v", ifmc) - err = setIPv6MulticastInterface(fd, ifi) - if err != nil { - t.Fatalf("setIPv6MulticastInterface failed: %v", err) + if ifi != nil { + err = setIPv6MulticastInterface(fd, ifi) + if err != nil { + t.Fatalf("setIPv6MulticastInterface failed: %v", err) + } } - - hoplim, err := ipv6MulticastHopLimit(fd) + _, err = ipv6MulticastHopLimit(fd) if err != nil { t.Fatalf("ipv6MulticastHopLimit failed: %v", err) } - t.Logf("IPv6 multicast hop limit: %v", hoplim) err = setIPv6MulticastHopLimit(fd, 1) if err != nil { t.Fatalf("setIPv6MulticastHopLimit failed: %v", err) } - - loop, err := ipv6MulticastLoopback(fd) + _, err = ipv6MulticastLoopback(fd) if err != nil { t.Fatalf("ipv6MulticastLoopback failed: %v", err) } - t.Logf("IPv6 multicast loopback: %v", loop) err = setIPv6MulticastLoopback(fd, false) if err != nil { t.Fatalf("setIPv6MulticastLoopback failed: %v", err) diff --git a/libgo/go/net/net.go b/libgo/go/net/net.go index 79d36a2a813..bf242ff8dd6 100644 --- a/libgo/go/net/net.go +++ b/libgo/go/net/net.go @@ -2,8 +2,41 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Package net provides a portable interface to Unix networks sockets, -// including TCP/IP, UDP, domain name resolution, and Unix domain sockets. +/* +Package net provides a portable interface for network I/O, including +TCP/IP, UDP, domain name resolution, and Unix domain sockets. + +Although the package provides access to low-level networking +primitives, most clients will need only the basic interface provided +by the Dial, Listen, and Accept functions and the associated +Conn and Listener interfaces. The crypto/tls package uses +the same interfaces and similar Dial and Listen functions. + +The Dial function connects to a server: + + conn, err := net.Dial("tcp", "google.com:80") + if err != nil { + // handle error + } + fmt.Fprintf(conn, "GET / HTTP/1.0\r\n\r\n") + status, err := bufio.NewReader(conn).ReadString('\n') + // ... + +The Listen function creates servers: + + ln, err := net.Listen("tcp", ":8080") + if err != nil { + // handle error + } + for { + conn, err := ln.Accept() + if err != nil { + // handle error + continue + } + go handleConnection(conn) + } +*/ package net // TODO(rsc): @@ -42,21 +75,28 @@ type Conn interface { RemoteAddr() Addr // SetDeadline sets the read and write deadlines associated - // with the connection. + // with the connection. It is equivalent to calling both + // SetReadDeadline and SetWriteDeadline. + // + // A deadline is an absolute time after which I/O operations + // fail with a timeout (see type Error) instead of + // blocking. The deadline applies to all future I/O, not just + // the immediately following call to Read or Write. + // + // An idle timeout can be implemented by repeatedly extending + // the deadline after successful Read or Write calls. + // + // A zero value for t means I/O operations will not time out. SetDeadline(t time.Time) error - // SetReadDeadline sets the deadline for all Read calls to return. - // If the deadline is reached, Read will fail with a timeout - // (see type Error) instead of blocking. + // SetReadDeadline sets the deadline for Read calls. // A zero value for t means Read will not time out. SetReadDeadline(t time.Time) error - // SetWriteDeadline sets the deadline for all Write calls to return. - // If the deadline is reached, Write will fail with a timeout - // (see type Error) instead of blocking. - // A zero value for t means Write will not time out. + // SetWriteDeadline sets the deadline for Write calls. // Even if write times out, it may return n > 0, indicating that // some of the data was successfully written. + // A zero value for t means Write will not time out. SetWriteDeadline(t time.Time) error } diff --git a/libgo/go/net/parse.go b/libgo/go/net/parse.go index 4c4200a49b7..7c87b42f6d9 100644 --- a/libgo/go/net/parse.go +++ b/libgo/go/net/parse.go @@ -67,7 +67,7 @@ func open(name string) (*file, error) { if err != nil { return nil, err } - return &file{fd, make([]byte, 1024)[0:0], false}, nil + return &file{fd, make([]byte, os.Getpagesize())[0:0], false}, nil } func byteIndex(s string, c byte) int { diff --git a/libgo/go/net/rpc/server_test.go b/libgo/go/net/rpc/server_test.go index 8cfa033ccc3..62c7b1e6004 100644 --- a/libgo/go/net/rpc/server_test.go +++ b/libgo/go/net/rpc/server_test.go @@ -387,12 +387,12 @@ func (WriteFailCodec) WriteRequest(*Request, interface{}) error { } func (WriteFailCodec) ReadResponseHeader(*Response) error { - time.Sleep(120 * time.Second) + select {} panic("unreachable") } func (WriteFailCodec) ReadResponseBody(interface{}) error { - time.Sleep(120 * time.Second) + select {} panic("unreachable") } diff --git a/libgo/go/net/server_test.go b/libgo/go/net/server_test.go index 55691493aa9..b9862168153 100644 --- a/libgo/go/net/server_test.go +++ b/libgo/go/net/server_test.go @@ -95,7 +95,7 @@ func doTest(t *testing.T, network, listenaddr, dialaddr string) { t.Logf("Test %q %q %q", network, listenaddr, dialaddr) switch listenaddr { case "", "0.0.0.0", "[::]", "[::ffff:0.0.0.0]": - if testing.Short() || avoidMacFirewall { + if testing.Short() || !*testExternal { t.Logf("skip wildcard listen during short test") return } diff --git a/libgo/go/net/smtp/smtp.go b/libgo/go/net/smtp/smtp.go index f600cc86482..59f6449f0ab 100644 --- a/libgo/go/net/smtp/smtp.go +++ b/libgo/go/net/smtp/smtp.go @@ -50,15 +50,14 @@ func Dial(addr string) (*Client, error) { // server name to be used when authenticating. func NewClient(conn net.Conn, host string) (*Client, error) { text := textproto.NewConn(conn) - _, msg, err := text.ReadResponse(220) + _, _, err := text.ReadResponse(220) if err != nil { text.Close() return nil, err } c := &Client{Text: text, conn: conn, serverName: host} - if strings.Contains(msg, "ESMTP") { - err = c.ehlo() - } else { + err = c.ehlo() + if err != nil { err = c.helo() } return c, err diff --git a/libgo/go/net/smtp/smtp_test.go b/libgo/go/net/smtp/smtp_test.go index ce887820531..c315d185c9d 100644 --- a/libgo/go/net/smtp/smtp_test.go +++ b/libgo/go/net/smtp/smtp_test.go @@ -8,9 +8,11 @@ import ( "bufio" "bytes" "io" + "net" "net/textproto" "strings" "testing" + "time" ) type authTest struct { @@ -59,9 +61,12 @@ type faker struct { io.ReadWriter } -func (f faker) Close() error { - return nil -} +func (f faker) Close() error { return nil } +func (f faker) LocalAddr() net.Addr { return nil } +func (f faker) RemoteAddr() net.Addr { return nil } +func (f faker) SetDeadline(time.Time) error { return nil } +func (f faker) SetReadDeadline(time.Time) error { return nil } +func (f faker) SetWriteDeadline(time.Time) error { return nil } func TestBasic(t *testing.T) { basicServer = strings.Join(strings.Split(basicServer, "\n"), "\r\n") @@ -180,3 +185,87 @@ Goodbye. . QUIT ` + +func TestNewClient(t *testing.T) { + newClientServer = strings.Join(strings.Split(newClientServer, "\n"), "\r\n") + newClientClient = strings.Join(strings.Split(newClientClient, "\n"), "\r\n") + + var cmdbuf bytes.Buffer + bcmdbuf := bufio.NewWriter(&cmdbuf) + out := func() string { + bcmdbuf.Flush() + return cmdbuf.String() + } + var fake faker + fake.ReadWriter = bufio.NewReadWriter(bufio.NewReader(strings.NewReader(newClientServer)), bcmdbuf) + c, err := NewClient(fake, "fake.host") + if err != nil { + t.Fatalf("NewClient: %v\n(after %v)", err, out()) + } + if ok, args := c.Extension("aUtH"); !ok || args != "LOGIN PLAIN" { + t.Fatalf("Expected AUTH supported") + } + if ok, _ := c.Extension("DSN"); ok { + t.Fatalf("Shouldn't support DSN") + } + if err := c.Quit(); err != nil { + t.Fatalf("QUIT failed: %s", err) + } + + actualcmds := out() + if newClientClient != actualcmds { + t.Fatalf("Got:\n%s\nExpected:\n%s", actualcmds, newClientClient) + } +} + +var newClientServer = `220 hello world +250-mx.google.com at your service +250-SIZE 35651584 +250-AUTH LOGIN PLAIN +250 8BITMIME +221 OK +` + +var newClientClient = `EHLO localhost +QUIT +` + +func TestNewClient2(t *testing.T) { + newClient2Server = strings.Join(strings.Split(newClient2Server, "\n"), "\r\n") + newClient2Client = strings.Join(strings.Split(newClient2Client, "\n"), "\r\n") + + var cmdbuf bytes.Buffer + bcmdbuf := bufio.NewWriter(&cmdbuf) + var fake faker + fake.ReadWriter = bufio.NewReadWriter(bufio.NewReader(strings.NewReader(newClient2Server)), bcmdbuf) + c, err := NewClient(fake, "fake.host") + if err != nil { + t.Fatalf("NewClient: %v", err) + } + if ok, _ := c.Extension("DSN"); ok { + t.Fatalf("Shouldn't support DSN") + } + if err := c.Quit(); err != nil { + t.Fatalf("QUIT failed: %s", err) + } + + bcmdbuf.Flush() + actualcmds := cmdbuf.String() + if newClient2Client != actualcmds { + t.Fatalf("Got:\n%s\nExpected:\n%s", actualcmds, newClient2Client) + } +} + +var newClient2Server = `220 hello world +502 EH? +250-mx.google.com at your service +250-SIZE 35651584 +250-AUTH LOGIN PLAIN +250 8BITMIME +221 OK +` + +var newClient2Client = `EHLO localhost +HELO localhost +QUIT +` diff --git a/libgo/go/net/sock.go b/libgo/go/net/sock.go index 70064c307ef..dc139f04a25 100644 --- a/libgo/go/net/sock.go +++ b/libgo/go/net/sock.go @@ -33,13 +33,14 @@ func socket(net string, f, t, p int, la, ra syscall.Sockaddr, toAddr func(syscal return nil, err } + var bla syscall.Sockaddr if la != nil { - la, err = listenerSockaddr(s, f, la, toAddr) + bla, err = listenerSockaddr(s, f, la, toAddr) if err != nil { closesocket(s) return nil, err } - err = syscall.Bind(s, la) + err = syscall.Bind(s, bla) if err != nil { closesocket(s) return nil, err @@ -61,7 +62,12 @@ func socket(net string, f, t, p int, la, ra syscall.Sockaddr, toAddr func(syscal } sa, _ := syscall.Getsockname(s) - laddr := toAddr(sa) + var laddr Addr + if la != nil && bla != la { + laddr = toAddr(la) + } else { + laddr = toAddr(sa) + } sa, _ = syscall.Getpeername(s) raddr := toAddr(sa) diff --git a/libgo/go/net/tcpsock_plan9.go b/libgo/go/net/tcpsock_plan9.go index 128766144dd..35f56966eae 100644 --- a/libgo/go/net/tcpsock_plan9.go +++ b/libgo/go/net/tcpsock_plan9.go @@ -7,7 +7,7 @@ package net import ( - "os" + "syscall" "time" ) @@ -19,35 +19,35 @@ type TCPConn struct { // SetDeadline implements the Conn SetDeadline method. func (c *TCPConn) SetDeadline(t time.Time) error { - return os.EPLAN9 + return syscall.EPLAN9 } // SetReadDeadline implements the Conn SetReadDeadline method. func (c *TCPConn) SetReadDeadline(t time.Time) error { - return os.EPLAN9 + return syscall.EPLAN9 } // SetWriteDeadline implements the Conn SetWriteDeadline method. func (c *TCPConn) SetWriteDeadline(t time.Time) error { - return os.EPLAN9 + return syscall.EPLAN9 } // CloseRead shuts down the reading side of the TCP connection. // Most callers should just use Close. func (c *TCPConn) CloseRead() error { if !c.ok() { - return os.EINVAL + return syscall.EINVAL } - return os.EPLAN9 + return syscall.EPLAN9 } // CloseWrite shuts down the writing side of the TCP connection. // Most callers should just use Close. func (c *TCPConn) CloseWrite() error { if !c.ok() { - return os.EINVAL + return syscall.EINVAL } - return os.EPLAN9 + return syscall.EPLAN9 } // DialTCP connects to the remote address raddr on the network net, diff --git a/libgo/go/net/tcpsock_posix.go b/libgo/go/net/tcpsock_posix.go index 200ce91566c..e05bc10170e 100644 --- a/libgo/go/net/tcpsock_posix.go +++ b/libgo/go/net/tcpsock_posix.go @@ -9,6 +9,7 @@ package net import ( + "fmt" "io" "os" "syscall" @@ -26,6 +27,11 @@ func sockaddrToTCP(sa syscall.Sockaddr) Addr { return &TCPAddr{sa.Addr[0:], sa.Port} case *syscall.SockaddrInet6: return &TCPAddr{sa.Addr[0:], sa.Port} + default: + if sa != nil { + // Diagnose when we will turn a non-nil sockaddr into a nil. + panic(fmt.Sprintf("unexpected type in sockaddrToTCP: %T", sa)) + } } return nil } @@ -70,7 +76,7 @@ func (c *TCPConn) ok() bool { return c != nil && c.fd != nil } // Read implements the Conn Read method. func (c *TCPConn) Read(b []byte) (n int, err error) { if !c.ok() { - return 0, os.EINVAL + return 0, syscall.EINVAL } return c.fd.Read(b) } @@ -86,7 +92,7 @@ func (c *TCPConn) ReadFrom(r io.Reader) (int64, error) { // Write implements the Conn Write method. func (c *TCPConn) Write(b []byte) (n int, err error) { if !c.ok() { - return 0, os.EINVAL + return 0, syscall.EINVAL } return c.fd.Write(b) } @@ -94,7 +100,7 @@ func (c *TCPConn) Write(b []byte) (n int, err error) { // Close closes the TCP connection. func (c *TCPConn) Close() error { if !c.ok() { - return os.EINVAL + return syscall.EINVAL } err := c.fd.Close() c.fd = nil @@ -105,7 +111,7 @@ func (c *TCPConn) Close() error { // Most callers should just use Close. func (c *TCPConn) CloseRead() error { if !c.ok() { - return os.EINVAL + return syscall.EINVAL } return c.fd.CloseRead() } @@ -114,7 +120,7 @@ func (c *TCPConn) CloseRead() error { // Most callers should just use Close. func (c *TCPConn) CloseWrite() error { if !c.ok() { - return os.EINVAL + return syscall.EINVAL } return c.fd.CloseWrite() } @@ -138,7 +144,7 @@ func (c *TCPConn) RemoteAddr() Addr { // SetDeadline implements the Conn SetDeadline method. func (c *TCPConn) SetDeadline(t time.Time) error { if !c.ok() { - return os.EINVAL + return syscall.EINVAL } return setDeadline(c.fd, t) } @@ -146,7 +152,7 @@ func (c *TCPConn) SetDeadline(t time.Time) error { // SetReadDeadline implements the Conn SetReadDeadline method. func (c *TCPConn) SetReadDeadline(t time.Time) error { if !c.ok() { - return os.EINVAL + return syscall.EINVAL } return setReadDeadline(c.fd, t) } @@ -154,7 +160,7 @@ func (c *TCPConn) SetReadDeadline(t time.Time) error { // SetWriteDeadline implements the Conn SetWriteDeadline method. func (c *TCPConn) SetWriteDeadline(t time.Time) error { if !c.ok() { - return os.EINVAL + return syscall.EINVAL } return setWriteDeadline(c.fd, t) } @@ -163,7 +169,7 @@ func (c *TCPConn) SetWriteDeadline(t time.Time) error { // receive buffer associated with the connection. func (c *TCPConn) SetReadBuffer(bytes int) error { if !c.ok() { - return os.EINVAL + return syscall.EINVAL } return setReadBuffer(c.fd, bytes) } @@ -172,7 +178,7 @@ func (c *TCPConn) SetReadBuffer(bytes int) error { // transmit buffer associated with the connection. func (c *TCPConn) SetWriteBuffer(bytes int) error { if !c.ok() { - return os.EINVAL + return syscall.EINVAL } return setWriteBuffer(c.fd, bytes) } @@ -190,7 +196,7 @@ func (c *TCPConn) SetWriteBuffer(bytes int) error { // data to be sent and acknowledged. func (c *TCPConn) SetLinger(sec int) error { if !c.ok() { - return os.EINVAL + return syscall.EINVAL } return setLinger(c.fd, sec) } @@ -199,7 +205,7 @@ func (c *TCPConn) SetLinger(sec int) error { // keepalive messages on the connection. func (c *TCPConn) SetKeepAlive(keepalive bool) error { if !c.ok() { - return os.EINVAL + return syscall.EINVAL } return setKeepAlive(c.fd, keepalive) } @@ -210,7 +216,7 @@ func (c *TCPConn) SetKeepAlive(keepalive bool) error { // that data is sent as soon as possible after a Write. func (c *TCPConn) SetNoDelay(noDelay bool) error { if !c.ok() { - return os.EINVAL + return syscall.EINVAL } return setNoDelay(c.fd, noDelay) } @@ -259,6 +265,17 @@ func DialTCP(net string, laddr, raddr *TCPAddr) (*TCPConn, error) { } func selfConnect(fd *netFD) bool { + // The socket constructor can return an fd with raddr nil under certain + // unknown conditions. The errors in the calls there to Getpeername + // are discarded, but we can't catch the problem there because those + // calls are sometimes legally erroneous with a "socket not connected". + // Since this code (selfConnect) is already trying to work around + // a problem, we make sure if this happens we recognize trouble and + // ask the DialTCP routine to try again. + // TODO: try to understand what's really going on. + if fd.laddr == nil || fd.raddr == nil { + return true + } l := fd.laddr.(*TCPAddr) r := fd.raddr.(*TCPAddr) return l.Port == r.Port && l.IP.Equal(r.IP) @@ -294,7 +311,7 @@ func ListenTCP(net string, laddr *TCPAddr) (*TCPListener, error) { // and the remote address. func (l *TCPListener) AcceptTCP() (c *TCPConn, err error) { if l == nil || l.fd == nil || l.fd.sysfd < 0 { - return nil, os.EINVAL + return nil, syscall.EINVAL } fd, err := l.fd.accept(sockaddrToTCP) if err != nil { @@ -317,7 +334,7 @@ func (l *TCPListener) Accept() (c Conn, err error) { // Already Accepted connections are not closed. func (l *TCPListener) Close() error { if l == nil || l.fd == nil { - return os.EINVAL + return syscall.EINVAL } return l.fd.Close() } @@ -329,7 +346,7 @@ func (l *TCPListener) Addr() Addr { return l.fd.laddr } // A zero time value disables the deadline. func (l *TCPListener) SetDeadline(t time.Time) error { if l == nil || l.fd == nil { - return os.EINVAL + return syscall.EINVAL } return setDeadline(l.fd, t) } diff --git a/libgo/go/net/testdata/hosts b/libgo/go/net/testdata/hosts new file mode 100644 index 00000000000..b601763898b --- /dev/null +++ b/libgo/go/net/testdata/hosts @@ -0,0 +1,12 @@ +255.255.255.255 broadcasthost +127.0.0.2 odin +127.0.0.3 odin # inline comment +::2 odin +127.1.1.1 thor +# aliases +127.1.1.2 ullr ullrhost +# Bogus entries that must be ignored. +123.123.123 loki +321.321.321.321 +# TODO(yvesj): Should we be able to parse this? From a Darwin system. +fe80::1%lo0 localhost diff --git a/libgo/go/net/testdata/igmp b/libgo/go/net/testdata/igmp new file mode 100644 index 00000000000..5f380a2c7db --- /dev/null +++ b/libgo/go/net/testdata/igmp @@ -0,0 +1,24 @@ +Idx Device : Count Querier Group Users Timer Reporter +1 lo : 1 V3 + 010000E0 1 0:00000000 0 +2 eth0 : 2 V2 + FB0000E0 1 0:00000000 1 + 010000E0 1 0:00000000 0 +3 eth1 : 1 V3 + 010000E0 1 0:00000000 0 +4 eth2 : 1 V3 + 010000E0 1 0:00000000 0 +5 eth0.100 : 2 V3 + FB0000E0 1 0:00000000 0 + 010000E0 1 0:00000000 0 +6 eth0.101 : 2 V3 + FB0000E0 1 0:00000000 0 + 010000E0 1 0:00000000 0 +7 eth0.102 : 2 V3 + FB0000E0 1 0:00000000 0 + 010000E0 1 0:00000000 0 +8 eth0.103 : 2 V3 + FB0000E0 1 0:00000000 0 + 010000E0 1 0:00000000 0 +9 device1tap2: 1 V3 + 010000E0 1 0:00000000 0 diff --git a/libgo/go/net/testdata/igmp6 b/libgo/go/net/testdata/igmp6 new file mode 100644 index 00000000000..6cd5a2d4d9d --- /dev/null +++ b/libgo/go/net/testdata/igmp6 @@ -0,0 +1,18 @@ +1 lo ff020000000000000000000000000001 1 0000000C 0 +2 eth0 ff0200000000000000000001ffac891e 1 00000006 0 +2 eth0 ff020000000000000000000000000001 1 0000000C 0 +3 eth1 ff0200000000000000000001ffac8928 2 00000006 0 +3 eth1 ff020000000000000000000000000001 1 0000000C 0 +4 eth2 ff0200000000000000000001ffac8932 2 00000006 0 +4 eth2 ff020000000000000000000000000001 1 0000000C 0 +5 eth0.100 ff0200000000000000000001ffac891e 1 00000004 0 +5 eth0.100 ff020000000000000000000000000001 1 0000000C 0 +6 pan0 ff020000000000000000000000000001 1 0000000C 0 +7 eth0.101 ff0200000000000000000001ffac891e 1 00000004 0 +7 eth0.101 ff020000000000000000000000000001 1 0000000C 0 +8 eth0.102 ff0200000000000000000001ffac891e 1 00000004 0 +8 eth0.102 ff020000000000000000000000000001 1 0000000C 0 +9 eth0.103 ff0200000000000000000001ffac891e 1 00000004 0 +9 eth0.103 ff020000000000000000000000000001 1 0000000C 0 +10 device1tap2 ff0200000000000000000001ff4cc3a3 1 00000004 0 +10 device1tap2 ff020000000000000000000000000001 1 0000000C 0 diff --git a/libgo/go/net/textproto/reader.go b/libgo/go/net/textproto/reader.go index 862cd536c46..125feb3e885 100644 --- a/libgo/go/net/textproto/reader.go +++ b/libgo/go/net/textproto/reader.go @@ -454,10 +454,14 @@ func (r *Reader) ReadMIMEHeader() (MIMEHeader, error) { // Key ends at first colon; must not have spaces. i := bytes.IndexByte(kv, ':') - if i < 0 || bytes.IndexByte(kv[0:i], ' ') >= 0 { + if i < 0 { return m, ProtocolError("malformed MIME header line: " + string(kv)) } - key := CanonicalMIMEHeaderKey(string(kv[0:i])) + key := string(kv[0:i]) + if strings.Index(key, " ") >= 0 { + key = strings.TrimRight(key, " ") + } + key = CanonicalMIMEHeaderKey(key) // Skip initial spaces in value. i++ // skip colon @@ -503,6 +507,11 @@ MustRewrite: a := []byte(s) upper := true for i, v := range a { + if v == ' ' { + a[i] = '-' + upper = true + continue + } if upper && 'a' <= v && v <= 'z' { a[i] = v + 'A' - 'a' } diff --git a/libgo/go/net/textproto/reader_test.go b/libgo/go/net/textproto/reader_test.go index 4d036914801..7c5d16227ff 100644 --- a/libgo/go/net/textproto/reader_test.go +++ b/libgo/go/net/textproto/reader_test.go @@ -164,6 +164,29 @@ func TestLargeReadMIMEHeader(t *testing.T) { } } +// Test that we read slightly-bogus MIME headers seen in the wild, +// with spaces before colons, and spaces in keys. +func TestReadMIMEHeaderNonCompliant(t *testing.T) { + // Invalid HTTP response header as sent by an Axis security + // camera: (this is handled by IE, Firefox, Chrome, curl, etc.) + r := reader("Foo: bar\r\n" + + "Content-Language: en\r\n" + + "SID : 0\r\n" + + "Audio Mode : None\r\n" + + "Privilege : 127\r\n\r\n") + m, err := r.ReadMIMEHeader() + want := MIMEHeader{ + "Foo": {"bar"}, + "Content-Language": {"en"}, + "Sid": {"0"}, + "Audio-Mode": {"None"}, + "Privilege": {"127"}, + } + if !reflect.DeepEqual(m, want) || err != nil { + t.Fatalf("ReadMIMEHeader =\n%v, %v; want:\n%v", m, err, want) + } +} + type readResponseTest struct { in string inCode int diff --git a/libgo/go/net/textproto/textproto.go b/libgo/go/net/textproto/textproto.go index 317ec72b0cc..ad5840cf7da 100644 --- a/libgo/go/net/textproto/textproto.go +++ b/libgo/go/net/textproto/textproto.go @@ -20,6 +20,9 @@ // // Writer, to write dot-encoded text blocks. // +// Conn, a convenient packaging of Reader, Writer, and Pipeline for use +// with a single network connection. +// package textproto import ( diff --git a/libgo/go/net/udpsock_plan9.go b/libgo/go/net/udpsock_plan9.go index f90a5fe9ab8..4f298a42f87 100644 --- a/libgo/go/net/udpsock_plan9.go +++ b/libgo/go/net/udpsock_plan9.go @@ -9,6 +9,7 @@ package net import ( "errors" "os" + "syscall" "time" ) @@ -20,17 +21,17 @@ type UDPConn struct { // SetDeadline implements the Conn SetDeadline method. func (c *UDPConn) SetDeadline(t time.Time) error { - return os.EPLAN9 + return syscall.EPLAN9 } // SetReadDeadline implements the Conn SetReadDeadline method. func (c *UDPConn) SetReadDeadline(t time.Time) error { - return os.EPLAN9 + return syscall.EPLAN9 } // SetWriteDeadline implements the Conn SetWriteDeadline method. func (c *UDPConn) SetWriteDeadline(t time.Time) error { - return os.EPLAN9 + return syscall.EPLAN9 } // UDP-specific methods. @@ -43,7 +44,7 @@ func (c *UDPConn) SetWriteDeadline(t time.Time) error { // after a fixed time limit; see SetDeadline and SetReadDeadline. func (c *UDPConn) ReadFromUDP(b []byte) (n int, addr *UDPAddr, err error) { if !c.ok() { - return 0, nil, os.EINVAL + return 0, nil, syscall.EINVAL } if c.data == nil { c.data, err = os.OpenFile(c.dir+"/data", os.O_RDWR, 0) @@ -69,7 +70,7 @@ func (c *UDPConn) ReadFromUDP(b []byte) (n int, addr *UDPAddr, err error) { // ReadFrom implements the PacketConn ReadFrom method. func (c *UDPConn) ReadFrom(b []byte) (n int, addr Addr, err error) { if !c.ok() { - return 0, nil, os.EINVAL + return 0, nil, syscall.EINVAL } return c.ReadFromUDP(b) } @@ -82,7 +83,7 @@ func (c *UDPConn) ReadFrom(b []byte) (n int, addr Addr, err error) { // On packet-oriented connections, write timeouts are rare. func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (n int, err error) { if !c.ok() { - return 0, os.EINVAL + return 0, syscall.EINVAL } if c.data == nil { c.data, err = os.OpenFile(c.dir+"/data", os.O_RDWR, 0) @@ -106,11 +107,11 @@ func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (n int, err error) { // WriteTo implements the PacketConn WriteTo method. func (c *UDPConn) WriteTo(b []byte, addr Addr) (n int, err error) { if !c.ok() { - return 0, os.EINVAL + return 0, syscall.EINVAL } a, ok := addr.(*UDPAddr) if !ok { - return 0, &OpError{"write", c.dir, addr, os.EINVAL} + return 0, &OpError{"write", c.dir, addr, syscall.EINVAL} } return c.WriteToUDP(b, a) } @@ -191,5 +192,5 @@ func ListenUDP(net string, laddr *UDPAddr) (c *UDPConn, err error) { // the interface to join. ListenMulticastUDP uses default // multicast interface if ifi is nil. func ListenMulticastUDP(net string, ifi *Interface, gaddr *UDPAddr) (*UDPConn, error) { - return nil, os.EPLAN9 + return nil, syscall.EPLAN9 } diff --git a/libgo/go/net/udpsock_posix.go b/libgo/go/net/udpsock_posix.go index 6108373568a..1f99dc53867 100644 --- a/libgo/go/net/udpsock_posix.go +++ b/libgo/go/net/udpsock_posix.go @@ -63,7 +63,7 @@ func (c *UDPConn) ok() bool { return c != nil && c.fd != nil } // Read implements the Conn Read method. func (c *UDPConn) Read(b []byte) (int, error) { if !c.ok() { - return 0, os.EINVAL + return 0, syscall.EINVAL } return c.fd.Read(b) } @@ -71,7 +71,7 @@ func (c *UDPConn) Read(b []byte) (int, error) { // Write implements the Conn Write method. func (c *UDPConn) Write(b []byte) (int, error) { if !c.ok() { - return 0, os.EINVAL + return 0, syscall.EINVAL } return c.fd.Write(b) } @@ -79,7 +79,7 @@ func (c *UDPConn) Write(b []byte) (int, error) { // Close closes the UDP connection. func (c *UDPConn) Close() error { if !c.ok() { - return os.EINVAL + return syscall.EINVAL } err := c.fd.Close() c.fd = nil @@ -105,7 +105,7 @@ func (c *UDPConn) RemoteAddr() Addr { // SetDeadline implements the Conn SetDeadline method. func (c *UDPConn) SetDeadline(t time.Time) error { if !c.ok() { - return os.EINVAL + return syscall.EINVAL } return setDeadline(c.fd, t) } @@ -113,7 +113,7 @@ func (c *UDPConn) SetDeadline(t time.Time) error { // SetReadDeadline implements the Conn SetReadDeadline method. func (c *UDPConn) SetReadDeadline(t time.Time) error { if !c.ok() { - return os.EINVAL + return syscall.EINVAL } return setReadDeadline(c.fd, t) } @@ -121,7 +121,7 @@ func (c *UDPConn) SetReadDeadline(t time.Time) error { // SetWriteDeadline implements the Conn SetWriteDeadline method. func (c *UDPConn) SetWriteDeadline(t time.Time) error { if !c.ok() { - return os.EINVAL + return syscall.EINVAL } return setWriteDeadline(c.fd, t) } @@ -130,7 +130,7 @@ func (c *UDPConn) SetWriteDeadline(t time.Time) error { // receive buffer associated with the connection. func (c *UDPConn) SetReadBuffer(bytes int) error { if !c.ok() { - return os.EINVAL + return syscall.EINVAL } return setReadBuffer(c.fd, bytes) } @@ -139,7 +139,7 @@ func (c *UDPConn) SetReadBuffer(bytes int) error { // transmit buffer associated with the connection. func (c *UDPConn) SetWriteBuffer(bytes int) error { if !c.ok() { - return os.EINVAL + return syscall.EINVAL } return setWriteBuffer(c.fd, bytes) } @@ -154,7 +154,7 @@ func (c *UDPConn) SetWriteBuffer(bytes int) error { // after a fixed time limit; see SetDeadline and SetReadDeadline. func (c *UDPConn) ReadFromUDP(b []byte) (n int, addr *UDPAddr, err error) { if !c.ok() { - return 0, nil, os.EINVAL + return 0, nil, syscall.EINVAL } n, sa, err := c.fd.ReadFrom(b) switch sa := sa.(type) { @@ -169,7 +169,7 @@ func (c *UDPConn) ReadFromUDP(b []byte) (n int, addr *UDPAddr, err error) { // ReadFrom implements the PacketConn ReadFrom method. func (c *UDPConn) ReadFrom(b []byte) (int, Addr, error) { if !c.ok() { - return 0, nil, os.EINVAL + return 0, nil, syscall.EINVAL } n, uaddr, err := c.ReadFromUDP(b) return n, uaddr.toAddr(), err @@ -183,7 +183,7 @@ func (c *UDPConn) ReadFrom(b []byte) (int, Addr, error) { // On packet-oriented connections, write timeouts are rare. func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (int, error) { if !c.ok() { - return 0, os.EINVAL + return 0, syscall.EINVAL } if c.fd.isConnected { return 0, &OpError{"write", c.fd.net, addr, ErrWriteToConnected} @@ -198,11 +198,11 @@ func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (int, error) { // WriteTo implements the PacketConn WriteTo method. func (c *UDPConn) WriteTo(b []byte, addr Addr) (int, error) { if !c.ok() { - return 0, os.EINVAL + return 0, syscall.EINVAL } a, ok := addr.(*UDPAddr) if !ok { - return 0, &OpError{"write", c.fd.net, addr, os.EINVAL} + return 0, &OpError{"write", c.fd.net, addr, syscall.EINVAL} } return c.WriteToUDP(b, a) } @@ -262,7 +262,7 @@ func ListenMulticastUDP(net string, ifi *Interface, gaddr *UDPAddr) (*UDPConn, e return nil, UnknownNetworkError(net) } if gaddr == nil || gaddr.IP == nil { - return nil, &OpError{"listenmulticastudp", "udp", nil, errMissingAddress} + return nil, &OpError{"listenmulticast", net, nil, errMissingAddress} } fd, err := internetSocket(net, gaddr.toAddr(), nil, syscall.SOCK_DGRAM, 0, "listen", sockaddrToUDP) if err != nil { diff --git a/libgo/go/net/unixsock_plan9.go b/libgo/go/net/unixsock_plan9.go index 1d9d7578f4f..7b4ae6bd116 100644 --- a/libgo/go/net/unixsock_plan9.go +++ b/libgo/go/net/unixsock_plan9.go @@ -7,7 +7,7 @@ package net import ( - "os" + "syscall" "time" ) @@ -19,17 +19,17 @@ type UnixConn bool // Read implements the Conn Read method. func (c *UnixConn) Read(b []byte) (n int, err error) { - return 0, os.EPLAN9 + return 0, syscall.EPLAN9 } // Write implements the Conn Write method. func (c *UnixConn) Write(b []byte) (n int, err error) { - return 0, os.EPLAN9 + return 0, syscall.EPLAN9 } // Close closes the Unix domain connection. func (c *UnixConn) Close() error { - return os.EPLAN9 + return syscall.EPLAN9 } // LocalAddr returns the local network address, a *UnixAddr. @@ -47,28 +47,28 @@ func (c *UnixConn) RemoteAddr() Addr { // SetDeadline implements the Conn SetDeadline method. func (c *UnixConn) SetDeadline(t time.Time) error { - return os.EPLAN9 + return syscall.EPLAN9 } // SetReadDeadline implements the Conn SetReadDeadline method. func (c *UnixConn) SetReadDeadline(t time.Time) error { - return os.EPLAN9 + return syscall.EPLAN9 } // SetWriteDeadline implements the Conn SetWriteDeadline method. func (c *UnixConn) SetWriteDeadline(t time.Time) error { - return os.EPLAN9 + return syscall.EPLAN9 } // ReadFrom implements the PacketConn ReadFrom method. func (c *UnixConn) ReadFrom(b []byte) (n int, addr Addr, err error) { - err = os.EPLAN9 + err = syscall.EPLAN9 return } // WriteTo implements the PacketConn WriteTo method. func (c *UnixConn) WriteTo(b []byte, addr Addr) (n int, err error) { - err = os.EPLAN9 + err = syscall.EPLAN9 return } @@ -76,7 +76,7 @@ func (c *UnixConn) WriteTo(b []byte, addr Addr) (n int, err error) { // which must be "unix" or "unixgram". If laddr is not nil, it is used // as the local address for the connection. func DialUnix(net string, laddr, raddr *UnixAddr) (c *UnixConn, err error) { - return nil, os.EPLAN9 + return nil, syscall.EPLAN9 } // UnixListener is a Unix domain socket listener. @@ -87,19 +87,19 @@ type UnixListener bool // ListenUnix announces on the Unix domain socket laddr and returns a Unix listener. // Net must be "unix" (stream sockets). func ListenUnix(net string, laddr *UnixAddr) (l *UnixListener, err error) { - return nil, os.EPLAN9 + return nil, syscall.EPLAN9 } // Accept implements the Accept method in the Listener interface; // it waits for the next call and returns a generic Conn. func (l *UnixListener) Accept() (c Conn, err error) { - return nil, os.EPLAN9 + return nil, syscall.EPLAN9 } // Close stops listening on the Unix address. // Already accepted connections are not closed. func (l *UnixListener) Close() error { - return os.EPLAN9 + return syscall.EPLAN9 } // Addr returns the listener's network address. diff --git a/libgo/go/net/unixsock_posix.go b/libgo/go/net/unixsock_posix.go index 10b79668511..3a94cf5c5ad 100644 --- a/libgo/go/net/unixsock_posix.go +++ b/libgo/go/net/unixsock_posix.go @@ -59,8 +59,8 @@ func unixSocket(net string, laddr, raddr *UnixAddr, mode string) (fd *netFD, err f = sockaddrToUnixpacket } - fd, oserr := socket(net, syscall.AF_UNIX, sotype, 0, la, ra, f) - if oserr != nil { + fd, err = socket(net, syscall.AF_UNIX, sotype, 0, la, ra, f) + if err != nil { goto Error } return fd, nil @@ -70,7 +70,7 @@ Error: if mode == "listen" { addr = laddr } - return nil, &OpError{Op: mode, Net: net, Addr: addr, Err: oserr} + return nil, &OpError{Op: mode, Net: net, Addr: addr, Err: err} } func sockaddrToUnix(sa syscall.Sockaddr) Addr { @@ -123,7 +123,7 @@ func (c *UnixConn) ok() bool { return c != nil && c.fd != nil } // Read implements the Conn Read method. func (c *UnixConn) Read(b []byte) (n int, err error) { if !c.ok() { - return 0, os.EINVAL + return 0, syscall.EINVAL } return c.fd.Read(b) } @@ -131,7 +131,7 @@ func (c *UnixConn) Read(b []byte) (n int, err error) { // Write implements the Conn Write method. func (c *UnixConn) Write(b []byte) (n int, err error) { if !c.ok() { - return 0, os.EINVAL + return 0, syscall.EINVAL } return c.fd.Write(b) } @@ -139,7 +139,7 @@ func (c *UnixConn) Write(b []byte) (n int, err error) { // Close closes the Unix domain connection. func (c *UnixConn) Close() error { if !c.ok() { - return os.EINVAL + return syscall.EINVAL } err := c.fd.Close() c.fd = nil @@ -168,7 +168,7 @@ func (c *UnixConn) RemoteAddr() Addr { // SetDeadline implements the Conn SetDeadline method. func (c *UnixConn) SetDeadline(t time.Time) error { if !c.ok() { - return os.EINVAL + return syscall.EINVAL } return setDeadline(c.fd, t) } @@ -176,7 +176,7 @@ func (c *UnixConn) SetDeadline(t time.Time) error { // SetReadDeadline implements the Conn SetReadDeadline method. func (c *UnixConn) SetReadDeadline(t time.Time) error { if !c.ok() { - return os.EINVAL + return syscall.EINVAL } return setReadDeadline(c.fd, t) } @@ -184,7 +184,7 @@ func (c *UnixConn) SetReadDeadline(t time.Time) error { // SetWriteDeadline implements the Conn SetWriteDeadline method. func (c *UnixConn) SetWriteDeadline(t time.Time) error { if !c.ok() { - return os.EINVAL + return syscall.EINVAL } return setWriteDeadline(c.fd, t) } @@ -193,7 +193,7 @@ func (c *UnixConn) SetWriteDeadline(t time.Time) error { // receive buffer associated with the connection. func (c *UnixConn) SetReadBuffer(bytes int) error { if !c.ok() { - return os.EINVAL + return syscall.EINVAL } return setReadBuffer(c.fd, bytes) } @@ -202,7 +202,7 @@ func (c *UnixConn) SetReadBuffer(bytes int) error { // transmit buffer associated with the connection. func (c *UnixConn) SetWriteBuffer(bytes int) error { if !c.ok() { - return os.EINVAL + return syscall.EINVAL } return setWriteBuffer(c.fd, bytes) } @@ -216,7 +216,7 @@ func (c *UnixConn) SetWriteBuffer(bytes int) error { // see SetDeadline and SetReadDeadline. func (c *UnixConn) ReadFromUnix(b []byte) (n int, addr *UnixAddr, err error) { if !c.ok() { - return 0, nil, os.EINVAL + return 0, nil, syscall.EINVAL } n, sa, err := c.fd.ReadFrom(b) switch sa := sa.(type) { @@ -229,7 +229,7 @@ func (c *UnixConn) ReadFromUnix(b []byte) (n int, addr *UnixAddr, err error) { // ReadFrom implements the PacketConn ReadFrom method. func (c *UnixConn) ReadFrom(b []byte) (n int, addr Addr, err error) { if !c.ok() { - return 0, nil, os.EINVAL + return 0, nil, syscall.EINVAL } n, uaddr, err := c.ReadFromUnix(b) return n, uaddr.toAddr(), err @@ -243,10 +243,10 @@ func (c *UnixConn) ReadFrom(b []byte) (n int, addr Addr, err error) { // On packet-oriented connections, write timeouts are rare. func (c *UnixConn) WriteToUnix(b []byte, addr *UnixAddr) (n int, err error) { if !c.ok() { - return 0, os.EINVAL + return 0, syscall.EINVAL } if addr.Net != sotypeToNet(c.fd.sotype) { - return 0, os.EAFNOSUPPORT + return 0, syscall.EAFNOSUPPORT } sa := &syscall.SockaddrUnix{Name: addr.Name} return c.fd.WriteTo(b, sa) @@ -255,18 +255,18 @@ func (c *UnixConn) WriteToUnix(b []byte, addr *UnixAddr) (n int, err error) { // WriteTo implements the PacketConn WriteTo method. func (c *UnixConn) WriteTo(b []byte, addr Addr) (n int, err error) { if !c.ok() { - return 0, os.EINVAL + return 0, syscall.EINVAL } a, ok := addr.(*UnixAddr) if !ok { - return 0, &OpError{"write", c.fd.net, addr, os.EINVAL} + return 0, &OpError{"write", c.fd.net, addr, syscall.EINVAL} } return c.WriteToUnix(b, a) } func (c *UnixConn) ReadMsgUnix(b, oob []byte) (n, oobn, flags int, addr *UnixAddr, err error) { if !c.ok() { - return 0, 0, 0, nil, os.EINVAL + return 0, 0, 0, nil, syscall.EINVAL } n, oobn, flags, sa, err := c.fd.ReadMsg(b, oob) switch sa := sa.(type) { @@ -278,11 +278,11 @@ func (c *UnixConn) ReadMsgUnix(b, oob []byte) (n, oobn, flags int, addr *UnixAdd func (c *UnixConn) WriteMsgUnix(b, oob []byte, addr *UnixAddr) (n, oobn int, err error) { if !c.ok() { - return 0, 0, os.EINVAL + return 0, 0, syscall.EINVAL } if addr != nil { if addr.Net != sotypeToNet(c.fd.sotype) { - return 0, 0, os.EAFNOSUPPORT + return 0, 0, syscall.EAFNOSUPPORT } sa := &syscall.SockaddrUnix{Name: addr.Name} return c.fd.WriteMsg(b, oob, sa) @@ -339,7 +339,7 @@ func ListenUnix(net string, laddr *UnixAddr) (*UnixListener, error) { // and the remote address. func (l *UnixListener) AcceptUnix() (*UnixConn, error) { if l == nil || l.fd == nil { - return nil, os.EINVAL + return nil, syscall.EINVAL } fd, err := l.fd.accept(sockaddrToUnix) if err != nil { @@ -363,7 +363,7 @@ func (l *UnixListener) Accept() (c Conn, err error) { // Already accepted connections are not closed. func (l *UnixListener) Close() error { if l == nil || l.fd == nil { - return os.EINVAL + return syscall.EINVAL } // The operating system doesn't clean up @@ -391,7 +391,7 @@ func (l *UnixListener) Addr() Addr { return l.fd.laddr } // A zero time value disables the deadline. func (l *UnixListener) SetDeadline(t time.Time) (err error) { if l == nil || l.fd == nil { - return os.EINVAL + return syscall.EINVAL } return setDeadline(l.fd, t) } diff --git a/libgo/go/net/url/url.go b/libgo/go/net/url/url.go index a9ce3b31e24..88ff7ebfef3 100644 --- a/libgo/go/net/url/url.go +++ b/libgo/go/net/url/url.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Package URL parses URLs and implements query escaping. +// Package url parses URLs and implements query escaping. // See RFC 3986. package url @@ -321,19 +321,28 @@ func split(s string, c byte, cutc bool) (string, string) { } // Parse parses rawurl into a URL structure. -// The string rawurl is assumed not to have a #fragment suffix. -// (Web browsers strip #fragment before sending the URL to a web server.) // The rawurl may be relative or absolute. func Parse(rawurl string) (url *URL, err error) { - return parse(rawurl, false) + // Cut off #frag + u, frag := split(rawurl, '#', true) + if url, err = parse(u, false); err != nil { + return nil, err + } + if frag == "" { + return url, nil + } + if url.Fragment, err = unescape(frag, encodeFragment); err != nil { + return nil, &Error{"parse", rawurl, err} + } + return url, nil } -// ParseRequest parses rawurl into a URL structure. It assumes that -// rawurl was received from an HTTP request, so the rawurl is interpreted +// ParseRequestURI parses rawurl into a URL structure. It assumes that +// rawurl was received in an HTTP request, so the rawurl is interpreted // only as an absolute URI or an absolute path. // The string rawurl is assumed not to have a #fragment suffix. // (Web browsers strip #fragment before sending the URL to a web server.) -func ParseRequest(rawurl string) (url *URL, err error) { +func ParseRequestURI(rawurl string) (url *URL, err error) { return parse(rawurl, true) } @@ -415,22 +424,6 @@ func parseAuthority(authority string) (user *Userinfo, host string, err error) { return } -// ParseWithReference is like Parse but allows a trailing #fragment. -func ParseWithReference(rawurlref string) (url *URL, err error) { - // Cut off #frag - rawurl, frag := split(rawurlref, '#', true) - if url, err = Parse(rawurl); err != nil { - return nil, err - } - if frag == "" { - return url, nil - } - if url.Fragment, err = unescape(frag, encodeFragment); err != nil { - return nil, &Error{"parse", rawurlref, err} - } - return url, nil -} - // String reassembles the URL into a valid URL string. func (u *URL) String() string { // TODO: Rewrite to use bytes.Buffer @@ -589,15 +582,15 @@ func (u *URL) IsAbs() bool { return u.Scheme != "" } -// Parse parses a URL in the context of a base URL. The URL in ref +// Parse parses a URL in the context of the receiver. The provided URL // may be relative or absolute. Parse returns nil, err on parse // failure, otherwise its return value is the same as ResolveReference. -func (base *URL) Parse(ref string) (*URL, error) { +func (u *URL) Parse(ref string) (*URL, error) { refurl, err := Parse(ref) if err != nil { return nil, err } - return base.ResolveReference(refurl), nil + return u.ResolveReference(refurl), nil } // ResolveReference resolves a URI reference to an absolute URI from @@ -606,13 +599,13 @@ func (base *URL) Parse(ref string) (*URL, error) { // URL instance, even if the returned URL is identical to either the // base or reference. If ref is an absolute URL, then ResolveReference // ignores base and returns a copy of ref. -func (base *URL) ResolveReference(ref *URL) *URL { +func (u *URL) ResolveReference(ref *URL) *URL { if ref.IsAbs() { url := *ref return &url } // relativeURI = ( net_path | abs_path | rel_path ) [ "?" query ] - url := *base + url := *u url.RawQuery = ref.RawQuery url.Fragment = ref.Fragment if ref.Opaque != "" { @@ -632,7 +625,7 @@ func (base *URL) ResolveReference(ref *URL) *URL { url.Path = ref.Path } else { // The "rel_path" case. - path := resolvePath(base.Path, ref.Path) + path := resolvePath(u.Path, ref.Path) if !strings.HasPrefix(path, "/") { path = "/" + path } diff --git a/libgo/go/net/url/url_test.go b/libgo/go/net/url/url_test.go index 9fe5ff886b7..2d911ed505a 100644 --- a/libgo/go/net/url/url_test.go +++ b/libgo/go/net/url/url_test.go @@ -188,22 +188,6 @@ var urltests = []URLTest{ }, "http://user:password@google.com", }, -} - -var urlnofragtests = []URLTest{ - { - "http://www.google.com/?q=go+language#foo", - &URL{ - Scheme: "http", - Host: "www.google.com", - Path: "/", - RawQuery: "q=go+language#foo", - }, - "", - }, -} - -var urlfragtests = []URLTest{ { "http://www.google.com/?q=go+language#foo", &URL{ @@ -257,12 +241,6 @@ func DoTest(t *testing.T, parse func(string) (*URL, error), name string, tests [ func TestParse(t *testing.T) { DoTest(t, Parse, "Parse", urltests) - DoTest(t, Parse, "Parse", urlnofragtests) -} - -func TestParseWithReference(t *testing.T) { - DoTest(t, ParseWithReference, "ParseWithReference", urltests) - DoTest(t, ParseWithReference, "ParseWithReference", urlfragtests) } const pathThatLooksSchemeRelative = "//not.a.user@not.a.host/just/a/path" @@ -281,16 +259,16 @@ var parseRequestUrlTests = []struct { {"../dir/", false}, } -func TestParseRequest(t *testing.T) { +func TestParseRequestURI(t *testing.T) { for _, test := range parseRequestUrlTests { - _, err := ParseRequest(test.url) + _, err := ParseRequestURI(test.url) valid := err == nil if valid != test.expectedValid { t.Errorf("Expected valid=%v for %q; got %v", test.expectedValid, test.url, valid) } } - url, err := ParseRequest(pathThatLooksSchemeRelative) + url, err := ParseRequestURI(pathThatLooksSchemeRelative) if err != nil { t.Fatalf("Unexpected error %v", err) } @@ -319,9 +297,6 @@ func DoTestString(t *testing.T, parse func(string) (*URL, error), name string, t func TestURLString(t *testing.T) { DoTestString(t, Parse, "Parse", urltests) - DoTestString(t, Parse, "Parse", urlnofragtests) - DoTestString(t, ParseWithReference, "ParseWithReference", urltests) - DoTestString(t, ParseWithReference, "ParseWithReference", urlfragtests) } type EscapeTest struct { @@ -538,7 +513,7 @@ var resolveReferenceTests = []struct { func TestResolveReference(t *testing.T) { mustParse := func(url string) *URL { - u, err := ParseWithReference(url) + u, err := Parse(url) if err != nil { t.Fatalf("Expected URL to parse: %q, got error: %v", url, err) } @@ -589,7 +564,7 @@ func TestResolveReference(t *testing.T) { func TestResolveReferenceOpaque(t *testing.T) { mustParse := func(url string) *URL { - u, err := ParseWithReference(url) + u, err := Parse(url) if err != nil { t.Fatalf("Expected URL to parse: %q, got error: %v", url, err) } |