Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ cmake_install.cmake
install_manifest.txt
compile_commands.json
CTestTestfile.cmake
cmake-build-debug/
build

### LaTeX ###
Expand Down
17 changes: 17 additions & 0 deletions tcp/client/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
cmake_minimum_required(VERSION 2.8)
project(calculator)
set(CMAKE_CXX_STANDARD 17)

file(GLOB SOURCE_FILES "src/*.cpp")

add_executable(calculator ${SOURCE_FILES} src/CalculatorApp.cpp include/CalculatorApp.hpp src/CalcuatorServerDriver.cpp include/CalcuatorServerDriver.hpp src/main.cpp include/requests.hpp include/ConcurrentQueue.hpp src/requests.cpp)

target_include_directories(calculator PRIVATE include)

find_package(Threads REQUIRED)
if(THREADS_HAVE_PTHREAD_ARG)
target_compile_options(calculator PUBLIC "-pthread")
endif()
if(CMAKE_THREAD_LIBS_INIT)
target_link_libraries(calculator "${CMAKE_THREAD_LIBS_INIT}")
endif()
50 changes: 50 additions & 0 deletions tcp/client/include/CalcuatorServerDriver.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#include <utility>

#pragma once

#include <string>
#include <queue>
#include <thread>
#include <mutex>
#include "requests.hpp"
#include "socketUtils.hpp"
#include "ConcurrentQueue.hpp"

class CalcuatorServerDriver {
public:
CalcuatorServerDriver(std::string host, uint16_t port) : m_host(std::move(host)), m_port(port) {}

~CalcuatorServerDriver();

void connect();

bool hasResult();

CalculatorResponse getResult();

void factorial(uint32_t id, int64_t arg);

void sqrt(uint32_t id, int64_t arg);

CalculatorResponse plus(uint32_t id, int64_t arg1, int64_t arg2);

CalculatorResponse minus(uint32_t id, int64_t arg1, int64_t arg2);

CalculatorResponse multiply(uint32_t id, int64_t arg1, int64_t arg2);

CalculatorResponse divide(uint32_t id, int64_t arg1, int64_t arg2);

private:
void sendRequest(CalculatorRequest const &request);

CalculatorResponse getResponse();

void readingThreadTask();

ConcurrentQueue<CalculatorResponse> m_longResults;
ConcurrentQueue<CalculatorResponse> m_instantResults;
int m_socket = 0;
std::string m_host;
uint16_t m_port;
std::thread m_readingThread;
};
33 changes: 33 additions & 0 deletions tcp/client/include/CalculatorApp.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#pragma once

#include <iostream>
#include <sstream>
#include <iterator>
#include "CalcuatorServerDriver.hpp"
#include "socketUtils.hpp"

class CalculatorApp {
public:
CalculatorApp(std::string const &host, uint16_t port) : m_driver(host, port) {}

void start();

private:
void printPrompt(uint32_t computationId);

void processInput(std::string &line);

template<typename T>
void printResult(uint32_t id, T const &value) {
std::cout << "Out [" << id << "]: " << value << std::endl;
}

void printEntryMessage();

void printLine(std::string const &line = "");

uint32_t m_currentComputation = 0;
CalcuatorServerDriver m_driver;

void printResponse(const CalculatorResponse &response);
};
33 changes: 33 additions & 0 deletions tcp/client/include/ConcurrentQueue.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#pragma once

#include <mutex>
#include <queue>

template<typename T>
class ConcurrentQueue {
public:
void push(T const &response) {
m_queueMutex.lock();
m_resultsQueue.push(response);
m_queueMutex.unlock();
}

T pop() {
m_queueMutex.lock();
auto result = m_resultsQueue.front();
m_resultsQueue.pop();
m_queueMutex.unlock();
return result;
}

bool empty() {
m_queueMutex.lock();
bool isEmpty = m_resultsQueue.empty();
m_queueMutex.unlock();
return isEmpty;
}

private:
std::mutex m_queueMutex;
std::queue<T> m_resultsQueue;
};
47 changes: 47 additions & 0 deletions tcp/client/include/requests.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#pragma once

#include <cstdint>
#include <string>

#pragma pack(push, 1)
struct CalculatorResponse {
uint8_t errorCode;
uint8_t operationType;
uint32_t computationId;
int64_t result;
};
#pragma pack(pop)

enum OperationType {
FAST = 1,
SLOW
};

enum ErrorCode {
OK = 0,
WAIT_FOR_RESULT,
OVERFLOW,
DIV_BY_ZERO,
FACT_OF_NEGATIVE,
SQRT_OF_NEGATIVE,
};

std::string errorCodeToString(uint8_t code);

#pragma pack(push, 1)
struct CalculatorRequest {
uint8_t type;
uint32_t computationId;
int64_t firstOperand;
int64_t secondOperand;
};
#pragma pack(pop)

enum RequestType {
PLUS = 1,
MINUS,
MULT,
DIV,
SQRT,
FACT
};
36 changes: 36 additions & 0 deletions tcp/client/include/socketUtils.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#pragma once

#include <iostream>
#include <stdlib.h>

#include <netdb.h>
#include <netinet/in.h>
#include <unistd.h>
#include <strings.h>

void writeToSocket(int socketDescriptor, const void *buffer, size_t size);

void readFromSocket(int socketDescriptor, uint8_t *buffer, size_t size);

void printError(const std::string &s);

void error(const std::string &s);

void error(const std::string &type, const std::string &s);

int connectToServer(std::string const &hostname, uint16_t port);

template<typename T>
void writeObject(int socketDescriptor, const T &object) {
writeToSocket(socketDescriptor, (uint8_t const *) &object, sizeof(T));
}

template<typename T>
T readObject(int socketDescriptor) {
T object;
readFromSocket(socketDescriptor, (uint8_t *) &object, sizeof(T));

return object;
}

std::string read_until_zero(int *ptr, char *buffer, size_t buffer_size);
75 changes: 75 additions & 0 deletions tcp/client/src/CalcuatorServerDriver.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
//
// Created by karvozavr on 16/02/19.
//

#include "CalcuatorServerDriver.hpp"

CalcuatorServerDriver::~CalcuatorServerDriver() {
shutdown(m_socket, SHUT_RDWR);
close(m_socket);
}

void CalcuatorServerDriver::connect() {
m_socket = connectToServer(m_host, m_port);
m_readingThread = std::thread(&CalcuatorServerDriver::readingThreadTask, this);
}

void CalcuatorServerDriver::readingThreadTask() {
while (true) {
auto response = readObject<CalculatorResponse>(m_socket);
if (response.errorCode != WAIT_FOR_RESULT) {
if (response.operationType == SLOW) {
m_longResults.push(response);
} else if (response.operationType == FAST) {
m_instantResults.push(response);
}
}
}
}

bool CalcuatorServerDriver::hasResult() {
return !m_longResults.empty();
}

CalculatorResponse CalcuatorServerDriver::getResult() {
return m_longResults.pop();
}

void CalcuatorServerDriver::factorial(uint32_t id, int64_t arg) {
sendRequest({FACT, id, arg, 0});
}

void CalcuatorServerDriver::sqrt(uint32_t id, int64_t arg) {
sendRequest({SQRT, id, arg, 0});
}

CalculatorResponse CalcuatorServerDriver::plus(uint32_t id, int64_t arg1, int64_t arg2) {
sendRequest({PLUS, id, arg1, arg2});
return getResponse();
}

CalculatorResponse CalcuatorServerDriver::minus(uint32_t id, int64_t arg1, int64_t arg2) {
sendRequest({MINUS, id, arg1, arg2});
return getResponse();
}

CalculatorResponse CalcuatorServerDriver::multiply(uint32_t id, int64_t arg1, int64_t arg2) {
sendRequest({MULT, id, arg1, arg2});
return getResponse();
}

CalculatorResponse CalcuatorServerDriver::divide(uint32_t id, int64_t arg1, int64_t arg2) {
sendRequest({DIV, id, arg1, arg2});
return getResponse();
}

void CalcuatorServerDriver::sendRequest(CalculatorRequest const &request) {
writeObject(m_socket, request);
}

CalculatorResponse CalcuatorServerDriver::getResponse() {
while (m_instantResults.empty()) {}
return m_instantResults.pop();
}


Loading