diff --git a/Makefile b/Makefile
index 3a9ef3d..6bff332 100644
--- a/Makefile
+++ b/Makefile
@@ -5,13 +5,14 @@ CLIENT=client
SERVER=server
ERROR=errors.o
CHALLENGE=challenges.o
+RANDOM=random.o
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
- $(CC) $(CCFLAGS) server.c -o server challenges.o errors.o
+$(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 random.o -lm
objcopy --add-section .RUN_ME="$(TMP)" --set-section-flags .mydata=noload,readonly server
strip --strip-debug server
rm "$(TMP)"
@@ -23,7 +24,7 @@ $(CLIENT): client.c errors.c include/errors.h include/client.h
$(CC) $(CCFLAGS) -I./include -c $<
clean:
- rm -rf $(ERROR) $(CHALLENGE) $(CLIENT) $(SERVER)
+ rm -rf $(ERROR) $(CHALLENGE) $(CLIENT) $(SERVER) $(RANDOM)
test:
pvs-studio-analyzer trace -- make
diff --git a/README.md b/README.md
index 7b3744a..0406afd 100644
--- a/README.md
+++ b/README.md
@@ -27,7 +27,19 @@ make all
## Ejecución
-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
@@ -37,7 +49,17 @@ En orden de realizar un análisis estático del sistema usted debe tener instala
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
- Barmasch, Juan Martín (61033)
diff --git a/challenges.c b/challenges.c
index cb9e3ed..bcc116e 100644
--- a/challenges.c
+++ b/challenges.c
@@ -2,8 +2,6 @@
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#include "include/challenges.h"
-char too_easy = 'a';
-
char genChallenge(FILE * stream, char ** output, challenge_t challenge) {
printf("------------- DESAFIO -------------\n");
printf("%s\n\n", challenge.message);
@@ -19,7 +17,6 @@ char genChallenge(FILE * stream, char ** output, challenge_t challenge) {
printSystemError("Challenges: getline()");
int ans = strcmp(*output, challenge.flag);
- // free(*output);
return !ans;
}
@@ -32,14 +29,14 @@ void filterChallenge() {
char * ans = "La respuesta es K5n2UFfpFMUN\n";
int i = 0;
while (ans[i] != '\0') {
- int fdRandom = (rand() % (UPPER - LOWER + 1)) + LOWER;
- if (fdRandom == STDOUT_FILENO) {
+ double fdRandom = getUniform(1);
+ if (fdRandom <= 0.25) {
if (write(STDOUT_FILENO, ans + i++, 1) < 0)
printSystemError("Challenges: write()");
}
else {
- for (int i = (rand() % (6)) + 1; i > 0; i--) {
- int randNum = 90 * (rand() / (RAND_MAX + 1.0));
+ for (int j = (int) getUniform(3) + 1; j > 0; j--) {
+ int randNum = (int) getUniform(90);
char randLetter = (char) (randNum + '#');
if (write(STDERR_FILENO, &randLetter, 1) < 0)
printSystemError("Challenges: write()");
@@ -95,4 +92,19 @@ void gdbChallenge() {
printf("La respuesta es gdb_rules\n");
else
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");
}
\ No newline at end of file
diff --git a/client.c b/client.c
index cac786e..46cb63f 100644
--- a/client.c
+++ b/client.c
@@ -2,15 +2,15 @@
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#include "include/client.h"
+void setSockAddress(int argc, char *argv[], struct sockaddr_in * address);
+
int main(int argc, char *argv[]) {
- int fd = 0;
+ int fd;
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
printSystemError("User: socket()");
struct sockaddr_in serv_addr;
- serv_addr.sin_family = AF_INET;
- serv_addr.sin_port = htons(PORT);
- serv_addr.sin_addr.s_addr = inet_addr(ADDRESS);
+ setSockAddress(argc, argv, &serv_addr);
if (connect(fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
printSystemError("User: connect()");
@@ -30,3 +30,30 @@ int main(int argc, char *argv[]) {
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");
+ }
+ }
+}
\ No newline at end of file
diff --git a/errors.c b/errors.c
index dd8ed0a..cb59560 100644
--- a/errors.c
+++ b/errors.c
@@ -3,8 +3,7 @@
#include "include/errors.h"
void printError(char * string) {
- fprintf(stderr, "%s", string);
- fprintf(stderr, "\n");
+ fprintf(stderr, "%s\n", string);
exit(EXIT_FAILURE);
}
diff --git a/include/challenges.h b/include/challenges.h
index a42626a..ae657b1 100644
--- a/include/challenges.h
+++ b/include/challenges.h
@@ -7,11 +7,15 @@
#include
#include
#include
+#include
#include "errors.h"
+#include "random.h"
#define MAX_LEN 100
+#define MAX_NORMALS 1000
#define UPPER 2
#define LOWER 1
+#define M_PI 3.14159265358979323846
typedef struct challenge_t {
char * message;
@@ -26,5 +30,6 @@ void filterChallenge();
void questionChallenge();
void quineChallenge();
void gdbChallenge();
+void normalChallenge();
#endif
\ No newline at end of file
diff --git a/include/challengesLib.h b/include/challengesLib.h
new file mode 100644
index 0000000..01c942d
--- /dev/null
+++ b/include/challengesLib.h
@@ -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
\ No newline at end of file
diff --git a/include/client.h b/include/client.h
index 277e179..f123fb2 100644
--- a/include/client.h
+++ b/include/client.h
@@ -1,6 +1,8 @@
#ifndef CLIENT_H
#define CLIENT_H
+#define _POSIX_C_SOURCE 200809L
+
#include
#include
#include
diff --git a/include/random.h b/include/random.h
new file mode 100644
index 0000000..dc80db5
--- /dev/null
+++ b/include/random.h
@@ -0,0 +1,8 @@
+#ifndef MATH_H
+#define MATH_H
+
+#include
+
+double getUniform(uint32_t max);
+
+#endif
\ No newline at end of file
diff --git a/include/server.h b/include/server.h
index 420629c..66839f7 100644
--- a/include/server.h
+++ b/include/server.h
@@ -13,46 +13,14 @@
#include
#include "errors.h"
#include "challenges.h"
+#include "challengesLib.h"
#define MAX_LEN 100
#define PORT 8080
#define ADDRESS "127.0.0.1"
#define MAX_PEND_REQ 3
-#define MAX_CHALLENGES 11
#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();
#endif
\ No newline at end of file
diff --git a/quine.c b/quine.c
index 9927c54..c86c7ce 100644
--- a/quine.c
+++ b/quine.c
@@ -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); }
diff --git a/random.c b/random.c
new file mode 100644
index 0000000..db49d70
--- /dev/null
+++ b/random.c
@@ -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;
+}
\ No newline at end of file
diff --git a/server.c b/server.c
index e9b97fb..44b7c54 100644
--- a/server.c
+++ b/server.c
@@ -2,6 +2,8 @@
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#include "include/server.h"
+void setSockAddress(int argc, char *argv[], struct sockaddr_in * address);
+
int main(int argc, char *argv[]) {
int fd;
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == 0)
@@ -12,10 +14,7 @@ int main(int argc, char *argv[]) {
printSystemError("Server: setsockopt()");
struct sockaddr_in address;
- address.sin_family = AF_INET;
- // address.sin_addr.s_addr = INADDR_ANY;
- address.sin_addr.s_addr = inet_addr(ADDRESS);
- address.sin_port = htons(PORT);
+ setSockAddress(argc, argv, &address);
if (bind(fd, (struct sockaddr *) &address, sizeof(address)) < 0)
printSystemError("Server: bind()");
@@ -27,6 +26,9 @@ int main(int argc, char *argv[]) {
if ((fdAux = accept(fd, (struct sockaddr *) &address, (socklen_t *) &addrlen)) < 0)
printSystemError("Server: accept()");
+ if (setvbuf(stdout, NULL, _IONBF, 0) != 0)
+ printSystemError("Server: setvbuf()");
+
startChallenge(fdAux);
close(fdAux);
@@ -43,7 +45,6 @@ void startChallenge(int fd) {
int challengeCount = 0;
char * output = NULL;
- srand(time(NULL));
while (challengeCount < MAX_CHALLENGES) {
challenge_t currentChallenge = challenges[challengeCount];
printf("\033[1;1H\033[2J");
@@ -57,7 +58,38 @@ void startChallenge(int fd) {
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;
+}
+
+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");
+ }
+ }
}
\ No newline at end of file