zmq.io.mechanism.Mechanism Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jeromq Show documentation
Show all versions of jeromq Show documentation
Pure Java implementation of libzmq
The newest version!
package zmq.io.mechanism;
import static zmq.io.Metadata.IDENTITY;
import static zmq.io.Metadata.SOCKET_TYPE;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import zmq.Msg;
import zmq.Options;
import zmq.ZError;
import zmq.ZMQ;
import zmq.io.Metadata;
import zmq.io.Msgs;
import zmq.io.SessionBase;
import zmq.io.net.Address;
import zmq.socket.Sockets;
import zmq.util.Blob;
import zmq.util.Wire;
// Abstract class representing security mechanism.
// Different mechanism extends this class.
public abstract class Mechanism
{
public enum Status
{
HANDSHAKING,
READY,
ERROR
}
protected final Options options;
private Blob identity;
private Blob userId;
// Properties received from ZAP server.
public final Metadata zapProperties = new Metadata();
// Properties received from ZMTP peer.
public final Metadata zmtpProperties = new Metadata();
protected final SessionBase session;
private final Address peerAddress;
protected String statusCode;
protected Mechanism(SessionBase session, Address peerAddress, Options options)
{
this.session = session;
this.options = options;
this.peerAddress = peerAddress;
}
public abstract Status status();
private void setPeerIdentity(byte[] data)
{
identity = Blob.createBlob(data);
}
public final Msg peerIdentity()
{
byte[] data = new byte[0];
int size = 0;
if (identity != null) {
data = identity.data();
size = identity.size();
}
Msg msg = new Msg(size);
msg.put(data, 0, size);
msg.setFlags(Msg.IDENTITY);
return msg;
}
private void setUserId(byte[] data)
{
userId = Blob.createBlob(data);
zapProperties.put(Metadata.USER_ID, new String(data, ZMQ.CHARSET));
}
public final Blob getUserId()
{
return userId;
}
protected final void addProperty(ByteBuffer buf, String name, String value)
{
addProperty(buf, name, value.getBytes(ZMQ.CHARSET));
}
protected final void addProperty(Msg msg, String name, String value)
{
addProperty(msg, name, value.getBytes(ZMQ.CHARSET));
}
protected final void addProperty(ByteBuffer buf, String name, byte[] value)
{
byte[] nameB = name.getBytes(ZMQ.CHARSET);
int nameLength = nameB.length;
assert (nameLength <= 255);
int valueLength = value == null ? 0 : value.length;
buf.put((byte) nameLength);
buf.put(nameB);
Wire.putUInt32(buf, valueLength);
if (value != null) {
buf.put(value);
}
}
protected final void addProperty(Msg msg, String name, byte[] value)
{
byte[] nameB = name.getBytes(ZMQ.CHARSET);
int nameLength = nameB.length;
assert (nameLength <= 255);
int valueLength = value == null ? 0 : value.length;
msg.put((byte) nameLength);
msg.put(nameB);
Wire.putUInt32(msg, valueLength);
if (value != null) {
msg.put(value);
}
}
protected final int parseMetadata(Msg msg, int offset, boolean zapFlag)
{
return parseMetadata(msg.buf(), offset, zapFlag);
}
protected final int parseMetadata(ByteBuffer msg, int offset, boolean zapFlag)
{
Metadata meta = zapFlag ? zapProperties : zmtpProperties;
return meta.read(msg, offset, (name, value, valueAsString) -> {
int type = options.asType != -1 ? options.asType : options.type;
if (IDENTITY.equals(name) && options.recvIdentity) {
setPeerIdentity(value);
}
else if (SOCKET_TYPE.equals(name)) {
if (!Sockets.compatible(type, valueAsString)) {
return ZError.EINVAL;
}
}
else {
int rc = property(name, value);
if (rc == -1) {
return -1;
}
}
// continue
return 0;
});
}
protected int property(String name, byte[] value)
{
// Default implementation does not check
// property values and returns 0 to signal success.
return 0;
}
protected final String socketType()
{
if (options.asType != -1) {
return Sockets.name(options.asType);
}
else {
return Sockets.name(options.type);
}
}
protected boolean compare(Msg msg, String data, boolean includeLength)
{
return Msgs.startsWith(msg, data, includeLength);
}
protected boolean compare(ByteBuffer a1, byte[] b, int offset, int length)
{
if (length > b.length) {
return false;
}
boolean comparison = true;
for (int idx = 0; idx < length; ++idx) {
comparison = a1.get(idx + offset) == b[idx];
if (!comparison) {
break;
}
}
return comparison;
}
public Msg decode(Msg msg)
{
return msg;
}
public Msg encode(Msg msg)
{
return msg;
}
public abstract int zapMsgAvailable();
public abstract int processHandshakeCommand(Msg msg);
public abstract int nextHandshakeCommand(Msg msg);
protected int parseErrorMessage(Msg msg)
{
if (msg.size() < 7 && msg.size() != 6) {
session.getSocket().eventHandshakeFailedProtocol(session.getEndpoint(), ZMQ.ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_ERROR);
return ZError.EPROTO;
}
if (msg.size() >= 7) {
byte errorReasonLength = msg.get(6);
if (errorReasonLength > msg.size() - 7) {
session.getSocket().eventHandshakeFailedProtocol(session.getEndpoint(), ZMQ.ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_ERROR);
return ZError.EPROTO;
}
// triple digit status code
if (msg.size() == 10) {
byte[] statusBuffer = Arrays.copyOfRange(msg.data(), 7, 10);
String statusCode = new String(statusBuffer, ZMQ.CHARSET);
if (handleErrorReason(statusCode) < 0) {
return ZError.EPROTO;
}
}
}
return 0;
}
protected int handleErrorReason(String reason)
{
int rc = -1;
if (reason.length() == 3
&& reason.charAt(1) == '0'
&& reason.charAt(2) == '0'
&& reason.charAt(0) >= '3'
&& reason.charAt(0) <= '5') {
try {
int statusCode = Integer.parseInt(reason);
session.getSocket().eventHandshakeFailedAuth(session.getEndpoint(), statusCode);
rc = 0;
}
catch (NumberFormatException e) {
session.getSocket().eventHandshakeFailedProtocol(session.getEndpoint(), ZMQ.ZMQ_PROTOCOL_ERROR_ZAP_MALFORMED_REPLY);
}
}
else {
session.getSocket().eventHandshakeFailedProtocol(session.getEndpoint(), ZMQ.ZMQ_PROTOCOL_ERROR_ZAP_MALFORMED_REPLY);
}
return rc;
}
protected final void sendZapRequest(Mechanisms mechanism, boolean more)
{
assert (session != null);
assert (peerAddress != null);
assert (mechanism != null);
Msg msg = new Msg();
// Address delimiter frame
msg.setFlags(Msg.MORE);
boolean rc = session.writeZapMsg(msg);
assert (rc);
// Version frame
msg = new Msg(3);
msg.setFlags(Msg.MORE);
msg.put("1.0".getBytes(ZMQ.CHARSET));
rc = session.writeZapMsg(msg);
assert (rc);
// Request id frame
msg = new Msg(1);
msg.setFlags(Msg.MORE);
msg.put("1".getBytes(ZMQ.CHARSET));
rc = session.writeZapMsg(msg);
assert (rc);
// Domain frame
msg = new Msg(options.zapDomain.length());
msg.setFlags(Msg.MORE);
msg.put(options.zapDomain.getBytes(ZMQ.CHARSET));
rc = session.writeZapMsg(msg);
assert (rc);
// Address frame
byte[] host = peerAddress.host().getBytes(ZMQ.CHARSET);
msg = new Msg(host.length);
msg.setFlags(Msg.MORE);
msg.put(host);
rc = session.writeZapMsg(msg);
assert (rc);
// Identity frame
msg = new Msg(options.identitySize);
msg.setFlags(Msg.MORE);
msg.put(options.identity, 0, options.identitySize);
rc = session.writeZapMsg(msg);
assert (rc);
// Mechanism frame
msg = new Msg(mechanism.name().length());
msg.put(mechanism.name().getBytes(ZMQ.CHARSET));
if (more) {
msg.setFlags(Msg.MORE);
}
rc = session.writeZapMsg(msg);
assert (rc);
}
protected final int receiveAndProcessZapReply()
{
assert (session != null);
List msgs = new ArrayList<>(7); // ZAP reply consists of 7 frames
// Initialize all reply frames
for (int idx = 0; idx < 7; ++idx) {
Msg msg = session.readZapMsg();
if (msg == null) {
return session.errno.get();
}
if ((msg.flags() & Msg.MORE) == (idx < 6 ? 0 : Msg.MORE)) {
session.getSocket().eventHandshakeFailedProtocol(session.getEndpoint(), ZMQ.ZMQ_PROTOCOL_ERROR_ZAP_MALFORMED_REPLY);
return ZError.EPROTO;
}
msgs.add(msg);
}
// Address delimiter frame
if (msgs.get(0).size() > 0) {
session.getSocket().eventHandshakeFailedProtocol(session.getEndpoint(), ZMQ.ZMQ_PROTOCOL_ERROR_ZAP_UNSPECIFIED);
return ZError.EPROTO;
}
// Version frame
if (msgs.get(1).size() != 3 || !compare(msgs.get(1), "1.0", false)) {
session.getSocket().eventHandshakeFailedProtocol(session.getEndpoint(), ZMQ.ZMQ_PROTOCOL_ERROR_ZAP_BAD_VERSION);
return ZError.EPROTO;
}
// Request id frame
if (msgs.get(2).size() != 1 || !compare(msgs.get(2), "1", false)) {
session.getSocket().eventHandshakeFailedProtocol(session.getEndpoint(), ZMQ.ZMQ_PROTOCOL_ERROR_ZAP_BAD_REQUEST_ID);
return ZError.EPROTO;
}
// Status code frame
if (msgs.get(3).size() != 3) {
session.getSocket().eventHandshakeFailedProtocol(session.getEndpoint(), ZMQ.ZMQ_PROTOCOL_ERROR_ZAP_INVALID_STATUS_CODE);
return ZError.EPROTO;
}
// Save status code
statusCode = new String(msgs.get(3).data(), ZMQ.CHARSET);
// Save user id
setUserId(msgs.get(5).data());
// Process metadata frame
return parseMetadata(msgs.get(6), 0, true);
}
public void destroy()
{
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy