go.nanomsg.org/mangos/v3@v3.4.3-0.20240217232803-46464076f1f5/protocol/xpair1/xpair1.go (about) 1 // Copyright 2022 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 xpair1 implements the PAIRv1 protocol in monogamous mode only. 16 // This is a simple 1:1 messaging pattern. Only one peer can be connected at a time. 17 package xpair1 18 19 import ( 20 "encoding/binary" 21 "sync" 22 "time" 23 24 "go.nanomsg.org/mangos/v3/protocol" 25 ) 26 27 // Protocol identity information. 28 const ( 29 Self = protocol.ProtoPair1 30 Peer = protocol.ProtoPair1 31 SelfName = "pair1" 32 PeerName = "pair1" 33 ) 34 35 type pipe struct { 36 p protocol.Pipe 37 s *socket 38 closeQ chan struct{} 39 } 40 41 type socket struct { 42 closed bool 43 closeQ chan struct{} 44 sizeQ chan struct{} 45 peer *pipe 46 recvQLen int 47 sendQLen int 48 ttl int 49 recvExpire time.Duration 50 sendExpire time.Duration 51 bestEffort bool 52 recvQ chan *protocol.Message 53 sendQ chan *protocol.Message 54 sync.Mutex 55 } 56 57 var ( 58 nilQ <-chan time.Time 59 closedQ chan time.Time 60 ) 61 62 func init() { 63 closedQ = make(chan time.Time) 64 close(closedQ) 65 } 66 67 const defaultQLen = 128 68 69 func (s *socket) SendMsg(m *protocol.Message) error { 70 if len(m.Header) < 4 { 71 m.Free() 72 return nil 73 } 74 75 if m.Header[0] != 0 || m.Header[1] != 0 || m.Header[2] != 0 { 76 m.Free() 77 return nil 78 } 79 80 timeQ := nilQ 81 s.Lock() 82 if s.closed { 83 s.Unlock() 84 return protocol.ErrClosed 85 } 86 if s.bestEffort { 87 timeQ = closedQ 88 } else if s.sendExpire > 0 { 89 timeQ = time.After(s.sendExpire) 90 } 91 sizeQ := s.sizeQ 92 sendQ := s.sendQ 93 closeQ := s.closeQ 94 s.Unlock() 95 96 select { 97 case <-closeQ: 98 return protocol.ErrClosed 99 case <-timeQ: 100 if timeQ == closedQ { 101 m.Free() 102 return nil 103 } 104 return protocol.ErrSendTimeout 105 106 case <-sizeQ: 107 m.Free() 108 return nil 109 110 case sendQ <- m: 111 return nil 112 } 113 } 114 115 func (s *socket) RecvMsg() (*protocol.Message, error) { 116 for { 117 timeQ := nilQ 118 s.Lock() 119 if s.recvExpire > 0 { 120 timeQ = time.After(s.recvExpire) 121 } 122 closeQ := s.closeQ 123 recvQ := s.recvQ 124 sizeQ := s.sizeQ 125 s.Unlock() 126 select { 127 case <-closeQ: 128 return nil, protocol.ErrClosed 129 case <-timeQ: 130 return nil, protocol.ErrRecvTimeout 131 case m := <-recvQ: 132 return m, nil 133 case <-sizeQ: 134 } 135 } 136 } 137 138 func (s *socket) SetOption(name string, value interface{}) error { 139 switch name { 140 141 case protocol.OptionBestEffort: 142 if v, ok := value.(bool); ok { 143 s.Lock() 144 s.bestEffort = v 145 s.Unlock() 146 return nil 147 } 148 return protocol.ErrBadValue 149 150 case protocol.OptionRecvDeadline: 151 if v, ok := value.(time.Duration); ok { 152 s.Lock() 153 s.recvExpire = v 154 s.Unlock() 155 return nil 156 } 157 return protocol.ErrBadValue 158 159 case protocol.OptionSendDeadline: 160 if v, ok := value.(time.Duration); ok { 161 s.Lock() 162 s.sendExpire = v 163 s.Unlock() 164 return nil 165 } 166 return protocol.ErrBadValue 167 168 case protocol.OptionReadQLen: 169 if v, ok := value.(int); ok && v >= 0 { 170 recvQ := make(chan *protocol.Message, v) 171 sizeQ := make(chan struct{}) 172 s.Lock() 173 s.recvQLen = v 174 s.recvQ = recvQ 175 sizeQ, s.sizeQ = s.sizeQ, sizeQ 176 s.Unlock() 177 close(sizeQ) 178 179 return nil 180 } 181 return protocol.ErrBadValue 182 183 case protocol.OptionWriteQLen: 184 if v, ok := value.(int); ok && v >= 0 { 185 sendQ := make(chan *protocol.Message, v) 186 sizeQ := make(chan struct{}) 187 s.Lock() 188 s.sendQLen = v 189 s.sendQ = sendQ 190 sizeQ, s.sizeQ = s.sizeQ, sizeQ 191 s.Unlock() 192 close(sizeQ) 193 194 return nil 195 } 196 return protocol.ErrBadValue 197 198 case protocol.OptionTTL: 199 if v, ok := value.(int); ok && v > 0 && v < 256 { 200 s.Lock() 201 s.ttl = v 202 s.Unlock() 203 return nil 204 } 205 return protocol.ErrBadValue 206 207 } 208 209 return protocol.ErrBadOption 210 } 211 212 func (s *socket) GetOption(option string) (interface{}, error) { 213 switch option { 214 case protocol.OptionRaw: 215 return true, nil 216 case protocol.OptionBestEffort: 217 s.Lock() 218 v := s.bestEffort 219 s.Unlock() 220 return v, nil 221 case protocol.OptionRecvDeadline: 222 s.Lock() 223 v := s.recvExpire 224 s.Unlock() 225 return v, nil 226 case protocol.OptionSendDeadline: 227 s.Lock() 228 v := s.sendExpire 229 s.Unlock() 230 return v, nil 231 case protocol.OptionReadQLen: 232 s.Lock() 233 v := s.recvQLen 234 s.Unlock() 235 return v, nil 236 case protocol.OptionWriteQLen: 237 s.Lock() 238 v := s.sendQLen 239 s.Unlock() 240 return v, nil 241 case protocol.OptionTTL: 242 s.Lock() 243 v := s.ttl 244 s.Unlock() 245 return v, nil 246 } 247 248 return nil, protocol.ErrBadOption 249 } 250 251 func (s *socket) AddPipe(pp protocol.Pipe) error { 252 s.Lock() 253 defer s.Unlock() 254 if s.closed { 255 return protocol.ErrClosed 256 } 257 if s.peer != nil { 258 return protocol.ErrProtoState 259 } 260 p := &pipe{ 261 p: pp, 262 s: s, 263 closeQ: make(chan struct{}), 264 } 265 s.peer = p 266 go p.receiver() 267 go p.sender() 268 return nil 269 } 270 271 func (s *socket) RemovePipe(pp protocol.Pipe) { 272 s.Lock() 273 if p := s.peer; p != nil && pp == p.p { 274 s.peer = nil 275 close(p.closeQ) 276 } 277 s.Unlock() 278 } 279 280 func (s *socket) OpenContext() (protocol.Context, error) { 281 return nil, protocol.ErrProtoOp 282 } 283 284 func (*socket) Info() protocol.Info { 285 return protocol.Info{ 286 Self: Self, 287 Peer: Peer, 288 SelfName: SelfName, 289 PeerName: PeerName, 290 } 291 } 292 293 func (s *socket) Close() error { 294 s.Lock() 295 if s.closed { 296 s.Unlock() 297 return protocol.ErrClosed 298 } 299 s.closed = true 300 s.Unlock() 301 close(s.closeQ) 302 return nil 303 } 304 305 func (p *pipe) receiver() { 306 s := p.s 307 outer: 308 for { 309 m := p.p.RecvMsg() 310 if m == nil { 311 break 312 } 313 314 if len(m.Body) < 4 { 315 m.Free() 316 continue 317 } 318 319 hops := binary.BigEndian.Uint32(m.Body) 320 321 s.Lock() 322 if hops >= 255 || hops > uint32(s.ttl) { 323 s.Unlock() 324 m.Free() 325 continue 326 } 327 m = m.MakeUnique() 328 m.Header = append(m.Header, m.Body[:4]...) 329 m.Header[3] = byte(hops + 1) 330 m.Body = m.Body[4:] 331 recvQ := s.recvQ 332 sizeQ := s.sizeQ 333 s.Unlock() 334 335 select { 336 case recvQ <- m: 337 case <-sizeQ: 338 m.Free() 339 case <-p.closeQ: 340 m.Free() 341 break outer 342 } 343 } 344 p.close() 345 } 346 347 func (p *pipe) sender() { 348 s := p.s 349 outer: 350 for { 351 s.Lock() 352 sendQ := s.sendQ 353 sizeQ := s.sizeQ 354 s.Unlock() 355 356 select { 357 case m := <-sendQ: 358 if err := p.p.SendMsg(m); err != nil { 359 m.Free() 360 break outer 361 } 362 363 case <-sizeQ: 364 365 case <-p.closeQ: 366 break outer 367 } 368 } 369 p.close() 370 } 371 372 func (p *pipe) close() { 373 _ = p.p.Close() 374 } 375 376 // NewProtocol returns a new protocol implementation. 377 func NewProtocol() protocol.Protocol { 378 s := &socket{ 379 closeQ: make(chan struct{}), 380 sizeQ: make(chan struct{}), 381 recvQ: make(chan *protocol.Message, defaultQLen), 382 sendQ: make(chan *protocol.Message, defaultQLen), 383 recvQLen: defaultQLen, 384 sendQLen: defaultQLen, 385 ttl: 8, 386 } 387 return s 388 } 389 390 // NewSocket allocates a raw Socket using the PULL protocol. 391 func NewSocket() (protocol.Socket, error) { 392 return protocol.MakeSocket(NewProtocol()), nil 393 }