netperfmeter-1.2.3/ 0000775 0001750 0001750 00000000000 11774302304 011221 5 0000000 0000000 netperfmeter-1.2.3/src/ 0000775 0001750 0001750 00000000000 11774302305 012011 5 0000000 0000000 netperfmeter-1.2.3/src/cpustatus.cc 0000664 0001750 0001750 00000023006 11774302044 014274 0000000 0000000 /* $Id: cpustatus.cc 1431 2012-07-02 11:21:07Z dreibh $
*
* Network Performance Meter
* Copyright (C) 2009-2012 by Thomas Dreibholz
*
* 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 3 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, see .
*
* Contact: dreibh@iem.uni-due.de
*/
#include "cpustatus.h"
#include
#include
#include
#include
#include
#include
#include
#include
#ifdef __FreeBSD__
#include
#endif
#ifdef __APPLE__
#include
#endif
#include
#ifdef __FreeBSD__
#define IDLE_INDEX 4
const char* CPUStatus::CpuStateNames[] = {
"User", "Nice", "System", "Interrupt", "Idle"
};
#elif defined __linux__
#define IDLE_INDEX 3
const char* CPUStatus::CpuStateNames[] = {
"User", "Nice", "System", "Idle", "IOWait",
"Hardware Interrupts", "Software Interrupts", "Hypervisor"
};
#elif defined __APPLE__
#define IDLE_INDEX 2
const char* CPUStatus::CpuStateNames[] = {
"User", "System", "Idle", "Nice"
};
#endif
#ifdef __FreeBSD__
bool CPUStatus::getSysCtl(const char* name, void* ptr, size_t len)
{
size_t nlen = len;
if(sysctlbyname(name, ptr, &nlen, NULL, 0) < 0) {
std::cerr << "ERROR: sysctlbyname(" << name << ") failed: "
<< strerror(errno) << std::endl;
exit(1);
}
if(nlen != len) {
return(false);
}
return(true);
}
#endif
// ###### Constructor #######################################################
CPUStatus::CPUStatus()
{
// ====== Initialize =====================================================
#ifdef __FreeBSD__
CpuStates = CPUSTATES;
getSysCtl("hw.ncpu", &CPUs, sizeof(CPUs));
#elif defined __linux__
CpuStates = 8;
CPUs = sysconf(_SC_NPROCESSORS_CONF);
if(CPUs < 1) {
CPUs = 1;
}
ProcStatFD = fopen("/proc/stat", "r");
if(ProcStatFD == NULL) {
std::cerr << "ERROR: Unable to open /proc/stat!" << std::endl;
exit(1);
}
#elif defined __APPLE__
#ifdef USE_PER_CPU_STATISTICS
kern_return_t kr;
mach_msg_type_number_t count;
host_basic_info_data_t hinfo;
#endif
CpuStates = CPU_STATE_MAX;
if ((host = mach_host_self()) == MACH_PORT_NULL) {
std::cerr << "ERROR: Couldn't receive send rights." << std::endl;
exit(1);
}
#ifdef USE_PER_CPU_STATISTICS
if((kr = host_get_host_priv_port(host, &host_priv)) != KERN_SUCCESS) {
mach_error("host_get_host_priv_port():", kr);
exit(1);
}
count = HOST_BASIC_INFO_COUNT;
if((kr = host_info(host, HOST_BASIC_INFO, (host_info_t)&hinfo, &count)) != KERN_SUCCESS) {
mach_error("host_info():", kr);
exit(1);
};
CPUs = hinfo.max_cpus;
#else
CPUs = 1;
#endif
#endif
// ====== Allocate current times array ===================================
size_t cpuTimesSize = sizeof(tick_t) * (CPUs + 1) * CpuStates;
CpuTimes = (tick_t*)calloc(1, cpuTimesSize);
assert(CpuTimes != NULL);
// ====== Allocate old times array =======================================
cpuTimesSize = sizeof(tick_t) * (CPUs + 1) * CpuStates;
OldCpuTimes = (tick_t*)malloc(cpuTimesSize);
assert(OldCpuTimes != NULL);
memcpy(OldCpuTimes, CpuTimes, cpuTimesSize);
// ====== Allocate percentages array =====================================
const size_t percentagesSize = sizeof(float) * (CPUs + 1) * CpuStates;
Percentages = (float*)malloc(percentagesSize);
assert(Percentages != NULL);
for(unsigned int i = 0; i < (CPUs + 1) * CpuStates; i++) {
Percentages[i] = 100.0 / CpuStates;
}
#ifdef __linux__
update();
#endif
}
// ###### Destructor ########################################################
CPUStatus::~CPUStatus()
{
free(CpuTimes);
CpuTimes = NULL;
free(OldCpuTimes);
OldCpuTimes = NULL;
free(Percentages);
Percentages = NULL;
#ifdef __linux__
fclose(ProcStatFD);
ProcStatFD = NULL;
#endif
#ifdef __APPLE__
#ifdef USE_PER_CPU_STATISTICS
mach_port_deallocate(mach_task_self(), host_priv);
#endif
mach_port_deallocate(mach_task_self(), host);
#endif
}
// ###### Update status #####################################################
void CPUStatus::update()
{
// ====== Save old values ================================================
size_t cpuTimesSize = sizeof(tick_t) * (CPUs + 1) * CpuStates;
memcpy(OldCpuTimes, CpuTimes, cpuTimesSize);
// ====== Get counters ===================================================
#ifdef __FreeBSD__
cpuTimesSize = sizeof(tick_t) * CPUs * CpuStates; /* Total is calculated later! */
getSysCtl("kern.cp_times", &CpuTimes[CpuStates], cpuTimesSize);
// ------ Compute total values -------------------------
for(unsigned int j = 0; j < CpuStates; j++) {
CpuTimes[j] = 0;
for(unsigned int i = 0; i < CPUs; i++) {
CpuTimes[j] += CpuTimes[((i + 1) * CpuStates) + j];
}
}
#elif defined __linux__
rewind(ProcStatFD);
fflush(ProcStatFD);
for(unsigned int i = 0; i <= CPUs; i++) {
char buffer[1024];
if(fgets(buffer, sizeof(buffer), ProcStatFD) == 0) {
std::cerr << "ERROR: Unable to read from /proc/stat!" << std::endl;
exit(1);
}
int result;
if(i == 0) { // Get totals
result = sscanf(buffer, "cpu %llu %llu %llu %llu %llu %llu %llu %llu\n",
&CpuTimes[0],
&CpuTimes[1],
&CpuTimes[2],
&CpuTimes[3],
&CpuTimes[4],
&CpuTimes[5],
&CpuTimes[6],
&CpuTimes[7]);
}
else {
unsigned int id;
result = sscanf(buffer, "cpu%u %llu %llu %llu %llu %llu %llu %llu %llu\n",
&id,
&CpuTimes[(i * CpuStates) + 0],
&CpuTimes[(i * CpuStates) + 1],
&CpuTimes[(i * CpuStates) + 2],
&CpuTimes[(i * CpuStates) + 3],
&CpuTimes[(i * CpuStates) + 4],
&CpuTimes[(i * CpuStates) + 5],
&CpuTimes[(i * CpuStates) + 6],
&CpuTimes[(i * CpuStates) + 7]);
}
if( ((i == 0) && (result < 8)) || ((i > 0) && (result < 9)) ) {
std::cerr << "ERROR: Bad input fromat in /proc/stat!" << std::endl;
exit(1);
}
}
#elif __APPLE__
kern_return_t kr;
#ifdef USE_PER_CPU_STATISTICS
processor_port_array_t processor_list;
natural_t processor_count, info_count;
processor_cpu_load_info_data_t cpu_load_info;
if((kr = host_processors(host_priv, &processor_list, &processor_count)) != KERN_SUCCESS) {
mach_error("host_processors():", kr);
exit(1);
}
for(unsigned int i = 0; i < processor_count; i++) {
info_count = PROCESSOR_CPU_LOAD_INFO_COUNT;
if ((kr = processor_info(processor_list[i], PROCESSOR_CPU_LOAD_INFO, &host, (processor_info_t)&cpu_load_info, &info_count)) != KERN_SUCCESS) {
mach_error("processor_info():", kr);
exit(1);
}
for(unsigned int j = 0; j < CpuStates; j++) {
CpuTimes[((i + 1) * CpuStates) + j] = cpu_load_info.cpu_ticks[j];
}
}
vm_deallocate(mach_task_self(), (vm_address_t)processor_list, processor_count * sizeof(processor_t *));
// ------ Compute total values -------------------------
for(unsigned int j = 0; j < CpuStates; j++) {
CpuTimes[j] = 0;
for(unsigned int i = 0; i < CPUs; i++) {
CpuTimes[j] += CpuTimes[((i + 1) * CpuStates) + j];
}
}
#else
mach_msg_type_number_t count;
host_cpu_load_info_data_t cpu_load_info;
count = HOST_CPU_LOAD_INFO_COUNT;
if((kr = host_statistics(host, HOST_CPU_LOAD_INFO, (host_info_t)&cpu_load_info, &count)) != KERN_SUCCESS) {
mach_error("host_statistics():", kr);
exit(1);
}
for(unsigned int j = 0; j < CpuStates; j++) {
CpuTimes[j] = CpuTimes[CpuStates + j] = cpu_load_info.cpu_ticks[j];
}
#endif
#endif
// ====== Calculate percentages ==========================================
for(unsigned int i = 0; i < CPUs + 1; i++) {
tick_t diffTotal = 0;
tick_t diff[CpuStates];
for(unsigned int j = 0; j < CpuStates; j++) {
const unsigned int index = (i * CpuStates) + j;
if(CpuTimes[index] >= OldCpuTimes[index]) {
diff[j] = CpuTimes[index] - OldCpuTimes[index];
}
else { // Counter wrap!
diff[j] = OldCpuTimes[index] - CpuTimes[index];
}
diffTotal += diff[j];
}
for(unsigned int j = 0; j < CpuStates; j++) {
const unsigned int index = (i * CpuStates) + j;
if(diffTotal != 0) { // Avoid division by zero!
Percentages[index] = 100.0 * (float)diff[j] / (float)diffTotal;
}
assert( (Percentages[index] >= 0.0) && (Percentages[index] <= 100.0) );
}
}
}
// ###### Get CPU utilization ###############################################
float CPUStatus::getCpuUtilization(const unsigned int cpuIndex) const
{
return(100.0 - getCpuStatePercentage(cpuIndex, IDLE_INDEX));
}
netperfmeter-1.2.3/src/TODO 0000664 0001750 0001750 00000000000 11761413565 012416 0000000 0000000 netperfmeter-1.2.3/src/measurement.cc 0000664 0001750 0001750 00000010665 11761413565 014604 0000000 0000000 /* $Id: measurement.cc 1384 2012-05-29 09:48:36Z dreibh $
*
* Network Performance Meter
* Copyright (C) 2009-2012 by Thomas Dreibholz
*
* 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 3 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, see .
*
* Contact: dreibh@iem.uni-due.de
*/
#include "measurement.h"
#include "flow.h"
// ###### Destructor ########################################################
Measurement::Measurement()
{
MeasurementID = 0;
FirstTransmission = 0;
LastTransmission = 0;
FirstReception = 0;
LastReception = 0;
StatisticsInterval = 1000000;
FirstStatisticsEvent = 0;
LastStatisticsEvent = 0;
NextStatisticsEvent = 0;
}
// ###### Destructor ########################################################
Measurement::~Measurement()
{
finish(true);
}
// ###### Initialize measurement ############################################
bool Measurement::initialize(const unsigned long long now,
const uint64_t measurementID,
const char* vectorNamePattern,
const OutputFileFormat vectorFileFormat,
const char* scalarNamePattern,
const OutputFileFormat scalarFileFormat)
{
MeasurementID = measurementID;
FirstStatisticsEvent = 0;
LastStatisticsEvent = 0;
NextStatisticsEvent = 0;
if(FlowManager::getFlowManager()->addMeasurement(this)) {
VectorNamePattern = (vectorNamePattern != NULL) ?
std::string(vectorNamePattern) : std::string();
const bool s1 = VectorFile.initialize(
(vectorNamePattern != NULL) ?
Flow::getNodeOutputName(vectorNamePattern, "active").c_str() : NULL,
vectorFileFormat);
ScalarNamePattern = (scalarNamePattern != NULL) ?
std::string(scalarNamePattern) : std::string();
const bool s2 = ScalarFile.initialize(
(scalarNamePattern != NULL) ?
Flow::getNodeOutputName(scalarNamePattern, "active").c_str() : NULL,
scalarFileFormat);
return(s1 && s2);
}
return(false);
}
// ###### Finish measurement ################################################
bool Measurement::finish(const bool closeFiles)
{
FlowManager::getFlowManager()->removeMeasurement(this);
const bool s1 = VectorFile.finish(closeFiles);
const bool s2 = ScalarFile.finish(closeFiles);
return(s1 && s2);
}
// ###### Write scalars #####################################################
void Measurement::writeScalarStatistics(const unsigned long long now)
{
lock();
FlowManager::getFlowManager()->writeScalarStatistics(
MeasurementID, now, ScalarFile,
FirstStatisticsEvent);
unlock();
}
// ###### Write vectors #####################################################
void Measurement::writeVectorStatistics(const unsigned long long now,
FlowBandwidthStats& globalStats,
FlowBandwidthStats& relGlobalStats)
{
lock();
// ====== Timer management ===============================================
NextStatisticsEvent += StatisticsInterval;
if(NextStatisticsEvent <= now) { // Initialization!
NextStatisticsEvent = now + StatisticsInterval;
}
if(FirstStatisticsEvent == 0) {
FirstStatisticsEvent = now;
LastStatisticsEvent = now;
}
// ====== Write statistics ===============================================
FlowManager::getFlowManager()->writeVectorStatistics(
MeasurementID, now, VectorFile,
globalStats, relGlobalStats,
FirstStatisticsEvent, LastStatisticsEvent);
// ====== Update timing ==================================================
LastStatisticsEvent = now;
unlock();
}
netperfmeter-1.2.3/src/transfer.h 0000664 0001750 0001750 00000002376 11761413565 013745 0000000 0000000 /* $Id: transfer.h 1140 2011-11-23 06:43:27Z dreibh $
*
* Network Performance Meter
* Copyright (C) 2009-2012 by Thomas Dreibholz
*
* 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 3 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, see .
*
* Contact: dreibh@iem.uni-due.de
*/
#ifndef TRANSFER_H
#define TRANSFER_H
#include "flow.h"
#include
ssize_t transmitFrame(Flow* flow,
const unsigned long long now);
ssize_t handleNetPerfMeterData(const bool isActiveMode,
const unsigned long long now,
const int protocol,
const int sd);
#endif
netperfmeter-1.2.3/src/rootshell.c 0000664 0001750 0001750 00000004621 11761413565 014122 0000000 0000000 /* $Id: rootshell.c 1140 2011-11-23 06:43:27Z dreibh $
* --------------------------------------------------------------------------
*
* //===// //===== //===// // // //===//
* // // // // // // // // //
* //===// //===== //===// // // //===<<
* // \\ // // // // // //
* // \\ =====// // //===== // //===// Version II
*
* ------------- An Efficient RSerPool Prototype Implementation -------------
*
* Copyright (C) 2002-2012 by Thomas Dreibholz
*
* 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 3 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, see .
*
* Contact: dreibh@iem.uni-due.de
*/
#include
#include
#include
#include
int main(int argc, char** argv)
{
const char* directory = NULL;
int programArg = 1;
int i;
if(argc < 2) {
fprintf(stderr, "Usage: %s {-chdir=Directory} [Program] {Argument} ...\n", argv[0]);
exit(1);
}
for(i = 1; i < argc; i++) {
if(argv[i][0] == '-') {
programArg = i + 1;
if(strncmp(argv[i], "-chdir=", 7) == 0) {
directory = (const char*)&argv[i][7];
}
else {
fprintf(stderr, "ERROR: Bad parameter \"%s\".\n", argv[i]);
exit(1);
}
}
else {
break;
}
}
if( (setuid(0) == 0) && (setgid(0) == 0) ) {
if(directory) {
if(chdir(directory) != 0) {
perror("Unable to change directory");
exit(1);
}
}
execve(argv[programArg], &argv[programArg], NULL);
perror("Unable to start program");
}
else {
perror("Unable obtain root permissions. Ensure that rootshell is owned by root and has setuid set! Error");
}
return(1);
}
netperfmeter-1.2.3/src/flowbandwidthstats.h 0000664 0001750 0001750 00000004213 11761413565 016024 0000000 0000000 /* $Id: flowbandwidthstats.h 1384 2012-05-29 09:48:36Z dreibh $
*
* Network Performance Meter
* Copyright (C) 2009-2012 by Thomas Dreibholz
*
* 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 3 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, see .
*
* Contact: dreibh@iem.uni-due.de
*/
#ifndef FLOWBANDWIDTHSTATS_H
#define FLOWBANDWIDTHSTATS_H
#include
#include
#include
class FlowBandwidthStats
{
// ====== Methods ========================================================
public:
FlowBandwidthStats();
~FlowBandwidthStats();
void print(std::ostream& os,
const double transmissionDuration,
const double receptionDuration) const;
void reset();
inline static unsigned long long calculateRate(const unsigned long long value,
const double duration) {
if(duration < 0.000001) {
return(0);
}
return((unsigned long long)rint(value / duration));
}
// ====== Public Data ====================================================
public:
unsigned long long TransmittedBytes;
unsigned long long TransmittedPackets;
unsigned long long TransmittedFrames;
unsigned long long ReceivedBytes;
unsigned long long ReceivedPackets;
unsigned long long ReceivedFrames;
unsigned long long LostBytes;
unsigned long long LostPackets;
unsigned long long LostFrames;
};
FlowBandwidthStats operator+(const FlowBandwidthStats& s1, const FlowBandwidthStats& s2);
FlowBandwidthStats operator-(const FlowBandwidthStats& s1, const FlowBandwidthStats& s2);
#endif
netperfmeter-1.2.3/src/outputfile.h 0000664 0001750 0001750 00000004416 11761413565 014316 0000000 0000000 /* $Id: outputfile.h 1384 2012-05-29 09:48:36Z dreibh $
*
* Plain/BZip2 File Output
* Copyright (C) 2009-2012 by Thomas Dreibholz
*
* 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 3 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, see .
*
* Contact: dreibh@iem.uni-due.de
*/
#ifndef OUTPUTFILE_H
#define OUTPUTFILE_H
#include
#include
#include
#include
// Output File Formats
enum OutputFileFormat
{
OFF_None = 0,
OFF_Plain = 1,
OFF_BZip2 = 2
};
class OutputFile
{
// ====== Methods ========================================================
public:
OutputFile();
~OutputFile();
bool initialize(const char* name,
const OutputFileFormat format,
const unsigned int compressionLevel = 9);
bool finish(const bool closeFile = true,
unsigned long long* bytesIn = NULL,
unsigned long long* bytesOut = NULL);
bool printf(const char* str, ...);
bool write(const char* buffer, const size_t bufferLength);
inline bool exists() const {
return(File || BZFile);
}
inline OutputFileFormat getFormat() const {
return(Format);
}
inline FILE* getFile() const {
return(File);
}
inline const std::string& getName() const {
return(Name);
}
inline unsigned long long getLine() const {
return(Line);
}
inline unsigned long long nextLine() {
return(++Line);
}
// ====== Private Data ===================================================
private:
OutputFileFormat Format;
std::string Name;
unsigned long long Line;
FILE* File;
BZFILE* BZFile;
bool WriteError;
};
#endif
netperfmeter-1.2.3/src/messagereader.cc 0000664 0001750 0001750 00000027112 11761413565 015061 0000000 0000000 /* $Id: messagereader.cc 1140 2011-11-23 06:43:27Z dreibh $
*
* Network Performance Meter
* Copyright (C) 2009-2012 by Thomas Dreibholz
*
* 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 3 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, see .
*
* Contact: dreibh@iem.uni-due.de
*/
#include "messagereader.h"
#include
#include
#include
#include
#include "tools.h"
// #define DEBUG_SOCKETS
// #define DEBUG_MESSAGEREADER
// ###### Constructor #######################################################
MessageReader::MessageReader()
{
}
// ###### Destructor ########################################################
MessageReader::~MessageReader()
{
std::map::iterator iterator = SocketMap.begin();
while(iterator != SocketMap.end()) {
Socket* socket = iterator->second;
deregisterSocket(socket->SocketDescriptor);
iterator = SocketMap.begin();
}
}
// ###### Register a socket #################################################
bool MessageReader::registerSocket(const int protocol,
const int sd,
const size_t maxMessageSize)
{
Socket* socket;
std::map::iterator found = SocketMap.find(sd);
if(found == SocketMap.end()) {
assert(maxMessageSize >= sizeof(TLVHeader));
socket = new Socket;
assert(socket != NULL);
socket->MessageBuffer = new char[maxMessageSize];
assert(socket->MessageBuffer != NULL);
socket->MessageBufferSize = maxMessageSize;
socket->MessageSize = 0;
socket->BytesRead = 0;
socket->Status = Socket::MRS_WaitingForHeader;
socket->Protocol = protocol;
socket->SocketDescriptor = sd;
socket->UseCount = 1;
SocketMap.insert(std::pair(sd, socket));
}
else {
socket = found->second;
socket->UseCount++;
}
#ifdef DEBUG_SOCKETS
printf("RegisterSocket: UseCount[sd=%d,proto=%d]=%u\n",
socket->SocketDescriptor, socket->Protocol, (unsigned int)socket->UseCount);
#endif
return(true);
}
// ###### Deregister a socket ###############################################
bool MessageReader::deregisterSocket(const int sd)
{
std::map::iterator found = SocketMap.find(sd);
if(found != SocketMap.end()) {
Socket* socket = found->second;
socket->UseCount--;
#ifdef DEBUG_SOCKETS
printf("DeregisterSocket: UseCount[sd=%d,proto=%d]=%u\n",
socket->SocketDescriptor, socket->Protocol, (unsigned int)socket->UseCount);
#endif
if(socket->UseCount == 0) {
SocketMap.erase(found);
delete [] socket->MessageBuffer;
delete socket;
return(true);
}
return(false); // Socket is still in use!
}
return(true);
}
// ###### Receive full message ##############################################
ssize_t MessageReader::receiveMessage(const int sd,
void* buffer,
size_t bufferSize,
sockaddr* from,
socklen_t* fromSize,
sctp_sndrcvinfo* sinfo,
int* msgFlags)
{
Socket* socket = getSocket(sd);
if(socket != NULL) {
// ====== Find out the number of bytes to read ========================
ssize_t received;
size_t bytesToRead;
if( (socket->Protocol == IPPROTO_SCTP) ||
(socket->Protocol == IPPROTO_TCP) ||
(socket->Protocol == IPPROTO_MPTCP) ) {
// SCTP and TCP can return partial messages upon recv() calls. TCP
// may event return multiple messages, if the buffer size is large enough!
if(socket->Status == Socket::MRS_WaitingForHeader) {
assert(sizeof(TLVHeader) >= socket->BytesRead);
bytesToRead = sizeof(TLVHeader) - socket->BytesRead;
}
else if(socket->Status == Socket::MRS_PartialRead) {
bytesToRead = socket->MessageSize - socket->BytesRead;
}
else {
if(socket->Protocol != IPPROTO_TCP) {
// An error occurred before. Reset and try again ...
socket->Status = Socket::MRS_WaitingForHeader;
socket->BytesRead = 0;
bytesToRead = sizeof(TLVHeader);
}
else {
// Not useful to retry when synchronization has been lost for TCP!
return(MRRM_STREAM_ERROR);
}
}
assert(bytesToRead + socket->BytesRead <= socket->MessageBufferSize);
}
else {
// DCCP and UDP will always return only a single message on recv() calls.
bytesToRead = socket->MessageBufferSize;
}
// ====== Read from socket ============================================
int dummyFlags;
if(msgFlags == NULL) {
dummyFlags = 0;
msgFlags = &dummyFlags;
}
if(socket->Protocol == IPPROTO_SCTP) {
received = sctp_recvmsg(socket->SocketDescriptor,
(char*)&socket->MessageBuffer[socket->BytesRead], bytesToRead,
from, fromSize, sinfo, msgFlags);
}
else {
received = ext_recvfrom(socket->SocketDescriptor,
(char*)&socket->MessageBuffer[socket->BytesRead], bytesToRead,
*msgFlags, from, fromSize);
}
// printf("recv(%d)=%d, eor=%d\n", socket->SocketDescriptor, received, ((*msgFlags & MSG_EOR) != 0));
// ====== Handle received data ========================================
if(received > 0) {
socket->BytesRead += (size_t)received;
// ====== Handle message header ====================================
if(socket->Status == Socket::MRS_WaitingForHeader) {
// ====== Handle SCTP notification header =======================
if((socket->Protocol == IPPROTO_SCTP) && (*msgFlags & MSG_NOTIFICATION)) {
socket->MessageSize = sizeof(sctp_notification); // maximum length
socket->Status = Socket::MRS_PartialRead;
// SCTP notification has no TLV header, but must be handled like
// a message. The actual length of the notification is unknown, we
// need to look for MSG_EOF!
}
// ====== Handle TLV header =====================================
else {
if(socket->BytesRead >= sizeof(TLVHeader)) {
const TLVHeader* header = (const TLVHeader*)socket->MessageBuffer;
#ifdef DEBUG_MESSAGEREADER
printf("Socket %d: T=%u F=%02x L=%u [Header]\n",
socket->SocketDescriptor,
(unsigned int)header->Type, (unsigned int)header->Flags, ntohs(header->Length));
#endif
socket->MessageSize = ntohs(header->Length);
if(socket->MessageSize < sizeof(TLVHeader)) {
std::cerr << "ERROR: Message size < TLV size!" << std::endl;
socket->Status = Socket::MRS_StreamError;
return(MRRM_STREAM_ERROR);
}
else if(socket->MessageSize > socket->MessageBufferSize) {
std::cerr << "ERROR: Message too large to fit buffer!" << std::endl;
socket->Status = Socket::MRS_StreamError;
return(MRRM_STREAM_ERROR);
}
socket->Status = Socket::MRS_PartialRead;
}
else {
return(MRRM_PARTIAL_READ);
}
}
// Continue here with MRS_PartialRead status!
// (will return MRRM_PARTIAL_READ, or message on header-only message)
}
// ====== Handle message payload ===================================
if(socket->Status == Socket::MRS_PartialRead) {
#ifdef DEBUG_MESSAGEREADER
printf("Socket %d: T=%u F=%02x L=%u [%u/%u]\n",
socket->SocketDescriptor,
((const TLVHeader*)socket->MessageBuffer)->Type,
((const TLVHeader*)socket->MessageBuffer)->Flags,
ntohs(((const TLVHeader*)socket->MessageBuffer)->Length),
(unsigned int)socket->BytesRead,
(unsigned int)socket->MessageSize);
#endif
// ====== Partially read message ================================
if(socket->BytesRead < socket->MessageSize) {
if(socket->Protocol == IPPROTO_SCTP) {
if(*msgFlags & MSG_EOR) { // end of SCTP message
if(!(*msgFlags & MSG_NOTIFICATION)) { // data message
std::cerr << "ERROR: SCTP message end before TLV message end!" << std::endl
<< " Read " << socket->BytesRead
<< ", expected " << socket->MessageSize << std::endl;
socket->Status = Socket::MRS_StreamError;
return(MRRM_STREAM_ERROR);
}
// This is the end of the SCTP notification. The message
// is complete here. Return it to the caller.
socket->MessageSize = socket->BytesRead;
}
else {
return(MRRM_PARTIAL_READ);
}
}
else {
return(MRRM_PARTIAL_READ);
}
}
// ====== Completed reading =====================================
if(socket->MessageSize > bufferSize) {
std::cerr << "ERROR: Buffer size for MessageReader::receiveMessage() is too small!"
<< std::endl;
socket->Status = Socket::MRS_StreamError;
return(MRRM_STREAM_ERROR);
}
if((socket->Protocol == IPPROTO_SCTP) && (!(*msgFlags & MSG_EOR))) {
std::cerr << "ERROR: TLV message end does not match with SCTP message end!"
<< std::endl;
socket->Status = Socket::MRS_StreamError;
return(MRRM_STREAM_ERROR);
}
received = socket->MessageSize;
memcpy(buffer, socket->MessageBuffer, socket->MessageSize);
socket->Status = Socket::MRS_WaitingForHeader;
socket->MessageSize = 0;
socket->BytesRead = 0;
return(received);
}
return(MRRM_BAD_SOCKET);
}
// ====== Handle read errors ==========================================
else if(received < 0) {
return(MRRM_SOCKET_ERROR);
}
else { // received == 0
return(received);
}
}
else {
std::cerr << "ERROR: Unknown socket " << sd
<< " given in call of MessageReader::receiveMessage()!" << std::endl;
return(MRRM_BAD_SOCKET);
}
}
netperfmeter-1.2.3/src/thread.cc 0000664 0001750 0001750 00000004544 11761413565 013525 0000000 0000000 /* $Id: thread.cc 1140 2011-11-23 06:43:27Z dreibh $
*
* Network Performance Meter
* Copyright (C) 2009-2012 by Thomas Dreibholz
*
* 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 3 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, see .
*
* Contact: dreibh@iem.uni-due.de
*/
#include
#include
#include
#include
#include "thread.h"
// ###### Constructor #######################################################
Thread::Thread()
{
MyThread = 0;
lock();
Stopping = false;
unlock();
}
// ###### Destructor ########################################################
Thread::~Thread()
{
if(MyThread != 0) {
waitForFinish();
}
}
// ###### Start routine to lauch thread's run() function ####################
void* Thread::startRoutine(void* object)
{
Thread* thread = (Thread*)object;
thread->run();
return(NULL);
}
// ###### Start thread ######################################################
bool Thread::start()
{
if(MyThread == 0) {
lock();
Stopping = false;
unlock();
if(pthread_create(&MyThread, NULL, startRoutine, (void*)this) == 0) {
return(true);
}
MyThread = 0;
std::cerr << "ERROR: Unable to start new thread!" << std::endl;
}
else {
std::cerr << "ERROR: Thread already running!" << std::endl;
}
return(false);
}
// ###### Stop thread #######################################################
void Thread::stop()
{
lock();
Stopping = true;
unlock();
}
// ###### Wait until thread has been finished ###############################
void Thread::waitForFinish()
{
if(MyThread != 0) {
pthread_join(MyThread, NULL);
MyThread = 0;
}
}
// ###### Wait a given amount of microseconds ###############################
void Thread::delay(const unsigned int us)
{
usleep(us);
}
netperfmeter-1.2.3/src/messagereader.h 0000664 0001750 0001750 00000005363 11774302044 014720 0000000 0000000 /* $Id: messagereader.h 1431 2012-07-02 11:21:07Z dreibh $
*
* Network Performance Meter
* Copyright (C) 2009-2012 by Thomas Dreibholz
*
* 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 3 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, see .
*
* Contact: dreibh@iem.uni-due.de
*/
#ifndef MESSAGEREADER_H
#define MESSAGEREADER_H
#include
#include
#include
#include