/* * connection.cpp * * Copyright (c) 2004-2006,2008 Arnout Engelen * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, *USA. * */ #include #include #ifdef __APPLE__ #include #else #include #endif #include "nethogs.h" #include "connection.h" #include "process.h" ConnList *connections = NULL; void PackList::add(Packet *p) { if (content == NULL) { content = new PackListNode(new Packet(*p)); return; } if (content->val->time.tv_sec == p->time.tv_sec) { content->val->len += p->len; return; } /* store copy of packet, so that original may be freed */ content = new PackListNode(new Packet(*p), content); } /* sums up the total bytes used and removes 'old' packets */ u_int32_t PackList::sumanddel(timeval t) { u_int32_t retval = 0; PackListNode *current = content; PackListNode *previous = NULL; while (current != NULL) { // std::cout << "Comparing " << current->val->time.tv_sec << " <= " << // t.tv_sec - PERIOD << endl; if (current->val->time.tv_sec <= t.tv_sec - PERIOD) { if (current == content) content = NULL; else if (previous != NULL) previous->next = NULL; delete current; return retval; } retval += current->val->len; previous = current; current = current->next; } return retval; } /* packet may be deleted by caller */ Connection::Connection(Packet *packet) { assert(packet != NULL); connections = new ConnList(this, connections); sent_packets = new PackList(); recv_packets = new PackList(); sumSent = 0; sumRecv = 0; if (DEBUG) { std::cout << "New connection, with package len " << packet->len << std::endl; } if (packet->Outgoing()) { sumSent += packet->len; sent_packets->add(packet); refpacket = new Packet(*packet); } else { sumRecv += packet->len; recv_packets->add(packet); refpacket = packet->newInverted(); } lastpacket = packet->time.tv_sec; if (DEBUG) std::cout << "New reference packet created at " << refpacket << std::endl; } Connection::~Connection() { if (DEBUG) std::cout << "Deleting connection" << std::endl; /* refpacket is not a pointer to one of the packets in the lists * so deleted */ delete (refpacket); if (sent_packets != NULL) delete sent_packets; if (recv_packets != NULL) delete recv_packets; ConnList *curr_conn = connections; ConnList *prev_conn = NULL; while (curr_conn != NULL) { if (curr_conn->getVal() == this) { ConnList *todelete = curr_conn; curr_conn = curr_conn->getNext(); if (prev_conn == NULL) { connections = curr_conn; } else { prev_conn->setNext(curr_conn); } delete (todelete); } else { prev_conn = curr_conn; curr_conn = curr_conn->getNext(); } } } /* the packet will be freed by the calling code */ void Connection::add(Packet *packet) { lastpacket = packet->time.tv_sec; if (packet->Outgoing()) { if (DEBUG) { std::cout << "Outgoing: " << packet->len << std::endl; } sumSent += packet->len; sent_packets->add(packet); } else { if (DEBUG) { std::cout << "Incoming: " << packet->len << std::endl; } sumRecv += packet->len; if (DEBUG) { std::cout << "sumRecv now: " << sumRecv << std::endl; } recv_packets->add(packet); } } Connection *findConnectionWithMatchingSource(Packet *packet) { assert(packet->Outgoing()); ConnList *current = connections; while (current != NULL) { /* the reference packet is always outgoing */ if (packet->matchSource(current->getVal()->refpacket)) { return current->getVal(); } current = current->getNext(); } return NULL; } Connection *findConnectionWithMatchingRefpacketOrSource(Packet *packet) { ConnList *current = connections; while (current != NULL) { /* the reference packet is always *outgoing* */ if (packet->match(current->getVal()->refpacket)) { return current->getVal(); } current = current->getNext(); } return findConnectionWithMatchingSource(packet); } /* * finds connection to which this packet belongs. * a packet belongs to a connection if it matches * to its reference packet */ Connection *findConnection(Packet *packet) { if (packet->Outgoing()) return findConnectionWithMatchingRefpacketOrSource(packet); else { Packet *invertedPacket = packet->newInverted(); Connection *result = findConnectionWithMatchingRefpacketOrSource(invertedPacket); delete invertedPacket; return result; } } /* * Connection::sumanddel * * sums up the total bytes used * and removes 'old' packets. * * Returns sum of sent packages (by address) * sum of recieved packages (by address) */ void Connection::sumanddel(timeval t, u_int32_t *recv, u_int32_t *sent) { (*sent) = (*recv) = 0; *sent = sent_packets->sumanddel(t); *recv = recv_packets->sumanddel(t); }