github.com/tcnksm/go@v0.0.0-20141208075154-439b32936367/src/net/fd_plan9.go (about)

     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  	// locking/lifetime of sysfd + serialize access to Read and Write methods
    17  	fdmu fdMutex
    18  
    19  	// immutable until Close
    20  	proto        string
    21  	n            string
    22  	dir          string
    23  	ctl, data    *os.File
    24  	laddr, raddr Addr
    25  }
    26  
    27  var (
    28  	netdir string // default network
    29  )
    30  
    31  func sysInit() {
    32  	netdir = "/net"
    33  }
    34  
    35  func dial(net string, ra Addr, dialer func(time.Time) (Conn, error), deadline time.Time) (Conn, error) {
    36  	// On plan9, use the relatively inefficient
    37  	// goroutine-racing implementation.
    38  	return dialChannel(net, ra, dialer, deadline)
    39  }
    40  
    41  func newFD(proto, name string, ctl, data *os.File, laddr, raddr Addr) (*netFD, error) {
    42  	return &netFD{proto: proto, n: name, dir: netdir + "/" + proto + "/" + name, ctl: ctl, data: data, laddr: laddr, raddr: raddr}, nil
    43  }
    44  
    45  func (fd *netFD) init() error {
    46  	// stub for future fd.pd.Init(fd)
    47  	return nil
    48  }
    49  
    50  func (fd *netFD) name() string {
    51  	var ls, rs string
    52  	if fd.laddr != nil {
    53  		ls = fd.laddr.String()
    54  	}
    55  	if fd.raddr != nil {
    56  		rs = fd.raddr.String()
    57  	}
    58  	return fd.proto + ":" + ls + "->" + rs
    59  }
    60  
    61  func (fd *netFD) ok() bool { return fd != nil && fd.ctl != nil }
    62  
    63  func (fd *netFD) destroy() {
    64  	if !fd.ok() {
    65  		return
    66  	}
    67  	err := fd.ctl.Close()
    68  	if fd.data != nil {
    69  		if err1 := fd.data.Close(); err1 != nil && err == nil {
    70  			err = err1
    71  		}
    72  	}
    73  	fd.ctl = nil
    74  	fd.data = nil
    75  }
    76  
    77  // Add a reference to this fd.
    78  // Returns an error if the fd cannot be used.
    79  func (fd *netFD) incref() error {
    80  	if !fd.fdmu.Incref() {
    81  		return errClosing
    82  	}
    83  	return nil
    84  }
    85  
    86  // Remove a reference to this FD and close if we've been asked to do so
    87  // (and there are no references left).
    88  func (fd *netFD) decref() {
    89  	if fd.fdmu.Decref() {
    90  		fd.destroy()
    91  	}
    92  }
    93  
    94  // Add a reference to this fd and lock for reading.
    95  // Returns an error if the fd cannot be used.
    96  func (fd *netFD) readLock() error {
    97  	if !fd.fdmu.RWLock(true) {
    98  		return errClosing
    99  	}
   100  	return nil
   101  }
   102  
   103  // Unlock for reading and remove a reference to this FD.
   104  func (fd *netFD) readUnlock() {
   105  	if fd.fdmu.RWUnlock(true) {
   106  		fd.destroy()
   107  	}
   108  }
   109  
   110  // Add a reference to this fd and lock for writing.
   111  // Returns an error if the fd cannot be used.
   112  func (fd *netFD) writeLock() error {
   113  	if !fd.fdmu.RWLock(false) {
   114  		return errClosing
   115  	}
   116  	return nil
   117  }
   118  
   119  // Unlock for writing and remove a reference to this FD.
   120  func (fd *netFD) writeUnlock() {
   121  	if fd.fdmu.RWUnlock(false) {
   122  		fd.destroy()
   123  	}
   124  }
   125  
   126  func (fd *netFD) Read(b []byte) (n int, err error) {
   127  	if !fd.ok() || fd.data == nil {
   128  		return 0, syscall.EINVAL
   129  	}
   130  	if err := fd.readLock(); err != nil {
   131  		return 0, err
   132  	}
   133  	defer fd.readUnlock()
   134  	n, err = fd.data.Read(b)
   135  	if fd.proto == "udp" && err == io.EOF {
   136  		n = 0
   137  		err = nil
   138  	}
   139  	return
   140  }
   141  
   142  func (fd *netFD) Write(b []byte) (n int, err error) {
   143  	if !fd.ok() || fd.data == nil {
   144  		return 0, syscall.EINVAL
   145  	}
   146  	if err := fd.writeLock(); err != nil {
   147  		return 0, err
   148  	}
   149  	defer fd.writeUnlock()
   150  	return fd.data.Write(b)
   151  }
   152  
   153  func (fd *netFD) closeRead() error {
   154  	if !fd.ok() {
   155  		return syscall.EINVAL
   156  	}
   157  	return syscall.EPLAN9
   158  }
   159  
   160  func (fd *netFD) closeWrite() error {
   161  	if !fd.ok() {
   162  		return syscall.EINVAL
   163  	}
   164  	return syscall.EPLAN9
   165  }
   166  
   167  func (fd *netFD) Close() error {
   168  	if !fd.fdmu.IncrefAndClose() {
   169  		return errClosing
   170  	}
   171  	if !fd.ok() {
   172  		return syscall.EINVAL
   173  	}
   174  	err := fd.ctl.Close()
   175  	if fd.data != nil {
   176  		if err1 := fd.data.Close(); err1 != nil && err == nil {
   177  			err = err1
   178  		}
   179  	}
   180  	fd.ctl = nil
   181  	fd.data = nil
   182  	return err
   183  }
   184  
   185  // This method is only called via Conn.
   186  func (fd *netFD) dup() (*os.File, error) {
   187  	if !fd.ok() || fd.data == nil {
   188  		return nil, syscall.EINVAL
   189  	}
   190  	return fd.file(fd.data, fd.dir+"/data")
   191  }
   192  
   193  func (l *TCPListener) dup() (*os.File, error) {
   194  	if !l.fd.ok() {
   195  		return nil, syscall.EINVAL
   196  	}
   197  	return l.fd.file(l.fd.ctl, l.fd.dir+"/ctl")
   198  }
   199  
   200  func (fd *netFD) file(f *os.File, s string) (*os.File, error) {
   201  	syscall.ForkLock.RLock()
   202  	dfd, err := syscall.Dup(int(f.Fd()), -1)
   203  	syscall.ForkLock.RUnlock()
   204  	if err != nil {
   205  		return nil, &OpError{"dup", s, fd.laddr, err}
   206  	}
   207  	return os.NewFile(uintptr(dfd), s), nil
   208  }
   209  
   210  func (fd *netFD) setDeadline(t time.Time) error {
   211  	return syscall.EPLAN9
   212  }
   213  
   214  func (fd *netFD) setReadDeadline(t time.Time) error {
   215  	return syscall.EPLAN9
   216  }
   217  
   218  func (fd *netFD) setWriteDeadline(t time.Time) error {
   219  	return syscall.EPLAN9
   220  }
   221  
   222  func setReadBuffer(fd *netFD, bytes int) error {
   223  	return syscall.EPLAN9
   224  }
   225  
   226  func setWriteBuffer(fd *netFD, bytes int) error {
   227  	return syscall.EPLAN9
   228  }
   229  
   230  func skipRawSocketTests() (skip bool, skipmsg string, err error) {
   231  	return true, "skipping test on plan9", nil
   232  }