Advertisement
Guest User

Untitled

a guest
Nov 24th, 2017
110
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 11.73 KB | None | 0 0
  1. // Jonathan Galvan Perez 101250 || Alejandro Balladares 101118
  2. #define _XOPEN_SOURCE
  3. #define _POSIX_C_SOURCE 200809L //getline
  4. #include "strutil.h"
  5. #include "heap.h"
  6. #include "hash.h"
  7. #include "abb.h"
  8. #include "lista.h"
  9. #include <string.h>
  10. #include <stdlib.h>
  11. #include <stdio.h>
  12. #include <stdbool.h>
  13. #include <time.h>
  14. #define DOS 2
  15. #define LIMITE_DE_DOS 5
  16. #define SEP_COMANDOS ' '
  17. #define SEP_REQUEST '\t'
  18. #define SEP_IP '.'
  19. #define TIME_FORMAT "%FT%T%z"
  20.  
  21. //////////////////////////////////////////////////////////////////////////////////////
  22. /*                              ESTRUCTURAS DE DATOS                                */
  23. //////////////////////////////////////////////////////////////////////////////////////
  24.  
  25. typedef struct dato{
  26.     const char* url;
  27.     int visitas;
  28. }dato_t;
  29.  
  30. typedef struct request{
  31.     char* ip;
  32.     time_t tiempo;
  33.     char* metodo;
  34.     char* url;
  35. } request_t;
  36.  
  37.  
  38. //////////////////////////////////////////////////////////////////////////////////////
  39. /*                              FUNCIONES AUXILIARES                                */
  40. //////////////////////////////////////////////////////////////////////////////////////
  41.  
  42. time_t iso8601_to_time(const char* iso8601){
  43.     struct tm bktime = { 0 };
  44.     strptime(iso8601, TIME_FORMAT, &bktime);
  45.     return mktime(&bktime);
  46. }
  47.  
  48. char* quitar_barra_n(char* cadena){
  49.     size_t largo = strlen(cadena);
  50.     if(cadena[largo-1] == '\n') cadena[largo-1] = '\0';
  51.     return cadena;
  52. }
  53.  
  54. void conseguir_request(char* linea, request_t* request){
  55.     char* linea_aux = quitar_barra_n(linea);
  56.     char** campos = split(linea_aux, SEP_REQUEST);
  57.     request->ip = strdup(campos[0]);
  58.     request->tiempo = iso8601_to_time(campos[1]);
  59.     request->url = strdup(campos[3]);
  60.     free_strv(campos);
  61. }
  62.  
  63. void request_destruir(request_t* request){
  64.     free(request->ip);
  65.     free(request->url);
  66. }
  67.  
  68. void lista_wrapper(void* lista_void){
  69.     lista_t* lista = lista_void;
  70.     lista_destruir(lista, free);
  71. }
  72.  
  73. int comparar_visitas(const void* dato1_void, const void* dato2_void){
  74.     const dato_t* dato1 = dato1_void;
  75.     const dato_t* dato2 = dato2_void;
  76.     return dato2->visitas - dato1->visitas; //funcion al reves para heap de minimos
  77. }
  78.  
  79. int comparar_ips(const char* ip1, const char* ip2){
  80.     int respuesta = 0;
  81.     char** ip1_partes = split(ip1, SEP_IP);
  82.     int ip1_campos[4];
  83.     ip1_campos[0] = atoi(ip1_partes[0]);
  84.     ip1_campos[1] = atoi(ip1_partes[1]);
  85.     ip1_campos[2] = atoi(ip1_partes[2]);
  86.     ip1_campos[3] = atoi(ip1_partes[3]);
  87.     char** ip2_partes = split(ip2, SEP_IP);
  88.     int ip2_campos[4];
  89.     ip2_campos[0] = atoi(ip2_partes[0]);
  90.     ip2_campos[1] = atoi(ip2_partes[1]);
  91.     ip2_campos[2] = atoi(ip2_partes[2]);
  92.     ip2_campos[3] = atoi(ip2_partes[3]);
  93.  
  94.     for(int i = 0; i < 4; i++){
  95.         if(ip1_campos[i] > ip2_campos[i]){
  96.             respuesta = 1;
  97.             break;
  98.         }
  99.            
  100.         if(ip1_campos[i] < ip2_campos[i]){
  101.             respuesta = -1;
  102.             break;
  103.         }
  104.     }
  105.     free_strv(ip1_partes);
  106.     free_strv(ip2_partes);
  107.  
  108.     return respuesta;
  109. }
  110.  
  111. bool imprimir_dos(const char* ip, void* extra1, void* extra2){
  112.     printf("DoS: %s\n", ip);
  113.     return true;
  114. }
  115.  
  116. bool imprimir_ip(const char* clave){
  117.     printf("\t%s\n",clave);
  118.     return true;
  119. }
  120.  
  121. void imprimir_url_maximos(heap_t* mas_visitados){
  122.     if (heap_esta_vacio(mas_visitados)) return;
  123.     dato_t* dato = heap_desencolar(mas_visitados);
  124.     imprimir_url_maximos(mas_visitados);
  125.     printf("\t%s - %d\n",dato->url, dato->visitas);
  126.     free(dato);
  127. }
  128.  
  129. //////////////////////////////////////////////////////////////////////////////////////
  130. /*                              FUNCIONES PRINCIPALES                               */
  131. //////////////////////////////////////////////////////////////////////////////////////
  132.  
  133. bool agregar_archivo(char* archivo, abb_t* abb_ips, hash_t* url_visitas);
  134.  
  135. bool ver_visitantes(abb_t* arbol_ips, char* desde, char* hasta);
  136.  
  137. void ver_mas_visitados(size_t n, hash_t* url_visitas);
  138.  
  139. int ejecutar_comando(char** comando, abb_t* abb_ips, hash_t* url_visitas);
  140.  
  141. int main(int argc,char* argv[]){
  142.     if(argc >= 2) return 0;
  143.     int errores_tipo2 = 0;
  144.     abb_t* abb_ips = abb_crear(comparar_ips, NULL);
  145.     hash_t* url_visitas = hash_crear(free);
  146.     char* linea = NULL; size_t capacidad = 0; ssize_t leidos;
  147.     while((leidos = getline(&linea,&capacidad,stdin)) > 0){
  148.         char* comando_aux = quitar_barra_n(linea);
  149.         char** comando = split(comando_aux,' ');
  150.         errores_tipo2 = ejecutar_comando(comando, abb_ips, url_visitas);
  151.         if(errores_tipo2 > 0) break;        
  152.     }
  153.     free(linea);
  154.     abb_destruir(abb_ips);
  155.     hash_destruir(url_visitas);
  156.     return 0;
  157. }
  158.  
  159. int ejecutar_comando(char** comando, abb_t* abb_ips, hash_t* url_visitas){
  160.     int errores_tipo2 = 0;
  161.     if(strcmp(comando[0], "agregar_archivo") == 0){
  162.         if(!comando[1]){
  163.             fprintf(stderr, "%s\n","Error en comando agregar_archivo");
  164.             errores_tipo2++;
  165.         }else
  166.             if(!agregar_archivo(comando[1], abb_ips, url_visitas)) errores_tipo2++;
  167.     }else if(strcmp(comando[0], "ver_visitantes") == 0){
  168.         if(!comando[1] || !comando[2]){
  169.             fprintf(stderr, "%s\n","Error en comando ver_visitantes");
  170.             errores_tipo2++;
  171.         }else
  172.             if(!ver_visitantes(abb_ips, comando[1], comando[2])) errores_tipo2++;
  173.     }else if(strcmp(comando[0], "ver_mas_visitados") == 0){
  174.         if(!comando[1]){
  175.             fprintf(stderr, "%s\n","Error en comando ver_mas_visitados");
  176.             errores_tipo2++;
  177.         }else ver_mas_visitados(atoi(comando[1]), url_visitas);
  178.     }else{
  179.         fprintf(stderr, "%s %s\n","Error en comando",comando[0]);
  180.         errores_tipo2++;
  181.     }
  182.     free_strv(comando);
  183.     return errores_tipo2;
  184. }
  185.  
  186. void guardar_url(hash_t* hash_visitas, request_t* request){
  187.     if(!hash_pertenece(hash_visitas, request->url)){
  188.         int* visitas = malloc(sizeof(int));
  189.         *visitas = 1;
  190.         hash_guardar(hash_visitas, request->url, visitas);
  191.     }else{
  192.         int* visitas = hash_obtener(hash_visitas, request->url);
  193.         *visitas = *visitas + 1;
  194.     }        
  195. }
  196.  
  197.  
  198. // Recorre todas las listas del "hash_lista_tiempos", a menos que tenga menos de 5
  199. // elementos (time_t*). A medida va desencolando cada elemento de una lista los
  200. // inserta en una lista vacia "lista_dos" de manera que todos los elementos en ella
  201. // no tengan una diferencia mayor o igual a 2 segundos. Si el nuevo elemento rompe
  202. // la invariante, borra el primer elemento de la "lista_dos" hasta que se vuelva a
  203. // cumplir. Si "lista_dos" llega a 5 elementos inserta la ip en un arbol "abb_dos".
  204.  
  205. abb_t* detectar_dos(hash_t* hash_lista_tiempos){
  206.     abb_t* abb_dos = abb_crear(comparar_ips, NULL);
  207.     hash_iter_t* hash_iter = hash_iter_crear(hash_lista_tiempos);
  208.     while(!hash_iter_al_final(hash_iter)){
  209.         const char* ip = hash_iter_ver_actual(hash_iter);
  210.         lista_t* lista_tiempos = hash_obtener(hash_lista_tiempos, ip);
  211.         if(lista_largo(lista_tiempos) < 5){
  212.             hash_iter_avanzar(hash_iter);
  213.             continue;
  214.         }
  215.         lista_t* lista_dos = lista_crear();
  216.         time_t* tiempo_inicial = lista_borrar_primero(lista_tiempos);
  217.         lista_insertar_ultimo(lista_dos, tiempo_inicial);
  218.         while(!lista_esta_vacia(lista_tiempos)){
  219.             time_t* tiempo_ult = lista_borrar_primero(lista_tiempos);
  220.             double diferencia = difftime(*tiempo_ult, *tiempo_inicial);
  221.             while(diferencia >= DOS){
  222.                 time_t* tiempo_borrar = lista_borrar_primero(lista_dos);
  223.                 free(tiempo_borrar);
  224.                 tiempo_inicial = lista_ver_primero(lista_dos);
  225.                 if (!tiempo_inicial) break;
  226.                 diferencia = difftime(*tiempo_ult, *tiempo_inicial);
  227.             }
  228.             lista_insertar_ultimo(lista_dos, tiempo_ult);
  229.             if(lista_largo(lista_dos) == 5)
  230.                 abb_guardar(abb_dos, ip , NULL);
  231.             tiempo_inicial = lista_ver_primero(lista_dos);
  232.         }
  233.         lista_destruir(lista_dos, free);
  234.         hash_iter_avanzar(hash_iter);
  235.     }
  236.     hash_iter_destruir(hash_iter);
  237.     return abb_dos;
  238. }
  239.  
  240. bool agregar_archivo(char* nombre_archivo, abb_t* abb_ips, hash_t* url_visitas){
  241.     FILE* archivo = fopen(nombre_archivo,"r");
  242.     if(archivo == NULL){
  243.         fprintf(stderr, "%s\n","Error en comando agregar_archivo");
  244.         return false;
  245.     }
  246.     hash_t* hash_lista_tiempos = hash_crear(lista_wrapper);    
  247.     char* linea = NULL; size_t capacidad = 0; ssize_t leidos;
  248.     while((leidos = getline(&linea,&capacidad,archivo)) > 0){
  249.  
  250.         // request es una variable estatica que almacena la informacion relevante
  251.         // de la linea (ip, url, tiempo)
  252.         request_t request;
  253.         conseguir_request(linea, &request);
  254.         char* ip = request.ip;
  255.        
  256.         // Actualiza el arbol de ips para "ver_vistantes"
  257.         if(!abb_pertenece(abb_ips, request.ip)) abb_guardar(abb_ips, request.ip, NULL);
  258.  
  259.         // Actualiza el hash de urls para "ver_mas_visitados"
  260.         guardar_url(url_visitas, &request);
  261.  
  262.         // Actualiza el hash de listas de tiempos para "detectar_dos"
  263.         time_t* tiempo_nuevo = malloc(sizeof(time_t));
  264.         *tiempo_nuevo = request.tiempo;
  265.         if(hash_pertenece(hash_lista_tiempos, ip)){
  266.             lista_t* lista_tiempos = hash_obtener(hash_lista_tiempos, ip);
  267.             lista_insertar_ultimo(lista_tiempos, tiempo_nuevo);
  268.         }else{
  269.             lista_t* lista_nueva = lista_crear();
  270.             lista_insertar_ultimo(lista_nueva, tiempo_nuevo);
  271.             hash_guardar(hash_lista_tiempos, ip, lista_nueva);
  272.         }
  273.        
  274.         request_destruir(&request);
  275.     }
  276.  
  277.     abb_t* abb_dos = detectar_dos(hash_lista_tiempos);
  278.     free(linea);
  279.     fclose(archivo);
  280.     abb_in_order(abb_dos, imprimir_dos, NULL);
  281.     abb_destruir(abb_dos);
  282.     hash_destruir(hash_lista_tiempos);
  283.     printf("OK\n");
  284.     return true;
  285. }
  286.  
  287. bool ver_visitantes(abb_t* abb_ips, char* desde, char* hasta){
  288.     if(abb_cantidad(abb_ips) == 0) return false;
  289.     printf("%s\n","Visitantes:");
  290.     abb_in_order_rango(abb_ips, imprimir_ip, desde, hasta);
  291.     printf("%s\n","OK" );
  292.     return true;
  293. }
  294.  
  295. void ver_mas_visitados(size_t n, hash_t* url_visitas){
  296.     heap_t* mas_visitados = heap_crear(comparar_visitas);
  297.     hash_iter_t* hash_iter = hash_iter_crear(url_visitas);
  298.  
  299.     // Inserta los primeros n elementos del hash de urls "urls_visitas" a un heap
  300.     // de minimos "mas_visitados"
  301.     for (int i = 0; i < n; i++){
  302.         if(hash_iter_al_final(hash_iter)) break;
  303.         dato_t* dato = malloc(sizeof(dato_t));
  304.         dato->url = hash_iter_ver_actual(hash_iter);
  305.         dato->visitas = *(int*)hash_obtener(url_visitas, dato->url);
  306.         heap_encolar(mas_visitados, dato);
  307.         hash_iter_avanzar(hash_iter);
  308.     }
  309.  
  310.     // Recorre el resto del hash y solo inserta si el elemento es mayor al tope
  311.     // del heap de minimos
  312.     while(!hash_iter_al_final(hash_iter)){
  313.         dato_t* dato = malloc(sizeof(dato_t));
  314.         dato->url = (char*)hash_iter_ver_actual(hash_iter);
  315.         dato->visitas = *(int*)hash_obtener(url_visitas, dato->url);
  316.         dato_t* tope = (dato_t*)heap_ver_max(mas_visitados);
  317.         if (dato->visitas > tope->visitas){
  318.             heap_desencolar(mas_visitados);
  319.             free(tope);
  320.             heap_encolar(mas_visitados, dato);
  321.         }else free(dato);
  322.         hash_iter_avanzar(hash_iter);
  323.     }
  324.     hash_iter_destruir(hash_iter);
  325.  
  326.     // Imprime los elementos del heap de manera inversa (recursivamente)
  327.     printf("%s\n","Sitios mรƒยกs visitados:");
  328.     imprimir_url_maximos(mas_visitados);
  329.     printf("%s\n","OK" );
  330.     heap_destruir(mas_visitados, NULL);
  331. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement