#include #include #include #include #include #include #include #include #include #include "db.h" #define BUF_SIZE 512 #define MAX 10 #define PORT 9000 sqlite3 *db; enum method_t { GET, DELETE, POST }; typedef struct client_t { int sock; } client_t; typedef struct request_t { enum method_t method; int sock; char *endPoint; } request_t; void *handleClient(void *client); void parseRequest(int sock, char *req); void getJoke(request_t request); void deleteJoke(request_t request); void newJoke(request_t request, char *data); int main(int argc, char *argv[]) { db = initDB(); if (!db) { perror("error init db"); return -1; } int serverSock = 0, clientSock; struct sockaddr_in serverAddr, clientAddr; pthread_t threadID = 1; serverSock = socket(AF_INET, SOCK_STREAM, 0); if (serverSock < 0) { perror("listen socket failed"); return -1; } int on = 1; if (setsockopt(serverSock, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) { perror("listen setsockopt failed"); return -1; } serverAddr.sin_family = AF_INET; serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); serverAddr.sin_port = htons(PORT); if (bind(serverSock, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0) { perror("failed to bind"); } if (listen(serverSock, MAX) < 0) { perror("failed to listen"); } while(true) { socklen_t clientLen = sizeof(clientAddr); if ((clientSock = accept(serverSock, (struct sockaddr *)&clientAddr, &clientLen)) < 0) { perror("could not accept client"); continue; } client_t *c = (client_t *)malloc(sizeof(client_t)); c->sock = clientSock; if ((pthread_create(&threadID, NULL, handleClient, (void *)c)) < 0) { perror("Could not create pthread"); close(clientSock); continue; } pthread_join(threadID, NULL); free(c); } close(serverSock); return 0; } void *handleClient(void *c) { client_t *client = (client_t*)c; if (!client) { perror("could not create our client_t"); return NULL; } int read = 0; char buf[BUF_SIZE]; if ((read = recv(client->sock, buf, BUF_SIZE, 0)) <= 0) { perror("Client disconnected"); close(client->sock); return NULL; } parseRequest(client->sock, buf); close(client->sock); return NULL; } void parseRequest(int sock, char *req) { request_t httpReq; httpReq.sock = sock; char *lines[10]; char *token = NULL; int i = 0; token = strtok(req, "\n"); lines[i++] = token; while (token) { token = strtok(NULL, "\n"); lines[i++] = token; } char topLine[BUF_SIZE]; strcpy(topLine, lines[0]); // POST, GET, DELETE char *request = strtok(lines[0], " "); if (strcmp(request, "POST") == 0) { httpReq.method = POST; } else if (strcmp(request, "GET") == 0) { httpReq.method = GET; } else if (strcmp(request, "DELETE") == 0) { httpReq.method = DELETE; } int len = strlen(request); request = topLine + len; char *endPoint = strtok(request, " "); httpReq.endPoint = endPoint; if (httpReq.method == GET) { getJoke(httpReq); } else if (httpReq.method == DELETE) { deleteJoke(httpReq); } else if (httpReq.method == POST) { newJoke(httpReq, lines[7]); } } void getJoke(request_t request) { char *joke = GetJoke(db); if (joke) { send(request.sock, joke, strlen(joke), 0); } else { char *msg = "error getting the joke"; send(request.sock, msg, strlen(msg), 0); } } void deleteJoke(request_t request) { // /joke/{id} char *val = request.endPoint + 6; int id = atoi(val); if (DeleteJoke(db, id)) { char msg[128]; sprintf(msg, "deleted joke %d\n", id); send(request.sock, msg, strlen(msg), 0); } else { char *msg = "error deleting the joke"; send(request.sock, msg, strlen(msg), 0); } } void newJoke(request_t request, char *data) { char *joke = strtok(data, ":"); joke = strtok(NULL, ":"); int len = strlen(joke); joke[len-1] = '\0'; if (NewJoke(db, joke)) { char msg[256]; sprintf(msg, "created new joke %s\n", joke); send(request.sock, msg, strlen(msg), 0); } else { char *msg = "error creating new joke"; send(request.sock, msg, strlen(msg), 0); } }