github.com/godevsig/adaptiveservice@v0.9.23/chantransport.go (about) 1 package adaptiveservice 2 3 import ( 4 "fmt" 5 "io" 6 "net" 7 "reflect" 8 "unsafe" 9 10 "github.com/barkimedes/go-deepcopy" 11 ) 12 13 type chanTransportMsg struct { 14 srcChan chan interface{} 15 msg interface{} 16 } 17 18 type handshake struct { 19 connClose chan struct{} 20 serverChanInfo chan chan *chanTransportMsg 21 } 22 23 // server main receive chan transport. 24 type chanTransport struct { 25 svc *service 26 acceptChan chan handshake 27 closed chan struct{} 28 } 29 30 func (svc *service) newChanTransport() (*chanTransport, error) { 31 ct := &chanTransport{ 32 svc: svc, 33 acceptChan: make(chan handshake), 34 closed: make(chan struct{}), 35 } 36 go ct.receiver() 37 regServiceChan(svc.publisherName, svc.serviceName, ct) 38 svc.s.lg.Infof("service %s %s listening on internal channel", svc.publisherName, svc.serviceName) 39 return ct, nil 40 } 41 42 func (ct *chanTransport) close() { 43 close(ct.closed) 44 delServiceChan(ct.svc.publisherName, ct.svc.serviceName) 45 } 46 47 type chanServerStream struct { 48 Context 49 netconn chanconn 50 connClose *chan struct{} 51 srcChan chan interface{} 52 privateChan chan interface{} // dedicated to the client 53 timeouter 54 } 55 56 func (ss *chanServerStream) GetNetconn() Netconn { 57 return ss.netconn 58 } 59 60 func (ss *chanServerStream) Send(msg interface{}) error { 61 if *ss.connClose == nil { 62 return io.EOF 63 } 64 ss.srcChan <- msg 65 return nil 66 } 67 68 func (ss *chanServerStream) Recv(msgPtr interface{}) (err error) { 69 connClose := *ss.connClose 70 if *ss.connClose == nil { 71 return io.EOF 72 } 73 rptr := reflect.ValueOf(msgPtr) 74 if msgPtr != nil && (rptr.Kind() != reflect.Ptr || rptr.IsNil()) { 75 panic("not a pointer or nil pointer") 76 } 77 78 select { 79 case <-connClose: 80 return io.EOF 81 case <-ss.timeouter.timeoutChan(): 82 return ErrRecvTimeout 83 case msg := <-ss.privateChan: 84 if err, ok := msg.(error); ok { 85 return err 86 } 87 if msgPtr == nil { // msgPtr is nil 88 return nil // user just looks at error, no error here 89 } 90 91 rv := rptr.Elem() 92 defer func() { 93 if e := recover(); e != nil { 94 err = fmt.Errorf("message type mismatch: %v", e) 95 } 96 }() 97 rv.Set(reflect.ValueOf(msg)) 98 } 99 100 return 101 } 102 103 func (ss *chanServerStream) SendRecv(msgSnd interface{}, msgRcvPtr interface{}) error { 104 if err := ss.Send(msgSnd); err != nil { 105 return err 106 } 107 if err := ss.Recv(msgRcvPtr); err != nil { 108 return err 109 } 110 return nil 111 } 112 113 type chanAddr uint64 114 115 type chanconn struct { 116 localAddr chanAddr 117 remoteAddr chanAddr 118 } 119 120 func (cc chanconn) Close() error { 121 return nil 122 } 123 124 func (cc chanconn) LocalAddr() net.Addr { 125 return cc.localAddr 126 } 127 128 func (cc chanconn) RemoteAddr() net.Addr { 129 return cc.remoteAddr 130 } 131 132 func (ca chanAddr) Network() string { 133 return "chan" 134 } 135 136 func (ca chanAddr) String() string { 137 return fmt.Sprintf("0x%x", uint64(ca)) 138 } 139 140 func (ct *chanTransport) receiver() { 141 mq := ct.svc.s.mq 142 lg := ct.svc.s.lg 143 144 for { 145 select { 146 case <-ct.closed: 147 return 148 case hs := <-ct.acceptChan: 149 go func() { 150 connClose := hs.connClose 151 recvChan := make(chan *chanTransportMsg, ct.svc.s.qsize) 152 hs.serverChanInfo <- recvChan 153 cc := chanconn{ 154 localAddr: chanAddr(uintptr(unsafe.Pointer(&ct.closed))), 155 remoteAddr: chanAddr(uintptr(unsafe.Pointer(&connClose))), 156 } 157 lg.Debugf("%s %s new chan connection from: %s", ct.svc.publisherName, ct.svc.serviceName, cc.RemoteAddr().String()) 158 if ct.svc.fnOnConnect != nil { 159 lg.Debugf("%s %s on connect", ct.svc.publisherName, ct.svc.serviceName) 160 if ct.svc.fnOnConnect(cc) { 161 return 162 } 163 } 164 defer func() { 165 if ct.svc.fnOnDisconnect != nil { 166 lg.Debugf("%s %s on disconnect", ct.svc.publisherName, ct.svc.serviceName) 167 ct.svc.fnOnDisconnect(cc) 168 } 169 lg.Debugf("%s %s chan connection disconnected: %s", ct.svc.publisherName, ct.svc.serviceName, cc.RemoteAddr().String()) 170 }() 171 ssMap := make(map[chan interface{}]*chanServerStream) 172 for { 173 select { 174 case <-connClose: 175 connClose = nil 176 return 177 case tm := <-recvChan: 178 ss := ssMap[tm.srcChan] 179 if ss == nil { 180 ss = &chanServerStream{ 181 netconn: cc, 182 connClose: &connClose, 183 Context: &contextImpl{}, 184 srcChan: tm.srcChan, 185 privateChan: make(chan interface{}, cap(tm.srcChan)), 186 } 187 ssMap[tm.srcChan] = ss 188 if ct.svc.fnOnNewStream != nil { 189 lg.Debugf("%s %s on new stream", ct.svc.publisherName, ct.svc.serviceName) 190 ct.svc.fnOnNewStream(ss) 191 } 192 } 193 if ct.svc.canHandle(tm.msg) { 194 mm := &metaKnownMsg{ 195 stream: ss, 196 msg: tm.msg.(KnownMessage), 197 } 198 mq.putMetaMsg(mm) 199 } else { 200 ss.privateChan <- tm.msg 201 } 202 } 203 } 204 }() 205 } 206 } 207 } 208 209 // below for client side 210 211 type chanClientStream struct { 212 conn *chanConnection 213 msgChan chan interface{} 214 timeouter 215 } 216 217 type clientChanTransport struct { 218 owner *Client 219 ct *chanTransport 220 } 221 222 // chan connection for client. 223 type chanConnection struct { 224 Stream 225 cct *clientChanTransport 226 connClose chan struct{} 227 serverChan chan *chanTransportMsg // link to server receive chan 228 } 229 230 // newConnection creates a new connection to the chan transport for client. 231 func (cct *clientChanTransport) newConnection() *chanConnection { 232 connClose := make(chan struct{}) 233 serverChanInfo := make(chan chan *chanTransportMsg) 234 235 cct.ct.acceptChan <- handshake{connClose, serverChanInfo} 236 conn := &chanConnection{ 237 cct: cct, 238 connClose: connClose, 239 serverChan: <-serverChanInfo, 240 } 241 conn.Stream = conn.NewStream() 242 return conn 243 } 244 245 // NewStream creates a new client stream. 246 func (conn *chanConnection) NewStream() Stream { 247 cs := &chanClientStream{ 248 conn: conn, 249 msgChan: make(chan interface{}, cap(conn.serverChan)), 250 } 251 return cs 252 } 253 254 func (conn *chanConnection) Close() { 255 close(conn.connClose) 256 } 257 258 func (cs *chanClientStream) GetNetconn() Netconn { 259 cc := chanconn{ 260 localAddr: chanAddr(uintptr(unsafe.Pointer(&cs.conn.connClose))), 261 remoteAddr: chanAddr(uintptr(unsafe.Pointer(&cs.conn.cct.ct.closed))), 262 } 263 return cc 264 } 265 266 func (cs *chanClientStream) Send(msg interface{}) error { 267 if cs.msgChan == nil { 268 return io.EOF 269 } 270 if cs.conn.cct.owner.deepCopy { 271 msg = deepcopy.MustAnything(msg) 272 } 273 cs.conn.serverChan <- &chanTransportMsg{srcChan: cs.msgChan, msg: msg} 274 return nil 275 } 276 277 func (cs *chanClientStream) Recv(msgPtr interface{}) (err error) { 278 msgChan := cs.msgChan 279 if cs.msgChan == nil { 280 return io.EOF 281 } 282 rptr := reflect.ValueOf(msgPtr) 283 if msgPtr != nil && (rptr.Kind() != reflect.Ptr || rptr.IsNil()) { 284 panic("not a pointer or nil pointer") 285 } 286 287 select { 288 case <-cs.timeouter.timeoutChan(): 289 return ErrRecvTimeout 290 case msg := <-msgChan: 291 if err, ok := msg.(error); ok { // message handler returned error 292 if err == io.EOF { 293 cs.msgChan = nil 294 } 295 return err 296 } 297 if msgPtr == nil { // msgPtr is nil 298 return nil // user just looks at error, no error here 299 } 300 301 rv := rptr.Elem() 302 mrv := reflect.ValueOf(msg) 303 if rv.Kind() != reflect.Ptr && mrv.Kind() == reflect.Ptr { 304 mrv = mrv.Elem() 305 } 306 defer func() { 307 if e := recover(); e != nil { 308 err = fmt.Errorf("message type mismatch: %v", e) 309 } 310 }() 311 rv.Set(mrv) 312 } 313 314 return 315 } 316 317 func (cs *chanClientStream) SendRecv(msgSnd interface{}, msgRcvPtr interface{}) error { 318 if err := cs.Send(msgSnd); err != nil { 319 return err 320 } 321 if err := cs.Recv(msgRcvPtr); err != nil { 322 return err 323 } 324 return nil 325 }