nanomsg.org/go/mangos/v2@v2.0.9-0.20200203084354-8a092611e461/protocol/respondent/respondent.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 respondent implements the RESPONDENT protocol, which is the 16 // response side of the survey pattern. 17 package respondent 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.ProtoRespondent 29 Peer = protocol.ProtoSurveyor 30 SelfName = "respondent" 31 PeerName = "surveyor" 32 ) 33 34 type msg struct { 35 m *protocol.Message 36 p *pipe 37 } 38 39 type pipe struct { 40 s *socket 41 p protocol.Pipe 42 sendQ chan *protocol.Message 43 closeQ chan struct{} 44 } 45 46 type socket struct { 47 closed bool 48 ttl int 49 sendQLen int 50 recvQLen int 51 sizeQ chan struct{} 52 recvQ chan msg 53 contexts map[*context]struct{} 54 defCtx *context 55 closeQ chan struct{} 56 57 sync.Mutex 58 } 59 60 type context struct { 61 s *socket 62 closed bool 63 recvExpire time.Duration 64 sendExpire time.Duration 65 bestEffort bool 66 recvPipe *pipe 67 backtrace []byte 68 closeQ chan struct{} 69 } 70 71 const defaultQLen = 128 72 73 // closedQ represents a non-blocking time channel. 74 var closedQ <-chan time.Time 75 76 // nilQ represents a nil time channel (blocks forever) 77 var nilQ <-chan time.Time 78 79 func init() { 80 tq := make(chan time.Time) 81 closedQ = tq 82 close(tq) 83 } 84 85 func (c *context) RecvMsg() (*protocol.Message, error) { 86 s := c.s 87 88 for { 89 s.Lock() 90 if c.closed { 91 s.Unlock() 92 return nil, protocol.ErrClosed 93 } 94 cq := c.closeQ 95 tq := nilQ 96 rq := s.recvQ 97 zq := s.sizeQ 98 expTime := c.recvExpire 99 c.backtrace = nil 100 c.recvPipe = nil 101 s.Unlock() 102 103 if expTime > 0 { 104 tq = time.After(expTime) 105 } 106 107 select { 108 case msg := <-rq: 109 s.Lock() 110 c.recvPipe = msg.p 111 c.backtrace = append([]byte{}, msg.m.Header...) 112 s.Unlock() 113 msg.m.Header = nil 114 return msg.m, nil 115 case <-zq: 116 continue 117 case <-tq: 118 return nil, protocol.ErrRecvTimeout 119 case <-cq: 120 return nil, protocol.ErrClosed 121 } 122 } 123 } 124 125 func (c *context) SendMsg(m *protocol.Message) error { 126 127 s := c.s 128 s.Lock() 129 if s.closed || c.closed { 130 s.Unlock() 131 return protocol.ErrClosed 132 } 133 if c.backtrace == nil { 134 s.Unlock() 135 return protocol.ErrProtoState 136 } 137 p := c.recvPipe 138 bt := c.backtrace 139 c.backtrace = nil 140 c.recvPipe = nil 141 bestEffort := c.bestEffort 142 tq := nilQ 143 cq := c.closeQ 144 s.Unlock() 145 146 if bestEffort { 147 tq = closedQ 148 } else if c.sendExpire > 0 { 149 tq = time.After(c.sendExpire) 150 } 151 152 m.Header = bt 153 154 select { 155 case <-cq: 156 m.Header = nil 157 return protocol.ErrClosed 158 case <-p.closeQ: 159 // Pipe closed, so no way to get it to the recipient. 160 // Just discard the message. 161 m.Free() 162 return nil 163 case <-tq: 164 if bestEffort { 165 m.Free() 166 return nil 167 } 168 m.Header = nil 169 return protocol.ErrSendTimeout 170 171 case p.sendQ <- m: 172 return nil 173 } 174 } 175 176 func (c *context) close() { 177 if !c.closed { 178 delete(c.s.contexts, c) 179 c.closed = true 180 close(c.closeQ) 181 } 182 } 183 184 func (c *context) Close() error { 185 s := c.s 186 s.Lock() 187 defer s.Unlock() 188 if c.closed { 189 return protocol.ErrClosed 190 } 191 c.close() 192 return nil 193 } 194 195 func (c *context) GetOption(name string) (interface{}, error) { 196 switch name { 197 case protocol.OptionBestEffort: 198 c.s.Lock() 199 v := c.bestEffort 200 c.s.Unlock() 201 return v, nil 202 203 case protocol.OptionRecvDeadline: 204 c.s.Lock() 205 v := c.recvExpire 206 c.s.Unlock() 207 return v, nil 208 209 case protocol.OptionSendDeadline: 210 c.s.Lock() 211 v := c.sendExpire 212 c.s.Unlock() 213 return v, nil 214 215 default: 216 return nil, protocol.ErrBadOption 217 } 218 } 219 220 func (c *context) SetOption(name string, v interface{}) error { 221 switch name { 222 case protocol.OptionSendDeadline: 223 if val, ok := v.(time.Duration); ok && val.Nanoseconds() > 0 { 224 c.s.Lock() 225 c.sendExpire = val 226 c.s.Unlock() 227 return nil 228 } 229 return protocol.ErrBadValue 230 231 case protocol.OptionRecvDeadline: 232 if val, ok := v.(time.Duration); ok && val.Nanoseconds() > 0 { 233 c.s.Lock() 234 c.recvExpire = val 235 c.s.Unlock() 236 return nil 237 } 238 return protocol.ErrBadValue 239 240 case protocol.OptionBestEffort: 241 if val, ok := v.(bool); ok { 242 c.s.Lock() 243 c.bestEffort = val 244 c.s.Unlock() 245 return nil 246 } 247 return protocol.ErrBadValue 248 249 default: 250 return protocol.ErrBadOption 251 } 252 } 253 254 func (p *pipe) receiver() { 255 s := p.s 256 outer: 257 for { 258 m := p.p.RecvMsg() 259 if m == nil { 260 break 261 } 262 263 // Move backtrace from body to header. 264 hops := 0 265 for { 266 if hops >= s.ttl { 267 m.Free() // ErrTooManyHops 268 continue outer 269 } 270 hops++ 271 if len(m.Body) < 4 { 272 m.Free() // ErrGarbled 273 continue outer 274 } 275 m.Header = append(m.Header, m.Body[:4]...) 276 m.Body = m.Body[4:] 277 // Check for high order bit set (0x80000000, big endian) 278 if m.Header[len(m.Header)-4]&0x80 != 0 { 279 // Protocol error from partner, discard and 280 // close the pipe. 281 break 282 } 283 } 284 msg := msg{ 285 m: m, 286 p: p, 287 } 288 289 inner: 290 for { 291 s.Lock() 292 rq := s.recvQ 293 cq := s.closeQ 294 zq := s.sizeQ 295 s.Unlock() 296 297 select { 298 case <-zq: 299 continue inner 300 case rq <- msg: 301 break inner 302 case <-cq: 303 m.Free() 304 break outer 305 } 306 } 307 } 308 go p.close() 309 } 310 311 func (p *pipe) sender() { 312 for { 313 select { 314 case m := <-p.sendQ: 315 if p.p.SendMsg(m) != nil { 316 p.close() 317 return 318 } 319 case <-p.closeQ: 320 return 321 } 322 } 323 } 324 325 func (p *pipe) close() { 326 _ = p.p.Close() 327 } 328 329 func (s *socket) Close() error { 330 331 s.Lock() 332 defer s.Unlock() 333 334 if s.closed { 335 return protocol.ErrClosed 336 } 337 s.closed = true 338 close(s.closeQ) 339 for c := range s.contexts { 340 c.close() 341 } 342 return nil 343 } 344 345 func (*socket) Info() protocol.Info { 346 return protocol.Info{ 347 Self: Self, 348 Peer: Peer, 349 SelfName: SelfName, 350 PeerName: PeerName, 351 } 352 } 353 354 func (s *socket) AddPipe(pp protocol.Pipe) error { 355 356 p := &pipe{ 357 p: pp, 358 s: s, 359 sendQ: make(chan *protocol.Message, s.sendQLen), 360 closeQ: make(chan struct{}), 361 } 362 pp.SetPrivate(p) 363 s.Lock() 364 if s.closed { 365 s.Unlock() 366 return protocol.ErrClosed 367 } 368 go p.sender() 369 go p.receiver() 370 s.Unlock() 371 return nil 372 } 373 374 func (s *socket) RemovePipe(pp protocol.Pipe) { 375 376 p := pp.GetPrivate().(*pipe) 377 close(p.closeQ) 378 } 379 380 func (s *socket) SetOption(name string, v interface{}) error { 381 switch name { 382 case protocol.OptionWriteQLen: 383 if qLen, ok := v.(int); ok && qLen >= 0 { 384 s.Lock() 385 s.sendQLen = qLen 386 s.Unlock() 387 return nil 388 } 389 return protocol.ErrBadValue 390 391 case protocol.OptionReadQLen: 392 if qLen, ok := v.(int); ok && qLen >= 0 { 393 394 newQ := make(chan msg, qLen) 395 s.Lock() 396 sizeQ := s.sizeQ 397 s.sizeQ = make(chan struct{}) 398 s.recvQ = newQ 399 s.recvQLen = qLen 400 s.Unlock() 401 402 // Close the sizeQ to let anyone watching know that 403 // they should re-examine the recvQ. 404 close(sizeQ) 405 return nil 406 } 407 return protocol.ErrBadValue 408 409 case protocol.OptionTTL: 410 if ttl, ok := v.(int); ok && ttl > 0 && ttl < 256 { 411 s.Lock() 412 s.ttl = ttl 413 s.Unlock() 414 return nil 415 } 416 return protocol.ErrBadValue 417 } 418 return s.defCtx.SetOption(name, v) 419 } 420 421 func (s *socket) GetOption(name string) (interface{}, error) { 422 switch name { 423 case protocol.OptionRaw: 424 return false, nil 425 case protocol.OptionTTL: 426 s.Lock() 427 v := s.ttl 428 s.Unlock() 429 return v, nil 430 case protocol.OptionWriteQLen: 431 s.Lock() 432 v := s.sendQLen 433 s.Unlock() 434 return v, nil 435 436 case protocol.OptionReadQLen: 437 s.Lock() 438 v := s.recvQLen 439 s.Unlock() 440 return v, nil 441 } 442 443 return s.defCtx.GetOption(name) 444 } 445 446 func (s *socket) OpenContext() (protocol.Context, error) { 447 s.Lock() 448 defer s.Unlock() 449 if s.closed { 450 return nil, protocol.ErrClosed 451 } 452 c := &context{ 453 s: s, 454 closeQ: make(chan struct{}), 455 bestEffort: s.defCtx.bestEffort, 456 recvExpire: s.defCtx.recvExpire, 457 sendExpire: s.defCtx.sendExpire, 458 } 459 s.contexts[c] = struct{}{} 460 return c, nil 461 } 462 463 func (s *socket) RecvMsg() (*protocol.Message, error) { 464 return s.defCtx.RecvMsg() 465 } 466 467 func (s *socket) SendMsg(m *protocol.Message) error { 468 return s.defCtx.SendMsg(m) 469 } 470 471 // NewProtocol allocates a protocol state for the RESPONDENT protocol. 472 func NewProtocol() protocol.Protocol { 473 s := &socket{ 474 ttl: 8, 475 contexts: make(map[*context]struct{}), 476 recvQLen: defaultQLen, 477 recvQ: make(chan msg, defaultQLen), 478 closeQ: make(chan struct{}), 479 sizeQ: make(chan struct{}), 480 defCtx: &context{ 481 closeQ: make(chan struct{}), 482 }, 483 } 484 s.defCtx.s = s 485 s.contexts[s.defCtx] = struct{}{} 486 return s 487 } 488 489 // NewSocket allocates a new Socket using the REP protocol. 490 func NewSocket() (protocol.Socket, error) { 491 return protocol.MakeSocket(NewProtocol()), nil 492 }