Class BinaryMsgSession
- All Implemented Interfaces:
BlinkProtocol,Ready,Runnable
The protocol is not inherently client/server other than the fact that java is a socket server and thus everything else is a client. This protocol can also be run over a serial connection which doesn't have a concept of a client/server but rather simply peers.
There are three types of addresses currently defined when sending a message:
- API call with response
- API call without response
- Response
Use "API call without response" when calling an api without waiting for a response. This tells the receiver that it need not bother sending the response at all which cuts down on message processing overhead. The native sock library is designed such that every api returns a response by default, if for no other reason than to confirm that it finished. If the sender is not going to use the response it can use this type of address and the sock library will simply discard the response message.
Generally speaking an implementation can send a response even when requested not to as it will simply be ignored by the receiver.
This protocol supports sending payloads up to 64k, but by using the upper two bits of the msgId as two extra bits of bodyLen it can support up to 256k. Simple implementations of the protocol can simply treat msgId as 14 bits and ignore large message support knowing that no large message will ever be sent or received. For stacks that require large messages such as when sending large firmware images, the additional msgId/bodyLen processing can be added. Both java and the native sock library support large messages.
The message header is defined as:
+------------+------------+------------+------------+
| marker | error | address |
+------------+------------+------------+------------+
| bodyLen | msgId |
+------------+------------+------------+------------+
The fields are described below:
bits description
--------------------
0..7 : marker : '$' for little endian, '%' for big endian.
8..15 : error : 8 bits : Error code associated with the message. Sent as a positive value but should
be negated before being used. Value of zero implies no error.
16..31 : address : Bitfield that indicates the target of the message. The two high bits of
the address indicates the nature of the request and the type of address:
bit description
------------------
15 : 1 = request
bits 8..13 : Interface number : This allows up to 64 api interfaces
bits 0..7 : Api number : This allows 256 api calls per interface
15 : 0 = response
bits 0..13 : msgId of the message this response is to
14 : 1 = expect reply
The caller will block waiting for a reply via a response message
with an address of the msgId of this message
14 : 0 = no reply
The caller will not block and no reply is expected and if sent it
will be ignored.
32..47 : bodyLen : 16 bit length of the body following the header. When used with large message
support, the upper two bits of msgId are used as the upper two bits of bodyLen to make
it an 18 bit number.
50..63 : msgId : 16 bit field where only the lower 14 bits are used for the message id. When
not using large message support the upper two bits of the 16 bit value should always be
zero (treating msgId as a 14 bit value). When large message support is used, the upper
two bits contains the upper two bits of an 18 bit bodyLen value. The msgId value is
a monotonically increasing number generated by the sender which is used in response
messages.
This protocol supports both big end little endian encodings which allows for mixed hardware environments.
The protocol does not support changing endian on the fly. The identity object used to identify sessions
of this protocol will identify the endian of the connection and the marker in the header is expected
to match.
Note that the 16bit values in the header are encoded in the declared endian format of the connection. This means that the upper bits of bodyLen stored in the msgId field change location depending on the endian of the header. While unusual, this makes constructing the header trivial regardless of the endian of the platform (just a normal C structure) and on the java side we simply define the receive ByteBuffer to match the connection encoding and it all just works.
- Since:
- 1.0
- Version:
- 2022-09-21
-
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final intstatic final intstatic final byte -
Constructor Summary
ConstructorsConstructorDescriptionBinaryMsgSession(BlinkConn conn, BinaryMsgIdentity identity, JsonNode identityJson) Create a new BinaryMsgSession. -
Method Summary
Modifier and TypeMethodDescriptionfinal voidconnect()Called once the session is established after the identity phase.final voidCalled when the underlying connection is closed.voidDispatch a message to a handler.Return the byte order of the stream.Get the core iface for the session.intReturn the currently configured default timeout for receive operations.<T> TgetIdentity(Class<T> clazz) Convert identity data to the specified type.intReturn the number of interfaces.byteThe marker to use in the header.getName()Return the name of the session, which is the name of the core iface.Return the nodeId that the client is running on.Return the read buffer to read channel data into.getReady()Fetches the associated ready indicator.intReturn the client revision in the identity.booleanTrue if the client is still connected.booleanReturn true if the nodeId is the primary node.msg(int ifaceNum, int apiNum) Return a new message instance that can be populated with data and sent to the client side of the session.voidread()Process incoming data placed in the read buffer.voidSend the specified message without expecting any response.sendAndRecv(BinaryMsg msg, int timeout) Send the specified message and wait for a response.voidsendAndRecv(BinaryMsg msg, int timeout, BinaryMsgListener listener) Send the specified message and send the response to the listener.voidsetDefaultTimeout(int timeout) Set the default timeout for receive operations.Methods inherited from class com.tccc.kos.commons.core.service.blink.BlinkSession
getRemoteAddr, queue, run, toString, write, write
-
Field Details
-
MARKER
public static final byte MARKER- See Also:
-
HEADER_SIZE
public static final int HEADER_SIZE- See Also:
-
DEFAULT_TIMEOUT
public static final int DEFAULT_TIMEOUT- See Also:
-
-
Constructor Details
-
BinaryMsgSession
Create a new BinaryMsgSession.- Parameters:
conn- the underlying connection for dataidentity- identity objectidentityJson- parsed json identity data so interfaces can examine it
-
-
Method Details
-
connect
public final void connect()Description copied from class:BlinkSessionCalled once the session is established after the identity phase. The session can do any additional setup now that is is past the identity timeout phase of the protocol.- Overrides:
connectin classBlinkSession<BinaryMsg>
-
disconnect
public final void disconnect()Description copied from interface:BlinkProtocolCalled when the underlying connection is closed.- Specified by:
disconnectin interfaceBlinkProtocol
-
getIdentity
Convert identity data to the specified type. Useful if the identity json payload contains additional data for a given interface.- Parameters:
clazz- the class to convert json data to- Returns:
- instance of identity data
- Throws:
Exception
-
getCoreIface
Get the core iface for the session. This is the iface at position zero and represents the overall name of the session. -
getName
Return the name of the session, which is the name of the core iface. -
getInterfaceCount
public int getInterfaceCount()Return the number of interfaces. -
read
Description copied from interface:BlinkProtocolProcess incoming data placed in the read buffer. Ideally read() will do one of the following:- Consume all of the data and clear the buffer before returning. - Consume some of the data and compress the remaining to the front of the buffer.
Beware that if you do not consume all of the data in the hope that you'll get a complete message on the next callback, it's entirely possible that the message you're waiting for won't fit in the receive buffer in which case you'll get stuck. Incomplete processing of data is only really safe if you're waiting for the rest of a fixed size header to be received or something like that.
- Specified by:
readin interfaceBlinkProtocol- Throws:
IOException- throwing this will close the connection
-
getRevision
public int getRevision()Return the client revision in the identity. -
getByteOrder
Return the byte order of the stream.- Returns:
- the byte order of the stream
-
getMarker
public byte getMarker()The marker to use in the header. -
getDefaultTimeout
public int getDefaultTimeout()Return the currently configured default timeout for receive operations. -
setDefaultTimeout
public void setDefaultTimeout(int timeout) Set the default timeout for receive operations.- Parameters:
timeout- the new default timeout 0 = system default
-
dispatch
Description copied from class:BlinkSessionDispatch a message to a handler. This will be called for every message placed in the dispatch queue by calling queue(). This will be called by a worker thread from the endpoint thread pool so it can block or be long running. Only one message is dispatched at a time. This means that if a dispatched message blocks, this method will not be called again until the blocked message finally returns. This ensures that messages are dispatched in the order they were received.- Specified by:
dispatchin classBlinkSession<BinaryMsg>- Parameters:
msg- the handler to run in the dispatch thread pool
-
getReadBuf
Description copied from interface:BlinkProtocolReturn the read buffer to read channel data into.- Specified by:
getReadBufin interfaceBlinkProtocol
-
getNodeId
Return the nodeId that the client is running on. This may be different from the current node when using clustering.- Returns:
- the nodeId of the client connection
-
isPrimary
public boolean isPrimary()Return true if the nodeId is the primary node. -
isConnected
public boolean isConnected()True if the client is still connected.- Returns:
- true if connected
-
msg
Return a new message instance that can be populated with data and sent to the client side of the session.- Parameters:
ifaceNum- the interface numberapiNum- the api number- Returns:
- the new message instance
- Throws:
IOException
-
send
Send the specified message without expecting any response.- Parameters:
msg- the message to send- Throws:
IOException
-
sendAndRecv
Send the specified message and wait for a response.- Parameters:
msg- the message to sendtimeout- timeout for receive (<= uses default)- Returns:
- the response message
- Throws:
TimeoutBinaryMsgException- if there is a timeoutErrorBinaryMsgException- if the response contains an errorIOException- if there is a problem sending
-
sendAndRecv
Send the specified message and send the response to the listener. Listener will be called with a null message if there is a timeout.- Parameters:
msg- the message to sendtimeout- timeout for receive (<=0 uses default)- Throws:
IOException- if there is a problem sending
-
getReady
Description copied from interface:ReadyFetches the associated ready indicator.
-