Mikio Hara | 306afc7 | 2012-11-13 16:18:37 +0900 | [diff] [blame] | 1 | // Copyright 2009 The Go Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style |
| 3 | // license that can be found in the LICENSE file. |
| 4 | |
| 5 | package net |
| 6 | |
| 7 | import ( |
| 8 | "io" |
| 9 | "os" |
| 10 | "syscall" |
| 11 | "time" |
| 12 | ) |
| 13 | |
| 14 | // Network file descritor. |
| 15 | type netFD struct { |
| 16 | proto, name, dir string |
| 17 | ctl, data *os.File |
| 18 | laddr, raddr Addr |
| 19 | } |
| 20 | |
Mikio Hara | 306afc7 | 2012-11-13 16:18:37 +0900 | [diff] [blame] | 21 | func sysInit() { |
| 22 | } |
| 23 | |
Mikio Hara | 89b2676 | 2013-09-11 10:48:53 -0400 | [diff] [blame] | 24 | func dial(net string, ra Addr, dialer func(time.Time) (Conn, error), deadline time.Time) (Conn, error) { |
Alex Brainman | 810e439 | 2013-01-11 12:42:09 +1100 | [diff] [blame] | 25 | // On plan9, use the relatively inefficient |
| 26 | // goroutine-racing implementation. |
Mikio Hara | 89b2676 | 2013-09-11 10:48:53 -0400 | [diff] [blame] | 27 | return dialChannel(net, ra, dialer, deadline) |
Alex Brainman | 810e439 | 2013-01-11 12:42:09 +1100 | [diff] [blame] | 28 | } |
| 29 | |
Akshat Kumar | 66b69a1 | 2013-02-19 17:11:17 -0800 | [diff] [blame] | 30 | func newFD(proto, name string, ctl, data *os.File, laddr, raddr Addr) *netFD { |
| 31 | return &netFD{proto, name, "/net/" + proto + "/" + name, ctl, data, laddr, raddr} |
Mikio Hara | 306afc7 | 2012-11-13 16:18:37 +0900 | [diff] [blame] | 32 | } |
| 33 | |
| 34 | func (fd *netFD) ok() bool { return fd != nil && fd.ctl != nil } |
| 35 | |
| 36 | func (fd *netFD) Read(b []byte) (n int, err error) { |
Akshat Kumar | 66b69a1 | 2013-02-19 17:11:17 -0800 | [diff] [blame] | 37 | if !fd.ok() || fd.data == nil { |
Mikio Hara | 306afc7 | 2012-11-13 16:18:37 +0900 | [diff] [blame] | 38 | return 0, syscall.EINVAL |
| 39 | } |
Mikio Hara | 306afc7 | 2012-11-13 16:18:37 +0900 | [diff] [blame] | 40 | n, err = fd.data.Read(b) |
| 41 | if fd.proto == "udp" && err == io.EOF { |
| 42 | n = 0 |
| 43 | err = nil |
| 44 | } |
| 45 | return |
| 46 | } |
| 47 | |
| 48 | func (fd *netFD) Write(b []byte) (n int, err error) { |
Akshat Kumar | 66b69a1 | 2013-02-19 17:11:17 -0800 | [diff] [blame] | 49 | if !fd.ok() || fd.data == nil { |
Mikio Hara | 306afc7 | 2012-11-13 16:18:37 +0900 | [diff] [blame] | 50 | return 0, syscall.EINVAL |
| 51 | } |
Mikio Hara | 306afc7 | 2012-11-13 16:18:37 +0900 | [diff] [blame] | 52 | return fd.data.Write(b) |
| 53 | } |
| 54 | |
| 55 | func (fd *netFD) CloseRead() error { |
| 56 | if !fd.ok() { |
| 57 | return syscall.EINVAL |
| 58 | } |
| 59 | return syscall.EPLAN9 |
| 60 | } |
| 61 | |
| 62 | func (fd *netFD) CloseWrite() error { |
| 63 | if !fd.ok() { |
| 64 | return syscall.EINVAL |
| 65 | } |
| 66 | return syscall.EPLAN9 |
| 67 | } |
| 68 | |
| 69 | func (fd *netFD) Close() error { |
| 70 | if !fd.ok() { |
| 71 | return syscall.EINVAL |
| 72 | } |
| 73 | err := fd.ctl.Close() |
Mikio Hara | 306afc7 | 2012-11-13 16:18:37 +0900 | [diff] [blame] | 74 | if fd.data != nil { |
Akshat Kumar | 66b69a1 | 2013-02-19 17:11:17 -0800 | [diff] [blame] | 75 | if err1 := fd.data.Close(); err1 != nil && err == nil { |
| 76 | err = err1 |
| 77 | } |
Mikio Hara | 306afc7 | 2012-11-13 16:18:37 +0900 | [diff] [blame] | 78 | } |
| 79 | fd.ctl = nil |
| 80 | fd.data = nil |
| 81 | return err |
| 82 | } |
| 83 | |
Akshat Kumar | b461fe6 | 2013-02-26 01:26:40 +0100 | [diff] [blame] | 84 | // This method is only called via Conn. |
Mikio Hara | 306afc7 | 2012-11-13 16:18:37 +0900 | [diff] [blame] | 85 | func (fd *netFD) dup() (*os.File, error) { |
Akshat Kumar | b461fe6 | 2013-02-26 01:26:40 +0100 | [diff] [blame] | 86 | if !fd.ok() || fd.data == nil { |
| 87 | return nil, syscall.EINVAL |
| 88 | } |
| 89 | return fd.file(fd.data, fd.dir+"/data") |
| 90 | } |
| 91 | |
| 92 | func (l *TCPListener) dup() (*os.File, error) { |
| 93 | if !l.fd.ok() { |
| 94 | return nil, syscall.EINVAL |
| 95 | } |
| 96 | return l.fd.file(l.fd.ctl, l.fd.dir+"/ctl") |
| 97 | } |
| 98 | |
| 99 | func (fd *netFD) file(f *os.File, s string) (*os.File, error) { |
| 100 | syscall.ForkLock.RLock() |
| 101 | dfd, err := syscall.Dup(int(f.Fd()), -1) |
| 102 | syscall.ForkLock.RUnlock() |
| 103 | if err != nil { |
| 104 | return nil, &OpError{"dup", s, fd.laddr, err} |
| 105 | } |
| 106 | return os.NewFile(uintptr(dfd), s), nil |
Mikio Hara | 306afc7 | 2012-11-13 16:18:37 +0900 | [diff] [blame] | 107 | } |
| 108 | |
Mikio Hara | 39a7017 | 2013-08-13 20:00:58 +0900 | [diff] [blame] | 109 | func (fd *netFD) setDeadline(t time.Time) error { |
Mikio Hara | 306afc7 | 2012-11-13 16:18:37 +0900 | [diff] [blame] | 110 | return syscall.EPLAN9 |
| 111 | } |
| 112 | |
Mikio Hara | 39a7017 | 2013-08-13 20:00:58 +0900 | [diff] [blame] | 113 | func (fd *netFD) setReadDeadline(t time.Time) error { |
Mikio Hara | 306afc7 | 2012-11-13 16:18:37 +0900 | [diff] [blame] | 114 | return syscall.EPLAN9 |
| 115 | } |
| 116 | |
Mikio Hara | 39a7017 | 2013-08-13 20:00:58 +0900 | [diff] [blame] | 117 | func (fd *netFD) setWriteDeadline(t time.Time) error { |
Mikio Hara | 306afc7 | 2012-11-13 16:18:37 +0900 | [diff] [blame] | 118 | return syscall.EPLAN9 |
| 119 | } |
| 120 | |
| 121 | func setReadBuffer(fd *netFD, bytes int) error { |
| 122 | return syscall.EPLAN9 |
| 123 | } |
| 124 | |
| 125 | func setWriteBuffer(fd *netFD, bytes int) error { |
| 126 | return syscall.EPLAN9 |
| 127 | } |