diff --git a/CMakeLists.txt b/CMakeLists.txt index 105436cfa..4a3788bd8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.13) -project(applewin HOMEPAGE_URL "https://github.com/audetto/AppleWin") +project(applewin HOMEPAGE_URL "https://github.com/FujiNetWIFI/AppleWin") option(BUILD_APPLEN "build ncurses frontend") option(BUILD_QAPPLE "build Qt5 frontend") diff --git a/source/.clang-format b/source/.clang-format new file mode 100644 index 000000000..1c3d88231 --- /dev/null +++ b/source/.clang-format @@ -0,0 +1,5 @@ +BasedOnStyle: LLVM +ColumnLimit: 160 +BreakBeforeBraces: Allman +AllowShortBlocksOnASingleLine: true +AlwaysBreakAfterReturnType: None diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index f8fc180d5..e01476d0d 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -94,6 +94,7 @@ set(SOURCE_FILES Utilities.cpp FrameBase.cpp CmdLine.cpp + SmartPortOverSlip.cpp Configuration/PropertySheetHelper.cpp Configuration/Config.cpp @@ -119,6 +120,36 @@ set(SOURCE_FILES linux/duplicates/SNESMAX.cpp linux/duplicates/Keyboard.cpp + SPoverSLIP/CloseRequest.cpp + SPoverSLIP/CloseResponse.cpp + SPoverSLIP/Connection.cpp + SPoverSLIP/ControlRequest.cpp + SPoverSLIP/ControlResponse.cpp + SPoverSLIP/FormatRequest.cpp + SPoverSLIP/FormatResponse.cpp + SPoverSLIP/InitRequest.cpp + SPoverSLIP/InitResponse.cpp + SPoverSLIP/Listener.cpp + SPoverSLIP/OpenRequest.cpp + SPoverSLIP/OpenResponse.cpp + SPoverSLIP/ReadBlockRequest.cpp + SPoverSLIP/ReadBlockResponse.cpp + SPoverSLIP/ReadRequest.cpp + SPoverSLIP/ReadResponse.cpp + SPoverSLIP/Request.cpp + SPoverSLIP/Requestor.cpp + SPoverSLIP/ResetRequest.cpp + SPoverSLIP/ResetResponse.cpp + SPoverSLIP/Response.cpp + SPoverSLIP/SLIP.cpp + SPoverSLIP/StatusRequest.cpp + SPoverSLIP/StatusResponse.cpp + SPoverSLIP/TCPConnection.cpp + SPoverSLIP/WriteBlockRequest.cpp + SPoverSLIP/WriteBlockResponse.cpp + SPoverSLIP/WriteRequest.cpp + SPoverSLIP/WriteResponse.cpp + Z80VICE/z80.cpp Z80VICE/z80mem.cpp Z80VICE/daa.cpp @@ -178,6 +209,7 @@ set(HEADER_FILES FrameBase.h FourPlay.h SNESMAX.h + SmartPortOverSlip.h Common.h DiskDefs.h @@ -215,6 +247,39 @@ set(HEADER_FILES linux/network/slirp2.h linux/network/portfwds.h + SPoverSLIP/CloseRequest.h + SPoverSLIP/CloseResponse.h + SPoverSLIP/Connection.h + SPoverSLIP/ControlRequest.h + SPoverSLIP/ControlResponse.h + SPoverSLIP/FormatRequest.h + SPoverSLIP/FormatResponse.h + SPoverSLIP/InitRequest.h + SPoverSLIP/InitResponse.h + SPoverSLIP/Listener.h + SPoverSLIP/OpenRequest.h + SPoverSLIP/OpenResponse.h + SPoverSLIP/Packet.h + SPoverSLIP/ReadBlockRequest.h + SPoverSLIP/ReadBlockResponse.h + SPoverSLIP/ReadRequest.h + SPoverSLIP/ReadResponse.h + SPoverSLIP/Request.h + SPoverSLIP/Requestor.h + SPoverSLIP/ResetRequest.h + SPoverSLIP/ResetResponse.h + SPoverSLIP/Response.h + SPoverSLIP/SLIP.h + SPoverSLIP/SmartPortCodes.h + SPoverSLIP/SPoSLIP.h + SPoverSLIP/StatusRequest.h + SPoverSLIP/StatusResponse.h + SPoverSLIP/TCPConnection.h + SPoverSLIP/WriteBlockRequest.h + SPoverSLIP/WriteBlockResponse.h + SPoverSLIP/WriteRequest.h + SPoverSLIP/WriteResponse.h + Z80VICE/z80.h Z80VICE/z80mem.h Z80VICE/z80regs.h diff --git a/source/CardManager.cpp b/source/CardManager.cpp index a6d1e8385..7bb5e9723 100644 --- a/source/CardManager.cpp +++ b/source/CardManager.cpp @@ -27,6 +27,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ +#include "Log.h" #include "StdAfx.h" #include "CardManager.h" @@ -117,6 +118,7 @@ void CardManager::InsertInternal(UINT slot, SS_CARDTYPE type) m_slot[slot] = new Uthernet2(slot); break; case CT_SmartPortOverSlip: + LogOutput("Inserting SP over SLIP in slot %d\n", slot); m_slot[slot] = new SmartPortOverSlip(slot); break; case CT_LanguageCard: diff --git a/source/SPoverSLIP/CloseRequest.cpp b/source/SPoverSLIP/CloseRequest.cpp index 6f9c8a780..290152561 100644 --- a/source/SPoverSLIP/CloseRequest.cpp +++ b/source/SPoverSLIP/CloseRequest.cpp @@ -1,29 +1,26 @@ -#include "stdafx.h" #include "CloseRequest.h" #include "CloseResponse.h" #include "SmartPortCodes.h" - -CloseRequest::CloseRequest(const uint8_t request_sequence_number, const uint8_t sp_unit) - : Request(request_sequence_number, SP_CLOSE, sp_unit) {} +CloseRequest::CloseRequest(const uint8_t request_sequence_number, const uint8_t sp_unit) : Request(request_sequence_number, SP_CLOSE, sp_unit) {} std::vector CloseRequest::serialize() const { - std::vector request_data; - request_data.push_back(this->get_request_sequence_number()); - request_data.push_back(this->get_command_number()); - request_data.push_back(this->get_sp_unit()); - return request_data; + std::vector request_data; + request_data.push_back(this->get_request_sequence_number()); + request_data.push_back(this->get_command_number()); + request_data.push_back(this->get_sp_unit()); + return request_data; } -std::unique_ptr CloseRequest::deserialize(const std::vector& data) const +std::unique_ptr CloseRequest::deserialize(const std::vector &data) const { - if (data.size() < 2) - { - throw std::runtime_error("Not enough data to deserialize CloseResponse"); - } + if (data.size() < 2) + { + throw std::runtime_error("Not enough data to deserialize CloseResponse"); + } - auto response = std::make_unique(data[0], data[1]); - return response; + auto response = std::make_unique(data[0], data[1]); + return response; } diff --git a/source/SPoverSLIP/CloseRequest.h b/source/SPoverSLIP/CloseRequest.h index c20bfeb6a..ca55c360c 100644 --- a/source/SPoverSLIP/CloseRequest.h +++ b/source/SPoverSLIP/CloseRequest.h @@ -1,7 +1,7 @@ #pragma once -#include #include +#include #include "Request.h" #include "Response.h" @@ -9,7 +9,7 @@ class CloseRequest : public Request { public: - CloseRequest(uint8_t request_sequence_number, uint8_t sp_unit); - std::vector serialize() const override; - std::unique_ptr deserialize(const std::vector& data) const override; + CloseRequest(uint8_t request_sequence_number, uint8_t sp_unit); + std::vector serialize() const override; + std::unique_ptr deserialize(const std::vector &data) const override; }; diff --git a/source/SPoverSLIP/CloseResponse.cpp b/source/SPoverSLIP/CloseResponse.cpp index cb4abc4e6..cdd5230c9 100644 --- a/source/SPoverSLIP/CloseResponse.cpp +++ b/source/SPoverSLIP/CloseResponse.cpp @@ -1,12 +1,11 @@ -#include "stdafx.h" #include "CloseResponse.h" CloseResponse::CloseResponse(const uint8_t request_sequence_number, const uint8_t status) : Response(request_sequence_number, status) {} std::vector CloseResponse::serialize() const { - std::vector data; - data.push_back(this->get_request_sequence_number()); - data.push_back(this->get_status()); - return data; + std::vector data; + data.push_back(this->get_request_sequence_number()); + data.push_back(this->get_status()); + return data; } \ No newline at end of file diff --git a/source/SPoverSLIP/CloseResponse.h b/source/SPoverSLIP/CloseResponse.h index 5b921fe64..4143c9452 100644 --- a/source/SPoverSLIP/CloseResponse.h +++ b/source/SPoverSLIP/CloseResponse.h @@ -4,6 +4,6 @@ class CloseResponse : public Response { public: - explicit CloseResponse(uint8_t request_sequence_number, uint8_t status); - std::vector serialize() const override; + explicit CloseResponse(uint8_t request_sequence_number, uint8_t status); + std::vector serialize() const override; }; diff --git a/source/SPoverSLIP/Connection.cpp b/source/SPoverSLIP/Connection.cpp index 813833133..606073d9f 100644 --- a/source/SPoverSLIP/Connection.cpp +++ b/source/SPoverSLIP/Connection.cpp @@ -1,39 +1,39 @@ -#include "StdAfx.h" - -#include +#include "Connection.h" +#include #include #include -#include -#include "Connection.h" +#include +#include std::vector Connection::wait_for_response(uint8_t request_id, std::chrono::seconds timeout) { - std::unique_lock lock(responses_mutex_); - // mutex is unlocked as it goes into a wait, so then the inserting thread can add to map, and this can then pick it up when notified, or timeout. - if (!response_cv_.wait_for(lock, timeout, [this, request_id]() { return responses_.count(request_id) > 0; })) - { - throw std::runtime_error("Timeout waiting for response"); - } - std::vector response_data = responses_[request_id]; - responses_.erase(request_id); - return response_data; + std::unique_lock lock(responses_mutex_); + // mutex is unlocked as it goes into a wait, so then the inserting thread can + // add to map, and this can then pick it up when notified, or timeout. + if (!response_cv_.wait_for(lock, timeout, [this, request_id]() { return responses_.count(request_id) > 0; })) + { + throw std::runtime_error("Timeout waiting for response"); + } + std::vector response_data = responses_[request_id]; + responses_.erase(request_id); + return response_data; } std::vector Connection::wait_for_request() { - std::unique_lock lock(responses_mutex_); - response_cv_.wait(lock, [this]() { return !responses_.empty(); }); - const auto it = responses_.begin(); - std::vector request_data = it->second; - responses_.erase(it); + std::unique_lock lock(responses_mutex_); + response_cv_.wait(lock, [this]() { return !responses_.empty(); }); + const auto it = responses_.begin(); + std::vector request_data = it->second; + responses_.erase(it); - return request_data; + return request_data; } void Connection::join() { - if (reading_thread_.joinable()) - { - reading_thread_.join(); - } + if (reading_thread_.joinable()) + { + reading_thread_.join(); + } } diff --git a/source/SPoverSLIP/Connection.h b/source/SPoverSLIP/Connection.h index f61e6fc43..1bca4ee20 100644 --- a/source/SPoverSLIP/Connection.h +++ b/source/SPoverSLIP/Connection.h @@ -1,36 +1,37 @@ #pragma once -#include #include -#include +#include +#include #include +#include #include -#include -#include +#include +#include class Connection { public: - virtual ~Connection() = default; - virtual void send_data(const std::vector& data) = 0; + virtual ~Connection() = default; + virtual void send_data(const std::vector &data) = 0; - virtual void create_read_channel() = 0; + virtual void create_read_channel() = 0; - bool is_connected() const { return is_connected_; } - void set_is_connected(const bool is_connected) { is_connected_ = is_connected; } + bool is_connected() const { return is_connected_; } + void set_is_connected(const bool is_connected) { is_connected_ = is_connected; } - std::vector wait_for_response(uint8_t request_id, std::chrono::seconds timeout); - std::vector wait_for_request(); + std::vector wait_for_response(uint8_t request_id, std::chrono::seconds timeout); + std::vector wait_for_request(); - void join(); + void join(); private: - std::atomic is_connected_{false}; + std::atomic is_connected_{false}; protected: - std::map> responses_; - std::thread reading_thread_; + std::map> responses_; + std::thread reading_thread_; - std::mutex responses_mutex_; - std::condition_variable response_cv_; + std::mutex responses_mutex_; + std::condition_variable response_cv_; }; diff --git a/source/SPoverSLIP/ControlRequest.cpp b/source/SPoverSLIP/ControlRequest.cpp index 015b24ae2..9efa7b5b4 100644 --- a/source/SPoverSLIP/ControlRequest.cpp +++ b/source/SPoverSLIP/ControlRequest.cpp @@ -1,31 +1,31 @@ -#include "stdafx.h" #include "ControlRequest.h" #include "ControlResponse.h" #include "SmartPortCodes.h" - -ControlRequest::ControlRequest(const uint8_t request_sequence_number, const uint8_t sp_unit, const uint8_t control_code, std::vector& data) - : Request(request_sequence_number, SP_CONTROL, sp_unit), control_code_(control_code), data_(std::move(data)) {} +ControlRequest::ControlRequest(const uint8_t request_sequence_number, const uint8_t sp_unit, const uint8_t control_code, std::vector &data) + : Request(request_sequence_number, SP_CONTROL, sp_unit), control_code_(control_code), data_(std::move(data)) +{ +} std::vector ControlRequest::serialize() const { - std::vector request_data; - request_data.push_back(this->get_request_sequence_number()); - request_data.push_back(this->get_command_number()); - request_data.push_back(this->get_sp_unit()); - request_data.push_back(this->get_control_code()); - request_data.insert(request_data.end(), get_data().begin(), get_data().end()); - return request_data; + std::vector request_data; + request_data.push_back(this->get_request_sequence_number()); + request_data.push_back(this->get_command_number()); + request_data.push_back(this->get_sp_unit()); + request_data.push_back(this->get_control_code()); + request_data.insert(request_data.end(), get_data().begin(), get_data().end()); + return request_data; } -std::unique_ptr ControlRequest::deserialize(const std::vector& data) const +std::unique_ptr ControlRequest::deserialize(const std::vector &data) const { - if (data.size() < 2) - { - throw std::runtime_error("Not enough data to deserialize ControlResponse"); - } + if (data.size() < 2) + { + throw std::runtime_error("Not enough data to deserialize ControlResponse"); + } - auto response = std::make_unique(data[0], data[1]); - return response; + auto response = std::make_unique(data[0], data[1]); + return response; } diff --git a/source/SPoverSLIP/ControlRequest.h b/source/SPoverSLIP/ControlRequest.h index 8f9ed99aa..6d8ae5653 100644 --- a/source/SPoverSLIP/ControlRequest.h +++ b/source/SPoverSLIP/ControlRequest.h @@ -1,7 +1,7 @@ #pragma once -#include #include +#include #include "Request.h" #include "Response.h" @@ -9,14 +9,14 @@ class ControlRequest : public Request { public: - ControlRequest(const uint8_t request_sequence_number, const uint8_t sp_unit, const uint8_t control_code, std::vector& data); - std::vector serialize() const override; - std::unique_ptr deserialize(const std::vector& data) const override; + ControlRequest(const uint8_t request_sequence_number, const uint8_t sp_unit, const uint8_t control_code, std::vector &data); + std::vector serialize() const override; + std::unique_ptr deserialize(const std::vector &data) const override; - const std::vector& get_data() const { return data_; } - uint8_t get_control_code() const { return control_code_; } + const std::vector &get_data() const { return data_; } + uint8_t get_control_code() const { return control_code_; } private: - uint8_t control_code_; - std::vector data_; + uint8_t control_code_; + std::vector data_; }; diff --git a/source/SPoverSLIP/ControlResponse.cpp b/source/SPoverSLIP/ControlResponse.cpp index de8ecc418..e76e06bca 100644 --- a/source/SPoverSLIP/ControlResponse.cpp +++ b/source/SPoverSLIP/ControlResponse.cpp @@ -1,12 +1,11 @@ -#include "stdafx.h" #include "ControlResponse.h" ControlResponse::ControlResponse(const uint8_t request_sequence_number, const uint8_t status) : Response(request_sequence_number, status) {} std::vector ControlResponse::serialize() const { - std::vector data; - data.push_back(this->get_request_sequence_number()); - data.push_back(this->get_status()); - return data; + std::vector data; + data.push_back(this->get_request_sequence_number()); + data.push_back(this->get_status()); + return data; } \ No newline at end of file diff --git a/source/SPoverSLIP/ControlResponse.h b/source/SPoverSLIP/ControlResponse.h index bcff3af9b..73a20a62a 100644 --- a/source/SPoverSLIP/ControlResponse.h +++ b/source/SPoverSLIP/ControlResponse.h @@ -4,6 +4,6 @@ class ControlResponse : public Response { public: - explicit ControlResponse(uint8_t request_sequence_number, uint8_t status); - std::vector serialize() const override; + explicit ControlResponse(uint8_t request_sequence_number, uint8_t status); + std::vector serialize() const override; }; diff --git a/source/SPoverSLIP/FormatRequest.cpp b/source/SPoverSLIP/FormatRequest.cpp index 81ae165cf..5991ace28 100644 --- a/source/SPoverSLIP/FormatRequest.cpp +++ b/source/SPoverSLIP/FormatRequest.cpp @@ -1,29 +1,26 @@ -#include "stdafx.h" #include "FormatRequest.h" #include "FormatResponse.h" #include "SmartPortCodes.h" - -FormatRequest::FormatRequest(const uint8_t request_sequence_number, const uint8_t sp_unit) - : Request(request_sequence_number, SP_FORMAT, sp_unit) {} +FormatRequest::FormatRequest(const uint8_t request_sequence_number, const uint8_t sp_unit) : Request(request_sequence_number, SP_FORMAT, sp_unit) {} std::vector FormatRequest::serialize() const { - std::vector request_data; - request_data.push_back(this->get_request_sequence_number()); - request_data.push_back(this->get_command_number()); - request_data.push_back(this->get_sp_unit()); - return request_data; + std::vector request_data; + request_data.push_back(this->get_request_sequence_number()); + request_data.push_back(this->get_command_number()); + request_data.push_back(this->get_sp_unit()); + return request_data; } -std::unique_ptr FormatRequest::deserialize(const std::vector& data) const +std::unique_ptr FormatRequest::deserialize(const std::vector &data) const { - if (data.size() < 2) - { - throw std::runtime_error("Not enough data to deserialize FormatResponse"); - } + if (data.size() < 2) + { + throw std::runtime_error("Not enough data to deserialize FormatResponse"); + } - auto response = std::make_unique(data[0], data[1]); - return response; + auto response = std::make_unique(data[0], data[1]); + return response; } diff --git a/source/SPoverSLIP/FormatRequest.h b/source/SPoverSLIP/FormatRequest.h index 7b71aed60..b942cef02 100644 --- a/source/SPoverSLIP/FormatRequest.h +++ b/source/SPoverSLIP/FormatRequest.h @@ -1,7 +1,7 @@ #pragma once -#include #include +#include #include "Request.h" #include "Response.h" @@ -9,7 +9,7 @@ class FormatRequest : public Request { public: - FormatRequest(const uint8_t request_sequence_number, const uint8_t sp_unit); - std::vector serialize() const override; - std::unique_ptr deserialize(const std::vector& data) const override; + FormatRequest(const uint8_t request_sequence_number, const uint8_t sp_unit); + std::vector serialize() const override; + std::unique_ptr deserialize(const std::vector &data) const override; }; diff --git a/source/SPoverSLIP/FormatResponse.cpp b/source/SPoverSLIP/FormatResponse.cpp index cd34fb652..5c6e29502 100644 --- a/source/SPoverSLIP/FormatResponse.cpp +++ b/source/SPoverSLIP/FormatResponse.cpp @@ -1,12 +1,11 @@ -#include "stdafx.h" #include "FormatResponse.h" FormatResponse::FormatResponse(const uint8_t request_sequence_number, const uint8_t status) : Response(request_sequence_number, status) {} std::vector FormatResponse::serialize() const { - std::vector data; - data.push_back(this->get_request_sequence_number()); - data.push_back(this->get_status()); - return data; + std::vector data; + data.push_back(this->get_request_sequence_number()); + data.push_back(this->get_status()); + return data; } \ No newline at end of file diff --git a/source/SPoverSLIP/FormatResponse.h b/source/SPoverSLIP/FormatResponse.h index 04b785f7a..dccb1a1ec 100644 --- a/source/SPoverSLIP/FormatResponse.h +++ b/source/SPoverSLIP/FormatResponse.h @@ -4,6 +4,6 @@ class FormatResponse : public Response { public: - explicit FormatResponse(uint8_t request_sequence_number, uint8_t status); - std::vector serialize() const override; + explicit FormatResponse(uint8_t request_sequence_number, uint8_t status); + std::vector serialize() const override; }; diff --git a/source/SPoverSLIP/InitRequest.cpp b/source/SPoverSLIP/InitRequest.cpp index e8231039e..7ea138c93 100644 --- a/source/SPoverSLIP/InitRequest.cpp +++ b/source/SPoverSLIP/InitRequest.cpp @@ -1,29 +1,26 @@ -#include "stdafx.h" #include "InitRequest.h" #include "InitResponse.h" #include "SmartPortCodes.h" - -InitRequest::InitRequest(const uint8_t request_sequence_number, const uint8_t sp_unit) - : Request(request_sequence_number, SP_INIT, sp_unit) {} +InitRequest::InitRequest(const uint8_t request_sequence_number, const uint8_t sp_unit) : Request(request_sequence_number, SP_INIT, sp_unit) {} std::vector InitRequest::serialize() const { - std::vector request_data; - request_data.push_back(this->get_request_sequence_number()); - request_data.push_back(this->get_command_number()); - request_data.push_back(this->get_sp_unit()); - return request_data; + std::vector request_data; + request_data.push_back(this->get_request_sequence_number()); + request_data.push_back(this->get_command_number()); + request_data.push_back(this->get_sp_unit()); + return request_data; } -std::unique_ptr InitRequest::deserialize(const std::vector& data) const +std::unique_ptr InitRequest::deserialize(const std::vector &data) const { - if (data.size() < 2) - { - throw std::runtime_error("Not enough data to deserialize InitResponse"); - } + if (data.size() < 2) + { + throw std::runtime_error("Not enough data to deserialize InitResponse"); + } - auto response = std::make_unique(data[0], data[1]); - return response; + auto response = std::make_unique(data[0], data[1]); + return response; } diff --git a/source/SPoverSLIP/InitRequest.h b/source/SPoverSLIP/InitRequest.h index 7c5ad5b9f..9132f7771 100644 --- a/source/SPoverSLIP/InitRequest.h +++ b/source/SPoverSLIP/InitRequest.h @@ -1,7 +1,7 @@ #pragma once -#include #include +#include #include "Request.h" #include "Response.h" @@ -9,7 +9,7 @@ class InitRequest : public Request { public: - InitRequest(uint8_t request_sequence_number, uint8_t sp_unit); - std::vector serialize() const override; - std::unique_ptr deserialize(const std::vector& data) const override; + InitRequest(uint8_t request_sequence_number, uint8_t sp_unit); + std::vector serialize() const override; + std::unique_ptr deserialize(const std::vector &data) const override; }; diff --git a/source/SPoverSLIP/InitResponse.cpp b/source/SPoverSLIP/InitResponse.cpp index cf4698554..b9a167c8e 100644 --- a/source/SPoverSLIP/InitResponse.cpp +++ b/source/SPoverSLIP/InitResponse.cpp @@ -1,12 +1,11 @@ -#include "stdafx.h" #include "InitResponse.h" InitResponse::InitResponse(const uint8_t request_sequence_number, const uint8_t status) : Response(request_sequence_number, status) {} std::vector InitResponse::serialize() const { - std::vector data; - data.push_back(this->get_request_sequence_number()); - data.push_back(this->get_status()); - return data; + std::vector data; + data.push_back(this->get_request_sequence_number()); + data.push_back(this->get_status()); + return data; } \ No newline at end of file diff --git a/source/SPoverSLIP/InitResponse.h b/source/SPoverSLIP/InitResponse.h index f539564c3..5b53c5d58 100644 --- a/source/SPoverSLIP/InitResponse.h +++ b/source/SPoverSLIP/InitResponse.h @@ -4,6 +4,6 @@ class InitResponse : public Response { public: - explicit InitResponse(uint8_t request_sequence_number, uint8_t status); - std::vector serialize() const override; + explicit InitResponse(uint8_t request_sequence_number, uint8_t status); + std::vector serialize() const override; }; diff --git a/source/SPoverSLIP/Listener.cpp b/source/SPoverSLIP/Listener.cpp index aa0ca4d23..af6717504 100644 --- a/source/SPoverSLIP/Listener.cpp +++ b/source/SPoverSLIP/Listener.cpp @@ -1,210 +1,234 @@ -#include "StdAfx.h" +#include #include -#include #include +#include +#include +#include +#include +#include #include "Listener.h" #include "InitRequest.h" #include "InitResponse.h" -#include "TCPConnection.h" #include "SLIP.h" +#include "TCPConnection.h" #include "Log.h" #include "Requestor.h" +// clang-format off +#ifdef WIN32 + #include + #pragma comment(lib, "ws2_32.lib") + #define CLOSE_SOCKET closesocket + #define SOCKET_ERROR_CODE WSAGetLastError() +#else + #include + #define CLOSE_SOCKET close + #define SOCKET_ERROR_CODE errno + #define INVALID_SOCKET -1 + #define SOCKET_ERROR -1 +#endif +// clang-format off + uint8_t Listener::next_device_id_ = 1; -Listener::Listener(std::string ip_address, const u_short port): ip_address_(std::move(ip_address)), port_(port), is_listening_(false) +Listener::Listener(std::string ip_address, const u_short port) + : ip_address_(std::move(ip_address)), port_(port), is_listening_(false) { } -bool Listener::get_is_listening() const -{ - return is_listening_; -} +bool Listener::get_is_listening() const { return is_listening_; } -void Listener::insert_connection(uint8_t start_id, uint8_t end_id, const std::shared_ptr& conn) +void Listener::insert_connection(uint8_t start_id, uint8_t end_id, const std::shared_ptr &conn) { - connection_map_[{start_id, end_id}] = conn; + connection_map_[{start_id, end_id}] = conn; } -uint8_t Listener::get_total_device_count() -{ - return next_device_id_ - 1; -} +uint8_t Listener::get_total_device_count() { return next_device_id_ - 1; } -Listener::~Listener() -{ - stop(); -} +Listener::~Listener() { stop(); } -std::thread Listener::create_listener_thread() -{ - return std::thread(&Listener::listener_function, this); -} +std::thread Listener::create_listener_thread() { return std::thread(&Listener::listener_function, this); } void Listener::listener_function() { - LogFileOutput("Listener::listener_function - RUNNING\n"); - unsigned int server_fd, new_socket; - struct sockaddr_in address; - int address_length = sizeof(address); - WSADATA wsa_data; - WSAStartup(MAKEWORD(2, 2), &wsa_data); - if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) - { - LogFileOutput("Listener::listener_function - Socket creation failed\n"); - return; - } - - address.sin_family = AF_INET; - address.sin_port = htons(port_); - address.sin_addr.s_addr = inet_addr(ip_address_.c_str()); - - if (bind(server_fd, reinterpret_cast(&address), sizeof(address)) == SOCKET_ERROR) - { - LogFileOutput("Listener::listener_function - bind failed\n"); - return; - } - - if (listen(server_fd, 3) < 0) - { - LogFileOutput("Listener::listener_function - listen failed\n"); - return; - } - - while (is_listening_) - { - fd_set sock_set; - FD_ZERO(&sock_set); - FD_SET(server_fd, &sock_set); - - timeval timeout; - timeout.tv_sec = 2; - timeout.tv_usec = 0; - - const int activity = select(0, &sock_set, nullptr, nullptr, &timeout); - - if (activity == SOCKET_ERROR) { - LogFileOutput("Listener::listener_function - select failed\n"); - is_listening_ = false; - break; - } - - if (activity == 0) { - // timeout occurred, no client connection. Still need to check is_listening_ - continue; - } - - if ((new_socket = accept(server_fd, reinterpret_cast(&address), &address_length)) == INVALID_SOCKET) - { - LogFileOutput("Listener::listener_function - accept failed\n"); - is_listening_ = false; - break; - } - - create_connection(new_socket); - } - - LogFileOutput("Listener::listener_function - listener closing down\n"); - - closesocket(server_fd); - WSACleanup(); + LogFileOutput("Listener::listener_function - RUNNING\n"); + int server_fd, new_socket; + struct sockaddr_in address; + socklen_t address_length = sizeof(address); + +#ifdef WIN32 + WSADATA wsa_data; + WSAStartup(MAKEWORD(2, 2), &wsa_data); +#endif + + if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) + { + LogFileOutput("Listener::listener_function - Socket creation failed\n"); + return; + } + + address.sin_family = AF_INET; + address.sin_port = htons(port_); + address.sin_addr.s_addr = inet_addr(ip_address_.c_str()); + + if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) == SOCKET_ERROR) + { + LogFileOutput("Listener::listener_function - bind failed\n"); + return; + } + + if (listen(server_fd, 3) < 0) + { + LogFileOutput("Listener::listener_function - listen failed\n"); + return; + } + + while (is_listening_) + { + fd_set sock_set; + FD_ZERO(&sock_set); + FD_SET(server_fd, &sock_set); + + timeval timeout; + timeout.tv_sec = 2; + timeout.tv_usec = 0; + + const int activity = select(server_fd + 1, &sock_set, nullptr, nullptr, &timeout); + + if (activity == SOCKET_ERROR) + { + LogFileOutput("Listener::listener_function - select failed\n"); + is_listening_ = false; + break; + } + + if (activity == 0) + { + // timeout occurred, no client connection. Still need to check is_listening_ + continue; + } + + if ((new_socket = accept(server_fd, (struct sockaddr *)&address, &address_length)) == INVALID_SOCKET) + { + LogFileOutput("Listener::listener_function - accept failed\n"); + is_listening_ = false; + break; + } + + create_connection(new_socket); + } + + LogFileOutput("Listener::listener_function - listener closing down\n"); + + CLOSE_SOCKET(server_fd); +#ifdef WIN32 + WSACleanup(); +#endif } // Creates a Connection object, which is how SP device(s) will register itself with our listener. void Listener::create_connection(unsigned int socket) { - // Create a connection, give it some time to settle, else exit without creating listener to connection - const std::shared_ptr conn = std::make_shared(socket); - conn->create_read_channel(); - - const auto start = std::chrono::steady_clock::now(); - // Give the connection a generous 10 seconds to work. - constexpr auto timeout = std::chrono::seconds(10); - - while (!conn->is_connected()) - { - auto now = std::chrono::steady_clock::now(); - if (std::chrono::duration_cast(now - start) > timeout) { - LogFileOutput("Listener::create_connection() - Failed to establish connection, timed out.\n"); - return; - } - } - - // We need to send an INIT to device 01 for this connection, then 02, ... until we get an error back - // This will determine the number of devices attached. - - bool still_scanning = true; - uint8_t unit_id = 1; - - // send init requests to find all the devices on this connection, or we have too many devices. - while(still_scanning && (unit_id + next_device_id_) < 255) - { - LogFileOutput("SmartPortOverSlip listener sending request for unit_id: %d\n", unit_id); - InitRequest request(Requestor::next_request_number(), unit_id); - const auto response = Requestor::send_request(request, conn.get()); - const auto init_response = dynamic_cast(response.get()); - still_scanning = init_response->get_status() == 0; - if (still_scanning) unit_id++; - } - - const auto start_id = next_device_id_; - const auto end_id = static_cast(start_id + unit_id - 1); - next_device_id_ = end_id + 1; - // track the connection and device ranges it reported. Further connections can add to the devices we can target. - LogFileOutput("SmartPortOverSlip listener creating connection for start: %d, end: %d\n", start_id, end_id); - insert_connection(start_id, end_id, conn); + // Create a connection, give it some time to settle, else exit without creating listener to connection + const std::shared_ptr conn = std::make_shared(socket); + conn->create_read_channel(); + + const auto start = std::chrono::steady_clock::now(); + // Give the connection a generous 10 seconds to work. + constexpr auto timeout = std::chrono::seconds(10); + + while (!conn->is_connected()) + { + auto now = std::chrono::steady_clock::now(); + if (std::chrono::duration_cast(now - start) > timeout) + { + LogFileOutput("Listener::create_connection() - Failed to establish " + "connection, timed out.\n"); + return; + } + } + + // We need to send an INIT to device 01 for this connection, then 02, ... + // until we get an error back This will determine the number of devices + // attached. + + bool still_scanning = true; + uint8_t unit_id = 1; + + // send init requests to find all the devices on this connection, or we have too many devices. + while (still_scanning && (unit_id + next_device_id_) < 255) + { + LogFileOutput("SmartPortOverSlip listener sending request for unit_id: %d\n", unit_id); + InitRequest request(Requestor::next_request_number(), unit_id); + const auto response = Requestor::send_request(request, conn.get()); + const auto init_response = dynamic_cast(response.get()); + still_scanning = init_response->get_status() == 0; + if (still_scanning) + unit_id++; + } + + const auto start_id = next_device_id_; + const auto end_id = static_cast(start_id + unit_id - 1); + next_device_id_ = end_id + 1; + // track the connection and device ranges it reported. Further connections can add to the devices we can target. + LogFileOutput("SmartPortOverSlip listener creating connection for start: %d, end: %d\n", start_id, end_id); + insert_connection(start_id, end_id, conn); } void Listener::start() { - is_listening_ = true; - listening_thread_ = std::thread(&Listener::listener_function, this); + is_listening_ = true; + listening_thread_ = std::thread(&Listener::listener_function, this); } void Listener::stop() { - LogFileOutput("Listener::stop()\n"); - if (is_listening_) - { - // Give our own thread time to stop while we stop the connections. - is_listening_ = false; - - for (auto& pair : connection_map_) - { - const auto& connection = pair.second; - connection->set_is_connected(false); - connection->join(); - } - LogFileOutput("Listener::stop() ... joining listener until it stops\n"); - listening_thread_.join(); - } - LogFileOutput("Listener::stop() ... finished\n"); + LogFileOutput("Listener::stop()\n"); + if (is_listening_) + { + // Give our own thread time to stop while we stop the connections. + is_listening_ = false; + + for (auto &pair : connection_map_) + { + const auto &connection = pair.second; + connection->set_is_connected(false); + connection->join(); + } + LogFileOutput("Listener::stop() ... joining listener until it stops\n"); + listening_thread_.join(); + } + LogFileOutput("Listener::stop() ... finished\n"); } // Returns the lower bound of the device id, and connection. std::pair> Listener::find_connection_with_device(const uint8_t device_id) const { - std::pair> result; - for (const auto& kv : connection_map_) { - if (device_id >= kv.first.first && device_id <= kv.first.second) { - result = std::make_pair(kv.first.first, kv.second); - break; - } - } - return result; + std::pair> result; + for (const auto &kv : connection_map_) + { + if (device_id >= kv.first.first && device_id <= kv.first.second) + { + result = std::make_pair(kv.first.first, kv.second); + break; + } + } + return result; } -std::vector> Listener::get_all_connections() const +std::vector> Listener::get_all_connections() const { - std::vector> connections; - for (const auto& kv : connection_map_) { - for (uint8_t id = kv.first.first; id <= kv.first.second; ++id) { - connections.emplace_back(id, kv.second.get()); - } - } - return connections; + std::vector> connections; + for (const auto &kv : connection_map_) + { + for (uint8_t id = kv.first.first; id <= kv.first.second; ++id) + { + connections.emplace_back(id, kv.second.get()); + } + } + return connections; } diff --git a/source/SPoverSLIP/Listener.h b/source/SPoverSLIP/Listener.h index de9096f13..43df3f6dd 100644 --- a/source/SPoverSLIP/Listener.h +++ b/source/SPoverSLIP/Listener.h @@ -10,32 +10,32 @@ class Listener { public: - Listener(std::string ip_address, const u_short port); + Listener(std::string ip_address, const u_short port); - ~Listener(); + ~Listener(); - void start(); - void stop(); + void start(); + void stop(); - std::thread create_listener_thread(); - bool get_is_listening() const; + std::thread create_listener_thread(); + bool get_is_listening() const; - std::pair> find_connection_with_device(const uint8_t device_id) const; - std::vector> get_all_connections() const; + std::pair> find_connection_with_device(const uint8_t device_id) const; + std::vector> get_all_connections() const; - void insert_connection(uint8_t start_id, uint8_t end_id, const std::shared_ptr& conn); + void insert_connection(uint8_t start_id, uint8_t end_id, const std::shared_ptr &conn); - static uint8_t get_total_device_count(); + static uint8_t get_total_device_count(); private: - std::string ip_address_; - u_short port_; - std::mutex mtx_; - std::thread listening_thread_; - static uint8_t next_device_id_; - std::map, std::shared_ptr> connection_map_; - - bool is_listening_; - void create_connection(unsigned int socket); - void listener_function(); + std::string ip_address_; + u_short port_; + std::mutex mtx_; + std::thread listening_thread_; + static uint8_t next_device_id_; + std::map, std::shared_ptr> connection_map_; + + bool is_listening_; + void create_connection(unsigned int socket); + void listener_function(); }; diff --git a/source/SPoverSLIP/OpenRequest.cpp b/source/SPoverSLIP/OpenRequest.cpp index 7e65290a8..0c23be2a5 100644 --- a/source/SPoverSLIP/OpenRequest.cpp +++ b/source/SPoverSLIP/OpenRequest.cpp @@ -1,29 +1,26 @@ -#include "stdafx.h" #include "OpenRequest.h" #include "OpenResponse.h" #include "SmartPortCodes.h" - -OpenRequest::OpenRequest(const uint8_t request_sequence_number, const uint8_t sp_unit) - : Request(request_sequence_number, SP_OPEN, sp_unit) {} +OpenRequest::OpenRequest(const uint8_t request_sequence_number, const uint8_t sp_unit) : Request(request_sequence_number, SP_OPEN, sp_unit) {} std::vector OpenRequest::serialize() const { - std::vector request_data; - request_data.push_back(this->get_request_sequence_number()); - request_data.push_back(this->get_command_number()); - request_data.push_back(this->get_sp_unit()); - return request_data; + std::vector request_data; + request_data.push_back(this->get_request_sequence_number()); + request_data.push_back(this->get_command_number()); + request_data.push_back(this->get_sp_unit()); + return request_data; } -std::unique_ptr OpenRequest::deserialize(const std::vector& data) const +std::unique_ptr OpenRequest::deserialize(const std::vector &data) const { - if (data.size() < 2) - { - throw std::runtime_error("Not enough data to deserialize OpenResponse"); - } + if (data.size() < 2) + { + throw std::runtime_error("Not enough data to deserialize OpenResponse"); + } - auto response = std::make_unique(data[0], data[1]); - return response; + auto response = std::make_unique(data[0], data[1]); + return response; } diff --git a/source/SPoverSLIP/OpenRequest.h b/source/SPoverSLIP/OpenRequest.h index 0b263d2cf..b77e4c6f4 100644 --- a/source/SPoverSLIP/OpenRequest.h +++ b/source/SPoverSLIP/OpenRequest.h @@ -1,7 +1,7 @@ #pragma once -#include #include +#include #include "Request.h" #include "Response.h" @@ -9,7 +9,7 @@ class OpenRequest : public Request { public: - OpenRequest(uint8_t request_sequence_number, uint8_t sp_unit); - std::vector serialize() const override; - std::unique_ptr deserialize(const std::vector& data) const override; + OpenRequest(uint8_t request_sequence_number, uint8_t sp_unit); + std::vector serialize() const override; + std::unique_ptr deserialize(const std::vector &data) const override; }; diff --git a/source/SPoverSLIP/OpenResponse.cpp b/source/SPoverSLIP/OpenResponse.cpp index 820eab81e..7b8ca323a 100644 --- a/source/SPoverSLIP/OpenResponse.cpp +++ b/source/SPoverSLIP/OpenResponse.cpp @@ -1,12 +1,11 @@ -#include "stdafx.h" #include "OpenResponse.h" OpenResponse::OpenResponse(const uint8_t request_sequence_number, const uint8_t status) : Response(request_sequence_number, status) {} std::vector OpenResponse::serialize() const { - std::vector data; - data.push_back(this->get_request_sequence_number()); - data.push_back(this->get_status()); - return data; + std::vector data; + data.push_back(this->get_request_sequence_number()); + data.push_back(this->get_status()); + return data; } \ No newline at end of file diff --git a/source/SPoverSLIP/OpenResponse.h b/source/SPoverSLIP/OpenResponse.h index d544e1692..fb5656596 100644 --- a/source/SPoverSLIP/OpenResponse.h +++ b/source/SPoverSLIP/OpenResponse.h @@ -4,6 +4,6 @@ class OpenResponse : public Response { public: - explicit OpenResponse(uint8_t request_sequence_number, uint8_t status); - std::vector serialize() const override; + explicit OpenResponse(uint8_t request_sequence_number, uint8_t status); + std::vector serialize() const override; }; diff --git a/source/SPoverSLIP/Packet.h b/source/SPoverSLIP/Packet.h index 937391f01..cca068b66 100644 --- a/source/SPoverSLIP/Packet.h +++ b/source/SPoverSLIP/Packet.h @@ -1,12 +1,12 @@ #pragma once -#include -#include #include "SPoSLIP.h" +#include +#include class Packet : public SPoSLIP { public: - explicit Packet(const uint8_t request_sequence_number) : SPoSLIP(request_sequence_number) {} - virtual std::vector serialize() const = 0; + explicit Packet(const uint8_t request_sequence_number) : SPoSLIP(request_sequence_number) {} + virtual std::vector serialize() const = 0; }; diff --git a/source/SPoverSLIP/ReadBlockRequest.cpp b/source/SPoverSLIP/ReadBlockRequest.cpp index 847638726..9ed8729c4 100644 --- a/source/SPoverSLIP/ReadBlockRequest.cpp +++ b/source/SPoverSLIP/ReadBlockRequest.cpp @@ -1,43 +1,41 @@ -#include "stdafx.h" #include "ReadBlockRequest.h" #include "ReadBlockResponse.h" #include "SmartPortCodes.h" - ReadBlockRequest::ReadBlockRequest(const uint8_t request_sequence_number, const uint8_t sp_unit) - : Request(request_sequence_number, SP_READ_BLOCK, sp_unit), block_number_{} {} - -std::vector ReadBlockRequest::serialize() const + : Request(request_sequence_number, SP_READ_BLOCK, sp_unit), block_number_{} { - std::vector request_data; - request_data.push_back(this->get_request_sequence_number()); - request_data.push_back(this->get_command_number()); - request_data.push_back(this->get_sp_unit()); - request_data.insert(request_data.end(), block_number_.begin(), block_number_.end()); - return request_data; } -std::unique_ptr ReadBlockRequest::deserialize(const std::vector& data) const +std::vector ReadBlockRequest::serialize() const { - if (data.size() != 514) - { - throw std::runtime_error("Not enough data to deserialize ReadBlockResponse"); - } - - auto response = std::make_unique(data[0], data[1]); - if (response->get_status() == 0) - { - response->set_block_data(data.begin() + 2, data.end()); - } - return response; + std::vector request_data; + request_data.push_back(this->get_request_sequence_number()); + request_data.push_back(this->get_command_number()); + request_data.push_back(this->get_sp_unit()); + request_data.insert(request_data.end(), block_number_.begin(), block_number_.end()); + return request_data; } -const std::array& ReadBlockRequest::get_block_number() const +std::unique_ptr ReadBlockRequest::deserialize(const std::vector &data) const { - return block_number_; + if (data.size() != 514) + { + throw std::runtime_error("Not enough data to deserialize ReadBlockResponse"); + } + + auto response = std::make_unique(data[0], data[1]); + if (response->get_status() == 0) + { + response->set_block_data(data.begin() + 2, data.end()); + } + return response; } -void ReadBlockRequest::set_block_number_from_ptr(const uint8_t* ptr, const size_t offset) { - std::copy_n(ptr + offset, block_number_.size(), block_number_.begin()); +const std::array &ReadBlockRequest::get_block_number() const { return block_number_; } + +void ReadBlockRequest::set_block_number_from_ptr(const uint8_t *ptr, const size_t offset) +{ + std::copy_n(ptr + offset, block_number_.size(), block_number_.begin()); } \ No newline at end of file diff --git a/source/SPoverSLIP/ReadBlockRequest.h b/source/SPoverSLIP/ReadBlockRequest.h index 708cba410..5d9daa111 100644 --- a/source/SPoverSLIP/ReadBlockRequest.h +++ b/source/SPoverSLIP/ReadBlockRequest.h @@ -1,8 +1,9 @@ #pragma once -#include -#include +#include #include +#include +#include #include "Request.h" #include "Response.h" @@ -10,12 +11,12 @@ class ReadBlockRequest : public Request { public: - ReadBlockRequest(uint8_t request_sequence_number, uint8_t sp_unit); - std::vector serialize() const override; - std::unique_ptr deserialize(const std::vector& data) const override; - const std::array& get_block_number() const; - void set_block_number_from_ptr(const uint8_t* ptr, size_t offset); + ReadBlockRequest(uint8_t request_sequence_number, uint8_t sp_unit); + std::vector serialize() const override; + std::unique_ptr deserialize(const std::vector &data) const override; + const std::array &get_block_number() const; + void set_block_number_from_ptr(const uint8_t *ptr, size_t offset); private: - std::array block_number_; + std::array block_number_; }; diff --git a/source/SPoverSLIP/ReadBlockResponse.cpp b/source/SPoverSLIP/ReadBlockResponse.cpp index 4d285c779..f9e1cda4e 100644 --- a/source/SPoverSLIP/ReadBlockResponse.cpp +++ b/source/SPoverSLIP/ReadBlockResponse.cpp @@ -1,5 +1,4 @@ // ReSharper disable CppPassValueParameterByConstReference -#include "stdafx.h" #include #include "ReadBlockResponse.h" @@ -8,19 +7,16 @@ ReadBlockResponse::ReadBlockResponse(const uint8_t request_sequence_number, cons std::vector ReadBlockResponse::serialize() const { - std::vector data; - data.push_back(this->get_request_sequence_number()); - data.push_back(this->get_status()); - data.insert(data.end(), block_data_.begin(), block_data_.end()); - return data; + std::vector data; + data.push_back(this->get_request_sequence_number()); + data.push_back(this->get_status()); + data.insert(data.end(), block_data_.begin(), block_data_.end()); + return data; } void ReadBlockResponse::set_block_data(std::vector::const_iterator begin, std::vector::const_iterator end) { - std::copy(begin, end, block_data_.begin()); // NOLINT(performance-unnecessary-value-param) + std::copy(begin, end, block_data_.begin()); // NOLINT(performance-unnecessary-value-param) } -const std::array& ReadBlockResponse::get_block_data() const -{ - return block_data_; -} \ No newline at end of file +const std::array &ReadBlockResponse::get_block_data() const { return block_data_; } \ No newline at end of file diff --git a/source/SPoverSLIP/ReadBlockResponse.h b/source/SPoverSLIP/ReadBlockResponse.h index c310b70e8..f5ebe7656 100644 --- a/source/SPoverSLIP/ReadBlockResponse.h +++ b/source/SPoverSLIP/ReadBlockResponse.h @@ -1,16 +1,16 @@ #pragma once -#include #include "Response.h" +#include class ReadBlockResponse : public Response { public: - explicit ReadBlockResponse(uint8_t request_sequence_number, uint8_t status); - std::vector serialize() const override; + explicit ReadBlockResponse(uint8_t request_sequence_number, uint8_t status); + std::vector serialize() const override; - void set_block_data(std::vector::const_iterator begin, std::vector::const_iterator end); - const std::array& get_block_data() const; + void set_block_data(std::vector::const_iterator begin, std::vector::const_iterator end); + const std::array &get_block_data() const; private: - std::array block_data_; + std::array block_data_; }; diff --git a/source/SPoverSLIP/ReadRequest.cpp b/source/SPoverSLIP/ReadRequest.cpp index 9bb197404..10724c91d 100644 --- a/source/SPoverSLIP/ReadRequest.cpp +++ b/source/SPoverSLIP/ReadRequest.cpp @@ -1,55 +1,43 @@ -#include "stdafx.h" #include "ReadRequest.h" #include "ReadResponse.h" #include "SmartPortCodes.h" - ReadRequest::ReadRequest(const uint8_t request_sequence_number, const uint8_t sp_unit) - : Request(request_sequence_number, SP_READ, sp_unit), byte_count_(), address_() + : Request(request_sequence_number, SP_READ, sp_unit), byte_count_(), address_() { } std::vector ReadRequest::serialize() const { - std::vector request_data; - request_data.push_back(this->get_request_sequence_number()); - request_data.push_back(this->get_command_number()); - request_data.push_back(this->get_sp_unit()); - request_data.insert(request_data.end(), get_byte_count().begin(), get_byte_count().end()); - request_data.insert(request_data.end(), get_address().begin(), get_address().end()); - return request_data; + std::vector request_data; + request_data.push_back(this->get_request_sequence_number()); + request_data.push_back(this->get_command_number()); + request_data.push_back(this->get_sp_unit()); + request_data.insert(request_data.end(), get_byte_count().begin(), get_byte_count().end()); + request_data.insert(request_data.end(), get_address().begin(), get_address().end()); + return request_data; } -std::unique_ptr ReadRequest::deserialize(const std::vector& data) const +std::unique_ptr ReadRequest::deserialize(const std::vector &data) const { - if (data.size() < 3) - { - throw std::runtime_error("Not enough data to deserialize ReadResponse"); - } - - auto response = std::make_unique(data[0], data[1]); - if (response->get_status() == 0) - { - response->set_data(data.begin() + 2, data.end()); - } - return response; + if (data.size() < 3) + { + throw std::runtime_error("Not enough data to deserialize ReadResponse"); + } + + auto response = std::make_unique(data[0], data[1]); + if (response->get_status() == 0) + { + response->set_data(data.begin() + 2, data.end()); + } + return response; } -const std::array& ReadRequest::get_byte_count() const -{ - return byte_count_; -} +const std::array &ReadRequest::get_byte_count() const { return byte_count_; } -const std::array& ReadRequest::get_address() const -{ - return address_; -} +const std::array &ReadRequest::get_address() const { return address_; } -void ReadRequest::set_byte_count_from_ptr(const uint8_t* ptr, const size_t offset) { - std::copy_n(ptr + offset, byte_count_.size(), byte_count_.begin()); -} +void ReadRequest::set_byte_count_from_ptr(const uint8_t *ptr, const size_t offset) { std::copy_n(ptr + offset, byte_count_.size(), byte_count_.begin()); } -void ReadRequest::set_address_from_ptr(const uint8_t* ptr, const size_t offset) { - std::copy_n(ptr + offset, address_.size(), address_.begin()); -} +void ReadRequest::set_address_from_ptr(const uint8_t *ptr, const size_t offset) { std::copy_n(ptr + offset, address_.size(), address_.begin()); } diff --git a/source/SPoverSLIP/ReadRequest.h b/source/SPoverSLIP/ReadRequest.h index 68d816c2c..025fc1071 100644 --- a/source/SPoverSLIP/ReadRequest.h +++ b/source/SPoverSLIP/ReadRequest.h @@ -1,8 +1,9 @@ #pragma once -#include -#include +#include #include +#include +#include #include "Request.h" #include "Response.h" @@ -10,17 +11,17 @@ class ReadRequest : public Request { public: - ReadRequest(uint8_t request_sequence_number, uint8_t sp_unit); - std::vector serialize() const override; - std::unique_ptr deserialize(const std::vector& data) const override; + ReadRequest(uint8_t request_sequence_number, uint8_t sp_unit); + std::vector serialize() const override; + std::unique_ptr deserialize(const std::vector &data) const override; - const std::array& get_byte_count() const; - void set_byte_count_from_ptr(const uint8_t* ptr, size_t offset); + const std::array &get_byte_count() const; + void set_byte_count_from_ptr(const uint8_t *ptr, size_t offset); - const std::array& get_address() const; - void set_address_from_ptr(const uint8_t * ptr, size_t offset); + const std::array &get_address() const; + void set_address_from_ptr(const uint8_t *ptr, size_t offset); private: - std::array byte_count_; - std::array address_; + std::array byte_count_; + std::array address_; }; diff --git a/source/SPoverSLIP/ReadResponse.cpp b/source/SPoverSLIP/ReadResponse.cpp index dab1b5b5d..6e7835483 100644 --- a/source/SPoverSLIP/ReadResponse.cpp +++ b/source/SPoverSLIP/ReadResponse.cpp @@ -1,21 +1,21 @@ // ReSharper disable CppPassValueParameterByConstReference -#include "stdafx.h" #include "ReadResponse.h" +#include ReadResponse::ReadResponse(const uint8_t request_sequence_number, const uint8_t status) : Response(request_sequence_number, status) {} std::vector ReadResponse::serialize() const { - std::vector data; - data.push_back(this->get_request_sequence_number()); - data.push_back(this->get_status()); - data.insert(data.end(), get_data().begin(), get_data().end()); - return data; + std::vector data; + data.push_back(this->get_request_sequence_number()); + data.push_back(this->get_status()); + data.insert(data.end(), get_data().begin(), get_data().end()); + return data; } -void ReadResponse::set_data(const std::vector::const_iterator& begin, const std::vector::const_iterator& end) +void ReadResponse::set_data(const std::vector::const_iterator &begin, const std::vector::const_iterator &end) { - const size_t new_size = std::distance(begin, end); - data_.resize(new_size); - std::copy(begin, end, data_.begin()); // NOLINT(performance-unnecessary-value-param) -} \ No newline at end of file + const size_t new_size = std::distance(begin, end); + data_.resize(new_size); + std::copy(begin, end, data_.begin()); // NOLINT(performance-unnecessary-value-param) +} diff --git a/source/SPoverSLIP/ReadResponse.h b/source/SPoverSLIP/ReadResponse.h index 27510da74..f784a0342 100644 --- a/source/SPoverSLIP/ReadResponse.h +++ b/source/SPoverSLIP/ReadResponse.h @@ -4,12 +4,12 @@ class ReadResponse : public Response { public: - explicit ReadResponse(uint8_t request_sequence_number, uint8_t status); - std::vector serialize() const override; + explicit ReadResponse(uint8_t request_sequence_number, uint8_t status); + std::vector serialize() const override; - const std::vector& get_data() const { return data_; } - void set_data(const std::vector::const_iterator& begin, const std::vector::const_iterator& end); + const std::vector &get_data() const { return data_; } + void set_data(const std::vector::const_iterator &begin, const std::vector::const_iterator &end); private: - std::vector data_; + std::vector data_; }; diff --git a/source/SPoverSLIP/Request.cpp b/source/SPoverSLIP/Request.cpp index f6a6643a2..df8ecee2f 100644 --- a/source/SPoverSLIP/Request.cpp +++ b/source/SPoverSLIP/Request.cpp @@ -1,9 +1,10 @@ -#include "StdAfx.h" #include "Request.h" Request::Request(const uint8_t request_sequence_number, const uint8_t command_number, const uint8_t sp_unit) - : Packet(request_sequence_number), command_number_(command_number), sp_unit_(sp_unit) {} + : Packet(request_sequence_number), command_number_(command_number), sp_unit_(sp_unit) +{ +} uint8_t Request::get_command_number() const { return command_number_; } diff --git a/source/SPoverSLIP/Request.h b/source/SPoverSLIP/Request.h index 142548243..6ef5dfe12 100644 --- a/source/SPoverSLIP/Request.h +++ b/source/SPoverSLIP/Request.h @@ -1,10 +1,10 @@ #pragma once -#include -#include +#include "Packet.h" #include +#include #include -#include "Packet.h" +#include // Forward reference to break circular dependency class Response; @@ -12,14 +12,14 @@ class Response; class Request : public Packet { public: - Request(uint8_t request_sequence_number, uint8_t command_number, uint8_t sp_unit); - std::vector serialize() const override = 0; - virtual std::unique_ptr deserialize(const std::vector& data) const = 0; + Request(uint8_t request_sequence_number, uint8_t command_number, uint8_t sp_unit); + std::vector serialize() const override = 0; + virtual std::unique_ptr deserialize(const std::vector &data) const = 0; - uint8_t get_command_number() const; - uint8_t get_sp_unit() const; + uint8_t get_command_number() const; + uint8_t get_sp_unit() const; private: - uint8_t command_number_ = 0; - uint8_t sp_unit_ = 0; + uint8_t command_number_ = 0; + uint8_t sp_unit_ = 0; }; diff --git a/source/SPoverSLIP/Requestor.cpp b/source/SPoverSLIP/Requestor.cpp index 34ee0d4be..4a1b34832 100644 --- a/source/SPoverSLIP/Requestor.cpp +++ b/source/SPoverSLIP/Requestor.cpp @@ -1,36 +1,36 @@ -#include "StdAfx.h" -#include #include "Requestor.h" #include "Listener.h" +#include uint8_t Requestor::request_number_ = 0; Requestor::Requestor() = default; -std::unique_ptr Requestor::send_request(const Request& request, Connection* connection) +std::unique_ptr Requestor::send_request(const Request &request, Connection *connection) { - // Send the serialized request - connection->send_data(request.serialize()); + // Send the serialized request + connection->send_data(request.serialize()); - std::vector response_data; - try - { - response_data = connection->wait_for_response(request.get_request_sequence_number(), std::chrono::seconds(5)); - } - catch (const std::runtime_error& e) - { - std::cerr << "Requestor::send_request did not get response, error = " << e.what() << std::endl; - return nullptr; - } + std::vector response_data; + try + { + response_data = connection->wait_for_response(request.get_request_sequence_number(), std::chrono::seconds(5)); + } + catch (const std::runtime_error &e) + { + std::cerr << "Requestor::send_request did not get response, error = " << e.what() << std::endl; + return nullptr; + } - // Deserialize the response data into a Response object. - // Each Request type (e.g. StatusRequest) is able to deserialize into its twin Response (e.g. StatusResponse). - return request.deserialize(response_data); + // Deserialize the response data into a Response object. + // Each Request type (e.g. StatusRequest) is able to deserialize into its twin Response (e.g. StatusResponse). + return request.deserialize(response_data); } -uint8_t Requestor::next_request_number() { - const uint8_t current_number = request_number_; - request_number_ = (request_number_ + 1) % 256; - return current_number; +uint8_t Requestor::next_request_number() +{ + const uint8_t current_number = request_number_; + request_number_ = (request_number_ + 1) % 256; + return current_number; } \ No newline at end of file diff --git a/source/SPoverSLIP/Requestor.h b/source/SPoverSLIP/Requestor.h index 0e6c74d26..dfe4f3169 100644 --- a/source/SPoverSLIP/Requestor.h +++ b/source/SPoverSLIP/Requestor.h @@ -1,19 +1,19 @@ #pragma once -#include #include "Connection.h" #include "Request.h" #include "Response.h" +#include class Requestor { public: - Requestor(); + Requestor(); - // The Request's deserialize function will always return a Response, e.g. StatusRequest -> StatusResponse - static std::unique_ptr send_request(const Request& request, Connection* connection); - static uint8_t next_request_number(); + // The Request's deserialize function will always return a Response, e.g. StatusRequest -> StatusResponse + static std::unique_ptr send_request(const Request &request, Connection *connection); + static uint8_t next_request_number(); private: - static uint8_t request_number_; + static uint8_t request_number_; }; diff --git a/source/SPoverSLIP/ResetRequest.cpp b/source/SPoverSLIP/ResetRequest.cpp index 656afd6f4..4adf386bf 100644 --- a/source/SPoverSLIP/ResetRequest.cpp +++ b/source/SPoverSLIP/ResetRequest.cpp @@ -1,29 +1,26 @@ -#include "stdafx.h" #include "ResetRequest.h" #include "ResetResponse.h" #include "SmartPortCodes.h" - -ResetRequest::ResetRequest(const uint8_t request_sequence_number, const uint8_t sp_unit) - : Request(request_sequence_number, SP_RESET, sp_unit) {} +ResetRequest::ResetRequest(const uint8_t request_sequence_number, const uint8_t sp_unit) : Request(request_sequence_number, SP_RESET, sp_unit) {} std::vector ResetRequest::serialize() const { - std::vector request_data; - request_data.push_back(this->get_request_sequence_number()); - request_data.push_back(this->get_command_number()); - request_data.push_back(this->get_sp_unit()); - return request_data; + std::vector request_data; + request_data.push_back(this->get_request_sequence_number()); + request_data.push_back(this->get_command_number()); + request_data.push_back(this->get_sp_unit()); + return request_data; } -std::unique_ptr ResetRequest::deserialize(const std::vector& data) const +std::unique_ptr ResetRequest::deserialize(const std::vector &data) const { - if (data.size() < 2) - { - throw std::runtime_error("Not enough data to deserialize ResetResponse"); - } + if (data.size() < 2) + { + throw std::runtime_error("Not enough data to deserialize ResetResponse"); + } - auto response = std::make_unique(data[0], data[1]); - return response; + auto response = std::make_unique(data[0], data[1]); + return response; } diff --git a/source/SPoverSLIP/ResetRequest.h b/source/SPoverSLIP/ResetRequest.h index 0fbf90c78..4418c0d58 100644 --- a/source/SPoverSLIP/ResetRequest.h +++ b/source/SPoverSLIP/ResetRequest.h @@ -1,7 +1,7 @@ #pragma once -#include #include +#include #include "Request.h" #include "Response.h" @@ -9,7 +9,7 @@ class ResetRequest : public Request { public: - ResetRequest(uint8_t request_sequence_number, uint8_t sp_unit); - std::vector serialize() const override; - std::unique_ptr deserialize(const std::vector& data) const override; + ResetRequest(uint8_t request_sequence_number, uint8_t sp_unit); + std::vector serialize() const override; + std::unique_ptr deserialize(const std::vector &data) const override; }; diff --git a/source/SPoverSLIP/ResetResponse.cpp b/source/SPoverSLIP/ResetResponse.cpp index 39a5ef1a3..113066bc2 100644 --- a/source/SPoverSLIP/ResetResponse.cpp +++ b/source/SPoverSLIP/ResetResponse.cpp @@ -1,12 +1,11 @@ -#include "stdafx.h" #include "ResetResponse.h" ResetResponse::ResetResponse(const uint8_t request_sequence_number, const uint8_t status) : Response(request_sequence_number, status) {} std::vector ResetResponse::serialize() const { - std::vector data; - data.push_back(this->get_request_sequence_number()); - data.push_back(this->get_status()); - return data; + std::vector data; + data.push_back(this->get_request_sequence_number()); + data.push_back(this->get_status()); + return data; } \ No newline at end of file diff --git a/source/SPoverSLIP/ResetResponse.h b/source/SPoverSLIP/ResetResponse.h index a11dae72f..37209dc27 100644 --- a/source/SPoverSLIP/ResetResponse.h +++ b/source/SPoverSLIP/ResetResponse.h @@ -4,6 +4,6 @@ class ResetResponse : public Response { public: - explicit ResetResponse(uint8_t request_sequence_number, uint8_t status); - std::vector serialize() const override; + explicit ResetResponse(uint8_t request_sequence_number, uint8_t status); + std::vector serialize() const override; }; diff --git a/source/SPoverSLIP/Response.cpp b/source/SPoverSLIP/Response.cpp index ac8fa5a31..d212ae0f6 100644 --- a/source/SPoverSLIP/Response.cpp +++ b/source/SPoverSLIP/Response.cpp @@ -1,8 +1,6 @@ -#include "StdAfx.h" #include "Response.h" -Response::Response(const uint8_t request_sequence_number, const uint8_t status) - : Packet(request_sequence_number), status_(status) {} +Response::Response(const uint8_t request_sequence_number, const uint8_t status) : Packet(request_sequence_number), status_(status) {} uint8_t Response::get_status() const { return status_; } diff --git a/source/SPoverSLIP/Response.h b/source/SPoverSLIP/Response.h index 65ea2f514..d9e730a92 100644 --- a/source/SPoverSLIP/Response.h +++ b/source/SPoverSLIP/Response.h @@ -1,17 +1,17 @@ #pragma once -#include -#include #include "Packet.h" +#include +#include class Response : public Packet { public: - Response(uint8_t request_sequence_number, uint8_t status); - std::vector serialize() const override = 0; + Response(uint8_t request_sequence_number, uint8_t status); + std::vector serialize() const override = 0; - uint8_t get_status() const; + uint8_t get_status() const; private: - uint8_t status_ = 0; + uint8_t status_ = 0; }; \ No newline at end of file diff --git a/source/SPoverSLIP/SLIP.cpp b/source/SPoverSLIP/SLIP.cpp index 41910ec63..6001c11a4 100644 --- a/source/SPoverSLIP/SLIP.cpp +++ b/source/SPoverSLIP/SLIP.cpp @@ -1,145 +1,144 @@ -#include "StdAfx.h" -#include #include "SLIP.h" +#include -std::vector SLIP::encode(const std::vector& data) +std::vector SLIP::encode(const std::vector &data) { - std::vector encoded_data; - - // start with SLIP_END - encoded_data.push_back(SLIP_END); - - // Escape any SLIP special characters in the packet data - for (uint8_t byte : data) - { - if (byte == SLIP_END || byte == SLIP_ESC) - { - encoded_data.push_back(SLIP_ESC); - encoded_data.push_back(byte == SLIP_END ? SLIP_ESC_END : SLIP_ESC_ESC); - } - else - { - encoded_data.push_back(byte); - } - } - - // Add the SLIP END byte to the end of the encoded data - encoded_data.push_back(SLIP_END); - - return encoded_data; + std::vector encoded_data; + + // start with SLIP_END + encoded_data.push_back(SLIP_END); + + // Escape any SLIP special characters in the packet data + for (uint8_t byte : data) + { + if (byte == SLIP_END || byte == SLIP_ESC) + { + encoded_data.push_back(SLIP_ESC); + encoded_data.push_back(byte == SLIP_END ? SLIP_ESC_END : SLIP_ESC_ESC); + } + else + { + encoded_data.push_back(byte); + } + } + + // Add the SLIP END byte to the end of the encoded data + encoded_data.push_back(SLIP_END); + + return encoded_data; } -std::vector SLIP::decode(const std::vector& data) +std::vector SLIP::decode(const std::vector &data) { - std::vector decoded_data; - auto bytes_read = data.size(); - - size_t i = 0; - while (i < bytes_read) - { - if (data[i] == SLIP_END) - { - // Start of a SLIP packet - i++; - - // Decode the SLIP packet data - while (i < bytes_read && data[i] != SLIP_END) - { - if (data[i] == SLIP_ESC) - { - // Escaped byte - i++; - - if (data[i] == SLIP_ESC_END) - { - // Escaped END byte - decoded_data.push_back(SLIP_END); - } - else if (data[i] == SLIP_ESC_ESC) - { - // Escaped ESC byte - decoded_data.push_back(SLIP_ESC); - } - else - { - // Invalid escape sequence - return std::vector(); - } - } - else - { - // Non-escaped byte - decoded_data.push_back(data[i]); - } - - i++; - } - - // Check for end of packet - if (i == bytes_read || data[i] != SLIP_END) - { - // Incomplete SLIP packet - return std::vector(); - } - } - else - { - // Invalid SLIP packet - return std::vector(); - } - - i++; - } - - return decoded_data; + std::vector decoded_data; + auto bytes_read = data.size(); + + size_t i = 0; + while (i < bytes_read) + { + if (data[i] == SLIP_END) + { + // Start of a SLIP packet + i++; + + // Decode the SLIP packet data + while (i < bytes_read && data[i] != SLIP_END) + { + if (data[i] == SLIP_ESC) + { + // Escaped byte + i++; + + if (data[i] == SLIP_ESC_END) + { + // Escaped END byte + decoded_data.push_back(SLIP_END); + } + else if (data[i] == SLIP_ESC_ESC) + { + // Escaped ESC byte + decoded_data.push_back(SLIP_ESC); + } + else + { + // Invalid escape sequence + return std::vector(); + } + } + else + { + // Non-escaped byte + decoded_data.push_back(data[i]); + } + + i++; + } + + // Check for end of packet + if (i == bytes_read || data[i] != SLIP_END) + { + // Incomplete SLIP packet + return std::vector(); + } + } + else + { + // Invalid SLIP packet + return std::vector(); + } + + i++; + } + + return decoded_data; } // This breaks up a vector of data into a list of decoded vectors of serialized objects. // The returned data is already "SLIP::decode"d -std::vector> SLIP::split_into_packets(const uint8_t* data, size_t bytes_read) +std::vector> SLIP::split_into_packets(const uint8_t *data, size_t bytes_read) { - // The list of decoded SLIP packets - std::vector> decoded_packets; - - enum class State - { - NotParsing, - Parsing - } state = State::NotParsing; - - // Iterate over the data and find the SLIP packet boundaries - size_t i = 0; - const uint8_t* packet_start = nullptr; // Keep track of where the packet starts - while (i < bytes_read) - { - switch (state) - { - case State::NotParsing: - // If we are not yet parsing and see a SLIP_END byte (which also marks start), start parsing a new SLIP packet - if (data[i] == SLIP_END) - { - state = State::Parsing; - packet_start = data + i; // Mark the start of the packet - } - break; - case State::Parsing: - // If we see another SLIP_END byte, we have reached the end of the SLIP packet - if (data[i] == SLIP_END) - { - // Extract the SLIP packet data - std::vector slip_packet_data(packet_start, data + i + 1); // Include all bytes in the packet - - // Add the data to the list of SLIP decoded packets - decoded_packets.push_back(SLIP::decode(slip_packet_data)); - - // Transition back to the NotParsing state - state = State::NotParsing; - } - break; - } - i++; - } - - return decoded_packets; + // The list of decoded SLIP packets + std::vector> decoded_packets; + + enum class State + { + NotParsing, + Parsing + } state = State::NotParsing; + + // Iterate over the data and find the SLIP packet boundaries + size_t i = 0; + const uint8_t *packet_start = nullptr; // Keep track of where the packet starts + while (i < bytes_read) + { + switch (state) + { + case State::NotParsing: + // If we are not yet parsing and see a SLIP_END byte (which also marks start), start parsing a new SLIP packet + if (data[i] == SLIP_END) + { + state = State::Parsing; + packet_start = data + i; // Mark the start of the packet + } + break; + case State::Parsing: + // If we see another SLIP_END byte, we have reached the end of the SLIP packet + if (data[i] == SLIP_END) + { + // Extract the SLIP packet data + std::vector slip_packet_data(packet_start, data + i + 1); // Include all bytes in the packet + + // Add the data to the list of SLIP decoded packets + decoded_packets.push_back(SLIP::decode(slip_packet_data)); + + // Transition back to the NotParsing state + state = State::NotParsing; + } + break; + } + i++; + } + + return decoded_packets; } diff --git a/source/SPoverSLIP/SLIP.h b/source/SPoverSLIP/SLIP.h index 4be88e972..57c0ac55a 100644 --- a/source/SPoverSLIP/SLIP.h +++ b/source/SPoverSLIP/SLIP.h @@ -1,18 +1,19 @@ #pragma once -#include +#include #include +#include -#define SLIP_END 0300 /* indicates end of packet */ -#define SLIP_ESC 0333 /* indicates byte stuffing */ -#define SLIP_ESC_END 0334 /* ESC ESC_END means END data byte */ -#define SLIP_ESC_ESC 0335 /* ESC ESC_ESC means ESC data byte */ +#define SLIP_END 0300 /* indicates end of packet */ +#define SLIP_ESC 0333 /* indicates byte stuffing */ +#define SLIP_ESC_END 0334 /* ESC ESC_END means END data byte */ +#define SLIP_ESC_ESC 0335 /* ESC ESC_ESC means ESC data byte */ class SLIP { public: - // these encode and decode exactly one SLIP frame, and expect it to be sane. - static std::vector encode(const std::vector& data); - static std::vector decode(const std::vector& data); - static std::vector> split_into_packets(const uint8_t* data, size_t bytes_read); + // these encode and decode exactly one SLIP frame, and expect it to be sane. + static std::vector encode(const std::vector &data); + static std::vector decode(const std::vector &data); + static std::vector> split_into_packets(const uint8_t *data, size_t bytes_read); }; diff --git a/source/SPoverSLIP/SPoSLIP.h b/source/SPoverSLIP/SPoSLIP.h index db8cf8dd8..bf7713a78 100644 --- a/source/SPoverSLIP/SPoSLIP.h +++ b/source/SPoverSLIP/SPoSLIP.h @@ -5,11 +5,11 @@ class SPoSLIP { private: - uint8_t request_sequence_number_ = 0; + uint8_t request_sequence_number_ = 0; public: - explicit SPoSLIP(const uint8_t request_sequence_number) : request_sequence_number_(request_sequence_number) {} - virtual ~SPoSLIP() = default; + explicit SPoSLIP(const uint8_t request_sequence_number) : request_sequence_number_(request_sequence_number) {} + virtual ~SPoSLIP() = default; - uint8_t get_request_sequence_number() const { return request_sequence_number_; } + uint8_t get_request_sequence_number() const { return request_sequence_number_; } }; diff --git a/source/SPoverSLIP/SmartPortCodes.h b/source/SPoverSLIP/SmartPortCodes.h index bb328b689..4eeba2db4 100644 --- a/source/SPoverSLIP/SmartPortCodes.h +++ b/source/SPoverSLIP/SmartPortCodes.h @@ -2,15 +2,15 @@ enum { - SP_STATUS = 0, - SP_READ_BLOCK = 1, - SP_WRITE_BLOCK = 2, - SP_FORMAT = 3, - SP_CONTROL = 4, - SP_INIT = 5, - SP_OPEN = 6, - SP_CLOSE = 7, - SP_READ = 8, - SP_WRITE = 9, - SP_RESET = 10 + SP_STATUS = 0, + SP_READ_BLOCK = 1, + SP_WRITE_BLOCK = 2, + SP_FORMAT = 3, + SP_CONTROL = 4, + SP_INIT = 5, + SP_OPEN = 6, + SP_CLOSE = 7, + SP_READ = 8, + SP_WRITE = 9, + SP_RESET = 10 }; diff --git a/source/SPoverSLIP/StatusRequest.cpp b/source/SPoverSLIP/StatusRequest.cpp index 5159b6d42..16bae15aa 100644 --- a/source/SPoverSLIP/StatusRequest.cpp +++ b/source/SPoverSLIP/StatusRequest.cpp @@ -1,4 +1,3 @@ -#include "StdAfx.h" #include @@ -7,35 +6,37 @@ #include "StatusResponse.h" StatusRequest::StatusRequest(const uint8_t request_sequence_number, const uint8_t sp_unit, const uint8_t status_code) - : Request(request_sequence_number, SP_STATUS, sp_unit), status_code_(status_code) {} + : Request(request_sequence_number, SP_STATUS, sp_unit), status_code_(status_code) +{ +} std::vector StatusRequest::serialize() const { - std::vector request_data; - request_data.push_back(this->get_request_sequence_number()); - request_data.push_back(this->get_command_number()); - request_data.push_back(this->get_sp_unit()); - request_data.push_back(this->get_status_code()); + std::vector request_data; + request_data.push_back(this->get_request_sequence_number()); + request_data.push_back(this->get_command_number()); + request_data.push_back(this->get_sp_unit()); + request_data.push_back(this->get_status_code()); - return request_data; + return request_data; } -std::unique_ptr StatusRequest::deserialize(const std::vector& data) const +std::unique_ptr StatusRequest::deserialize(const std::vector &data) const { - if (data.size() < 2) - { - throw std::runtime_error("Not enough data to deserialize StatusResponse"); - } - - auto response = std::make_unique(data[0], data[1]); - - if (response->get_status() == 0 && data.size() > 2) - { - for (size_t i = 2; i < data.size(); ++i) - { - response->add_data(data[i]); - } - } - - return response; + if (data.size() < 2) + { + throw std::runtime_error("Not enough data to deserialize StatusResponse"); + } + + auto response = std::make_unique(data[0], data[1]); + + if (response->get_status() == 0 && data.size() > 2) + { + for (size_t i = 2; i < data.size(); ++i) + { + response->add_data(data[i]); + } + } + + return response; } diff --git a/source/SPoverSLIP/StatusRequest.h b/source/SPoverSLIP/StatusRequest.h index 54692bbf1..90fd19e12 100644 --- a/source/SPoverSLIP/StatusRequest.h +++ b/source/SPoverSLIP/StatusRequest.h @@ -1,19 +1,19 @@ #pragma once -#include -#include #include "Request.h" #include "Response.h" +#include +#include class StatusRequest : public Request { public: - StatusRequest(uint8_t request_sequence_number, uint8_t sp_unit, uint8_t status_code); - virtual std::vector serialize() const override; - std::unique_ptr deserialize(const std::vector& data) const override; + StatusRequest(uint8_t request_sequence_number, uint8_t sp_unit, uint8_t status_code); + virtual std::vector serialize() const override; + std::unique_ptr deserialize(const std::vector &data) const override; - uint8_t get_status_code() const { return status_code_; } + uint8_t get_status_code() const { return status_code_; } private: - uint8_t status_code_; + uint8_t status_code_; }; diff --git a/source/SPoverSLIP/StatusResponse.cpp b/source/SPoverSLIP/StatusResponse.cpp index 780607e72..a24b1daf2 100644 --- a/source/SPoverSLIP/StatusResponse.cpp +++ b/source/SPoverSLIP/StatusResponse.cpp @@ -1,27 +1,24 @@ -#include "StdAfx.h" #include "StatusResponse.h" #include "StatusRequest.h" StatusResponse::StatusResponse(const uint8_t request_sequence_number, const uint8_t status) : Response(request_sequence_number, status) {} -const std::vector& StatusResponse::get_data() const { return data_; } +const std::vector &StatusResponse::get_data() const { return data_; } void StatusResponse::add_data(const uint8_t d) { data_.push_back(d); } -void StatusResponse::set_data(const std::vector& data) { - data_ = data; -} +void StatusResponse::set_data(const std::vector &data) { data_ = data; } std::vector StatusResponse::serialize() const { - std::vector data; - data.push_back(this->get_request_sequence_number()); - data.push_back(this->get_status()); + std::vector data; + data.push_back(this->get_request_sequence_number()); + data.push_back(this->get_status()); - for (uint8_t b : get_data()) - { - data.push_back(b); - } - return data; + for (uint8_t b : get_data()) + { + data.push_back(b); + } + return data; } diff --git a/source/SPoverSLIP/StatusResponse.h b/source/SPoverSLIP/StatusResponse.h index e59daa6b8..348664e0e 100644 --- a/source/SPoverSLIP/StatusResponse.h +++ b/source/SPoverSLIP/StatusResponse.h @@ -1,20 +1,19 @@ #pragma once -#include -#include #include "Response.h" +#include +#include class StatusResponse : public Response { public: - explicit StatusResponse(uint8_t request_sequence_number, uint8_t status); - std::vector serialize() const override; + explicit StatusResponse(uint8_t request_sequence_number, uint8_t status); + std::vector serialize() const override; - const std::vector& get_data() const; - void add_data(uint8_t d); - void set_data(const std::vector& data); + const std::vector &get_data() const; + void add_data(uint8_t d); + void set_data(const std::vector &data); private: - std::vector data_; - + std::vector data_; }; diff --git a/source/SPoverSLIP/TCPConnection.cpp b/source/SPoverSLIP/TCPConnection.cpp index 81f1bf21f..e41520ba0 100644 --- a/source/SPoverSLIP/TCPConnection.cpp +++ b/source/SPoverSLIP/TCPConnection.cpp @@ -1,101 +1,118 @@ -#include "StdAfx.h" #include "TCPConnection.h" -#include #include +#include #include +// clang-format off +#ifdef WIN32 + #include + #pragma comment(lib, "ws2_32.lib") + #define CLOSE_SOCKET closesocket + #define SOCKET_ERROR_CODE WSAGetLastError() +#else + #include + #include + #include + #define CLOSE_SOCKET close + #define SOCKET_ERROR_CODE errno + #define INVALID_SOCKET -1 + #define SOCKET_ERROR -1 +#endif +// clang-format off + #include "Log.h" #include "SLIP.h" -void TCPConnection::send_data(const std::vector& data) +void TCPConnection::send_data(const std::vector &data) { - if (data.empty()) - { - std::cerr << "TCPConnection::send_data No data was given to send" << std::endl; - return; - } + if (data.empty()) + { + std::cerr << "TCPConnection::send_data No data was given to send" << std::endl; + return; + } - const auto slip_data = SLIP::encode(data); - send(socket_, reinterpret_cast(slip_data.data()), slip_data.size(), 0); + const auto slip_data = SLIP::encode(data); + send(socket_, reinterpret_cast(slip_data.data()), slip_data.size(), 0); } void TCPConnection::create_read_channel() { - // Start a new thread to listen for incoming data - reading_thread_ = std::thread([self = shared_from_this()]() - { - std::vector complete_data; - std::vector buffer(1024); - bool is_initialising = true; + // Start a new thread to listen for incoming data + reading_thread_ = std::thread( + [self = shared_from_this()]() + { + std::vector complete_data; + std::vector buffer(1024); + bool is_initialising = true; - // Set a timeout on the socket - timeval timeout; - timeout.tv_sec = 5; - timeout.tv_usec = 0; - setsockopt(self->get_socket(), SOL_SOCKET, SO_RCVTIMEO, reinterpret_cast(&timeout), sizeof(timeout)); + // Set a timeout on the socket + timeval timeout; + timeout.tv_sec = 5; + timeout.tv_usec = 0; + setsockopt(self->get_socket(), SOL_SOCKET, SO_RCVTIMEO, reinterpret_cast(&timeout), sizeof(timeout)); - while (self->is_connected() || is_initialising) - { - int valread = 0; - do - { - if (is_initialising) - { - is_initialising = false; - LogFileOutput("SmartPortOverSlip TCPConnection: connected\n"); - self->set_is_connected(true); - } + while (self->is_connected() || is_initialising) + { + int valread = 0; + do + { + if (is_initialising) + { + is_initialising = false; + LogFileOutput("SmartPortOverSlip TCPConnection: connected\n"); + self->set_is_connected(true); + } - valread = recv(self->get_socket(), reinterpret_cast(buffer.data()), static_cast(buffer.size()), 0); - const int errsv = errno; - if (valread < 0) - { - // timeout is fine, just reloop. - if (errno == EAGAIN || errno == EWOULDBLOCK || errsv == 0) - { - continue; - } - // otherwise it was a genuine error. - std::cerr << "Error in read thread for connection, errno: " << errsv << " = " << strerror(errsv) << std::endl; - self->set_is_connected(false); - } - if (valread == 0) - { - // disconnected, close connection, should remove it too: TODO - self->set_is_connected(false); - } - if (valread > 0) - { - // LogFileOutput("SmartPortOverSlip TCPConnection, inserting data, valread: %d\n", valread); - complete_data.insert(complete_data.end(), buffer.begin(), buffer.begin() + valread); - } - } - while (valread == 1024); + valread = recv(self->get_socket(), reinterpret_cast(buffer.data()), static_cast(buffer.size()), 0); + const int errsv = SOCKET_ERROR_CODE; + if (valread < 0) + { + // timeout is fine, just reloop. + if (errno == EAGAIN || errno == EWOULDBLOCK || errsv == 0) + { + continue; + } + // otherwise it was a genuine error. + std::cerr << "Error in read thread for connection, errno: " << errsv << " = " << strerror(errsv) << std::endl; + self->set_is_connected(false); + } + if (valread == 0) + { + // disconnected, close connection, should remove it too: TODO + self->set_is_connected(false); + } + if (valread > 0) + { + // LogFileOutput("SmartPortOverSlip TCPConnection, inserting data, valread: %d\n", valread); + complete_data.insert(complete_data.end(), buffer.begin(), buffer.begin() + valread); + } + } while (valread == 1024); - if (!complete_data.empty()) - { - std::vector> decoded_packets = SLIP::split_into_packets(complete_data.data(), complete_data.size()); - // LogFileOutput("SmartPortOverSlip TCPConnection, packets decoded: %d\n", decoded_packets.size()); + if (!complete_data.empty()) + { + std::vector> decoded_packets = + SLIP::split_into_packets(complete_data.data(), complete_data.size()); + // LogFileOutput("SmartPortOverSlip TCPConnection, packets decoded: %d\n", decoded_packets.size()); - if (!decoded_packets.empty()) - { - for (const auto& packet : decoded_packets) - { - if (!packet.empty()) - { - { - std::lock_guard lock(self->responses_mutex_); - self->responses_[packet[0]] = packet; - } - self->response_cv_.notify_all(); - } - } - } - complete_data.clear(); - } - } - LogFileOutput("TCPConnection::create_read_channel - thread is EXITING\n"); - }); + if (!decoded_packets.empty()) + { + for (const auto &packet : decoded_packets) + { + if (!packet.empty()) + { + { + std::lock_guard lock(self->responses_mutex_); + self->responses_[packet[0]] = packet; + } + self->response_cv_.notify_all(); + } + } + } + complete_data.clear(); + } + } + LogFileOutput("TCPConnection::create_read_channel - thread is EXITING\n"); + }); } diff --git a/source/SPoverSLIP/TCPConnection.h b/source/SPoverSLIP/TCPConnection.h index 8e05e2437..d1e3a12c7 100644 --- a/source/SPoverSLIP/TCPConnection.h +++ b/source/SPoverSLIP/TCPConnection.h @@ -1,22 +1,20 @@ #pragma once #include "Connection.h" -#include #include +#include class TCPConnection : public Connection, public std::enable_shared_from_this { public: - TCPConnection(int socket) : socket_(socket) - { - } + TCPConnection(int socket) : socket_(socket) {} - virtual void send_data(const std::vector& data) override; - virtual void create_read_channel() override; + virtual void send_data(const std::vector &data) override; + virtual void create_read_channel() override; - int get_socket() const { return socket_; } - void set_socket(int socket) { this->socket_ = socket; } + int get_socket() const { return socket_; } + void set_socket(int socket) { this->socket_ = socket; } private: - int socket_; + int socket_; }; diff --git a/source/SPoverSLIP/WriteBlockRequest.cpp b/source/SPoverSLIP/WriteBlockRequest.cpp index 618d68b94..c93e4eeb3 100644 --- a/source/SPoverSLIP/WriteBlockRequest.cpp +++ b/source/SPoverSLIP/WriteBlockRequest.cpp @@ -1,50 +1,43 @@ -#include "stdafx.h" #include "WriteBlockRequest.h" -#include "WriteBlockResponse.h" #include "SmartPortCodes.h" - +#include "WriteBlockResponse.h" WriteBlockRequest::WriteBlockRequest(const uint8_t request_sequence_number, const uint8_t sp_unit) - : Request(request_sequence_number, SP_WRITE_BLOCK, sp_unit), block_number_{}, block_data_{} {} + : Request(request_sequence_number, SP_WRITE_BLOCK, sp_unit), block_number_{}, block_data_{} +{ +} std::vector WriteBlockRequest::serialize() const { - std::vector request_data; - request_data.push_back(this->get_request_sequence_number()); - request_data.push_back(this->get_command_number()); - request_data.push_back(this->get_sp_unit()); - request_data.insert(request_data.end(), block_number_.begin(), block_number_.end()); - request_data.insert(request_data.end(), block_data_.begin(), block_data_.end()); - - return request_data; + std::vector request_data; + request_data.push_back(this->get_request_sequence_number()); + request_data.push_back(this->get_command_number()); + request_data.push_back(this->get_sp_unit()); + request_data.insert(request_data.end(), block_number_.begin(), block_number_.end()); + request_data.insert(request_data.end(), block_data_.begin(), block_data_.end()); + + return request_data; } -std::unique_ptr WriteBlockRequest::deserialize(const std::vector& data) const +std::unique_ptr WriteBlockRequest::deserialize(const std::vector &data) const { - if (data.size() < 2) - { - throw std::runtime_error("Not enough data to deserialize WriteBlockResponse"); - } + if (data.size() < 2) + { + throw std::runtime_error("Not enough data to deserialize WriteBlockResponse"); + } - auto response = std::make_unique(data[0], data[1]); - return response; + auto response = std::make_unique(data[0], data[1]); + return response; } -const std::array& WriteBlockRequest::get_block_number() const -{ - return block_number_; -} +const std::array &WriteBlockRequest::get_block_number() const { return block_number_; } -const std::array& WriteBlockRequest::get_block_data() const -{ - return block_data_; -} +const std::array &WriteBlockRequest::get_block_data() const { return block_data_; } -void WriteBlockRequest::set_block_number_from_ptr(const uint8_t* ptr, const size_t offset) { - std::copy_n(ptr + offset, block_number_.size(), block_number_.begin()); +void WriteBlockRequest::set_block_number_from_ptr(const uint8_t *ptr, const size_t offset) +{ + std::copy_n(ptr + offset, block_number_.size(), block_number_.begin()); } -void WriteBlockRequest::set_block_data_from_ptr(const uint8_t* ptr, const size_t offset) { - std::copy_n(ptr + offset, block_data_.size(), block_data_.begin()); -} +void WriteBlockRequest::set_block_data_from_ptr(const uint8_t *ptr, const size_t offset) { std::copy_n(ptr + offset, block_data_.size(), block_data_.begin()); } diff --git a/source/SPoverSLIP/WriteBlockRequest.h b/source/SPoverSLIP/WriteBlockRequest.h index eb9c9a7ba..308adf825 100644 --- a/source/SPoverSLIP/WriteBlockRequest.h +++ b/source/SPoverSLIP/WriteBlockRequest.h @@ -1,8 +1,9 @@ #pragma once -#include -#include +#include #include +#include +#include #include "Request.h" #include "Response.h" @@ -10,16 +11,16 @@ class WriteBlockRequest : public Request { public: - WriteBlockRequest(uint8_t request_sequence_number, uint8_t sp_unit); - std::vector serialize() const override; - std::unique_ptr deserialize(const std::vector& data) const override; - const std::array& get_block_number() const; - void set_block_number_from_ptr(const uint8_t* ptr, size_t offset); + WriteBlockRequest(uint8_t request_sequence_number, uint8_t sp_unit); + std::vector serialize() const override; + std::unique_ptr deserialize(const std::vector &data) const override; + const std::array &get_block_number() const; + void set_block_number_from_ptr(const uint8_t *ptr, size_t offset); - const std::array& get_block_data() const; - void set_block_data_from_ptr(const uint8_t* ptr, size_t offset); + const std::array &get_block_data() const; + void set_block_data_from_ptr(const uint8_t *ptr, size_t offset); private: - std::array block_number_; - std::array block_data_; + std::array block_number_; + std::array block_data_; }; diff --git a/source/SPoverSLIP/WriteBlockResponse.cpp b/source/SPoverSLIP/WriteBlockResponse.cpp index 44d9396e3..dba012991 100644 --- a/source/SPoverSLIP/WriteBlockResponse.cpp +++ b/source/SPoverSLIP/WriteBlockResponse.cpp @@ -1,12 +1,11 @@ -#include "stdafx.h" #include "WriteBlockResponse.h" WriteBlockResponse::WriteBlockResponse(const uint8_t request_sequence_number, const uint8_t status) : Response(request_sequence_number, status) {} std::vector WriteBlockResponse::serialize() const { - std::vector data; - data.push_back(this->get_request_sequence_number()); - data.push_back(this->get_status()); - return data; + std::vector data; + data.push_back(this->get_request_sequence_number()); + data.push_back(this->get_status()); + return data; } \ No newline at end of file diff --git a/source/SPoverSLIP/WriteBlockResponse.h b/source/SPoverSLIP/WriteBlockResponse.h index c8a942da3..61bf1d21c 100644 --- a/source/SPoverSLIP/WriteBlockResponse.h +++ b/source/SPoverSLIP/WriteBlockResponse.h @@ -4,6 +4,6 @@ class WriteBlockResponse : public Response { public: - explicit WriteBlockResponse(uint8_t request_sequence_number, uint8_t status); - std::vector serialize() const override; + explicit WriteBlockResponse(uint8_t request_sequence_number, uint8_t status); + std::vector serialize() const override; }; diff --git a/source/SPoverSLIP/WriteRequest.cpp b/source/SPoverSLIP/WriteRequest.cpp index 97fe79c6d..9d35da537 100644 --- a/source/SPoverSLIP/WriteRequest.cpp +++ b/source/SPoverSLIP/WriteRequest.cpp @@ -1,60 +1,48 @@ // ReSharper disable CppPassValueParameterByConstReference -#include "stdafx.h" #include "WriteRequest.h" -#include "WriteResponse.h" #include "SmartPortCodes.h" - +#include "WriteResponse.h" WriteRequest::WriteRequest(const uint8_t request_sequence_number, const uint8_t sp_unit) - : Request(request_sequence_number, SP_WRITE, sp_unit), byte_count_(), address_() + : Request(request_sequence_number, SP_WRITE, sp_unit), byte_count_(), address_() { } std::vector WriteRequest::serialize() const { - std::vector request_data; - request_data.push_back(this->get_request_sequence_number()); - request_data.push_back(this->get_command_number()); - request_data.push_back(this->get_sp_unit()); - request_data.insert(request_data.end(), get_byte_count().begin(), get_byte_count().end()); - request_data.insert(request_data.end(), get_address().begin(), get_address().end()); - request_data.insert(request_data.end(), get_data().begin(), get_data().end()); - return request_data; + std::vector request_data; + request_data.push_back(this->get_request_sequence_number()); + request_data.push_back(this->get_command_number()); + request_data.push_back(this->get_sp_unit()); + request_data.insert(request_data.end(), get_byte_count().begin(), get_byte_count().end()); + request_data.insert(request_data.end(), get_address().begin(), get_address().end()); + request_data.insert(request_data.end(), get_data().begin(), get_data().end()); + return request_data; } -std::unique_ptr WriteRequest::deserialize(const std::vector& data) const +std::unique_ptr WriteRequest::deserialize(const std::vector &data) const { - if (data.size() < 2) - { - throw std::runtime_error("Not enough data to deserialize WriteResponse"); - } + if (data.size() < 2) + { + throw std::runtime_error("Not enough data to deserialize WriteResponse"); + } - auto response = std::make_unique(data[0], data[1]); - return response; + auto response = std::make_unique(data[0], data[1]); + return response; } -const std::array& WriteRequest::get_byte_count() const -{ - return byte_count_; -} +const std::array &WriteRequest::get_byte_count() const { return byte_count_; } -const std::array& WriteRequest::get_address() const -{ - return address_; -} +const std::array &WriteRequest::get_address() const { return address_; } -void WriteRequest::set_byte_count_from_ptr(const uint8_t* ptr, const size_t offset) { - std::copy_n(ptr + offset, byte_count_.size(), byte_count_.begin()); -} +void WriteRequest::set_byte_count_from_ptr(const uint8_t *ptr, const size_t offset) { std::copy_n(ptr + offset, byte_count_.size(), byte_count_.begin()); } -void WriteRequest::set_address_from_ptr(const uint8_t* ptr, const size_t offset) { - std::copy_n(ptr + offset, address_.size(), address_.begin()); -} +void WriteRequest::set_address_from_ptr(const uint8_t *ptr, const size_t offset) { std::copy_n(ptr + offset, address_.size(), address_.begin()); } -void WriteRequest::set_data_from_ptr(const uint8_t* ptr, const size_t offset, const size_t length) +void WriteRequest::set_data_from_ptr(const uint8_t *ptr, const size_t offset, const size_t length) { - data_.clear(); - data_.insert(data_.end(), ptr + offset, ptr + offset + length); + data_.clear(); + data_.insert(data_.end(), ptr + offset, ptr + offset + length); } \ No newline at end of file diff --git a/source/SPoverSLIP/WriteRequest.h b/source/SPoverSLIP/WriteRequest.h index fa2738b66..785abe374 100644 --- a/source/SPoverSLIP/WriteRequest.h +++ b/source/SPoverSLIP/WriteRequest.h @@ -1,8 +1,9 @@ #pragma once -#include -#include +#include #include +#include +#include #include "Request.h" #include "Response.h" @@ -10,22 +11,21 @@ class WriteRequest : public Request { public: - WriteRequest(const uint8_t request_sequence_number, const uint8_t sp_unit); - std::vector serialize() const override; - std::unique_ptr deserialize(const std::vector& data) const override; + WriteRequest(const uint8_t request_sequence_number, const uint8_t sp_unit); + std::vector serialize() const override; + std::unique_ptr deserialize(const std::vector &data) const override; - const std::array& get_byte_count() const; - void set_byte_count_from_ptr(const uint8_t* ptr, size_t offset); + const std::array &get_byte_count() const; + void set_byte_count_from_ptr(const uint8_t *ptr, size_t offset); - const std::array& get_address() const; - void set_address_from_ptr(const uint8_t* ptr, size_t offset); + const std::array &get_address() const; + void set_address_from_ptr(const uint8_t *ptr, size_t offset); - const std::vector& get_data() const { return data_; } - void set_data_from_ptr(const uint8_t* ptr, size_t offset, size_t length); + const std::vector &get_data() const { return data_; } + void set_data_from_ptr(const uint8_t *ptr, size_t offset, size_t length); private: - std::array byte_count_; - std::array address_; - std::vector data_; - + std::array byte_count_; + std::array address_; + std::vector data_; }; diff --git a/source/SPoverSLIP/WriteResponse.cpp b/source/SPoverSLIP/WriteResponse.cpp index 77b2e8dd2..496a588b9 100644 --- a/source/SPoverSLIP/WriteResponse.cpp +++ b/source/SPoverSLIP/WriteResponse.cpp @@ -1,12 +1,11 @@ -#include "stdafx.h" #include "WriteResponse.h" WriteResponse::WriteResponse(const uint8_t request_sequence_number, const uint8_t status) : Response(request_sequence_number, status) {} std::vector WriteResponse::serialize() const { - std::vector data; - data.push_back(this->get_request_sequence_number()); - data.push_back(this->get_status()); - return data; + std::vector data; + data.push_back(this->get_request_sequence_number()); + data.push_back(this->get_status()); + return data; } \ No newline at end of file diff --git a/source/SPoverSLIP/WriteResponse.h b/source/SPoverSLIP/WriteResponse.h index 8fb9eb000..4b3c1d728 100644 --- a/source/SPoverSLIP/WriteResponse.h +++ b/source/SPoverSLIP/WriteResponse.h @@ -4,6 +4,6 @@ class WriteResponse : public Response { public: - explicit WriteResponse(uint8_t request_sequence_number, uint8_t status); - std::vector serialize() const override; + explicit WriteResponse(uint8_t request_sequence_number, uint8_t status); + std::vector serialize() const override; }; diff --git a/source/SmartPortOverSlip.cpp b/source/SmartPortOverSlip.cpp index d76e29e0a..e3d7747a8 100644 --- a/source/SmartPortOverSlip.cpp +++ b/source/SmartPortOverSlip.cpp @@ -21,18 +21,18 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // ReSharper disable CppInconsistentNaming #include -#include #include +#include -#include "YamlHelper.h" -#include "SmartPortOverSlip.h" -#include "Interface.h" #include "../Registry.h" +#include "Interface.h" +#include "SmartPortOverSlip.h" +#include "YamlHelper.h" -#include "Memory.h" +#include "../resource/resource.h" #include "CPU.h" #include "Log.h" -#include "../resource/resource.h" +#include "Memory.h" #include "SPoverSLIP/CloseRequest.h" #include "SPoverSLIP/CloseResponse.h" #include "SPoverSLIP/ControlRequest.h" @@ -47,9 +47,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "SPoverSLIP/ReadBlockResponse.h" #include "SPoverSLIP/ReadRequest.h" #include "SPoverSLIP/ReadResponse.h" +#include "SPoverSLIP/Requestor.h" #include "SPoverSLIP/ResetRequest.h" #include "SPoverSLIP/ResetResponse.h" -#include "SPoverSLIP/Requestor.h" #include "SPoverSLIP/StatusRequest.h" #include "SPoverSLIP/StatusResponse.h" #include "SPoverSLIP/WriteBlockRequest.h" @@ -59,348 +59,362 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA int SmartPortOverSlip::active_instances = 0; -const std::string& SmartPortOverSlip::GetSnapshotCardName() +const std::string &SmartPortOverSlip::GetSnapshotCardName() { - static const std::string name("SmartPortOverSlip"); - LogFileOutput("SmartPortOverSlip Returning name SmartPortOverSlip\n"); - return name; + static const std::string name("SmartPortOverSlip"); + return name; } SmartPortOverSlip::SmartPortOverSlip(const UINT slot) : Card(CT_SmartPortOverSlip, slot) { - if (active_instances > 0) { - throw std::runtime_error("There is an existing slot active for SP over SLIP. You can only have 1 of these cards active."); - } - active_instances++; - - LogFileOutput("SmartPortOverSlip ctor, slot: %d\n", slot); - create_listener(); - SmartPortOverSlip::Reset(true); + if (active_instances > 0) + { + throw std::runtime_error("There is an existing slot active for SP over SLIP. You can only have " + "1 of these cards active."); + } + active_instances++; + + LogFileOutput("SmartPortOverSlip ctor, slot: %d\n", slot); + create_listener(); + SmartPortOverSlip::Reset(true); } SmartPortOverSlip::~SmartPortOverSlip() { - active_instances--; - LogFileOutput("SmartPortOverSlip destructor\n"); - if (listener_ != nullptr) - { - listener_->stop(); - } - listener_.reset(); + active_instances--; + LogFileOutput("SmartPortOverSlip destructor\n"); + if (listener_ != nullptr) + { + listener_->stop(); + } + listener_.reset(); } void SmartPortOverSlip::Reset(const bool powerCycle) { - LogFileOutput("SmartPortOverSlip Bridge Initialization, reset called\n"); - if (powerCycle) - { - // send RESET to all devices - const auto connections = listener_->get_all_connections(); - for (const auto& id_and_connection : connections) { - reset(id_and_connection.first, id_and_connection.second); - } - } + LogFileOutput("SmartPortOverSlip Bridge Initialization, reset called\n"); + if (powerCycle) + { + // send RESET to all devices + const auto connections = listener_->get_all_connections(); + for (const auto &id_and_connection : connections) + { + reset(id_and_connection.first, id_and_connection.second); + } + } } void SmartPortOverSlip::handle_write() { - // stack pointer location holds the data we need to service this request - WORD rts_location = static_cast(mem[regs.sp + 1]) + static_cast(mem[regs.sp + 2] << 8); - const BYTE command = mem[rts_location + 1]; - const WORD cmd_list_loc = mem[rts_location + 2] + (mem[rts_location + 3] << 8); - // BYTE paramCount = mem[cmdListLoc]; // parameter count not used - const BYTE unit_number = mem[cmd_list_loc + 1]; - const WORD sp_payload_loc = static_cast(mem[cmd_list_loc + 2]) + static_cast(mem[cmd_list_loc + 3] << 8); - const WORD params_loc = cmd_list_loc + 4; - - LogFileOutput("SmartPortOverSlip processing SP command: 0x%02x, unit: 0x%02x, cmdList: 0x%04x, spPayLoad: 0x%04x, p1: 0x%02x\n", command, unit_number, cmd_list_loc, sp_payload_loc, mem[params_loc]); - - // Fix the stack so the RTS in the firmware returns to the instruction after the data - rts_location += 3; - mem[regs.sp + 1] = rts_location & 0xff; - mem[regs.sp + 2] = (rts_location >> 8) & 0xff; - - // Deal with DIB, doesn't need connection details. - if (unit_number == 0 && mem[params_loc] == 0) - { - device_count(sp_payload_loc); - return; - } - - const auto id_and_connection = listener_->find_connection_with_device(unit_number); - if (id_and_connection.second == nullptr) - { - regs.a = 1; // TODO: what value should we error with? - regs.x = 0; - regs.y = 0; - unset_processor_status(AF_ZERO); - return; - } - - const auto lower_device_id = id_and_connection.first; - const auto connection = id_and_connection.second.get(); - - // convert the unit_number given to the id of the target connection, as we may have more than one connection - const auto target_unit_id = static_cast(unit_number - lower_device_id + 1); - - switch (command) { - case SP_CMD_STATUS: - status(target_unit_id, connection, sp_payload_loc, mem[params_loc]); - break; - case SP_CMD_READBLOCK: - read_block(target_unit_id, connection, sp_payload_loc, params_loc); - break; - case SP_CMD_WRITEBLOCK: - write_block(target_unit_id, connection, sp_payload_loc, params_loc); - break; - case SP_CMD_FORMAT: - format(target_unit_id, connection); - break; - case SP_CMD_CONTROL: - control(target_unit_id, connection, sp_payload_loc, mem[params_loc]); - break; - case SP_CMD_INIT: - init(target_unit_id, connection); - break; - case SP_CMD_OPEN: - open(target_unit_id, connection); - break; - case SP_CMD_CLOSE: - close(target_unit_id, connection); - break; - case SP_CMD_READ: - read(target_unit_id, connection, sp_payload_loc, params_loc); - break; - case SP_CMD_WRITE: - write(target_unit_id, connection, sp_payload_loc, params_loc); - break; - case SP_CMD_RESET: - reset(target_unit_id, connection); - break; - default: - break; - } - + // stack pointer location holds the data we need to service this request + WORD rts_location = static_cast(mem[regs.sp + 1]) + static_cast(mem[regs.sp + 2] << 8); + const BYTE command = mem[rts_location + 1]; + const WORD cmd_list_loc = mem[rts_location + 2] + (mem[rts_location + 3] << 8); + // BYTE paramCount = mem[cmdListLoc]; // parameter count not used + const BYTE unit_number = mem[cmd_list_loc + 1]; + const WORD sp_payload_loc = static_cast(mem[cmd_list_loc + 2]) + static_cast(mem[cmd_list_loc + 3] << 8); + const WORD params_loc = cmd_list_loc + 4; + + LogFileOutput("SmartPortOverSlip processing SP command: 0x%02x, unit: " + "0x%02x, cmdList: 0x%04x, spPayLoad: 0x%04x, p1: 0x%02x\n", + command, unit_number, cmd_list_loc, sp_payload_loc, mem[params_loc]); + + // Fix the stack so the RTS in the firmware returns to the instruction after + // the data + rts_location += 3; + mem[regs.sp + 1] = rts_location & 0xff; + mem[regs.sp + 2] = (rts_location >> 8) & 0xff; + + // Deal with DIB, doesn't need connection details. + if (unit_number == 0 && mem[params_loc] == 0) + { + device_count(sp_payload_loc); + return; + } + + const auto id_and_connection = listener_->find_connection_with_device(unit_number); + if (id_and_connection.second == nullptr) + { + regs.a = 1; // TODO: what value should we error with? + regs.x = 0; + regs.y = 0; + unset_processor_status(AF_ZERO); + return; + } + + const auto lower_device_id = id_and_connection.first; + const auto connection = id_and_connection.second.get(); + + // convert the unit_number given to the id of the target connection, as we may + // have more than one connection + const auto target_unit_id = static_cast(unit_number - lower_device_id + 1); + + switch (command) + { + case SP_CMD_STATUS: + status(target_unit_id, connection, sp_payload_loc, mem[params_loc]); + break; + case SP_CMD_READBLOCK: + read_block(target_unit_id, connection, sp_payload_loc, params_loc); + break; + case SP_CMD_WRITEBLOCK: + write_block(target_unit_id, connection, sp_payload_loc, params_loc); + break; + case SP_CMD_FORMAT: + format(target_unit_id, connection); + break; + case SP_CMD_CONTROL: + control(target_unit_id, connection, sp_payload_loc, mem[params_loc]); + break; + case SP_CMD_INIT: + init(target_unit_id, connection); + break; + case SP_CMD_OPEN: + open(target_unit_id, connection); + break; + case SP_CMD_CLOSE: + close(target_unit_id, connection); + break; + case SP_CMD_READ: + read(target_unit_id, connection, sp_payload_loc, params_loc); + break; + case SP_CMD_WRITE: + write(target_unit_id, connection, sp_payload_loc, params_loc); + break; + case SP_CMD_RESET: + reset(target_unit_id, connection); + break; + default: + break; + } } BYTE SmartPortOverSlip::io_write0(WORD programCounter, const WORD address, const BYTE value, ULONG nCycles) { - const uint8_t loc = address & 0x0f; - // Only do something if $65 is sent to address $02 - if (value == 0x65 && loc == 0x02) - { - handle_write(); - } - return 0; + const uint8_t loc = address & 0x0f; + // Only do something if $65 is sent to address $02 + if (value == 0x65 && loc == 0x02) + { + handle_write(); + } + return 0; } void SmartPortOverSlip::device_count(const WORD sp_payload_loc) { - // Fill the status information directly into SP payload memory. - // The count is from sum of all devices across all Connections. - const BYTE deviceCount = Listener::get_total_device_count(); - mem[sp_payload_loc] = deviceCount; - mem[sp_payload_loc + 1] = 1 << 6; // no interrupt - mem[sp_payload_loc + 2] = 0x4D; // 0x4D46 == MF for vendor ID - mem[sp_payload_loc + 3] = 0x46; - mem[sp_payload_loc + 4] = 0x0A; // version 1.00 Alpha = $100A - mem[sp_payload_loc + 5] = 0x10; - regs.a = 0; - regs.x = 6; - regs.y = 0; - set_processor_status(AF_ZERO); + // Fill the status information directly into SP payload memory. + // The count is from sum of all devices across all Connections. + const BYTE deviceCount = Listener::get_total_device_count(); + mem[sp_payload_loc] = deviceCount; + mem[sp_payload_loc + 1] = 1 << 6; // no interrupt + mem[sp_payload_loc + 2] = 0x4D; // 0x4D46 == MF for vendor ID + mem[sp_payload_loc + 3] = 0x46; + mem[sp_payload_loc + 4] = 0x0A; // version 1.00 Alpha = $100A + mem[sp_payload_loc + 5] = 0x10; + regs.a = 0; + regs.x = 6; + regs.y = 0; + set_processor_status(AF_ZERO); } -void SmartPortOverSlip::read_block(const BYTE unit_number, Connection* connection, const WORD sp_payload_loc, const WORD params_loc) +void SmartPortOverSlip::read_block(const BYTE unit_number, Connection *connection, const WORD sp_payload_loc, const WORD params_loc) { - ReadBlockRequest request(Requestor::next_request_number(), unit_number); - // Assume that (cmd_list_loc + 4 == params_loc) holds 3 bytes for the block number. If it's in the payload, this is wrong and will have to be fixed. - request.set_block_number_from_ptr(mem, params_loc); - auto response = Requestor::send_request(request, connection); - - handle_response(std::move(response), [this, sp_payload_loc](const ReadBlockResponse* rbr) { - memcpy(mem + sp_payload_loc, rbr->get_block_data().data(), 512); - regs.a = 0; - regs.x = 0; - regs.y = 2; // 512 bytes - }); + ReadBlockRequest request(Requestor::next_request_number(), unit_number); + // Assume that (cmd_list_loc + 4 == params_loc) holds 3 bytes for the block + // number. If it's in the payload, this is wrong and will have to be fixed. + request.set_block_number_from_ptr(mem, params_loc); + auto response = Requestor::send_request(request, connection); + + handle_response(std::move(response), + [this, sp_payload_loc](const ReadBlockResponse *rbr) + { + memcpy(mem + sp_payload_loc, rbr->get_block_data().data(), 512); + regs.a = 0; + regs.x = 0; + regs.y = 2; // 512 bytes + }); } -void SmartPortOverSlip::write_block(const BYTE unit_number, Connection* connection, const WORD sp_payload_loc, const WORD params_loc) +void SmartPortOverSlip::write_block(const BYTE unit_number, Connection *connection, const WORD sp_payload_loc, const WORD params_loc) { - WriteBlockRequest request(Requestor::next_request_number(), unit_number); - // Assume that (cmd_list_loc + 4 == params_loc) holds 3 bytes for the block number. The payload contains the data to write - request.set_block_number_from_ptr(mem, params_loc); - request.set_block_data_from_ptr(mem, sp_payload_loc); - - auto response = Requestor::send_request(request, connection); - handle_simple_response(std::move(response)); + WriteBlockRequest request(Requestor::next_request_number(), unit_number); + // Assume that (cmd_list_loc + 4 == params_loc) holds 3 bytes for the block + // number. The payload contains the data to write + request.set_block_number_from_ptr(mem, params_loc); + request.set_block_data_from_ptr(mem, sp_payload_loc); + + auto response = Requestor::send_request(request, connection); + handle_simple_response(std::move(response)); } -void SmartPortOverSlip::read(const BYTE unit_number, Connection* connection, const WORD sp_payload_loc, const WORD params_loc) +void SmartPortOverSlip::read(const BYTE unit_number, Connection *connection, const WORD sp_payload_loc, const WORD params_loc) { - ReadRequest request(Requestor::next_request_number(), unit_number); - request.set_byte_count_from_ptr(mem, params_loc); - request.set_address_from_ptr(mem, params_loc + 2); // move along by byte_count size. would be better to get its size rather than hard code it here. - auto response = Requestor::send_request(request, connection); - - handle_response(std::move(response), [sp_payload_loc](const ReadResponse* rr) { - const auto response_size = rr->get_data().size(); - memcpy(mem + sp_payload_loc, rr->get_data().data(), response_size); - regs.a = 0; - regs.x = response_size & 0xff; - regs.y = (response_size >> 8) & 0xff; - }); + ReadRequest request(Requestor::next_request_number(), unit_number); + request.set_byte_count_from_ptr(mem, params_loc); + request.set_address_from_ptr(mem, params_loc + 2); // move along by byte_count size. would be better to + // get its size rather than hard code it here. + auto response = Requestor::send_request(request, connection); + + handle_response(std::move(response), + [sp_payload_loc](const ReadResponse *rr) + { + const auto response_size = rr->get_data().size(); + memcpy(mem + sp_payload_loc, rr->get_data().data(), response_size); + regs.a = 0; + regs.x = response_size & 0xff; + regs.y = (response_size >> 8) & 0xff; + }); } -void SmartPortOverSlip::write(const BYTE unit_number, Connection* connection, const WORD sp_payload_loc, const WORD params_loc) +void SmartPortOverSlip::write(const BYTE unit_number, Connection *connection, const WORD sp_payload_loc, const WORD params_loc) { - WriteRequest request(Requestor::next_request_number(), unit_number); - request.set_byte_count_from_ptr(mem, params_loc); - request.set_address_from_ptr(mem, params_loc + 2); // move along by byte_count size. would be better to get its size rather than hard code it here. - const auto byte_count = request.get_byte_count(); - const auto write_length = byte_count[0] + (byte_count[1] << 8); - request.set_data_from_ptr(mem, sp_payload_loc, write_length); - - auto response = Requestor::send_request(request, connection); - handle_simple_response(std::move(response)); + WriteRequest request(Requestor::next_request_number(), unit_number); + request.set_byte_count_from_ptr(mem, params_loc); + request.set_address_from_ptr(mem, params_loc + 2); // move along by byte_count size. would be better to + // get its size rather than hard code it here. + const auto byte_count = request.get_byte_count(); + const auto write_length = byte_count[0] + (byte_count[1] << 8); + request.set_data_from_ptr(mem, sp_payload_loc, write_length); + + auto response = Requestor::send_request(request, connection); + handle_simple_response(std::move(response)); } -void SmartPortOverSlip::status(const BYTE unit_number, Connection* connection, const WORD sp_payload_loc, const BYTE status_code) +void SmartPortOverSlip::status(const BYTE unit_number, Connection *connection, const WORD sp_payload_loc, const BYTE status_code) { - // see https://www.1000bit.it/support/manuali/apple/technotes/smpt/tn.smpt.2.html - const StatusRequest request(Requestor::next_request_number(), unit_number, status_code); - auto response = Requestor::send_request(request, connection); - handle_response(std::move(response), [sp_payload_loc](const StatusResponse* sr) { - const auto response_size = sr->get_data().size(); - memcpy(mem + sp_payload_loc, sr->get_data().data(), response_size); - regs.a = 0; - regs.x = response_size & 0xff; - regs.y = (response_size >> 8) & 0xff; - }); + // see + // https://www.1000bit.it/support/manuali/apple/technotes/smpt/tn.smpt.2.html + const StatusRequest request(Requestor::next_request_number(), unit_number, status_code); + auto response = Requestor::send_request(request, connection); + handle_response(std::move(response), + [sp_payload_loc](const StatusResponse *sr) + { + const auto response_size = sr->get_data().size(); + memcpy(mem + sp_payload_loc, sr->get_data().data(), response_size); + regs.a = 0; + regs.x = response_size & 0xff; + regs.y = (response_size >> 8) & 0xff; + }); } -void SmartPortOverSlip::control(const BYTE unit_number, Connection* connection, const WORD sp_payload_loc, const BYTE control_code) +void SmartPortOverSlip::control(const BYTE unit_number, Connection *connection, const WORD sp_payload_loc, const BYTE control_code) { - const auto length = mem[sp_payload_loc] + (mem[sp_payload_loc + 1] << 8) + 2; - uint8_t* start_ptr = &mem[sp_payload_loc]; - std::vector payload(start_ptr, start_ptr + length); + const auto length = mem[sp_payload_loc] + (mem[sp_payload_loc + 1] << 8) + 2; + uint8_t *start_ptr = &mem[sp_payload_loc]; + std::vector payload(start_ptr, start_ptr + length); - const ControlRequest request(Requestor::next_request_number(), unit_number, control_code, payload); - auto response = Requestor::send_request(request, connection); - handle_simple_response(std::move(response)); + const ControlRequest request(Requestor::next_request_number(), unit_number, control_code, payload); + auto response = Requestor::send_request(request, connection); + handle_simple_response(std::move(response)); } -void SmartPortOverSlip::init(const BYTE unit_number, Connection* connection) +void SmartPortOverSlip::init(const BYTE unit_number, Connection *connection) { - const InitRequest request(Requestor::next_request_number(), unit_number); - auto response = Requestor::send_request(request, connection); - handle_simple_response(std::move(response)); + const InitRequest request(Requestor::next_request_number(), unit_number); + auto response = Requestor::send_request(request, connection); + handle_simple_response(std::move(response)); } -void SmartPortOverSlip::open(const BYTE unit_number, Connection* connection) +void SmartPortOverSlip::open(const BYTE unit_number, Connection *connection) { - const OpenRequest request(Requestor::next_request_number(), unit_number); - auto response = Requestor::send_request(request, connection); - handle_simple_response(std::move(response)); + const OpenRequest request(Requestor::next_request_number(), unit_number); + auto response = Requestor::send_request(request, connection); + handle_simple_response(std::move(response)); } -void SmartPortOverSlip::close(const BYTE unit_number, Connection* connection) +void SmartPortOverSlip::close(const BYTE unit_number, Connection *connection) { - const CloseRequest request(Requestor::next_request_number(), unit_number); - auto response = Requestor::send_request(request, connection); - handle_simple_response(std::move(response)); + const CloseRequest request(Requestor::next_request_number(), unit_number); + auto response = Requestor::send_request(request, connection); + handle_simple_response(std::move(response)); } -void SmartPortOverSlip::reset(const BYTE unit_number, Connection* connection) +void SmartPortOverSlip::reset(const BYTE unit_number, Connection *connection) { - const ResetRequest request(Requestor::next_request_number(), unit_number); - auto response = Requestor::send_request(request, connection); - handle_simple_response(std::move(response)); + const ResetRequest request(Requestor::next_request_number(), unit_number); + auto response = Requestor::send_request(request, connection); + handle_simple_response(std::move(response)); } -void SmartPortOverSlip::format(const BYTE unit_number, Connection* connection) +void SmartPortOverSlip::format(const BYTE unit_number, Connection *connection) { - const FormatRequest request(Requestor::next_request_number(), unit_number); - auto response = Requestor::send_request(request, connection); - handle_simple_response(std::move(response)); + const FormatRequest request(Requestor::next_request_number(), unit_number); + auto response = Requestor::send_request(request, connection); + handle_simple_response(std::move(response)); } - BYTE __stdcall c0Handler(const WORD programCounter, const WORD address, const BYTE write, const BYTE value, const ULONG nCycles) { - const UINT uSlot = ((address & 0xf0) >> 4) - 8; - - if (uSlot < 8) { - auto* pCard = static_cast(MemGetSlotParameters(uSlot)); - if (write) { - return pCard->io_write0(programCounter, address, value, nCycles); - } - } - return 0; + const UINT uSlot = ((address & 0xf0) >> 4) - 8; + + if (uSlot < 8) + { + auto *pCard = static_cast(MemGetSlotParameters(uSlot)); + if (write) + { + return pCard->io_write0(programCounter, address, value, nCycles); + } + } + return 0; } void SmartPortOverSlip::InitializeIO(LPBYTE pCxRomPeripheral) { - LogFileOutput("SmartPortOverSlip InitialiseIO\n"); - - // Load firmware into chosen slot - const BYTE* pData = GetFrame().GetResource(IDR_SPOVERSLIP_FW, "FIRMWARE", APPLE_SLOT_SIZE); - if (pData == nullptr) - return; - - // Copy the data into the destination memory - std::memcpy(pCxRomPeripheral + m_slot * APPLE_SLOT_SIZE, pData, APPLE_SLOT_SIZE); - - // Set location in firmware that need to know the slot number for reading/writing to the card - const BYTE locCN1 = pData[0xF9]; // location of where to put $n2 - const BYTE locCN2 = pData[0xFA]; // location of where to put $n2 - const BYTE cn = ((m_slot & 0xff) | 0xC0); // slot(n) || 0xC0 = 0xCn - - const BYTE locN2 = pData[0xFB]; // location of where to put $n2 - const BYTE n2 = static_cast(((m_slot & 0xff) | 0x08) << 4) + 0x02; // (slot + 8) * 16 + 2, giving low byte of $C0n2 - - // Modify the destination memory to hold the slot information needed by the firmware. - // The pData memory is R/O, and we get an access violation writing to it, so alter the destination instead. - const LPBYTE pDest = pCxRomPeripheral + m_slot * APPLE_SLOT_SIZE; - pDest[locCN1] = cn; - pDest[locCN2] = cn; - pDest[locN2] = n2; - - RegisterIoHandler(m_slot, nullptr, c0Handler, nullptr, nullptr, this, nullptr); + // Load firmware into chosen slot + const BYTE *pData = GetFrame().GetResource(IDR_SPOVERSLIP_FW, "FIRMWARE", APPLE_SLOT_SIZE); + if (pData == nullptr) + return; + + // Copy the data into the destination memory + std::memcpy(pCxRomPeripheral + m_slot * APPLE_SLOT_SIZE, pData, APPLE_SLOT_SIZE); + + // Set location in firmware that need to know the slot number for + // reading/writing to the card + const BYTE locCN1 = pData[0xF9]; // location of where to put $n2 + const BYTE locCN2 = pData[0xFA]; // location of where to put $n2 + const BYTE cn = ((m_slot & 0xff) | 0xC0); // slot(n) || 0xC0 = 0xCn + + const BYTE locN2 = pData[0xFB]; // location of where to put $n2 + const BYTE n2 = static_cast(((m_slot & 0xff) | 0x08) << 4) + 0x02; // (slot + 8) * 16 + 2, giving low byte of $C0n2 + + // Modify the destination memory to hold the slot information needed by the + // firmware. The pData memory is R/O, and we get an access violation writing + // to it, so alter the destination instead. + const LPBYTE pDest = pCxRomPeripheral + m_slot * APPLE_SLOT_SIZE; + pDest[locCN1] = cn; + pDest[locCN2] = cn; + pDest[locN2] = n2; + + RegisterIoHandler(m_slot, nullptr, c0Handler, nullptr, nullptr, this, nullptr); } void SmartPortOverSlip::Update(const ULONG nExecutedCycles) { - // LogFileOutput("SmartPortOverSlip Update\n"); + // LogFileOutput("SmartPortOverSlip Update\n"); } +void SmartPortOverSlip::SaveSnapshot(YamlSaveHelper &yamlSaveHelper) { LogFileOutput("SmartPortOverSlip SaveSnapshot\n"); } -void SmartPortOverSlip::SaveSnapshot(YamlSaveHelper& yamlSaveHelper) -{ - LogFileOutput("SmartPortOverSlip SaveSnapshot\n"); -} - -bool SmartPortOverSlip::LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT version) +bool SmartPortOverSlip::LoadSnapshot(YamlLoadHelper &yamlLoadHelper, UINT version) { - LogFileOutput("SmartPortOverSlip LoadSnapshot\n"); - return true; + LogFileOutput("SmartPortOverSlip LoadSnapshot\n"); + return true; } void SmartPortOverSlip::create_listener() { - // grab the configured IP and Port TODO + // grab the configured IP and Port TODO - listener_ = std::make_unique("0.0.0.0", 1985); - listener_->start(); - LogFileOutput("SmartPortOverSlip Created SP over SLIP listener on 0.0.0.0:1985\n"); + listener_ = std::make_unique("0.0.0.0", 1985); + listener_->start(); + LogFileOutput("SmartPortOverSlip Created SP over SLIP listener on 0.0.0.0:1985\n"); } void SmartPortOverSlip::Destroy() { - // Stop the listener and its connections - if (listener_ != nullptr) - { - listener_->stop(); - } + // Stop the listener and its connections + if (listener_ != nullptr) + { + listener_->stop(); + } } diff --git a/source/SmartPortOverSlip.h b/source/SmartPortOverSlip.h index fbe1cdd20..ef7dcc73b 100644 --- a/source/SmartPortOverSlip.h +++ b/source/SmartPortOverSlip.h @@ -14,112 +14,112 @@ class InitResponse; enum { - SP_CMD_STATUS = 0, - SP_CMD_READBLOCK = 1, - SP_CMD_WRITEBLOCK = 2, - SP_CMD_FORMAT = 3, - SP_CMD_CONTROL = 4, - SP_CMD_INIT = 5, - SP_CMD_OPEN = 6, - SP_CMD_CLOSE = 7, - SP_CMD_READ = 8, - SP_CMD_WRITE = 9, - SP_CMD_RESET = 10 + SP_CMD_STATUS = 0, + SP_CMD_READBLOCK = 1, + SP_CMD_WRITEBLOCK = 2, + SP_CMD_FORMAT = 3, + SP_CMD_CONTROL = 4, + SP_CMD_INIT = 5, + SP_CMD_OPEN = 6, + SP_CMD_CLOSE = 7, + SP_CMD_READ = 8, + SP_CMD_WRITE = 9, + SP_CMD_RESET = 10 }; - class SmartPortOverSlip : public Card { public: - static const std::string& GetSnapshotCardName(); - - explicit SmartPortOverSlip(UINT slot); - ~SmartPortOverSlip() override; - - void Destroy() override; - void InitializeIO(LPBYTE pCxRomPeripheral) override; - void Reset(bool powerCycle) override; - void Update(ULONG nExecutedCycles) override; - void SaveSnapshot(YamlSaveHelper& yamlSaveHelper) override; - bool LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT version) override; - - BYTE io_write0(WORD programCounter, WORD address, BYTE value, ULONG nCycles); - static void device_count(WORD sp_payload_loc); - void handle_write(); - void status(BYTE unit_number, Connection* connection, WORD sp_payload_loc, BYTE status_code); - void control(BYTE unit_number, Connection* connection, WORD sp_payload_loc, BYTE control_code); - void init(BYTE unit_number, Connection* connection); - void open(BYTE unit_number, Connection* connection); - void close(BYTE unit_number, Connection* connection); - void format(BYTE unit_number, Connection* connection); - void reset(BYTE unit_number, Connection* connection); - void read_block(BYTE unit_number, Connection* connection, WORD sp_payload_loc, WORD params_loc); - void write_block(BYTE unit_number, Connection* connection, WORD sp_payload_loc, WORD params_loc); - void read(BYTE unit_number, Connection* connection, WORD sp_payload_loc, WORD params_loc); - void write(BYTE unit_number, Connection* connection, WORD sp_payload_loc, WORD params_loc); - - static void set_processor_status(const uint8_t flags) { regs.ps |= flags; } - static void unset_processor_status(const uint8_t flags) { regs.ps &= (0xFF - flags); } - // if condition is true then set the flags given, else remove them. - static void update_processor_status(const bool condition, const uint8_t flags) { condition ? set_processor_status(flags) : unset_processor_status(flags); } - - // SP over SLIP - void create_listener(); - - template - void handle_simple_response(const std::unique_ptr response) { - static_assert(std::is_base_of::value, "T must be a subclass of Response"); - auto specific_response = dynamic_cast(response.get()); - - if (specific_response != nullptr) - { - const BYTE status = specific_response->get_status(); - regs.a = status; - regs.x = 0; - regs.y = 0; - update_processor_status(status == 0, AF_ZERO); - } - else - { - regs.a = 1; // TODO: what error should we return? - regs.x = 0; - regs.y = 0; - unset_processor_status(AF_ZERO); - } - } - - template - void handle_response(const std::unique_ptr response, Func call_back) { - auto specific_response = dynamic_cast(response.get()); - - if (specific_response != nullptr) - { - if (specific_response->get_status() == 0) - { - call_back(specific_response); - set_processor_status(AF_ZERO); - } - else - { - // An error in the response - regs.a = specific_response->get_status(); - regs.x = 0; - regs.y = 0; - unset_processor_status(AF_ZERO); - } - } - else - { - // An error trying to do the request, as there was no response - regs.a = 1; // TODO: what error should we return? - regs.x = 0; - regs.y = 0; - unset_processor_status(AF_ZERO); - } + static const std::string &GetSnapshotCardName(); + + explicit SmartPortOverSlip(UINT slot); + ~SmartPortOverSlip() override; + + void Destroy() override; + void InitializeIO(LPBYTE pCxRomPeripheral) override; + void Reset(bool powerCycle) override; + void Update(ULONG nExecutedCycles) override; + void SaveSnapshot(YamlSaveHelper &yamlSaveHelper) override; + bool LoadSnapshot(YamlLoadHelper &yamlLoadHelper, UINT version) override; + + BYTE io_write0(WORD programCounter, WORD address, BYTE value, ULONG nCycles); + static void device_count(WORD sp_payload_loc); + void handle_write(); + void status(BYTE unit_number, Connection *connection, WORD sp_payload_loc, BYTE status_code); + void control(BYTE unit_number, Connection *connection, WORD sp_payload_loc, BYTE control_code); + void init(BYTE unit_number, Connection *connection); + void open(BYTE unit_number, Connection *connection); + void close(BYTE unit_number, Connection *connection); + void format(BYTE unit_number, Connection *connection); + void reset(BYTE unit_number, Connection *connection); + void read_block(BYTE unit_number, Connection *connection, WORD sp_payload_loc, WORD params_loc); + void write_block(BYTE unit_number, Connection *connection, WORD sp_payload_loc, WORD params_loc); + void read(BYTE unit_number, Connection *connection, WORD sp_payload_loc, WORD params_loc); + void write(BYTE unit_number, Connection *connection, WORD sp_payload_loc, WORD params_loc); + + static void set_processor_status(const uint8_t flags) { regs.ps |= flags; } + static void unset_processor_status(const uint8_t flags) { regs.ps &= (0xFF - flags); } + // if condition is true then set the flags given, else remove them. + static void update_processor_status(const bool condition, const uint8_t flags) { condition ? set_processor_status(flags) : unset_processor_status(flags); } + + // SP over SLIP + void create_listener(); + + template void handle_simple_response(const std::unique_ptr response) + { + static_assert(std::is_base_of::value, "T must be a subclass of Response"); + auto specific_response = dynamic_cast(response.get()); + + if (specific_response != nullptr) + { + const BYTE status = specific_response->get_status(); + regs.a = status; + regs.x = 0; + regs.y = 0; + update_processor_status(status == 0, AF_ZERO); + } + else + { + regs.a = 1; // TODO: what error should we return? + regs.x = 0; + regs.y = 0; + unset_processor_status(AF_ZERO); + } + } + + template void handle_response(const std::unique_ptr response, Func call_back) + { + auto specific_response = dynamic_cast(response.get()); + + if (specific_response != nullptr) + { + if (specific_response->get_status() == 0) + { + call_back(specific_response); + set_processor_status(AF_ZERO); + } + else + { + // An error in the response + regs.a = specific_response->get_status(); + regs.x = 0; + regs.y = 0; + unset_processor_status(AF_ZERO); + } } + else + { + // An error trying to do the request, as there was no response + regs.a = 1; // TODO: what error should we return? + regs.x = 0; + regs.y = 0; + unset_processor_status(AF_ZERO); + } + } + private: - std::unique_ptr listener_; + std::unique_ptr listener_; - // Ensure no more than 1 card is active, as we only listen on 1 port - static int active_instances; -}; \ No newline at end of file + // Ensure no more than 1 card is active, as we only listen on 1 port + static int active_instances; +}; diff --git a/source/frontends/qt/qapple.qrc b/source/frontends/qt/qapple.qrc index 5484eb477..5fdcaf642 100644 --- a/source/frontends/qt/qapple.qrc +++ b/source/frontends/qt/qapple.qrc @@ -22,6 +22,7 @@ resources/Apple2_JPlus_Video.rom resources/Base64A.rom resources/Base64A_German_Video.rom + resources/spoverslip.bin resources/APPLEWIN.ICO diff --git a/source/frontends/sdl/imgui/settingshelper.cpp b/source/frontends/sdl/imgui/settingshelper.cpp index 21adc15e7..e23f89de7 100644 --- a/source/frontends/sdl/imgui/settingshelper.cpp +++ b/source/frontends/sdl/imgui/settingshelper.cpp @@ -42,6 +42,7 @@ namespace {CT_SNESMAX, "SNESMAX"}, {CT_VidHD, "VidHD"}, {CT_Uthernet2, "Uthernet2"}, + {CT_SmartPortOverSlip, "SPoverSLIP"}, }; const std::map apple2Types = @@ -110,13 +111,13 @@ namespace const std::map> cardsForSlots = { {0, {CT_Empty, CT_LanguageCard, CT_Saturn128K}}, - {1, {CT_Empty, CT_GenericPrinter, CT_Uthernet2}}, - {2, {CT_Empty, CT_SSC, CT_Uthernet2}}, - {3, {CT_Empty, CT_Uthernet, CT_Uthernet2, CT_VidHD}}, - {4, {CT_Empty, CT_MockingboardC, CT_MegaAudio, CT_SDMusic, CT_MouseInterface, CT_Phasor, CT_Uthernet2}}, - {5, {CT_Empty, CT_MockingboardC, CT_MegaAudio, CT_SDMusic, CT_Disk2, CT_GenericHDD, CT_Phasor, CT_Uthernet2, CT_Z80, CT_SAM, CT_FourPlay, CT_SNESMAX}}, - {6, {CT_Empty, CT_Disk2, CT_Uthernet2}}, - {7, {CT_Empty, CT_GenericHDD, CT_Uthernet2}}, + {1, {CT_Empty, CT_GenericPrinter, CT_Uthernet2, CT_SmartPortOverSlip}}, + {2, {CT_Empty, CT_SSC, CT_Uthernet2, CT_SmartPortOverSlip}}, + {3, {CT_Empty, CT_Uthernet, CT_Uthernet2, CT_SmartPortOverSlip, CT_VidHD}}, + {4, {CT_Empty, CT_MockingboardC, CT_MegaAudio, CT_SDMusic, CT_MouseInterface, CT_Phasor, CT_Uthernet2, CT_SmartPortOverSlip}}, + {5, {CT_Empty, CT_MockingboardC, CT_MegaAudio, CT_SDMusic, CT_Disk2, CT_GenericHDD, CT_Phasor, CT_Uthernet2, CT_SmartPortOverSlip, CT_Z80, CT_SAM, CT_FourPlay, CT_SNESMAX}}, + {6, {CT_Empty, CT_Disk2, CT_Uthernet2, CT_SmartPortOverSlip}}, + {7, {CT_Empty, CT_GenericHDD, CT_Uthernet2, CT_SmartPortOverSlip}}, }; const std::vector expansionCards = diff --git a/source/linux/resources.cpp b/source/linux/resources.cpp index e4f99e350..4323a65f8 100644 --- a/source/linux/resources.cpp +++ b/source/linux/resources.cpp @@ -27,7 +27,8 @@ namespace {IDR_MOUSEINTERFACE_FW, "MouseInterface.rom"}, {IDR_THUNDERCLOCKPLUS_FW, "ThunderClockPlus.rom"}, {IDR_TKCLOCK_FW, "TKClock.rom"}, - {IDR_BASE64A_VIDEO_ROM, "Base64A_German_Video.rom"} + {IDR_BASE64A_VIDEO_ROM, "Base64A_German_Video.rom"}, + {IDR_SPOVERSLIP_FW, "spoverslip.bin"} }; }