nanomsg.org/go/mangos/v2@v2.0.9-0.20200203084354-8a092611e461/protocol/rep/rep.go (about) 1 // Copyright 2019 The Mangos Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use file except in compliance with the License. 5 // You may obtain a copy of the license at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Package rep implements the REP protocol, which is the response side of 16 // the request/response pattern. (REQ is the request.) 17 package rep 18 19 import ( 20 "sync" 21 "time" 22 23 "nanomsg.org/go/mangos/v2/protocol" 24 ) 25 26 // Protocol identity information. 27 const ( 28 Self = protocol.ProtoRep 29 Peer = protocol.ProtoReq 30 SelfName = "rep" 31 PeerName = "req" 32 ) 33 34 type pipe struct { 35 s *socket 36 p protocol.Pipe 37 sendQ chan *protocol.Message 38 closeQ chan struct{} 39 } 40 41 type recvQEntry struct { 42 m *protocol.Message 43 p *pipe 44 } 45 46 type socket struct { 47 closed bool 48 ttl int 49 sendQLen int 50 recvQ chan recvQEntry 51 contexts map[*context]struct{} 52 master *context 53 sync.Mutex 54 } 55 56 type context struct { 57 s *socket 58 closed bool 59 recvWait bool 60 recvExpire time.Duration 61 recvPipe *pipe 62 closeQ chan struct{} 63 sendExpire time.Duration 64 bestEffort bool 65 backtrace []byte 66 } 67 68 // closedQ represents a non-blocking time channel. 69 var closedQ <-chan time.Time 70 71 // nilQ represents a nil time channel (blocks forever) 72 var nilQ <-chan time.Time 73 74 func init() { 75 tq := make(chan time.Time) 76 closedQ = tq 77 close(tq) 78 } 79 80 func (c *context) RecvMsg() (*protocol.Message, error) { 81 s := c.s 82 s.Lock() 83 84 if c.closed { 85 s.Unlock() 86 return nil, protocol.ErrClosed 87 } 88 if c.recvWait { 89 s.Unlock() 90 return nil, protocol.ErrProtoState 91 } 92 c.recvWait = true 93 94 cq := c.closeQ 95 wq := nilQ 96 expireTime := c.recvExpire 97 s.Unlock() 98 99 if expireTime > 0 { 100 wq = time.After(expireTime) 101 } 102 103 var err error 104 var m *protocol.Message 105 var p *pipe 106 107 select { 108 case entry := <-s.recvQ: 109 m, p = entry.m, entry.p 110 case <-wq: 111 err = protocol.ErrRecvTimeout 112 case <-cq: 113 err = protocol.ErrClosed 114 } 115 116 s.Lock() 117 118 if m != nil { 119 c.backtrace = append([]byte{}, m.Header...) 120 m.Header = nil 121 c.recvPipe = p 122 } 123 c.recvWait = false 124 s.Unlock() 125 return m, err 126 } 127 128 func (c *context) SendMsg(m *protocol.Message) error { 129 r := c.s 130 r.Lock() 131 132 if r.closed || c.closed { 133 r.Unlock() 134 return protocol.ErrClosed 135 } 136 if c.backtrace == nil { 137 r.Unlock() 138 return protocol.ErrProtoState 139 } 140 p := c.recvPipe 141 c.recvPipe = nil 142 143 bestEffort := c.bestEffort 144 timeQ := nilQ 145 if bestEffort { 146 timeQ = closedQ 147 } else if c.sendExpire > 0 { 148 timeQ = time.After(c.sendExpire) 149 } 150 151 m.Header = c.backtrace 152 c.backtrace = nil 153 cq := c.closeQ 154 r.Unlock() 155 156 select { 157 case <-cq: 158 m.Header = nil 159 return protocol.ErrClosed 160 case <-p.closeQ: 161 // Pipe closed, so no way to get it to the recipient. 162 // Just discard the message. 163 m.Free() 164 return nil 165 case <-timeQ: 166 if bestEffort { 167 // No way to report to caller, so just discard 168 // the message. 169 m.Free() 170 return nil 171 } 172 m.Header = nil 173 return protocol.ErrSendTimeout 174 175 case p.sendQ <- m: 176 return nil 177 } 178 } 179 180 func (c *context) Close() error { 181 s := c.s 182 s.Lock() 183 if c.closed { 184 s.Unlock() 185 return protocol.ErrClosed 186 } 187 delete(s.contexts, c) 188 c.closed = true 189 close(c.closeQ) 190 s.Unlock() 191 return nil 192 } 193 194 func (c *context) GetOption(name string) (interface{}, error) { 195 switch name { 196 case protocol.OptionBestEffort: 197 c.s.Lock() 198 v := c.bestEffort 199 c.s.Unlock() 200 return v, nil 201 202 case protocol.OptionRecvDeadline: 203 c.s.Lock() 204 v := c.recvExpire 205 c.s.Unlock() 206 return v, nil 207 208 case protocol.OptionSendDeadline: 209 c.s.Lock() 210 v := c.sendExpire 211 c.s.Unlock() 212 return v, nil 213 214 default: 215 return nil, protocol.ErrBadOption 216 } 217 } 218 219 func (c *context) SetOption(name string, v interface{}) error { 220 switch name { 221 case protocol.OptionBestEffort: 222 if val, ok := v.(bool); ok { 223 c.s.Lock() 224 c.bestEffort = val 225 c.s.Unlock() 226 return nil 227 } 228 return protocol.ErrBadValue 229 230 case protocol.OptionSendDeadline: 231 if val, ok := v.(time.Duration); ok && val > 0 { 232 c.s.Lock() 233 c.sendExpire = val 234 c.s.Unlock() 235 return nil 236 } 237 return protocol.ErrBadValue 238 239 case protocol.OptionRecvDeadline: 240 if val, ok := v.(time.Duration); ok && val > 0 { 241 c.s.Lock() 242 c.recvExpire = val 243 c.s.Unlock() 244 return nil 245 } 246 return protocol.ErrBadValue 247 248 default: 249 return protocol.ErrBadOption 250 } 251 } 252 253 func (p *pipe) receiver() { 254 s := p.s 255 outer: 256 for { 257 m := p.p.RecvMsg() 258 if m == nil { 259 break 260 } 261 262 // Move backtrace from body to header. 263 hops := 0 264 for { 265 if hops >= s.ttl { 266 m.Free() // ErrTooManyHops 267 continue outer 268 } 269 hops++ 270 if len(m.Body) < 4 { 271 m.Free() // ErrGarbled 272 continue outer 273 } 274 m.Header = append(m.Header, m.Body[:4]...) 275 m.Body = m.Body[4:] 276 // Check for high order bit set (0x80000000, big endian) 277 if m.Header[len(m.Header)-4]&0x80 != 0 { 278 break 279 } 280 } 281 282 entry := recvQEntry{m: m, p: p} 283 select { 284 case s.recvQ <- entry: 285 case <-p.closeQ: 286 // Either the pipe or the socket has closed (which 287 // closes the pipe.) In either case, we have no 288 // way to return a response, so we have to abandon. 289 m.Free() 290 break outer 291 } 292 } 293 go p.close() 294 } 295 296 func (p *pipe) sender() { 297 for { 298 select { 299 case m := <-p.sendQ: 300 if p.p.SendMsg(m) != nil { 301 p.close() 302 return 303 } 304 case <-p.closeQ: 305 return 306 } 307 } 308 } 309 310 func (p *pipe) close() { 311 _ = p.p.Close() 312 } 313 314 func (s *socket) Close() error { 315 316 s.Lock() 317 318 if s.closed { 319 s.Unlock() 320 return protocol.ErrClosed 321 } 322 s.closed = true 323 var contexts []*context 324 for c := range s.contexts { 325 contexts = append(contexts, c) 326 } 327 s.Unlock() 328 329 for _, c := range contexts { 330 _ = c.Close() 331 } 332 return nil 333 } 334 335 func (*socket) Info() protocol.Info { 336 return protocol.Info{ 337 Self: Self, 338 Peer: Peer, 339 SelfName: SelfName, 340 PeerName: PeerName, 341 } 342 } 343 344 func (s *socket) AddPipe(pp protocol.Pipe) error { 345 346 p := &pipe{ 347 p: pp, 348 s: s, 349 sendQ: make(chan *protocol.Message, s.sendQLen), 350 closeQ: make(chan struct{}), 351 } 352 pp.SetPrivate(p) 353 s.Lock() 354 if s.closed { 355 s.Unlock() 356 return protocol.ErrClosed 357 } 358 go p.sender() 359 go p.receiver() 360 s.Unlock() 361 return nil 362 } 363 364 func (s *socket) RemovePipe(pp protocol.Pipe) { 365 366 p := pp.GetPrivate().(*pipe) 367 close(p.closeQ) 368 } 369 370 func (s *socket) SetOption(name string, v interface{}) error { 371 switch name { 372 case protocol.OptionWriteQLen: 373 if qlen, ok := v.(int); ok && qlen >= 0 { 374 s.Lock() 375 s.sendQLen = qlen 376 s.Unlock() 377 return nil 378 } 379 return protocol.ErrBadValue 380 381 case protocol.OptionTTL: 382 if ttl, ok := v.(int); ok && ttl > 0 && ttl < 256 { 383 s.Lock() 384 s.ttl = ttl 385 s.Unlock() 386 return nil 387 } 388 return protocol.ErrBadValue 389 } 390 return s.master.SetOption(name, v) 391 } 392 393 func (s *socket) GetOption(name string) (interface{}, error) { 394 switch name { 395 case protocol.OptionRaw: 396 return false, nil 397 case protocol.OptionTTL: 398 s.Lock() 399 v := s.ttl 400 s.Unlock() 401 return v, nil 402 case protocol.OptionWriteQLen: 403 s.Lock() 404 v := s.sendQLen 405 s.Unlock() 406 return v, nil 407 } 408 409 return s.master.GetOption(name) 410 } 411 412 func (s *socket) OpenContext() (protocol.Context, error) { 413 s.Lock() 414 defer s.Unlock() 415 if s.closed { 416 return nil, protocol.ErrClosed 417 } 418 c := &context{ 419 s: s, 420 closeQ: make(chan struct{}), 421 } 422 s.contexts[c] = struct{}{} 423 return c, nil 424 } 425 426 func (s *socket) RecvMsg() (*protocol.Message, error) { 427 return s.master.RecvMsg() 428 } 429 430 func (s *socket) SendMsg(m *protocol.Message) error { 431 return s.master.SendMsg(m) 432 } 433 434 // NewProtocol allocates a protocol state for the REP protocol. 435 func NewProtocol() protocol.Protocol { 436 s := &socket{ 437 ttl: 8, 438 contexts: make(map[*context]struct{}), 439 recvQ: make(chan recvQEntry), // unbuffered! 440 master: &context{ 441 closeQ: make(chan struct{}), 442 }, 443 } 444 s.master.s = s 445 s.contexts[s.master] = struct{}{} 446 return s 447 } 448 449 // NewSocket allocates a new Socket using the REP protocol. 450 func NewSocket() (protocol.Socket, error) { 451 return protocol.MakeSocket(NewProtocol()), nil 452 }