summaryrefslogtreecommitdiff
path: root/src/session.cpp
blob: d18dbd664b557977baff82d143524dd0c7c85440 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include "session.hpp"
#include "log.hpp"
#include <cerrno>
#include <cstring>
#include <sys/socket.h>
#include <unistd.h>

CSession::CSession(Hyprutils::OS::CFileDescriptor sockfd)
	: m_sockfd(std::move(sockfd)) {
	if (!m_sockfd.isValid())
		throw std::runtime_error("Failed to create socket");
}

CSession::~CSession() {
	onDisconnect();
	m_sockfd.reset();
}

void CSession::onConnect() const {
	log(INFO, "Client connected");
}

void CSession::onDisconnect() const {
	log(INFO, "Client disconnected");
}

void CSession::onErrno(eEventType eventType) const {
	const auto err = strerror(errno);
	switch (eventType) {
	case READ:
		log(ERROR, "Error while reading: {}", err);
	case WRITE:
		log(ERROR, "Error while writing: {}", err);
	}
}

void CSession::onRecv(const SRecvData &data) const {
	log(INFO, "Received: {}", data.data, data.dataSize);
}

void CSession::onSend(const std::string &msg) const {
	log(INFO, "Sent: {}", msg);
}

void CSession::recvManager() {
	while (true) {
		CSession::SRecvData recvData = read();
		if (!recvData.good)
			break;
	}
}

CSession::SRecvData CSession::read() {
	SRecvData recvData;
	ssize_t	  dataSize = recv(m_sockfd.get(), recvData.data, recvData.dataSize, 0);
	if (dataSize < 0) {
		recvData.good = false;
		onErrno(READ);
	}
	if (dataSize == 0) {
		recvData.good = false;
		onDisconnect();
	}

	onRecv(recvData);
	return recvData;
}

CSession::SRecvData CSession::read(const std::string &msg) {
	write(eFormatType::STANDARD, "{}", msg, false);
	return read();
}

void CSession::run() {
	onConnect();
	registerSession();
	recvManager();
}

bool CSession::registerSession() {
	SRecvData recvData = read("Name: ");
	if (!recvData.good)
		return false;

	if (recvData.data[0] == '\n' || recvData.data[0] == ' ') {
		write("Name cannot be empty", eFormatType::ERROR);
		registerSession();
	}

	m_name = recvData.data;

	std::println("Client registered as: {}", m_name);

	return true;
}

bool CSession::isValid() const {
	if (!m_sockfd.isValid() || m_name.empty())
		return false;

	if (send(m_sockfd.get(), "", 0, MSG_NOSIGNAL) < 0)
		return false;

	return true;
}

template <typename... Args>
bool CSession::write(eFormatType type, std::format_string<Args...> fmt, Args &&...args) const {
	std::string msg = CFormatter::fmt(type, fmt, std::forward<Args>(args)...);

	if (send(m_sockfd.get(), msg.c_str(), msg.size(), 0) < 0) {
		onErrno(WRITE);
		return false;
	}
	onSend(msg);
	return true;
}

bool CSession::write(const std::string &msg, eFormatType type) const {
	return write(type, "{}", msg);
}

std::string CSession::getName() const {
	return m_name;
}