initial hashmap code
This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
|
BasedOnStyle: Google
|
||||||
|
ColumnLimit: 120
|
||||||
UseTab: Always
|
UseTab: Always
|
||||||
IndentWidth: 8
|
IndentWidth: 8
|
||||||
TabWidth: 8
|
TabWidth: 8
|
||||||
|
|||||||
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
@@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"clangd.path": "/usr/bin/clangd",
|
"clangd.path": "/usr/bin/clangd",
|
||||||
"clangd.arguments": [ "--header-insertion=never" ]
|
"clangd.arguments": [ "--header-insertion=never" ],
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
# cws
|
# cws
|
||||||
A simple Web Server written in C (learning purposes), it works only on Linux systems
|
A simple Web Server written in C (learning purposes), it works only on Linux systems.
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
- [meson](https://mesonbuild.com/index.html)
|
- [meson](https://mesonbuild.com/index.html)
|
||||||
|
|||||||
@@ -2,16 +2,16 @@
|
|||||||
#define __CLIENT_H__
|
#define __CLIENT_H__
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
int test_client_connection(const char *hostname, const char *port);
|
int test_client_connection(const char *hostname, const char *service);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
16
include/hashmap.h
Normal file
16
include/hashmap.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#ifndef __HASHMAP_C__
|
||||||
|
#define __HASHMAP_C__
|
||||||
|
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#define HASHMAP_MAX_ITEMS 10000
|
||||||
|
|
||||||
|
struct hashmap {
|
||||||
|
int sockfd;
|
||||||
|
struct sockaddr_storage sas;
|
||||||
|
};
|
||||||
|
|
||||||
|
int hash(int sockfd);
|
||||||
|
void hm_insert(struct hashmap *map, int sockfd, struct sockaddr_storage *sas);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -2,18 +2,17 @@
|
|||||||
#define __SERVER_H__
|
#define __SERVER_H__
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/epoll.h>
|
#include <sys/epoll.h>
|
||||||
#include <fcntl.h>
|
#include <sys/socket.h>
|
||||||
#include <errno.h>
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#define PORT 3030
|
#define PORT 3030
|
||||||
#define BACKLOG 10
|
#define BACKLOG 10
|
||||||
@@ -24,7 +23,9 @@ int start_server(const char *hostname, const char *service);
|
|||||||
void setup_hints(struct addrinfo *hints, size_t len, const char *hostname);
|
void setup_hints(struct addrinfo *hints, size_t len, const char *hostname);
|
||||||
void handle_clients(int sockfd);
|
void handle_clients(int sockfd);
|
||||||
void epoll_ctl_add(int epfd, int sockfd, uint32_t events);
|
void epoll_ctl_add(int epfd, int sockfd, uint32_t events);
|
||||||
|
void epoll_ctl_del(int epfd, int sockfd);
|
||||||
void setnonblocking(int sockfd);
|
void setnonblocking(int sockfd);
|
||||||
void handle_new_client(int sockfd);
|
int handle_new_client(int sockfd, struct sockaddr_storage *their_sa, socklen_t *theirsa_size);
|
||||||
|
void print_client_ip(struct sockaddr_in *sin);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -4,12 +4,11 @@
|
|||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
// print every IPs of a hostname
|
// print every IPs of a hostname
|
||||||
void print_ips(const char *hostname, const char *port);
|
void print_ips(const char *hostname, const char *port);
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ It is similar to `poll()` but more efficient when dealing with lots of fds. The
|
|||||||
int epoll_create1(int flags);
|
int epoll_create1(int flags);
|
||||||
```
|
```
|
||||||
|
|
||||||
Just pass 0 for the `flags`, it is an improved version of the `epoll_create()`. It creates a new epoll instance nad returns the fd of that instance.
|
Just pass 0 for the `flags`, it is an improved version of the `epoll_create()`. It creates a new epoll instance and returns the fd of that instance.
|
||||||
|
|
||||||
```c
|
```c
|
||||||
#include <sys/epoll.h>
|
#include <sys/epoll.h>
|
||||||
|
|||||||
19
notes/hash-table.md
Normal file
19
notes/hash-table.md
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# Hash Table
|
||||||
|
Well, the moment has come. I never made a Hash Map algorithm, but in this scenario I have to save both fd and sockaddr (I could make a simply linked list, but it's a way to learn new things).
|
||||||
|
|
||||||
|
Let's start with a little bit of theory.
|
||||||
|
|
||||||
|
A *Hash Table* is a data structure also called **dictionary** or **map**. It maps *keys* to *values* thanks to a **hash function** that computes and *index* (**hash code**) into an array of **buckets**.
|
||||||
|
|
||||||
|
One problem could be the *hash collision* where the hash function computes the same index for different values. A fix could be the **chaining** method, where for the same hash code you can make a linked list and append the index. Then the lookup function will go through the list and find the key.
|
||||||
|
|
||||||
|
In a Hash Map you can insert, delete and lookup (simply search).
|
||||||
|
|
||||||
|
### Hash function
|
||||||
|
The easiest way... don't judge me.
|
||||||
|
|
||||||
|
- Integer keys:
|
||||||
|
$$ hash(\text{key}) = \text{key} \mod \text{table\_dim} $$
|
||||||
|
|
||||||
|
- String keys:
|
||||||
|
$$ hash(key) = \sum_{i=0}^{len(key) - 1} ascii\_value(key[i]) * prime\_number$$
|
||||||
11
notes/http-request.md
Normal file
11
notes/http-request.md
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# HTTP Request
|
||||||
|
This is an example of a basic HTTP request made from the browser:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
GET / HTTP/1.1
|
||||||
|
User-Agent: Mozilla/4.0 (compatible; MSIE5.01; Windows NT)
|
||||||
|
Host: www.tutorialspoint.com
|
||||||
|
Accept-Language: en-us
|
||||||
|
Accept-Encoding: gzip, deflate
|
||||||
|
Connection: Keep-Alive
|
||||||
|
```
|
||||||
20
src/client.c
20
src/client.c
@@ -1,9 +1,10 @@
|
|||||||
// THIS FILE IS ONLY A TEST FOR THE BASIC STUFF
|
// THIS FILE IS ONLY A TEST FOR THE BASIC STUFF
|
||||||
|
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
|
|
||||||
#include "colors.h"
|
#include "colors.h"
|
||||||
|
|
||||||
int test_client_connection(const char *hostname, const char *port) {
|
int test_client_connection(const char *hostname, const char *service) {
|
||||||
struct addrinfo hints;
|
struct addrinfo hints;
|
||||||
struct addrinfo *res;
|
struct addrinfo *res;
|
||||||
|
|
||||||
@@ -11,10 +12,9 @@ int test_client_connection(const char *hostname, const char *port) {
|
|||||||
hints.ai_socktype = SOCK_STREAM;
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
hints.ai_family = AF_INET;
|
hints.ai_family = AF_INET;
|
||||||
|
|
||||||
int status = getaddrinfo(hostname, port, &hints, &res);
|
int status = getaddrinfo(hostname, service, &hints, &res);
|
||||||
if (status != 0) {
|
if (status != 0) {
|
||||||
fprintf(stderr, RED BOLD "[client] getaddrinfo(): %s\n" RESET,
|
fprintf(stderr, RED BOLD "[client] getaddrinfo(): %s\n" RESET, gai_strerror(status));
|
||||||
gai_strerror(status));
|
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -22,15 +22,17 @@ int test_client_connection(const char *hostname, const char *port) {
|
|||||||
|
|
||||||
status = connect(sockfd, res->ai_addr, res->ai_addrlen);
|
status = connect(sockfd, res->ai_addr, res->ai_addrlen);
|
||||||
if (status != 0) {
|
if (status != 0) {
|
||||||
fprintf(stderr, RED BOLD "[client] connect(): %s\n" RESET,
|
fprintf(stderr, RED BOLD "[client] connect(): %s\n" RESET, strerror(errno));
|
||||||
gai_strerror(status));
|
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
char buf[4096];
|
char buf[4096];
|
||||||
int bytes_read = recv(sockfd, buf, 4096, 0);
|
int bytes_read = recv(sockfd, buf, sizeof buf, 0);
|
||||||
fprintf(stdout, BLUE "[client] Read %d bytes: %s\n" RESET, bytes_read,
|
fprintf(stdout, BLUE "[client] Read %d bytes: %s\n" RESET, bytes_read, buf);
|
||||||
buf);
|
|
||||||
|
fprintf(stdout, "[client] => ");
|
||||||
|
fgets(buf, sizeof buf, stdin);
|
||||||
|
send(sockfd, buf, strlen(buf), 0);
|
||||||
|
|
||||||
freeaddrinfo(res);
|
freeaddrinfo(res);
|
||||||
close(sockfd);
|
close(sockfd);
|
||||||
|
|||||||
9
src/hashmap.c
Normal file
9
src/hashmap.c
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#include "hashmap.h"
|
||||||
|
|
||||||
|
int hash(int sockfd) { return sockfd % HASHMAP_MAX_ITEMS; }
|
||||||
|
|
||||||
|
void hm_insert(struct hashmap *map, int sockfd, struct sockaddr_storage *sas) {
|
||||||
|
int index = hash(sockfd);
|
||||||
|
map[index].sockfd = sockfd;
|
||||||
|
map[index].sas = *sas;
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
|
||||||
#include "colors.h"
|
#include "colors.h"
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
fprintf(stdout, BOLD GREEN "[client] Running cws...\n" RESET);
|
fprintf(stdout, BOLD GREEN "[client] Running cws...\n" RESET);
|
||||||
|
|
||||||
int ret = test_client_connection("localhost", "3030");
|
int ret = test_client_connection(argv[1], argv[2]);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
fprintf(stderr, BOLD RED "Unable to start client\n");
|
fprintf(stderr, BOLD RED "Unable to start client\n");
|
||||||
}
|
}
|
||||||
|
|||||||
127
src/server.c
127
src/server.c
@@ -1,4 +1,5 @@
|
|||||||
#include "server.h"
|
#include "server.h"
|
||||||
|
|
||||||
#include "colors.h"
|
#include "colors.h"
|
||||||
|
|
||||||
int start_server(const char *hostname, const char *service) {
|
int start_server(const char *hostname, const char *service) {
|
||||||
@@ -9,25 +10,22 @@ int start_server(const char *hostname, const char *service) {
|
|||||||
|
|
||||||
int status = getaddrinfo(hostname, service, &hints, &res);
|
int status = getaddrinfo(hostname, service, &hints, &res);
|
||||||
if (status != 0) {
|
if (status != 0) {
|
||||||
fprintf(stderr,
|
fprintf(stderr, RED BOLD "[server] getaddrinfo() error: %s\n" RESET, gai_strerror(status));
|
||||||
RED BOLD "[server] getaddrinfo() error: %s\n" RESET,
|
|
||||||
gai_strerror(status));
|
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
int sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
|
int sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
|
||||||
|
fprintf(stdout, YELLOW "[server] sockfd: %d\n" RESET, sockfd);
|
||||||
|
|
||||||
status = bind(sockfd, res->ai_addr, res->ai_addrlen);
|
status = bind(sockfd, res->ai_addr, res->ai_addrlen);
|
||||||
if (status != 0) {
|
if (status != 0) {
|
||||||
fprintf(stderr, RED BOLD "[server] bind(): %s\n" RESET,
|
fprintf(stderr, RED BOLD "[server] bind(): %s\n" RESET, gai_strerror(status));
|
||||||
gai_strerror(status));
|
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
status = listen(sockfd, BACKLOG);
|
status = listen(sockfd, BACKLOG);
|
||||||
if (status != 0) {
|
if (status != 0) {
|
||||||
fprintf(stderr, RED BOLD "[server] listen(): %s\n" RESET,
|
fprintf(stderr, RED BOLD "[server] listen(): %s\n" RESET, gai_strerror(status));
|
||||||
gai_strerror(status));
|
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,55 +54,56 @@ void handle_clients(int sockfd) {
|
|||||||
setnonblocking(sockfd);
|
setnonblocking(sockfd);
|
||||||
epoll_ctl_add(epfd, sockfd, EPOLLIN | EPOLLET);
|
epoll_ctl_add(epfd, sockfd, EPOLLIN | EPOLLET);
|
||||||
|
|
||||||
struct epoll_event *revents =
|
struct epoll_event *revents = malloc(EPOLL_MAXEVENTS * sizeof(struct epoll_event));
|
||||||
malloc(EPOLL_MAXEVENTS * sizeof(struct epoll_event));
|
|
||||||
int nfds;
|
int nfds;
|
||||||
|
|
||||||
char *msg = "Hello there!";
|
char *msg = "Hello there!";
|
||||||
size_t msg_len = strlen(msg);
|
size_t msg_len = strlen(msg);
|
||||||
|
char data[4096];
|
||||||
|
int client_fd;
|
||||||
|
int run = 1;
|
||||||
|
|
||||||
for (;;) {
|
while (run) {
|
||||||
nfds =
|
nfds = epoll_wait(epfd, revents, EPOLL_MAXEVENTS, EPOLL_TIMEOUT);
|
||||||
epoll_wait(epfd, revents, EPOLL_MAXEVENTS, EPOLL_TIMEOUT);
|
|
||||||
|
|
||||||
for (int i = 0; i < nfds; ++i) {
|
for (int i = 0; i < nfds; ++i) {
|
||||||
if (revents[i].data.fd == sockfd) {
|
if (revents[i].data.fd == sockfd) {
|
||||||
int client_fd =
|
// new client
|
||||||
accept(sockfd, (struct sockaddr *)&their_sa,
|
client_fd = handle_new_client(sockfd, &their_sa, &theirsa_size);
|
||||||
&theirsa_size);
|
setnonblocking(client_fd);
|
||||||
|
epoll_ctl_add(epfd, client_fd, EPOLLIN);
|
||||||
|
|
||||||
if (client_fd == -1) {
|
print_client_ip((struct sockaddr_in *)&their_sa);
|
||||||
if (errno != EWOULDBLOCK) {
|
|
||||||
fprintf(stderr,
|
int bytes_sent = send(client_fd, msg, msg_len, 0);
|
||||||
RED BOLD "[server] "
|
fprintf(stdout, BLUE "[server] Sent %d bytes\n" RESET, bytes_sent);
|
||||||
"accept(): "
|
} else {
|
||||||
"%s\n" RESET,
|
// incoming data
|
||||||
strerror(errno));
|
client_fd = revents[i].data.fd;
|
||||||
}
|
// fprintf(stdout, "[%d] EPOLLIN\n", client_fd);
|
||||||
|
int bytes_read = recv(client_fd, data, sizeof data, 0);
|
||||||
|
|
||||||
|
if (bytes_read == 0) {
|
||||||
|
// client disconnect
|
||||||
|
fprintf(stdout, BLUE "[server] Client disconnection\n");
|
||||||
|
epoll_ctl_del(epfd, client_fd);
|
||||||
|
close(client_fd);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
setnonblocking(client_fd);
|
data[strlen(data) - 1] = '\0';
|
||||||
|
fprintf(stdout, "[server] Bytes read (%d): %s\n", bytes_read, data);
|
||||||
|
if (strcmp(data, "stop") == 0) {
|
||||||
|
fprintf(stdout, GREEN BOLD "[server] Stopping...\n" RESET);
|
||||||
|
run = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct sockaddr_in *client =
|
free(revents);
|
||||||
(struct sockaddr_in *)&their_sa;
|
close(epfd);
|
||||||
char client_ip[INET_ADDRSTRLEN];
|
|
||||||
inet_ntop(AF_INET, &client->sin_addr, client_ip,
|
|
||||||
INET_ADDRSTRLEN);
|
|
||||||
fprintf(stdout,
|
|
||||||
BLUE "[server] Incoming "
|
|
||||||
"client, ip: %s\n" RESET,
|
|
||||||
client_ip);
|
|
||||||
|
|
||||||
int bytes_sent =
|
|
||||||
send(client_fd, msg, msg_len, 0);
|
|
||||||
fprintf(stdout,
|
|
||||||
BLUE "[server] Sent %d bytes\n" RESET,
|
|
||||||
bytes_sent);
|
|
||||||
close(client_fd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void epoll_ctl_add(int epfd, int sockfd, uint32_t events) {
|
void epoll_ctl_add(int epfd, int sockfd, uint32_t events) {
|
||||||
@@ -113,8 +112,15 @@ void epoll_ctl_add(int epfd, int sockfd, uint32_t events) {
|
|||||||
event.data.fd = sockfd;
|
event.data.fd = sockfd;
|
||||||
int status = epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &event);
|
int status = epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &event);
|
||||||
if (status != 0) {
|
if (status != 0) {
|
||||||
fprintf(stderr, RED BOLD "[server] epoll_ctl(): %s\n" RESET,
|
fprintf(stderr, RED BOLD "[server] epoll_ctl_add(): %s\n" RESET, strerror(errno));
|
||||||
gai_strerror(status));
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void epoll_ctl_del(int epfd, int sockfd) {
|
||||||
|
int status = epoll_ctl(epfd, EPOLL_CTL_DEL, sockfd, NULL);
|
||||||
|
if (status != 0) {
|
||||||
|
fprintf(stdout, RED BOLD "[server] epoll_ctl_del(): %s\n" RESET, strerror(errno));
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -122,12 +128,35 @@ void epoll_ctl_add(int epfd, int sockfd, uint32_t events) {
|
|||||||
void setnonblocking(int sockfd) {
|
void setnonblocking(int sockfd) {
|
||||||
int status = fcntl(sockfd, F_SETFL, O_NONBLOCK);
|
int status = fcntl(sockfd, F_SETFL, O_NONBLOCK);
|
||||||
if (status == -1) {
|
if (status == -1) {
|
||||||
fprintf(stderr, RED BOLD "[server] fcntl(): %s\n" RESET,
|
fprintf(stderr, RED BOLD "[server] fcntl(): %s\n" RESET, gai_strerror(status));
|
||||||
gai_strerror(status));
|
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void handle_new_client(int sockfd) {
|
int handle_new_client(int sockfd, struct sockaddr_storage *their_sa, socklen_t *theirsa_size) {
|
||||||
// handle here new clients
|
int client_fd = accept(sockfd, (struct sockaddr *)their_sa, theirsa_size);
|
||||||
|
|
||||||
|
if (client_fd == -1) {
|
||||||
|
if (errno != EWOULDBLOCK) {
|
||||||
|
fprintf(stderr,
|
||||||
|
RED BOLD
|
||||||
|
"[server] "
|
||||||
|
"accept(): "
|
||||||
|
"%s\n" RESET,
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return client_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_client_ip(struct sockaddr_in *sin) {
|
||||||
|
char ip[INET_ADDRSTRLEN];
|
||||||
|
inet_ntop(AF_INET, &sin->sin_addr, ip, INET_ADDRSTRLEN);
|
||||||
|
fprintf(stdout,
|
||||||
|
BLUE
|
||||||
|
"[server] Incoming "
|
||||||
|
"client, IP: %s\n" RESET,
|
||||||
|
ip);
|
||||||
}
|
}
|
||||||
16
src/utils.c
16
src/utils.c
@@ -1,4 +1,5 @@
|
|||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
#include "colors.h"
|
#include "colors.h"
|
||||||
|
|
||||||
void print_ips(const char *hostname, const char *port) {
|
void print_ips(const char *hostname, const char *port) {
|
||||||
@@ -12,8 +13,7 @@ void print_ips(const char *hostname, const char *port) {
|
|||||||
|
|
||||||
int status = getaddrinfo(hostname, port, &ai, &res);
|
int status = getaddrinfo(hostname, port, &ai, &res);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
fprintf(stderr, RED "getaddrinfo(): %s\n" RESET,
|
fprintf(stderr, RED "getaddrinfo(): %s\n" RESET, gai_strerror(status));
|
||||||
gai_strerror(status));
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -22,16 +22,12 @@ void print_ips(const char *hostname, const char *port) {
|
|||||||
|
|
||||||
for (struct addrinfo *p = res; p != NULL; p = p->ai_next) {
|
for (struct addrinfo *p = res; p != NULL; p = p->ai_next) {
|
||||||
if (p->ai_family == AF_INET) {
|
if (p->ai_family == AF_INET) {
|
||||||
struct sockaddr_in *sin =
|
struct sockaddr_in *sin = (struct sockaddr_in *)p->ai_addr;
|
||||||
(struct sockaddr_in *)p->ai_addr;
|
inet_ntop(AF_INET, &sin->sin_addr, ipv4, INET_ADDRSTRLEN);
|
||||||
inet_ntop(AF_INET, &sin->sin_addr, ipv4,
|
|
||||||
INET_ADDRSTRLEN);
|
|
||||||
fprintf(stdout, BLUE "%s\n" RESET, ipv4);
|
fprintf(stdout, BLUE "%s\n" RESET, ipv4);
|
||||||
} else if (p->ai_family == AF_INET6) {
|
} else if (p->ai_family == AF_INET6) {
|
||||||
struct sockaddr_in6 *sin6 =
|
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)p->ai_addr;
|
||||||
(struct sockaddr_in6 *)p->ai_addr;
|
inet_ntop(AF_INET6, &sin6->sin6_addr, ipv6, INET6_ADDRSTRLEN);
|
||||||
inet_ntop(AF_INET6, &sin6->sin6_addr, ipv6,
|
|
||||||
INET6_ADDRSTRLEN);
|
|
||||||
fprintf(stdout, BLUE "%s\n" RESET, ipv6);
|
fprintf(stdout, BLUE "%s\n" RESET, ipv6);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user