Make lots of improvements (and add extra features)

Co-authored-by: Ezequiel Bellver <ebellver@itba.edu.ar>
Co-authored-by: Juan Barmasch <jbarmasch@itba.edu.ar>
This commit is contained in:
Santiago Lo Coco 2021-11-07 22:04:16 -03:00
parent f91992bb62
commit c150cb1e4e
13 changed files with 202 additions and 60 deletions

View File

@ -5,13 +5,14 @@ CLIENT=client
SERVER=server SERVER=server
ERROR=errors.o ERROR=errors.o
CHALLENGE=challenges.o CHALLENGE=challenges.o
RANDOM=random.o
TMP := $(shell mktemp) TMP := $(shell mktemp)
all: $(ERROR) $(CHALLENGE) $(CLIENT) $(SERVER) all: $(ERROR) $(CHALLENGE) $(RANDOM) $(CLIENT) $(SERVER)
$(SERVER): server.c challenges.c errors.c include/errors.h include/challenges.h include/server.h $(SERVER): server.c challenges.c errors.c include/errors.h include/challenges.h include/server.h include/challengesLib.h
$(CC) $(CCFLAGS) server.c -o server challenges.o errors.o $(CC) $(CCFLAGS) server.c -o server challenges.o errors.o random.o -lm
objcopy --add-section .RUN_ME="$(TMP)" --set-section-flags .mydata=noload,readonly server objcopy --add-section .RUN_ME="$(TMP)" --set-section-flags .mydata=noload,readonly server
strip --strip-debug server strip --strip-debug server
rm "$(TMP)" rm "$(TMP)"
@ -23,7 +24,7 @@ $(CLIENT): client.c errors.c include/errors.h include/client.h
$(CC) $(CCFLAGS) -I./include -c $< $(CC) $(CCFLAGS) -I./include -c $<
clean: clean:
rm -rf $(ERROR) $(CHALLENGE) $(CLIENT) $(SERVER) rm -rf $(ERROR) $(CHALLENGE) $(CLIENT) $(SERVER) $(RANDOM)
test: test:
pvs-studio-analyzer trace -- make pvs-studio-analyzer trace -- make

View File

@ -27,7 +27,19 @@ make all
## Ejecución <a name="ejecución"></a> ## Ejecución <a name="ejecución"></a>
Ahora, tendrá dos ejecutables: `client` y `server`. Ahora, tendrá dos ejecutables: `client` y `server`. Note que primero debe correr el `server` y luego conectarse con el `client`.
```bash
./server
```
y en otra terminal
```bash
./client
```
Debe notar que el `server` usará el puerto 8080 de localhost por lo que si tiene algún otro servidor en ese puerto debe cerrarlo antes de correrlo.
## Testeos <a name="tests"></a> ## Testeos <a name="tests"></a>
@ -37,7 +49,17 @@ En orden de realizar un análisis estático del sistema usted debe tener instala
make test make test
``` ```
Por último, si quiere hacer un análisis dinámico (usando [valgrind](https://valgrind.org/)) debe... Por último, si quiere hacer un análisis dinámico (usando [valgrind](https://valgrind.org/)) puede hacerlo mediante:
```bash
valgrind ./server
```
y en otra terminal
```bash
valgrind ./client
```
# Autores # Autores
- Barmasch, Juan Martín (61033) - Barmasch, Juan Martín (61033)

View File

@ -2,8 +2,6 @@
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com // PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#include "include/challenges.h" #include "include/challenges.h"
char too_easy = 'a';
char genChallenge(FILE * stream, char ** output, challenge_t challenge) { char genChallenge(FILE * stream, char ** output, challenge_t challenge) {
printf("------------- DESAFIO -------------\n"); printf("------------- DESAFIO -------------\n");
printf("%s\n\n", challenge.message); printf("%s\n\n", challenge.message);
@ -19,7 +17,6 @@ char genChallenge(FILE * stream, char ** output, challenge_t challenge) {
printSystemError("Challenges: getline()"); printSystemError("Challenges: getline()");
int ans = strcmp(*output, challenge.flag); int ans = strcmp(*output, challenge.flag);
// free(*output);
return !ans; return !ans;
} }
@ -32,14 +29,14 @@ void filterChallenge() {
char * ans = "La respuesta es K5n2UFfpFMUN\n"; char * ans = "La respuesta es K5n2UFfpFMUN\n";
int i = 0; int i = 0;
while (ans[i] != '\0') { while (ans[i] != '\0') {
int fdRandom = (rand() % (UPPER - LOWER + 1)) + LOWER; double fdRandom = getUniform(1);
if (fdRandom == STDOUT_FILENO) { if (fdRandom <= 0.25) {
if (write(STDOUT_FILENO, ans + i++, 1) < 0) if (write(STDOUT_FILENO, ans + i++, 1) < 0)
printSystemError("Challenges: write()"); printSystemError("Challenges: write()");
} }
else { else {
for (int i = (rand() % (6)) + 1; i > 0; i--) { for (int j = (int) getUniform(3) + 1; j > 0; j--) {
int randNum = 90 * (rand() / (RAND_MAX + 1.0)); int randNum = (int) getUniform(90);
char randLetter = (char) (randNum + '#'); char randLetter = (char) (randNum + '#');
if (write(STDERR_FILENO, &randLetter, 1) < 0) if (write(STDERR_FILENO, &randLetter, 1) < 0)
printSystemError("Challenges: write()"); printSystemError("Challenges: write()");
@ -96,3 +93,18 @@ void gdbChallenge() {
else else
printf("ENTER para reintentar.\n"); printf("ENTER para reintentar.\n");
} }
void boxMuller(double * normal) {
double random1 = getUniform(1);
double random2 = getUniform(1);
*normal = sqrt(-2 * log(random1)) * cos(2 * M_PI * random2);
}
void normalChallenge() {
for (int i = 0; i < MAX_NORMALS; i++) {
double normal = 0;
boxMuller(&normal);
printf("%.6f ", normal);
}
printf("\n");
}

View File

@ -2,15 +2,15 @@
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com // PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#include "include/client.h" #include "include/client.h"
void setSockAddress(int argc, char *argv[], struct sockaddr_in * address);
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
int fd = 0; int fd;
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
printSystemError("User: socket()"); printSystemError("User: socket()");
struct sockaddr_in serv_addr; struct sockaddr_in serv_addr;
serv_addr.sin_family = AF_INET; setSockAddress(argc, argv, &serv_addr);
serv_addr.sin_port = htons(PORT);
serv_addr.sin_addr.s_addr = inet_addr(ADDRESS);
if (connect(fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) if (connect(fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
printSystemError("User: connect()"); printSystemError("User: connect()");
@ -30,3 +30,30 @@ int main(int argc, char *argv[]) {
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
void setSockAddress(int argc, char *argv[], struct sockaddr_in * address) {
address->sin_family = AF_INET;
if (argc == 1) {
address->sin_addr.s_addr = inet_addr(ADDRESS);
address->sin_port = htons(PORT);
}
int opt;
while ((opt = getopt(argc, argv, "a:p:")) != -1) {
switch (opt) {
case 'a':
if (optarg[0] == '-')
printError("Usage: server [-a address] [-p port]\n");
address->sin_addr.s_addr = inet_addr(optarg);
break;
case 'p':
if (optarg[0] == '-')
printError("Usage: server [-a address] [-p port]\n");
address->sin_port = htons(atoi(optarg));
break;
default:
printError("Usage: server [-a address] [-p port]\n");
}
}
}

View File

@ -3,8 +3,7 @@
#include "include/errors.h" #include "include/errors.h"
void printError(char * string) { void printError(char * string) {
fprintf(stderr, "%s", string); fprintf(stderr, "%s\n", string);
fprintf(stderr, "\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }

View File

@ -7,11 +7,15 @@
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <math.h>
#include "errors.h" #include "errors.h"
#include "random.h"
#define MAX_LEN 100 #define MAX_LEN 100
#define MAX_NORMALS 1000
#define UPPER 2 #define UPPER 2
#define LOWER 1 #define LOWER 1
#define M_PI 3.14159265358979323846
typedef struct challenge_t { typedef struct challenge_t {
char * message; char * message;
@ -26,5 +30,6 @@ void filterChallenge();
void questionChallenge(); void questionChallenge();
void quineChallenge(); void quineChallenge();
void gdbChallenge(); void gdbChallenge();
void normalChallenge();
#endif #endif

51
include/challengesLib.h Normal file
View File

@ -0,0 +1,51 @@
#ifndef CHALLENGESLIB_H
#define CHALLENGESLIB_H
#include "challenges.h"
#define MAX_CHALLENGES 12
challenge_t challenges[] = {
{"Bienvenidos al TP3 y felicitaciones, ya resolvieron el primer acertijo.\n\n\
En este TP deberán finalizar el juego que ya comenzaron resolviendo los desafíos \
de cada nivel.\nAdemás tendrán que investigar otras preguntas para responder \
durante la defensa.\nEl desafío final consiste en crear un programa que se \
comporte igual que yo, es decir, que provea los mismos desafíos y que sea necesario \
hacer lo mismo para resolverlos. No basta con esperar la respuesta.\nAdemás, \
deberán implementar otro programa para comunicarse conmigo.\n\nDeberán estar atentos \
a los easter eggs.\n\nPara verificar que sus respuestas tienen el formato correcto \
respondan a este desafío con la palabra 'entendido\\n'", "¿Cómo descubrieron el protocolo, \
la dirección y el puerto para conectarse?", "entendido\n", NULL},
{"The Wire S1E5\n5295 888 6288", "¿Qué diferencias hay entre TCP y UDP y en qué casos \
conviene usar cada uno?", "itba\n", NULL},
{"https://ibb.co/tc0Hb6w", "¿El puerto que usaron para conectarse al server es el mismo \
que usan para mandar las respuestas? ¿Por qué?", "M4GFKZ289aku\n", NULL},
{"EBADF...", "¿Qué útil abstracción es utilizada para comunicarse con sockets? ¿se puede \
utilizar read(2) y write(2) para operar?", "fk3wfLCm3QvS\n", writeChallenge},
{"respuesta = strings:269", "¿Cómo garantiza TCP que los paquetes llegan en orden y no se \
pierden?", "too_easy\n", NULL},
{".data .bss .comment ? .shstrtab .symtab .strtab", "Un servidor suele crear un nuevo proceso \
o thread para atender las conexiones entrantes. ¿Qué conviene más?", ".RUN_ME\n", NULL},
{"Filter error", "¿Cómo se puede implementar un servidor que atienda muchas conexiones sin usar \
procesos ni threads?", "K5n2UFfpFMUN\n", filterChallenge},
{"¿?", "¿Qué aplicaciones se pueden utilizar para ver el tráfico por la red?",
"BUmyYq5XxXGt\n", questionChallenge},
{"Latexme\n\nSi\n \\mathrm{d}y = u^v{\\cdot}(v'{\\cdot}\\ln{(u)}+v{\\cdot}\\frac{u'}{u})\n\
entonces\ny = ", "sockets es un mecanismo de IPC. ¿Qué es más eficiente entre sockets y pipes?",
"u^v\n", NULL},
{"quine", "¿Cuáles son las características del protocolo SCTP?", "chin_chu_lan_cha\n", quineChallenge},
{"b gdbme y encontrá el valor mágico", "¿Qué es un RFC?", "gdb_rules\n", gdbChallenge},
{"Me conoces", "¿Fue divertido?", "normal\n", normalChallenge}
};
char too_easy = 'a';
char * easter_egg1 = " _______________________\n\
< ESTO ES UN EASTER_EGG >\n\
-----------------------\n\
\\ ^__^\n\
\\ (oo)\\_______\n\n\
(__)\\ )\\/\\\n\
||----w |\n\
|| ||\n";
#endif

View File

@ -1,6 +1,8 @@
#ifndef CLIENT_H #ifndef CLIENT_H
#define CLIENT_H #define CLIENT_H
#define _POSIX_C_SOURCE 200809L
#include <stdio.h> #include <stdio.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <arpa/inet.h> #include <arpa/inet.h>

8
include/random.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef MATH_H
#define MATH_H
#include <stdint.h>
double getUniform(uint32_t max);
#endif

View File

@ -13,46 +13,14 @@
#include <netinet/in.h> #include <netinet/in.h>
#include "errors.h" #include "errors.h"
#include "challenges.h" #include "challenges.h"
#include "challengesLib.h"
#define MAX_LEN 100 #define MAX_LEN 100
#define PORT 8080 #define PORT 8080
#define ADDRESS "127.0.0.1" #define ADDRESS "127.0.0.1"
#define MAX_PEND_REQ 3 #define MAX_PEND_REQ 3
#define MAX_CHALLENGES 11
#define TIME_SLEEP 2 #define TIME_SLEEP 2
challenge_t challenges[] = {
{"Bienvenidos al TP3 y felicitaciones, ya resolvieron el primer acertijo.\n\n\
En este TP deberán finalizar el juego que ya comenzaron resolviendo los desafíos \
de cada nivel.\n\nAdemás tendrán que investigar otras preguntas para responder \
durante la defensa.\n\nEl desafío final consiste en crear un programa que se \
comporte igual que yo, es decir, que provea los mismos desafíos y que sea necesario \
hacer lo mismo para resolverlos. No basta con esperar la respuesta.\n\nAdemás, \
deberán implementar otro programa para comunicarse conmigo.\n\nDeberán estar atentos \
a los easter eggs.\n\nPara verificar que sus respuestas tienen el formato correcto \
respondan a este desafío con la palabra 'entendido\\n'", "¿Cómo descubrieron el protocolo, \
la dirección y el puerto para conectarse?", "entendido\n", NULL},
{"The Wire S1E5\n\n5295 888 6288", "¿Qué diferencias hay entre TCP y UDP y en qué casos \
conviene usar cada uno?", "itba\n", NULL},
{"https://ibb.co/tc0Hb6w", "¿El puerto que usaron para conectarse al server es el mismo \
que usan para mandar las respuestas? ¿Por qué?", "M4GFKZ289aku\n", NULL},
{"EBADF...", "¿Qué útil abstracción es utilizada para comunicarse con sockets? ¿se puede \
utilizar read(2) y write(2) para operar?", "fk3wfLCm3QvS\n", writeChallenge},
{"respuesta = strings:269", "¿Cómo garantiza TCP que los paquetes llegan en orden y no se \
pierden?", "too_easy\n", NULL},
{".data .bss .comment ? .shstrtab .symtab .strtab", "Un servidor suele crear un nuevo proceso \
o thread para atender las conexiones entrantes. ¿Qué conviene más?", ".RUN_ME\n", NULL},
{"Filter error", "¿Cómo se puede implementar un servidor que atienda muchas conexiones sin usar \
procesos ni threads?", "K5n2UFfpFMUN\n", filterChallenge},
{"¿?", "¿Qué aplicaciones se pueden utilizar para ver el tráfico por la red?",
"BUmyYq5XxXGt\n", questionChallenge},
{"Latexme\n\nSi\n \\mathrm{d}y = u^v{\\cdot}(v'{\\cdot}\\ln{(u)}+v{\\cdot}\\frac{u'}{u})\n\
entonces\ny =", "sockets es un mecanismo de IPC. ¿Qué es más eficiente entre sockets y pipes?",
"u^v\n", NULL},
{"quine", "¿Cuáles son las características del protocolo SCTP?", "chin_chu_lan_cha\n", quineChallenge},
{"b gdbme y encontrá el valor mágico", "¿Qué es un RFC?", "gdb_rules\n", gdbChallenge},
};
void startChallenge(); void startChallenge();
#endif #endif

View File

@ -1,3 +1 @@
// This is a personal academic project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
main() { char *s="main() { char *s=%c%s%c; printf(s,34,s,34,10); }%c"; printf(s,34,s,34,10); } main() { char *s="main() { char *s=%c%s%c; printf(s,34,s,34,10); }%c"; printf(s,34,s,34,10); }

17
random.c Normal file
View File

@ -0,0 +1,17 @@
// This is a personal academic project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#include "include/random.h"
static uint32_t m_z = 362436069;
static uint32_t m_w = 521288629;
uint32_t getUint() {
m_z = 36969 * (m_z & 65535) + (m_z >> 16);
m_w = 18000 * (m_w & 65535) + (m_w >> 16);
return (m_z << 16) + m_w;
}
double getUniform(uint32_t max) {
uint32_t u = getUint();
return (u + 1.0) * 2.328306435454494e-10 * max;
}

View File

@ -2,6 +2,8 @@
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com // PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#include "include/server.h" #include "include/server.h"
void setSockAddress(int argc, char *argv[], struct sockaddr_in * address);
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
int fd; int fd;
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == 0)
@ -12,10 +14,7 @@ int main(int argc, char *argv[]) {
printSystemError("Server: setsockopt()"); printSystemError("Server: setsockopt()");
struct sockaddr_in address; struct sockaddr_in address;
address.sin_family = AF_INET; setSockAddress(argc, argv, &address);
// address.sin_addr.s_addr = INADDR_ANY;
address.sin_addr.s_addr = inet_addr(ADDRESS);
address.sin_port = htons(PORT);
if (bind(fd, (struct sockaddr *) &address, sizeof(address)) < 0) if (bind(fd, (struct sockaddr *) &address, sizeof(address)) < 0)
printSystemError("Server: bind()"); printSystemError("Server: bind()");
@ -27,6 +26,9 @@ int main(int argc, char *argv[]) {
if ((fdAux = accept(fd, (struct sockaddr *) &address, (socklen_t *) &addrlen)) < 0) if ((fdAux = accept(fd, (struct sockaddr *) &address, (socklen_t *) &addrlen)) < 0)
printSystemError("Server: accept()"); printSystemError("Server: accept()");
if (setvbuf(stdout, NULL, _IONBF, 0) != 0)
printSystemError("Server: setvbuf()");
startChallenge(fdAux); startChallenge(fdAux);
close(fdAux); close(fdAux);
@ -43,7 +45,6 @@ void startChallenge(int fd) {
int challengeCount = 0; int challengeCount = 0;
char * output = NULL; char * output = NULL;
srand(time(NULL));
while (challengeCount < MAX_CHALLENGES) { while (challengeCount < MAX_CHALLENGES) {
challenge_t currentChallenge = challenges[challengeCount]; challenge_t currentChallenge = challenges[challengeCount];
printf("\033[1;1H\033[2J"); printf("\033[1;1H\033[2J");
@ -57,7 +58,38 @@ void startChallenge(int fd) {
free(output); free(output);
} }
fclose(stream); printf("\033[1;1H\033[2J");
printf("Felicitaciones, finalizaron el juego. Ahora deberán implementar el servidor que se comporte como el servidor provisto\n");
if (stream != NULL)
fclose(stream);
return; return;
} }
void setSockAddress(int argc, char *argv[], struct sockaddr_in * address) {
address->sin_family = AF_INET;
if (argc == 1) {
address->sin_addr.s_addr = inet_addr(ADDRESS);
address->sin_port = htons(PORT);
}
int opt;
while ((opt = getopt(argc, argv, "a:p:")) != -1) {
switch (opt) {
case 'a':
if (optarg[0] == '-')
printError("Usage: server [-a address] [-p port]\n");
address->sin_addr.s_addr = inet_addr(optarg);
break;
case 'p':
if (optarg[0] == '-')
printError("Usage: server [-a address] [-p port]\n");
address->sin_port = htons(atoi(optarg));
break;
default:
printError("Usage: server [-a address] [-p port]\n");
}
}
}