diff --git a/sock.cpp b/sock.cpp index a2e230f..9ca0ef8 100644 --- a/sock.cpp +++ b/sock.cpp @@ -4,10 +4,19 @@ #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) { @@ -29,33 +38,70 @@ Sock::Sock(int ip_ver, char protocol, const char* address, int port) { 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."); } - - try { - create_socket(); - } catch (int e) { - throw; - } } -void Sock::sendAll(std::string to_send) { +/* 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 */ - while (total_bytes_sent < str_length) { - num_bytes_sent = send(this->getSockFD(), to_send.substr(total_bytes_sent).data(), str_length - total_bytes_sent, 0); - total_bytes_sent += num_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; } -std::string Sock::recvAll() { +/* 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); - while (recv(this->getSockFD(), buffer, 100, 0) != 0) { + 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; }