github.com/gdamore/mangos@v1.4.0/protocol.go (about) 1 // Copyright 2016 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 mangos 16 17 import ( 18 "time" 19 ) 20 21 // Endpoint represents the handle that a Protocol implementation has 22 // to the underlying stream transport. It can be thought of as one side 23 // of a TCP, IPC, or other type of connection. 24 type Endpoint interface { 25 // GetID returns a unique 31-bit value associated with the Endpoint. 26 // The value is unique for a given socket, at a given time. 27 GetID() uint32 28 29 // Close does what you think. 30 Close() error 31 32 // SendMsg sends a message. On success it returns nil. This is a 33 // blocking call. 34 SendMsg(*Message) error 35 36 // RecvMsg receives a message. It blocks until the message is 37 // received. On error, the pipe is closed and nil is returned. 38 RecvMsg() *Message 39 } 40 41 // Protocol implementations handle the "meat" of protocol processing. Each 42 // protocol type will implement one of these. For protocol pairs (REP/REQ), 43 // there will be one for each half of the protocol. 44 type Protocol interface { 45 46 // Init is called by the core to allow the protocol to perform 47 // any initialization steps it needs. It should save the handle 48 // for future use, as well. 49 Init(ProtocolSocket) 50 51 // Shutdown is used to drain the send side. It is only ever called 52 // when the socket is being shutdown cleanly. Protocols should use 53 // the linger time, and wait up to that time for sockets to drain. 54 Shutdown(time.Time) 55 56 // AddEndpoint is called when a new Endpoint is added to the socket. 57 // Typically this is as a result of connect or accept completing. 58 AddEndpoint(Endpoint) 59 60 // RemoveEndpoint is called when an Endpoint is removed from the socket. 61 // Typically this indicates a disconnected or closed connection. 62 RemoveEndpoint(Endpoint) 63 64 // ProtocolNumber returns a 16-bit value for the protocol number, 65 // as assigned by the SP governing body. (IANA?) 66 Number() uint16 67 68 // Name returns our name. 69 Name() string 70 71 // PeerNumber() returns a 16-bit number for our peer protocol. 72 PeerNumber() uint16 73 74 // PeerName() returns the name of our peer protocol. 75 PeerName() string 76 77 // GetOption is used to retrieve the current value of an option. 78 // If the protocol doesn't recognize the option, EBadOption should 79 // be returned. 80 GetOption(string) (interface{}, error) 81 82 // SetOption is used to set an option. EBadOption is returned if 83 // the option name is not recognized, EBadValue if the value is 84 // invalid. 85 SetOption(string, interface{}) error 86 } 87 88 // The follow are optional interfaces that a Protocol can choose to implement. 89 90 // ProtocolRecvHook is intended to be an additional extension 91 // to the Protocol interface. 92 type ProtocolRecvHook interface { 93 // RecvHook is called just before the message is handed to the 94 // application. The message may be modified. If false is returned, 95 // then the message is dropped. 96 RecvHook(*Message) bool 97 } 98 99 // ProtocolSendHook is intended to be an additional extension 100 // to the Protocol interface. 101 type ProtocolSendHook interface { 102 // SendHook is called when the application calls Send. 103 // If false is returned, the message will be silently dropped. 104 // Note that the message may be dropped for other reasons, 105 // such as if backpressure is applied. 106 SendHook(*Message) bool 107 } 108 109 // ProtocolSocket is the "handle" given to protocols to interface with the 110 // socket. The Protocol implementation should not access any sockets or pipes 111 // except by using functions made available on the ProtocolSocket. Note 112 // that all functions listed here are non-blocking. 113 type ProtocolSocket interface { 114 // SendChannel represents the channel used to send messages. The 115 // application injects messages to it, and the protocol consumes 116 // messages from it. The channel may be closed when the core needs to 117 // create a new channel, typically after an option is set that requires 118 // the channel to be reconfigured. (OptionWriteQLen) When the protocol 119 // implementation notices this, it should call this function again to obtain 120 // the value of the new channel. 121 SendChannel() <-chan *Message 122 123 // RecvChannel is the channel used to receive messages. The protocol 124 // should inject messages to it, and the application will consume them 125 // later. 126 RecvChannel() chan<- *Message 127 128 // The protocol can wait on this channel to close. When it is closed, 129 // it indicates that the application has closed the upper read socket, 130 // and the protocol should stop any further read operations on this 131 // instance. 132 CloseChannel() <-chan struct{} 133 134 // GetOption may be used by the protocol to retrieve an option from 135 // the socket. This can ultimately wind up calling into the socket's 136 // own GetOption handler, so care should be used! 137 GetOption(string) (interface{}, error) 138 139 // SetOption is used by the Protocol to set an option on the socket. 140 // Note that this may set transport options, or even call back down 141 // into the protocol's own SetOption interface! 142 SetOption(string, interface{}) error 143 144 // SetRecvError is used to cause socket RX callers to report an 145 // error. This can be used to force an error return rather than 146 // waiting for a message that will never arrive (e.g. due to state). 147 // If set to nil, then RX works normally. 148 SetRecvError(error) 149 150 // SetSendError is used to cause socket TX callers to report an 151 // error. This can be used to force an error return rather than 152 // waiting to send a message that will never be delivered (e.g. due 153 // to incorrect state.) If set to nil, then TX works normally. 154 SetSendError(error) 155 } 156 157 // Useful constants for protocol numbers. Note that the major protocol number 158 // is stored in the upper 12 bits, and the minor (subprotocol) is located in 159 // the bottom 4 bits. 160 const ( 161 ProtoPair = (1 * 16) 162 ProtoPub = (2 * 16) 163 ProtoSub = (2 * 16) + 1 164 ProtoReq = (3 * 16) 165 ProtoRep = (3 * 16) + 1 166 ProtoPush = (5 * 16) 167 ProtoPull = (5 * 16) + 1 168 ProtoSurveyor = (6 * 16) + 2 169 ProtoRespondent = (6 * 16) + 3 170 ProtoBus = (7 * 16) 171 172 // Experimental Protocols - Use at Risk 173 174 ProtoStar = (100 * 16) 175 ) 176 177 // ProtocolName returns the name corresponding to a given protocol number. 178 // This is useful for transports like WebSocket, which use a text name 179 // rather than the number in the handshake. 180 func ProtocolName(number uint16) string { 181 names := map[uint16]string{ 182 ProtoPair: "pair", 183 ProtoPub: "pub", 184 ProtoSub: "sub", 185 ProtoReq: "req", 186 ProtoRep: "rep", 187 ProtoPush: "push", 188 ProtoPull: "pull", 189 ProtoSurveyor: "surveyor", 190 ProtoRespondent: "respondent", 191 ProtoBus: "bus"} 192 return names[number] 193 } 194 195 // ValidPeers returns true if the two sockets are capable of 196 // peering to one another. For example, REQ can peer with REP, 197 // but not with BUS. 198 func ValidPeers(p1, p2 Protocol) bool { 199 if p1.Number() != p2.PeerNumber() { 200 return false 201 } 202 if p2.Number() != p1.PeerNumber() { 203 return false 204 } 205 return true 206 } 207 208 // NullRecv simply loops, receiving and discarding messages, until the 209 // Endpoint returns back a nil message. This allows the Endpoint to notice 210 // a dropped connection. It is intended for use by Protocols that are write 211 // only -- it lets them become aware of a loss of connectivity even when they 212 // have no data to send. 213 func NullRecv(ep Endpoint) { 214 for { 215 var m *Message 216 if m = ep.RecvMsg(); m == nil { 217 return 218 } 219 m.Free() 220 } 221 }