First commit
This commit is contained in:
		
							
								
								
									
										169
									
								
								easysock.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								easysock.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,169 @@ | ||||
| #include "easysock.h" | ||||
|  | ||||
| int create_socket(int network, char transport) {   | ||||
| 	int domain; | ||||
| 	int type; | ||||
|  | ||||
| 	if (network == 4) { | ||||
| 		domain = AF_INET; | ||||
| 	} else if (network == 6) { | ||||
| 		domain = AF_INET6; | ||||
| 	} else { | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	if (transport == 'T') { | ||||
| 		type = SOCK_STREAM; | ||||
| 	} else if (transport == 'U') { | ||||
| 		type = SOCK_DGRAM; | ||||
| 	} else { | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	int newSock = socket(domain,type,0); | ||||
| 	return newSock; | ||||
| } | ||||
|  | ||||
|  | ||||
| void create_addr(int network, char* address, int port,struct sockaddr* dest) { | ||||
| 	if (network == 4) { | ||||
| 		struct sockaddr_in listen_address; | ||||
| 		 | ||||
| 		listen_address.sin_family = AF_INET; | ||||
| 		listen_address.sin_port = htons(port); | ||||
| 		inet_pton(AF_INET,address,&listen_address.sin_addr); | ||||
| 		memcpy(dest,&listen_address,sizeof(listen_address)); | ||||
| 		return;	 | ||||
|  | ||||
| 	} else if (network == 6) { | ||||
| 		struct sockaddr_in6 listen_ipv6; | ||||
| 		listen_ipv6.sin6_family = AF_INET6; | ||||
| 		listen_ipv6.sin6_port = htons(port); | ||||
| 		inet_pton(AF_INET6,address,&listen_ipv6.sin6_addr); | ||||
| 		memcpy(dest,&listen_ipv6,sizeof(listen_ipv6)); | ||||
| 		return; | ||||
|  | ||||
| 	} else { | ||||
| 		exit(202); | ||||
| 	} | ||||
| 		 | ||||
| } | ||||
|  | ||||
| int create_local (int network, char transport, char* address, int port,struct sockaddr* addr_struct) { | ||||
| 	int socket = create_socket(network,transport); | ||||
| 	if (socket < 0) { | ||||
| 		exit(errno); | ||||
| 	} | ||||
| 	create_addr(network,address,port,addr_struct); | ||||
| 	int addrlen; | ||||
| 	if (network == 4) { | ||||
| 		addrlen = sizeof(struct sockaddr_in); | ||||
| 	} else if (network == 6) { | ||||
| 		addrlen = sizeof(struct sockaddr_in6); | ||||
| 	} else { | ||||
| 		exit(207); | ||||
| 	} | ||||
|  | ||||
| 	/* The value of addrlen should be the size of the 'sockaddr'.  | ||||
| 	This should be set to the size of 'sockaddr_in' for IPv4, and 'sockaddr_in6' for IPv6. | ||||
| 	See https://stackoverflow.com/questions/73707162/socket-bind-failed-with-invalid-argument-error-for-program-running-on-macos */ | ||||
|  | ||||
| 	int i = bind (socket,addr_struct,(socklen_t)addrlen); | ||||
| 	if (i < 0) { | ||||
| 		exit(errno); | ||||
| 	} | ||||
| 	return socket; | ||||
| } | ||||
|  | ||||
| int create_remote (int network,char transport,char* address,int port,struct sockaddr* remote_addr_struct) { | ||||
|  | ||||
| 	struct addrinfo hints;  /* Used to tell getaddrinfo what kind of address we want */ | ||||
| 	struct addrinfo* results; /* Used by getaddrinfo to store the addresses */ | ||||
|  | ||||
|  | ||||
| 	if (check_ip_ver(address) < 0) { /* If the address is a domain name */ | ||||
| 		int err_code; | ||||
| 		char* port_str = malloc(10 * sizeof(char)); | ||||
|  | ||||
| 		sprintf(port_str,"%d",port); /* getaddrinfo expects a string for its port */ | ||||
|  | ||||
|  | ||||
| 		memset(&hints,'\0',sizeof(hints)); | ||||
| 		hints.ai_socktype = char_to_socktype(transport); | ||||
|  | ||||
| 		err_code = getaddrinfo(address,port_str,&hints,&results); | ||||
| 		if (err_code != 0) { | ||||
| 			exit(err_code); | ||||
| 		} | ||||
| 		remote_addr_struct = results->ai_addr; | ||||
| 		network = inet_to_int(results->ai_family); | ||||
| 	} else { | ||||
| 	        create_addr(network,address,port,remote_addr_struct); | ||||
| 	} | ||||
|  | ||||
| 	int socket = create_socket(network,transport); | ||||
| 	if (socket < 0) { | ||||
|                 exit(errno); | ||||
|         } | ||||
|  | ||||
|        	int addrlen; | ||||
| 	if (network == 4) { | ||||
| 		addrlen = sizeof(struct sockaddr_in); | ||||
| 	} else if (network == 6) { | ||||
| 		addrlen = sizeof(struct sockaddr_in6); | ||||
| 	} else { | ||||
| 		exit(207); | ||||
| 	} | ||||
|  | ||||
| 	/* The value of addrlen should be the size of the 'sockaddr'.  | ||||
| 	This should be set to the size of 'sockaddr_in' for IPv4, and 'sockaddr_in6' for IPv6. | ||||
| 	See https://stackoverflow.com/questions/73707162/socket-bind-failed-with-invalid-argument-error-for-program-running-on-macos */ | ||||
|  | ||||
|         int i = connect(socket,remote_addr_struct,(socklen_t)addrlen); | ||||
| 	if (i < 0) { | ||||
| 		exit(errno); | ||||
| 	} | ||||
|         return socket; | ||||
| } | ||||
|  | ||||
|  | ||||
| int check_ip_ver(char* address) { | ||||
| 	char buffer[16]; /* 16 chars - 128 bits - is enough to hold an ipv6 address */ | ||||
| 	if (inet_pton(AF_INET,address,buffer) == 1) { | ||||
| 		return 4; | ||||
| 	} else if (inet_pton(AF_INET6,address,buffer) == 1) { | ||||
| 		return 6; | ||||
| 	} else { | ||||
| 		return -1; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| int int_to_inet(int network) { | ||||
| 	if (network == 4) { | ||||
| 		return AF_INET; | ||||
| 	} else if (network == 6) { | ||||
| 		return AF_INET6; | ||||
| 	} else { | ||||
| 		exit(207); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| int inet_to_int(int af_type) { | ||||
| 	if (af_type == AF_INET) { | ||||
| 		return 4; | ||||
| 	} else if (af_type == AF_INET6) { | ||||
| 		return 6; | ||||
| 	} else { | ||||
| 		exit(207); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| int char_to_socktype(char transport) { | ||||
| 	if (transport == 'T') { | ||||
| 		return SOCK_STREAM; | ||||
| 	} else if (transport == 'U') { | ||||
| 		return SOCK_DGRAM; | ||||
| 	} else { | ||||
| 		exit(250); | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										75
									
								
								easysock.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								easysock.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,75 @@ | ||||
| #ifndef EASYSOCK_H_ | ||||
| #define EASYSOCK_H_ | ||||
|  | ||||
| #include <string.h> | ||||
| #include <sys/types.h> | ||||
| #include <sys/socket.h> | ||||
| #include <netdb.h> | ||||
| #include <arpa/inet.h> | ||||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| #include <errno.h> | ||||
|  | ||||
|  | ||||
| /* This function takes: | ||||
| a layer 3 - network layer - integer, which must be '4' for IPv4 | ||||
| and 6 for IPv6; and | ||||
| a layer 4 - transport layer - character, which must be 'T' for | ||||
| TCP or 'U' for UDP.  | ||||
|  | ||||
| It returns the created socket, or -1 if the socket creation failed.*/ | ||||
|  | ||||
| int create_socket(int network, char transport); | ||||
|  | ||||
|  | ||||
| /* This function fills in the sockaddr struct 'dest' based on the given information. | ||||
| 'network' is an integer that contains '4' for IPv4 or '6' for IPv6; | ||||
| 'address' is the address that is filled into the struct; | ||||
| port is self-explanatory; | ||||
| and dest is a pointer to the sockaddr struct that will be filled in.  | ||||
|  | ||||
| The function exits with error code 202 if the network parameter contained neither '4' | ||||
| nor '6'. */ | ||||
|  | ||||
| void create_addr(int network, char* address, int port,struct sockaddr* dest); | ||||
|  | ||||
|  | ||||
|  | ||||
| /* This function utilizes the above two functions; it creates the socket and | ||||
| _binds_ the addresses. It is used for local sockets (server sockets). Parameters are | ||||
| same as above.  | ||||
|  | ||||
| It prints the error returned by 'bind' if something went wrong, and exits with errno.*/ | ||||
|  | ||||
| int create_local (int network, char transport, char* address, int port,struct sockaddr* addr_struct); | ||||
|  | ||||
|  | ||||
| /* This function utilizes the same functions as 'create_local' but _connects_ to the | ||||
| requested address. It is used for remote sockets (client sockets). The paramters are same | ||||
| as above. This function needs an empty 'sockaddr *' structure passed to it, which it will fill. | ||||
|  | ||||
| It prints the error returned by 'connect' if something went wrong, and exits with errno.*/ | ||||
|  | ||||
| int create_remote (int network,char transport,char* address,int port,struct sockaddr* remote_addr_struct); | ||||
|  | ||||
| /* check_ip_ver - This function checks if the given string is an IPv4 address (returns 4),  | ||||
| IPv6 address (returns 6) or neither (returns -1). */ | ||||
|  | ||||
| int check_ip_ver(char* address); | ||||
|  | ||||
| /* int_to_inet - Takes an int value (4 for IPv4, 6 for IPv6) and returns AF_INET or | ||||
| AF_INET6 respectively. */ | ||||
|  | ||||
| int int_to_inet(int network); | ||||
|  | ||||
| /* char_to_socktype - Takes a character that represents a transport-layer protocol | ||||
| (currently only supports 'T' for TCP or 'U' for UDP - exits with error code 250 if  | ||||
| the given characters is neither of these) and return the appropriate SOCKTYPE value. */ | ||||
|  | ||||
| int char_to_socktype(char transport); | ||||
|  | ||||
| /* inet_to_int - Takes an int value that corresponds to AF_INET or AF_INET6, | ||||
| and returns the appropriate int value. */ | ||||
| int inet_to_int(int af_type); | ||||
|  | ||||
| #endif | ||||
		Reference in New Issue
	
	Block a user