github.com/codingeasygo/util@v0.0.0-20231206062002-1ce2f004b7d9/xio/processor.go (about) 1 package xio 2 3 import ( 4 "fmt" 5 "io" 6 "net" 7 "strings" 8 "sync" 9 ) 10 11 // Processor is interface for process connection 12 type Processor interface { 13 ProcConn(conn io.ReadWriteCloser) (err error) 14 } 15 16 // ProcessorF is func to implement Processor 17 type ProcessorF func(conn io.ReadWriteCloser) (err error) 18 19 // ProcConn is process connection by func 20 func (p ProcessorF) ProcConn(conn io.ReadWriteCloser) (err error) { 21 err = p(conn) 22 return 23 } 24 25 // ErrAsyncRunning is error for async running on PipeConn 26 var ErrAsyncRunning = fmt.Errorf("asynced") 27 28 // Piper is interface for process pipe connection 29 type Piper interface { 30 PipeConn(conn io.ReadWriteCloser, target string) (err error) 31 Close() (err error) 32 } 33 34 // PiperF is func to implement Piper 35 type PiperF func(conn io.ReadWriteCloser, target string) (err error) 36 37 func (p PiperF) PipeConn(conn io.ReadWriteCloser, target string) (err error) { 38 err = p(conn, target) 39 return 40 } 41 42 func (p PiperF) Close() (err error) { 43 return 44 } 45 46 // PiperDialer is interface for implement piper dialer 47 type PiperDialer interface { 48 DialPiper(uri string, bufferSize int) (raw Piper, err error) 49 } 50 51 // PiperDialerF is func to implement PiperDialer 52 type PiperDialerF func(uri string, bufferSize int) (raw Piper, err error) 53 54 // DialPiper will dial one piper by uri 55 func (p PiperDialerF) DialPiper(uri string, bufferSize int) (raw Piper, err error) { 56 raw, err = p(uri, bufferSize) 57 return 58 } 59 60 // NetPiper is Piper implement by net.Dial 61 type NetPiper struct { 62 net.Conn 63 CopyPiper 64 } 65 66 // DialNetPiper will return new NetPiper by net.Dial 67 func DialNetPiper(uri string, bufferSize int) (piper Piper, err error) { 68 var network, address string 69 parts := strings.SplitN(uri, "://", 2) 70 if len(parts) < 2 { 71 network = "tcp" 72 address = parts[0] 73 } else { 74 network = parts[0] 75 address = parts[1] 76 } 77 conn, err := net.Dial(network, address) 78 if err == nil { 79 piper = &NetPiper{ 80 Conn: conn, 81 CopyPiper: CopyPiper{ 82 ReadWriteCloser: conn, 83 BufferSize: bufferSize, 84 }, 85 } 86 } 87 return 88 } 89 90 // CopyPiper is Piper implement by copy 91 type CopyPiper struct { 92 io.ReadWriteCloser 93 BufferSize int 94 XX string 95 } 96 97 // NewCopyPiper will return new CopyPiper 98 func NewCopyPiper(raw io.ReadWriteCloser, bufferSize int) (piper *CopyPiper) { 99 piper = &CopyPiper{ReadWriteCloser: raw, BufferSize: bufferSize} 100 return 101 } 102 103 // PipeConn will pipe connection to raw 104 func (c *CopyPiper) PipeConn(conn io.ReadWriteCloser, target string) (err error) { 105 wc := make(chan int, 1) 106 go func() { 107 var readErr error 108 if to, ok := conn.(io.WriterTo); ok { 109 _, readErr = to.WriteTo(c.ReadWriteCloser) 110 } else if from, ok := c.ReadWriteCloser.(io.ReaderFrom); ok { 111 _, readErr = from.ReadFrom(conn) 112 } else { 113 _, readErr = io.CopyBuffer(c.ReadWriteCloser, conn, make([]byte, c.BufferSize)) 114 } 115 c.ReadWriteCloser.Close() 116 wc <- 1 117 if err == nil { 118 err = readErr 119 } 120 }() 121 { 122 var writeErr error 123 if from, ok := conn.(io.ReaderFrom); ok { 124 _, writeErr = from.ReadFrom(c.ReadWriteCloser) 125 } else if to, ok := c.ReadWriteCloser.(io.WriterTo); ok { 126 _, writeErr = to.WriteTo(conn) 127 } else { 128 _, writeErr = io.CopyBuffer(conn, c.ReadWriteCloser, make([]byte, c.BufferSize)) 129 } 130 conn.Close() 131 if err == nil { 132 err = writeErr 133 } 134 } 135 <-wc 136 close(wc) 137 return 138 } 139 140 // ByteDistributeProcessor is distribute processor by prefix read first byte 141 type ByteDistributeProcessor struct { 142 Next map[byte]Processor 143 conns map[string]io.ReadWriteCloser 144 listeners map[string]net.Listener 145 locker sync.RWMutex 146 } 147 148 // NewByteDistributeProcessor will return new processor 149 func NewByteDistributeProcessor() (processor *ByteDistributeProcessor) { 150 processor = &ByteDistributeProcessor{ 151 Next: map[byte]Processor{}, 152 conns: map[string]io.ReadWriteCloser{}, 153 listeners: map[string]net.Listener{}, 154 locker: sync.RWMutex{}, 155 } 156 return 157 } 158 159 // AddProcessor will add processor by mode 160 func (b *ByteDistributeProcessor) AddProcessor(m byte, procesor Processor) { 161 b.Next[m] = procesor 162 } 163 164 // RemoveProcessor will remove processor by mode 165 func (b *ByteDistributeProcessor) RemoveProcessor(m byte) { 166 delete(b.Next, m) 167 } 168 169 // ProcAccept will loop accept net.Conn and async call ProcConn 170 func (b *ByteDistributeProcessor) ProcAccept(listener net.Listener) (err error) { 171 b.locker.Lock() 172 b.listeners[fmt.Sprintf("%p", listener)] = listener 173 b.locker.Unlock() 174 defer func() { 175 b.locker.Lock() 176 delete(b.listeners, fmt.Sprintf("%p", listener)) 177 b.locker.Unlock() 178 }() 179 procConn := func(c net.Conn) { 180 xerr := b.ProcConn(c) 181 if xerr != ErrAsyncRunning { 182 c.Close() 183 } 184 } 185 var conn net.Conn 186 for { 187 conn, err = listener.Accept() 188 if err != nil { 189 break 190 } 191 go procConn(conn) 192 } 193 return 194 } 195 196 // ProcConn will process connection by prefix reader and distribute to next processor 197 func (b *ByteDistributeProcessor) ProcConn(conn io.ReadWriteCloser) (err error) { 198 b.locker.Lock() 199 b.conns[fmt.Sprintf("%p", conn)] = conn 200 b.locker.Unlock() 201 defer func() { 202 b.locker.Lock() 203 delete(b.conns, fmt.Sprintf("%p", conn)) 204 b.locker.Unlock() 205 }() 206 preConn := NewPrefixReadWriteCloser(conn) 207 pre, err := preConn.PreRead(1) 208 if err != nil { 209 return 210 } 211 processor := b.Next[pre[0]] 212 if processor == nil { 213 processor = b.Next['*'] 214 } 215 if processor == nil { 216 err = fmt.Errorf("processor is not exist by %v", pre[0]) 217 return 218 } 219 err = processor.ProcConn(preConn) 220 return 221 } 222 223 // Close will close all listener and connection 224 func (b *ByteDistributeProcessor) Close() (err error) { 225 b.locker.Lock() 226 for _, conn := range b.conns { 227 conn.Close() 228 } 229 for _, listener := range b.listeners { 230 listener.Close() 231 } 232 b.locker.Unlock() 233 return 234 }