Source file src/net/fd_plan9.go

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

View as plain text