sendMessage method
Future<IsoMsg?>
sendMessage(
- IsoMsg message, {
- Duration? timeout,
- IsoLinkEvents? events,
- Future<
void> beforeSend(- IsoMsg request
MACs, frames and sends message, then waits for its response.
beforeSend runs after the header is attached and before the bytes leave,
which is where a reversible transaction stores its reversal record.
Implementation
Future<IsoMsg?> sendMessage(
IsoMsg message, {
Duration? timeout,
IsoLinkEvents? events,
Future<void> Function(IsoMsg request)? beforeSend,
}) async {
final Duration effectiveTimeout = timeout ?? Duration(seconds: config.defaultTxnTimeoutSeconds);
try {
await macComponent.generateMac(message, 4);
IsoTrace.log(IsoTraceKind.mac, "request MAC built with the ${macComponent.usesDefaultMac(message) ? "default (KTM) " : "session "}key", bytes: message.getBytes(64));
} catch (error) {
IsoTrace.log(IsoTraceKind.mac, "the PED could not build a MAC: $error");
throw UIsoException(UIsoErrorCode.securityModuleFailed, "could not build the request MAC", error);
}
message.recalcBitMap();
final OssAcqHeader header = OssAcqHeader(source: config.sourceId, destination: config.destinationId)
..flags = 0x00
..sequence = OssAcqHeader.generateSequence();
message.isoHeader = header.header;
await _ensureConnected(events);
if (beforeSend != null) await beforeSend(message);
events?.onWaitForReceive();
final String key = OssFrameCodec.messageKey(message);
IsoTrace.log(IsoTraceKind.out, "mti=${message.mti} pc=${message.getString(3)} stan=${message.getString(11)} key=$key");
final IsoMsg? response = await _multiplexer.request(
key,
() async {
final Uint8List frame = _codec.encode(message);
IsoTrace.log(IsoTraceKind.out, "frame out, ${frame.length} bytes", bytes: frame);
await _transport!.send(frame);
},
effectiveTimeout,
);
if (response == null) {
IsoTrace.log(IsoTraceKind.result, "nothing came back within ${effectiveTimeout.inSeconds}s");
events?.onReceiveTimeout();
return null;
}
if (!response.isReject) {
final bool macValid = await macComponent.checkMac(response, 4);
if (!macValid) {
IsoTrace.log(IsoTraceKind.result, "the host answered but its MAC did not verify — the response is discarded");
throw UIsoException(UIsoErrorCode.badResponseMac, "the host answered but the response MAC did not verify");
}
IsoTrace.log(IsoTraceKind.mac, "response MAC verified");
} else {
IsoTrace.log(IsoTraceKind.result, "the host rejected the message, reject code ${response.rejectCode}");
}
return response;
}