diff --git a/ping/.gitignore b/ping/.gitignore new file mode 100644 index 00000000..7c63a771 --- /dev/null +++ b/ping/.gitignore @@ -0,0 +1 @@ +ft_ping diff --git a/ping/Makefile b/ping/Makefile new file mode 100644 index 00000000..e6031de4 --- /dev/null +++ b/ping/Makefile @@ -0,0 +1,67 @@ +# **************************************************************************** # +# # +# ::: :::::::: # +# Makefile :+: :+: :+: # +# +:+ +:+ +:+ # +# By: wescande +#+ +:+ +#+ # +# +#+#+#+#+#+ +#+ # +# Created: 2016/08/29 21:32:58 by wescande #+# #+# # +# Updated: 2017/10/08 14:36:33 by jhalford ### ########.fr # +# # +# **************************************************************************** # + +SHELL := bash + +NAME = ft_ping + +CC = gcc +RM = rm -rf 2>&- +W_FLAGS = -Wall -Wextra -Werror +D_FLAGS = -D _GNU_SOURCE +FLAGS = $(W_FLAGS) $(D_FLAGS) + +LEN_NAME = `printf "%s" $(NAME) |wc -c` +DELTA = $$(echo "$$(tput cols)-31-$(LEN_NAME)"|bc) + +SRC_DIR = ./ +INC_DIR = ./ +OBJ_DIR = objs/ + +SRC_BASE = \ +ping.c\ +create_client.c\ +cksum.c\ +rs.c\ +epoch.c\ +cliopts.c\ +error.c\ + +SRCS = $(addprefix $(SRC_DIR), $(SRC_BASE)) +OBJS = $(addprefix $(OBJ_DIR), $(SRC_BASE:.c=.o)) +NB = $(words $(SRC_BASE)) +INDEX = 0 + +all : + @make -j $(NAME) + +$(NAME): $(OBJ_DIR) $(OBJS) $(CLIENT_OBJ) + $(CC) $(OBJS) -o $@ -I $(INC_DIR) $(CLIENT_OBJ) $(FLAGS) -lm + # sudo setcap cap_net_raw+ep $@ 2>&- + +$(OBJ_DIR) : + @mkdir -p $(OBJ_DIR) + +$(OBJ_DIR)%.o : $(SRC_DIR)%.c | $(OBJ_DIR) + $(CC) $(FLAGS) $(OBJ_FLAG) -MMD -c $< -o $@ -I $(INC_DIR) + +clean: + $(RM) $(OBJ_DIR) + +re: fclean all + +fclean: clean + $(RM) $(NAME) + +.PHONY : fclean clean re + +-include $(OBJS:.o=.d) diff --git a/ping/cksum.c b/ping/cksum.c new file mode 100644 index 00000000..e4da4227 --- /dev/null +++ b/ping/cksum.c @@ -0,0 +1,31 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* cksum.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: jhalford +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2017/10/08 12:45:43 by jhalford #+# #+# */ +/* Updated: 2017/10/08 12:48:41 by jhalford ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "ping.h" + +unsigned short cksum(void *b, int len) +{ + unsigned short *buf; + unsigned int sum; + + buf = b; + sum = 0; + while (len > 1) + { + sum += *((unsigned short*)buf++); + len -= 2; + } + if (len == 1) + sum += *(unsigned char*)buf; + sum = (sum >> 16) + (sum & 0xFFFF); + return (~(sum + (sum >> 16))); +} diff --git a/ping/cliopts.c b/ping/cliopts.c new file mode 100644 index 00000000..5a7bd001 --- /dev/null +++ b/ping/cliopts.c @@ -0,0 +1,132 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* cliopts_get.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: jhalford +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2017/03/14 20:04:04 by jhalford #+# #+# */ +/* Updated: 2017/04/02 20:45:11 by jhalford ### ########.fr */ +/* */ +/* ************************************************************************** */ + +/* +** void *data must be a structure starting with `int flag` +** to do polymorphism with t_data_template ! +*/ + +#include "cliopts.h" + +t_cliopts *cliopts_getmap_long(t_cliopts opt_map[], char *arg) +{ + int i; + + i = -1; + while (opt_map[++i].c) + if (!strcmp(opt_map[i].str, arg)) + return (&opt_map[i]); + return (NULL); +} + +t_cliopts *cliopts_getmap_short(t_cliopts opt_map[], char arg) +{ + int i; + + i = -1; + while (opt_map[++i].c) + if (opt_map[i].c == arg) + return (&opt_map[i]); + return (NULL); +} + +static char *check_required(char ***av, char *arg) +{ + char *ret; + + if (!av || !*av) + return (NULL); + if (!arg || !*arg || !*(arg + 1)) + return (*++(*av)); + ret = arg + 1; + return (ret); +} + +static int cliopts_parse_short( + char ***av, t_cliopts opt_map[], void *data) +{ + t_cliopts *map; + char *arg; + int i; + char *tmp; + + arg = **av + 1; + i = -1; + while (arg[++i] && !(tmp = NULL)) + { + if (!(map = cliopts_getmap_short(opt_map, arg[i]))) + return (ERR_SET(E_CO_INV, arg[i])); + ((t_data_template*)data)->flag |= map->flag_on; + ((t_data_template*)data)->flag &= ~map->flag_off; + if (map->get) + { + if (map->arg_required && !(tmp = check_required(av, arg + i))) + return (ERR_SET(E_CO_MISS, *arg)); + tmp = tmp ? tmp : **av; + if ((map->get)(tmp, data)) + return (ERR_SET(E_CO_MISS, *arg)); + if (map->arg_required) + break ; + } + } + return (++(*av) ? 0 : 0); +} + +static int cliopts_parse_long( + char ***av, t_cliopts opt_map[], void *data) +{ + t_cliopts *map; + char *arg; + char *tmp; + + arg = **av + 2; + tmp = NULL; + if (!(map = cliopts_getmap_long(opt_map, arg))) + return (ERR_SET(E_CO_INVL, arg)); + ((t_data_template*)data)->flag |= map->flag_on; + ((t_data_template*)data)->flag &= ~map->flag_off; + if (map->get) + { + if (map->arg_required && !(tmp = check_required(av, NULL))) + return (ERR_SET(E_CO_MISS, *arg)); + if ((map->get)(tmp, data)) + return (ERR_SET(E_CO_MISSL, arg)); + } + ++(*av); + return (0); +} + +int cliopts_get(char **av, t_cliopts opt_map[], void *data) +{ + if (!av) + return (1); + av++; + while (av && *av) + { + if (strcmp(*av, "-") == 0 || (strcmp(*av, "--") == 0 && av++)) + break ; + else if ((*av)[0] == '-' && (*av)[1] == '-') + { + if (cliopts_parse_long(&av, opt_map, data)) + return (1); + } + else if ((*av)[0] == '-') + { + if (cliopts_parse_short(&av, opt_map, data)) + return (1); + } + else + break ; + } + ((t_data_template*)data)->av_data = av; + return (0); +} diff --git a/ping/cliopts.h b/ping/cliopts.h new file mode 100644 index 00000000..cb12f929 --- /dev/null +++ b/ping/cliopts.h @@ -0,0 +1,40 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* cliopts.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: jhalford +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2017/03/14 20:22:56 by jhalford #+# #+# */ +/* Updated: 2017/10/07 18:04:53 by jhalford ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#pragma once + +# include "error.h" +# include + +typedef struct s_cliopts t_cliopts; +typedef struct s_data_template t_data_template; +typedef long long t_flag; + +struct s_cliopts +{ + char c; + char *str; + t_flag flag_on; + t_flag flag_off; + int (*get)(); // (char *arg, void *data) + int arg_required:1; +}; + +struct s_data_template +{ + t_flag flag; + char **av_data; +}; + +int cliopts_get(char **av, t_cliopts opt_map[], void *data); +t_cliopts *cliopts_getmap_long(t_cliopts opt_map[], char *arg); +t_cliopts *cliopts_getmap_short(t_cliopts opt_map[], char arg); diff --git a/ping/create_client.c b/ping/create_client.c new file mode 100644 index 00000000..ccc63429 --- /dev/null +++ b/ping/create_client.c @@ -0,0 +1,59 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* create_client.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: jhalford +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2017/10/07 17:59:28 by jhalford #+# #+# */ +/* Updated: 2017/10/08 13:33:51 by jhalford ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "ping.h" + +int create_client(char *addr, int port, char *protoname) +{ + int sock; + struct protoent *proto; + struct sockaddr_in sin; + + if (!(proto = getprotobyname(protoname))) + return (-1); + sock = socket(PF_INET, SOCK_STREAM, proto->p_proto); + sin.sin_family = AF_INET; + sin.sin_port = htons(port); + sin.sin_addr.s_addr = inet_addr(addr); + if (connect(sock, (const struct sockaddr *)&sin, sizeof(sin)) < 0) + return (-1); + return (sock); +} + +void listener(int domain, int sock, int proto, + void (*handler)(void *buf, int bytes, struct sockaddr *addr)) +{ + int sd; + struct sockaddr addr; + unsigned char buf[1024]; + int bytes; + socklen_t len; + + len = sizeof(addr); + sd = socket(domain, sock, proto); + if (sd < 0) + { + perror("listener socket"); + exit(0); + } + while (1) + { + bzero(buf, sizeof(buf)); + bytes = recvfrom(sd, buf, sizeof(buf), 0, + &addr, &len); + if (bytes > 0 && handler) + handler(buf, bytes, &addr); + else + perror("recvfrom"); + } + exit(0); +} diff --git a/ping/epoch.c b/ping/epoch.c new file mode 100644 index 00000000..42a7df27 --- /dev/null +++ b/ping/epoch.c @@ -0,0 +1,31 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* epoch.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: jhalford +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2017/10/07 17:58:42 by jhalford #+# #+# */ +/* Updated: 2017/10/08 13:15:50 by jhalford ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "ping.h" + +uint64_t epoch_micro(void) +{ + struct timeval tv; + + if (gettimeofday(&tv, NULL)) + return (0); + return (tv.tv_sec * 1000000 + tv.tv_usec); +} + +double time_milli(void) +{ + struct timeval tv; + + if (gettimeofday(&tv, NULL)) + return (0); + return ((double)(tv.tv_sec * 1000. + (double)tv.tv_usec / 1000.)); +} diff --git a/ping/error.c b/ping/error.c new file mode 100644 index 00000000..cbc459dc --- /dev/null +++ b/ping/error.c @@ -0,0 +1,68 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* error.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: jhalford +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2017/03/14 16:47:00 by jhalford #+# #+# */ +/* Updated: 2017/03/25 01:53:25 by jhalford ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "error.h" + +char g_error_msglist[E_MAX][ERRMSG_MAX_SIZE] = +{ + "unknown error 0", + "invalid option -%c", + "invalid option --%s", + "option '%c' awaits argument(s): please don't combine", + "option '%c': missing argument", + "option '%s': missing argument", + "%s: no such file or directory", + "%s: Is a directory", + "%s: Permission denied", +}; + +int g_errnum = 0; +char *g_errmsg = NULL; +char **g_argv; + +int error_set(int n, ...) +{ + va_list ap; + + g_errnum = n; + va_start(ap, n); + if (g_errmsg) + { + free(g_errmsg); + g_errmsg = NULL; + } + vasprintf(&g_errmsg, g_error_msglist[n], ap); + return (g_errnum); +} + +int ft_perror(char *utility) +{ + utility = utility ? utility : g_argv[0]; + ERR_MSG(utility, g_errmsg); + return (g_errnum); +} + +void ft_usage(char *format, ...) +{ + va_list ap; + char *usage; + + va_start(ap, format); + usage = NULL; + vasprintf(&usage, format, ap); + dprintf(2, "usage: %s\n", usage); + if (usage) + { + free(usage); + usage = NULL; + } +} diff --git a/ping/error.h b/ping/error.h new file mode 100644 index 00000000..4ff21d9c --- /dev/null +++ b/ping/error.h @@ -0,0 +1,64 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* error.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: jhalford +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2017/03/14 15:34:21 by jhalford #+# #+# */ +/* Updated: 2017/05/15 17:37:29 by ariard ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef ERROR_H +# define ERROR_H + +# include +# include +# include + +/* +** DEBUG with malloc +*/ +# define DG_MSG "{inv}{ran}%5i{yel}%21s {bol}{blu}%-3d{eoc}" +# define DG_ARGS getpid(), getpid(), ft_path_notdir(__FILE__), __LINE__ +# define DG(s, ...) dprintf(STDBUG,DG_MSG s "{eoc}\n",DG_ARGS,##__VA_ARGS__) + +/* +** DEBUG with no malloc +*/ +# define DG2 ft_putstr(__FILE__"\t");ft_putnbr(__LINE__) +# define DGW(d) DG2;d;ft_putchar('\n') +# define DGS(s) DGW(ft_putstr(": "s"=")) +# define DGSN(s, n) DGW(ft_putstr(": "s"=");ft_putnbr(n)) +# define DGSH(s, n) DGW(ft_putstr(": "s"=");ft_putnbr_hex(n)) + +# define ERR_PROTO(u, m) "%s: %s\n", u, m +# define ERR_MSG(u, m) dprintf(2, ERR_PROTO(u, m)) +# define ERR_SET(n, ...) error_set(n, ##__VA_ARGS__) +# define ERRMSG_MAX_SIZE 150 + +enum e_errors +{ + E_NOERR, + E_CO_INV, + E_CO_INVL, + E_CO_MULT, + E_CO_MISS, + E_CO_MISSL, + E_SYS_NOFILE, + E_SYS_ISDIR, + E_SYS_NOPERM, + E_MAX, +}; + +extern char g_error_msg[E_MAX][ERRMSG_MAX_SIZE]; +extern char *g_errmsg; +extern int g_errnum; +extern char **g_argv; + +int error_set(int n, ...); +int ft_perror(char *utility); +void ft_usage(char *format, ...); + +#endif diff --git a/ping/ping.c b/ping/ping.c new file mode 100644 index 00000000..0ec0e764 --- /dev/null +++ b/ping/ping.c @@ -0,0 +1,195 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* main.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: jhalford +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2017/04/22 14:10:24 by jhalford #+# #+# */ +/* Updated: 2017/10/08 14:35:02 by jhalford ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "ping.h" + +#define PING_USAGE "%s [-hv] [-t ttl] destination" + +t_ping g_ping = +{ + .pid = -1, + .pkt_size = 56, + .pkt_sent = -1, + .pkt_recv = 0, + .ttl = 255, +}; + +int get_ttl(char *arg, t_ping *data); + +t_cliopts opts[] = +{ +#define FLAG_HELP (1 << 0) +#define FLAG_VERBOSE (1 << 1) +#define FLAG_TTL (1 << 2) + {'h', NULL, FLAG_HELP, 0, NULL, 0}, + {'v', NULL, FLAG_VERBOSE, 0, NULL, 0}, + {'t', NULL, FLAG_TTL, 0, get_ttl, 1}, +}; + +int resolve_host(char *node, t_ping *ping) +{ + struct addrinfo *result; + struct addrinfo hints; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_INET; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags |= AI_CANONNAME; + if (getaddrinfo(node, NULL, &hints, &result) != 0) + { + perror("getaddrinfo"); + exit(1); + } + ping->sa = result; + inet_ntop(AF_INET, &(((struct sockaddr_in*)ping->sa->ai_addr)->sin_addr), + ping->ip4, INET_ADDRSTRLEN); + return (0); +} + +void display_time_exceeded(struct sockaddr *addr, struct icmp *icmp) +{ + char ipbuf[INET_ADDRSTRLEN]; + + bzero(ipbuf, INET_ADDRSTRLEN); + getnameinfo(addr, sizeof(struct sockaddr_in), ipbuf, INET_ADDRSTRLEN, + NULL, 0, NI_NUMERICHOST); + printf("From %s icmp_seq=%d Time to live exceeded\n", + ipbuf, icmp->icmp_id); +} + +void display(void *buf, int bytes, struct sockaddr *addr) +{ + struct ip *ip; + struct icmp *icmp; + int hlen; + double triptime; + char hbuf[NI_MAXHOST]; + char ipbuf[INET_ADDRSTRLEN]; + + ip = buf; + (void)bytes; + hlen = ip->ip_hl << 2; + icmp = (struct icmp*)(buf + hlen); + if (icmp->icmp_type == ICMP_TIME_EXCEEDED) + return (display_time_exceeded(addr, icmp)); + else if (icmp->icmp_id != g_ping.pid) + { + dprintf(2, "id = %i\n", icmp->icmp_id); + return ; + } + triptime = time_milli() - *(double*)(icmp + 1); + rs_push(&g_ping.rs, triptime); + g_ping.pkt_recv++; + + bzero(hbuf, NI_MAXHOST); + bzero(ipbuf, INET_ADDRSTRLEN); + getnameinfo(addr, sizeof(struct sockaddr_in), ipbuf, INET_ADDRSTRLEN, + NULL, 0, NI_NUMERICHOST); + if (getnameinfo(addr, sizeof(struct sockaddr_in), hbuf, NI_MAXHOST, NULL, 0, 0) == 0) + printf("%zu bytes from %s (%s): icmp_seq=%d ttl=%i time=%.1f ms\n", + bytes - hlen - sizeof(struct icmphdr), hbuf, ipbuf, icmp->icmp_seq, ip->ip_ttl, triptime); + else + printf("%zu bytes from %s: icmp_seq=%d ttl=%i time=%.1f ms\n", + bytes - hlen - sizeof(struct icmphdr), ipbuf, icmp->icmp_seq, ip->ip_ttl, triptime); + +} + +void ping(int signo) +{ + char pkt[g_ping.pkt_size + sizeof(struct icmp)]; + double *msg; + struct icmp *hdr; + double epoch; + + (void)signo; + hdr = (struct icmp*)&pkt; + bzero(&pkt, sizeof(pkt)); + hdr->icmp_type = ICMP_ECHO; + hdr->icmp_id = g_ping.pid; + hdr->icmp_seq = ++g_ping.pkt_sent; + msg = (double*)(pkt + sizeof(struct icmp)); + epoch = time_milli(); + memcpy(msg, (void*)&epoch, sizeof(double)); + hdr->icmp_cksum = cksum(&pkt, sizeof(pkt)); + sendto(g_ping.sock, &pkt, sizeof(pkt), 0, g_ping.sa->ai_addr, + sizeof(struct sockaddr)); + alarm(1); +} + +void stats_recap(int signo) +{ + double loss; + + (void)signo; + rs_final(&g_ping.rs); + loss = FT_PCT(g_ping.pkt_recv, g_ping.pkt_sent); + printf("\n--- %s ping statistics ---", g_ping.sa->ai_canonname); + printf("\n%d packets transmitted, %d packets received, %0.1f%% packet loss", + g_ping.pkt_sent, g_ping.pkt_recv, loss); + printf("\nrtt min/avg/max/stddev = %.3f/%.3f/%.3f/%.3f ms\n", + g_ping.rs.min, g_ping.rs.avg, g_ping.rs.max, g_ping.rs.stdev); + freeaddrinfo(g_ping.sa); + exit(0); +} + +int get_interval(char *arg, t_ping *data) +{ + data->interval = atof(arg); + return (0); +} + +int get_ttl(char *arg, t_ping *data) +{ + data->ttl = atoi(arg); + return (0); +} + +int main(int ac, char **av) +{ + (void)ac; + if (cliopts_get(av, opts, &g_ping)) + { + ft_perror(av[0]); + ft_usage(PING_USAGE, av[0]); + exit(1); + } + if (g_ping.flag & FLAG_HELP || !g_ping.av_data[0]) + { + ft_usage(PING_USAGE, av[0]); + exit(!(g_ping.flag & FLAG_HELP)); + } + resolve_host(g_ping.av_data[0], &g_ping); + if (g_ping.sa->ai_canonname) + printf("PING %s (%s): %zu(%zu) data bytes\n", + g_ping.sa->ai_canonname, g_ping.ip4, + g_ping.pkt_size, g_ping.pkt_size + sizeof(struct icmp)); + else + printf("PING %s: %zu(%zu) data bytes\n", g_ping.ip4, + g_ping.pkt_size, g_ping.pkt_size + sizeof(struct icmp)); + if ((g_ping.sock = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) + { + perror("socket"); + exit(1); + } + if (setsockopt(g_ping.sock, 0, IP_TTL, &g_ping.ttl, sizeof(g_ping.ttl)) != 0) + { + perror("setsockopt"); + exit(1); + } + g_ping.pid = getpid(); + rs_init(&g_ping.rs); + signal(SIGINT, stats_recap); + signal(SIGALRM, ping); + alarm(1); + listener(PF_INET, SOCK_RAW, IPPROTO_ICMP, &display); + return (0); +} diff --git a/ping/ping.h b/ping/ping.h new file mode 100644 index 00000000..26773ba8 --- /dev/null +++ b/ping/ping.h @@ -0,0 +1,66 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_ping.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: jhalford +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2017/04/22 14:10:24 by jhalford #+# #+# */ +/* Updated: 2017/10/08 14:36:37 by jhalford ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#pragma once + +# include "rs.h" +# include "cliopts.h" + +# include +# include +# include +# include +# include +# include +# include + +# include +# include +# include +# include +# include +# include +# include +# include + +# define FT_PCT(a, t) (t ? 100 * (float)(t - a)/(float)t : 0) + +typedef struct s_ping t_ping; + +struct s_ping +{ + t_flag flag; + char **av_data; + size_t pkt_size; + pid_t pid; + t_rs rs; + int pkt_sent; + int pkt_recv; + int ttl; + float interval; + int sock; + struct addrinfo *sa; + union + { + char ip4[INET_ADDRSTRLEN]; + char ip6[INET6_ADDRSTRLEN]; + } ip; +#define ip4 ip.ip4 +#define ip6 ip.ip6 +}; + +extern t_ping g_ping; + +unsigned short cksum(void *b, int len); +double time_milli(void); +void listener(int domain, int sock, int proto, + void (*handler)(void *buf, int bytes, struct sockaddr *addr)); diff --git a/ping/rs.c b/ping/rs.c new file mode 100644 index 00000000..9d4906ae --- /dev/null +++ b/ping/rs.c @@ -0,0 +1,61 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* rs.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: jhalford +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2017/10/07 17:57:54 by jhalford #+# #+# */ +/* Updated: 2017/10/07 18:19:47 by jhalford ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "rs.h" +#include + +double sqrt(double x); + +void rs_init(t_rs *rs) +{ + bzero(rs, sizeof(t_rs)); + rs->count = 0; + rs->min = DBL_MAX; + rs->max = -DBL_MAX; +} + +void rs_push(t_rs *rs, double n) +{ + double delta; + + rs->count++; + n < rs->min ? rs->min = n : (0); + n > rs->max ? rs->max = n : (0); + if (rs->count == 1) + { + rs->avg = n; + rs->m = 0; + } + else + { + delta = n - rs->avg; + rs->avg += delta / rs->count; + rs->m += delta * (n - rs->avg); + } +} + +void rs_final(t_rs *rs) +{ + if (rs->count == 0) + { + rs->min = 0; + rs->max = 0; + } + if (rs->count < 2) + { + rs->var = 0; + rs->stdev = 0; + return ; + } + rs->var = rs->m / (rs->count - 1); + rs->stdev = sqrt(rs->var); +} diff --git a/ping/rs.h b/ping/rs.h new file mode 100644 index 00000000..3aa6bd6b --- /dev/null +++ b/ping/rs.h @@ -0,0 +1,34 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* rs.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: jhalford +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2017/10/07 18:05:30 by jhalford #+# #+# */ +/* Updated: 2017/10/08 15:59:58 by jhalford ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#pragma once + +# include +# include +# include +# include + +typedef struct s_rs t_rs; + +struct s_rs { + int count; + double min; + double max; + double avg; + double m; + double stdev; + double var; +}; + +void rs_init(t_rs *rs); +void rs_push(t_rs *rs, double n); +void rs_final(t_rs *rs);