int UDP_setup_socket_bound( int32_t *psocketfd, uint16_t numero_porta_locale, int dimSndBuf, int dimRcvBuf) { int ris; struct sockaddr_in Local; *psocketfd = socket(AF_INET, SOCK_DGRAM, 0); if (*psocketfd < 0) { printf ("socket() failed, Err: %d \"%s\"\n", errno,strerror(errno)); return(0); } /* avoid EADDRINUSE error on bind() */ ris = SetsockoptReuseAddr(*psocketfd); if (!ris) { printf ("SetsockoptReuseAddr() failed, Err: %d \"%s\"\n", errno,strerror(errno)); close(*psocketfd); return(0); } if(dimSndBuf>0) { int n; ris=SetsockoptSndBuf(*psocketfd,dimSndBuf); if (!ris) exit(5); ris=GetsockoptSndBuf(*psocketfd,&n); if (!ris) exit(5); /* else printf ("SndBuf socketfd %d\n", n); */ } if(dimRcvBuf>0) { int n; ris=SetsockoptRcvBuf(*psocketfd,dimRcvBuf); if (!ris) exit(5); ris=GetsockoptRcvBuf(*psocketfd,&n); if (!ris) exit(5); /* else printf ("RcvBuf socketfd %d\n", n); */ } /*name the socket */ memset ( &Local, 0, sizeof(Local) ); Local.sin_family= AF_INET; /* specifico l'indirizzo IP attraverso cui voglio ricevere la connessione */ Local.sin_addr.s_addr = htonl(INADDR_ANY); Local.sin_port = htons(numero_porta_locale); ris = bind(*psocketfd, (struct sockaddr*) &Local, sizeof(Local)); if (ris<0) { printf ("bind() failed, Err: %d \"%s\"\n",errno,strerror(errno)); fflush(stderr); close(*psocketfd); return(0); } return(1); }
int TCP_setup_connection(int *pserverfd, char *string_IP_remote_address, int port_number_remote) { struct sockaddr_in Local, Serv; int ris; *pserverfd = socket(AF_INET, SOCK_STREAM, 0); if (*pserverfd<0) { printf ("socket() failed, Err: %d \"%s\"\n", errno,strerror(errno)); fflush(stdout); return(0); } ris = SetsockoptReuseAddr(*pserverfd); if (ris==0) { printf ("SetsockoptReuseAddr() failed, Err: %d \"%s\"\n",errno,strerror(errno)); return(0); } /* name the socket */ memset ( &Local, 0, sizeof(Local) ); Local.sin_family = AF_INET; Local.sin_addr.s_addr = htonl(INADDR_ANY); /* wildcard */ Local.sin_port = htons(0); ris = bind(*pserverfd, (struct sockaddr*) &Local, sizeof(Local)); if (ris<0) { printf ("bind() failed, Err: %d \"%s\"\n",errno,strerror(errno)); return(0); } /* assign our destination address */ memset ( &Serv, 0, sizeof(Serv) ); Serv.sin_family = AF_INET; Serv.sin_addr.s_addr = inet_addr(string_IP_remote_address); Serv.sin_port = htons(port_number_remote); #ifdef DEBUG printf ("connecting to %s %d\n", string_IP_remote_address, port_number_remote); fflush(stdout); #endif do { ris = connect(*pserverfd, (struct sockaddr*) &Serv, sizeof(Serv)); } while( (ris<0)&&(errno==EINTR)); if (ris<0) { printf ("Connect() failed, Err: %d \"%s\"\n",errno,strerror(errno)); fflush(stdout); return(0); } #ifdef DEBUG printf ("connected to %s %d\n", string_IP_remote_address, port_number_remote); fflush(stdout); #endif return(1); }
int TCPS_setup_socket_listening(int *plistenfd, int numero_porta_locale) { int ris; struct sockaddr_in Local; *plistenfd = TCP_Session_IPv4_Socket(); if (*plistenfd < 0) { printf ("TCP_Session_IPv4_Socket() failed, Err: %d \"%s\"\n", errno,strerror(errno)); return(0); } /* avoid EADDRINUSE error on bind() */ ris = SetsockoptReuseAddr(*plistenfd); if (!ris) { printf ("SetsockoptReuseAddr() failed, Err: %d \"%s\"\n", errno,strerror(errno)); return(0); } /*name the socket */ memset ( &Local, 0, sizeof(Local) ); Local.sin_family= AF_INET; /* specifico l'indirizzo IP attraverso cui voglio ricevere la connessione */ Local.sin_addr.s_addr = htonl(INADDR_ANY); Local.sin_port = htons(numero_porta_locale); ris = Bind(*plistenfd, (struct sockaddr*) &Local, sizeof(Local)); if (ris<0) { printf ("Bind() failed, Err: %d \"%s\"\n",errno,strerror(errno)); fflush(stderr); return(0); } /* enable accepting of connection */ ris = Listen(*plistenfd, 100 ); if (ris<0) { printf ("Listen() failed, Err: %d \"%s\"\n",errno,strerror(errno)); exit(1); } return(1); }
int main(int argc, char *argv[]) { int listenfd; struct sockaddr_in Client, Local; unsigned int len; int ris; int local_port; pthread_attr_t attr; /* Aggancio segnali */ if (signal(SIGINT,handler) == SIG_ERR) { printf("Signal fallita\n"); fflush(stdout); exit(1); } if (argc == 1) { printf ("Porta di default: 55554\n\n"); fflush(stdout); local_port = 55554; } else if (argc == 2) local_port = atoi(argv[1]); /* Controllo argomenti */ else { printf ("Usage: ./proxy local_port\n"); fflush(stdout); return(1); } printf("Cleaning cache...\n\n"); fflush(stdout); /* Cancellazione file della cache */ DIR *dir_p; struct dirent *entry; char dir_cache[]="../cache/"; char toremove[512]; /* Creo nome file e cancello */ dir_p = opendir(dir_cache); while (1) { #ifdef DEBUG printf("While cleaning cache\n"); fflush(stdout); #endif if ((entry = readdir(dir_p)) == NULL) break; strcpy(toremove, dir_cache); /* Evito di cancellare file nascosti e le directory speciali unix "." e "..", operazione comunque non possibile con uid del proxy */ if ((strncmp(entry->d_name, ".", sizeof("."))) && (strncmp(entry->d_name, "..", sizeof("..")))) { remove(strcat(toremove, entry->d_name)); printf("Removing \"%s\"\n", entry->d_name); fflush(stdout); } } printf("\nCache clean.\n"); fflush(stdout); /* Inizializzazione strutture cache */ init_cache_list(); /* Inizializzazione thread */ pthread_mutex_init(&mutex_num,NULL); pthread_mutex_init(&mutex_name,NULL); pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED); #ifdef DAEMON_CACHE_CLEAN pthread_t threadID_daemon; /* Faccio partire il thread "demone" per la pulizia cache */ ris = pthread_create(&threadID_daemon, &attr, daemon_cache_clean, NULL); if(ris != 0) { printf("Chiamata a pthread_create() fallita.\n Errore: %d \"%s\"\n", errno,strerror(errno)); fflush(stdout); exit(1); } #endif int repeat; while (1) { #ifdef DEBUG printf("While nel main, per listen\n"); fflush(stdout); #endif listenfd = 0; listenfd = socket(AF_INET, SOCK_STREAM, 0); if (listenfd < 0) { printf ("socket() failed, Err: %d \"%s\"\n", errno,strerror(errno)); fflush(stdout); exit(1); } memset ( &Local, 0, sizeof(Local) ); Local.sin_family= AF_INET; Local.sin_addr.s_addr = htonl(INADDR_ANY); Local.sin_port = htons(local_port); /* Evito EADDRINUSE sulla bind() */ ris = SetsockoptReuseAddr(listenfd); if (ris == 0) { close(listenfd); exit(1); } ris = bind(listenfd, (struct sockaddr*) &Local, sizeof(Local)); if (ris < 0) { printf ("bind() failed, Err: %d \"%s\"\n",errno,strerror(errno)); fflush(stdout); exit(1); } ris = listen(listenfd, 100); if (ris < 0) { printf ("listen() failed, Err: %d \"%s\"\n",errno,strerror(errno)); fflush(stdout); exit(1); } /* Abilito/Riabilito entrata in ciclo per accept */ repeat = 1; /* Ciclo infinito in attesa di richieste al proxy */ while(repeat) { #ifdef DEBUG printf("While nel main, per accept\n"); fflush(stdout); #endif memset ( &Client, 0, sizeof(Client) ); len = sizeof(Client); #ifdef DEBUG printf("Aspetto clients"); fflush(stdout); #endif /* Attendi richiesta di connessione */ ris = accept(listenfd,(struct sockaddr *)&Client, &len); #ifdef DEBUG printf("Dopo accept"); fflush(stdout); #endif if(ris < 0){ if(errno == EINTR) continue; /* Ritenta */ else { printf("Chiamata ad accept() fallita.\n Errore: %d \"%s\"\n", errno,strerror(errno)); fflush(stdout); close(listenfd); repeat = 0; /* Altro socket listening */ /*exit(1);*/ } } /* Accept a buon fine, nuova connessione con client. Faccio partire sessione cli-pro-[serv-pro-]cli. */ else { /* Struttura per passaggio parametri al thread */ struct param *p; p = malloc(sizeof(struct param)); if(p == NULL) { printf("Chiamata a malloc() fallita.\n Errore: %d \"%s\"\n", errno,strerror(errno)); fflush(stdout); exit(1); } else { pthread_t threadID; /* Passo al thread il socket che identifica la connessione con questo client */ p->fd = ris; /* Parte il thread relativo alla sessione con questo client */ ris = pthread_create(&threadID, &attr, Session, (void*)p); if(ris != 0) { printf("Chiamata a pthread_create() fallita.\n Errore: %d \"%s\"\n", errno,strerror(errno)); fflush(stdout); exit(1); } p = NULL; } } /* Creazione Thread */ } /* While accept */ } /* While listen */ } /* Main */
/* Thread per sessione di connessione */ static void *Session (void *p) { int clifd; /* Socket Client-Proxy */ int servfd; /* Socket Proxy-Server */ int ris; /* Utili */ struct Request req; /* Conterrà le informazioni per forward e prefetch */ struct Response resp; /* Conterrà info per invio file cache, struttura richiesta da prepareResponse ecc */ char cache_filename[MAXLENPATH]; char error_response[16]; char buffer[MAXLENRESP]; int buffer_len; struct sockaddr_in Local, Serv; /* Per connessione con il server */ /* Client socket Timeout */ struct timeval timercli; timercli.tv_sec = INACTIVITY_TIMEOUT_SECONDS; timercli.tv_usec = 0; /* Estrazione informazioni parametro thread */ clifd = ((struct param*)p)->fd; free(p); p = NULL; /* Controllo sul numero dei thread */ pthread_mutex_lock(&mutex_num); if(numthread < MAXNUMTHREADWORKING) numthread++; pthread_mutex_unlock(&mutex_num); if(numthread >= MAXNUMTHREADWORKING) { close(clifd); exitThread(); return(NULL); } #ifdef DEBUG printf("Thread: %ld. Client FD passato: %d\n", pthread_self(), clifd); fflush(stdout); #endif /* Imposto il timeout per questo socket client */ setsockopt(clifd, SOL_SOCKET, SO_RCVTIMEO, &timercli, sizeof(struct timeval)); setsockopt(clifd, SOL_SOCKET, SO_SNDTIMEO, &timercli, sizeof(struct timeval)); /* Inizializzo struttura per richiesta */ initRequest(&req); /* Prelevo la richiesta ed estraggo le informazioni. Se a buon fine l'avrò tutta in req->buf, mentre il resto sarà estratto e messo negli altri campi di req. */ ris = getRequest(clifd,&req); switch(ris) { case -3: /* Client ha chiuso la connessione */ #ifdef DEBUG printf("Thread: %ld. Client ha chiuso connessione. \nBuffer: %s\n", pthread_self(), req.buf); fflush(stdout); #endif close(clifd); exitThread(); return(NULL); break; case -2: /* Errore in lettura, chiudo thread e connessione */ #ifdef DEBUG printf("Thread: %ld. Errore in lettura client request. \nBuffer: %s\n", pthread_self(), req.buf); fflush(stdout); #endif close(clifd); exitThread(); return(NULL); break; case -1: /* Lettura richiesta terminata, formato richiesta sbagliato */ strcpy(error_response, "403\n\n"); mysend(clifd, error_response, strlen(error_response)); #ifdef DEBUG printf("Thread: %ld. Lettura req terminata, formato richiesta sbagliato. \nBuffer: %s\n", pthread_self(), req.buf); fflush(stdout); #endif close(clifd); exitThread(); return(NULL); break; case 1: /* Lettura richiesta OK -> proseguo */ #ifdef DEBUG printf("Thread: %ld. Lettura req OK. \nBuffer: %s\n", pthread_self(), req.buf); fflush(stdout); #endif break; default: /* Errore sconosciuto */ strcpy(error_response, "402\n\n"); mysend(clifd, error_response, strlen(error_response)); #ifdef DEBUG printf("Thread: %ld. Errore sconosciuto. \nBuffer: %s\n", pthread_self(), req.buf); fflush(stdout); #endif close(clifd); exitThread(); return(NULL); break; } /* Switch */ /* Ora ho nella struttura Request tutte le informazioni che mi servono */ /* Tentativi connessione server */ int servconn_chance = SERVER_CHANCE; /* Ogni qualvolta ritento una connessione con il server per errori, ricontrollo di avere il file in cache, qualche altro thread potrebbe averlo salvato nel frattempo. */ while (1) { #ifdef DEBUG printf("Controllo su thread: %ld. While session().\n", pthread_self()); fflush(stdout); #endif /* Se ha fatto una richiesta GET e ho il file in cache */ if ((req.reqType == GET) && (get_cache_name(&(req.inaddr), req.port, req.path, cache_filename))) { /* Cerco di preparare la risposta da mandare (Anche con RANGE), l'eventuale contenuto del file è nel buffer di resp */ ris = prepareGetResponse(&req, &resp, cache_filename); #ifdef DEBUG printf("Thread: %ld. La req è GET e ho il file in cache. \nFile: %s\n", pthread_self(), resp.buf); fflush(stdout); #endif switch(ris) { case 1: ris = mysend(clifd, resp.buf, resp.lenresp); /* caso OK ------> MANDO AL CLIENT IL FILE CHE ERA IN CACHE e chiudo */ if (ris == -1) { printf ("Error on cached file response send.\n"); fflush(stdout); } if (ris == -2) { printf ("Time out on cached file response send.\n"); fflush(stdout); } if (ris == 0) { printf ("Client closed connection before sending cached file.\n"); fflush(stdout); } else { printf ("Cached file sent to client.\n"); fflush(stdout); } close(clifd); exitThread(); return(NULL); break; case -3: /* file not found (expired nel frattempo) ---> faccio la richiesta */ #ifdef DEBUG printf("Thread: %ld. Avevo il file ma è expired. \n", pthread_self()); fflush(stdout); #endif break; case -4: /* interval not found -----> lo notifico */ strcpy(error_response, "405\n\n"); mysend(clifd, error_response, strlen(error_response)); #ifdef DEBUG printf("Thread: %ld. Avevo il file ma il RANGE è sbagliato. \n", pthread_self()); fflush(stdout); #endif close(clifd); exitThread(); return(NULL); break; case -5: /* unknown error */ default: strcpy(error_response, "402\n\n"); mysend(clifd, error_response, strlen(error_response)); #ifdef DEBUG printf("Thread: %ld. Avevo il file ma dopo la prepareResponse errore sconosciuto.\n", pthread_self()); fflush(stdout); #endif close(clifd); exitThread(); return(NULL); break; } } /* Fine GET e ho il file in cache */ /* Non ho file in cache oppure richiesta INF -> Forward richiesta al server e poi discrimino in base a GET (prefetch) e INF (solo forward risposta) */ servfd = socket(AF_INET, SOCK_STREAM, 0); if (servfd < 0) { printf("Thread: %ld. Chiamata a socket() per serverfd fallita. Errore: %d \"%s\"\n", pthread_self(), errno,strerror(errno)); fflush(stdout); close(clifd); exitThread(); return(NULL); } /* Server socket Timeout */ struct timeval timerserv; timerserv.tv_sec = INACTIVITY_TIMEOUT_SECONDS; timerserv.tv_usec = 0; if ((SetsockoptReuseAddr(servfd) == 0) || (setsockopt(servfd, SOL_SOCKET, SO_RCVTIMEO, &timerserv, sizeof(struct timeval)) != 0) || (setsockopt(servfd, SOL_SOCKET, SO_SNDTIMEO, &timerserv, sizeof(struct timeval)) != 0)) { printf("Thread: %ld. Error on a setsockopt for server socket\n", pthread_self()); fflush(stdout); close(servfd); close(clifd); exitThread(); return(NULL); } /* Binding */ memset(&Local, 0, sizeof(Local)); Local.sin_family = AF_INET; Local.sin_addr.s_addr = INADDR_ANY; Local.sin_port = htons(0); ris = bind(servfd, (struct sockaddr *)&Local, sizeof(Local)); if (ris < 0) { printf("Thread: %ld. Chiamata a bind() per serverfd fallita. Errore: %d \"%s\"\n", pthread_self(), errno,strerror(errno)); fflush(stdout); close(servfd); exitThread(); return(NULL); } /* Compilo campi server */ memset(&Serv, 0, sizeof(Serv)); Serv.sin_family = AF_INET; Serv.sin_addr.s_addr = req.inaddr.s_addr; Serv.sin_port = htons(req.port); #ifdef DEBUG printf ("Thread: %ld, %d° tentativo connessione con server. FD: %d\n", pthread_self(), (SERVER_CHANCE-servconn_chance+1), servfd); fflush(stdout); #endif int repeat; repeat = 0; while (1) { #ifdef DEBUG printf("Controllo su thread: %ld. While connect session.\n", pthread_self()); fflush(stdout); #endif ris = connect (servfd, (struct sockaddr *)&Serv, sizeof(Serv)); if (ris < 0) { if ((errno == EINTR) || (errno == EINPROGRESS)) ; /* Ritento */ if (errno == EISCONN) { printf("Thread: %ld, Chiamata a connect() per serverfd fallita. FD: %d. Errore: %d \"%s\"\n", pthread_self(), servfd, errno,strerror(errno)); fflush(stdout); repeat = 0; break; } else { printf("Thread: %ld, Chiamata a connect() per serverfd fallita. FD: %d. Errore: %d \"%s\"\n", pthread_self(), servfd, errno,strerror(errno)); fflush(stdout); if (servconn_chance > 0) servconn_chance--; /* Ritento */ else { printf("Thread: %ld, Chiamata a connect() per serverfd fallita. FD: %d. Errore: %d \"%s\"\n", pthread_self(), servfd, errno,strerror(errno)); fflush(stdout); close(servfd); exitThread(); return(NULL); } /* Ritento nuovo socket */ repeat = 1; break; } /* Errore non recuperabile */ } /* Error on connect */ else { /* OK */ repeat = 0; break; } } /* Connect while */ /* Se è il caso torno indietro */ if (repeat) continue; /* Forwardo la richiesta, qualunque essa sia (inf/get) */ #ifdef DEBUG printf("Thread: %ld. Forward richiesta del client al server.\n Req: %s\n", pthread_self(), req.buf); fflush(stdout); #endif ris = mysend(servfd, req.buf, strlen(req.buf)); if (ris < 0) { #ifdef DEBUG printf("Thread: %ld. Errore su forward req.\n", pthread_self()); fflush(stdout); #endif if (servconn_chance > 0) { servconn_chance--; close(servfd); continue; /* Chiudo questa connessione e ritento */ } else { close(clifd); close(servfd); exitThread(); return(NULL); } } /* Aspetto la risposta del server */ ris = myread(servfd, buffer, MAXLENRESP); if (ris <= 0) { #ifdef DEBUG printf("Thread: %ld. Errore in risposta server a forward req del client.\nErrore: %d \"%s\"\n", pthread_self(), errno,strerror(errno)); fflush(stdout); #endif if (servconn_chance > 0) { servconn_chance--; close(servfd); continue; /* Chiudo questa connessione e ritento */ } else { close(clifd); close(servfd); exitThread(); return(NULL); } } #ifdef DEBUG printf("Thread: %ld. OK arrivo risposta dal server per forward al client.\n Resp: %s\n", pthread_self(), buffer); fflush(stdout); #endif /* Concludo chiusura con server */ close(servfd); /* Terminatore */ buffer[ris] = '\0'; buffer_len = ris; /* Controllo errori 40X nel qual caso forwardo e chiudo */ if ((!(strncmp(buffer,"402\n\n",5))) || (!(strncmp(buffer,"403\n\n",5))) || (!(strncmp(buffer,"404\n\n",5))) || (!(strncmp(buffer,"405\n\n",5)))) { #ifdef DEBUG printf("Thread: %ld. Server ha inviato un errore 40X, faccio forward al Client", pthread_self()); fflush(stdout); #endif ris = mysend(clifd, buffer, buffer_len); close(clifd); exitThread(); return(NULL); } /* Se la richiesta era INF faccio un parsing per INF e invio a client */ if (req.reqType == INF) { /* Corretto */ if (parseINF(buffer, buffer_len) == 0){ ris = mysend(clifd, buffer, buffer_len); if (ris < 0) /* Errore irreparabile col client */ #ifdef DEBUG printf("Thread: %ld. Errore in risposta a Client (dopo arrivo dal server).\n Errore: %d \"%s\"\n", pthread_self(), errno,strerror(errno)); fflush(stdout); #endif close(clifd); exitThread(); return(NULL); } /* Errato */ else continue; /* Ritento */ } /* Se la richiesta era GET per RANGE faccio il parsing per RANGE e poi invio il file */ if (req.is_range) { /* Corretto */ if (parseRANGE(buffer, buffer_len) == 0) ; /* Vado comunque a fare il parsing per fare prefetch sugli URL che trovo */ /* Errato */ else continue; /* Ritento */ } int expire; char cachename[MAXLENPATH]; struct timeval tod; /* Se invece la richiesta era GET per file completo prima faccio parsing per GET completo. Se corretto salvo il file (così è a disposizione di altri thread) e poi invio a client */ if (!(req.is_range)) { #ifdef DEBUG printf("Thread: %ld. Prelevo nome per caching.\n", pthread_self()); fflush(stdout); #endif /* Prelevo nome univoco */ my_tempname(cachename); #ifdef DEBUG printf("Thread: %ld. Salvo file caching.\n", pthread_self()); fflush(stdout); #endif /* SE CORRETTO E COMPLETO salvo file appena scaricato in cache e prelevo expire */ expire = buffer_data_to_file (cachename, buffer, buffer_len); /* Non completo / Corrotto */ if (expire < 0) { #ifdef DEBUG printf("Thread: %ld. Il file arrivato è corrotto.\nEcco il file:\n", pthread_self()); fflush(stdout); #endif write(1, buffer, MAXLENRESP); fflush(stdout); continue; /* Ritento da capo connessione con server e richiesta */ } else { /* Prendo tempo attuale da sommare al tempo di expire del file appena ricevuto */ gettimeofday(&tod, NULL); /* Gestione cache, aggiunta file */ add_file_cache(&(req.inaddr), req.port, req.path, (tod.tv_sec + expire), cachename); } } /* Ora ho nel buffer ciò che devo inviare a Client e in ogni caso faccio lo stesso tipo di invio */ ris = mysend(clifd, buffer, buffer_len); if (ris < 0) { /* Errore irreparabile col client */ #ifdef DEBUG printf("Thread: %ld. Errore in risposta a Client (dopo arrivo dal server).\n Errore: %d \"%s\"\n", pthread_self(), errno,strerror(errno)); fflush(stdout); #endif close(clifd); exitThread(); return(NULL); } #ifdef DEBUG printf("Thread: %ld. OK risposta dopo arrivo file del Server verso Client.\n Resp: %s\n", pthread_self(), buffer); fflush(stdout); #endif /* In ogni caso ho finito col client */ close(clifd); /* Inizializzo qui, ma viene modificato nel parsing per scorrere il buffer con la risposta */ int lenparsed = 0; struct Request *p_prefetch_req; char tmpname[MAXLENPATH]; #ifdef DEBUG printf("Thread: %ld. Fase prefetching.\n", pthread_self()); fflush(stdout); #endif while(1) { #ifdef DEBUG printf("Controllo su thread: %ld. While parse session().\n", pthread_self()); fflush(stdout); #endif /* Struttura Request per fare richiesta al server, già passabile come parametro a thread */ p_prefetch_req = (struct Request *) malloc (sizeof(struct Request)); if (p_prefetch_req == NULL){ #ifdef DEBUG printf("Thread: %ld. Errore in allocazione p_prefetch_req.\n", pthread_self()); fflush(stdout); #endif exitThread(); return(NULL); } /* Chiamo il parsing saltando almeno il minimo numero di byte che possono esserci prima dei dati. NB: USO CAMPO "buf[]" della struttura Request per l'URL!! NB2: Chiedo sia REF che IDX;REF per 1° e 2° livello */ #ifdef DEBUG printf("Thread: %ld. Fase parsing del buffer.\n", pthread_self()); fflush(stdout); #endif ris = parse((buffer+MIN_BYTE_BEFORE_DATA), &lenparsed, (buffer_len-MIN_BYTE_BEFORE_DATA), p_prefetch_req, FIRST_SECOND_LEVEL_PREFETCHING); /* Parsing finito, per errori o fine buffer */ if(ris <= 0) { exitThread(); return(NULL); } else if(ris == 1) { #ifdef DEBUG printf("Thread: %ld. OK parsing, URL estratto: %s.\n", pthread_self(), p_prefetch_req->buf); fflush(stdout); #endif /* Thread che fanno prefetch su REF - IDX+REF */ pthread_attr_t attr; pthread_attr_init(&attr); pthread_t threadID; pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED); /* Se ho già il file passo al prossimo URL */ if(get_cache_name(&(p_prefetch_req->inaddr), p_prefetch_req->port, p_prefetch_req->path, tmpname)) { free(p_prefetch_req); p_prefetch_req = NULL; continue; } /* Altrimenti setto il campo reqType della struttura Request che uso come parametro al thread, impostandolo per il prefetching di primo e secondo livello.. */ p_prefetch_req->reqType = FIRST_SECOND_LEVEL_PREFETCHING; /* .. e faccio partire il thread relativo alla sessione di prefetching per URL specificato in p_prefetch_req->buf[] */ ris = pthread_create(&threadID, &attr, get_and_cache, (void *)p_prefetch_req); if(ris != 0) { printf("Thread: %ld. Chiamata a pthread_create() fallita.\n Errore: %d \"%s\"\n", pthread_self(), errno,strerror(errno)); fflush(stdout); continue; } } } /* while del parsing */ } /* While socket/binding */ } /* Session ****************/
int TCP_setup_socket_listening(int *plistenfd, int numero_porta_locale, int dimSndBuf, int dimRcvBuf, int TcpNoDelay) { int ris; struct sockaddr_in Local; *plistenfd = socket(AF_INET, SOCK_STREAM, 0); if (*plistenfd < 0) { printf ("socket() failed, Err: %d \"%s\"\n", errno,strerror(errno)); return(0); } /* avoid EADDRINUSE error on bind() */ ris = SetsockoptReuseAddr(*plistenfd); if (!ris) { printf ("SetsockoptReuseAddr() failed, Err: %d \"%s\"\n", errno,strerror(errno)); close(*plistenfd); return(0); } if(dimSndBuf>0) { int n; ris=SetsockoptSndBuf(*plistenfd,dimSndBuf); if (!ris) exit(5); ris=GetsockoptSndBuf(*plistenfd,&n); if (!ris) exit(5); /* else printf ("SndBuf listenfd %d\n", n); */ } if(dimRcvBuf>0) { int n; ris=SetsockoptRcvBuf(*plistenfd,dimRcvBuf); if (!ris) exit(5); ris=GetsockoptRcvBuf(*plistenfd,&n); if (!ris) exit(5); /* else printf ("RcvBuf listenfd %d\n", n); */ } { int n; ris=SetsockoptTCPNODELAY(*plistenfd,TcpNoDelay); if (!ris) exit(5); ris=GetsockoptTCPNODELAY(*plistenfd,&n); if (!ris) exit(5); /* else printf ("TCPNODELAY listenfd %d\n", n); */ } /*name the socket */ memset ( &Local, 0, sizeof(Local) ); Local.sin_family= AF_INET; /* specifico l'indirizzo IP attraverso cui voglio ricevere la connessione */ Local.sin_addr.s_addr = htonl(INADDR_ANY); Local.sin_port = htons(numero_porta_locale); ris = bind(*plistenfd, (struct sockaddr*) &Local, sizeof(Local)); if (ris<0) { printf ("bind() failed, Err: %d \"%s\"\n",errno,strerror(errno)); fflush(stderr); close(*plistenfd); return(0); } /* enable accepting of connection */ ris = listen(*plistenfd, 100 ); if (ris<0) { printf ("listen() failed, Err: %d \"%s\"\n",errno,strerror(errno)); exit(1); } return(1); }