-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathconn_unix.go
149 lines (133 loc) · 2.64 KB
/
conn_unix.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/**
* @Author: llh
* @Date: 2019-06-01 15:08:12
* @Last Modified by: llh
*/
// +build darwin netbsd freebsd openbsd dragonfly linux
package tfg
import (
"golang.org/x/sys/unix"
"net"
"sync"
"sync/atomic"
"syscall"
"time"
)
const (
AVAILABLEWRITE uint32 = iota
UNAVAILABLEWRITE
CONN_CLOSE uint32 = iota
CONN_OPEN
CONN_NEEE_CLOSED
)
type Conn interface {
Write(b []byte) (int, error)
Close() error
LocalAddr() net.Addr
RemoteAddr() net.Addr
SetDeadline(t time.Time) error
isNeedClose() bool
}
type conn struct {
fd int
sa unix.Sockaddr // remote socket address
laddr net.Addr
raddr net.Addr
s *server
indexPollEvent int
status uint32
once sync.Once
}
func (c *conn) setConnOpened() {
atomic.StoreUint32(&c.status, CONN_OPEN)
}
func (c *conn) setConnNeedClosed() {
atomic.StoreUint32(&c.status, CONN_NEEE_CLOSED)
}
func (c *conn) setConnClosed() {
atomic.StoreUint32(&c.status, CONN_CLOSE)
}
func (c *conn) isNeedClose() bool {
if atomic.LoadUint32(&c.status) == CONN_CLOSE {
return true
}
return false
}
func (c *conn) ok() bool { return c != nil && c.fd != 0 }
func (c *conn) Write(b []byte) (int, error) {
if b == nil || len(b) == 0 {
return 0, ErrInputConnWrite
}
var n int
var err error
for {
if atomic.LoadUint32(&c.s.isWrite) == AVAILABLEWRITE {
n, err = unix.Write(c.fd, b)
if err != nil {
if err == syscall.EAGAIN {
c.s.setUnAvailableWrite()
continue
}
return 0, c.Close()
}
break
}
}
return n, nil
}
func (c *conn) Close() error {
var err error
c.once.Do(func() {
c.s.connManager.delete(c.fd)
pollEvent := c.s.pollEvents[c.indexPollEvent]
pollEvent.poll.remove(c.fd)
if err = unix.Close(c.fd); err != nil {
return
}
c.s.connManager.decConnCount()
pollEvent.decConnCount()
c.setConnClosed()
c.s.connManager.connCache.Put(c)
})
return err
}
func (c *conn) LocalAddr() net.Addr {
if !c.ok() {
return nil
}
return c.laddr
}
func (c *conn) RemoteAddr() net.Addr {
if !c.ok() {
return nil
}
return c.raddr
}
func (c *conn) SetDeadline(t time.Time) error {
return nil
}
func (c *conn) saToAddr(sa unix.Sockaddr) net.Addr {
var a net.Addr
switch sa := sa.(type) {
case *unix.SockaddrInet4:
a = &net.TCPAddr{
IP: append([]byte{}, sa.Addr[:]...),
Port: sa.Port,
}
case *unix.SockaddrInet6:
var zone string
if sa.ZoneId != 0 {
if ifi, err := net.InterfaceByIndex(int(sa.ZoneId)); err == nil {
zone = ifi.Name
}
}
if zone == "" && sa.ZoneId != 0 {
}
a = &net.TCPAddr{
IP: append([]byte{}, sa.Addr[:]...),
Port: sa.Port,
Zone: zone,
}
}
return a
}