HTTP Client program segmentation fault

Ok, i have some strange problem.
I was working on a HTTP server and client program which works very fine on my laptop on Debian and Slackware. But when i tried to run it on others systems, it started giving segmentation faults. I again tried that code on my laptop and it works fine! Is that possible?

Here is the code!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <sys/wait.h>
#include <signal.h>
#include <time.h>
#include <dirent.h>

#define LENGTH 512
#define MAXDATASIZE 1000

typedef enum {FALSE, TRUE} bool;

/* inout() - This function prints out the results of the file descriptor 
 * after finishing sending the request to the server
 */
int inout(int in, int out)
{
	char *s;
	int i = 0;

	s = (char *) malloc (1000*sizeof(char));
	while(read(in, s+i, 1) != 0) {
		if (s[i] == '\n') {
			write(out, s, i+1);
			return i+1;
		}
		i++;
	}
	return 0;
}

void *get_in_addr(struct sockaddr *sa)
{
	if (sa->sa_family == AF_INET) {
		return &(((struct sockaddr_in*)sa)->sin_addr);
	}

	return &(((struct sockaddr_in6*)sa)->sin6_addr);
}

/* isvalidip() - Uses the inet_pton() function to check whether or not 
 * the specified IP address is valid. Returns TRUE if valid and FALSE
 * otherwise.
 */
bool isvalidip(char *ip)
{
	struct sockaddr_in sa;
	int valid = inet_pton(AF_INET, ip, &(sa.sin_addr));
	return valid != 0;
}

/* send_request() - Contains the principal code the for the program.
 * The function creates a HTTP GET string to send to the server
 * and returns everything on a file descriptor to pass it to main().
 */
int send_request(char *dns, char *port,char *reqtype)
{

	int sockfd, bindfd; // socket and bind file descriptors
	char *ptr, *host, path[100];
	char getrequest[1024];
	struct addrinfo hints, *res;

	memset(&hints, 0, sizeof hints);
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;

	// conditions to differentiate between an IP address and a hostname
	if ( isvalidip(dns) ) { 							// when an IP is found then no paths are specified
		sprintf(getrequest, "%s / HTTP/1.0\nHOST: %s\n\n",reqtype, dns); 	// create a get request only for the IP
	} else { 									// if it's not an IP, then it should be a DNS name
		if ( (ptr = strstr(dns, "/")) == NULL) { 				// if the DNS name does not contain a slash at the end
			sprintf(getrequest, "%s / HTTP/1.0\nHOST: %s\n\n",reqtype, dns);// we send a request only for the dns name
		}
		else {  								// it there is a slash right after the DNS name then there is path to a filename
			strcpy(path, ptr);
			host = strtok(dns, "/"); 					//truncate the argument to a PATH and DNS name
			sprintf(getrequest, "%s %s HTTP/1.0\nHOST: %s\n\n",reqtype, path, dns);
		}
	}
											// gets linked list of results of a specified hostname
	if ( getaddrinfo(dns, port, &hints, &res) != 0 ){
		fprintf(stderr, "Host or IP not valid\n"); 				//quits program if the hostname was not found
		exit(0);
	}

	// creates a socket from hostname results and passes everything to a file descriptor
	sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);

	// bind the socket to the port passed to getaddrinfo()
	bindfd = bind(sockfd, res->ai_addr, res->ai_addrlen);

	// establish a connection and quits if there is a connection error
	if ( connect(sockfd, res->ai_addr, res->ai_addrlen) != 0 ){
		fprintf(stderr, "Connection error\n");
		exit(0);
	}

	int optval = 1; //is 
	setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval);

	// writes the HTTP request to the socked file descriptor
	write(sockfd, getrequest, strlen(getrequest));

	return sockfd; //returns the results to main
}


int main(int argc, char **argv)
{
	int port, sockfd;
	char *host, *ptr;

	port = atoi(argv[2]);
	sprintf(host,"%s/%s",argv[1],argv[4]);

	if(argv[3][0]=='G'&&argv[3][1]=='E'&&argv[3][2]=='T') 			//For GET requests
	{
		sockfd = send_request(host, argv[2],argv[3]);
		while(inout(sockfd, 1) > 0);
	} else if(argv[3][0]=='P'&&argv[3][1]=='U'&&argv[3][2]=='T') 		//For PUT requests
	{

		char* fs_name = argv[4];
		char sdbuf[LENGTH]; 
		printf("\nclient>> Sending %s to the Server... ", fs_name);
		FILE *fs = fopen(fs_name, "r");
		if(fs == NULL)
		{
			printf("\nclient>> ERROR: File %s not found.", fs_name);
			exit(1);
		}
		sockfd = send_request(host, argv[2],argv[3]);

		bzero(sdbuf, LENGTH); 
		int fs_block_sz; 
		while((fs_block_sz = fread(sdbuf, sizeof(char), LENGTH, fs)) > 0)
		{
			if(send(sockfd, sdbuf, fs_block_sz, 0) < 0)
			{
				fprintf(stderr, "ERROR: Failed to send file %s. (errno = %d)", fs_name, errno);
				exit(1);
			}
			bzero(sdbuf, LENGTH);
		}
		shutdown(sockfd, SHUT_WR);
		printf("\nclient>> Ok File %s from Client was Sent!\n", fs_name);

	} else {								//For INVALID requests
		printf("\nclient>> Invalid request.\n");
		exit(1);
	}

	close(sockfd);

	return 0;
}




arguments are
./client 127.0.0.1 9001 GET index.html
Last edited on
It's a bit of a mess and I don't know why it's crashing. But maybe you could consider these points.

 
if(argv[3][0]=='G'&&argv[3][1]=='E'&&argv[3][2]=='T')
can be written as
 
if (strcmp(argv[3], "GET") == 0)
The same goes for PUT.

The client shouldn't call bind(). It gets bound when a connection is made thru connect().

in inout(), read() returns -1 on failure, >1 on success. You're not checking for errors, your only checking for read() to return zero (stop).

Also, in inout(), you're allocating a buffer and not freeing it.
Last edited on
Topic archived. No new replies allowed.