Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Jonathan Galvan Perez 101250 || Alejandro Balladares 101118
- #define _XOPEN_SOURCE
- #define _POSIX_C_SOURCE 200809L //getline
- #include "strutil.h"
- #include "heap.h"
- #include "hash.h"
- #include "abb.h"
- #include "lista.h"
- #include <string.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <stdbool.h>
- #include <time.h>
- #define DOS 2
- #define LIMITE_DE_DOS 5
- #define SEP_COMANDOS ' '
- #define SEP_REQUEST '\t'
- #define SEP_IP '.'
- #define TIME_FORMAT "%FT%T%z"
- //////////////////////////////////////////////////////////////////////////////////////
- /* ESTRUCTURAS DE DATOS */
- //////////////////////////////////////////////////////////////////////////////////////
- typedef struct dato{
- const char* url;
- int visitas;
- }dato_t;
- typedef struct request{
- char* ip;
- time_t tiempo;
- char* metodo;
- char* url;
- } request_t;
- //////////////////////////////////////////////////////////////////////////////////////
- /* FUNCIONES AUXILIARES */
- //////////////////////////////////////////////////////////////////////////////////////
- time_t iso8601_to_time(const char* iso8601){
- struct tm bktime = { 0 };
- strptime(iso8601, TIME_FORMAT, &bktime);
- return mktime(&bktime);
- }
- char* quitar_barra_n(char* cadena){
- size_t largo = strlen(cadena);
- if(cadena[largo-1] == '\n') cadena[largo-1] = '\0';
- return cadena;
- }
- void conseguir_request(char* linea, request_t* request){
- char* linea_aux = quitar_barra_n(linea);
- char** campos = split(linea_aux, SEP_REQUEST);
- request->ip = strdup(campos[0]);
- request->tiempo = iso8601_to_time(campos[1]);
- request->url = strdup(campos[3]);
- free_strv(campos);
- }
- void request_destruir(request_t* request){
- free(request->ip);
- free(request->url);
- }
- void lista_wrapper(void* lista_void){
- lista_t* lista = lista_void;
- lista_destruir(lista, free);
- }
- int comparar_visitas(const void* dato1_void, const void* dato2_void){
- const dato_t* dato1 = dato1_void;
- const dato_t* dato2 = dato2_void;
- return dato2->visitas - dato1->visitas; //funcion al reves para heap de minimos
- }
- int comparar_ips(const char* ip1, const char* ip2){
- int respuesta = 0;
- char** ip1_partes = split(ip1, SEP_IP);
- int ip1_campos[4];
- ip1_campos[0] = atoi(ip1_partes[0]);
- ip1_campos[1] = atoi(ip1_partes[1]);
- ip1_campos[2] = atoi(ip1_partes[2]);
- ip1_campos[3] = atoi(ip1_partes[3]);
- char** ip2_partes = split(ip2, SEP_IP);
- int ip2_campos[4];
- ip2_campos[0] = atoi(ip2_partes[0]);
- ip2_campos[1] = atoi(ip2_partes[1]);
- ip2_campos[2] = atoi(ip2_partes[2]);
- ip2_campos[3] = atoi(ip2_partes[3]);
- for(int i = 0; i < 4; i++){
- if(ip1_campos[i] > ip2_campos[i]){
- respuesta = 1;
- break;
- }
- if(ip1_campos[i] < ip2_campos[i]){
- respuesta = -1;
- break;
- }
- }
- free_strv(ip1_partes);
- free_strv(ip2_partes);
- return respuesta;
- }
- bool imprimir_dos(const char* ip, void* extra1, void* extra2){
- printf("DoS: %s\n", ip);
- return true;
- }
- bool imprimir_ip(const char* clave){
- printf("\t%s\n",clave);
- return true;
- }
- void imprimir_url_maximos(heap_t* mas_visitados){
- if (heap_esta_vacio(mas_visitados)) return;
- dato_t* dato = heap_desencolar(mas_visitados);
- imprimir_url_maximos(mas_visitados);
- printf("\t%s - %d\n",dato->url, dato->visitas);
- free(dato);
- }
- //////////////////////////////////////////////////////////////////////////////////////
- /* FUNCIONES PRINCIPALES */
- //////////////////////////////////////////////////////////////////////////////////////
- bool agregar_archivo(char* archivo, abb_t* abb_ips, hash_t* url_visitas);
- bool ver_visitantes(abb_t* arbol_ips, char* desde, char* hasta);
- void ver_mas_visitados(size_t n, hash_t* url_visitas);
- int ejecutar_comando(char** comando, abb_t* abb_ips, hash_t* url_visitas);
- int main(int argc,char* argv[]){
- if(argc >= 2) return 0;
- int errores_tipo2 = 0;
- abb_t* abb_ips = abb_crear(comparar_ips, NULL);
- hash_t* url_visitas = hash_crear(free);
- char* linea = NULL; size_t capacidad = 0; ssize_t leidos;
- while((leidos = getline(&linea,&capacidad,stdin)) > 0){
- char* comando_aux = quitar_barra_n(linea);
- char** comando = split(comando_aux,' ');
- errores_tipo2 = ejecutar_comando(comando, abb_ips, url_visitas);
- if(errores_tipo2 > 0) break;
- }
- free(linea);
- abb_destruir(abb_ips);
- hash_destruir(url_visitas);
- return 0;
- }
- int ejecutar_comando(char** comando, abb_t* abb_ips, hash_t* url_visitas){
- int errores_tipo2 = 0;
- if(strcmp(comando[0], "agregar_archivo") == 0){
- if(!comando[1]){
- fprintf(stderr, "%s\n","Error en comando agregar_archivo");
- errores_tipo2++;
- }else
- if(!agregar_archivo(comando[1], abb_ips, url_visitas)) errores_tipo2++;
- }else if(strcmp(comando[0], "ver_visitantes") == 0){
- if(!comando[1] || !comando[2]){
- fprintf(stderr, "%s\n","Error en comando ver_visitantes");
- errores_tipo2++;
- }else
- if(!ver_visitantes(abb_ips, comando[1], comando[2])) errores_tipo2++;
- }else if(strcmp(comando[0], "ver_mas_visitados") == 0){
- if(!comando[1]){
- fprintf(stderr, "%s\n","Error en comando ver_mas_visitados");
- errores_tipo2++;
- }else ver_mas_visitados(atoi(comando[1]), url_visitas);
- }else{
- fprintf(stderr, "%s %s\n","Error en comando",comando[0]);
- errores_tipo2++;
- }
- free_strv(comando);
- return errores_tipo2;
- }
- void guardar_url(hash_t* hash_visitas, request_t* request){
- if(!hash_pertenece(hash_visitas, request->url)){
- int* visitas = malloc(sizeof(int));
- *visitas = 1;
- hash_guardar(hash_visitas, request->url, visitas);
- }else{
- int* visitas = hash_obtener(hash_visitas, request->url);
- *visitas = *visitas + 1;
- }
- }
- // Recorre todas las listas del "hash_lista_tiempos", a menos que tenga menos de 5
- // elementos (time_t*). A medida va desencolando cada elemento de una lista los
- // inserta en una lista vacia "lista_dos" de manera que todos los elementos en ella
- // no tengan una diferencia mayor o igual a 2 segundos. Si el nuevo elemento rompe
- // la invariante, borra el primer elemento de la "lista_dos" hasta que se vuelva a
- // cumplir. Si "lista_dos" llega a 5 elementos inserta la ip en un arbol "abb_dos".
- abb_t* detectar_dos(hash_t* hash_lista_tiempos){
- abb_t* abb_dos = abb_crear(comparar_ips, NULL);
- hash_iter_t* hash_iter = hash_iter_crear(hash_lista_tiempos);
- while(!hash_iter_al_final(hash_iter)){
- const char* ip = hash_iter_ver_actual(hash_iter);
- lista_t* lista_tiempos = hash_obtener(hash_lista_tiempos, ip);
- if(lista_largo(lista_tiempos) < 5){
- hash_iter_avanzar(hash_iter);
- continue;
- }
- lista_t* lista_dos = lista_crear();
- time_t* tiempo_inicial = lista_borrar_primero(lista_tiempos);
- lista_insertar_ultimo(lista_dos, tiempo_inicial);
- while(!lista_esta_vacia(lista_tiempos)){
- time_t* tiempo_ult = lista_borrar_primero(lista_tiempos);
- double diferencia = difftime(*tiempo_ult, *tiempo_inicial);
- while(diferencia >= DOS){
- time_t* tiempo_borrar = lista_borrar_primero(lista_dos);
- free(tiempo_borrar);
- tiempo_inicial = lista_ver_primero(lista_dos);
- if (!tiempo_inicial) break;
- diferencia = difftime(*tiempo_ult, *tiempo_inicial);
- }
- lista_insertar_ultimo(lista_dos, tiempo_ult);
- if(lista_largo(lista_dos) == 5)
- abb_guardar(abb_dos, ip , NULL);
- tiempo_inicial = lista_ver_primero(lista_dos);
- }
- lista_destruir(lista_dos, free);
- hash_iter_avanzar(hash_iter);
- }
- hash_iter_destruir(hash_iter);
- return abb_dos;
- }
- bool agregar_archivo(char* nombre_archivo, abb_t* abb_ips, hash_t* url_visitas){
- FILE* archivo = fopen(nombre_archivo,"r");
- if(archivo == NULL){
- fprintf(stderr, "%s\n","Error en comando agregar_archivo");
- return false;
- }
- hash_t* hash_lista_tiempos = hash_crear(lista_wrapper);
- char* linea = NULL; size_t capacidad = 0; ssize_t leidos;
- while((leidos = getline(&linea,&capacidad,archivo)) > 0){
- // request es una variable estatica que almacena la informacion relevante
- // de la linea (ip, url, tiempo)
- request_t request;
- conseguir_request(linea, &request);
- char* ip = request.ip;
- // Actualiza el arbol de ips para "ver_vistantes"
- if(!abb_pertenece(abb_ips, request.ip)) abb_guardar(abb_ips, request.ip, NULL);
- // Actualiza el hash de urls para "ver_mas_visitados"
- guardar_url(url_visitas, &request);
- // Actualiza el hash de listas de tiempos para "detectar_dos"
- time_t* tiempo_nuevo = malloc(sizeof(time_t));
- *tiempo_nuevo = request.tiempo;
- if(hash_pertenece(hash_lista_tiempos, ip)){
- lista_t* lista_tiempos = hash_obtener(hash_lista_tiempos, ip);
- lista_insertar_ultimo(lista_tiempos, tiempo_nuevo);
- }else{
- lista_t* lista_nueva = lista_crear();
- lista_insertar_ultimo(lista_nueva, tiempo_nuevo);
- hash_guardar(hash_lista_tiempos, ip, lista_nueva);
- }
- request_destruir(&request);
- }
- abb_t* abb_dos = detectar_dos(hash_lista_tiempos);
- free(linea);
- fclose(archivo);
- abb_in_order(abb_dos, imprimir_dos, NULL);
- abb_destruir(abb_dos);
- hash_destruir(hash_lista_tiempos);
- printf("OK\n");
- return true;
- }
- bool ver_visitantes(abb_t* abb_ips, char* desde, char* hasta){
- if(abb_cantidad(abb_ips) == 0) return false;
- printf("%s\n","Visitantes:");
- abb_in_order_rango(abb_ips, imprimir_ip, desde, hasta);
- printf("%s\n","OK" );
- return true;
- }
- void ver_mas_visitados(size_t n, hash_t* url_visitas){
- heap_t* mas_visitados = heap_crear(comparar_visitas);
- hash_iter_t* hash_iter = hash_iter_crear(url_visitas);
- // Inserta los primeros n elementos del hash de urls "urls_visitas" a un heap
- // de minimos "mas_visitados"
- for (int i = 0; i < n; i++){
- if(hash_iter_al_final(hash_iter)) break;
- dato_t* dato = malloc(sizeof(dato_t));
- dato->url = hash_iter_ver_actual(hash_iter);
- dato->visitas = *(int*)hash_obtener(url_visitas, dato->url);
- heap_encolar(mas_visitados, dato);
- hash_iter_avanzar(hash_iter);
- }
- // Recorre el resto del hash y solo inserta si el elemento es mayor al tope
- // del heap de minimos
- while(!hash_iter_al_final(hash_iter)){
- dato_t* dato = malloc(sizeof(dato_t));
- dato->url = (char*)hash_iter_ver_actual(hash_iter);
- dato->visitas = *(int*)hash_obtener(url_visitas, dato->url);
- dato_t* tope = (dato_t*)heap_ver_max(mas_visitados);
- if (dato->visitas > tope->visitas){
- heap_desencolar(mas_visitados);
- free(tope);
- heap_encolar(mas_visitados, dato);
- }else free(dato);
- hash_iter_avanzar(hash_iter);
- }
- hash_iter_destruir(hash_iter);
- // Imprime los elementos del heap de manera inversa (recursivamente)
- printf("%s\n","Sitios mรยกs visitados:");
- imprimir_url_maximos(mas_visitados);
- printf("%s\n","OK" );
- heap_destruir(mas_visitados, NULL);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement