diff --git a/easysock.cpp b/easysock.cpp index fc9ffe8..f4557ee 100644 --- a/easysock.cpp +++ b/easysock.cpp @@ -1,4 +1,10 @@ #include "includes/easysock.hpp" +#include +#include +#include +#include +#include + #ifndef _WIN_32 const int INVALID_SOCKET = -1; #endif @@ -12,7 +18,6 @@ int sock_init(void) { return 0; #endif } - int sock_quit(void) { #ifdef _WIN32 return WSACleanup(); @@ -21,8 +26,11 @@ int sock_quit(void) { #endif } - -int create_socket(int network, char transport) { +/* Function to create a socket - Accepts IP version(4 or 6), protocol +type (PROTO_TCP or PROTO_UDP) and a flag to indicate whether the socket +should be set in blocking mode or not. This flag is ONLY FOR TCP. It does +nothing if the protocol is UDP.*/ +int create_socket(int network, char transport, bool is_blocking) { sock_init(); int domain; int type; @@ -35,15 +43,25 @@ int create_socket(int network, char transport) { return -1; } - if (transport == 'T') { + if (transport == ES_TCP) { type = SOCK_STREAM; - } else if (transport == 'U') { + } else if (transport == ES_UDP) { type = SOCK_DGRAM; } else { return -1; } int newSock = socket(domain,type,0); + + /* Set REUSEADDR flag, allowing program to be run twice */ + int set_opt = 1; + setsockopt(newSock, SOL_SOCKET, SO_REUSEADDR, (char *)&set_opt, sizeof(set_opt)); + + if (is_blocking && transport == ES_TCP) { + int flags = fcntl(newSock, F_GETFL); + flags |= O_NONBLOCK; + fcntl(newSock,F_SETFL,flags); + } return newSock; } @@ -72,8 +90,8 @@ int create_addr(int network, char* address, int port,struct sockaddr* dest) { } -int create_local (int network, char transport, char* address, int port,struct sockaddr* addr_struct) { - int socket = create_socket(network,transport); +int create_local (int network, char transport, char* address, int port,struct sockaddr* addr_struct, bool is_blocking) { + int socket = create_socket(network,transport, is_blocking); if (socket < 0) { return (-1 * errno); } @@ -98,7 +116,7 @@ int create_local (int network, char transport, char* address, int port,struct so return socket; } -int create_remote (int network,char transport,char* address,int port,struct sockaddr* remote_addr_struct) { +int create_remote (int network,char transport,char* address,int port,struct sockaddr* remote_addr_struct, bool is_blocking) { struct addrinfo hints; /* Used to tell getaddrinfo what kind of address we want */ struct addrinfo* results; /* Used by getaddrinfo to store the addresses */ @@ -124,7 +142,7 @@ int create_remote (int network,char transport,char* address,int port,struct sock create_addr(network,address,port,remote_addr_struct); } - int socket = create_socket(network,transport); + int socket = create_socket(network,transport, is_blocking); if (socket < 0) { return (-1 * errno); } @@ -197,9 +215,9 @@ int inet_to_int(int af_type) { } int char_to_socktype(char transport) { - if (transport == 'T') { + if (transport == ES_TCP) { return SOCK_STREAM; - } else if (transport == 'U') { + } else if (transport == ES_UDP) { return SOCK_DGRAM; } else { return -250; diff --git a/includes/easysock.hpp b/includes/easysock.hpp index bc267ea..c4db9c3 100644 --- a/includes/easysock.hpp +++ b/includes/easysock.hpp @@ -12,24 +12,26 @@ #include #endif -#include -#include -#include -#include - #ifndef _WIN_32 typedef int SOCKET; #endif +/* Constants that can be used in place of characters, when specifying +the transport layer protocol */ +const char ES_TCP 'T'; +const char ES_UDP 'U'; + /* This function takes: a layer 3 - network layer - integer, which must be '4' for IPv4 -and 6 for IPv6; and +and 6 for IPv6; a layer 4 - transport layer - character, which must be 'T' for -TCP or 'U' for UDP. +TCP or 'U' for UDP; and +a bool that indicates whether the socket should be blocking or non-blocking. + It returns the created socket, or -1 if the socket creation failed.*/ -SOCKET create_socket(int network, char transport); +SOCKET create_socket(int network, char transport, bool is_blocking = false); /* This function fills in the sockaddr struct 'dest' based on the given information. @@ -51,7 +53,7 @@ same as above. It prints the error returned by 'bind' if something went wrong, and returns ( -1 * errno ).*/ -SOCKET create_local (int network, char transport, char* address, int port,struct sockaddr* addr_struct); +SOCKET create_local (int network, char transport, char* address, int port,struct sockaddr* addr_struct, bool is_blocking = false); /* This function utilizes the same functions as 'create_local' but _connects_ to the @@ -60,7 +62,7 @@ as above. This function needs an empty 'sockaddr *' structure passed to it, whic If something goes wrong, this function returns with ( -1 * errno ). */ -SOCKET create_remote (int network,char transport,char* address,int port,struct sockaddr* remote_addr_struct); +SOCKET create_remote (int network,char transport,char* address,int port,struct sockaddr* remote_addr_struct, bool is_blocking = false); /* check_ip_ver - This function checks if the given string is an IPv4 address (returns 4), IPv6 address (returns 6) or neither (returns -1). */