| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164 |
- #include "ServerThread.h"
- using namespace std;
- // entry point for all threads
- char echo_buffer[100 *1024];
- void getExecDir(char*dir) {
- char* filename = nullptr;
- if (readlink("/proc/self/exe", dir, 1024) < 0) {
- dir[0] = '\0';
- return;
- }
- filename = strrchr(dir, '/');
- if (filename == nullptr) {
- dir[0] = '\0';
- return;
- }
- ++filename;
- *filename = '\0';
- sprintf(dir + strlen(dir), "%s", "index.html");
- return;
- }
- void* run(void* obj) {
- ((ServerThread*) obj)->Run();
- // when Run() finishes, mark for termination
- ((ServerThread*) obj)->MarkFT();
- }
- bool getExt(const char* path, char* ext) {
- int l = strlen(path), i = l;
- while (i > 0 && path[--i] != '.' && path[i] != '/');
- if (i == 0 || path[i] == '/') return false;
- for (int j = 0; i < l; ext[j++] = path[++i]);
- return true;
- }
- int getHeader(char *header, const char *buffer, int rd) {
- int hl = 0;
- int i = 0;
- for (; hl < rd && strcmp(term, buffer + hl); hl++) {
- for (i = 0; i < 4; i++)
- if (term[i] != buffer[hl + i]) break;
- if (i == 4) break;
- header[hl] = buffer[hl];
- }
- header[hl] = '\0';
- return hl;
- }
- ///////////////////////////////////////////////////////////
- ServerThread::ServerThread(int socket) {
- this->socket = socket;
- marked = serving = false;
- }
- ServerThread::~ServerThread() {
- }
- // start serving in a separate thread
- void ServerThread::Serve() {
- pthread_create(&tid, NULL, run, this);
- start = time(NULL);
- }
- // terminate the thread and close the socket
- bool ServerThread::Terminate(bool force) {
- if (serving&&!force)return false;
- pthread_cancel(tid);
- close(socket);
- return true;
- }
- // run in current thread
- void ServerThread::Run() {
- int rd, hl;
- while (1) {
- serving = false;
- rd = read(socket, buffer, BUFFERLENGTH - 1);
- if (rd <= 0) {
- // client disconnected mysteriously
- Terminate(true);
- break; // precautionary
- }
- // parse the header
- serving = true;
- char method[8], path[261], version[8], ext[5];
- strcpy(path, WORKDIR);
- // getExecDir(path);
- hl = getHeader(header, buffer, rd);
- sscanf(header, "%s %s %s", method, path + WDLEN, version);
- // handle default file name
- // if (!getExt(path, ext))strcat(path, "/index.html");
- getExecDir(path);
- // handle the request
- if (!strcmp("GET", method) || !strcmp("PUT", method)) {
- if (strlen(echo_buffer) > 0) {
- int size = strlen(echo_buffer);
- sprintf(buffer, "%s%d\r\n\r\n", "HTTP/1.1 200 OK\r\nContent-Length: ", size);
- send(socket, buffer, strlen(buffer), 0);
- send(socket, echo_buffer, size, 0);
- } else {
- // try to open the requested file
- FILE * file = fopen(path, "r");
- if (file) {
- fseek(file, 0, SEEK_END);
- int size = ftell(file);
- fseek(file, 0, 0);
- // send 200
- sprintf(buffer, "%s%d\r\n\r\n", "HTTP/1.1 200 OK\r\nContent-Length: ", size);
- send(socket, buffer, strlen(buffer), 0);
- cout << "200 " << path << endl;
- do {
- rd = fread(buffer, sizeof (char), BUFFERLENGTH, file);
- send(socket, buffer, rd, 0);
- } while (rd > 0);
- fclose(file);
- } else {
- // send 404
- sprintf(buffer, "%s\r\n\r\n", "HTTP/1.1 404 Not Found");
- send(socket, buffer, strlen(buffer), 0);
- cout << "404 " << path << endl;
- }
- }
- serving = false;
- Terminate(true);
- } else if (!strcmp("POST", method)) {
- if (fopen(path, "r") > 0) {
- int size = strlen(echo_buffer);
- sprintf(buffer, "%s%d\r\n\r\n", "HTTP/1.1 200 OK\r\nContent-Length: ", size);
- send(socket, buffer, strlen(buffer), 0);
- send(socket, echo_buffer, size, 0);
- continue;
- }
- FILE *file = fopen(path, "w+");
- if (file) {
- // send 200
- sprintf(buffer, "%s\r\n\r\n", "HTTP/1.1 200 OK");
- send(socket, buffer, strlen(buffer), 0);
- cout << "200 " << path << endl;
- // if client sent data after the header
- if (rd - hl > 4)
- fwrite(buffer + hl + 4, sizeof (char), rd - hl - 4, file);
- rd = read(socket, buffer, BUFFERLENGTH - 1);
- while (rd > 0) {
- fwrite(buffer, sizeof (char), rd, file);
- rd = read(socket, buffer, BUFFERLENGTH - 1);
- // TODO: implement blocks or read content length
- if (rd < BUFFERLENGTH - 1 || !strcmp(buffer - 4, term))
- break;
- }
- fclose(file);
- } else {
- sprintf(buffer, "%s\r\n\r\n", "HTTP/1.1 500 Internal Server Error");
- send(socket, buffer, strlen(buffer), 0);
- cout << "500 " << path << endl;
- }
- }
- }
- }
|