ok so i have to make a webserver using c. I think I got the connection part down
ID: 3563856 • Letter: O
Question
ok so i have to make a webserver using c. I think I got the connection part down, but the client is also supposed to request a file(website). Can someone tell me what functions I should look in to or anyother way to handle that?
Explanation / Answer
#include #include #include #include #include #include #include #include #include #include #include #include #include #define BACKLOG 10 //Variables used in get_conf(). char conf[5], dir[500], port[10], charset[200], user[100], group[100]; int portf; //Sockets stuff int sockfd, new_fd; struct sockaddr_in their_addr; socklen_t sin_size; struct sigaction sa; //Other global variables int buffer_counter; char * buffer; FILE *openfile; void read_chunk() { fread (buffer,1,1048576,openfile); buffer_counter++; } void sigchld_handler(int s) { while(waitpid(-1, NULL, WNOHANG) > 0); } //Chroot and change user and group to nobody. Got this function from Simple HTTPD 1.0. void drop_privileges() { struct passwd *pwd; struct group *grp; if ((pwd = getpwnam(user)) == 0) { fprintf(stderr, "User not found in /etc/passwd "); exit(1); } if ((grp = getgrnam(group)) == 0) { fprintf(stderr, "Group not found in /etc/group "); exit(1); } if (chdir(dir) != 0) { fprintf(stderr, "chdir(...) failed "); exit(1); } if (chroot(dir) != 0) { fprintf(stderr, "chroot(...) failed "); exit(1); } if (setgid(grp->gr_gid) != 0) { fprintf(stderr, "setgid(...) failed "); exit(1); } if (setuid(pwd->pw_uid) != 0) { fprintf(stderr, "setuid(...) failed "); exit(1); } } void get_conf() { FILE *conffile; conffile = fopen ("/etc/qshttpd.conf", "r"); while (fgets (conf , 6, conffile)) { if (strcmp (conf, "ROOT=") == 0){ fgets (dir, 500, conffile); strtok(dir, " "); } if (strcmp (conf, "PORT=") == 0){ fgets (port, 10, conffile); portf=atoi(port); } if (strcmp (conf, "CHAR=") == 0){ fgets (charset, 200, conffile); strtok(charset, " "); } if (strcmp (conf, "USER=") == 0){ fgets (user, 100, conffile); strtok(user, " "); } if (strcmp (conf, "GRUP=") == 0){ fgets (group, 100, conffile); strtok(group, " "); } } fclose (conffile); } void create_and_bind() { int yes=1; struct sockaddr_in my_addr; if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); } if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) { perror("setsockopt"); exit(1); } my_addr.sin_family = AF_INET; my_addr.sin_port = htons(portf); my_addr.sin_addr.s_addr = INADDR_ANY; memset(&(my_addr.sin_zero), '', 8); if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) { perror("bind"); exit(1); } drop_privileges(); if (listen(sockfd, BACKLOG) == -1) { perror("listen"); exit(1); } sa.sa_handler = sigchld_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; if (sigaction(SIGCHLD, &sa, NULL) == -1) { perror("sigaction"); exit(1); } } int main(void) { char in[3000], sent[500], code[50], file[200], mime[100], moved[200], length[100], auth[200], auth_dir[500], start[100], end[100]; char *result=NULL, *hostname, *hostnamef, *lines, *ext=NULL, *extf, *auth_dirf=NULL, *authf=NULL, *rangetmp; int buffer_chunks; long filesize, range=0; get_conf(); create_and_bind(); //Important stuff happens here. while(1) { sin_size = sizeof(struct sockaddr_in); if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1) { perror("accept"); continue; } if (!fork()) { close(sockfd); if (read(new_fd, in, 3000) == -1) { perror("recive"); } else { lines = strtok(in, " "); do { hostname = strtok(NULL, " "); if (hostname[0] == 'R' && hostname[1] == 'a' && hostname[2] == 'n' && hostname[3] == 'g' && hostname[4] == 'e') { rangetmp = hostname; strcpy(code, "206 Partial Content"); } } while (hostname[0] != 'H' || hostname[1] != 'o' || hostname[2] != 's' || hostname[3] != 't'); hostnamef = strtok(hostname, " "); hostnamef = strtok(NULL, " "); result = strtok(lines, " "); result = strtok(NULL, " "); if (strcmp(code, "206 Partial Content") == 0 ) { rangetmp = strtok(strpbrk(rangetmp, "="), "=-"); range = atoi(rangetmp); } strcpy(file, result); if (opendir(file)){ if (file[strlen(file)-1] == '/'){ strcat(file, "/index.html"); openfile=fopen (file, "r"); if (openfile){ strcpy(code, "200 OK"); } else { //Here should be some kind of directory listing strcpy(file, "/404.html"); openfile = fopen (file, "r"); strcpy(code, "404 Not Found"); } } else { strcpy(code, "301 Moved Permanently"); strcpy(moved, "Location: http://"); strcat(moved, hostnamef); strcat(moved, result); strcat(moved, "/"); } } else { openfile=fopen (file, "rb"); if (openfile){ if (strlen(code) < 1) { strcpy (code, "200 OK"); } } else { strcpy(file, "/404.html"); openfile = fopen (file, "r"); strcpy(code, "404 Not Found"); } } } if (strcmp(code, "301 Moved Permanently") != 0){ fseek (openfile , 0 , SEEK_END); filesize = ftell (openfile); rewind (openfile); if (range > 0) { sprintf(end, "%d", filesize); filesize = filesize - range; sprintf(start, "%d", range); fseek (openfile , range , SEEK_SET); } buffer_chunks = filesize/1048576; if(filesize%1048576 > 0){ buffer_chunks++; } sprintf(length, "%d", filesize); buffer_counter = 0; buffer = (char*) malloc (sizeof(char)*1048576); } if (strcmp(code, "404 Not Found") != 0 && strcmp(code, "301 Moved Permanently") !=0){ ext = strtok(file, "."); while(ext != NULL){ ext = strtok(NULL, "."); if (ext != NULL){ extf = ext; } } } else { extf="html"; } /* Maybe I should read mime types from a file. At least for now, add here what you need.*/ if (strcmp(extf, "html") == 0){ strcpy (mime, "text/html"); } else if(strcmp(extf, "jpg") == 0){ strcpy (mime, "image/jpeg"); } else if(strcmp(extf, "gif") == 0){ strcpy (mime, "image/gif"); } else if(strcmp(extf, "css") == 0){ strcpy (mime, "text/css"); } else { strcpy(mime, "application/octet-stream"); } strcpy(sent, "HTTP/1.1 "); strcat(sent, code); strcat(sent, " Server: qshttpd 0.3.0 "); if(strcmp(code, "301 Moved Permanently") == 0){ strcat(sent, moved); strcat(sent, " "); } strcat(sent, "Content-Length: "); if(strcmp(code, "301 Moved Permanently") != 0){ strcat(sent, length); } else { strcat(sent, "0"); } if(strcmp(code, "206 Partial Content") == 0) { strcat(sent, " Content-Range: bytes "); strcat(sent, start); strcat(sent, "-"); strcat(sent, end); strcat(sent, "/"); strcat(sent, end); } strcat(sent, " Connection: close Content-Type: "); strcat(sent, mime); strcat(sent, "; charset="); strcat(sent, charset); strcat(sent, " "); write(new_fd, sent, strlen(sent)); while (buffer_counterRelated Questions
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.