220 lines
4.3 KiB
C
220 lines
4.3 KiB
C
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <netdb.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <pthread.h>
|
|
#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);
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|