Removed submodules
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
#include <arpa/inet.h>
|
||||
#include <assert.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "client.h"
|
||||
|
||||
#define BUFFER_MAX_SIZE 4096
|
||||
|
||||
/* Given a struct with server information, return a dynamically allocated
|
||||
string of the IP address in dotted decimal or colon hexadecimal notation.
|
||||
Consult Chapter 4, as well as /usr/include/netdb.h and
|
||||
/usr/include/arpa/inet.h as needed. Use inet_ntop() to get the formatted
|
||||
string based on the address's ai_addr field.
|
||||
*/
|
||||
char *
|
||||
addr_string (struct addrinfo *server)
|
||||
{
|
||||
// Return safely in case server is NULL:
|
||||
if (server == NULL)
|
||||
return strdup ("no address information");
|
||||
|
||||
size_t addrlen
|
||||
= server->ai_family == AF_INET6 ? INET6_ADDRSTRLEN : INET_ADDRSTRLEN;
|
||||
char *buffer = calloc (addrlen, sizeof (char));
|
||||
|
||||
void *addr;
|
||||
if (server->ai_family == AF_INET)
|
||||
addr = &((struct sockaddr_in *)server->ai_addr)->sin_addr;
|
||||
else
|
||||
addr = &((struct sockaddr_in6 *)server->ai_addr)->sin6_addr;
|
||||
|
||||
inet_ntop (server->ai_family, addr, buffer, addrlen);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/* Given the server address info, return a dynamically allocated string with
|
||||
its transport-layer protocol, IP version, and IP address. For instance,
|
||||
querying jmu.edu over TCP/IPv4 should return:
|
||||
"TCP IPv4 134.126.10.50"
|
||||
Use addr_string() to get the formatted address string, concatenate it to
|
||||
the string to return, then free the result from addr_string(). If the
|
||||
passed server parameter is NULL, use strdup() to return a dynamically
|
||||
allocated copy of "no address information".
|
||||
|
||||
NOTE: When distinguishing TCP and UDP, you should be checking the
|
||||
server->ai_socktype field, not server->ai_protocol. The test cases do not
|
||||
set the server->ai_protocol, which is sometimes not used in practice.
|
||||
*/
|
||||
char *
|
||||
serv_string (struct addrinfo *server)
|
||||
{
|
||||
// Return safely in case server is NULL:
|
||||
if (server == NULL)
|
||||
return strdup ("no address information");
|
||||
|
||||
size_t addrlen
|
||||
= server->ai_family == AF_INET6 ? INET6_ADDRSTRLEN : INET_ADDRSTRLEN;
|
||||
|
||||
char *buffer = calloc (10 + addrlen, sizeof (char));
|
||||
|
||||
char *proto = server->ai_socktype == SOCK_STREAM ? "TCP" : "UDP";
|
||||
char *ipver = server->ai_family == AF_INET ? "IPv4" : "IPv6";
|
||||
|
||||
char *addr = addr_string (server);
|
||||
|
||||
snprintf (buffer, 10 + addrlen, "%s %s %s", proto, ipver, addr);
|
||||
|
||||
free (addr);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/* Given a hostname string, use getaddrinfo() to query DNS for the specified
|
||||
protocol parameters. Boolean values indicate whether or not to use IPv6
|
||||
(as opposed to IPv4) or TCP (as opposed to UDP). For this lab, the protocol
|
||||
will only be "http", though it could be others in a more complete
|
||||
implementation. Return the pointer to the linked list of server results.
|
||||
*/
|
||||
struct addrinfo *
|
||||
get_server_list (const char *hostname, const char *proto, bool tcp, bool ipv6)
|
||||
{
|
||||
struct addrinfo hints = { 0 };
|
||||
struct addrinfo *server_list = NULL;
|
||||
|
||||
hints.ai_family = ipv6 ? AF_INET6 : AF_INET;
|
||||
|
||||
if (tcp)
|
||||
{
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_protocol = IPPROTO_TCP;
|
||||
}
|
||||
else
|
||||
{
|
||||
hints.ai_socktype = SOCK_DGRAM;
|
||||
hints.ai_protocol = IPPROTO_UDP;
|
||||
}
|
||||
|
||||
getaddrinfo (hostname, proto, &hints, &server_list);
|
||||
|
||||
return server_list;
|
||||
}
|
||||
Reference in New Issue
Block a user