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