You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
netpong/sock.cpp

112 lines
3.2 KiB
C++

#include <cerrno>
#include <stdexcept>
#include "includes/sock.hpp"
#include "includes/exception_consts.hpp"
#include "includes/easysock.hpp"
/* Function to create socket. This function doesn't actually create a socket
(and isn't meant to be called directly). Instead, the client and server classes
extend this function, and create the appropriate sockets. */
void Sock::create_socket() {
dest = (struct sockaddr *)malloc(sizeof(struct sockaddr));
addrlen = sizeof(*dest);
}
/* Constructor - This function initializes the object attributes with the given
parameters. It throws an exception if an IPv4 address was given, but the type
given is IPv6 (or the other way around). */
Sock::Sock(int ip_ver, char protocol, const char* address, int port) {
/* Error checking */
if (ip_ver != 4 && ip_ver != 6) {
throw std::invalid_argument("Invalid IP address type");
}
if (port < 1024 || port > 65535) {
throw std::invalid_argument("Invalid port");
}
if (protocol != 'T' && protocol != 'U') {
throw std::invalid_argument("Invalid protocol");
}
this->ip_ver = ip_ver;
this->protocol = protocol;
this->port = port;
this->address = std::string(address);
/* Check to see if the given IP address matches the given ip_ver */
if ((check_ip_ver(address) != 6 && ip_ver == 6) || (check_ip_ver(address) != 4 && ip_ver == 4)) {
throw std::invalid_argument("Invalid IP address for given type.");
}
}
/* This method sends the given data, through the given socket. Client and server
classes extend this method, by calling it with different parameters.
This function needs more testing for TCP, as it focuses on UDP right now. */
void Sock::sendAll(std::string to_send, int dest_sock) {
int str_length = to_send.length();
int num_bytes_sent = 0; /* Number of bytes sent in one call to send */
int total_bytes_sent = 0; /* Total number of bytes sent */
/* For UDP sockets */
if (this->protocol == 'U') {
sendto(this->sock_fd, to_send.data(), str_length, 0, dest, addrlen);
}
/* For TCP sockets */
else {
while (total_bytes_sent < str_length) {
num_bytes_sent = send(dest_sock, to_send.substr(total_bytes_sent).data(), str_length - total_bytes_sent, 0);
if (num_bytes_sent < 0) {
throw errno * -1;
}
total_bytes_sent += num_bytes_sent;
}
}
return;
}
/* Receives data from given socket into a string, and returns that string. For TCP, the
'recv' method is called until all the data has been read. For UDP, the 'recvfrom'
method is only called once.
This function also needs more testing for TCP. */
std::string Sock::recvAll(int from_sock) {
int num_bytes_received;
std::string string = std::string();
char* buffer = (char *)malloc(100);
bool has_been_read = false;
if (this->protocol == 'U') {
recvfrom(this->sock_fd, buffer, 100, 0, dest, &addrlen);
string.append(std::string(buffer));
}
/* For TCP sockets */
else {
while ((num_bytes_received = recv(from_sock, buffer, 100, 0)) != 0) {
if ((errno == EAGAIN || errno == EWOULDBLOCK)) {
if (has_been_read) {
break;
} else {
continue;
}
}
if (num_bytes_received < 0) {
throw errno * -1;
}
string.append(std::string(buffer));
has_been_read = true;
}
}
return string;
}
int Sock::getSockFD() {
return sock_fd;
}