mirror of
https://github.com/rwinkhart/sys.git
synced 2026-09-05 16:47:27 -04:00
go.sys: copy files from syscall package to go.sys/{plan9,windows,unix}
This CL copies to each package of go.sys the files from syscall it will need.
Different directories have different files, but these:
mkall.sh
str.go
syscall.go
mksyscall.pl
race.go
race0.go
syscall_test.go
are copied to all three.
No changes yet, these are just copies. They are not ready to use yet:
package names are wrong, for starters. But this clean copy will make
it easier to follow the changes as the packages are enabled.
LGTM=rsc
R=golang-codereviews, rsc
CC=golang-codereviews
https://golang.org/cl/126960043
This commit is contained in:
@@ -0,0 +1,912 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// A simulated network for use within NaCl.
|
||||
// The simulation is not particularly tied to NaCl,
|
||||
// but other systems have real networks.
|
||||
|
||||
package syscall
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
// Interface to timers implemented in package runtime.
|
||||
// Must be in sync with ../runtime/runtime.h:/^struct.Timer$
|
||||
// Really for use by package time, but we cannot import time here.
|
||||
|
||||
type runtimeTimer struct {
|
||||
i int32
|
||||
when int64
|
||||
period int64
|
||||
f func(int64, interface{}) // NOTE: must not be closure
|
||||
arg interface{}
|
||||
}
|
||||
|
||||
func startTimer(*runtimeTimer)
|
||||
func stopTimer(*runtimeTimer) bool
|
||||
|
||||
type timer struct {
|
||||
expired bool
|
||||
q *queue
|
||||
r runtimeTimer
|
||||
}
|
||||
|
||||
func (t *timer) start(q *queue, deadline int64) {
|
||||
if deadline == 0 {
|
||||
return
|
||||
}
|
||||
t.q = q
|
||||
t.r.when = deadline
|
||||
t.r.f = timerExpired
|
||||
t.r.arg = t
|
||||
startTimer(&t.r)
|
||||
}
|
||||
|
||||
func (t *timer) stop() {
|
||||
stopTimer(&t.r)
|
||||
}
|
||||
|
||||
func timerExpired(now int64, i interface{}) {
|
||||
t := i.(*timer)
|
||||
go func() {
|
||||
t.q.Lock()
|
||||
defer t.q.Unlock()
|
||||
t.expired = true
|
||||
t.q.canRead.Broadcast()
|
||||
t.q.canWrite.Broadcast()
|
||||
}()
|
||||
}
|
||||
|
||||
// Network constants and data structures. These match the traditional values.
|
||||
|
||||
const (
|
||||
AF_UNSPEC = iota
|
||||
AF_UNIX
|
||||
AF_INET
|
||||
AF_INET6
|
||||
)
|
||||
|
||||
const (
|
||||
SHUT_RD = iota
|
||||
SHUT_WR
|
||||
SHUT_RDWR
|
||||
)
|
||||
|
||||
const (
|
||||
SOCK_STREAM = 1 + iota
|
||||
SOCK_DGRAM
|
||||
SOCK_RAW
|
||||
SOCK_SEQPACKET
|
||||
)
|
||||
|
||||
const (
|
||||
IPPROTO_IP = 0
|
||||
IPPROTO_IPV4 = 4
|
||||
IPPROTO_IPV6 = 0x29
|
||||
IPPROTO_TCP = 6
|
||||
IPPROTO_UDP = 0x11
|
||||
)
|
||||
|
||||
// Misc constants expected by package net but not supported.
|
||||
const (
|
||||
_ = iota
|
||||
SOL_SOCKET
|
||||
SO_TYPE
|
||||
NET_RT_IFLIST
|
||||
IFNAMSIZ
|
||||
IFF_UP
|
||||
IFF_BROADCAST
|
||||
IFF_LOOPBACK
|
||||
IFF_POINTOPOINT
|
||||
IFF_MULTICAST
|
||||
IPV6_V6ONLY
|
||||
SOMAXCONN
|
||||
F_DUPFD_CLOEXEC
|
||||
SO_BROADCAST
|
||||
SO_REUSEADDR
|
||||
SO_REUSEPORT
|
||||
SO_RCVBUF
|
||||
SO_SNDBUF
|
||||
SO_KEEPALIVE
|
||||
SO_LINGER
|
||||
SO_ERROR
|
||||
IP_PORTRANGE
|
||||
IP_PORTRANGE_DEFAULT
|
||||
IP_PORTRANGE_LOW
|
||||
IP_PORTRANGE_HIGH
|
||||
IP_MULTICAST_IF
|
||||
IP_MULTICAST_LOOP
|
||||
IP_ADD_MEMBERSHIP
|
||||
IPV6_PORTRANGE
|
||||
IPV6_PORTRANGE_DEFAULT
|
||||
IPV6_PORTRANGE_LOW
|
||||
IPV6_PORTRANGE_HIGH
|
||||
IPV6_MULTICAST_IF
|
||||
IPV6_MULTICAST_LOOP
|
||||
IPV6_JOIN_GROUP
|
||||
TCP_NODELAY
|
||||
TCP_KEEPINTVL
|
||||
TCP_KEEPIDLE
|
||||
|
||||
SYS_FCNTL = 500 // unsupported
|
||||
)
|
||||
|
||||
var SocketDisableIPv6 bool
|
||||
|
||||
// A Sockaddr is one of the SockaddrXxx structs.
|
||||
type Sockaddr interface {
|
||||
// copy returns a copy of the underlying data.
|
||||
copy() Sockaddr
|
||||
|
||||
// key returns the value of the underlying data,
|
||||
// for comparison as a map key.
|
||||
key() interface{}
|
||||
}
|
||||
|
||||
type SockaddrInet4 struct {
|
||||
Port int
|
||||
Addr [4]byte
|
||||
}
|
||||
|
||||
func (sa *SockaddrInet4) copy() Sockaddr {
|
||||
sa1 := *sa
|
||||
return &sa1
|
||||
}
|
||||
|
||||
func (sa *SockaddrInet4) key() interface{} { return *sa }
|
||||
|
||||
type SockaddrInet6 struct {
|
||||
Port int
|
||||
ZoneId uint32
|
||||
Addr [16]byte
|
||||
}
|
||||
|
||||
func (sa *SockaddrInet6) copy() Sockaddr {
|
||||
sa1 := *sa
|
||||
return &sa1
|
||||
}
|
||||
|
||||
func (sa *SockaddrInet6) key() interface{} { return *sa }
|
||||
|
||||
type SockaddrUnix struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
func (sa *SockaddrUnix) copy() Sockaddr {
|
||||
sa1 := *sa
|
||||
return &sa1
|
||||
}
|
||||
|
||||
func (sa *SockaddrUnix) key() interface{} { return *sa }
|
||||
|
||||
type SockaddrDatalink struct {
|
||||
Len uint8
|
||||
Family uint8
|
||||
Index uint16
|
||||
Type uint8
|
||||
Nlen uint8
|
||||
Alen uint8
|
||||
Slen uint8
|
||||
Data [12]int8
|
||||
}
|
||||
|
||||
func (sa *SockaddrDatalink) copy() Sockaddr {
|
||||
sa1 := *sa
|
||||
return &sa1
|
||||
}
|
||||
|
||||
func (sa *SockaddrDatalink) key() interface{} { return *sa }
|
||||
|
||||
// RoutingMessage represents a routing message.
|
||||
type RoutingMessage interface {
|
||||
unimplemented()
|
||||
}
|
||||
|
||||
type IPMreq struct {
|
||||
Multiaddr [4]byte /* in_addr */
|
||||
Interface [4]byte /* in_addr */
|
||||
}
|
||||
|
||||
type IPv6Mreq struct {
|
||||
Multiaddr [16]byte /* in6_addr */
|
||||
Interface uint32
|
||||
}
|
||||
|
||||
type Linger struct {
|
||||
Onoff int32
|
||||
Linger int32
|
||||
}
|
||||
|
||||
type ICMPv6Filter struct {
|
||||
Filt [8]uint32
|
||||
}
|
||||
|
||||
// A queue is the bookkeeping for a synchronized buffered queue.
|
||||
// We do not use channels because we need to be able to handle
|
||||
// writes after and during close, and because a chan byte would
|
||||
// require too many send and receive operations in real use.
|
||||
type queue struct {
|
||||
sync.Mutex
|
||||
canRead sync.Cond
|
||||
canWrite sync.Cond
|
||||
r int // total read index
|
||||
w int // total write index
|
||||
m int // index mask
|
||||
closed bool
|
||||
}
|
||||
|
||||
func (q *queue) init(size int) {
|
||||
if size&(size-1) != 0 {
|
||||
panic("invalid queue size - must be power of two")
|
||||
}
|
||||
q.canRead.L = &q.Mutex
|
||||
q.canWrite.L = &q.Mutex
|
||||
q.m = size - 1
|
||||
}
|
||||
|
||||
func past(deadline int64) bool {
|
||||
sec, nsec := now()
|
||||
return deadline > 0 && deadline < sec*1e9+int64(nsec)
|
||||
}
|
||||
|
||||
func (q *queue) waitRead(n int, deadline int64) (int, error) {
|
||||
if past(deadline) {
|
||||
return 0, EAGAIN
|
||||
}
|
||||
var t timer
|
||||
t.start(q, deadline)
|
||||
for q.w-q.r == 0 && !q.closed && !t.expired {
|
||||
q.canRead.Wait()
|
||||
}
|
||||
t.stop()
|
||||
m := q.w - q.r
|
||||
if m == 0 && t.expired {
|
||||
return 0, EAGAIN
|
||||
}
|
||||
if m > n {
|
||||
m = n
|
||||
q.canRead.Signal() // wake up next reader too
|
||||
}
|
||||
q.canWrite.Signal()
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (q *queue) waitWrite(n int, deadline int64) (int, error) {
|
||||
if past(deadline) {
|
||||
return 0, EAGAIN
|
||||
}
|
||||
var t timer
|
||||
t.start(q, deadline)
|
||||
for q.w-q.r > q.m && !q.closed && !t.expired {
|
||||
q.canWrite.Wait()
|
||||
}
|
||||
t.stop()
|
||||
m := q.m + 1 - (q.w - q.r)
|
||||
if m == 0 && t.expired {
|
||||
return 0, EAGAIN
|
||||
}
|
||||
if m == 0 {
|
||||
return 0, EAGAIN
|
||||
}
|
||||
if m > n {
|
||||
m = n
|
||||
q.canWrite.Signal() // wake up next writer too
|
||||
}
|
||||
q.canRead.Signal()
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (q *queue) close() {
|
||||
q.Lock()
|
||||
defer q.Unlock()
|
||||
q.closed = true
|
||||
q.canRead.Broadcast()
|
||||
q.canWrite.Broadcast()
|
||||
}
|
||||
|
||||
// A byteq is a byte queue.
|
||||
type byteq struct {
|
||||
queue
|
||||
data []byte
|
||||
}
|
||||
|
||||
func newByteq() *byteq {
|
||||
q := &byteq{
|
||||
data: make([]byte, 4096),
|
||||
}
|
||||
q.init(len(q.data))
|
||||
return q
|
||||
}
|
||||
|
||||
func (q *byteq) read(b []byte, deadline int64) (int, error) {
|
||||
q.Lock()
|
||||
defer q.Unlock()
|
||||
n, err := q.waitRead(len(b), deadline)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
b = b[:n]
|
||||
for len(b) > 0 {
|
||||
m := copy(b, q.data[q.r&q.m:])
|
||||
q.r += m
|
||||
b = b[m:]
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func (q *byteq) write(b []byte, deadline int64) (n int, err error) {
|
||||
q.Lock()
|
||||
defer q.Unlock()
|
||||
for n < len(b) {
|
||||
nn, err := q.waitWrite(len(b[n:]), deadline)
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
bb := b[n : n+nn]
|
||||
n += nn
|
||||
for len(bb) > 0 {
|
||||
m := copy(q.data[q.w&q.m:], bb)
|
||||
q.w += m
|
||||
bb = bb[m:]
|
||||
}
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// A msgq is a queue of messages.
|
||||
type msgq struct {
|
||||
queue
|
||||
data []interface{}
|
||||
}
|
||||
|
||||
func newMsgq() *msgq {
|
||||
q := &msgq{
|
||||
data: make([]interface{}, 32),
|
||||
}
|
||||
q.init(len(q.data))
|
||||
return q
|
||||
}
|
||||
|
||||
func (q *msgq) read(deadline int64) (interface{}, error) {
|
||||
q.Lock()
|
||||
defer q.Unlock()
|
||||
n, err := q.waitRead(1, deadline)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if n == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
m := q.data[q.r&q.m]
|
||||
q.r++
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (q *msgq) write(m interface{}, deadline int64) error {
|
||||
q.Lock()
|
||||
defer q.Unlock()
|
||||
_, err := q.waitWrite(1, deadline)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
q.data[q.w&q.m] = m
|
||||
q.w++
|
||||
return nil
|
||||
}
|
||||
|
||||
// An addr is a sequence of bytes uniquely identifying a network address.
|
||||
// It is not human-readable.
|
||||
type addr string
|
||||
|
||||
// A conn is one side of a stream-based network connection.
|
||||
// That is, a stream-based network connection is a pair of cross-connected conns.
|
||||
type conn struct {
|
||||
rd *byteq
|
||||
wr *byteq
|
||||
local addr
|
||||
remote addr
|
||||
}
|
||||
|
||||
// A pktconn is one side of a packet-based network connection.
|
||||
// That is, a packet-based network connection is a pair of cross-connected pktconns.
|
||||
type pktconn struct {
|
||||
rd *msgq
|
||||
wr *msgq
|
||||
local addr
|
||||
remote addr
|
||||
}
|
||||
|
||||
// A listener accepts incoming stream-based network connections.
|
||||
type listener struct {
|
||||
rd *msgq
|
||||
local addr
|
||||
}
|
||||
|
||||
// A netFile is an open network file.
|
||||
type netFile struct {
|
||||
defaultFileImpl
|
||||
proto *netproto
|
||||
sotype int
|
||||
listener *msgq
|
||||
packet *msgq
|
||||
rd *byteq
|
||||
wr *byteq
|
||||
rddeadline int64
|
||||
wrdeadline int64
|
||||
addr Sockaddr
|
||||
raddr Sockaddr
|
||||
}
|
||||
|
||||
// A netAddr is a network address in the global listener map.
|
||||
// All the fields must have defined == operations.
|
||||
type netAddr struct {
|
||||
proto *netproto
|
||||
sotype int
|
||||
addr interface{}
|
||||
}
|
||||
|
||||
// net records the state of the network.
|
||||
// It maps a network address to the listener on that address.
|
||||
var net = struct {
|
||||
sync.Mutex
|
||||
listener map[netAddr]*netFile
|
||||
}{
|
||||
listener: make(map[netAddr]*netFile),
|
||||
}
|
||||
|
||||
// TODO(rsc): Some day, do a better job with port allocation.
|
||||
// For playground programs, incrementing is fine.
|
||||
var nextport = 2
|
||||
|
||||
// A netproto contains protocol-specific functionality
|
||||
// (one for AF_INET, one for AF_INET6 and so on).
|
||||
// It is a struct instead of an interface because the
|
||||
// implementation needs no state, and I expect to
|
||||
// add some data fields at some point.
|
||||
type netproto struct {
|
||||
bind func(*netFile, Sockaddr) error
|
||||
}
|
||||
|
||||
var netprotoAF_INET = &netproto{
|
||||
bind: func(f *netFile, sa Sockaddr) error {
|
||||
if sa == nil {
|
||||
f.addr = &SockaddrInet4{
|
||||
Port: nextport,
|
||||
Addr: [4]byte{127, 0, 0, 1},
|
||||
}
|
||||
nextport++
|
||||
return nil
|
||||
}
|
||||
addr, ok := sa.(*SockaddrInet4)
|
||||
if !ok {
|
||||
return EINVAL
|
||||
}
|
||||
addr = addr.copy().(*SockaddrInet4)
|
||||
if addr.Port == 0 {
|
||||
addr.Port = nextport
|
||||
nextport++
|
||||
}
|
||||
f.addr = addr
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var netprotos = map[int]*netproto{
|
||||
AF_INET: netprotoAF_INET,
|
||||
}
|
||||
|
||||
// These functions implement the usual BSD socket operations.
|
||||
|
||||
func (f *netFile) bind(sa Sockaddr) error {
|
||||
if f.addr != nil {
|
||||
return EISCONN
|
||||
}
|
||||
if err := f.proto.bind(f, sa); err != nil {
|
||||
return err
|
||||
}
|
||||
if f.sotype == SOCK_DGRAM {
|
||||
_, ok := net.listener[netAddr{f.proto, f.sotype, f.addr.key()}]
|
||||
if ok {
|
||||
f.addr = nil
|
||||
return EADDRINUSE
|
||||
}
|
||||
net.listener[netAddr{f.proto, f.sotype, f.addr.key()}] = f
|
||||
f.packet = newMsgq()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *netFile) listen(backlog int) error {
|
||||
net.Lock()
|
||||
defer net.Unlock()
|
||||
if f.listener != nil {
|
||||
return EINVAL
|
||||
}
|
||||
_, ok := net.listener[netAddr{f.proto, f.sotype, f.addr.key()}]
|
||||
if ok {
|
||||
return EADDRINUSE
|
||||
}
|
||||
net.listener[netAddr{f.proto, f.sotype, f.addr.key()}] = f
|
||||
f.listener = newMsgq()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *netFile) accept() (fd int, sa Sockaddr, err error) {
|
||||
msg, err := f.listener.read(f.readDeadline())
|
||||
if err != nil {
|
||||
return -1, nil, err
|
||||
}
|
||||
newf, ok := msg.(*netFile)
|
||||
if !ok {
|
||||
// must be eof
|
||||
return -1, nil, EAGAIN
|
||||
}
|
||||
return newFD(newf), newf.raddr.copy(), nil
|
||||
}
|
||||
|
||||
func (f *netFile) connect(sa Sockaddr) error {
|
||||
if past(f.writeDeadline()) {
|
||||
return EAGAIN
|
||||
}
|
||||
if f.addr == nil {
|
||||
if err := f.bind(nil); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
net.Lock()
|
||||
if sa == nil {
|
||||
net.Unlock()
|
||||
return EINVAL
|
||||
}
|
||||
sa = sa.copy()
|
||||
if f.raddr != nil {
|
||||
net.Unlock()
|
||||
return EISCONN
|
||||
}
|
||||
if f.sotype == SOCK_DGRAM {
|
||||
net.Unlock()
|
||||
f.raddr = sa
|
||||
return nil
|
||||
}
|
||||
if f.listener != nil {
|
||||
net.Unlock()
|
||||
return EISCONN
|
||||
}
|
||||
l, ok := net.listener[netAddr{f.proto, f.sotype, sa.key()}]
|
||||
if !ok {
|
||||
net.Unlock()
|
||||
return ECONNREFUSED
|
||||
}
|
||||
f.raddr = sa
|
||||
f.rd = newByteq()
|
||||
f.wr = newByteq()
|
||||
newf := &netFile{
|
||||
proto: f.proto,
|
||||
sotype: f.sotype,
|
||||
addr: f.raddr,
|
||||
raddr: f.addr,
|
||||
rd: f.wr,
|
||||
wr: f.rd,
|
||||
}
|
||||
net.Unlock()
|
||||
l.listener.write(newf, f.writeDeadline())
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *netFile) read(b []byte) (int, error) {
|
||||
if f.rd == nil {
|
||||
if f.raddr != nil {
|
||||
n, _, err := f.recvfrom(b, 0)
|
||||
return n, err
|
||||
}
|
||||
return 0, ENOTCONN
|
||||
}
|
||||
return f.rd.read(b, f.readDeadline())
|
||||
}
|
||||
|
||||
func (f *netFile) write(b []byte) (int, error) {
|
||||
if f.wr == nil {
|
||||
if f.raddr != nil {
|
||||
err := f.sendto(b, 0, f.raddr)
|
||||
var n int
|
||||
if err == nil {
|
||||
n = len(b)
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
return 0, ENOTCONN
|
||||
}
|
||||
return f.wr.write(b, f.writeDeadline())
|
||||
}
|
||||
|
||||
type pktmsg struct {
|
||||
buf []byte
|
||||
addr Sockaddr
|
||||
}
|
||||
|
||||
func (f *netFile) recvfrom(p []byte, flags int) (n int, from Sockaddr, err error) {
|
||||
if f.sotype != SOCK_DGRAM {
|
||||
return 0, nil, EINVAL
|
||||
}
|
||||
if f.packet == nil {
|
||||
return 0, nil, ENOTCONN
|
||||
}
|
||||
msg1, err := f.packet.read(f.readDeadline())
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
msg, ok := msg1.(*pktmsg)
|
||||
if !ok {
|
||||
return 0, nil, EAGAIN
|
||||
}
|
||||
return copy(p, msg.buf), msg.addr, nil
|
||||
}
|
||||
|
||||
func (f *netFile) sendto(p []byte, flags int, to Sockaddr) error {
|
||||
if f.sotype != SOCK_DGRAM {
|
||||
return EINVAL
|
||||
}
|
||||
if f.packet == nil {
|
||||
if err := f.bind(nil); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
net.Lock()
|
||||
if to == nil {
|
||||
net.Unlock()
|
||||
return EINVAL
|
||||
}
|
||||
to = to.copy()
|
||||
l, ok := net.listener[netAddr{f.proto, f.sotype, to.key()}]
|
||||
if !ok || l.packet == nil {
|
||||
net.Unlock()
|
||||
return ECONNREFUSED
|
||||
}
|
||||
net.Unlock()
|
||||
msg := &pktmsg{
|
||||
buf: make([]byte, len(p)),
|
||||
addr: f.addr,
|
||||
}
|
||||
copy(msg.buf, p)
|
||||
l.packet.write(msg, f.writeDeadline())
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *netFile) close() error {
|
||||
if f.listener != nil {
|
||||
f.listener.close()
|
||||
}
|
||||
if f.packet != nil {
|
||||
f.packet.close()
|
||||
}
|
||||
if f.rd != nil {
|
||||
f.rd.close()
|
||||
}
|
||||
if f.wr != nil {
|
||||
f.wr.close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func fdToNetFile(fd int) (*netFile, error) {
|
||||
f, err := fdToFile(fd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
impl := f.impl
|
||||
netf, ok := impl.(*netFile)
|
||||
if !ok {
|
||||
return nil, EINVAL
|
||||
}
|
||||
return netf, nil
|
||||
}
|
||||
|
||||
func Socket(proto, sotype, unused int) (fd int, err error) {
|
||||
p := netprotos[proto]
|
||||
if p == nil {
|
||||
return -1, EPROTONOSUPPORT
|
||||
}
|
||||
if sotype != SOCK_STREAM && sotype != SOCK_DGRAM {
|
||||
return -1, ESOCKTNOSUPPORT
|
||||
}
|
||||
f := &netFile{
|
||||
proto: p,
|
||||
sotype: sotype,
|
||||
}
|
||||
return newFD(f), nil
|
||||
}
|
||||
|
||||
func Bind(fd int, sa Sockaddr) error {
|
||||
f, err := fdToNetFile(fd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return f.bind(sa)
|
||||
}
|
||||
|
||||
func StopIO(fd int) error {
|
||||
f, err := fdToNetFile(fd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
f.close()
|
||||
return nil
|
||||
}
|
||||
|
||||
func Listen(fd int, backlog int) error {
|
||||
f, err := fdToNetFile(fd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return f.listen(backlog)
|
||||
}
|
||||
|
||||
func Accept(fd int) (newfd int, sa Sockaddr, err error) {
|
||||
f, err := fdToNetFile(fd)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
return f.accept()
|
||||
}
|
||||
|
||||
func Getsockname(fd int) (sa Sockaddr, err error) {
|
||||
f, err := fdToNetFile(fd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if f.addr == nil {
|
||||
return nil, ENOTCONN
|
||||
}
|
||||
return f.addr.copy(), nil
|
||||
}
|
||||
|
||||
func Getpeername(fd int) (sa Sockaddr, err error) {
|
||||
f, err := fdToNetFile(fd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if f.raddr == nil {
|
||||
return nil, ENOTCONN
|
||||
}
|
||||
return f.raddr.copy(), nil
|
||||
}
|
||||
|
||||
func Connect(fd int, sa Sockaddr) error {
|
||||
f, err := fdToNetFile(fd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return f.connect(sa)
|
||||
}
|
||||
|
||||
func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) {
|
||||
f, err := fdToNetFile(fd)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
return f.recvfrom(p, flags)
|
||||
}
|
||||
|
||||
func Sendto(fd int, p []byte, flags int, to Sockaddr) error {
|
||||
f, err := fdToNetFile(fd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return f.sendto(p, flags, to)
|
||||
}
|
||||
|
||||
func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn, recvflags int, from Sockaddr, err error) {
|
||||
f, err := fdToNetFile(fd)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
n, from, err = f.recvfrom(p, flags)
|
||||
return
|
||||
}
|
||||
|
||||
func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) error {
|
||||
_, err := SendmsgN(fd, p, oob, to, flags)
|
||||
return err
|
||||
}
|
||||
|
||||
func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) {
|
||||
f, err := fdToNetFile(fd)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
switch f.sotype {
|
||||
case SOCK_STREAM:
|
||||
n, err = f.write(p)
|
||||
case SOCK_DGRAM:
|
||||
n = len(p)
|
||||
err = f.sendto(p, flags, to)
|
||||
}
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func GetsockoptInt(fd, level, opt int) (value int, err error) {
|
||||
f, err := fdToNetFile(fd)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
switch {
|
||||
case level == SOL_SOCKET && opt == SO_TYPE:
|
||||
return f.sotype, nil
|
||||
}
|
||||
return 0, ENOTSUP
|
||||
}
|
||||
|
||||
func SetsockoptInt(fd, level, opt int, value int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func SetsockoptByte(fd, level, opt int, value byte) error {
|
||||
_, err := fdToNetFile(fd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return ENOTSUP
|
||||
}
|
||||
|
||||
func SetsockoptLinger(fd, level, opt int, l *Linger) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func SetReadDeadline(fd int, t int64) error {
|
||||
f, err := fdToNetFile(fd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
atomic.StoreInt64(&f.rddeadline, t)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *netFile) readDeadline() int64 {
|
||||
return atomic.LoadInt64(&f.rddeadline)
|
||||
}
|
||||
|
||||
func SetWriteDeadline(fd int, t int64) error {
|
||||
f, err := fdToNetFile(fd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
atomic.StoreInt64(&f.wrdeadline, t)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *netFile) writeDeadline() int64 {
|
||||
return atomic.LoadInt64(&f.wrdeadline)
|
||||
}
|
||||
|
||||
func Shutdown(fd int, how int) error {
|
||||
f, err := fdToNetFile(fd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch how {
|
||||
case SHUT_RD:
|
||||
f.rd.close()
|
||||
case SHUT_WR:
|
||||
f.wr.close()
|
||||
case SHUT_RDWR:
|
||||
f.rd.close()
|
||||
f.wr.close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func SetsockoptICMPv6Filter(fd, level, opt int, filter *ICMPv6Filter) error { panic("SetsockoptICMPv") }
|
||||
func SetsockoptIPMreq(fd, level, opt int, mreq *IPMreq) error { panic("SetsockoptIPMreq") }
|
||||
func SetsockoptIPv6Mreq(fd, level, opt int, mreq *IPv6Mreq) error { panic("SetsockoptIPv") }
|
||||
func SetsockoptInet4Addr(fd, level, opt int, value [4]byte) error { panic("SetsockoptInet") }
|
||||
func SetsockoptString(fd, level, opt int, s string) error { panic("SetsockoptString") }
|
||||
func SetsockoptTimeval(fd, level, opt int, tv *Timeval) error { panic("SetsockoptTimeval") }
|
||||
func Socketpair(domain, typ, proto int) (fd [2]int, err error) { panic("Socketpair") }
|
||||
|
||||
func SetNonblock(fd int, nonblocking bool) error { return nil }
|
||||
Reference in New Issue
Block a user