2 * HTTP/HTTPS protocol support
4 * Copyright (C) 2000, 2001, 2002 by
5 * Jeffrey Fulmer - <jdfulmer@armstrong.com>
6 * This file is distributed as part of Libping
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #endif/*HAVE_CONFIG_H*/
43 CONN *C; /* threadsafe connection */
44 URL U; /* defined in url.h */
45 HEADERS *head; /* HTTP header structure */
46 int bytes; /* bytes read from srv. */
47 char *tmp; /* tmp storage for url */
48 struct timeval mytime;
50 tmp = strdup( H->url );
53 C = (CONN*)xmalloc( sizeof( CONN ));
55 C->timeout = ( H->timeout == 0 )?60:H->timeout;
57 (void) gettimeofday( &mytime, (struct timezone *)NULL);
59 if(( C->sock = JOEsocket( C, U.hostname )) <= 0 ){
63 JOEhttp_send( C, U.hostname, U.pathname );
64 head = JOEhttp_read_headers( C, U.hostname );
71 bytes = JOEhttp_read( C, 0 );
81 H->rtt = elapsed_time( &mytime );
83 if( head->code > 499 ){ return -1; }
88 * returns int, ( < 0 == error )
89 * formats and sends an HTTP/1.0 request
92 JOEhttp_send( CONN *C, char *host, char *path )
100 sprintf( fullpath, "%s", path );
102 memset( request, 0, sizeof( request ));
104 /* HTTP protocol string */
105 protocol = "HTTP/1.0";
109 request, sizeof( request ),
112 "Accept: */*\015\012"
113 "Accept-Encoding: * \015\012"
114 "User-Agent: JoeDog 1.00 [libping]\015\012"
115 "Connection: %s\015\012\015\012",
116 fullpath, protocol, host, keepalive
119 if( rlen < 0 || rlen > sizeof(request) ){
120 perror("http_send: request buffer overrun!");
124 if(( JOEsocket_check( C, WRITE )) < 0 ){
125 perror( "JOEsocket: not writeable" );
129 JOEsocket_write( C, request, rlen );
135 * returns int, ( < 0 == error )
136 * formats and sends an HTTP/1.0 request
139 JOEhttp_post( CONN *C, char *host, char *path, char *data, size_t len )
147 sprintf( fullpath, "%s", path );
149 memset( request, 0, sizeof( request ));
151 /* HTTP protocol string */
152 protocol = "HTTP/1.0";
156 request, sizeof( request ),
159 "Accept: */*\015\012"
160 "Accept-Encoding: * \015\012"
161 "User-Agent: JoeDog 1.00 [libping]\015\012"
162 "Connection: %s\015\012"
163 "Content-type: application/x-www-form-urlencoded\015\012"
164 "Content-length: %d\015\012\015\012"
166 fullpath, protocol, host, keepalive, len, len, len, data
169 if( rlen < 0 || rlen > sizeof(request) ){
170 perror("http_post: request buffer overrun!");
174 if(( JOEsocket_check( C, WRITE )) < 0 ){
175 perror( "JOEsocket: not writeable" );
179 JOEsocket_write( C, request, rlen );
185 * returns HEADERS struct
186 * reads from http/https socket and parses
187 * header information into the struct.
190 JOEhttp_read_headers( CONN *C, char *host )
192 int x; /* while loop index */
193 int n; /* assign socket_read */
194 char c; /* assign char read */
195 char line[512]; /* assign chars read */
196 HEADERS *h; /* struct to hold it all */
197 h = (HEADERS*)malloc( sizeof(HEADERS));
198 memset( h, 0, sizeof( HEADERS ));
200 if(( JOEsocket_check( C, READ )) < 0 ){
201 perror( "JOEsocket: not readable" );
209 memset( &line, 0, sizeof( line ));
210 while(( n = JOEsocket_read( C, &c, 1 )) == 1 ){
212 if(( line[0] == '\n' ) || ( line[1] == '\n' )){
215 if( line[x] == '\n' ) break;
219 /* strip trailing CR */
220 if (x > 0 && line[x-1] == '\r') line[x-1]=0;
221 if( strncasecmp( line, "http", 4 ) == 0 ){
222 strncpy( h->head, line, 8 );
223 h->code = atoi( line + 9 );
225 if( strncasecmp( line, "content-length: ", 16 ) == 0 ){
226 h->length = atol( line + 16 );
228 if( strncasecmp( line, "connection: ", 12 ) == 0 ){
229 if ( strncasecmp( line+12, "keep-alive", 10 ) == 0 ){
232 else if( strncasecmp( line+12, "close", 5 ) == 0 ){
237 if( strncasecmp(line, "location: ", 10) == 0) {
238 if (strlen(line) - 10 > sizeof(h->redirection) - 1) {
239 perror( "redirection URL too long, ignored");
242 strcpy(h->redirection, line+10);
247 perror("JOEhttp_read_headers");
249 } /* socket closed */
250 } /* end of while TRUE */
257 * reads a http/https socket
258 * ( you know what I mean :)
261 JOEhttp_read( CONN *C, int len )
267 if(( JOEsocket_check( C, READ )) < 0 ){
268 perror( "JOEsocket: not readable" );
272 memset( &body, 0, MAXFILE );
274 if(( n = JOEsocket_read( C, body, MAXFILE)) == 0 ){
277 /* IGV: should be accumulating bytes read, not just
278 recording those in the last packet */
285 pinghttp( char *hostname )
289 H = (HTTPDATA*)xmalloc( sizeof( HTTPDATA ));
290 H->url = (char*)strdup( hostname );
293 return( myhttp( H ));
297 pingthttp( char *hostname, int t )
301 H = (HTTPDATA*)xmalloc( sizeof( HTTPDATA ));
302 H->url = (char*)strdup( hostname );
305 return( myhttp( H ));
309 tpinghttp( char *hostname )
314 H = (HTTPDATA*)xmalloc( sizeof( HTTPDATA ));
315 H->url = (char*)strdup( hostname );
320 if( ret > 0 ){ return H->rtt; }
325 tpingthttp( char *hostname, int t )
330 H = (HTTPDATA*)xmalloc( sizeof( HTTPDATA ));
331 H->url = (char*)strdup( hostname );
336 if( ret > 0 ){ return H->rtt; }