diff --git a/.gitignore b/.gitignore index bcc6747..2566527 100644 --- a/.gitignore +++ b/.gitignore @@ -15,8 +15,10 @@ JasonWang/Lab1/build JasonWang/Lab2/Part1/build JasonWang/Lab2/Part1/result +Jason/lab3/result Jason/lab2/Part3/result + BenHall/lab1/part1/build BenHall/lab1/part2/build BenHall/lab2/part1/result/ diff --git a/Jason/lab3/CMakeLists.txt b/Jason/lab3/CMakeLists.txt new file mode 100644 index 0000000..2d43862 --- /dev/null +++ b/Jason/lab3/CMakeLists.txt @@ -0,0 +1,39 @@ +cmake_minimum_required(VERSION 3.10) +project(Lab3) + + +find_package(Protobuf REQUIRED) + +# Define the libraries +add_library(msg STATIC proto/message.pb.cc) +add_library(server STATIC src/server.cpp) +add_library(client STATIC src/client.cpp) + +target_include_directories(client PUBLIC + "$" + "$" +) +target_include_directories(server PUBLIC + "$" + "$" +) +target_include_directories(msg PUBLIC + "$" + "$" +) + +#Link the necessary targets +target_link_libraries(msg PUBLIC protobuf::libprotobuf) +target_link_libraries(client PUBLIC msg) +target_link_libraries(server PUBLIC msg) + +# Add the server executable +add_executable(server_exe app/server_driver.cpp) +target_link_libraries(server_exe PUBLIC server) + + +# Add the client executable +add_executable(client_exe app/client_driver.cpp) +target_link_libraries(client_exe PUBLIC client) + +install (TARGETS server_exe client_exe DESTINATION ${CMAKE_INSTALL_BINDIR}) \ No newline at end of file diff --git a/Jason/lab3/app/client_driver.cpp b/Jason/lab3/app/client_driver.cpp new file mode 100644 index 0000000..d78b74b --- /dev/null +++ b/Jason/lab3/app/client_driver.cpp @@ -0,0 +1,53 @@ +#include "client.hpp" +#include + +/** + * @brief Executable that initiates Client + * + * This files boots up the Client + */ +int main() { + // Initialize the client with server IP and port + Client client("127.0.0.1", 8080); // Replace with the server's IP address AKA the car + + // Create and send a message with the input '1' + message::data message; + message.set_sender_name("Msg From Client"); + + std::string input; + std::cout << "Press Enter to send a message: "; + std::getline(std::cin, input); + + while (true) { + std::cout << "Press Enter to send a message (or type -1 to exit): "; + std::getline(std::cin, input); + + // If the user enters -1, break the loop and exit + if (input == "-1") { + std::cout << "Exiting program..." << std::endl; + break; + } + + // If Enter is pressed (input is empty), send the message + if (input.empty()) { + // Send the message + if (client.SendMessage(message)) { + std::cout << "Message sent successfully" << std::endl; + } else { + std::cerr << "Failed to send message" << std::endl; + } + + // Receive and print the response + message::data responseMessage; + if (client.ReceiveMessage(responseMessage)) { + std::cout << "Received response from server" << std::endl; + } else { + std::cerr << "Failed to receive response" << std::endl; + } + } else { + std::cout << "No message sent." << std::endl; + } + } + + return 0; +} \ No newline at end of file diff --git a/Jason/lab3/app/server_driver.cpp b/Jason/lab3/app/server_driver.cpp new file mode 100644 index 0000000..62a42e0 --- /dev/null +++ b/Jason/lab3/app/server_driver.cpp @@ -0,0 +1,35 @@ +#include "server.hpp" +#include + +/** + * @brief Executable that initiates Server + * + * This files boots up the Server + */ +int main() { + // Initiate Server + Server server("0.0.0.0", 8080); + + std::cout << "Server is running and listening on port 8080..." << std::endl; + // Be on the constant lookout for messages + while (true) { + message::data receivedMessage; + + // Receive message from client + if (server.ReceiveMessage(receivedMessage)) { + // Prepare and send a response to client + message::data responseMessage; + responseMessage.set_sender_name("Message from Server"); + // Send message + if (server.SendMessage(responseMessage)) { + std::cout << "Response sent successfully" << std::endl; + } else { + std::cerr << "Failed to send response" << std::endl; + } + } else { + std::cerr << "Failed to receive message" << std::endl; + } + } + + return 0; +} \ No newline at end of file diff --git a/Jason/lab3/default.nix b/Jason/lab3/default.nix new file mode 100644 index 0000000..4995284 --- /dev/null +++ b/Jason/lab3/default.nix @@ -0,0 +1,9 @@ +{ stdenv, cmake, protobuf }: + +stdenv.mkDerivation rec { + pname = "lab3"; + version = "0.1.0"; + src = ./.; + nativeBuildInputs = [ cmake ]; + buildInputs = [ protobuf ]; +} \ No newline at end of file diff --git a/Jason/lab3/flake.lock b/Jason/lab3/flake.lock new file mode 100644 index 0000000..fba1f5e --- /dev/null +++ b/Jason/lab3/flake.lock @@ -0,0 +1,60 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1726188729, + "narHash": "sha256-7Q3KfkL7omryydTOZTj8KxMVl+B8P6XASkLSHmk8A7c=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "c3dabc54aaee299aa23483c293950eeae55bbf03", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixutils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs", + "nixutils": "nixutils" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/Jason/lab3/flake.nix b/Jason/lab3/flake.nix new file mode 100644 index 0000000..7ad3064 --- /dev/null +++ b/Jason/lab3/flake.nix @@ -0,0 +1,54 @@ +{ + description = "Lab 3 flake"; + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs"; + nixutils.url = "github:numtide/flake-utils"; + }; + + outputs = { + self, nixpkgs, nixutils + }: + + let + system = "aarch64-darwin"; + lab3_overlay = final: prev: { + lab3 = final.callPackage ./default.nix { }; + }; + + my_overlays = [ lab3_overlay ]; + pkgs = import nixpkgs { + system = "aarch64-darwin"; + overlays = [ self.overlays.default ]; + }; + + in { + overlays.default = nixpkgs.lib.composeManyExtensions my_overlays; + + packages.aarch64-darwin = + rec { + lab3 = pkgs.lab3; + default = lab3; + }; + + devShells.aarch64-darwin.default = + pkgs.mkShell rec { + name = "nix-devshell"; + packages = with pkgs; [ + cmake + protobuf + lab3 + ]; + shellHook = '' + export PS1="$(echo -e '\uF121') {\[$(tput sgr0)\]\[\033[38;5;228m\]\w\[$(tput sgr0)\]\[\033[38;5;15m\]} (${name}) \\$ \[$(tput sgr0)\]" + ''; + }; + + legacyPackages.aarch64-darwin = + import nixpkgs { + inherit system; + overlays = [ + (final: _: { lab3 = final.callPackage ./default.nix { }; }) + ]; + }; + }; +} \ No newline at end of file diff --git a/Jason/lab3/include/UDPSocket.hpp b/Jason/lab3/include/UDPSocket.hpp new file mode 100644 index 0000000..b5d95a2 --- /dev/null +++ b/Jason/lab3/include/UDPSocket.hpp @@ -0,0 +1,24 @@ +#ifndef UDP_SOCKET_H +#define UDP_SOCKET_H + +#include +#include + +class UDPSocket { +public: + UDPSocket(); + ~UDPSocket(); + + bool bindSocket(const std::string& ip, int port); + ssize_t sendTo(const std::string& message, const std::string& ip, int port); + ssize_t receiveFrom(std::string& message, std::string& senderIp, int& senderPort); + +private: + int sockfd; + struct sockaddr_in localAddr; + struct sockaddr_in remoteAddr; + + void closeSocket(); +}; + +#endif // UDP_SOCKET_H diff --git a/Jason/lab3/include/client.hpp b/Jason/lab3/include/client.hpp new file mode 100644 index 0000000..69190eb --- /dev/null +++ b/Jason/lab3/include/client.hpp @@ -0,0 +1,25 @@ +#ifndef CLIENT_H +#define CLIENT_H + +#include +#include // For sockaddr_in +#include // For socket functions +#include // For close + +#include "message.pb.h" + +class Client { +public: + Client(const std::string& server_ip, uint16_t server_port); + ~Client(); + + bool SendMessage(const message::data& message); + bool ReceiveMessage(message::data& message); + +private: + int _sockfd; + sockaddr_in _server_addr; + static const int _BUFFER_SIZE = 1024; +}; + +#endif // CLIENT_H \ No newline at end of file diff --git a/Jason/lab3/include/server.hpp b/Jason/lab3/include/server.hpp new file mode 100644 index 0000000..a00446f --- /dev/null +++ b/Jason/lab3/include/server.hpp @@ -0,0 +1,26 @@ +#ifndef SERVER_H +#define SERVER_H + +#include +#include // For sockaddr_in +#include // For socket functions +#include // For close + +#include "message.pb.h" + +class Server { +public: + Server(const std::string& server_ip, uint16_t server_port); + ~Server(); + + bool SendMessage(const message::data& message); + bool ReceiveMessage(message::data& message); + +private: + int _sock; + sockaddr_in _server_addr; + sockaddr_in _client_addr; + static const int _BUFFER_SIZE = 1024; +}; + +#endif // SERVER_H \ No newline at end of file diff --git a/Jason/lab3/proto/message.pb.cc b/Jason/lab3/proto/message.pb.cc new file mode 100644 index 0000000..98cfd43 --- /dev/null +++ b/Jason/lab3/proto/message.pb.cc @@ -0,0 +1,310 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: message.proto + +#include "message.pb.h" + +#include +#include "google/protobuf/io/coded_stream.h" +#include "google/protobuf/extension_set.h" +#include "google/protobuf/wire_format_lite.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/generated_message_reflection.h" +#include "google/protobuf/reflection_ops.h" +#include "google/protobuf/wire_format.h" +#include "google/protobuf/generated_message_tctable_impl.h" +// @@protoc_insertion_point(includes) + +// Must be included last. +#include "google/protobuf/port_def.inc" +PROTOBUF_PRAGMA_INIT_SEG +namespace _pb = ::google::protobuf; +namespace _pbi = ::google::protobuf::internal; +namespace _fl = ::google::protobuf::internal::field_layout; +namespace message { + +inline constexpr data::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : sender_name_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + _cached_size_{0} {} + +template +PROTOBUF_CONSTEXPR data::data(::_pbi::ConstantInitialized) + : _impl_(::_pbi::ConstantInitialized()) {} +struct dataDefaultTypeInternal { + PROTOBUF_CONSTEXPR dataDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~dataDefaultTypeInternal() {} + union { + data _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 dataDefaultTypeInternal _data_default_instance_; +} // namespace message +static ::_pb::Metadata file_level_metadata_message_2eproto[1]; +static constexpr const ::_pb::EnumDescriptor** + file_level_enum_descriptors_message_2eproto = nullptr; +static constexpr const ::_pb::ServiceDescriptor** + file_level_service_descriptors_message_2eproto = nullptr; +const ::uint32_t TableStruct_message_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE( + protodesc_cold) = { + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::message::data, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::message::data, _impl_.sender_name_), +}; + +static const ::_pbi::MigrationSchema + schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + {0, -1, -1, sizeof(::message::data)}, +}; + +static const ::_pb::Message* const file_default_instances[] = { + &::message::_data_default_instance_._instance, +}; +const char descriptor_table_protodef_message_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + "\n\rmessage.proto\022\007message\"\033\n\004data\022\023\n\013send" + "er_name\030\001 \001(\tb\006proto3" +}; +static ::absl::once_flag descriptor_table_message_2eproto_once; +const ::_pbi::DescriptorTable descriptor_table_message_2eproto = { + false, + false, + 61, + descriptor_table_protodef_message_2eproto, + "message.proto", + &descriptor_table_message_2eproto_once, + nullptr, + 0, + 1, + schemas, + file_default_instances, + TableStruct_message_2eproto::offsets, + file_level_metadata_message_2eproto, + file_level_enum_descriptors_message_2eproto, + file_level_service_descriptors_message_2eproto, +}; + +// This function exists to be marked as weak. +// It can significantly speed up compilation by breaking up LLVM's SCC +// in the .pb.cc translation units. Large translation units see a +// reduction of more than 35% of walltime for optimized builds. Without +// the weak attribute all the messages in the file, including all the +// vtables and everything they use become part of the same SCC through +// a cycle like: +// GetMetadata -> descriptor table -> default instances -> +// vtables -> GetMetadata +// By adding a weak function here we break the connection from the +// individual vtables back into the descriptor table. +PROTOBUF_ATTRIBUTE_WEAK const ::_pbi::DescriptorTable* descriptor_table_message_2eproto_getter() { + return &descriptor_table_message_2eproto; +} +// Force running AddDescriptors() at dynamic initialization time. +PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 +static ::_pbi::AddDescriptorsRunner dynamic_init_dummy_message_2eproto(&descriptor_table_message_2eproto); +namespace message { +// =================================================================== + +class data::_Internal { + public: +}; + +data::data(::google::protobuf::Arena* arena) + : ::google::protobuf::Message(arena) { + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:message.data) +} +inline PROTOBUF_NDEBUG_INLINE data::Impl_::Impl_( + ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, + const Impl_& from) + : sender_name_(arena, from.sender_name_), + _cached_size_{0} {} + +data::data( + ::google::protobuf::Arena* arena, + const data& from) + : ::google::protobuf::Message(arena) { + data* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_); + + // @@protoc_insertion_point(copy_constructor:message.data) +} +inline PROTOBUF_NDEBUG_INLINE data::Impl_::Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena) + : sender_name_(arena), + _cached_size_{0} {} + +inline void data::SharedCtor(::_pb::Arena* arena) { + new (&_impl_) Impl_(internal_visibility(), arena); +} +data::~data() { + // @@protoc_insertion_point(destructor:message.data) + _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + SharedDtor(); +} +inline void data::SharedDtor() { + ABSL_DCHECK(GetArena() == nullptr); + _impl_.sender_name_.Destroy(); + _impl_.~Impl_(); +} + +PROTOBUF_NOINLINE void data::Clear() { +// @@protoc_insertion_point(message_clear_start:message.data) + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.sender_name_.ClearToEmpty(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +const char* data::_InternalParse( + const char* ptr, ::_pbi::ParseContext* ctx) { + ptr = ::_pbi::TcParser::ParseLoop(this, ptr, ctx, &_table_.header); + return ptr; +} + + +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<0, 1, 0, 32, 2> data::_table_ = { + { + 0, // no _has_bits_ + 0, // no _extensions_ + 1, 0, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967294, // skipmap + offsetof(decltype(_table_), field_entries), + 1, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + &_data_default_instance_._instance, + ::_pbi::TcParser::GenericFallback, // fallback + }, {{ + // string sender_name = 1; + {::_pbi::TcParser::FastUS1, + {10, 63, 0, PROTOBUF_FIELD_OFFSET(data, _impl_.sender_name_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // string sender_name = 1; + {PROTOBUF_FIELD_OFFSET(data, _impl_.sender_name_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kUtf8String | ::_fl::kRepAString)}, + }}, + // no aux_entries + {{ + "\14\13\0\0\0\0\0\0" + "message.data" + "sender_name" + }}, +}; + +::uint8_t* data::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:message.data) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // string sender_name = 1; + if (!this->_internal_sender_name().empty()) { + const std::string& _s = this->_internal_sender_name(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "message.data.sender_name"); + target = stream->WriteStringMaybeAliased(1, _s, target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:message.data) + return target; +} + +::size_t data::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:message.data) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // string sender_name = 1; + if (!this->_internal_sender_name().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this->_internal_sender_name()); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::google::protobuf::Message::ClassData data::_class_data_ = { + data::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor +}; +const ::google::protobuf::Message::ClassData* data::GetClassData() const { + return &_class_data_; +} + +void data::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:message.data) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + if (!from._internal_sender_name().empty()) { + _this->_internal_set_sender_name(from._internal_sender_name()); + } + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void data::CopyFrom(const data& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:message.data) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +PROTOBUF_NOINLINE bool data::IsInitialized() const { + return true; +} + +::_pbi::CachedSize* data::AccessCachedSize() const { + return &_impl_._cached_size_; +} +void data::InternalSwap(data* PROTOBUF_RESTRICT other) { + using std::swap; + auto* arena = GetArena(); + ABSL_DCHECK_EQ(arena, other->GetArena()); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.sender_name_, &other->_impl_.sender_name_, arena); +} + +::google::protobuf::Metadata data::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_message_2eproto_getter, &descriptor_table_message_2eproto_once, + file_level_metadata_message_2eproto[0]); +} +// @@protoc_insertion_point(namespace_scope) +} // namespace message +namespace google { +namespace protobuf { +} // namespace protobuf +} // namespace google +// @@protoc_insertion_point(global_scope) +#include "google/protobuf/port_undef.inc" diff --git a/Jason/lab3/proto/message.pb.h b/Jason/lab3/proto/message.pb.h new file mode 100644 index 0000000..fa555cd --- /dev/null +++ b/Jason/lab3/proto/message.pb.h @@ -0,0 +1,337 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: message.proto +// Protobuf C++ Version: 4.25.4 + +#ifndef GOOGLE_PROTOBUF_INCLUDED_message_2eproto_2epb_2eh +#define GOOGLE_PROTOBUF_INCLUDED_message_2eproto_2epb_2eh + +#include +#include +#include +#include + +#include "google/protobuf/port_def.inc" +#if PROTOBUF_VERSION < 4025000 +#error "This file was generated by a newer version of protoc which is" +#error "incompatible with your Protocol Buffer headers. Please update" +#error "your headers." +#endif // PROTOBUF_VERSION + +#if 4025004 < PROTOBUF_MIN_PROTOC_VERSION +#error "This file was generated by an older version of protoc which is" +#error "incompatible with your Protocol Buffer headers. Please" +#error "regenerate this file with a newer version of protoc." +#endif // PROTOBUF_MIN_PROTOC_VERSION +#include "google/protobuf/port_undef.inc" +#include "google/protobuf/io/coded_stream.h" +#include "google/protobuf/arena.h" +#include "google/protobuf/arenastring.h" +#include "google/protobuf/generated_message_tctable_decl.h" +#include "google/protobuf/generated_message_util.h" +#include "google/protobuf/metadata_lite.h" +#include "google/protobuf/generated_message_reflection.h" +#include "google/protobuf/message.h" +#include "google/protobuf/repeated_field.h" // IWYU pragma: export +#include "google/protobuf/extension_set.h" // IWYU pragma: export +#include "google/protobuf/unknown_field_set.h" +// @@protoc_insertion_point(includes) + +// Must be included last. +#include "google/protobuf/port_def.inc" + +#define PROTOBUF_INTERNAL_EXPORT_message_2eproto + +namespace google { +namespace protobuf { +namespace internal { +class AnyMetadata; +} // namespace internal +} // namespace protobuf +} // namespace google + +// Internal implementation detail -- do not use these members. +struct TableStruct_message_2eproto { + static const ::uint32_t offsets[]; +}; +extern const ::google::protobuf::internal::DescriptorTable + descriptor_table_message_2eproto; +namespace message { +class data; +struct dataDefaultTypeInternal; +extern dataDefaultTypeInternal _data_default_instance_; +} // namespace message +namespace google { +namespace protobuf { +} // namespace protobuf +} // namespace google + +namespace message { + +// =================================================================== + + +// ------------------------------------------------------------------- + +class data final : + public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:message.data) */ { + public: + inline data() : data(nullptr) {} + ~data() override; + template + explicit PROTOBUF_CONSTEXPR data(::google::protobuf::internal::ConstantInitialized); + + inline data(const data& from) + : data(nullptr, from) {} + data(data&& from) noexcept + : data() { + *this = ::std::move(from); + } + + inline data& operator=(const data& from) { + CopyFrom(from); + return *this; + } + inline data& operator=(data&& from) noexcept { + if (this == &from) return *this; + if (GetArena() == from.GetArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const data& default_instance() { + return *internal_default_instance(); + } + static inline const data* internal_default_instance() { + return reinterpret_cast( + &_data_default_instance_); + } + static constexpr int kIndexInFileMessages = + 0; + + friend void swap(data& a, data& b) { + a.Swap(&b); + } + inline void Swap(data* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetArena() != nullptr && + GetArena() == other->GetArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetArena() == other->GetArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(data* other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + data* New(::google::protobuf::Arena* arena = nullptr) const final { + return CreateMaybeMessage(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const data& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom( const data& from) { + data::MergeImpl(*this, from); + } + private: + static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + ::size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::google::protobuf::internal::ParseContext* ctx) final; + ::uint8_t* _InternalSerialize( + ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + ::google::protobuf::internal::CachedSize* AccessCachedSize() const final; + void SharedCtor(::google::protobuf::Arena* arena); + void SharedDtor(); + void InternalSwap(data* other); + + private: + friend class ::google::protobuf::internal::AnyMetadata; + static ::absl::string_view FullMessageName() { + return "message.data"; + } + protected: + explicit data(::google::protobuf::Arena* arena); + data(::google::protobuf::Arena* arena, const data& from); + public: + + static const ClassData _class_data_; + const ::google::protobuf::Message::ClassData*GetClassData() const final; + + ::google::protobuf::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kSenderNameFieldNumber = 1, + }; + // string sender_name = 1; + void clear_sender_name() ; + const std::string& sender_name() const; + template + void set_sender_name(Arg_&& arg, Args_... args); + std::string* mutable_sender_name(); + PROTOBUF_NODISCARD std::string* release_sender_name(); + void set_allocated_sender_name(std::string* value); + + private: + const std::string& _internal_sender_name() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_sender_name( + const std::string& value); + std::string* _internal_mutable_sender_name(); + + public: + // @@protoc_insertion_point(class_scope:message.data) + private: + class _Internal; + + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable< + 0, 1, 0, + 32, 2> + _table_; + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + + inline explicit constexpr Impl_( + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena); + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena, const Impl_& from); + ::google::protobuf::internal::ArenaStringPtr sender_name_; + mutable ::google::protobuf::internal::CachedSize _cached_size_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_message_2eproto; +}; + +// =================================================================== + + + + +// =================================================================== + + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif // __GNUC__ +// ------------------------------------------------------------------- + +// data + +// string sender_name = 1; +inline void data::clear_sender_name() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.sender_name_.ClearToEmpty(); +} +inline const std::string& data::sender_name() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:message.data.sender_name) + return _internal_sender_name(); +} +template +inline PROTOBUF_ALWAYS_INLINE void data::set_sender_name(Arg_&& arg, + Args_... args) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.sender_name_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:message.data.sender_name) +} +inline std::string* data::mutable_sender_name() ABSL_ATTRIBUTE_LIFETIME_BOUND { + std::string* _s = _internal_mutable_sender_name(); + // @@protoc_insertion_point(field_mutable:message.data.sender_name) + return _s; +} +inline const std::string& data::_internal_sender_name() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.sender_name_.Get(); +} +inline void data::_internal_set_sender_name(const std::string& value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.sender_name_.Set(value, GetArena()); +} +inline std::string* data::_internal_mutable_sender_name() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + return _impl_.sender_name_.Mutable( GetArena()); +} +inline std::string* data::release_sender_name() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + // @@protoc_insertion_point(field_release:message.data.sender_name) + return _impl_.sender_name_.Release(); +} +inline void data::set_allocated_sender_name(std::string* value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.sender_name_.SetAllocated(value, GetArena()); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.sender_name_.IsDefault()) { + _impl_.sender_name_.Set("", GetArena()); + } + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:message.data.sender_name) +} + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif // __GNUC__ + +// @@protoc_insertion_point(namespace_scope) +} // namespace message + + +// @@protoc_insertion_point(global_scope) + +#include "google/protobuf/port_undef.inc" + +#endif // GOOGLE_PROTOBUF_INCLUDED_message_2eproto_2epb_2eh diff --git a/Jason/lab3/proto/message.proto b/Jason/lab3/proto/message.proto new file mode 100644 index 0000000..cca539f --- /dev/null +++ b/Jason/lab3/proto/message.proto @@ -0,0 +1,8 @@ +syntax = "proto3"; + +package message; + +// Define a simple message with a single string field +message data { + string sender_name = 1; +} \ No newline at end of file diff --git a/Jason/lab3/readme.md b/Jason/lab3/readme.md new file mode 100644 index 0000000..b65438a --- /dev/null +++ b/Jason/lab3/readme.md @@ -0,0 +1,4 @@ +1. nix-shell -p protobuf +2. cd jason/lab3 +3. nix build +4. run client_exe and server_exe found in result/bin \ No newline at end of file diff --git a/Jason/lab3/src/UDPSocket.cpp b/Jason/lab3/src/UDPSocket.cpp new file mode 100644 index 0000000..350a2a6 --- /dev/null +++ b/Jason/lab3/src/UDPSocket.cpp @@ -0,0 +1,70 @@ +#include "UDPSocket.hpp" +#include +#include +#include + +UDPSocket::UDPSocket() { + // Create the socket using IPv4 and UDP + sockfd = socket(AF_INET, SOCK_DGRAM, 0); + if (sockfd < 0) { + std::cerr << "Error creating socket\n"; + } + + // Initialize local and remote address structs + memset(&localAddr, 0, sizeof(localAddr)); + memset(&remoteAddr, 0, sizeof(remoteAddr)); +} + +UDPSocket::~UDPSocket() { + closeSocket(); +} + +bool UDPSocket::bindSocket(const std::string& ip, int port) { + localAddr.sin_family = AF_INET; + localAddr.sin_port = htons(port); + localAddr.sin_addr.s_addr = inet_addr(ip.c_str()); + + // Bind the socket to the specified IP and port + if (bind(sockfd, (struct sockaddr*)&localAddr, sizeof(localAddr)) < 0) { + std::cerr << "Error binding socket to " << ip << ":" << port << "\n"; + return false; + } + + return true; +} + +ssize_t UDPSocket::sendTo(const std::string& message, const std::string& ip, int port) { + remoteAddr.sin_family = AF_INET; + remoteAddr.sin_port = htons(port); + remoteAddr.sin_addr.s_addr = inet_addr(ip.c_str()); + + ssize_t bytesSent = sendto(sockfd, message.c_str(), message.length(), 0, + (struct sockaddr*)&remoteAddr, sizeof(remoteAddr)); + if (bytesSent < 0) { + std::cerr << "Error sending message\n"; + } + return bytesSent; +} + +ssize_t UDPSocket::receiveFrom(std::string& message, std::string& senderIp, int& senderPort) { + char buffer[1024]; + socklen_t addrLen = sizeof(remoteAddr); + ssize_t bytesReceived = recvfrom(sockfd, buffer, sizeof(buffer), 0, + (struct sockaddr*)&remoteAddr, &addrLen); + + if (bytesReceived > 0) { + message = std::string(buffer, bytesReceived); + senderIp = inet_ntoa(remoteAddr.sin_addr); + senderPort = ntohs(remoteAddr.sin_port); + } else { + std::cerr << "Error receiving message\n"; + } + + return bytesReceived; +} + +void UDPSocket::closeSocket() { + if (sockfd >= 0) { + close(sockfd); + } +} diff --git a/Jason/lab3/src/client.cpp b/Jason/lab3/src/client.cpp new file mode 100644 index 0000000..66171ee --- /dev/null +++ b/Jason/lab3/src/client.cpp @@ -0,0 +1,73 @@ +#include "client.hpp" +#include +#include // For memset + +#include "message.pb.h" + +/** + * @brief Class Client + * + * Set up socket + */ +Client::Client(const std::string& server_ip, uint16_t server_port) { + // Create socket + _sockfd = socket(AF_INET, SOCK_DGRAM, 0); + if (_sockfd < 0) { + std::cerr << "Failed to create socket" << std::endl; + exit(1); + } + + // Setup server address + memset(&_server_addr, 0, sizeof(_server_addr)); + _server_addr.sin_family = AF_INET; + _server_addr.sin_port = htons(server_port); + inet_pton(AF_INET, server_ip.c_str(), &_server_addr.sin_addr); +} + +Client::~Client() { + close(_sockfd); +} +/** + * @brief Class Client + * + * sends message to the server + */ +bool Client::SendMessage(const message::data& message) { + std::string serialized_message; + if (!message.SerializeToString(&serialized_message)) { + std::cerr << "Failed to serialize message" << std::endl; + return false; + } + + if (sendto(_sockfd, serialized_message.data(), serialized_message.size(), 0, + (struct sockaddr*)&_server_addr, sizeof(_server_addr)) < 0) { + std::cerr << "Failed to send message" << std::endl; + return false; + } + return true; +} +/** + * @brief Class Client + * + * sends response to the server + */ +bool Client::ReceiveMessage(message::data& message) { + char buffer[_BUFFER_SIZE]; + sockaddr_in from_addr; + socklen_t from_addr_len = sizeof(from_addr); + + ssize_t received_bytes = recvfrom(_sockfd, buffer, _BUFFER_SIZE, 0, + (struct sockaddr*)&from_addr, &from_addr_len); + if (received_bytes < 0) { + std::cerr << "Failed to receive message" << std::endl; + return false; + } + + if (!message.ParseFromArray(buffer, received_bytes)) { + std::cerr << "Failed to parse message" << std::endl; + return false; + } + + std::cout << "Received " << message.sender_name() << std::endl; + return true; +} \ No newline at end of file diff --git a/Jason/lab3/src/server.cpp b/Jason/lab3/src/server.cpp new file mode 100644 index 0000000..940558d --- /dev/null +++ b/Jason/lab3/src/server.cpp @@ -0,0 +1,80 @@ +#include "server.hpp" +#include +#include +#include // For memset + + +#include "message.pb.h" + +/** + * @brief Class Server + * + * Set up socket + */ +Server::Server(const std::string& server_ip, uint16_t server_port) { + _sock = socket(AF_INET, SOCK_DGRAM, 0); + if (_sock < 0) { + std::cerr << "Failed to create socket" << std::endl; + exit(1); + } + + // Setup server address + memset(&_server_addr, 0, sizeof(_server_addr)); + _server_addr.sin_family = AF_INET; + _server_addr.sin_port = htons(server_port); + inet_pton(AF_INET, server_ip.c_str(), &_server_addr.sin_addr); + + if (bind(_sock, (struct sockaddr*)&_server_addr, sizeof(_server_addr)) < 0) { + std::cerr << "Failed to bind socket" << std::endl; + exit(1); + } +} + +Server::~Server() { + close(_sock); +} + +/** + * @brief Class Server + * + * Sends response message to client + */ +bool Server::SendMessage(const message::data& message) { + + std::string serialized_message; + if (!message.SerializeToString(&serialized_message)) { + std::cerr << "Failed to serialize message" << std::endl; + return false; + } + + if (sendto(_sock, serialized_message.data(), serialized_message.size(), 0, + (struct sockaddr*)&_client_addr, sizeof(_client_addr)) < 0) { + std::cerr << "Failed to send message" << std:: endl; + } + return true; +} + +/** + * @brief Class Server + * + * Receives message from client + */ +bool Server::ReceiveMessage(message::data& message) { + char buffer[_BUFFER_SIZE]; + socklen_t _client_addr_len = sizeof(_client_addr); + + ssize_t received_bytes = recvfrom(_sock, buffer, _BUFFER_SIZE, 0, + (struct sockaddr*)&_client_addr, &_client_addr_len); + if (received_bytes < 0) { + std::cerr << "Failed to receive message" << std::endl; + return false; + } + + if (!message.ParseFromArray(buffer, received_bytes)) { + std::cerr << "Failed to parse message" << std::endl; + return false; + } + + std::cout << "Received " << message.sender_name() << std::endl; + return true; +} \ No newline at end of file