-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathclient.cpp
More file actions
108 lines (91 loc) · 3.05 KB
/
Copy pathclient.cpp
File metadata and controls
108 lines (91 loc) · 3.05 KB
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
#include <cstdio>
#include <cstring>
#include <cerrno>
#include <unistd.h>
#include <stdexcept>
#include <sys/socket.h>
#include <iostream>
#include "../include/client.h"
#include "../include/common.h"
Client::Client(int fileDescriptor) {
_sockfd.set(fileDescriptor);
setConnected(false);
}
bool Client::operator==(const Client & other) const {
if ((this->_sockfd.get() == other._sockfd.get()) &&
(this->_ip == other._ip) ) {
return true;
}
return false;
}
void Client::startListen() {
setConnected(true);
_receiveThread = new std::thread(&Client::receiveTask, this);
}
void Client::send(const char *msg, size_t msgSize) const {
const size_t numBytesSent = ::send(_sockfd.get(), (char *)msg, msgSize, 0);
const bool sendFailed = (numBytesSent < 0);
if (sendFailed) {
throw std::runtime_error(strerror(errno));
}
const bool notAllBytesWereSent = (numBytesSent < msgSize);
if (notAllBytesWereSent) {
char errorMsg[100];
sprintf(errorMsg, "Only %lu bytes out of %lu was sent to client", numBytesSent, msgSize);
throw std::runtime_error(errorMsg);
}
}
/*
* Receive client packets, and notify user
*/
void Client::receiveTask() {
while(isConnected()) {
const fd_wait::Result waitResult = fd_wait::waitFor(_sockfd);
if (waitResult == fd_wait::Result::FAILURE) {
throw std::runtime_error(strerror(errno));
} else if (waitResult == fd_wait::Result::TIMEOUT) {
continue;
}
char receivedMessage[MAX_PACKET_SIZE];
const size_t numOfBytesReceived = recv(_sockfd.get(), receivedMessage, MAX_PACKET_SIZE, 0);
if(numOfBytesReceived < 1) {
const bool clientClosedConnection = (numOfBytesReceived == 0);
std::string disconnectionMessage;
if (clientClosedConnection) {
disconnectionMessage = "Client closed connection";
} else {
disconnectionMessage = strerror(errno);
}
setConnected(false);
publishEvent(ClientEvent::DISCONNECTED, disconnectionMessage);
return;
} else {
publishEvent(ClientEvent::INCOMING_MSG, receivedMessage);
}
}
}
void Client::publishEvent(ClientEvent clientEvent, const std::string &msg) {
_eventHandlerCallback(*this, clientEvent, msg);
}
void Client::print() const {
const std::string connected = isConnected() ? "True" : "False";
std::cout << "-----------------\n" <<
"IP address: " << getIp() << std::endl <<
"Connected?: " << connected << std::endl <<
"Socket FD: " << _sockfd.get() << std::endl;
}
void Client::terminateReceiveThread() {
setConnected(false);
if (_receiveThread) {
_receiveThread->join();
delete _receiveThread;
_receiveThread = nullptr;
}
}
void Client::close() {
terminateReceiveThread();
const bool closeFailed = (::close(_sockfd.get()) == -1);
if (closeFailed) {
throw std::runtime_error(strerror(errno));
}
}