Codebase list httping / bc3680c
Imported Upstream version 2.4 Abhijith PA 8 years ago
46 changed file(s) with 7592 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
0 # The GPL applies to this program.
1 # In addition, as a special exception, the copyright holders give
2 # permission to link the code of portions of this program with the
3 # OpenSSL library under certain conditions as described in each
4 # individual source file, and distribute linked combinations
5 # including the two.
6 # You must obey the GNU General Public License in all respects
7 # for all of the code used other than OpenSSL. If you modify
8 # file(s) with this exception, you may extend this exception to your
9 # version of the file(s), but you are not obligated to do so. If you
10 # do not wish to do so, delete this exception statement from your
11 # version. If you delete this exception statement from all source
12 # files in the program, then also delete it here.
13 # $Revision: 278 $
14
15 -include makefile.inc
16
17 # *** configure script ***
18 # support for tcp fast open?
19 #TFO=yes
20 # disable SSL? (no = disable so the default is use openssl)
21 # SSL=no
22 # enable NCURSES interface?
23 #NC=yes
24 # do fft in ncurses interface? (requires libfftw3)
25 #FW=yes
26
27 ############# do not change anything below here #############
28
29 include version
30
31 TARGET=httping
32
33 LOCALEDIR=/usr/share/locale
34
35 DEBUG=yes
36 WFLAGS=-Wall -W -Wextra -pedantic -D_FORTIFY_SOURCE=2
37 OFLAGS=
38 CFLAGS+=$(WFLAGS) $(OFLAGS) -DVERSION=\"$(VERSION)\" -DLOCALEDIR=\"$(LOCALEDIR)\"
39 LDFLAGS+=-lm
40
41 PACKAGE=$(TARGET)-$(VERSION)
42 PREFIX?=/usr
43 BINDIR=$(PREFIX)/bin
44 MANDIR=$(PREFIX)/share/man
45 DOCDIR=$(PREFIX)/share/doc/$(TARGET)
46
47 INSTALL=install
48 INSTALLDIR=$(INSTALL) -m 0755 -d
49 INSTALLBIN=$(INSTALL) -m 0755
50 INSTALLMAN=$(INSTALL) -m 0644
51 INSTALLDOC=$(INSTALL) -m 0644
52 STRIP=/usr/bin/strip
53 RMDIR=/bin/rm -rf
54 MKDIR=/bin/mkdir
55 ARCHIVE=/bin/tar cf -
56 COMPRESS=/bin/gzip -9
57
58 TRANSLATIONS=nl.mo
59
60 OBJS=gen.o http.o io.o error.o utils.o main.o tcp.o res.o socks5.o kalman.o cookies.o help.o colors.o
61
62 MAN_EN=httping.1
63 MAN_NL=httping-nl.1
64
65 DOCS=license.txt license.OpenSSL readme.txt
66
67 ifeq ($(SSL),no)
68 CFLAGS+=-DNO_SSL
69 else
70 OBJS+=mssl.o
71 LDFLAGS+=-lssl -lcrypto
72 endif
73
74 ifeq ($(TFO),yes)
75 CFLAGS+=-DTCP_TFO
76 endif
77
78 ifeq ($(NC),yes)
79 CFLAGS+=-DNC
80 OBJS+=nc.o
81 LDFLAGS+=-lncursesw
82 endif
83
84 ifeq ($(FW),yes)
85 CFLAGS+=-DFW
86 OBJS+=fft.o
87 LDFLAGS+=-lfftw3
88 endif
89
90 ifeq ($(DEBUG),yes)
91 CFLAGS+=-D_DEBUG -ggdb
92 LDFLAGS+=-g
93 endif
94
95 ifeq ($(ARM),yes)
96 CC=arm-linux-gcc
97 endif
98
99 all: $(TARGET) $(TRANSLATIONS)
100
101 $(TARGET): $(OBJS)
102 $(CC) $(WFLAGS) $(OBJS) $(LDFLAGS) -o $(TARGET)
103 #
104 # Oh, blatant plug: http://www.vanheusden.com/wishlist.php
105
106 install: $(TARGET) $(TRANSLATIONS)
107 $(INSTALLDIR) $(DESTDIR)/$(BINDIR)
108 $(INSTALLBIN) $(TARGET) $(DESTDIR)/$(BINDIR)
109 $(INSTALLDIR) $(DESTDIR)/$(MANDIR)/man1
110 $(INSTALLMAN) $(MAN_EN) $(DESTDIR)/$(MANDIR)/man1
111 $(INSTALLDIR) $(DESTDIR)/$(MANDIR)/nl/man1
112 $(INSTALLMAN) $(MAN_NL) $(DESTDIR)/$(MANDIR)/nl/man1
113 $(INSTALLDIR) $(DESTDIR)/$(DOCDIR)
114 $(INSTALLDOC) $(DOCS) $(DESTDIR)/$(DOCDIR)
115 ifneq ($(DEBUG),yes)
116 $(STRIP) $(DESTDIR)/$(BINDIR)/$(TARGET)
117 endif
118 mkdir -p $(DESTDIR)/$(PREFIX)/share/locale/nl/LC_MESSAGES
119 cp nl.mo $(DESTDIR)/$(PREFIX)/share/locale/nl/LC_MESSAGES/httping.mo
120
121 makefile.inc:
122 ./configure
123
124 nl.mo: nl.po
125 msgfmt -o nl.mo nl.po
126
127 clean:
128 $(RMDIR) $(OBJS) $(TARGET) *~ core cov-int *.mo
129
130 distclean: clean
131 rm -f makefile.inc
132
133 package:
134 # source package
135 $(RMDIR) $(PACKAGE)*
136 $(MKDIR) $(PACKAGE)
137 $(INSTALLDOC) *.c *.h configure Makefile *.po version $(MAN_EN) $(MAN_NL) $(DOCS) $(PACKAGE)
138 $(INSTALLBIN) configure $(PACKAGE)
139 $(ARCHIVE) $(PACKAGE) | $(COMPRESS) > $(PACKAGE).tgz
140 $(RMDIR) $(PACKAGE)
141
142 check: makefile.inc
143 cppcheck -v --force -j 3 --enable=all --std=c++11 --inconclusive -I. . 2> err.txt
144 #
145 make clean
146 scan-build make
147
148 coverity: makefile.inc
149 make clean
150 rm -rf cov-int
151 CC=gcc cov-build --dir cov-int make all
152 tar vczf ~/site/coverity/httping.tgz README cov-int/
153 putsite -q
154 /home/folkert/.coverity-hp.sh
0 #include "colors.h"
1
2 const char *c_error = "";
3 const char *c_normal = "";
4 const char *c_very_normal = "";
5 const char *c_red = "";
6 const char *c_blue = "";
7 const char *c_green = "";
8 const char *c_yellow = "";
9 const char *c_magenta = "";
10 const char *c_cyan = "";
11 const char *c_white = "";
12 const char *c_bright = "";
13
14 void set_colors(char nc)
15 {
16 if (nc)
17 {
18 c_red = COLOR_ESCAPE "1";
19 c_blue = COLOR_ESCAPE "2";
20 c_green = COLOR_ESCAPE "3";
21 c_yellow = COLOR_ESCAPE "4";
22 c_magenta = COLOR_ESCAPE "5";
23 c_cyan = COLOR_ESCAPE "6";
24 c_white = COLOR_ESCAPE "7";
25
26 c_bright = COLOR_ESCAPE "8";
27 c_normal = COLOR_ESCAPE "9";
28
29 c_very_normal = COLOR_ESCAPE "7" COLOR_ESCAPE "9";
30
31 c_error = COLOR_ESCAPE "1";
32 }
33 else
34 {
35 c_red = "\033[31;40m";
36 c_blue = "\033[34;40m";
37 c_green = "\033[32;40m";
38 c_yellow = "\033[33;40m";
39 c_magenta = "\033[35;40m";
40 c_cyan = "\033[36;40m";
41 c_white = "\033[37;40m";
42
43 c_bright = "\033[1;40m";
44 c_normal = "\033[0;37;40m";
45
46 c_very_normal = "\033[0m";
47
48 c_error = "\033[1;4;40m";
49 }
50 }
0 extern const char *c_error;
1 extern const char *c_normal;
2 extern const char *c_very_normal;
3 extern const char *c_red;
4 extern const char *c_blue;
5 extern const char *c_green;
6 extern const char *c_yellow;
7 extern const char *c_magenta;
8 extern const char *c_cyan;
9 extern const char *c_white;
10 extern const char *c_bright;
11
12 #define COLOR_ESCAPE "\001"
13
14 void set_colors(char nc);
0 #! /bin/sh
1
2 FILE=`mktemp`
3 FILE2=`mktemp`
4
5 echo \*\*\* HTTPing v`grep VERSION version | cut -d = -f 2` \(`echo $Revision$ | awk '{ print $2; }'`\) configure script \*\*\*
6 echo
7
8 if [ -z "$CC" ]
9 then
10 CC=gcc
11 fi
12
13 F_TFO=0
14 F_NC=0
15 F_OS=0
16 F_FW=0
17 for var in "$@"
18 do
19 case "$var" in
20 --with-tfo)
21 F_TFO=1
22 ;;
23
24 --with-ncurses)
25 F_NC=1
26 ;;
27
28 --with-openssl)
29 F_OS=1
30 ;;
31
32 --with-fftw3)
33 F_FW=1
34 ;;
35
36 --help)
37 echo "--with-tfo force enable tcp fast open"
38 echo "--with-ncurses force enable ncurses"
39 echo "--with-openssl force enable openssl"
40 echo "--with-fftw3 force enable fftw3"
41 exit 0
42 ;;
43
44 *)
45 echo WARNING: Command line parameter \"$var\" is not understood.
46 echo Re-run this script with --help to see a list of switches.
47 ;;
48 esac
49 done
50
51 $CC -O0 -o $FILE test_TFO.c 2> $FILE2
52 if [ $? -eq 0 ] || [ $F_TFO -eq 1 ] ; then
53 echo \+ system supports TCP fast open
54 TFO="TFO=yes"
55 else
56 echo \- this system does NOT support TCP fast open - this is an optional feature
57 TFO=""
58 fi
59
60 $CC -O0 -lncursesw -o $FILE test_ncurses.c 2> $FILE2
61 if [ $? -eq 0 ] || [ $F_NC -eq 1 ] ; then
62 echo \+ system has ncurses development libraries
63 NC="NC=yes"
64 else
65 echo \- this system does NOT have the ncurses development libraries - they are optional
66 NC=""
67 fi
68
69 $CC -O0 -lssl -lcrypto -o $FILE test_openssl.c 2> $FILE2
70 if [ $? -eq 0 ] || [ $F_OS -eq 1 ] ; then
71 echo \+ system has OpenSSL development libraries
72 SSL="SSL=yes"
73 else
74 echo \- this system does NOT have the OpenSSL development libraries - they are optional
75 SSL="SSL=no"
76 fi
77
78 $CC -O0 -lfftw3 -o $FILE test_fftw3.c 2> $FILE2
79 if [ $? -eq 0 ] || [ $F_FW -eq 1 ] ; then
80 echo \+ system has FFTW3 development libraries
81 FW="FW=yes"
82 else
83 echo \- this system does NOT have the FFTW3 development libraries - they are optional and only useful when also including ncurses
84 FW=""
85 fi
86
87 > makefile.inc
88 echo $NC >> makefile.inc
89 echo $SSL >> makefile.inc
90 echo $TFO >> makefile.inc
91 echo $FW >> makefile.inc
92
93 rm -f $FILE $FILE2
94
95 echo
0 #include <stdlib.h>
1 #include <string.h>
2
3 #include "utils.h"
4
5 void add_cookie(char ***cookies, int *n_cookies, char *in)
6 {
7 char *in_copy = strdup(in), *is = strchr(in_copy, '=');
8 int index = 0, found_at = -1;
9
10 if (is)
11 *is = 0x00;
12
13 for(index=0; index<*n_cookies; index++)
14 {
15 char *dummy = strdup((*cookies)[index]);
16
17 is = strchr(dummy, '=');
18 if (is)
19 *is = 0x00;
20
21 if (strcmp(in_copy, dummy) == 0)
22 {
23 found_at = index;
24 free(dummy);
25 break;
26 }
27
28 free(dummy);
29 }
30
31 if (found_at >= 0)
32 {
33 free((*cookies)[found_at]);
34
35 (*cookies)[found_at] = strdup(in);
36 }
37 else
38 {
39 *cookies = (char **)realloc(*cookies, (*n_cookies + 1) * sizeof(char *));
40
41 (*cookies)[*n_cookies] = strdup(in);
42
43 (*n_cookies)++;
44 }
45
46 free(in_copy);
47 }
48
49 void combine_cookie_lists(char ***destc, int *n_dest, char **src, int n_src)
50 {
51 int loop = 0;
52
53 *destc = (char **)realloc(*destc, (*n_dest + n_src) * sizeof(char *));
54
55 for(loop=0; loop<n_src; loop++)
56 (*destc)[*n_dest + loop] = strdup(src[loop]);
57
58 (*n_dest) += n_src;
59 }
60
61 void free_cookies(char **dynamic_cookies, int n_dynamic_cookies)
62 {
63 int index = 0;
64
65 for(index=0; index<n_dynamic_cookies; index++)
66 free(dynamic_cookies[index]);
67
68 free(dynamic_cookies);
69 }
70
71 void get_cookies(const char *headers, char ***dynamic_cookies, int *n_dynamic_cookies, char ***static_cookies, int *n_static_cookies)
72 {
73 int index = 0;
74 char **header_lines = NULL;
75 int n_header_lines = 0;
76
77 split_string(headers, "\r\n", &header_lines, &n_header_lines);
78
79 for(index=0; index<n_header_lines; index++)
80 {
81 char use_static = 0;
82 char *result = NULL;
83 int cparts_index = 0;
84 char **cparts = NULL;
85 int n_cparts = 0;
86
87 if (strncmp(header_lines[index], "Set-Cookie:", 11) != 0)
88 continue;
89
90 split_string(&header_lines[index][12], ";", &cparts, &n_cparts);
91
92 for(cparts_index=0; cparts_index<n_cparts; cparts_index++)
93 {
94 char *part = cparts[cparts_index];
95
96 while(*part == ' ')
97 part++;
98
99 if (strncmp(part, "expires=", 8) == 0)
100 {
101 use_static = 1;
102 continue;
103 }
104
105 if (strncmp(part, "path=", 5) == 0)
106 continue;
107
108 if (strncmp(part, "domain=", 7) == 0)
109 continue;
110
111 if (strncmp(part, "HttpOnly", 8) == 0)
112 continue;
113
114 str_add(&result, "%s ", part);
115 }
116
117 free_splitted_string(cparts, n_cparts);
118
119 if (use_static)
120 add_cookie(static_cookies, n_static_cookies, result);
121 else
122 add_cookie(dynamic_cookies, n_dynamic_cookies, result);
123
124 free(result);
125 }
126
127 free_splitted_string(header_lines, n_header_lines);
128 }
0 void add_cookie(char ***cookies, int *n_cookies, char *in);
1 void combine_cookie_lists(char ***destc, int *n_dest, char **src, int n_src);
2 void free_cookies(char **dynamic_cookies, int n_dynamic_cookies);
3 void get_cookies(const char *headers, char ***dynamic_cookies, int *n_dynamic_cookies, char ***static_cookies, int *n_static_cookies);
0 /* Released under GPLv2 with exception for the OpenSSL library. See license.txt */
1 /* $Revision$ */
2
3 #include <libintl.h>
4 #include <errno.h>
5 #include <stdarg.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <sys/types.h>
10 #include <signal.h>
11
12 char last_error[4096] = { 0 };
13
14 void error_exit(char *format, ...)
15 {
16 int e = errno;
17 va_list ap;
18
19 va_start(ap, format);
20 (void)vfprintf(stderr, format, ap);
21 va_end(ap);
22
23 fprintf(stderr, gettext("\n\nerrno=%d which means %s (if applicable)\n"), e, strerror(e));
24
25 exit(1);
26 }
27
28 void set_error(const char *fmt, ...)
29 {
30 int buffer_size = sizeof last_error;
31 va_list ap;
32
33 if (last_error[0])
34 fprintf(stderr, "%s\n", last_error);
35
36 va_start(ap, fmt);
37 if (vsnprintf(last_error, sizeof last_error, fmt, ap) >= buffer_size)
38 error_exit(gettext("Error message '%s' truncated"), last_error);
39 va_end(ap);
40 }
41
42 void clear_error()
43 {
44 last_error[0] = 0x00;
45 }
46
47 char * get_error()
48 {
49 return last_error;
50 }
0 /* Released under GPLv2 with exception for the OpenSSL library. See license.txt */
1 /* $Revision$ */
2
3 void error_exit(const char *format, ...);
4 void set_error(const char *str, ...);
5 void clear_error(void);
6 char * get_error(void);
0 /* $Revision$ */
1 #include <libintl.h>
2 #include <math.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <fftw3.h>
6
7 #include "error.h"
8
9 double *pin = NULL;
10 fftw_complex *pout = NULL;
11 fftw_plan plan;
12 int sample_rate = 44100;
13
14 void fft_init(int sample_rate_in)
15 {
16 sample_rate = sample_rate_in;
17
18 pin = (double *)malloc(sizeof(double) * sample_rate_in);
19 if (!pin)
20 error_exit(gettext("failed allocating memory for fft (1)"));
21
22 pout = (fftw_complex *)fftw_malloc(sizeof(fftw_complex) * sample_rate_in + 1);
23 if (!pout)
24 error_exit(gettext("failed allocating memory for fft (2)"));
25
26 /* init fftw */
27 plan = fftw_plan_dft_r2c_1d(sample_rate_in, pin, pout, FFTW_ESTIMATE);
28 if (!plan)
29 error_exit(gettext("failed calculating plan for fft"));
30 }
31
32 void fft_free(void)
33 {
34 if (pin)
35 {
36 fftw_free(pout);
37 free(pin);
38 }
39
40 fftw_destroy_plan(plan);
41 }
42
43 void fft_stop(void)
44 {
45 fftw_cleanup();
46 }
47
48 void fft_do(double *in, double *output_mag, double *output_phase)
49 {
50 int loop = 0;
51
52 memcpy(pin, in, sizeof(double) * sample_rate);
53
54 /* calc fft */
55 fftw_execute(plan);
56
57 for(loop=0; loop<(sample_rate / 2) + 1; loop++)
58 {
59 double real = pout[loop][0];
60 double img = pout[loop][1];
61
62 /* magnitude */
63 output_mag[loop] = sqrt(pow(real, 2.0) + pow(img, 2.0));
64
65 /* phase */
66 output_phase[loop] = (real == 0 && img == 0) ? 0 : atan2(real, img);
67 }
68 }
0 /* $Revision$ */
1 void fft_init(int sample_rate_in);
2 void fft_free(void);
3 void fft_do(double *in, double *output_mag, double *output_phase);
4 void fft_stop(void);
0 /* $Revision$ */
1 #include <math.h>
2 #include <string.h>
3
4 #include "gen.h"
5
6 void init_statst(stats_t *data)
7 {
8 memset(data, 0x00, sizeof(stats_t));
9
10 data -> min = MY_DOUBLE_INF;
11 data -> max = -data -> min;
12 }
13
14 void update_statst(stats_t *data, double in)
15 {
16 data -> cur = in;
17 data -> min = min(data -> min, in);
18 data -> max = max(data -> max, in);
19 data -> avg += in;
20 data -> sd += in * in;
21 (data -> n)++;
22 data -> valid = 1;
23 data -> cur_valid = 1;
24 }
25
26 void reset_statst_cur(stats_t *data)
27 {
28 data -> cur_valid = 0;
29 }
30
31 double calc_sd(stats_t *in)
32 {
33 double avg = 0.0;
34
35 if (in -> n == 0 || !in -> valid)
36 return 0;
37
38 avg = in -> avg / (double)in -> n;
39
40 return sqrt((in -> sd / (double)in -> n) - pow(avg, 2.0));
41 }
42
43 /* Base64 encoding start */
44 const char *alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
45
46 void encode_tryptique(char source[3], char result[4])
47 /* Encode 3 char in B64, result give 4 Char */
48 {
49 int tryptique, i;
50 tryptique = source[0];
51 tryptique *= 256;
52 tryptique += source[1];
53 tryptique *= 256;
54 tryptique += source[2];
55 for (i=0; i<4; i++)
56 {
57 result[3-i] = alphabet[tryptique%64];
58 tryptique /= 64;
59 }
60 }
61
62 int enc_b64(char *source, int source_lenght, char *target)
63 {
64 /* Divide string /3 and encode trio */
65 while (source_lenght >= 3) {
66 encode_tryptique(source, target);
67 source_lenght -= 3;
68 source += 3;
69 target += 4;
70 }
71 /* Add padding to the rest */
72 if (source_lenght > 0) {
73 char pad[3];
74 memset(pad, 0, sizeof pad);
75 memcpy(pad, source, source_lenght);
76 encode_tryptique(pad, target);
77 target[3] = '=';
78 if (source_lenght == 1) target[2] = '=';
79 target += 4;
80 }
81 target[0] = 0;
82 return 1;
83 }
84 /* Base64 encoding END */
0 /* Released under GPLv2 with exception for the OpenSSL library. See license.txt */
1 /* $Revision$ */
2
3 #ifndef __GEN_H__
4 #define __GEN_H__
5
6 #define RC_OK 0
7 #define RC_SHORTREAD -1
8 #define RC_SHORTWRITE -1
9 #define RC_TIMEOUT -2
10 #define RC_CTRLC -3
11 #define RC_INVAL -4
12
13 #define RECV_BUFFER_SIZE (128 * 1024)
14
15 #define SPAM_FILE "/tmp/httping.dat"
16
17 #define MAX_SHOW_SUPPRESSION 3
18
19 #ifdef NO_SSL
20 #define SSL void
21 #define SSL_CTX void
22 #define BIO void
23 #endif
24
25 #define PI (4 * atan(1.0))
26 #define MY_DOUBLE_INF 999999999999999.9
27
28 #ifdef TCP_TFO
29 #ifndef MSG_FASTOPEN
30 #define MSG_FASTOPEN 0x20000000
31 #endif
32
33 #ifndef TCP_FASTOPEN
34 #define TCP_FASTOPEN 23
35 #endif
36 #ifndef TCPI_OPT_SYN_DATA
37 #define TCPI_OPT_SYN_DATA 32
38 #endif
39 #endif
40
41 #define min(x, y) ((x) < (y) ? (x) : (y))
42 #define max(x, y) ((x) > (y) ? (x) : (y))
43
44 typedef struct
45 {
46 double cur, min, avg, max, sd;
47 int n;
48 char valid, cur_valid;
49 } stats_t;
50
51 int enc_b64(char *source, int source_lenght, char *target);
52
53 void init_statst(stats_t *data);
54 void update_statst(stats_t *data, double in);
55 void reset_statst_cur(stats_t *data);
56 double calc_sd(stats_t *in);
57
58 #endif
0 #include <stdio.h>
1 #include <stdlib.h>
2 #include <string.h>
3 #include <unistd.h>
4 #include <sys/utsname.h>
5 #include <libintl.h>
6
7 #include "gen.h"
8 #include "main.h"
9 #include "help.h"
10 #include "utils.h"
11
12 void new_version_alert(void)
13 {
14 char new_version = 0;
15 FILE *fh = fopen(SPAM_FILE, "r");
16 if (!fh)
17 new_version = 1;
18 else
19 {
20 char buffer[4096], *dummy = 0x00;
21
22 fgets(buffer, sizeof buffer, fh);
23
24 fclose(fh);
25
26 dummy = strchr(buffer, '\n');
27 if (dummy)
28 *dummy = 0x00;
29
30 if (strcmp(buffer, VERSION) != 0)
31 new_version = 1;
32 }
33
34 if (new_version)
35 {
36 struct utsname buf;
37 FILE *fh = fopen(SPAM_FILE, "w");
38 if (fh)
39 {
40 fprintf(fh, "%s\n", VERSION);
41
42 fclose(fh);
43 }
44
45 printf("Welcome to the new HTTPing version " VERSION "!\n\n");
46 #ifdef NC
47 printf("Did you know that with -K you can start a fullscreen GUI version with nice graphs and lots more information? And that you can disable the moving graphs with -D?\n");
48 #ifndef FW
49 printf("And if you compile this program with libfftw3, that it can also show a fourier transform of the measured values?\n");
50 #endif
51 #else
52 printf("Did you know that if you compile this program with NCURSES, that it then includes a nice GUI with lots more information and graphs?\n");
53 #endif
54
55 #if !defined(TCP_TFO) && defined(linux)
56 if (uname(&buf) == 0)
57 {
58 char **rparts = NULL;
59 int n_rparts = 0;
60
61 split_string(buf.release, ".", &rparts, &n_rparts);
62
63 if (n_rparts >= 2 && ((atoi(rparts[0]) >= 3 && atoi(rparts[1]) >= 6) || atoi(rparts[0]) >= 4))
64 printf("This program supports TCP Fast Open! (if compiled in and only on Linux kernels 3.6 or more recent) See the readme.txt how to enable this.\n");
65
66 free_splitted_string(rparts, n_rparts);
67 }
68 #endif
69
70 printf("\n\n");
71 }
72 }
73
74 void version(void)
75 {
76 fprintf(stderr, gettext("HTTPing v" VERSION ", (C) 2003-2013 folkert@vanheusden.com\n"));
77 #ifndef NO_SSL
78 fprintf(stderr, gettext(" * SSL support included (-l)\n"));
79 #endif
80
81 #ifdef NC
82 #ifdef FW
83 fprintf(stderr, gettext(" * ncurses interface with FFT included (-K)\n"));
84 #else
85 fprintf(stderr, gettext(" * ncurses interface included (-K)\n"));
86 #endif
87 #endif
88
89 #ifdef TCP_TFO
90 fprintf(stderr, gettext(" * TFO (TCP fast open) support included (-F)\n"));
91 #endif
92 fprintf(stderr, gettext("\n"));
93 }
94
95 void format_help(const char *short_str, const char *long_str, const char *descr)
96 {
97 int par_width = SWITCHES_COLUMN_WIDTH, max_wrap_width = par_width / 2, cur_par_width = 0;
98 int descr_width = max_x - (par_width + 1);
99 char *line = NULL, *p = (char *)descr;
100 char first = 1;
101
102 if (long_str && short_str)
103 str_add(&line, "%-4s / %s", short_str, long_str);
104 else if (long_str)
105 str_add(&line, "%s", long_str);
106 else
107 str_add(&line, "%s", short_str);
108
109 cur_par_width = fprintf(stderr, "%-*s ", par_width, line);
110
111 free(line);
112
113 if (par_width + 1 >= max_x || cur_par_width >= max_x)
114 {
115 fprintf(stderr, "%s\n", descr);
116 return;
117 }
118
119 for(;strlen(p);)
120 {
121 char *n = NULL, *kn = NULL, *copy = NULL;
122 int n_len = 0, len_after_ww = 0, len_before_ww = 0;
123 int str_len = 0, cur_descr_width = first ? max_x - cur_par_width : descr_width;
124
125 while(*p == ' ')
126 p++;
127
128 str_len = strlen(p);
129 if (!str_len)
130 break;
131
132 len_before_ww = min(str_len, cur_descr_width);
133
134 n = &p[len_before_ww];
135 kn = n;
136
137 if (str_len > cur_descr_width)
138 {
139 while (*n != ' ' && n_len < max_wrap_width)
140 {
141 n--;
142 n_len++;
143 }
144
145 if (n_len >= max_wrap_width)
146 n = kn;
147 }
148
149 len_after_ww = (int)(n - p);
150 if (len_after_ww <= 0)
151 break;
152
153 copy = (char *)malloc(len_after_ww + 1);
154 memcpy(copy, p, len_after_ww);
155 copy[len_after_ww] = 0x00;
156
157 if (first)
158 first = 0;
159 else
160 fprintf(stderr, "%*s ", par_width, "");
161
162 fprintf(stderr, "%s\n", copy);
163
164 free(copy);
165
166 p = n;
167 }
168 }
169
170 void usage(const char *me)
171 {
172 char *dummy = NULL, has_color = 0;
173 char host[256] = { 0 };
174
175 /* where to connect to */
176 fprintf(stderr, gettext(" *** where to connect to ***\n"));
177 format_help("-g x", "--url", gettext("URL to ping (e.g. -g http://localhost/)"));
178 format_help("-h x", "--hostname", gettext("hostname to ping (e.g. localhost) - use either -g or -h"));
179 format_help("-p x", "--port", gettext("portnumber (e.g. 80) - use with -h"));
180 format_help("-6", "--ipv6", gettext("use IPv6 when resolving/connecting"));
181 #ifndef NO_SSL
182 format_help("-l", "--use-ssl", gettext("connect using SSL. pinging an https URL automatically enables this setting"));
183 #endif
184 fprintf(stderr, gettext("\n"));
185
186 /* proxy settings */
187 fprintf(stderr, gettext(" *** proxy settings ***\n"));
188 format_help("-x x", "--proxy", gettext("x should be \"host:port\" which are the network settings of the http/https proxy server. ipv6 ip-address should be \"[ip:address]:port\""));
189 format_help("-E", NULL, gettext("fetch proxy settings from environment variables"));
190 format_help(NULL, "--proxy-user x", gettext("username for authentication against proxy"));
191 format_help(NULL, "--proxy-password x", gettext("password for authentication against proxy"));
192 format_help(NULL, "--proxy-password-file x", gettext("read password for proxy authentication from file x"));
193 format_help("-5", NULL, gettext("proxy is a socks5 server"));
194 format_help(NULL, "--proxy-buster x", gettext("adds \"&x=[random value]\" to the request URL"));
195 fprintf(stderr, gettext("\n"));
196
197 /* timing settings */
198 fprintf(stderr, gettext(" *** timing settings ***\n"));
199 format_help("-c x", "--count", gettext("how many times to ping"));
200 format_help("-i x", "--interval", gettext("delay between each ping"));
201 format_help("-t x", "--timeout", gettext("timeout (default: 30s)"));
202 format_help(NULL, "--ai / --adaptive-interval", gettext("execute pings at multiples of interval relative to start, automatically enabled in ncurses output mode"));
203 format_help("-f", "--flood", gettext("flood connect (no delays)"));
204 fprintf(stderr, gettext("\n"));
205
206 /* http settings */
207 fprintf(stderr, gettext(" *** HTTP settings ***\n"));
208 format_help("-Z", "--no-cache", gettext("ask any proxies on the way not to cache the requests"));
209 format_help(NULL, "--divert-connect", gettext("connect to a different host than in the URL given"));
210 format_help(NULL, "--keep-cookies", gettext("return the cookies given by the HTTP server in the following request(s)"));
211 format_help(NULL, "--no-host-header", gettext("do not add \"Host:\"-line to the request headers"));
212 format_help("-Q", "--persistent-connections", gettext("use a persistent connection. adds a 'C' to the output if httping had to reconnect"));
213 format_help("-I x", "--user-agent", gettext("use 'x' for the UserAgent header"));
214 format_help("-R x", "--referer", gettext("use 'x' for the Referer header"));
215 format_help(NULL, "--header", gettext("adds an extra request-header"));
216 fprintf(stderr, gettext("\n"));
217
218 /* network settings */
219 fprintf(stderr, gettext(" *** networking settings ***\n"));
220 format_help(NULL, "--max-mtu", gettext("limit the MTU size"));
221 format_help(NULL, "--no-tcp-nodelay", gettext("do not disable Naggle"));
222 format_help(NULL, "--recv-buffer", gettext("receive buffer size"));
223 format_help(NULL, "--tx-buffer", gettext("transmit buffer size"));
224 format_help("-r", "--resolve-once", gettext("resolve hostname only once (useful when pinging roundrobin DNS: also takes the first DNS lookup out of the loop so that the first measurement is also correct)"));
225 format_help("-W", NULL, gettext("do not abort the program if resolving failed: keep retrying"));
226 format_help("-y x", "--bind-to", gettext("bind to an ip-address (and thus interface) with an optional port"));
227 #ifdef TCP_TFO
228 format_help("-F", "--tcp-fast-open", gettext("\"TCP fast open\" (TFO), reduces the latency of TCP connects"));
229 #endif
230 #ifdef linux
231 format_help(NULL, "--priority", gettext("set priority of packets"));
232 #endif
233 format_help(NULL, "--tos", gettext("set TOS (type of service)"));
234 fprintf(stderr, gettext("\n"));
235
236 /* http authentication */
237 fprintf(stderr, gettext(" *** HTTP authentication ***\n"));
238 format_help("-A", "--basic-auth", gettext("activate (\"basic\") authentication"));
239 format_help("-U x", "--username", gettext("username for authentication"));
240 format_help("-P x", "--password", gettext("password for authentication"));
241 format_help("-T x", NULL, gettext("read the password fom the file 'x' (replacement for -P)"));
242 fprintf(stderr, gettext("\n"));
243
244 /* output settings */
245 fprintf(stderr, gettext(" *** output settings ***\n"));
246 format_help("-s", "--show-statuscodes", gettext("show statuscodes"));
247 format_help("-S", "--split-time", gettext("split measured time in its individual components (resolve, connect, send, etc."));
248 format_help(NULL, "--threshold-red", gettext("from what ping value to show the value in red (must be bigger than yellow), only in color mode (-Y)"));
249 format_help(NULL, "--threshold-yellow", gettext("from what ping value to show the value in yellow"));
250 format_help(NULL, "--threshold-show", gettext("from what ping value to show the results"));
251 format_help(NULL, "--timestamp / --ts", gettext("put a timestamp before the measured values, use -v to include the date and -vv to show in microseconds"));
252 format_help(NULL, "--aggregate x[,y[,z]]", gettext("show an aggregate each x[/y[/z[/etc]]] seconds"));
253 #ifndef NO_SSL
254 format_help("-z", "--show-fingerprint", gettext("show fingerprint (SSL)"));
255 #endif
256 format_help("-v", NULL, gettext("verbose mode"));
257 fprintf(stderr, gettext("\n"));
258
259 /* GET settings */
260 fprintf(stderr, gettext(" *** \"GET\" (instead of HTTP \"HEAD\") settings ***\n"));
261 format_help("-G", "--get-request", gettext("do a GET request instead of HEAD (read the contents of the page as well)"));
262 format_help("-b", "--show-transfer-speed", gettext("show transfer speed in KB/s (use with -G)"));
263 format_help("-B", "--show-xfer-speed-compressed", gettext("like -b but use compression if available"));
264 format_help("-L x", "--data-limit", gettext("limit the amount of data transferred (for -b) to 'x' (in bytes)"));
265 format_help("-X", "--show-kb", gettext("show the number of KB transferred (for -b)"));
266 fprintf(stderr, gettext("\n"));
267
268 /* output mode settings */
269 fprintf(stderr, gettext(" *** output mode settings ***\n"));
270 format_help("-q", "--quiet", gettext("quiet, only returncode"));
271 format_help("-m", "--parseable-output", gettext("give machine parseable output (see also -o and -e)"));
272 format_help("-M", NULL, gettext("json output, cannot be combined with -m"));
273 format_help("-o rc,rc,...", "--ok-result-codes", gettext("what http results codes indicate 'ok' comma seperated WITHOUT spaces inbetween default is 200, use with -e"));
274 format_help("-e x", "--result-string", gettext("string to display when http result code doesn't match"));
275 format_help("-n warn,crit", "--nagios-mode-1 / --nagios-mode-2", gettext("Nagios-mode: return 1 when avg. response time >= warn, 2 if >= crit, otherwhise return 0"));
276 format_help("-N x", NULL, gettext("Nagios mode 2: return 0 when all fine, 'x' when anything failes"));
277 format_help("-C cookie=value", "--cookie", gettext("add a cookie to the request"));
278 format_help("-Y", "--colors", gettext("add colors"));
279 format_help("-a", "--audible-ping", gettext("audible ping"));
280 fprintf(stderr, gettext("\n"));
281
282 /* GUI/ncurses mode */
283 #if defined(NC)
284 fprintf(stderr, gettext(" *** GUI/ncurses mode settings ***\n"));
285 format_help("-K", "--ncurses / --gui", gettext("ncurses/GUI mode"));
286 #if defined(FW)
287 format_help(NULL, "--draw-phase", gettext("draw phase (fourier transform) in gui"));
288 #endif
289 format_help(NULL, "--slow-log", gettext("when the duration is x or more, show ping line in the slow log window (the middle window)"));
290 format_help(NULL, "--graph-limit x", gettext("do not scale to values above x"));
291 format_help("-D", "--no-graph", gettext("do not show graphs (in ncurses/GUI mode)"));
292 fprintf(stderr, gettext("\n"));
293 #endif
294
295 format_help("-V", "--version", gettext("show the version"));
296 fprintf(stderr, gettext("\n"));
297
298 dummy = getenv("TERM");
299 if (dummy)
300 {
301 if (strstr(dummy, "ANSI") || strstr(dummy, "xterm") || strstr(dummy, "screen"))
302 has_color = 1;
303 }
304
305 if (gethostname(host, sizeof host))
306 strcpy(host, "localhost");
307
308 fprintf(stderr, gettext("Example:\n"));
309 fprintf(stderr, "\t%s %s%s -s -Z\n\n", me, host, has_color ? " -Y" : "");
310
311 new_version_alert();
312 }
0 #define SWITCHES_COLUMN_WIDTH 24
1
2 void new_version_alert(void);
3 void version(void);
4 void help_long(void);
5 void usage(const char *me);
0 /* Released under GPLv2 with exception for the OpenSSL library. See license.txt */
1 /* $Revision$ */
2
3 #include <assert.h>
4 #include <stdio.h>
5 #include <string.h>
6 #include <unistd.h>
7 #ifndef NO_SSL
8 #include <openssl/ssl.h>
9 #include "mssl.h"
10 #endif
11
12 #include "gen.h"
13 #include "http.h"
14 #include "io.h"
15 #include "utils.h"
16
17 int get_HTTP_headers(int socket_h, SSL *ssl_h, char **headers, int *overflow, double timeout)
18 {
19 char *term = NULL;
20 int len_in=0, len=4096;
21 char *buffer = (char *)malloc(len + 1);
22 int rc = RC_OK;
23
24 *headers = NULL;
25
26 memset(buffer, 0x00, len);
27
28 for(;;)
29 {
30 int rrc = -1;
31 int now_n = len - len_in;
32
33 #ifndef NO_SSL
34 if (ssl_h)
35 rrc = SSL_read(ssl_h, &buffer[len_in], now_n);
36 else
37 #endif
38 rrc = read_to(socket_h, &buffer[len_in], now_n, timeout);
39
40 if (rrc == 0 || rrc == RC_SHORTREAD) /* socket closed before request was read? */
41 {
42 rc = RC_SHORTREAD;
43 break;
44 }
45 else if (rrc < 0)
46 {
47 free(buffer);
48 return rrc;
49 }
50
51 len_in += rrc;
52
53 assert(len_in >= 0);
54 assert(len_in <= len);
55
56 buffer[len_in] = 0x00;
57
58 if (strstr(buffer, "\r\n\r\n") != NULL)
59 break;
60
61 if (len_in >= len)
62 {
63 len <<= 1;
64 buffer = (char *)realloc(buffer, len + 1);
65 }
66 }
67
68 *headers = buffer;
69
70 term = strstr(buffer, "\r\n\r\n");
71 if (term)
72 *overflow = len_in - (term - buffer + 4);
73 else
74 *overflow = 0;
75
76 return rc;
77 }
78
79 int dumb_get_HTTP_headers(int socket_h, char **headers, double timeout)
80 {
81 int len_in=0, len=4096;
82 char *buffer = (char *)malloc(len);
83 int rc = RC_OK;
84
85 *headers = NULL;
86
87 for(;;)
88 {
89 int rrc = read_to(socket_h, &buffer[len_in], 1, timeout);
90 if (rrc == 0 || rrc == RC_SHORTREAD) /* socket closed before request was read? */
91 {
92 rc = RC_SHORTREAD;
93 break;
94 }
95 else if (rrc == RC_TIMEOUT) /* timeout */
96 {
97 free(buffer);
98 return RC_TIMEOUT;
99 }
100
101 len_in += rrc;
102
103 buffer[len_in] = 0x00;
104 if (memcmp(&buffer[len_in - 4], "\r\n\r\n", 4) == 0)
105 break;
106 if (memcmp(&buffer[len_in - 2], "\n\n", 2) == 0) /* broken proxies */
107 break;
108
109 if (len_in == (len - 1))
110 {
111 len <<= 1;
112 buffer = (char *)realloc(buffer, len);
113 }
114 }
115
116 *headers = buffer;
117
118 return rc;
119 }
0 /* Released under GPLv2 with exception for the OpenSSL library. See license.txt */
1 /* $Revision$ */
2
3 int get_HTTP_headers(int socket_h, SSL *ssl_h, char **headers, int *overflow, double timeout);
4 int dumb_get_HTTP_headers(int socket_h, char **headers, double timeout);
0 .\" Copyright Folkert van Heusden, 2003-2013
1 .\"
2 .\" This file may be copied under the conditions described
3 .\" in the GNU GENERAL PUBLIC LICENSE, version 2
4 .\" that can be found on the website of the free software
5 .\" foundation.
6 .\"
7 .TH HTTPING 1 2013-03 "httping"
8 .SH NAME
9 httping - meten van de latency en doorvoorsnelheid van een http server
10 .SH SAMENVATTING
11 .BI "httping [" opties "]
12 .sp
13 een aantal opties:
14 .BI "[\-g URL] [\-h systeem naam] [\-p port nummer] [\-x proxy systeem naam:port] [\-c aantal] [\-i interval] [\-t duur limiet] [\-s] [\-K] [\-Y]
15 .SH BESCHRIJVING
16 The program
17 Het programma
18 .B httping
19 meet de latency van een http server. Sinds versie 1.0.6 kan ook de dooorvoorsnelheid gemeten worden.
20 .PP
21 .SH OPTIES
22 .TP
23 .B "\-5"
24 De geselecteerde server is een SOCKS5 server.
25 .TP
26 .B "\-6"
27 Schakel IPv6 mode in. Standaard instelling is IPv4.
28 .TP
29 .B "\-a"
30 Hoorbare ping
31 .TP
32 .B "\-b"
33 Gebruik deze optie samen met \-G. HTTPing zal dan de doorvoorsnelheid (in kB/s) tonen.
34 .TP
35 .B "\-B"
36 Gebruik deze optie samen met \-G. HTTPing zal dan de doorvoorsnelheid (in kB/s) tonen. HTTPing zal echter vragen aan de webserver of deze de data comprimeerd.
37 .TP
38 .B "\-c aantal"
39 Hoevaak te pingen.
40 .TP
41 .B "\-D"
42 Teken geen grafieken (in ncurses (\-K) mode).
43 .TP
44 .B "\-e str"
45 Als de status-code anders is dan die ingesteld is met \-o, dan zal 'str' getoond worden.
46 .TP
47 .B "\-E"
48 Haal de proxy instellingen uit omgevings variabelen.
49 .TP
50 .B "\-F"
51 Probeer verbindingen met "TFO (TCP Fast open)" op te zetten. Dit werkt alleen met Linux kernel 3.7 of recenter.
52 .TP
53 .B "\-f"
54 Ping zo snel als mogelijk achter elkaar.
55 .TP
56 .B "\-G"
57 Doe een GET-verzoek in plaats van een HEAD-verzoek. Daarmee wordt ook de pagina-inhoud opgehaald.
58 .TP
59 .B "\-g URL"
60 Kies welke URL gepinged moet worden. Bijvoorbeeld: http://www.microsoft.com/
61 .TP
62 .B "\-h systeem naam"
63 In plaats van een URL kan men ook alleen een systeem naam opgeven.
64 .TP
65 .B "\-I str"
66 Welke "UserAgent" te sturen naar de webserver.
67 .TP
68 .B "\-i interval"
69 Hoeveel seconden (of delen daarvan) te wachten tussen het verzenden van iedere ping.
70 .TP
71 .B "\-K"
72 Gebruik de ncurses gebruikers interface.
73 .TP
74 .B "\-L x"
75 In combinatie met -G zet dit een limiet op hoeveel data er binnengehaald wordt.
76 .TP
77 .B "\-l"
78 Maak een SSL verbinding. Dit vereist een https-URL.
79 .TP
80 .B "\-m"
81 Geef output die makkelijker met een script te bewerken is.
82 .TP
83 .B "\-N x"
84 Nagios-mode 1: geef 1 terug als de gemiddel reaktie snelheid >= "warn" en 2 als die snelheid >= "crit", anders geef 0 terug. Nagios mode 2: geef 0 terug als alles goed ging, anders 'x'.
85 .TP
86 .B "\-n warn,crit"
87 Schakelt HTTPing naar Nagios-plugin mode 1. Geef afsluit code 1 als de gemiddelde response tijd groter is dan 'warn', geef 2 terug als die tijd groter is dan 'crit'. Anders 0.
88 .TP
89 .B "\-o x,x,..."
90 Selecteer de HTTP status-codes die als 'ok' beschouwd worden.
91 .TP
92 .B "\-p portnumber"
93 Gebruik dit on combinatie met h. Het zet het port-nummer om te pingen.
94 .TP
95 .B "\-q"
96 Geef geen uitvoer, alleen een teruggave code.
97 .TP
98 .B "\-R str"
99 Welke "Referer" te zenden naar de webserver.
100 .TP
101 .B "\-r"
102 Eenmalig systeemnaam vertalen (dit is zinvol bij het pingen van een roterende DNS, bovendien haalt het de eerste vertaling uit de ping lus zodat de 1e ping niet een bovengemiddelde tijd duurt).
103 .TP
104 .B "\-S"
105 Toon alle individuele componenten (verbinden, zenden, etc) van de gemeten tijden.
106 .TP
107 .B "\-s"
108 Toon de HTTP statuscodes.
109 .TP
110 .B "\-T x"
111 Lees de toegangscode voor website authenticatie uit bestand 'x'.
112 .TP
113 .B "\-t timeout"
114 Hoelang te wachten op een reactie van de webserver.
115 .TP
116 .B "\-U"
117 Gebruik authenticatie bij toegang tot de website. Combineer dit met \-P of \-T.
118 .TP
119 .B "\-v"
120 Toon meer details.
121 .TP
122 .B "\-W"
123 Stop HTTPing niet als het opzoeken van de server naam niet lukt.
124 .TP
125 .B "\-X"
126 Gebruik deze in combinatie met \-G. Toon hoeveel data er ontvangen werd.
127 .TP
128 .B "\-x proxyhost[:port]
129 Gebruik een proxy server om een verbinding op te zetten.
130 .TP
131 .B "\-Y"
132 Gebruik kleuren.
133 .TP
134 .B "\-z"
135 Toon de vingerafdruk van de X.509 certificaten bij het opzetten van een SSL verbinding.
136 .TP
137 .B "\-\-abbreviate"
138 Kort waardes af wanneer ze groter zijn dan 1000/1000000/etc.
139 .TP
140 .B "\-\-adaptive-interval" or "\-\-ai"
141 Zorg ervoor dat pings steeds met dezelfde interval uitgevoerd worden, relatief tot het start tijdstip. deze instelling wordt automatisch aangezet in "ncurses"\-mode.
142 .TP
143 .B "\-\-aggregates x[,y[,z[,etc.]]]"
144 Toon cumulatief de waardes van x[/y[/etc]] seconden.
145 .TP
146 .B "\-\-divert\-connect x"
147 Gebruik niet de systeemnaam uit de URL om naar te verbinden. Verbind naar 'x'.
148 .TP
149 .B "\-\-draw-phase"
150 Toon fase diagram.
151 .TP
152 .B "\-\-graph\-limit x"
153 Bij het bepalen van de grafiek-bandbreedte: negeer waardes hoger dan x.
154 .TP
155 .B "\-\-header x"
156 Voeg een extra verzoek-regel toe.
157 .TP
158 .B "\-\-keep\-cookies"
159 Als de HTTP server cookies geeft, zend die dan mee terug bij volgende pings.
160 .TP
161 .B "\-\-max\-mtu x"
162 Welke MTU te gebruiken. Kan niet groter zijn dan de MTU van de netwerk adapter.
163 .TP
164 .B "\-\-no\-host\-header"
165 Voeg niet een "Host:"\-regel toe aan het verzoek.
166 .TP
167 .B "\-\-no\-tcp\-nodelay"
168 Zet het Naggle-algorithme niet uit.
169 .TP
170 .B "\-\-priority x"
171 Geef packets een bepaalde prioriteit.
172 .TP
173 .B "\-\-tos x"
174 Configureer de TOS.
175 .TP
176 .B "\-\-proxy\-user x"
177 Gebruikersnaam voor proxy authenticatie.
178 .TP
179 .B "\-\-proxy\-password x"
180 Toegangscode voor proxy authenticatie.
181 .TP
182 .B "\-\-proxy\-password-file x"
183 Lees toegangscode voor proxy authenticatie uit bestand 'x'.
184 .TP
185 .B "\-\-recv-buffer x"
186 Configureer de grootte van de ontvangst buffer.
187 .TP
188 .B "\-\-slow\-log x"
189 Als een ping-tijd meer dan x is, toon het resultaat dan in het middelste venster.
190 .TP
191 .B "\-\-threshold\-red x"
192 Toon metingen in rood als de gemeten waarde meer dan x is.
193 .TP
194 .B "\-\-threshold\-yellow x"
195 Toon metingen in geel als de gemeten waarde meer dan x is.
196 .TP
197 .B "\-\-threshold\-show x"
198 Toon metingen alleen als ze hoger dan x zijn.
199 .TP
200 .B "\-\-timestamp" or "\-\-ts"
201 Voeg een een tijdstempel toe aan de uitvoer. Gebruik -v om ook een datum te zien en \-vv om ook microseconden te zien.
202 .TP
203 .B "\-\-tx-buffer x"
204 Configureer de grootte van de zend-buffer.
205 .TP
206 .B "\-V"
207 Toon versie informatie.
208
209 .SH UITVOER
210 In de -S mode zal iets als "tijd=0.08+24.09+23.17+15.64+0.02=62.98 ms" getoond worden. De eerste waarde is hoe lang het duurde om de systeem naam te vertalen, de 2e waarde hoe lang het duurde om te verbinden, de 3e waarde geeft aan hoe lang het duurde om het verzoek te verzenden en de 4e waarde is hoelang het duurde voordat de http-server een antwoord formuleerde en terugzond. de 5e waarde geeft aan hoelang het duurde om de socket te sluiten.
211
212 .SH GRAFIEK
213 De grafiek in ncurses mode gebruikt een aantal kleuren. Groen: de waarde is minder dan de ondergrens. Rood: de waarde is hoger dan de bovengrens. Blauw: de waarde is gelimiteerd door '--graph-limit'. Cyaan: er is geen meetwaarde.
214
215 .SH TOETSEN
216 Druk <CTRL> + <c> om het programma af te breken. Er zal dan een samenvatting getoond worden.
217 In ncurses mode: <CTRL> + <l> ververst het scherm, H stopt (en hervat) de grafieken en ook q zal het programma stoppen.
218
219 .SH VOORBEELDEN
220 .TP
221 .B "httping \-g http://localhost/"
222 Ping de HTTP server op URL http://localhost/
223 .TP
224 .B "httping \-h localhost \-p 1000"
225 Ping de HTTP server op systeem 'localhost' en port nummer 1000.
226 .TP
227
228 .SH BUGS
229 Geen.
230
231 .SH "ZIE OOK"
232 .BR http://www.vanheusden.com/httping/
233
234 .SH NOTITIES
235 Deze man-page beschrijft
236 .B httping
237 versie 2.3: andere versies kunnen iets of wat verschillen.
238 Stuur a.u.b. correcties, toevingen en foutraporten naar folkert@vanheusden.com
239 Wanneer u een donatie wilt doen, dan kunt u Bitcoins sturen naar: 1N5Sn4jny4xVwTwSYLnf7WnFQEGoVRmTQF
0 .\" Copyright Folkert van Heusden, 2003-2013
1 .\"
2 .\" This file may be copied under the conditions described
3 .\" in the GNU GENERAL PUBLIC LICENSE, version 2
4 .\" that can be found on the website of the free software
5 .\" foundation.
6 .\"
7 .TH HTTPING 1 2013-07 "httping"
8 .SH NAME
9 httping - measure the latency and throughput of a webserver
10 .SH SYNOPSIS
11 .BI "httping [" options "]
12 .sp
13 options:
14 .BI "[\-g url] [\-h hostname] [\-p portnumber] [\-x proxyhost:port] [\-c count] [\-i interval] [\-t timeout] [\-s] [\-G] [\-b] [\-L xferlimit] [\-X] [\-l] [\-z] [\-f] [\-m] [\-o rc,...] [\-e string]"
15 .BI "[\-I useragent string] [\-R referer string] [\-r] [\-n warn,crit] [\-N mode] [\-q] [\-V]"
16 .SH DESCRIPTION
17 The program
18 .B httping
19 lets you measure the latency of a webserver. Since version 1.0.6 also the throughput can be measured.
20 .PP
21 .SH OPTIONS
22 .TP
23 .B "\-5"
24 The proxy server selected is a SOCKS5 server.
25 .TP
26 .B "\-6"
27 Enable IPv6 mode. Default is IPv4.
28 .TP
29 .B "\-a"
30 Audible ping
31 .TP
32 .B "\-b"
33 Use this switch together with '\-G'. When this option is used, the transferspeed (in KB/s) is shown.
34 .TP
35 .B "\-B"
36 Use this switch together with '\-G'. Ask the HTTP server to compress the returned data: this will reduce the influence of the bandwidth of your connection while increasing the influence of the processorpower of the HTTP server.
37 .TP
38 .B "\-c count"
39 How many probes to send before exiting.
40 .TP
41 .B "\-D"
42 Do not draw graphs in ncurses mode (\-K).
43 .TP
44 .B "\-e str"
45 When the status-code differs from the ones selected with '\-o', the given string is displayed.
46 .TP
47 .B "\-E"
48 Retrieve proxy settings from environment variables ('http_proxy' and 'https_proxy').
49 .TP
50 .B "\-F"
51 Attempt TCP Fast Open while trying to connect to a server (for Linux, version 3.7 onwards of the kernel)
52 .TP
53 .B "\-f"
54 Flood ping: do not sit idle between each ping but ping as fast as the computer and network allow you to.
55 .TP
56 .B "\-G"
57 Do a GET request instead of a HEAD request: this means that also the complete page/file must be transferred. Note that in this case you're no longer measuring the latency!
58 .TP
59 .B "\-g url"
60 This selects the url to probe. E.g.: http://localhost/
61 .TP
62 .B "\-h hostname"
63 Instead of '\-g' one can also set a hostname to probe with -h: -h localhost
64 .TP
65 .B "\-I str"
66 UserAgent-string to send to the webserver (instead of 'HTTPing <version>').
67 .TP
68 .B "\-i interval"
69 How many seconds to sleep between every probe sent.
70 .TP
71 .B "\-K"
72 Enable ncurses user interface.
73 .TP
74 .B "\-L x"
75 Use this switch together with '\-G'. Limit the amount of data transferred to 'x'. Note that this only affects the content of the page/file and not the headerdata.
76 .TP
77 .B "\-l"
78 Connect using SSL: for this to work you need to give a 'https'-url or a 443 portnumber.
79 .TP
80 .B "\-m"
81 Show machine readable output (also check '\-o' and '\-e').
82 .TP
83 .B "\-N x"
84 Switches HTTPing to Nagios-plugin mode 2: return 0 when everything is fine, 'x' when anything fails. E.g.: 1 => Nagios warning state, 2 => Nagios critical state.
85 .TP
86 .B "\-n warn,crit"
87 Switches HTTPing to Nagios-plugin mode 1: return exitcode '1' when the average response time is bigger then 'warn', return exitcode '2' when the the average response time is bigger then 'crit'. In all other cases return exitcode '0'.
88 .TP
89 .B "\-o x,x,..."
90 This selects the HTTP status-codes which are regarded as an OK-state (only with '\-m').
91 .TP
92 .B "\-p portnumber"
93 -p can be used together with \-h. \-p selects the portnumber to probe.
94 .TP
95 .B "\-q"
96 Be quiet, only return an exit-code.
97 .TP
98 .B "\-R str"
99 Referer-string to send to the webserver.
100 .TP
101 .B "\-r"
102 Only resolve the hostname once: this takes the resolving out of the loop so that the latency of the DNS is not measured. Also useful when you want to measure only 1 webserver while the DNS returns a different ip-address for each resolve ('roundrobin').
103 .TP
104 .B "\-S"
105 Split measured latency in time to connect and time to exchange a request with the HTTP server.
106 .TP
107 .B "\-s"
108 When a successfull transaction was done, show the HTTP statuscode (200, 404, etc.).
109 .TP
110 .B "\-T x"
111 Read the password for website authentication from file 'x' (instead of entering it on the command line).
112 .TP
113 .B "\-t timeout"
114 How long to wait for answer from the other side.
115 .TP
116 .B "\-U"
117 Enable authentication against website. Set username with \-U, set password with \-P (or \-T to read the password from a file).
118 .TP
119 .B "\-v"
120 Increase verbosity mode. To show standard deviation and dates in output.
121 .TP
122 .B "\-W"
123 Do not abort program if resolving fails.
124 .TP
125 .B "\-X"
126 Use this switch together with '-G'. For each "ping" show the amount of data transferred (excluding the headers).
127 .TP
128 .B "\-x proxyhost[:port]
129 Probe using a proxyserver. Note that you're also measuring the latency of the proxyserver!
130 .TP
131 .B "\-Y"
132 Enable colors
133 .TP
134 .B "\-z"
135 When connecting using SSL, display the fingerprint of the X509 certificate(s) of the peer.
136 .TP
137 .B "\-\-abbreviate"
138 Abbreviate values bigger than thousand, million, billion, etc.
139 .TP
140 .B "\-\-adaptive-interval" or "\-\-ai"
141 (Try to) ping on the same interval. E.g. if interval is set to 1.0 seconds and ping a ping t[n] occurs at 500s with duration 250ms, then the next ping (t[n+1]) will happen at 501 seconds and not at 501.25 seconds. Of course when the ping duration is > bigger than the interval, a ping will be "skipped" (not literally: the sequence number will continue) and t[n+1] will then be e.g. 502s instead of the expected 501s. This is useful for example in the ncurses output mode where an fft is calculated over the ping times.
142 .TP
143 .B "\-\-aggregates x[,y[,z[,etc.]]]"
144 Show aggregates every x[/y[/z[/etc]]] seconds.
145 .TP
146 .B "\-\-divert\-connect x"
147 Ignore the hostname in the URL and connect to 'x' instead. The given URL will be requested at 'x'.
148 .TP
149 .B "\-\-draw-phase"
150 Not only draw the magnitude of the fourier transform, draw the phase as well.
151 .TP
152 .B "\-\-graph\-limit x"
153 If values measured are bigger than x, then they're limitted to x.
154 .TP
155 .B "\-\-header x"
156 Add an additional request-header 'x'.
157 .TP
158 .B "\-\-keep\-cookies"
159 When the server sends a cookie, it will be returned in the next request.
160 .TP
161 .B "\-\-max\-mtu x"
162 Maximum MTU to use. Cannot be larger than network interface MTU.
163 .TP
164 .B "\-\-no\-host\-header"
165 Do not put a "Host:"-header in the request header.
166 .TP
167 .B "\-\-no\-tcp\-nodelay"
168 Do not disable "tcp delay" (Naggle).
169 .TP
170 .B "\-\-priority x"
171 Set priority of packets.
172 .TP
173 .B "\-\-tos x"
174 Set type of service.
175 .TP
176 .B "\-\-proxy\-user x"
177 Use username 'x' to authenticate against proxy (http/socks5) server (optional).
178 .TP
179 .B "\-\-proxy\-password x"
180 Use password 'x' to authenticate against proxy (http/socks5) server (optional).
181 .TP
182 .B "\-\-proxy\-password-file x"
183 Read password from file 'x' to authenticate against proxy (http/socks5) server (optional).
184 .TP
185 .B "\-\-recv-buffer x"
186 Set the size of the receive buffer (in bytes).
187 .TP
188 .B "\-\-slow\-log x"
189 When the duration is x or more, show ping line in the slow log window (the middle window).
190 .TP
191 .B "\-\-threshold\-red x"
192 If the measured threshold is higher than x (and -Y is given), then the shown value is colored red. If you also use --threshold-yellow, then this value must be bigger.
193 .TP
194 .B "\-\-threshold\-yellow x"
195 If the measured threshold is higher than x (and -Y is given), then the shown value is colored yellow.
196 .TP
197 .B "\-\-threshold\-show x"
198 If the measured threshold is higher than x, then the result is shown (default is show always). The value x is in ms.
199 .TP
200 .B "\-\-timestamp" or "\-\-ts"
201 Put a timestamp before the result-lines. Use -v to also show a date.
202 .TP
203 .B "\-\-tx-buffer x"
204 Set the size of the transmit buffer (in bytes).
205 .TP
206 .B "\-V"
207 Show the version and exit.
208
209 .SH OUTPUT
210 In split mode (-S) something like "time=0.08+24.09+23.17+15.64+0.02=62.98 ms" is shown. The first value is the time it took to resolve the hostname (or 'n/a' if it did not resolve in this iteration, e.g. in "resolve once" (-r) mode), then the time it took to connect (or -1 for example in persistent connection (-Q, HTTP v1.1), after that the time it took to put the request on the wire, then the time it took for the HTTP server to process the request and send it back and lastly the time it took to close the connection.
211
212 .SH GRAPH
213 The graph in the ncurses uses colors to encode a meaning. Green: value is less than 1 block. Red: the value did not fit in the graph. Blue: the value was limitted by --graph-limit. Cyan: no measurement for that point in time.
214
215 .SH KEYS
216 Press <CTRL> + <c> to exit the program. It will display a summary of what was measured.
217 In the ncurses gui, press <CTRL> + <l> to forcibly redraw the screen. Press 'H' to halt the graphs (and again to continue). Press 'q' to stop the program (<CTRL> + <c> will work too).
218
219 .SH EXAMPLES
220 .TP
221 .B "httping \-g http://localhost/"
222 Ping the webserver on host 'localhost'.
223 .TP
224 .B "httping \-h localhost \-p 1000"
225 Ping the webserver on host 'localhost' and portnumber 1000.
226 .TP
227 .B "httping \-l \-g https://localhost/"
228 Ping the webserver on host 'localhost' using an SSL connection.
229 .TP
230 .B "httping \-g http://localhost/ -U username -P password"
231 Ping the webserver on host 'localhost' using the Basic HTTP Authentication.
232 .SH BUGS
233 None. This program is totally bug-free.
234
235 .SH "SEE ALSO"
236 .BR http://www.vanheusden.com/httping/
237
238 .SH NOTES
239 This page describes
240 .B httping
241 as found in the httping-2.3 package; other versions may differ slightly.
242 Please mail corrections and additions to folkert@vanheusden.com.
243 Report bugs in the program to folkert@vanheusden.com.
244 Please consider sending bitcoins to 1N5Sn4jny4xVwTwSYLnf7WnFQEGoVRmTQF
+193
-0
io.c less more
0 /* Released under GPLv2 with exception for the OpenSSL library. See license.txt */
1 /* $Revision$ */
2
3 #include <errno.h>
4 #include <libintl.h>
5 #include <fcntl.h>
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <string.h>
9 #include <syslog.h>
10 #include <sys/time.h>
11 #include <sys/types.h>
12 #include <sys/stat.h>
13 #include <unistd.h>
14
15 #include "gen.h"
16 #include "error.h"
17
18 ssize_t read_to(int fd, char *whereto, size_t len, double timeout)
19 {
20 for(;;)
21 {
22 ssize_t rc;
23 struct timeval to;
24 fd_set rfds;
25
26 FD_ZERO(&rfds);
27 FD_SET(fd, &rfds);
28
29 to.tv_sec = (long)(timeout / 1000.0);
30 to.tv_usec = (long)(timeout * 1000.0) % 1000000;
31
32 rc = select(fd + 1, &rfds, NULL, NULL, &to);
33 if (rc == 0)
34 return RC_TIMEOUT;
35 else if (rc == -1)
36 {
37 if (errno == EAGAIN)
38 continue;
39 if (errno == EINTR)
40 return RC_CTRLC;
41
42 set_error(gettext("myread::select failed: %s"), strerror(errno));
43
44 return RC_SHORTREAD;
45 }
46
47 return read(fd, whereto, len);
48 }
49 }
50
51 ssize_t myread(int fd, char *whereto, size_t len, double timeout)
52 {
53 ssize_t cnt=0;
54
55 while(len>0)
56 {
57 ssize_t rc;
58 struct timeval to;
59 fd_set rfds;
60
61 FD_ZERO(&rfds);
62 FD_SET(fd, &rfds);
63
64 to.tv_sec = (long)(timeout / 1000.0);
65 to.tv_usec = (long)(timeout * 1000.0) % 1000000;
66
67 rc = select(fd + 1, &rfds, NULL, NULL, &to);
68 if (rc == 0)
69 return RC_TIMEOUT;
70 else if (rc == -1)
71 {
72 if (errno == EAGAIN)
73 continue;
74 if (errno == EINTR)
75 return RC_CTRLC;
76
77 set_error(gettext("myread::select failed: %s"), strerror(errno));
78
79 return RC_SHORTREAD;
80 }
81
82 if (FD_ISSET(fd, &rfds))
83 {
84 rc = read(fd, whereto, len);
85
86 if (rc == -1)
87 {
88 if (errno == EAGAIN)
89 continue;
90 if (errno == EINTR)
91 return RC_CTRLC;
92
93 set_error(gettext("myread::read failed: %s"), strerror(errno));
94
95 return RC_SHORTREAD;
96 }
97 else if (rc == 0)
98 break;
99 else
100 {
101 whereto += rc;
102 len -= rc;
103 cnt += rc;
104 }
105 }
106 }
107
108 return cnt;
109 }
110
111 ssize_t mywrite(int fd, char *wherefrom, size_t len, double timeout)
112 {
113 ssize_t cnt=0;
114
115 while(len>0)
116 {
117 ssize_t rc;
118 struct timeval to;
119 fd_set wfds;
120
121 FD_ZERO(&wfds);
122 FD_SET(fd, &wfds);
123
124 to.tv_sec = (long)(timeout / 1000.0);
125 to.tv_usec = (long)(timeout * 1000.0) % 1000000;
126
127 rc = select(fd + 1, NULL, &wfds, NULL, &to);
128 if (rc == 0)
129 return RC_TIMEOUT;
130 else if (rc == -1)
131 {
132 if (errno == EAGAIN)
133 continue;
134 if (errno == EINTR)
135 return RC_CTRLC;
136
137 set_error(gettext("mywrite::select failed: %s"), strerror(errno));
138
139 return RC_SHORTWRITE;
140 }
141
142 rc = write(fd, wherefrom, len);
143
144 if (rc == -1)
145 {
146 if (errno == EAGAIN)
147 continue;
148 if (errno == EINTR)
149 return RC_CTRLC;
150
151 set_error(gettext("mywrite::write failed: %s"), strerror(errno));
152
153 return RC_SHORTWRITE;
154 }
155 else if (rc == 0)
156 break;
157 else
158 {
159 wherefrom += rc;
160 len -= rc;
161 cnt += rc;
162 }
163 }
164
165 return cnt;
166 }
167
168 int set_fd_nonblocking(int fd)
169 {
170 /* set fd to non-blocking */
171 if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1)
172 {
173 fprintf(stderr, gettext("set_fd_nonblocking failed! (%s)\n"), strerror(errno));
174
175 return -1;
176 }
177
178 return 0;
179 }
180
181 int set_fd_blocking(int fd)
182 {
183 /* set fd to blocking */
184 if (fcntl(fd, F_SETFL, 0) == -1)
185 {
186 fprintf(stderr, gettext("set_fd_blocking failed! (%s)\n"), strerror(errno));
187
188 return -1;
189 }
190
191 return 0;
192 }
0 /* Released under GPLv2 with exception for the OpenSSL library. See license.txt */
1 /* $Revision$ */
2
3 ssize_t read_to(int fd, char *whereto, size_t len, double timeout);
4 ssize_t myread(int fd, char *whereto, size_t len, double timeout);
5 ssize_t mywrite(int fd, const char *wherefrom, size_t len, double timeout);
6 int set_fd_nonblocking(int fd);
7 int set_fd_blocking(int fd);
0 /* #define _TEST */
1
2 #include <math.h>
3 #ifdef _TEST
4 #include <stdio.h>
5 #include <stdlib.h>
6 #endif
7
8 double x_est_last = 0.0, P_last = 0.0, Q = 0.0, R = 0.0, K = 0.0, P = 0.0, P_temp = 0.0, x_temp_est = 0.0, x_est = 0.0, z_measured = 0.0, z_real = 0.0, sum_error_kalman = 0.0, sum_error_measure = 0.0;
9 char first = 1;
10
11 void kalman_init(double ideal_value)
12 {
13 /* initial values for the kalman filter */
14 x_est_last = 0;
15 P_last = 0;
16 /* the noise in the system (FIXME?) */
17 Q = 0.022;
18 R = 0.617;
19 z_real = ideal_value; /* 0.5; the ideal value we wish to measure */
20
21 first = 1;
22 }
23
24 double kalman_do(double z_measured)
25 {
26 /* initialize with a measurement */
27 if (first)
28 {
29 first = 0;
30 x_est_last = z_measured;
31 }
32
33 /* do a prediction */
34 x_temp_est = x_est_last;
35 P_temp = P_last + Q;
36 /* calculate the Kalman gain */
37 K = P_temp * (1.0/(P_temp + R));
38 /* measure */
39 /*z_measured = z_real + frand()*0.09; the real measurement plus noise*/
40 /* correct */
41 x_est = x_temp_est + K * (z_measured - x_temp_est);
42 P = (1- K) * P_temp;
43 /* we have our new system */
44
45 #ifdef _TEST
46 printf("Ideal position: %6.3f \n",z_real);
47 printf("Mesaured position: %6.3f [diff:%.3f]\n",z_measured,fabs(z_real-z_measured));
48 printf("Kalman position: %6.3f [diff:%.3f]\n",x_est,fabs(z_real - x_est));
49 #endif
50
51 sum_error_kalman += fabs(z_real - x_est);
52 sum_error_measure += fabs(z_real-z_measured);
53
54 /* update our last's */
55 P_last = P;
56 x_est_last = x_est;
57
58 #ifdef _TEST
59 printf("Total error if using raw measured: %f\n",sum_error_measure);
60 printf("Total error if using kalman filter: %f\n",sum_error_kalman);
61 printf("Reduction in error: %d%% \n",100-(int)((sum_error_kalman/sum_error_measure)*100));
62 #endif
63
64 return x_est;
65 }
66
67 #ifdef _TEST
68 int main(int argc, char *argv[])
69 {
70 kalman_init(0.0);
71
72 for(int loop=0; loop<25; loop++)
73 {
74 double v = drand48();
75 printf("%d] %f %f\n", loop + 1, v, kalman_do(v));
76 }
77
78 return 0;
79 }
80 #endif
0 /* taken (and adapted) from http://www.dzone.com/snippets/simple-kalman-filter-c */
1
2 void kalman_init(double ideal_value);
3 double kalman_do(double value);
0 Please see license.txt.
0 HTTPing is (C) 2003-2013 by folkert@vanheusden.com
1
2 The GPL version 2 applies to this program. That document can be found
3 on the website of the free software foundation.
4
5 In addition, as a special exception, the copyright holder gives
6 permission to link the code of portions of this program with the
7 OpenSSL library under certain conditions as described in each
8 individual source file, and distribute linked combinations
9 including the two.
10 You must obey the GNU General Public License in all respects
11 for all of the code used other than OpenSSL. If you modify
12 file(s) with this exception, you may extend this exception to your
13 version of the file(s), but you are not obligated to do so. If you
14 do not wish to do so, delete this exception statement from your
15 version. If you delete this exception statement from all source
16 files in the program, then also delete it here.
+2442
-0
main.c less more
0 /* Released under GPLv2 with exception for the OpenSSL library. See license.txt */
1 /* $Revision: 278 $ */
2
3 #define _GNU_SOURCE
4 #include <sys/ioctl.h>
5 #include <stdio.h>
6 #include <locale.h>
7 #include <libintl.h>
8 #include <stdlib.h>
9 #include <errno.h>
10 #include <math.h>
11 #include <string.h>
12 #include <signal.h>
13 #include <unistd.h>
14 #include <getopt.h>
15 #include <sys/types.h>
16 #include <sys/socket.h>
17 #include <sys/ioctl.h>
18 #include <netinet/in.h>
19 #include <netinet/tcp.h>
20 #include <netdb.h>
21 #ifndef NO_SSL
22 #include <openssl/ssl.h>
23 #include "mssl.h"
24 #endif
25 #include <arpa/inet.h>
26 #include <time.h>
27 #include <sys/time.h>
28 #if defined(sun) || defined(__sun)
29 #include <sys/termios.h>
30 #endif
31 #ifdef NC
32 #include <ncurses.h>
33 #endif
34
35 #include "gen.h"
36 #include "help.h"
37 #include "colors.h"
38 #include "http.h"
39 #include "io.h"
40 #include "tcp.h"
41 #include "res.h"
42 #include "utils.h"
43 #include "error.h"
44 #include "socks5.h"
45 #ifdef NC
46 #include "nc.h"
47 #endif
48 #include "cookies.h"
49
50 volatile int stop = 0;
51
52 int quiet = 0;
53 char machine_readable = 0;
54 char json_output = 0;
55 char show_ts = 0;
56
57 int max_x = 80, max_y = 24;
58
59 char nagios_mode = 0;
60 char ncurses_mode = 0;
61
62 int fd = -1;
63
64 volatile char got_sigquit = 0;
65
66 void handler_quit(int s)
67 {
68 signal(SIGQUIT, handler_quit);
69
70 got_sigquit = 1;
71 }
72
73 void determine_terminal_size(int *max_y, int *max_x)
74 {
75 struct winsize size;
76
77 *max_x = *max_y = 0;
78
79 if (!isatty(1))
80 {
81 *max_y = 24;
82 *max_x = 80;
83 }
84 #ifdef TIOCGWINSZ
85 else if (ioctl(1, TIOCGWINSZ, &size) == 0)
86 {
87 *max_y = size.ws_row;
88 *max_x = size.ws_col;
89 }
90 #endif
91
92 if (!*max_x || !*max_y)
93 {
94 char *dummy = getenv("COLUMNS");
95 if (dummy)
96 *max_x = atoi(dummy);
97 else
98 *max_x = 80;
99
100 dummy = getenv("LINES");
101 if (dummy)
102 *max_y = atoi(dummy);
103 else
104 *max_y = 24;
105 }
106 }
107
108 void emit_statuslines(double run_time)
109 {
110 #ifdef NC
111 if (ncurses_mode)
112 {
113 time_t t = time(NULL);
114 char *t_str = ctime(&t);
115 char *dummy = strchr(t_str, '\n');
116
117 if (dummy)
118 *dummy = 0x00;
119
120 status_line(gettext("%s, run time: %.3fs, press ctrl + c to stop"), t_str, run_time);
121 }
122 #else
123 (void)run_time;
124 #endif
125 }
126
127 void emit_headers(char *in)
128 {
129 #ifdef NC
130 static char shown = 0;
131 int len_in = -1;
132
133 if (!shown && ncurses_mode && in != NULL && (len_in = strlen(in) - 4) > 0)
134 {
135 int pos = 0, pos_out = 0;
136 char *copy = (char *)malloc(len_in + 1), *dummy = NULL;
137
138 for(pos=0; pos<len_in; pos++)
139 {
140 if (in[pos] != '\r')
141 copy[pos_out++] = in[pos];
142 }
143
144 copy[pos_out] = 0x00;
145
146 /* in case more than the headers were sent */
147 dummy = strstr(copy, "\n\n");
148 if (dummy)
149 *dummy = 0x00;
150
151 slow_log("\n%s", copy);
152
153 free(copy);
154
155 shown = 1;
156 }
157 #else
158 (void)in;
159 #endif
160 }
161
162 void emit_json(char ok, int seq, double start_ts, stats_t *t_resolve, stats_t *t_connect, stats_t *t_request, int http_code, const char *msg, int header_size, int data_size, double Bps, const char *host, const char *ssl_fp, double toff_diff_ts, char tfo_success, stats_t *t_ssl, stats_t *t_write, stats_t *t_close, int n_cookies, stats_t *stats_to, stats_t *tcp_rtt_stats, int re_tx, int pmtu, int recv_tos, stats_t *t_total)
163 {
164 if (seq > 1)
165 printf(", \n");
166 printf("{ ");
167 printf("\"status\" : \"%d\", ", ok);
168 printf("\"seq\" : \"%d\", ", seq);
169 printf("\"start_ts\" : \"%f\", ", start_ts);
170 if (t_resolve!=NULL && t_resolve -> cur_valid)
171 printf("\"resolve_ms\" : \"%e\", ", t_resolve -> cur);
172 else
173 printf("\"resolve_ms\" : \"%e\", ",-1.0);
174 if (t_connect!=NULL && t_connect -> cur_valid)
175 printf("\"connect_ms\" : \"%e\", ", t_connect -> cur);
176 else
177 printf("\"connect_ms\" : \"%e\", ",-1.0);
178 printf("\"request_ms\" : \"%e\", ", t_request -> cur);
179 printf("\"total_ms\" : \"%e\", ", t_total -> cur);
180 printf("\"http_code\" : \"%d\", ", http_code);
181 printf("\"msg\" : \"%s\", ", msg);
182 printf("\"header_size\" : \"%d\", ", header_size);
183 printf("\"data_size\" : \"%d\", ", data_size);
184 printf("\"bps\" : \"%f\", ", Bps);
185 printf("\"host\" : \"%s\", ", host);
186 printf("\"ssl_fingerprint\" : \"%s\", ", ssl_fp ? ssl_fp : "");
187 printf("\"time_offset\" : \"%f\", ", toff_diff_ts);
188 printf("\"tfo_success\" : \"%s\", ", tfo_success ? "true" : "false");
189 if (t_ssl -> cur_valid)
190 printf("\"ssl_ms\" : \"%e\", ", t_ssl -> cur);
191 printf("\"tfo_succes\" : \"%s\", ", tfo_success ? "true" : "false");
192 if (t_ssl !=NULL && t_ssl -> cur_valid)
193 printf("\"ssl_ms\" : \"%e\", ", t_ssl -> cur);
194 printf("\"write\" : \"%e\", ", t_write -> cur);
195 printf("\"close\" : \"%e\", ", t_close -> cur);
196 printf("\"cookies\" : \"%d\", ", n_cookies);
197 if (stats_to != NULL && stats_to -> cur_valid)
198 printf("\"to\" : \"%e\", ", stats_to -> cur);
199 if (tcp_rtt_stats !=NULL && tcp_rtt_stats -> cur_valid)
200 printf("\"tcp_rtt_stats\" : \"%e\", ", tcp_rtt_stats -> cur);
201 printf("\"re_tx\" : \"%d\", ", re_tx);
202 printf("\"pmtu\" : \"%d\", ", pmtu);
203 printf("\"tos\" : \"%02x\" ", recv_tos);
204 printf("}");
205 }
206
207 char *get_ts_str(int verbose)
208 {
209 char buffer[4096] = { 0 };
210 struct tm *tvm = NULL;
211 struct timeval tv;
212
213 (void)gettimeofday(&tv, NULL);
214
215 tvm = localtime(&tv.tv_sec);
216
217 if (verbose == 1)
218 sprintf(buffer, "%04d/%02d/%02d ", tvm -> tm_year + 1900, tvm -> tm_mon + 1, tvm -> tm_mday);
219 else if (verbose >= 2)
220 sprintf(buffer, "%.6f", get_ts());
221
222 if (verbose <= 1)
223 sprintf(&buffer[strlen(buffer)], "%02d:%02d:%02d.%03d", tvm -> tm_hour, tvm -> tm_min, tvm -> tm_sec, (int)(tv.tv_usec / 1000));
224
225 return strdup(buffer);
226 }
227
228 void emit_error(int verbose, int seq, double start_ts)
229 {
230 char *ts = show_ts ? get_ts_str(verbose) : NULL;
231
232 #ifdef NC
233 if (ncurses_mode)
234 {
235 slow_log("\n%s%s", ts ? ts : "", get_error());
236 update_terminal();
237 }
238 else
239 #endif
240 if (!quiet && !machine_readable && !nagios_mode && !json_output)
241 printf("%s%s%s%s\n", ts ? ts : "", c_error, get_error(), c_normal);
242
243 if (json_output)
244 emit_json(0, seq, start_ts, NULL, NULL, NULL, -1, get_error(), -1, -1, -1, "", "", -1, 0, NULL, NULL, NULL, 0, NULL, NULL, 0, 0, 0, NULL);
245
246 clear_error();
247
248 free(ts);
249
250 fflush(NULL);
251 }
252
253 void handler(int sig)
254 {
255 #ifdef NC
256 if (sig == SIGWINCH)
257 win_resize = 1;
258 else
259 #endif
260 {
261 if (!json_output)
262 fprintf(stderr, gettext("Got signal %d\n"), sig);
263
264 stop = 1;
265 }
266 }
267
268 char * read_file(const char *file)
269 {
270 char buffer[4096] = { 0 }, *lf = NULL;
271 FILE *fh = fopen(file, "rb");
272 if (!fh)
273 error_exit(gettext("Cannot open password-file %s"), file);
274
275 if (!fgets(buffer, sizeof buffer, fh))
276 error_exit(gettext("Problem reading password from file %s"), file);
277
278 fclose(fh);
279
280 lf = strchr(buffer, '\n');
281 if (lf)
282 *lf = 0x00;
283
284 return strdup(buffer);
285 }
286
287 char * create_http_request_header(const char *get, char use_proxy_host, char get_instead_of_head, char persistent_connections, const char *hostname, const char *useragent, const char *referer, char ask_compression, char no_cache, const char *auth_usr, const char *auth_password, char **static_cookies, int n_static_cookies, char **dynamic_cookies, int n_dynamic_cookies, const char *proxy_buster, const char *proxy_user, const char *proxy_password, char **additional_headers, int n_additional_headers)
288 {
289 int index;
290 char *request = NULL;
291 char pb[128] = { 0 };
292
293 if (proxy_buster)
294 {
295 if (strchr(get, '?'))
296 pb[0] = '&';
297 else
298 pb[0] = '?';
299
300 snprintf(pb + 1, sizeof pb - 1, "%s=%ld", proxy_buster, lrand48());
301 }
302
303 if (use_proxy_host)
304 str_add(&request, "%s %s%s HTTP/1.%c\r\n", get_instead_of_head?"GET":"HEAD", get, pb, persistent_connections?'1':'0');
305 else
306 {
307 const char *dummy = get, *slash = NULL;
308 if (strncasecmp(dummy, "http://", 7) == 0)
309 dummy += 7;
310 else if (strncasecmp(dummy, "https://", 7) == 0)
311 dummy += 8;
312
313 slash = strchr(dummy, '/');
314 if (slash)
315 str_add(&request, "%s %s HTTP/1.%c\r\n", get_instead_of_head?"GET":"HEAD", slash, persistent_connections?'1':'0');
316 else
317 str_add(&request, "%s / HTTP/1.%c\r\n", get_instead_of_head?"GET":"HEAD", persistent_connections?'1':'0');
318 }
319
320 if (hostname)
321 str_add(&request, "Host: %s\r\n", hostname);
322
323 if (useragent)
324 str_add(&request, "User-Agent: %s\r\n", useragent);
325 else
326 str_add(&request, "User-Agent: HTTPing v" VERSION "\r\n");
327
328 if (referer)
329 str_add(&request, "Referer: %s\r\n", referer);
330
331 if (ask_compression)
332 str_add(&request, "Accept-Encoding: gzip,deflate\r\n");
333
334 if (no_cache)
335 {
336 str_add(&request, "Pragma: no-cache\r\n");
337 str_add(&request, "Cache-Control: no-cache\r\n");
338 }
339
340 /* Basic Authentification */
341 if (auth_usr)
342 {
343 char auth_string[256] = { 0 };
344 char b64_auth_string[512] = { 0 };
345
346 sprintf(auth_string, "%s:%s", auth_usr, auth_password);
347 enc_b64(auth_string, strlen(auth_string), b64_auth_string);
348
349 str_add(&request, "Authorization: Basic %s\r\n", b64_auth_string);
350 }
351
352 /* proxy authentication */
353 if (proxy_user)
354 {
355 char ppa_string[256] = { 0 };
356 char b64_ppa_string[512] = { 0 };
357
358 sprintf(ppa_string, "%s:%s", proxy_user, proxy_password);
359 enc_b64(ppa_string, strlen(ppa_string), b64_ppa_string);
360
361 str_add(&request, "Proxy-Authorization: Basic %s\r\n", b64_ppa_string);
362 }
363
364 /* Cookie insertion */
365 for(index=0; index<n_static_cookies; index++)
366 str_add(&request, "Cookie: %s\r\n", static_cookies[index]);
367 for(index=0; index<n_dynamic_cookies; index++)
368 str_add(&request, "Cookie: %s\r\n", dynamic_cookies[index]);
369
370 for(index=0; index<n_additional_headers; index++)
371 str_add(&request, "%s\r\n", additional_headers[index]);
372
373 if (persistent_connections)
374 str_add(&request, "Connection: keep-alive\r\n");
375
376 str_add(&request, "\r\n");
377
378 return request;
379 }
380
381 void interpret_url(const char *in, char **path, char **hostname, int *portnr, char use_ipv6, char use_ssl, char **complete_url, char **auth_user, char **auth_password)
382 {
383 char in_use[65536] = { 0 }, *dummy = NULL;
384
385 if (strlen(in) >= sizeof in_use)
386 error_exit(gettext("URL too big, HTTPing has a %d bytes limit"), sizeof in_use - 1);
387
388 /* make url complete, if not already */
389 if (strncasecmp(in, "http://", 7) == 0 || strncasecmp(in, "https://", 8) == 0) /* complete url? */
390 {
391 snprintf(in_use, sizeof in_use - 1, "%s", in);
392
393 if (strchr(&in[8], '/') == NULL)
394 in_use[strlen(in_use)] = '/';
395 }
396 else if (strchr(in, '/')) /* hostname + location without 'http://'? */
397 sprintf(in_use, "http://%s", in);
398 else if (use_ssl)
399 sprintf(in_use, "https://%s/", in);
400 else
401 sprintf(in_use, "http://%s/", in);
402
403 /* sanity check */
404 if (strncasecmp(in_use, "http://", 7) == 0 && use_ssl)
405 error_exit(gettext("using \"http://\" with SSL enabled (-l)"));
406
407 *complete_url = strdup(in_use);
408
409 /* fetch hostname */
410 if (strncasecmp(in_use, "http://", 7) == 0)
411 *hostname = strdup(&in_use[7]);
412 else /* https */
413 *hostname = strdup(&in_use[8]);
414
415 dummy = strchr(*hostname, '/');
416 if (dummy)
417 *dummy = 0x00;
418
419 /* fetch port number */
420 if (use_ssl || strncasecmp(in, "https://", 8) == 0)
421 *portnr = 443;
422 else
423 *portnr = 80;
424
425 if (!use_ipv6)
426 {
427 char *at = strchr(*hostname, '@');
428 char *colon = strchr(*hostname, ':');
429 char *colon2 = colon ? strchr(colon + 1, ':') : NULL;
430
431 if (colon2)
432 {
433 *colon2 = 0x00;
434 *portnr = atoi(colon2 + 1);
435
436 if (at)
437 {
438 *colon = 0x00;
439 *at = 0x00;
440
441 *auth_user = strdup(*hostname);
442 *auth_password = strdup(colon + 1);
443 }
444 }
445 else if (colon)
446 {
447 if (colon < at)
448 {
449 *colon = 0x00;
450 *at = 0x00;
451
452 *auth_user = strdup(*hostname);
453 *auth_password = strdup(colon + 1);
454 }
455 else if (at)
456 {
457 *at = 0x00;
458 *auth_user = strdup(*hostname);
459 }
460 else
461 {
462 *colon = 0x00;
463 *portnr = atoi(colon + 1);
464 }
465 }
466 }
467
468 /* fetch path */
469 dummy = strchr(&in_use[8], '/');
470 if (dummy)
471 *path = strdup(dummy);
472 else
473 *path = strdup("/");
474 }
475
476 typedef struct {
477 int interval, last_ts;
478 double value, sd, min, max;
479 int n_values;
480 } aggregate_t;
481
482 void set_aggregate(char *in, int *n_aggregates, aggregate_t **aggregates)
483 {
484 char *dummy = in;
485
486 *n_aggregates = 0;
487
488 for(;dummy;)
489 {
490 (*n_aggregates)++;
491
492 *aggregates = (aggregate_t *)realloc(*aggregates, *n_aggregates * sizeof(aggregate_t));
493
494 memset(&(*aggregates)[*n_aggregates - 1], 0x00, sizeof(aggregate_t));
495
496 (*aggregates)[*n_aggregates - 1].interval = atoi(dummy);
497 (*aggregates)[*n_aggregates - 1].max = -MY_DOUBLE_INF;
498 (*aggregates)[*n_aggregates - 1].min = MY_DOUBLE_INF;
499
500 dummy = strchr(dummy, ',');
501 if (dummy)
502 dummy++;
503 }
504 }
505
506 void do_aggregates(double cur_ms, int cur_ts, int n_aggregates, aggregate_t *aggregates, int verbose, char show_ts)
507 {
508 int index=0;
509
510 /* update measurements */
511 for(index=0; index<n_aggregates; index++)
512 {
513 aggregates[index].value += cur_ms;
514
515 if (cur_ms < aggregates[index].min)
516 aggregates[index].min = cur_ms;
517
518 if (cur_ms > aggregates[index].max)
519 aggregates[index].max = cur_ms;
520
521 aggregates[index].sd += cur_ms * cur_ms;
522
523 aggregates[index].n_values++;
524 }
525
526 /* emit */
527 for(index=0; index<n_aggregates && cur_ts > 0; index++)
528 {
529 aggregate_t *a = &aggregates[index];
530
531 if (cur_ts - a -> last_ts >= a -> interval)
532 {
533 char *line = NULL;
534 double avg = a -> n_values ? a -> value / (double)a -> n_values : -1.0;
535 char *ts = get_ts_str(verbose);
536
537 str_add(&line, "%s", show_ts ? ts : "");
538 free(ts);
539
540 str_add(&line, gettext("AGG[%d]: %d values, min/avg/max%s = %.1f/%.1f/%.1f"), a -> interval, a -> n_values, verbose ? gettext("/sd") : "", a -> min, avg, a -> max);
541
542 if (verbose)
543 {
544 double sd = -1.0;
545
546 if (a -> n_values)
547 sd = sqrt((a -> sd / (double)a -> n_values) - pow(avg, 2.0));
548
549 str_add(&line, "/%.1f", sd);
550 }
551
552 str_add(&line, " ms");
553
554 #ifdef NC
555 if (ncurses_mode)
556 slow_log("\n%s", line);
557 else
558 #endif
559 printf("%s\n", line);
560
561 free(line);
562
563 aggregates[index].value =
564 aggregates[index].sd = 0.0;
565 aggregates[index].min = MY_DOUBLE_INF;
566 aggregates[index].max = -MY_DOUBLE_INF;
567 aggregates[index].n_values = 0;
568 aggregates[index].last_ts = cur_ts;
569 }
570 }
571 }
572
573 void fetch_proxy_settings(char **proxy_user, char **proxy_password, char **proxy_host, int *proxy_port, char use_ssl, char use_ipv6)
574 {
575 char *str = getenv(use_ssl ? "https_proxy" : "http_proxy");
576
577 if (!str)
578 {
579 /* FIXME from wgetrc/curlrc? */
580 }
581
582 if (str)
583 {
584 char *path = NULL, *url = NULL;
585
586 interpret_url(str, &path, proxy_host, proxy_port, use_ipv6, use_ssl, &url, proxy_user, proxy_password);
587
588 free(url);
589 free(path);
590 }
591 }
592
593 void parse_nagios_settings(const char *in, double *nagios_warn, double *nagios_crit)
594 {
595 char *dummy = strchr(in, ',');
596 if (!dummy)
597 error_exit(gettext("-n: missing parameter\n"));
598
599 *nagios_warn = atof(in);
600
601 *nagios_crit = atof(dummy + 1);
602 }
603
604 void parse_bind_to(const char *in, struct sockaddr_in *bind_to_4, struct sockaddr_in6 *bind_to_6, struct sockaddr_in **bind_to)
605 {
606 char *dummy = strchr(in, ':');
607
608 if (dummy)
609 {
610 *bind_to = (struct sockaddr_in *)bind_to_6;
611 memset(bind_to_6, 0x00, sizeof *bind_to_6);
612 bind_to_6 -> sin6_family = AF_INET6;
613
614 if (inet_pton(AF_INET6, in, &bind_to_6 -> sin6_addr) != 1)
615 error_exit(gettext("cannot convert ip address '%s' (for -y)\n"), in);
616 }
617 else
618 {
619 *bind_to = (struct sockaddr_in *)bind_to_4;
620 memset(bind_to_4, 0x00, sizeof *bind_to_4);
621 bind_to_4 -> sin_family = AF_INET;
622
623 if (inet_pton(AF_INET, in, &bind_to_4 -> sin_addr) != 1)
624 error_exit(gettext("cannot convert ip address '%s' (for -y)\n"), in);
625 }
626 }
627
628 time_t parse_date_from_response_headers(const char *in)
629 {
630 char *date = NULL, *komma = NULL;
631 if (in == NULL)
632 return -1;
633
634 date = strstr(in, "\nDate:");
635 komma = date ? strchr(date, ',') : NULL;
636 if (date && komma)
637 {
638 struct tm tm;
639 memset(&tm, 0x00, sizeof tm);
640
641 /* 22 Feb 2013 09:13:56 */
642 if (strptime(komma + 1, "%d %b %Y %H:%M:%S %Z", &tm))
643 return mktime(&tm);
644 }
645
646 return -1;
647 }
648
649 int calc_page_age(const char *in, const time_t their_ts)
650 {
651 int age = -1;
652
653 if (in != NULL && their_ts > 0)
654 {
655 char *date = strstr(in, "\nLast-Modified:");
656 char *komma = date ? strchr(date, ',') : NULL;
657 if (date && komma)
658 {
659 struct tm tm;
660 memset(&tm, 0x00, sizeof tm);
661
662 /* 22 Feb 2013 09:13:56 */
663 if (strptime(komma + 1, "%d %b %Y %H:%M:%S %Z", &tm))
664 age = their_ts - mktime(&tm);
665 }
666 }
667
668 return age;
669 }
670
671 const char *get_location(const char *host, int port, char use_ssl, char *reply)
672 {
673 if (reply)
674 {
675 char *copy = strdup(reply);
676 char *head = strstr(copy, "\nLocation:");
677 char *lf = head ? strchr(head + 1, '\n') : NULL;
678
679 if (head)
680 {
681 char *buffer = NULL;
682 char *dest = head + 11;
683
684 if (lf)
685 *lf = 0x00;
686
687 if (memcmp(dest, "http", 4) == 0)
688 str_add(&buffer, "%s", dest);
689 else
690 str_add(&buffer, "http%s://%s:%d%s", use_ssl ? "s" : "", host, port, dest);
691
692 free(copy);
693
694 return buffer;
695 }
696
697 free(copy);
698 }
699
700 return NULL;
701 }
702
703 char check_compressed(const char *reply)
704 {
705 if (reply != NULL)
706 {
707 char *encoding = strstr(reply, "\nContent-Encoding:");
708
709 if (encoding)
710 {
711 char *dummy = strchr(encoding + 1, '\r');
712 if (dummy) *dummy = 0x00;
713
714 dummy = strchr(encoding + 1, '\n');
715 if (dummy) *dummy = 0x00;
716
717 if (strstr(encoding, "gzip") == 0 || strstr(encoding, "deflate") == 0)
718 return 1;
719 }
720 }
721
722 return 0;
723 }
724
725 int nagios_result(int ok, int nagios_mode, int nagios_exit_code, double avg_httping_time, double nagios_warn, double nagios_crit)
726 {
727 if (nagios_mode == 1)
728 {
729 if (ok == 0)
730 {
731 printf(gettext("CRITICAL - connecting failed: %s"), get_error());
732 return 2;
733 }
734 else if (avg_httping_time >= nagios_crit)
735 {
736 printf(gettext("CRITICAL - average httping-time is %.1f\n"), avg_httping_time);
737 return 2;
738 }
739 else if (avg_httping_time >= nagios_warn)
740 {
741 printf(gettext("WARNING - average httping-time is %.1f\n"), avg_httping_time);
742 return 1;
743 }
744
745 printf(gettext("OK - average httping-time is %.1f (%s)|ping=%f\n"), avg_httping_time, get_error(), avg_httping_time);
746
747 return 0;
748 }
749 else if (nagios_mode == 2)
750 {
751 const char *err = get_error();
752
753 if (ok && err[0] == 0x00)
754 {
755 printf(gettext("OK - all fine, avg httping time is %.1f|ping=%f\n"), avg_httping_time, avg_httping_time);
756 return 0;
757 }
758
759 printf(gettext("%s: - failed: %s"), nagios_exit_code == 1?"WARNING":(nagios_exit_code == 2?"CRITICAL":"ERROR"), err);
760 return nagios_exit_code;
761 }
762
763 return -1;
764 }
765
766 void proxy_to_host_and_port(char *in, char **proxy_host, int *proxy_port)
767 {
768 if (in[0] == '[')
769 {
770 char *dummy = NULL;
771
772 *proxy_host = strdup(in + 1);
773
774 dummy = strchr(*proxy_host, ']');
775 if (dummy)
776 {
777 *dummy = 0x00;
778
779 /* +2: ']:' */
780 *proxy_port = atoi(dummy + 2);
781 }
782 }
783 else
784 {
785 char *dummy = strchr(in, ':');
786
787 *proxy_host = in;
788
789 if (dummy)
790 {
791 *dummy=0x00;
792 *proxy_port = atoi(dummy + 1);
793 }
794 }
795 }
796
797 void stats_close(int *fd, stats_t *t_close, char is_failure)
798 {
799 double t_start = get_ts(), t_end = -1;;
800
801 if (is_failure)
802 failure_close(*fd);
803 else
804 close(*fd);
805
806 *fd = -1;
807
808 t_end = get_ts();
809
810 update_statst(t_close, (t_end - t_start) * 1000.0);
811 }
812
813 void add_header(char ***additional_headers, int *n_additional_headers, const char *in)
814 {
815 *additional_headers = (char **)realloc(*additional_headers, (*n_additional_headers + 1) * sizeof(char **));
816 (*additional_headers)[*n_additional_headers] = strdup(in);
817
818 (*n_additional_headers)++;
819 }
820
821 void free_headers(char **additional_headers, int n_additional_headers)
822 {
823 int index = 0;
824
825 for(index=0; index<n_additional_headers; index++)
826 free(additional_headers[index]);
827
828 free(additional_headers);
829 }
830
831 typedef struct
832 {
833 double Bps_min, Bps_max;
834 long long int Bps_avg;
835 } bps_t;
836
837 void stats_line(const char with_header, const char *const complete_url, const int count, const int curncount, const int err, const int ok, double started_at, const char verbose, const stats_t *const t_total, const double avg_httping_time, bps_t *const bps)
838 {
839 double total_took = get_ts() - started_at;
840 int dummy = count;
841
842 if (with_header)
843 printf(gettext("--- %s ping statistics ---\n"), complete_url);
844
845 if (curncount == 0 && err > 0)
846 fprintf(stderr, gettext("internal error! (curncount)\n"));
847
848 if (count == -1)
849 dummy = curncount;
850
851 printf(gettext("%s%d%s connects, %s%d%s ok, %s%3.2f%%%s failed, time %s%s%.0fms%s\n"), c_yellow, curncount, c_normal, c_green, ok, c_normal, c_red, (((double)err) / ((double)dummy)) * 100.0, c_normal, c_blue, c_bright, total_took * 1000.0, c_normal);
852
853 if (ok > 0)
854 {
855 printf(gettext("round-trip min/avg/max%s = %s%.1f%s/%s%.1f%s/%s%.1f%s"), verbose ? gettext("/sd") : "", c_bright, t_total -> min, c_normal, c_bright, avg_httping_time, c_normal, c_bright, t_total -> max, c_normal);
856
857 if (verbose)
858 {
859 double sd_final = t_total -> n ? sqrt((t_total -> sd / (double)t_total -> n) - pow(avg_httping_time, 2.0)) : -1.0;
860 printf("/%.1f", sd_final);
861 }
862
863 printf(" ms\n");
864
865 if (bps)
866 printf(gettext("Transfer speed: min/avg/max = %s%f%s/%s%f%s/%s%f%s KB\n"), c_bright, bps -> Bps_min / 1024, c_normal, c_bright, (bps -> Bps_avg / (double)ok) / 1024.0, c_normal, c_bright, bps -> Bps_max / 1024.0, c_normal);
867 }
868 }
869
870 int main(int argc, char *argv[])
871 {
872 double started_at = -1;
873 char do_fetch_proxy_settings = 0;
874 char *hostname = NULL;
875 char *proxy_host = NULL, *proxy_user = NULL, *proxy_password = NULL;
876 int proxy_port = 8080;
877 int portnr = 80;
878 char *get = NULL, *request = NULL;
879 int req_len = 0;
880 int c = 0;
881 int count = -1, curncount = 0;
882 double wait = 1.0;
883 char wait_set = 0;
884 int audible = 0;
885 int ok = 0, err = 0;
886 double timeout = 30.0;
887 char show_statuscodes = 0;
888 char use_ssl = 0;
889 const char *ok_str = "200";
890 const char *err_str = "-1";
891 const char *useragent = NULL;
892 const char *referer = NULL;
893 const char *auth_password = NULL;
894 const char *auth_usr = NULL;
895 char **static_cookies = NULL, **dynamic_cookies = NULL;
896 int n_static_cookies = 0, n_dynamic_cookies = 0;
897 char resolve_once = 0;
898 char have_resolved = 0;
899 double nagios_warn=0.0, nagios_crit=0.0;
900 int nagios_exit_code = 2;
901 double avg_httping_time = -1.0;
902 int get_instead_of_head = 0;
903 char show_Bps = 0, ask_compression = 0;
904 bps_t bps;
905 int Bps_limit = -1;
906 char show_bytes_xfer = 0, show_fp = 0;
907 SSL *ssl_h = NULL;
908 BIO *s_bio = NULL;
909 struct sockaddr_in *bind_to = NULL;
910 struct sockaddr_in bind_to_4;
911 struct sockaddr_in6 bind_to_6;
912 char split = 0, use_ipv6 = 0;
913 char persistent_connections = 0, persistent_did_reconnect = 0;
914 char no_cache = 0;
915 char use_tfo = 0;
916 char abort_on_resolve_failure = 1;
917 double offset_yellow = -1, offset_red = -1;
918 char colors = 0;
919 int verbose = 0;
920 double offset_show = -1.0;
921 char add_host_header = 1;
922 char *proxy_buster = NULL;
923 char proxy_is_socks5 = 0;
924 char *url = NULL, *complete_url = NULL;
925 int n_aggregates = 0;
926 aggregate_t *aggregates = NULL;
927 char *au_dummy = NULL, *ap_dummy = NULL;
928 stats_t t_connect, t_request, t_total, t_resolve, t_write, t_ssl, t_close, stats_to, tcp_rtt_stats, stats_header_size;
929 char first_resolve = 1;
930 double graph_limit = MY_DOUBLE_INF;
931 char nc_graph = 1;
932 char adaptive_interval = 0;
933 double show_slow_log = MY_DOUBLE_INF;
934 char use_tcp_nodelay = 1;
935 int max_mtu = -1;
936 int write_sleep = 500; /* in us (microseconds), determines resolution of transmit time determination */
937 char keep_cookies = 0;
938 char abbreviate = 0;
939 char *divert_connect = NULL;
940 int recv_buffer_size = -1, tx_buffer_size = -1;
941 int priority = -1, send_tos = -1;
942 char **additional_headers = NULL;
943 int n_additional_headers = 0;
944 #ifndef NO_SSL
945 SSL_CTX *client_ctx = NULL;
946 #endif
947 struct sockaddr_in6 addr;
948 struct addrinfo *ai = NULL, *ai_use = NULL;
949 struct addrinfo *ai_proxy = NULL, *ai_use_proxy = NULL;
950
951 static struct option long_options[] =
952 {
953 {"aggregate", 1, NULL, 9 },
954 {"url", 1, NULL, 'g' },
955 {"hostname", 1, NULL, 'h' },
956 {"port", 1, NULL, 'p' },
957 {"proxy", 1, NULL, 'x' },
958 {"count", 1, NULL, 'c' },
959 {"persistent-connections", 0, NULL, 'Q' },
960 {"interval", 1, NULL, 'i' },
961 {"timeout", 1, NULL, 't' },
962 {"ipv6", 0, NULL, '6' },
963 {"show-statuscodes", 0, NULL, 's' },
964 {"split-time", 0, NULL, 'S' },
965 {"get-request", 0, NULL, 'G' },
966 {"show-transfer-speed", 0, NULL, 'b' },
967 {"show-xfer-speed-compressed", 0, NULL, 'B' },
968 {"data-limit", 1, NULL, 'L' },
969 {"show-kb", 0, NULL, 'X' },
970 {"no-cache", 0, NULL, 'Z' },
971 #ifndef NO_SSL
972 {"use-ssl", 0, NULL, 'l' },
973 {"show-fingerprint", 0, NULL, 'z' },
974 #endif
975 {"flood", 0, NULL, 'f' },
976 {"audible-ping", 0, NULL, 'a' },
977 {"parseable-output", 0, NULL, 'm' },
978 {"ok-result-codes", 1, NULL, 'o' },
979 {"result-string", 1, NULL, 'e' },
980 {"user-agent", 1, NULL, 'I' },
981 {"referer", 1, NULL, 'S' },
982 {"resolve-once",0, NULL, 'r' },
983 {"nagios-mode-1", 1, NULL, 'n' },
984 {"nagios-mode-2", 1, NULL, 'n' },
985 {"bind-to", 1, NULL, 'y' },
986 {"quiet", 0, NULL, 'q' },
987 {"username", 1, NULL, 'U' },
988 {"password", 1, NULL, 'P' },
989 {"cookie", 1, NULL, 'C' },
990 {"colors", 0, NULL, 'Y' },
991 {"offset-yellow", 1, NULL, 1 },
992 {"threshold-yellow", 1, NULL, 1 },
993 {"offset-red", 1, NULL, 2 },
994 {"threshold-red", 1, NULL, 2 },
995 {"offset-show", 1, NULL, 3 },
996 {"show-offset", 1, NULL, 3 },
997 {"threshold-show", 1, NULL, 3 },
998 {"show-threshold", 1, NULL, 3 },
999 {"timestamp", 0, NULL, 4 },
1000 {"ts", 0, NULL, 4 },
1001 {"no-host-header", 0, NULL, 5 },
1002 {"proxy-buster", 1, NULL, 6 },
1003 {"proxy-user", 1, NULL, 7 },
1004 {"proxy-password", 1, NULL, 8 },
1005 {"proxy-password-file", 1, NULL, 10 },
1006 {"graph-limit", 1, NULL, 11 },
1007 {"adaptive-interval", 0, NULL, 12 },
1008 {"ai", 0, NULL, 12 },
1009 {"slow-log", 0, NULL, 13 },
1010 {"draw-phase", 0, NULL, 14 },
1011 {"no-tcp-nodelay", 0, NULL, 15 },
1012 {"max-mtu", 1, NULL, 16 },
1013 {"keep-cookies", 0, NULL, 17 },
1014 {"abbreviate", 0, NULL, 18 },
1015 {"divert-connect", 1, NULL, 19 },
1016 {"recv-buffer", 1, NULL, 20 },
1017 {"tx-buffer", 1, NULL, 21 },
1018 {"priority", 1, NULL, 23 },
1019 {"tos", 1, NULL, 24 },
1020 {"header", 1, NULL, 25 },
1021 #ifdef NC
1022 {"ncurses", 0, NULL, 'K' },
1023 {"gui", 0, NULL, 'K' },
1024 #ifdef FW
1025 {"no-graph", 0, NULL, 'D' },
1026 #endif
1027 #endif
1028 {"version", 0, NULL, 'V' },
1029 {"help", 0, NULL, 22 },
1030 {NULL, 0, NULL, 0 }
1031 };
1032
1033 bps.Bps_min = 1 << 30;
1034 bps.Bps_max = -bps.Bps_min;
1035 bps.Bps_avg = 0;
1036
1037 setlocale(LC_ALL, "");
1038 bindtextdomain("HTTPing", LOCALEDIR);
1039 textdomain("HTTPing");
1040
1041 init_statst(&t_resolve);
1042 init_statst(&t_connect);
1043 init_statst(&t_write);
1044 init_statst(&t_request);
1045 init_statst(&t_total);
1046 init_statst(&t_ssl);
1047 init_statst(&t_close);
1048
1049 init_statst(&stats_to);
1050 #if defined(linux) || defined(__FreeBSD__)
1051 init_statst(&tcp_rtt_stats);
1052 #endif
1053 init_statst(&stats_header_size);
1054
1055 determine_terminal_size(&max_y, &max_x);
1056
1057 signal(SIGPIPE, SIG_IGN);
1058
1059 while((c = getopt_long(argc, argv, "DKEA5MvYWT:ZQ6Sy:XL:bBg:h:p:c:i:Gx:t:o:e:falqsmV?I:R:rn:N:zP:U:C:F", long_options, NULL)) != -1)
1060 {
1061 switch(c)
1062 {
1063 case 25:
1064 add_header(&additional_headers, &n_additional_headers, optarg);
1065 break;
1066
1067 case 24:
1068 send_tos = atoi(optarg);
1069 break;
1070
1071 case 23:
1072 #ifdef linux
1073 priority = atoi(optarg);
1074 #else
1075 error_exit("Setting the network priority is only supported on Linux.\n");
1076 #endif
1077 break;
1078
1079 case 21:
1080 tx_buffer_size = atoi(optarg);
1081 break;
1082
1083 case 20:
1084 recv_buffer_size = atoi(optarg);
1085 break;
1086
1087 case 19:
1088 divert_connect = optarg;
1089 break;
1090
1091 case 18:
1092 abbreviate = 1;
1093 break;
1094
1095 case 17:
1096 keep_cookies = 1;
1097 break;
1098
1099 case 16:
1100 max_mtu = atoi(optarg);
1101 break;
1102
1103 case 15:
1104 use_tcp_nodelay = 0;
1105 break;
1106
1107 #ifdef NC
1108 case 14:
1109 draw_phase = 1;
1110 break;
1111 #endif
1112
1113 case 13:
1114 show_slow_log = atof(optarg);
1115 break;
1116
1117 case 12:
1118 adaptive_interval = 1;
1119 break;
1120
1121 case 11:
1122 graph_limit = atof(optarg);
1123 break;
1124
1125 #ifdef NC
1126 case 'K':
1127 ncurses_mode = 1;
1128 adaptive_interval = 1;
1129 if (!wait_set)
1130 wait = 0.5;
1131 break;
1132 #ifdef FW
1133 case 'D':
1134 nc_graph = 0;
1135 break;
1136 #endif
1137 #endif
1138
1139 case 'E':
1140 do_fetch_proxy_settings = 1;
1141 break;
1142
1143 case 'A':
1144 fprintf(stderr, gettext("\n *** -A is no longer required ***\n\n"));
1145 break;