Skip to content

Instantly share code, notes, and snippets.

@christophlsa
Created November 16, 2011 20:42
Show Gist options
  • Save christophlsa/1371314 to your computer and use it in GitHub Desktop.
Save christophlsa/1371314 to your computer and use it in GitHub Desktop.
homework for the study
/* webserver.c */
#include <cnaiapi.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/sendfile.h>
#include <errno.h>
#include <signal.h>
const char * HTDOCS = "htdocs/";
const char * INDEX_FILE = "index.html";
/*
* Writes a HTTP-Response to the connection
*/
bool initialResponseLine(connection _conn, char * _httpVersion, char * _responseStatusCode, char * _reasonPhrase)
{
char response[100] = "HTTP/";
strcat(response, strcat(_httpVersion, " "));
strcat(response, strcat(_responseStatusCode, " "));
strcat(response, _reasonPhrase);
strcat(response, "\n");
int ret = write(STDOUT_FILENO, response, strlen(response));
if (ret < 0) {
return false;
}
return true;
}
const char * mimes[][2] = {
{".jpg", "image/jpeg"},
{".jpeg", "image/jpeg"},
{".html", "text/html"},
{".htm", "text/html"},
};
// get mime type of file name
char * getMime(const char * file) {
char *ext = strrchr(file, '.');
if (ext == NULL)
return "text/plain";
int i;
for (i = 0; i < sizeof(mimes); i++) {
if (strcmp(ext, mimes[i][0]) == 0) {
return (char*)mimes[i][1];
}
}
return "text/plain";
}
int main(int argc, char *argv[])
{
signal(SIGCLD, SIG_IGN);
connection conn;
appnum app = atoi(argv[1]);
// Holds the complete request
char requestBuffer[1024] = "";
int requestLength = 0;
// Holds the requested file path, not it's content
char getBuffer[1024];
// Holds the length of the path to the file
int getLength = 0;
while (true) {
conn = await_contact(app);
if (conn < 0) {
printf("Fehler bei der Verbindung\n");
return 1;
}
// to connect clients simultaniously
pid_t pid = fork();
// child creation unsuccessful
if (pid < 0) {
printf("Fehler in child creation\n");
end_contact(conn);
}
else if (pid > 0) {
printf("Parent\n");
end_contact(conn);
}
else {
// read input -> blocks the thread until data is recieved
// Holds the Request from Client
char readBuffer[1024];
int l;
while ((l = read(conn, readBuffer, 1024))) {
if (l < 0) {
printf("%s\n", strerror(errno));
//end_contact(conn);
exit(1);
}
strncat(requestBuffer, readBuffer, l);
memset(&readBuffer[0], 0, sizeof(readBuffer));
char* requestEnd = strstr(requestBuffer, "\r\n\r\n");
if (requestEnd != NULL) {
break;
}
}
// check for GET-Request
int isGet = strncmp("GET", requestBuffer, 3);
if (isGet != 0) {
initialResponseLine(conn, "1.0", "501", "Not Implemented");
exit(1);
}
// parsing the request from 5. symbol in readBuffer from Client (start of path)
int i;
requestLength = strlen(requestBuffer);
printf("%d\n", requestLength);
for (i = 5; i < requestLength; i++) {
// check man page for comaprison
if (isspace(requestBuffer[i]) != false) {
break;
}
getBuffer[getLength++] = requestBuffer[i];
}
// deliver requested file
// if only "/" take index.html
if ( strlen(getBuffer) == 0 ) {
strcat(getBuffer, INDEX_FILE);
}
char filePath[1024] = "";
strcat(filePath, HTDOCS);
strcat(filePath, getBuffer);
// open file -> http://www.win-tux.de/c_018_025.htm#RxxobKap01802504002A2F1F02418C
int fd = open(filePath, O_RDONLY);
// if an error occurs -> 404
if (fd < 0) {
initialResponseLine(conn, "1.0", "404", "Not Found\r");
printf("%s\r", filePath);
exit(0);
}
struct stat st;
fstat (fd, &st);
char responseHeader[1024];
int len = sprintf(responseHeader, "HTTP/1.0 200 OK\r\nOK\r\nContent-Type: %s\r\nContent-Length: %ld\r\n\r\n", getMime(filePath), st.st_size);
write(conn, responseHeader, len);
int r = sendfile(conn, fd, 0, st.st_size);
if (r < 0) {
printf("Fehler beim Datei senden: %s", strerror(errno));
}
close(fd);
exit(0);
}
}
end_contact(conn);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment