update stuffs
This commit is contained in:
120
shared.h
Normal file
120
shared.h
Normal file
@@ -0,0 +1,120 @@
|
||||
#pragma once
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#define CC_ADDRLEN (INET6_ADDRSTRLEN + 8) // [...:12345]
|
||||
|
||||
static int sockaddr2str(const struct sockaddr *sa, char *s, const size_t maxlen) {
|
||||
if (sa->sa_family == AF_INET) {
|
||||
const struct sockaddr_in *sin = (struct sockaddr_in *)sa;
|
||||
inet_ntop(AF_INET, &sin->sin_addr, s, maxlen);
|
||||
const size_t len = strnlen(s, maxlen);
|
||||
return len + snprintf(s + len, maxlen - len, ":%u", ntohs(sin->sin_port));
|
||||
}
|
||||
|
||||
if (sa->sa_family == AF_INET6) {
|
||||
const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
|
||||
s[0] = '[';
|
||||
inet_ntop(AF_INET6, &sin6->sin6_addr, s + 1, maxlen - 1);
|
||||
const size_t len = strnlen(s, maxlen);
|
||||
return len + snprintf(s + len, maxlen - len, "]:%u", ntohs(sin6->sin6_port));
|
||||
}
|
||||
|
||||
strncpy(s, "unknown", maxlen);
|
||||
return 7;
|
||||
}
|
||||
|
||||
#define MAX_MESSAGE_LENGTH 1024
|
||||
|
||||
#define streq(a, b) (strcmp((a), (b)) == 0)
|
||||
|
||||
#define exit_error(...) do { \
|
||||
fprintf(stderr, __VA_ARGS__); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} while (0)
|
||||
|
||||
#define exit_perror(s) do { \
|
||||
perror(s); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} while (0)
|
||||
|
||||
static int resolve_domain_to_ipv6(const char *hostname, struct in6_addr *server_addr) {
|
||||
struct addrinfo hints, *res;
|
||||
int found = 0;
|
||||
|
||||
memset(&hints, 0, sizeof hints);
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
if (getaddrinfo(hostname, NULL, &hints, &res) != 0) return 0;
|
||||
|
||||
for (struct addrinfo *p = res; p != NULL; p = p->ai_next) {
|
||||
if (p->ai_family == AF_INET6) {
|
||||
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
|
||||
memcpy(server_addr, &ipv6->sin6_addr, sizeof(struct in6_addr));
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
if (p->ai_family == AF_INET && !found) {
|
||||
struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr;
|
||||
memset(server_addr, 0, sizeof(struct in6_addr));
|
||||
server_addr->s6_addr[10] = 0xff;
|
||||
server_addr->s6_addr[11] = 0xff;
|
||||
memcpy(&server_addr->s6_addr[12], &(ipv4->sin_addr), 4);
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
|
||||
freeaddrinfo(res);
|
||||
return found;
|
||||
}
|
||||
|
||||
static int cc_client_parse_args_and_connect(int argc, char* argv[], struct sockaddr_in6* server_addr, int* server_fd, FILE** reader, FILE** writer) {
|
||||
struct in6_addr bind_addr = in6addr_any;
|
||||
int port = 5000;
|
||||
if (argc >= 2) {
|
||||
if (inet_pton(AF_INET6, argv[1], &bind_addr) != 1) {
|
||||
struct in_addr v4;
|
||||
if (inet_pton(AF_INET, argv[1], &v4) != 1) {
|
||||
if (!resolve_domain_to_ipv6(argv[1], &bind_addr)) {
|
||||
exit_error("invalid address or domain: %s\n", argv[1]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
memset(&bind_addr, 0, sizeof(bind_addr));
|
||||
bind_addr.s6_addr[10] = 0xff;
|
||||
bind_addr.s6_addr[11] = 0xff;
|
||||
memcpy(&bind_addr.s6_addr[12], &v4, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (argc >= 3) {
|
||||
port = atoi(argv[2]);
|
||||
if (port <= 0) exit_error("unknown argument: %s\n", argv[2]);
|
||||
}
|
||||
|
||||
*server_fd = socket(AF_INET6, SOCK_STREAM, 0);
|
||||
if (*server_fd < 0) exit_perror("socket");
|
||||
const int server_fd2 = dup(*server_fd);
|
||||
if (server_fd2 < 0) exit_perror("dup");
|
||||
|
||||
server_addr->sin6_family = AF_INET6;
|
||||
server_addr->sin6_addr = bind_addr;
|
||||
server_addr->sin6_port = htons(port);
|
||||
|
||||
int opt = 0;
|
||||
if (setsockopt(*server_fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)) < 0) {
|
||||
// i guess so bro
|
||||
}
|
||||
|
||||
if (connect(*server_fd, (struct sockaddr *)server_addr, sizeof(*server_addr)) < 0) exit_perror("connect");
|
||||
|
||||
if ((*reader = fdopen(*server_fd, "r")) == NULL) exit_perror("fdopen reader");
|
||||
if ((*writer = fdopen(server_fd2, "w")) == NULL) exit_perror("fdopen writer");
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user