github.com/rakyll/go@v0.0.0-20170216000551-64c02460d703/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  	"internal/poll"
     9  	"io"
    10  	"os"
    11  	"syscall"
    12  )
    13  
    14  // Network file descriptor.
    15  type netFD struct {
    16  	pfd poll.FD
    17  
    18  	// immutable until Close
    19  	net               string
    20  	n                 string
    21  	dir               string
    22  	listen, ctl, data *os.File
    23  	laddr, raddr      Addr
    24  	isStream          bool
    25  }
    26  
    27  var (
    28  	netdir string // default network
    29  )
    30  
    31  func sysInit() {
    32  	netdir = "/net"
    33  }
    34  
    35  func newFD(net, name string, listen, ctl, data *os.File, laddr, raddr Addr) (*netFD, error) {
    36  	ret := &netFD{
    37  		net:    net,
    38  		n:      name,
    39  		dir:    netdir + "/" + net + "/" + name,
    40  		listen: listen,
    41  		ctl:    ctl, data: data,
    42  		laddr: laddr,
    43  		raddr: raddr,
    44  	}
    45  	ret.pfd.Destroy = ret.destroy
    46  	return ret, nil
    47  }
    48  
    49  func (fd *netFD) init() error {
    50  	// stub for future fd.pd.Init(fd)
    51  	return nil
    52  }
    53  
    54  func (fd *netFD) name() string {
    55  	var ls, rs string
    56  	if fd.laddr != nil {
    57  		ls = fd.laddr.String()
    58  	}
    59  	if fd.raddr != nil {
    60  		rs = fd.raddr.String()
    61  	}
    62  	return fd.net + ":" + ls + "->" + rs
    63  }
    64  
    65  func (fd *netFD) ok() bool { return fd != nil && fd.ctl != nil }
    66  
    67  func (fd *netFD) destroy() {
    68  	if !fd.ok() {
    69  		return
    70  	}
    71  	err := fd.ctl.Close()
    72  	if fd.data != nil {
    73  		if err1 := fd.data.Close(); err1 != nil && err == nil {
    74  			err = err1
    75  		}
    76  	}
    77  	if fd.listen != nil {
    78  		if err1 := fd.listen.Close(); err1 != nil && err == nil {
    79  			err = err1
    80  		}
    81  	}
    82  	fd.ctl = nil
    83  	fd.data = nil
    84  	fd.listen = nil
    85  }
    86  
    87  func (fd *netFD) Read(b []byte) (n int, err error) {
    88  	if !fd.ok() || fd.data == nil {
    89  		return 0, syscall.EINVAL
    90  	}
    91  	n, err = fd.pfd.Read(fd.data.Read, b)
    92  	if fd.net == "udp" && err == io.EOF {
    93  		n = 0
    94  		err = nil
    95  	}
    96  	return
    97  }
    98  
    99  func (fd *netFD) Write(b []byte) (n int, err error) {
   100  	if !fd.ok() || fd.data == nil {
   101  		return 0, syscall.EINVAL
   102  	}
   103  	return fd.pfd.Write(fd.data.Write, b)
   104  }
   105  
   106  func (fd *netFD) closeRead() error {
   107  	if !fd.ok() {
   108  		return syscall.EINVAL
   109  	}
   110  	return syscall.EPLAN9
   111  }
   112  
   113  func (fd *netFD) closeWrite() error {
   114  	if !fd.ok() {
   115  		return syscall.EINVAL
   116  	}
   117  	return syscall.EPLAN9
   118  }
   119  
   120  func (fd *netFD) Close() error {
   121  	if err := fd.pfd.Close(); err != nil {
   122  		return err
   123  	}
   124  	if !fd.ok() {
   125  		return syscall.EINVAL
   126  	}
   127  	if fd.net == "tcp" {
   128  		// The following line is required to unblock Reads.
   129  		_, err := fd.ctl.WriteString("close")
   130  		if err != nil {
   131  			return err
   132  		}
   133  	}
   134  	err := fd.ctl.Close()
   135  	if fd.data != nil {
   136  		if err1 := fd.data.Close(); err1 != nil && err == nil {
   137  			err = err1
   138  		}
   139  	}
   140  	if fd.listen != nil {
   141  		if err1 := fd.listen.Close(); err1 != nil && err == nil {
   142  			err = err1
   143  		}
   144  	}
   145  	fd.ctl = nil
   146  	fd.data = nil
   147  	fd.listen = nil
   148  	return err
   149  }
   150  
   151  // This method is only called via Conn.
   152  func (fd *netFD) dup() (*os.File, error) {
   153  	if !fd.ok() || fd.data == nil {
   154  		return nil, syscall.EINVAL
   155  	}
   156  	return fd.file(fd.data, fd.dir+"/data")
   157  }
   158  
   159  func (l *TCPListener) dup() (*os.File, error) {
   160  	if !l.fd.ok() {
   161  		return nil, syscall.EINVAL
   162  	}
   163  	return l.fd.file(l.fd.ctl, l.fd.dir+"/ctl")
   164  }
   165  
   166  func (fd *netFD) file(f *os.File, s string) (*os.File, error) {
   167  	dfd, err := syscall.Dup(int(f.Fd()), -1)
   168  	if err != nil {
   169  		return nil, os.NewSyscallError("dup", err)
   170  	}
   171  	return os.NewFile(uintptr(dfd), s), nil
   172  }
   173  
   174  func setReadBuffer(fd *netFD, bytes int) error {
   175  	return syscall.EPLAN9
   176  }
   177  
   178  func setWriteBuffer(fd *netFD, bytes int) error {
   179  	return syscall.EPLAN9
   180  }