TCP: Implemented ACK return stream, as a feedback channel (to be read properly!)
This commit is contained in:
@@ -51,6 +51,77 @@ TCPImagePuller::TCPImagePuller(const std::string &tcp_addr,
|
||||
cbor_thread = std::thread(&TCPImagePuller::CBORThread, this);
|
||||
}
|
||||
|
||||
bool TCPImagePuller::SendAll(const void *buf, size_t len) {
|
||||
const auto *p = static_cast<const uint8_t *>(buf);
|
||||
size_t sent = 0;
|
||||
while (sent < len) {
|
||||
if (disconnect)
|
||||
return false;
|
||||
|
||||
int local_fd = -1;
|
||||
{
|
||||
std::unique_lock ul(fd_mutex);
|
||||
local_fd = fd;
|
||||
}
|
||||
if (local_fd < 0)
|
||||
return false;
|
||||
|
||||
ssize_t rc = ::send(local_fd, p + sent, len - sent, MSG_NOSIGNAL);
|
||||
if (rc < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
return false;
|
||||
}
|
||||
sent += static_cast<size_t>(rc);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TCPImagePuller::SendAck(const PullerAckMessage &ack) {
|
||||
TcpFrameHeader h{};
|
||||
h.type = static_cast<uint16_t>(TCPFrameType::ACK);
|
||||
h.run_number = ack.run_number;
|
||||
h.socket_number = ack.socket_number;
|
||||
h.image_number = ack.image_number;
|
||||
h.flags = 0;
|
||||
if (ack.ok)
|
||||
h.flags |= TCP_ACK_FLAG_OK;
|
||||
if (ack.fatal)
|
||||
h.flags |= TCP_ACK_FLAG_FATAL;
|
||||
if (!ack.error_text.empty())
|
||||
h.flags |= TCP_ACK_FLAG_HAS_ERROR_TEXT;
|
||||
|
||||
h.ack_for = static_cast<uint16_t>(ack.ack_for);
|
||||
h.ack_processed_images = ack.processed_images;
|
||||
h.ack_code = static_cast<uint32_t>(ack.error_code);
|
||||
h.payload_size = ack.error_text.size();
|
||||
|
||||
if (!SendAll(&h, sizeof(h)))
|
||||
return false;
|
||||
if (!ack.error_text.empty())
|
||||
return SendAll(ack.error_text.data(), ack.error_text.size());
|
||||
return true;
|
||||
}
|
||||
|
||||
void TCPImagePuller::CBORThread() {
|
||||
auto ret = cbor_fifo.GetBlocking();
|
||||
while (ret.tcp_msg) {
|
||||
try {
|
||||
const auto type = static_cast<TCPFrameType>(ret.tcp_msg->header.type);
|
||||
if (type == TCPFrameType::CANCEL) {
|
||||
outside_fifo.PutBlocking(ret);
|
||||
} else {
|
||||
ret.cbor = CBORStream2Deserialize(ret.tcp_msg->payload.data(), ret.tcp_msg->payload.size());
|
||||
outside_fifo.PutBlocking(ret);
|
||||
}
|
||||
} catch (const JFJochException &e) {
|
||||
logger.ErrorException(e);
|
||||
}
|
||||
ret = cbor_fifo.GetBlocking();
|
||||
}
|
||||
outside_fifo.PutBlocking(ret);
|
||||
}
|
||||
|
||||
TCPImagePuller::~TCPImagePuller() {
|
||||
TCPImagePuller::Disconnect();
|
||||
}
|
||||
@@ -179,6 +250,17 @@ void TCPImagePuller::ReceiverThread() {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ignore ACK on puller side
|
||||
if (static_cast<TCPFrameType>(frame.header.type) == TCPFrameType::ACK) {
|
||||
if (frame.header.payload_size > 0) {
|
||||
std::vector<uint8_t> discard(frame.header.payload_size);
|
||||
if (!ReadExact(discard.data(), discard.size())) {
|
||||
CloseSocket();
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
ImagePullerOutput out;
|
||||
out.tcp_msg = std::make_shared<RawFrame>();
|
||||
out.tcp_msg->header = frame.header;
|
||||
@@ -206,19 +288,6 @@ void TCPImagePuller::ReceiverThread() {
|
||||
cbor_fifo.PutBlocking(ImagePullerOutput{});
|
||||
}
|
||||
|
||||
void TCPImagePuller::CBORThread() {
|
||||
auto ret = cbor_fifo.GetBlocking();
|
||||
while (ret.tcp_msg) {
|
||||
try {
|
||||
ret.cbor = CBORStream2Deserialize(ret.tcp_msg->payload.data(), ret.tcp_msg->payload.size());
|
||||
outside_fifo.PutBlocking(ret);
|
||||
} catch (const JFJochException &e) {
|
||||
logger.ErrorException(e);
|
||||
}
|
||||
ret = cbor_fifo.GetBlocking();
|
||||
}
|
||||
outside_fifo.PutBlocking(ret);
|
||||
}
|
||||
void TCPImagePuller::Disconnect() {
|
||||
if (disconnect.exchange(true))
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user