/* * Retrieve a process's psinfo via an already-opened or new file descriptor. * The supplied descriptor will be closed on failure. An optional callback * will be invoked with the last descriptor tried, and a supplied callback * argument, as its arguments, such that the new descriptor may be cached, or * an old one may be invalidated. If the result of the callback is zero, the * the caller is to assume responsibility for the file descriptor, to close it * with rfd_close(). * * On failure, a nonzero value is returned. */ int get_psinfo(pid_t pid, psinfo_t *psinfo, int cached_fd, int(*fd_update_cb)(void *, int), void *arg, lprocess_t *lpc) { int fd; int can_try_uncached; ASSERT(!(cached_fd > 0 && fd_update_cb == NULL)); do { if (cached_fd >= 0) { fd = cached_fd; can_try_uncached = 1; debug_high("%d/psinfo, trying cached fd %d\n", (int)pid, fd); } else { char pathbuf[PROC_PATH_MAX]; can_try_uncached = 0; (void) snprintf(pathbuf, sizeof (pathbuf), "/proc/%d/psinfo", (int)pid); if ((fd = rfd_open(pathbuf, 1, RFD_PSINFO, revoke_psinfo, lpc, O_RDONLY, 0000)) < 0) { debug("cannot open %s", pathbuf); break; } else debug_high("opened %s, fd %d\n", pathbuf, fd); } if (pread(fd, psinfo, sizeof (*psinfo), 0) == sizeof (*psinfo) && psinfo->pr_pid == pid) break; else { debug_high("closed fd %d\n", fd); if (rfd_close(fd) != 0) debug("could not close fd %d", fd); fd = cached_fd = -1; } } while (can_try_uncached == 1); if (fd_update_cb == NULL || fd_update_cb(arg, fd) != 0) if (fd >= 0) { debug_high("closed %s fd %d\n", fd_update_cb == NULL ? "uncached" : "cached", fd); if (rfd_close(fd) != 0) debug("could not close fd %d", fd); } debug_high("get_psinfo ret %d, fd %d, %s\n", ((fd >= 0) ? 0 : -1), fd, fd_update_cb != NULL ? "cached" : "uncached"); return ((fd >= 0) ? 0 : -1); }
static int list_walk_process_cb(lcollection_t *lcol, void *arg) { int (*cb)(lcollection_t *, lprocess_t *) = (int(*)(lcollection_t *, lprocess_t *))arg; lprocess_t *member; lprocess_t *next; member = lcol->lcol_lprocess; while (member != NULL) { pid_t pid = member->lpc_pid; next = member->lpc_next; debug_high("list_walk_all lpc %d\n", (int)pid); if (cb(lcol, member) != 0) { debug_high("list_walk_all aborted at lpc %d\n", (int)pid); return (1); } member = next; } return (0); }
/* * Unlink a process from its collection, updating relevant statistics, and * freeing its associated memory. */ void lprocess_free(lprocess_t *lpc) { pid_t pid; lpc->lpc_collection->lcol_stat.lcols_proc_out++; if (lpc->lpc_prev != NULL) lpc->lpc_prev->lpc_next = lpc->lpc_next; if (lpc->lpc_next != NULL) lpc->lpc_next->lpc_prev = lpc->lpc_prev; if (lpc->lpc_collection->lcol_lprocess == lpc) lpc->lpc_collection->lcol_lprocess = (lpc->lpc_next != lpc ? lpc->lpc_next : NULL); lpc->lpc_next = lpc->lpc_prev = NULL; if (lpc->lpc_prpageheader != NULL) free(lpc->lpc_prpageheader); if (lpc->lpc_xmap != NULL) free(lpc->lpc_xmap); if (lpc->lpc_psinfo_fd >= 0) { if (rfd_close(lpc->lpc_psinfo_fd) != 0) debug("could not close %d lpc_psinfo_fd %d", (int)lpc->lpc_pid, lpc->lpc_psinfo_fd); lpc->lpc_psinfo_fd = -1; } if (lpc->lpc_pgdata_fd >= 0) { if (rfd_close(lpc->lpc_pgdata_fd) != 0) debug("could not close %d lpc_pgdata_fd %d", (int)lpc->lpc_pid, lpc->lpc_pgdata_fd); lpc->lpc_pgdata_fd = -1; } if (lpc->lpc_xmap_fd >= 0) { if (rfd_close(lpc->lpc_xmap_fd) != 0) debug("could not close %d lpc_xmap_fd %d", (int)lpc->lpc_pid, lpc->lpc_xmap_fd); lpc->lpc_xmap_fd = -1; } if (lpc->lpc_ignore != NULL) lmapping_free(&lpc->lpc_ignore); pid = lpc->lpc_pid; free(lpc); debug_high("process %d freed\n", (int)pid); }
void ClientManager::manageTransferFromDestToClient(struct sockaddr_in *if_used) { int n_recv = 0; int n_tot_recv = 0; int block_stat_recv = 0; struct timeval time_st, time_en; debug_high("[PID: %d] - BEGIN ClientManager::manageTransferFromDestToClient\n", getpid()); gettimeofday(&time_st, NULL); debug_high("Receiving from server and sending to the client\n"); do { memset(buffer, 0, sizeof(buffer)); //n_recv = recv(sockfd_VideoServer, buffer, sizeof(buffer), 0); bool tryRead = true; time_t start_t, end_t; double diff_t; time(&start_t); while(tryRead) { tryRead = false; n_recv = recv(sockfd_VideoServer, buffer, sizeof(buffer), MSG_DONTWAIT); if ((n_recv < 0) && ((errno == EAGAIN) || (errno == EWOULDBLOCK))) { usleep(100000); time(&end_t); diff_t = difftime(end_t, start_t); //if (diff_t < InterfacesManager::getInstance().timer_update) { if (diff_t < 8) { tryRead = true; } } } if (n_recv > 0) { int n_sent = send(new_sockfd_VideoClient, buffer, n_recv, 0); if(n_sent < 0) { perror("Error sending to client the server reply"); } else if(n_sent == 0) { debug_low("Connection closed by the client while sending back the message!?!?!\n"); } else { n_tot_recv += n_recv; block_stat_recv += n_recv; debug_high("\r%d of %d ", n_recv, n_tot_recv); StatManager::getInstance().actual_stats.reply_ok = true; if (block_stat_recv >= byte_update) { gettimeofday(&time_en, NULL); InterfacesManager::getInstance().updateInterfaceStats(if_used, block_stat_recv, timevaldiff_usec(&time_st, &time_en)); block_stat_recv = 0; gettimeofday(&time_st, NULL); } } } else if (n_recv == 0) { debug_high("connection closed by the server\n"); } else { perror("manageTransferFromDestToClient: Error receiving from server while forwarding"); } } while (n_recv > 0); StatManager::getInstance().actual_stats.frag_bytesize = n_tot_recv; time(&StatManager::getInstance().actual_stats.end_request_time); gettimeofday(&StatManager::getInstance().actual_stats.end_request_timeval, NULL); debug_high("\n"); if (n_tot_recv == block_stat_recv) { // never made stats (packet size less then "byte_update") gettimeofday(&time_en, NULL); InterfacesManager::getInstance().updateInterfaceStats(if_used, block_stat_recv, timevaldiff_usec(&time_st, &time_en)); } StatManager::getInstance().makeStat(); debug_high("[PID: %d] - END ClientManager::manageTransferFromDestToClient\n", getpid()); }
void ClientManager::manageTransferOnStatUpdate(struct sockaddr_in *if_used) { int n_recv = 0; int n_tot_recv = 0; int block_stat_recv = 0; struct timeval time_st, time_en; gettimeofday(&time_st, NULL); debug_high("Receiving from client ONLY for statistics\n"); do { memset(buffer, 0, sizeof(buffer)); //n_recv = recv(sockfd_VideoServer, buffer, sizeof(buffer), 0); bool tryRead = true; time_t start_t, end_t; double diff_t; //debug_medium("[%d] ----- Start receiving the STATISTICAL packet\n", getpid()); time(&start_t); while(tryRead) { tryRead = false; n_recv = recv(sockfd_VideoServer, buffer, sizeof(buffer), MSG_DONTWAIT); //debug_medium("[%d] ----- Received %d byte for the the STATISTICAL packet\n", getpid(), n_recv); if ((n_recv < 0) && ((errno == EAGAIN) || (errno == EWOULDBLOCK))) { usleep(100000); time(&end_t); diff_t = difftime(end_t, start_t); double interval_update = InterfacesManager::getInstance().timer_update; if (interval_update < 8) { interval_update = 8; } if (diff_t < interval_update) { tryRead = true; } //debug_medium("[%d] ----- Received %d byte for the the STATISTICAL packet\n", getpid(), n_recv); } } if (n_recv > 0) { n_tot_recv += n_recv; block_stat_recv += n_recv; if (block_stat_recv > byte_update) { gettimeofday(&time_en, NULL); InterfacesManager::getInstance().updateInterfaceStats(if_used, block_stat_recv, timevaldiff_usec(&time_st, &time_en)); block_stat_recv = 0; gettimeofday(&time_st, NULL); } } else if (n_recv == 0) { //debug_high("connection closed by the server\n"); } else { perror("Error receiving from client while forwarding"); } } while (n_recv > 0); if (n_tot_recv == block_stat_recv) { // never made stats (packet size less then "byte_update") gettimeofday(&time_en, NULL); InterfacesManager::getInstance().updateInterfaceStats(if_used, block_stat_recv, timevaldiff_usec(&time_st, &time_en)); } }
bool ClientManager::sendGETtoDest(struct sockaddr_in *if_to_bind, bool dummy_req) { struct sockaddr_in host_addr; struct sockaddr_in dummy_if_to_bind; debug_high("[PID: %d] - BEGIN ClientManager::sendGETtoDest\n", getpid()); host_addr.sin_port = htons(rm.getServerPort()); host_addr.sin_family=AF_INET; //host_addr.sin_addr.s_addr = rm.getServerAddr(); if (strcmp(inet_ntoa(host_addr.sin_addr), "0.0.0.0") == 0){ inet_aton("143.205.176.132", &(host_addr.sin_addr)); } else { host_addr.sin_addr.s_addr = rm.getServerAddr(); } if (if_to_bind){ debug_high("Start sending the GET to the server using %s\n", inet_ntoa(if_to_bind->sin_addr)); } else { debug_high("[PID: %d] - DEBUG (making dummy address) ClientManager::sendGETtoDest\n", getpid()); dummy_if_to_bind.sin_family = AF_INET; //if_to_use.sin_port=htons(0); int portToUse = (rand()%1000) + 9000; dummy_if_to_bind.sin_port = htons(portToUse); dummy_if_to_bind.sin_addr.s_addr = INADDR_ANY; if_to_bind = &dummy_if_to_bind; } sockfd_VideoServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sockfd_VideoServer < 0) { perror("Error on creating socket for the server connection"); debug_high("[PID: %d] - END (false1) ClientManager::sendGETtoDest\n", getpid()); return false; } else { int risBind = 0; // if I don't have to execute the bind '0' will be OK debug_high("[PID: %d] - DEBUG (before bind) ClientManager::sendGETtoDest\n", getpid()); if (if_to_bind != NULL) { debug_high("[PID: %d] - DEBUG (really binding %s:%d) ClientManager::sendGETtoDest\n", getpid(), inet_ntoa(if_to_bind->sin_addr), (int)(ntohs(if_to_bind->sin_port))); risBind = bind (sockfd_VideoServer, (struct sockaddr *)if_to_bind, sizeof(struct sockaddr_in)); } debug_high("[PID: %d] - DEBUG (after bind) ClientManager::sendGETtoDest\n", getpid()); if (risBind == 0) { int x = fcntl(sockfd_VideoServer, F_GETFL,0); // Get socket flags fcntl(sockfd_VideoServer, F_SETFL, sockfd_VideoServer | O_NONBLOCK); // Add non-blocking flag int ris_conn; bool tryRead = true; time_t start_t, end_t; double diff_t; time(&start_t); while(tryRead) { tryRead = false; ris_conn = connect(sockfd_VideoServer, (struct sockaddr*)&host_addr, sizeof(struct sockaddr)); if ((ris_conn < 0) && ((errno == ETIMEDOUT) || (errno == ENETUNREACH) || (errno == EINPROGRESS) || (errno == EALREADY))) { usleep(200000); time(&end_t); diff_t = difftime(end_t, start_t); if (diff_t < 5) { tryRead = true; } } } //if (connect(sockfd_VideoServer, (struct sockaddr*)&host_addr, sizeof(struct sockaddr)) < 0) {à if (ris_conn < 0) { perror("Error in connecting to remote server"); debug_high("[PID: %d] - END (err connecting to %s:%d) ClientManager::sendGETtoDest\n", getpid(), inet_ntoa(host_addr.sin_addr), (int)(ntohs(host_addr.sin_port))); return false; } else { //debug_high("Sending the original req to the destination: \n******************************\n%s\n******************************\n", // rm.getCopyOfGET()); debug_high("[PID: %d] - DEBUG (connected) ClientManager::sendGETtoDest\n", getpid()); int n_send; if (dummy_req) n_send = send(sockfd_VideoServer, rm.getDummyGET(), strlen(rm.getDummyGET()), 0); else n_send = send(sockfd_VideoServer, rm.getCopyOfGET(), strlen(rm.getCopyOfGET()), 0); if (n_send < 0) { perror("Error writing to server socket"); debug_high("[PID: %d] - END (false3) ClientManager::sendGETtoDest\n", getpid()); return false; } debug_high("[PID: %d] - DEBUG (sent %d bytes) ClientManager::sendGETtoDest\n", getpid(), n_send); } } else { perror("Error binding"); debug_high("[PID: %d] - END (false4) ClientManager::sendGETtoDest\n", getpid()); return false; } } if ((if_to_bind) && (if_to_bind != &dummy_if_to_bind)) { debug_high("End sending the GET to the server using %s\n", inet_ntoa(if_to_bind->sin_addr)); } else { debug_high("End sending the GET to the server\n"); } //start STATS time(&StatManager::getInstance().actual_stats.start_request_time); gettimeofday(&(StatManager::getInstance().actual_stats.start_request_timeval), NULL); debug_high("[PID: %d] - END (true) ClientManager::sendGETtoDest\n", getpid()); return true; }
bool ClientManager::manageRequest(void) { debug_high("[PID: %d] - BEGIN ClientManager::manageRequest\n", getpid()); if (!rm.isLoaded()) { debug_high("[PID: %d] - END (false1) ClientManager::sendGETtoDest\n", getpid()); return false; } struct sockaddr_in if_to_use; struct sockaddr_in *if_to_use_act = NULL; // pointer used to check later if the bind should be done or not //choose the interface to use and, in some cases, update the unused interfaces //if ((rm.isGET()) && (rm.isMPEGDASHreq())) { if ((rm.isGET()) && (rm.isMPEGDASH_M4S())) { std::list<struct sockaddr_in> if_to_update; std::list<struct sockaddr_in>::iterator it_update; InterfacesManager::getInstance().chooseIF(if_to_use, if_to_update); if_to_use_act = &if_to_use; StatManager::getInstance().actual_stats.isMS4 = true; StatManager::getInstance().actual_stats.choosed_interface.s_addr = if_to_use.sin_addr.s_addr; StatManager::getInstance().actual_stats.reply_ok = false; StatManager::getInstance().fillFragmentField(rm.getPathName()); //before managing request check if some interfaces must be updated for (it_update = if_to_update.begin(); it_update != if_to_update.end(); it_update++){ struct sockaddr_in *act_sock = &(*it_update); forkAndUpdateStats(act_sock); // updates are done by other processes // only the parent process should exit from this function... } } else { //tratto in maniera trasparente questa connessione tcp debug_medium("Managing transparently non MPEG-DASH M4S frame get (no stats update)\n"); StatManager::getInstance().actual_stats.isMS4 = false; } if (rm.isMPEGDASHreq() || (!discard_MPEGDASH)) { // Sending the REQUEST to destination and managing the transfer if (sendGETtoDest(if_to_use_act, false)) { manageTransferFromDestToClient(if_to_use_act); close (sockfd_VideoServer); sockfd_VideoServer = -1; } else { debug_low("Error sending request to the destination\n"); } } else { debug_low("Discarding non MPEGH-DASH requests due to the '-x' parameter\n"); } if ((rm.isGET()) && (rm.isMPEGDASH_M4S()) && (StatManager::getInstance().actual_stats.reply_ok == false) && (if_to_use_act != NULL)) { InterfacesManager::getInstance().updateInterfaceStats(if_to_use_act, 1, 1000000); } debug_high("[PID: %d] - END (true) ClientManager::manageRequest\n", getpid()); return true; }
bool ClientManager::getRequestFromClient(void) { debug_high("[PID: %d] - BEGIN ClientManager::getRequestFromClient\n", getpid()); if (new_sockfd_VideoClient < 0) { debug_high("[PID: %d] - END (false1) ClientManager::getRequestFromClient\n", getpid()); return false; } bzero(buffer, sizeof(buffer)); int nrcv = recv(new_sockfd_VideoClient, buffer, sizeof(buffer), 0); if (nrcv < 0) { perror("Error recv from client socket"); debug_high("[PID: %d] - END (false2) ClientManager::getRequestFromClient\n", getpid()); return false; } else if (nrcv == 0) { debug_high("ClientManager::getRequestFromClient - Connection closed by client\n"); debug_high("[PID: %d] - END (false3) ClientManager::getRequestFromClient\n", getpid()); return false; } else { // parsing the GET debug_high("[PID: %d] - DEBUG (before load_req) ClientManager::getRequestFromClient\n", getpid()); if (!rm.load_req(buffer, nrcv)) { // not a get and hence I have to get the destination address in another way // fill at least host_name and server_port (if present) // assume s is a connected socket socklen_t len; struct sockaddr_storage addr; char ipstr[INET6_ADDRSTRLEN]; int port; debug_high("[PID: %d] - DEBUG (false load_req) ClientManager::getRequestFromClient\n", getpid()); len = sizeof addr; getpeername(new_sockfd_VideoClient, (struct sockaddr*)&addr, &len); // deal with IPv4 only: if (addr.ss_family == AF_INET) { struct sockaddr_in *s = (struct sockaddr_in *)&addr; port = ntohs(s->sin_port); inet_ntop(AF_INET, &s->sin_addr, ipstr, sizeof ipstr); printf("Peer IP address: %s\n", ipstr); printf("Peer port : %d\n", port); rm.setServerPort(port); rm.setServerAddr(s->sin_addr.s_addr); } if (rm.isConnectReq()) { debug_high("Replying to CONNECT request\n"); char *rep = "HTTP/1.1 403 Forbidden\n" "Date: Thu, 19 Feb 2009 12:27:04 GMT\n" "Server: Apache/2.2.3\n" "Last-Modified: Wed, 18 Jun 2003 16:05:58 GMT\n" "ETag: \"56d-9989200-1132c580\"\n" "Content-Type: text/html\n" "Content-Length: 15\n" "Accept-Ranges: bytes\n" "Connection: close\n" "\n" "sdfkjsdnbfkjbsf"; //snprintf(rep, sizeof(rep), ""); int s = send (new_sockfd_VideoClient, rep, strlen(rep), 0); debug_high("Succesfully sent %d bytes\n", s); } debug_high("[PID: %d] - END (false4) ClientManager::getRequestFromClient\n", getpid()); return false; //TODO non so come si fa... per ora prendo solo GET // boh! non so come/dove leggere la destinazione } } debug_high("[PID: %d] - END (true) ClientManager::getRequestFromClient\n", getpid()); return true; }