#include "telnet.h" #include "../string_utils.h" #include "grbl.h" #include #include #include #include #include #include bool iosender::TelnetStream::IsOpen() { return fd > 0 && isConnected; } int iosender::TelnetStream::OutCount() { return 0; } std::string iosender::TelnetStream::Reply() { return reply; } iosender::Comms::StreamType iosender::TelnetStream::StreamType() { return Comms::StreamType::Telnet; } bool iosender::TelnetStream::EventMode() { return eventMode; } void iosender::TelnetStream::EventMode(bool mode) { eventMode = mode; } void iosender::TelnetStream::Close() { shouldQuit = true; workerThread.join(); } int iosender::TelnetStream::ReadByte() { return 0; } void iosender::TelnetStream::WriteByte(uint8_t data) { auto result = write(fd, &data, 1); if (result == -1) { std::cerr << "Failed while writing." << std::endl; } } void iosender::TelnetStream::WriteBytes(uint8_t *bytes, int len) { ssize_t written_bytes = 0; for (; written_bytes < len;) { auto result = write(fd, &bytes, len); if (result == -1) { std::cerr << "Failed while writing." << std::endl; return; } written_bytes += result; } } void iosender::TelnetStream::WriteString(std::string data) { WriteBytes(reinterpret_cast(data.data()), data.size()); } void iosender::TelnetStream::WriteCommand(std::string command) { CommandState = Comms::State::AwaitAck; if (command.size() == 1 && command != GrblConstants::CMD_PROGRAM_DEMARCATION) { WriteByte(*command.data()); } else { command += "\r"; WriteString(command); } } std::string iosender::TelnetStream::GetReply(std::string command) { reply = ""; AwaitResponse(command); return reply; } void iosender::TelnetStream::AwaitAck() { while (Comms::GetCom()->CommandState == Comms::State::DataReceived || Comms::GetCom()->CommandState == Comms::State::AwaitAck) { std::this_thread::sleep_for(std::chrono::microseconds(500)); } } void iosender::TelnetStream::AwaitAck(std::string command) { WriteCommand(command); AwaitAck(); } void iosender::TelnetStream::AwaitResponse() { while (Comms::GetCom()->CommandState == Comms::State::AwaitAck) { std::this_thread::sleep_for(std::chrono::microseconds(500)); } } void iosender::TelnetStream::AwaitResponse(std::string command) { WriteCommand(command); AwaitResponse(); } void iosender::TelnetStream::PurgeQueue() { } iosender::TelnetStream::TelnetStream(std::string host, iosender::DataReceivedHandler *dataHandler, iosender::ByteReceivedHandler *byteHandler) { Comms::SetCom(this); reply = ""; dataReceivedHandler = dataHandler; byteReceivedHandler = byteHandler; if (!string_contains(host, ":")) { host += ":23"; } auto parameter = split_string(host, ":"); auto ip = parameter[0]; auto port = std::stoi(parameter[1]); fd = socket(AF_INET, SOCK_STREAM, 0); if (fd == -1) { std::cerr << "Error creating socket" << std::endl; } struct sockaddr_in serv_addr{}; serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(port); if (inet_pton(AF_INET, ip.c_str(), &serv_addr.sin_addr) <= 0) { std::cerr << "Invalid address/ Address not supported" << std::endl; return; } auto status = connect(fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)); if (status < 0) { std::cerr << "Connection failed"; return; } isConnected = true; // set non-blocking please, after we connected fcntl(fd, F_SETFL, O_NONBLOCK); workerThread = std::thread(&iosender::TelnetStream::readWorker, this); } iosender::TelnetStream::~TelnetStream() { Close(); } void iosender::TelnetStream::readWorker() { std::string received; uint8_t buffer[200]; while (!shouldQuit) { if (isConnected) { // anything to read? auto readBytes = read(fd, buffer, 200); if (readBytes == -1 && (errno == EWOULDBLOCK || errno == EAGAIN)) { // do nothing } else if (readBytes == -1) { std::cerr << "Failed while reading." << std::endl; Close(); } else { for (int i = 0; i < readBytes; i++) { auto isEol = buffer[i] == '\n'; if (isEol) { reply = received; CommandState = reply == "ok" ? Comms::State::ACK : (starts_with(reply, "error") ? Comms::State::NAK : Comms::State::DataReceived); if (!reply.empty() && dataReceivedHandler != nullptr) { dataReceivedHandler->DataReceived(reply); } received.clear(); } else { received.push_back(static_cast(buffer[i])); } } } // give some time to others std::this_thread::sleep_for(std::chrono::milliseconds(1)); } } }