// GRUPO: 18 // DATA DO PRAZO DE ENTREGA: 10/12/2004 // NUMERO DO TRABALHO: 02 // NOME FICHEIRO: CheckLink_18.c // SUMARIO DO PROGRAMA: // Este programa permite verificar o estado da ligacao a um determinado // servidor http. Analisa se o link e valido e tenta efectuar a ligacao em // intervalos de tempo aleatorios. //----------------------------------------- #include #include #include #include #include #include #include #include #include #define MAXSTR 255 #define PORT 80 typedef struct serv{ char httpd[100], httpstatus[20]; int checkstatus, tested, valid, stoped; pthread_t threadP,threadF; pthread_cond_t cond; pthread_mutex_t mutex; } *servers; servers httpserver[100]; int timeout=0, periodo=0; FILE *conffile; int grace=0, thrd1=0, thrd2=0, thrd3=0; // Funcao connect_server --- int connect_server(char *server){ int sockfd, rc, count; char msg[256], buffer[8192]; struct hostent *he; struct sockaddr_in server_addr; he = gethostbyname(server); if (he == NULL) return -1; sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) return -1; server_addr.sin_family = AF_INET; server_addr.sin_port = htons(PORT); server_addr.sin_addr = *((struct in_addr *)he->h_addr); memset(&(server_addr.sin_zero), '\0', 8); rc = connect(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)); if (rc < 0){ close(sockfd); return -1; } sprintf(msg, "GET / HTTP/1.0\nHost: %s\n\n", server); rc = send(sockfd, msg, strlen(msg), 0); if (rc < 0){ close (sockfd); return -1; } do{ count = recv(sockfd, buffer, sizeof(buffer), 0); } while (count > 0); close(sockfd); return 0; } // --- // Funcao validate_link --- int validate_link(char link[100]){ int i=0, j=0, x=0, z=0, test=0; char caracteres[70]; strcpy(caracteres,"1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-."); x = strlen(link); z = strlen(caracteres); for (i=0;i < x;i++){ for (j=0;j < z;j++){ if (link[i] == caracteres[j]) test=1; } if (test == 0) return (1); test=0; } if (strstr(link,"..")) return (1); return (0); } // --- // load_content2men --- void load_content2mem(){ int i=0; char *fileline; fileline = (char *)malloc(sizeof(char *)*20); conffile=fopen("checkLink.conf","r"); if (conffile == NULL){ printf("# Ficheiro de configuracao nao encontrado!\n"); exit(1); } else{ while (fgets(fileline,MAXSTR,conffile) != NULL) { if ((strcmp(fileline,"") != 0) || (strcmp(fileline,"\n") != 0)){ httpserver[i]=(servers)malloc(sizeof(struct serv)); strcpy(httpserver[i]->httpd,strtok(fileline,"\n")); httpserver[i]->checkstatus = 0; httpserver[i]->tested = 0; httpserver[i]->stoped = 0; if (validate_link(httpserver[i]->httpd) == 0){ httpserver[i]->valid = 0; strcpy(httpserver[i]->httpstatus,"not tested"); } else { httpserver[i]->valid = 1; strcpy(httpserver[i]->httpstatus,"invalid link"); printf("# Link invalido encontrado: %s\n",httpserver[i]->httpd); printf("# O link foi adicionado mas nao ira ser testado!\n"); } } i++; } if (i > 1) printf("# %d Links adicionados a lista\n",i); else if (i = 1) printf("# %d Link adicionado a lista\n",i); else printf("# Ficheiro de configuracao vazio\n"); } fclose(conffile); free(fileline); } // --- // Funcao add_new_server --- void check_conffile(){ int i=0,test=0; char *fileline; while(1){ fileline = (char *)malloc(sizeof(char *)*20); conffile=fopen("checkLink.conf","r"); if (conffile != NULL){ while (fgets(fileline,MAXSTR,conffile) != NULL) { strcmp(fileline,strtok(fileline,"\n")); while (httpserver[i] != NULL){ if (strcmp(fileline,httpserver[i]->httpd)==0){ test = 1; } i++; } if (test == 0){ httpserver[i]=(servers)malloc(sizeof(struct serv)); strcpy(httpserver[i]->httpd,fileline); httpserver[i]->checkstatus = 0; httpserver[i]->tested = 0; httpserver[i]->stoped = 0; if (validate_link(httpserver[i]->httpd) == 0){ httpserver[i]->valid = 0; strcpy(httpserver[i]->httpstatus,"not tested"); printf("# --\n"); printf("# Novo Link adicionado: %s\n",fileline); } else { httpserver[i]->valid = 1; strcpy(httpserver[i]->httpstatus,"invalid link"); printf("# --\n"); printf("# Link invalido encontrado: %s\n",httpserver[i]->httpd); printf("# O link foi adicionado mas nao ira ser testado!\n"); } } i=0; test=0; sleep(1); } } fclose(conffile); free(fileline); if (grace !=0){ thrd1 = 1; pthread_exit(); } } } // --- // Funcao print_test_results -- void print_report(){ int i=0, pos=0, neg=0, time=0, ntested=0, inv=0, aux=0; float media; while (httpserver[i] != NULL){ aux = strlen(httpserver[i]->httpd); if (aux < 12) printf("# %s \t\t\t [ %s ]\n",httpserver[i]->httpd,httpserver[i]->httpstatus); else printf("# %s \t\t [ %s ]\n",httpserver[i]->httpd,httpserver[i]->httpstatus); if (!(strcmp(httpserver[i]->httpstatus,"ok"))) ++pos; else if (!(strcmp(httpserver[i]->httpstatus,"failed"))) ++neg; else if (!(strcmp(httpserver[i]->httpstatus,"timeout"))) ++time; else if (!(strcmp(httpserver[i]->httpstatus,"not tested"))) ++ntested; else ++inv; i++; } media = ((float)pos/((float)i-(float)inv))*100; aux = i-inv; printf("# %.2f positive checked links. Cheked links: %d (total %d);\n",media,aux,i); } // --- // Funcao cicle_print_report void cicle_print_report(){ while (1){ if (grace !=0){ thrd2 = 1; pthread_exit(); } sleep(5); printf("# --\n"); print_report(); if (grace !=0){ thrd2 = 1; pthread_exit(); } } } // --- // Funcao linktester --- void linktester(int indice){ int result; result = connect_server(httpserver[indice]->httpd); pthread_mutex_lock(&httpserver[indice]->mutex); if (result < 0) strcpy(httpserver[indice]->httpstatus,"failed"); else strcpy(httpserver[indice]->httpstatus,"ok"); httpserver[indice]->tested = 1; pthread_mutex_unlock(&httpserver[indice]->mutex); pthread_cond_signal(&httpserver[indice]->cond); } // --- // Funcao test_link --- void test_link(int indice){ int secs, test=0, j=0, i=0, sleeptime=0; struct timespec ts; struct timeval tv; pthread_mutex_init(&httpserver[indice]->mutex, NULL); pthread_cond_init(&httpserver[indice]->cond, NULL); while (1){ pthread_mutex_lock(&httpserver[indice]->mutex); pthread_create(&httpserver[indice]->threadF, NULL, (void *)&linktester, indice); secs = gettimeofday(&tv,NULL); ts.tv_sec = tv.tv_sec + timeout; ts.tv_nsec = tv.tv_usec*1000; pthread_cond_timedwait(&httpserver[indice]->cond,&httpserver[indice]->mutex,&ts); if (httpserver[indice]->tested == 0){ strcpy(httpserver[indice]->httpstatus,"timeout"); pthread_kill(&httpserver[indice]->threadF,9); } httpserver[indice]->tested=0; pthread_mutex_unlock(&httpserver[indice]->mutex); j=0+(int) (16.0*rand()/(RAND_MAX+1.0)); i=0+(int) (2.0*rand()/(RAND_MAX+1.0)); if (i==0){ sleeptime = periodo - j; if (sleeptime < 0) sleeptime = 0; } else{ sleeptime = periodo + j; } if (grace !=0){ httpserver[indice]->stoped = 1; pthread_exit(); } sleep(sleeptime); } } // -- // Funcao create_test_threads --- void create_test_threads(){ int i=0; while (1){ while(httpserver[i] != NULL){ if ((httpserver[i]->checkstatus == 0) && (httpserver[i]->valid == 0)){ httpserver[i]->checkstatus = 1; pthread_create(&httpserver[i]->threadP, NULL, (void *)&test_link, i); } i++; } i=0; if (grace !=0){ thrd3 = 1; pthread_exit(); } sleep(1); } } // --- // Funcao catch_pressed_keys --- void catch_pressed_keys(){ int i=0, test=0; while(1){ switch (getchar()){ case 'a': { printf("# --\n"); printf("# user aborted, exiting -- last report\n"); printf("# --\n"); print_report(); printf("\n"); free(*httpserver); exit(1); break; } case 'g':{ grace = 1; printf("# --\n"); printf("# starting exit procedure\n"); while (1){ if ((thrd1 == 1) && (thrd2 == 1)){ while(1){ while(httpserver[i] != NULL){ if (httpserver[i]->stoped == 0){ test = 1; } i++; } if (test == 0){ printf("# -- last report --\n"); print_report(); printf("\n"); free(*httpserver); exit(1); } test = 0; i=0; } } } break; } default: { printf("# tecla invalida!\n"); break; } } } } // --- // main --- main(int argc, char *argv[]){ pthread_t threadA, threadB, threadC; char itemA = 'A', itemB = 'B', itemC = 'C'; if ((argv[1] == NULL) || (argv[2] == NULL)) printf("# Argumentos iniciais sao necessarios\n"); else { timeout = atoi(argv[1]); periodo = atoi(argv[2]); if ((timeout == 0) || (periodo == 0)){ if ((strcmp(argv[1],"0")!=0) || (strcmp(argv[2],"0")!=0)){ printf("# Argumentos iniciais invalidos\n"); exit(1); } } if ((timeout < 0) || (periodo < 0)){ printf("# Argumentos iniciais invalidos\n"); exit(1); } system("clear"); printf("# -- timeout: %d / periodo: %d --\n",timeout,periodo); load_content2mem(); pthread_create(&threadA, NULL, (void *)&check_conffile, (void *)&itemA); pthread_create(&threadB, NULL, (void *)&create_test_threads, (void *)&itemB); pthread_create(&threadC, NULL, (void *)&cicle_print_report, (void *)&itemC); catch_pressed_keys(); } return 0; } // ---