github.com/weedge/lib@v0.0.0-20230424045628-a36dcc1d90e4/poller/conn.go (about) 1 package poller 2 3 import ( 4 "sync/atomic" 5 "syscall" 6 "time" 7 8 "github.com/weedge/lib/log" 9 ) 10 11 // Conn keepalive connection 12 type Conn struct { 13 server *Server // server reference 14 pollerFD int // event poller File descriptor 15 fd int // socket connect File descriptor 16 addr string // peer address 17 buffer *Buffer // Read the buffer 18 lastReadTime time.Time // Time of last read 19 data interface{} // Business custom data, used as an extension 20 } 21 22 // newConn create tcp connection 23 func newConn(pollerFD, fd int, addr string, server *Server) *Conn { 24 return &Conn{ 25 server: server, 26 pollerFD: pollerFD, 27 fd: fd, 28 addr: addr, 29 buffer: NewBuffer(server.readBufferPool.Get().([]byte)), 30 lastReadTime: time.Now(), 31 } 32 } 33 34 // GetFd gets the file descriptor 35 func (c *Conn) GetFd() int { 36 return c.fd 37 } 38 39 // GetAddr gets the client address 40 func (c *Conn) GetAddr() string { 41 return c.addr 42 } 43 44 // GetAddr gets the conn buff 45 func (c *Conn) GetBuff() *Buffer { 46 return c.buffer 47 } 48 49 // Read 50 // block read bytes until read readBufferLen bytes from connect fd 51 func (c *Conn) Read() error { 52 c.lastReadTime = time.Now() 53 fd := c.GetFd() 54 for { 55 err := c.buffer.ReadFromFD(fd) 56 if err != nil { 57 // There is no data to read in the buffer 58 if err == syscall.EAGAIN { 59 return nil 60 } 61 return err 62 } 63 64 err = c.MsgFilter() 65 if err != nil { 66 log.Errorf("msg filter err:%s", err.Error()) 67 continue 68 } 69 } 70 } 71 72 // MsgFilter 73 // use msg decoder and onmessage handle 74 func (c *Conn) MsgFilter() (err error) { 75 if c.server.options.decoder == nil { 76 c.server.handler.OnMessage(c, c.buffer.ReadAll()) 77 return 78 } 79 80 val, err := c.server.options.decoder.Decode(c.buffer) 81 if err != nil { 82 return 83 } 84 c.server.handler.OnMessage(c, val) 85 86 return 87 } 88 89 // AsyncBlockRead trigger a async kernerl block read from connect socket fd to buff 90 func (c *Conn) AsyncBlockRead() { 91 c.lastReadTime = time.Now() 92 fd := c.GetFd() 93 ring := c.server.GetIoUring(fd) 94 c.buffer.AsyncReadFromFD(fd, ring, c.getReadCallback()) 95 } 96 97 func (c *Conn) getReadCallback() EventCallBack { 98 return func(e *eventInfo) (err error) { 99 err = c.MsgFilter() 100 return 101 } 102 } 103 104 // processReadEvent 105 // process connect read complete event 106 // add async block read bytes event until read readBufferLen bytes from connect fd 107 func (c *Conn) processReadEvent(e *eventInfo) (err error) { 108 err = e.cb(e) 109 if err != nil { 110 // There is no data to read in the buffer 111 if err == syscall.EAGAIN { 112 return nil 113 } 114 return err 115 } 116 // if un use poll in ready, need add read event op again 117 c.AsyncBlockRead() 118 return 119 } 120 121 // AsyncBlockWrite 122 // async block write bytes 123 func (c *Conn) AsyncBlockWrite(bytes []byte) { 124 ring := c.server.GetIoUring(c.fd) 125 ring.addSendSqe(noOpsEventCb, c.fd, bytes, len(bytes), 0) 126 } 127 128 func (c *Conn) processWirteEvent(e *eventInfo) (err error) { 129 if e.cqe.Res < 0 { 130 err = ErrIOUringWriteFail 131 return 132 } 133 134 err = e.cb(e) 135 if err != nil { 136 return 137 } 138 139 return 140 } 141 142 // Write Writer impl 143 // notice: if use iouring async write to fd, return 0, nil 144 func (c *Conn) Write(bytes []byte) (int, error) { 145 if c.server.options.ioMode == IOModeUring { 146 c.AsyncBlockWrite(bytes) 147 return 0, nil 148 } 149 150 return syscall.Write(c.fd, bytes) 151 } 152 153 // WriteWithEncoder 154 // write with encoder, encode bytes to writer 155 func (c *Conn) WriteWithEncoder(bytes []byte) error { 156 return c.server.options.encoder.EncodeToWriter(c, bytes) 157 } 158 159 // Close Closes the connection 160 func (c *Conn) Close() { 161 // Remove from the file descriptor that epoll is listening for 162 err := closeFD(c.pollerFD, c.fd) 163 if err != nil { 164 log.Error(err) 165 } 166 c.CloseConnect() 167 } 168 169 func (c *Conn) CloseConnect() { 170 // Remove conn from conns 171 c.server.conns.Delete(c.fd) 172 // Return the cache 173 c.server.readBufferPool.Put(c.buffer.buf) 174 // Subtract one from the number of connections 175 atomic.AddInt64(&c.server.connsNum, -1) 176 } 177 178 // CloseRead closes connection 179 func (c *Conn) CloseRead() error { 180 err := closeFDRead(int(c.fd)) 181 if err != nil { 182 log.Error(err) 183 return err 184 } 185 return nil 186 } 187 188 // GetData gets the data 189 func (c *Conn) GetData() interface{} { 190 return c.data 191 } 192 193 // SetData sets the data 194 func (c *Conn) SetData(data interface{}) { 195 c.data = data 196 }