Newer
Older
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
#include "tcpstream.hpp"
#include <stdexcept>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
TcpStream::TcpStream(SockAddr _remote)
: remote{_remote}, sockfd{0}
{ }
TcpStream::TcpStream(IpAddr remoteAddress, uint16_t port)
: TcpStream{SockAddr{remoteAddress, port}}
{ }
TcpStream::TcpStream(const std::string &remoteAddress, uint16_t port)
: TcpStream{SockAddr{remoteAddress, port}}
{ }
TcpStream::TcpStream(const std::string &remoteAddressPort)
: TcpStream{SockAddr{remoteAddressPort}}
{ }
TcpStream::~TcpStream()
{
close();
}
void TcpStream::connect()
{
if (sockfd != 0)
throw std::runtime_error("Can't call connect on open socket");
int af;
socklen_t sock_len;
if (remote.address.type == IpAddr::Type::V4)
{
af = AF_INET;
sock_len = sizeof(sockaddr_in);
}
else if (remote.address.type == IpAddr::Type::V6)
{
af = AF_INET6;
sock_len = sizeof(sockaddr_in6);
}
else
{
throw std::runtime_error("Can't connect to IpAddr::Type::Undef");
}
// Create the socket and get the socket file descriptor
sockfd = socket(af, SOCK_STREAM, 0);
if (sockfd <= 0)
{
throw std::runtime_error("Creating TCP Socket failed");
}
if (::connect(sockfd, &remote.raw_sockaddr.generic, sock_len) != 0)
{
close();
throw std::runtime_error("Connecting TCP Socket failed");
}
}
void TcpStream::close()
{
if (sockfd != 0)
{
::close(sockfd);
}
sockfd = 0;
}
ssize_t TcpStream::send(const void *data, size_t len)
{
if (sockfd == 0)
throw std::runtime_error("Can't write to closed socket");
ssize_t bytes_sent = ::write(sockfd, data, len);
if (bytes_sent < 0)
{
close();
throw std::runtime_error("Error while writing to socket");
}
return bytes_sent;
}
void TcpStream::sendAll(const void *data, size_t len)
{
if (sockfd == 0)
throw std::runtime_error("Can't write to closed socket");
size_t bytesSentTotal = 0;
while (bytesSentTotal < len)
{
ssize_t bytesSent = ::write(sockfd, (uint8_t*)data + bytesSentTotal, len-bytesSentTotal);
if (bytesSent < 0)
{
close();
throw std::runtime_error("Error while writing to socket");
}
bytesSentTotal += bytesSent;
}
}
ssize_t TcpStream::read(void *data, size_t len)
{
if (sockfd == 0)
throw std::runtime_error("Can't read from closed socket");
ssize_t bytes_read = ::read(sockfd, data, len);
if (bytes_read < 0)
{
close();
throw std::runtime_error("Error while reading from socket");
}
return bytes_read;
}
ssize_t TcpStream::readAll(void *data, size_t len)
{
if (sockfd == 0)
throw std::runtime_error("Can't read from closed socket");
size_t bytesReadTotal = 0;
while (true)
{
ssize_t bytesRead = ::read(sockfd, (uint8_t*)data + bytesReadTotal, len-bytesReadTotal);
if (bytesRead == 0) break;
if (bytesRead < 0)
{
close();
throw std::runtime_error("Error while reading from socket");
}
bytesReadTotal += bytesRead;
}
return bytesReadTotal;
}