init
This commit is contained in:
151
dbclient.c
Normal file
151
dbclient.c
Normal file
@@ -0,0 +1,151 @@
|
||||
#include "dbclient.h"
|
||||
|
||||
char *construct_header(char *key, char *value) {
|
||||
char *header = NULL;
|
||||
|
||||
// If there is no value, make a get request, otherwise make a put request
|
||||
// with that value
|
||||
if (!value) {
|
||||
size_t needed_size = snprintf(NULL, 0, GET_REQUEST, key);
|
||||
header = (char *)malloc(needed_size + sizeof(char));
|
||||
sprintf(header, GET_REQUEST, key);
|
||||
} else {
|
||||
size_t body_size = strlen(value) * sizeof(char);
|
||||
size_t needed_size =
|
||||
snprintf(NULL, 0, PUT_REQUEST, key, body_size, value);
|
||||
header = (char *)malloc(needed_size + sizeof(char));
|
||||
sprintf(header, PUT_REQUEST, key, body_size, value);
|
||||
}
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
int handle_connect(char *port, int *fd) {
|
||||
struct addrinfo *ai = NULL;
|
||||
struct addrinfo hints;
|
||||
memset(&hints, 0, sizeof(struct addrinfo));
|
||||
|
||||
// Set hints
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
// Get address information
|
||||
int err;
|
||||
if ((err = getaddrinfo("localhost", port, &hints, &ai))) {
|
||||
freeaddrinfo(ai);
|
||||
fprintf(stderr, "%s\n", gai_strerror(err));
|
||||
return EXIT_ERR;
|
||||
}
|
||||
|
||||
// Connect to port
|
||||
*fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
// clang-format off
|
||||
if (connect(*fd, (struct sockaddr *)ai->ai_addr,
|
||||
sizeof(struct sockaddr))) {
|
||||
// clang-format on
|
||||
freeaddrinfo(ai);
|
||||
close(*fd);
|
||||
|
||||
fprintf(stderr, "dbclient: unable to connect to port %s\n", port);
|
||||
return EXIT_PORT_ERR;
|
||||
}
|
||||
freeaddrinfo(ai);
|
||||
|
||||
return EXIT_OK;
|
||||
}
|
||||
|
||||
int handle_response(FILE *recv, int valueSet) {
|
||||
HttpHeader **responseHeaders = NULL;
|
||||
memset(&responseHeaders, 0, sizeof(HttpHeader *));
|
||||
|
||||
int status;
|
||||
char *statusExplain = NULL;
|
||||
char *body = NULL;
|
||||
get_HTTP_response(recv, &status, &statusExplain, &responseHeaders, &body);
|
||||
|
||||
// Print the value only if GET and got status 200
|
||||
if (!valueSet && status == 200) {
|
||||
printf("%s\n", body);
|
||||
}
|
||||
|
||||
free_array_of_headers(responseHeaders);
|
||||
free(statusExplain);
|
||||
free(body);
|
||||
|
||||
if (status != 200 && valueSet) {
|
||||
return EXIT_PUT_ERR;
|
||||
} else if (status != 200) {
|
||||
return EXIT_GET_ERR;
|
||||
}
|
||||
|
||||
return EXIT_OK;
|
||||
}
|
||||
|
||||
int handle_connection(char *port, char *key, char *value) {
|
||||
int connectStatus = 0;
|
||||
int sendFd;
|
||||
if ((connectStatus = handle_connect(port, &sendFd))) {
|
||||
close(sendFd);
|
||||
return connectStatus;
|
||||
}
|
||||
|
||||
// Setup fd's for sending and receiving requests
|
||||
int recvFd = dup(sendFd);
|
||||
FILE *send = fdopen(sendFd, "w");
|
||||
FILE *recv = fdopen(recvFd, "r");
|
||||
|
||||
// Send Request
|
||||
char *header = construct_header(key, value);
|
||||
fprintf(send, "%s", header);
|
||||
fflush(send);
|
||||
fclose(send);
|
||||
free(header);
|
||||
close(sendFd);
|
||||
|
||||
// Get Response
|
||||
int valueSet = (value != NULL);
|
||||
int exitCode = handle_response(recv, valueSet);
|
||||
fclose(recv);
|
||||
close(recvFd);
|
||||
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
int is_valid_key(char *key) {
|
||||
for (int i = 0; i < strlen(key); i++) {
|
||||
if (isspace(key[i])) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc < 3) {
|
||||
fprintf(stderr, "Usage: dbclient portnum key [value]\n");
|
||||
return EXIT_ERR;
|
||||
}
|
||||
|
||||
char *portnumArgument = strdup(argv[1]);
|
||||
char *keyArgument = strdup(argv[2]);
|
||||
char *valueArgument = NULL;
|
||||
|
||||
if (argc > 3) {
|
||||
valueArgument = strdup(argv[3]);
|
||||
}
|
||||
|
||||
if (!is_valid_key(keyArgument)) {
|
||||
fprintf(stderr, "dbclient: key must not contain spaces or newlines\n");
|
||||
return EXIT_ERR;
|
||||
}
|
||||
|
||||
int exitStatus =
|
||||
handle_connection(portnumArgument, keyArgument, valueArgument);
|
||||
|
||||
free(portnumArgument);
|
||||
free(keyArgument);
|
||||
free(valueArgument);
|
||||
|
||||
return exitStatus;
|
||||
}
|
||||
Reference in New Issue
Block a user