Advertisement
Guest User

Untitled

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