directories utils->lib and tools->tool renamed; ebusd_send changed to fit with all commands.

This commit is contained in:
Roland Jax
2014-06-03 14:37:18 +02:00
parent 8e9169afd4
commit 6b304334f3
17 changed files with 18 additions and 21 deletions
+217
View File
@@ -0,0 +1,217 @@
/*
* Copyright (C) Roland Jax 2012-2014 <roland.jax@liwest.at>
*
* This file is part of ebusd.
*
* ebusd 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.
*
* ebusd 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 ebusd. If not, see http://www.gnu.org/licenses/.
*/
#include "appl.h"
#include <iostream>
#include <iomanip>
#include <cstdlib>
Appl& Appl::Instance()
{
static Appl instance;
return instance;
}
Appl::~Appl()
{
m_args.clear();
m_params.clear();
}
void Appl::addArgs(const std::string argTxt, const int argNum)
{
m_argTxt = argTxt;
m_argNum = argNum;
}
void Appl::addItem(const char* name, Param param, const char* shortname,
const char* longname, const char* description,
Datatype datatype, Optiontype optiontype)
{
if (strlen(name) != 0)
m_params[name] = param;
if (strlen(longname) != 0) {
Arg arg;
arg.name = name;
arg.shortname = shortname;
arg.longname = longname;
arg.description = description;
arg.datatype = datatype;
arg.optiontype = optiontype;
m_args.push_back(arg);
}
}
void Appl::printArgs()
{
std::cerr << std::endl << "Usage:" << std::endl << " "
<< m_argv[0].substr(2) << " [OPTIONS...]" ;
if (m_argTxt.size() != 0)
std::cerr << " " << m_argTxt;
std::cerr << std::endl << std::endl;
for (a_it = m_args.begin(); a_it < m_args.end(); a_it++) {
const char* c = (strlen(a_it->shortname) == 1) ? a_it->shortname : " ";
std::cerr << ((strcmp(c, " ") == 0) ? " " : "-") << c
<< " | --" << a_it->longname
<< "\t" << a_it->description
<< std::endl;
}
std::cerr << std::endl;
}
bool Appl::parseArgs(int argc, char* argv[])
{
std::vector<std::string> _argv(argv, argv + argc);
m_argc = argc;
m_argv = _argv;
for (int i = 1; i < m_argc; i++) {
// find option with long format '--'
if (m_argv[i].rfind("--") == 0 && m_argv[i].size() > 2) {
// is next item an added argument?
if (i+1 < m_argc && m_argv[i+1].rfind("-", 0) == std::string::npos) {
if (checkArg(m_argv[i].substr(2), m_argv[i+1]) == false)
return false;
} else {
if (checkArg(m_argv[i].substr(2), "") == false)
return false;
}
// find option with short format '-'
} else if (m_argv[i].rfind("-") == 0 && m_argv[i].size() > 1) {
// walk through all characters
for (size_t j = 1; j < m_argv[i].size(); j++) {
// only last charater could have an argument
if (i+1 < m_argc && m_argv[i+1].rfind("-", 0) == std::string::npos
&& j+1 == m_argv[i].size()) {
if (checkArg(m_argv[i].substr(j,1), m_argv[i+1]) == false)
return false;
} else {
if (checkArg(m_argv[i].substr(j,1), "") == false)
return false;
}
}
}
}
// check args
if (m_argNum > 0) {
if (m_argc < (m_argNum + 1))
return false;
for (int i = 1; i < m_argc; i++) {
if (m_argv[i].rfind("-", 0) != std::string::npos) {
i++;
continue;
}
m_argValues.push_back(m_argv[i]);
}
}
return true;
}
void Appl::printSettings()
{
std::cerr << std::endl << "Settings:" << std::endl;
for (a_it = m_args.begin(); a_it < m_args.end(); a_it++) {
const char* c = (strlen(a_it->shortname) == 1) ? a_it->shortname : " ";
std::cerr << ((strcmp(c, " ") == 0) ? " " : "-") << c
<< " | --" << a_it->longname
<< " = ";
if (a_it->datatype == type_bool) {
if (getParam<bool>(a_it->name) == true)
std::cerr << "yes" << std::endl;
else
std::cerr << "no" << std::endl;
}
else if (a_it->datatype == type_int) {
std::cerr << getParam<int>(a_it->name) << std::endl;
}
else if (a_it->datatype == type_long) {
std::cerr << getParam<long>(a_it->name) << std::endl;
}
else if (a_it->datatype == type_float) {
std::cerr << getParam<float>(a_it->name) << std::endl;
}
else if (a_it->datatype == type_string) {
std::cerr << getParam<const char*>(a_it->name) << std::endl;
}
}
std::cerr << std::endl;
}
bool Appl::checkArg(const std::string& name, const std::string& arg)
{
for (a_it = m_args.begin(); a_it < m_args.end(); a_it++) {
if (a_it->shortname == name || a_it->longname == name) {
if (a_it->optiontype == opt_mandatory && arg.size() == 0) {
std::cerr << std::endl << "option requires an argument '"
<< name << "'" << std::endl;
return false;
}
if ((a_it->optiontype == opt_optional && arg.size() != 0)
|| a_it->optiontype != opt_optional)
addParam(a_it->name, arg, a_it->datatype);
return true;
}
}
std::cerr << m_argv[0].substr(2) << ": Unknown Option -- " << name << std::endl;
return false;
}
void Appl::addParam(const char* name, const std::string arg, Datatype datatype)
{
switch (datatype) {
case type_bool:
m_params[name] = true;
break;
case type_int:
m_params[name] = strtol(arg.c_str(), NULL, 10);
break;
case type_long:
m_params[name] = strtol(arg.c_str(), NULL, 10);
break;
case type_float:
m_params[name] = static_cast<float>(strtod(arg.c_str(), NULL));
break;
case type_string:
m_params[name] = arg.c_str();
break;
default:
break;
}
}
+112
View File
@@ -0,0 +1,112 @@
/*
* Copyright (C) Roland Jax 2012-2014 <roland.jax@liwest.at>
*
* This file is part of ebusd.
*
* ebusd 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.
*
* ebusd 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 ebusd. If not, see http://www.gnu.org/licenses/.
*/
#ifndef APPL_H_
#define APPL_H_
#include <string>
#include <cstring>
#include <map>
#include <vector>
class Appl
{
private:
struct Option;
public:
enum Datatype { type_none, type_bool, type_int, type_long, type_float, type_string };
enum Optiontype { opt_none, opt_optional, opt_mandatory };
union Param {
bool b;
int i;
long l;
float f;
const char* c;
Param() { memset(this, 0, sizeof(Param)); }
Param(bool _b) : b(_b) {}
Param(int _i) : i(_i) {}
Param(long _l) : l(_l) {}
Param(float _f) : f(_f) {}
Param(const char* _c) : c(_c) {}
};
template <typename T>
T getParam(const char* name)
{
p_it = m_params.find(name);
return (reinterpret_cast<T&>(p_it->second));
}
static Appl& Instance();
~Appl();
void addArgs(const std::string argTxt, const int argNum);
size_t numArg() const { return m_argValues.size(); }
std::string getArg(const int argNum) const { return m_argValues[argNum]; }
void addItem(const char* name, Param param, const char* shortname,
const char* longname, const char* description,
Datatype datatype, Optiontype optiontype);
void printArgs();
bool parseArgs(int argc, char* argv[]);
void printSettings();
private:
Appl() {}
Appl(const Appl&);
Appl& operator= (const Appl&);
struct Arg {
const char* name;
const char* shortname;
const char* longname;
const char* description;
Datatype datatype;
Optiontype optiontype;
};
int m_argc;
std::vector<std::string> m_argv;
std::vector<Arg> m_args;
std::vector<Arg>::const_iterator a_it;
std::map<const char*, Param> m_params;
std::map<const char*, Param>::iterator p_it;
std::string m_argTxt;
int m_argNum;
std::vector<std::string> m_argValues;
bool checkArg(const std::string& name, const std::string& arg);
void addParam(const char* name, Param param) { m_params[name] = param; }
void addParam(const char* name, const std::string arg, Datatype datatype);
};
#endif // APPL_H_
+117
View File
@@ -0,0 +1,117 @@
/*
* Copyright (C) Roland Jax 2012-2014 <roland.jax@liwest.at>
*
* This file is part of ebusd.
*
* ebusd 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.
*
* ebusd 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 ebusd. If not, see http://www.gnu.org/licenses/.
*/
#include "daemon.h"
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
Daemon& Daemon::Instance()
{
static Daemon instance;
return instance;
}
void Daemon::run(const char* file)
{
m_status = false;
m_pidfile = file;
m_pidfd = 0;
pid_t pid;
// fork off the parent process
pid = fork();
if (pid < 0) {
std::cerr << "daemon fork() failed." << std::endl;
exit(EXIT_FAILURE);
}
// If we got a good PID, then we can exit the parent process
if (pid > 0) {
// printf("Child process created: %d\n", pid);
exit(EXIT_SUCCESS);
}
// At this point we are executing as the child process
// Set file permissions 750
umask(027);
// Create a new SID for the child process and
// detach the process from the parent (normally a shell)
if (setsid() < 0) {
std::cerr << "daemon setsid() failed." << std::endl;
exit(EXIT_FAILURE);
}
// Change the current working directory. This prevents the current
// directory from being locked; hence not being able to remove it.
if (chdir("/tmp") < 0) { //DAEMON_WORKDIR
std::cerr << "daemon chdir() failed." << std::endl;
exit(EXIT_FAILURE);
}
// Close stdin, stdout and stderr
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
// write pidfile and try to lock it
if (pidfile_open() == false) {
std::cerr << "can't open pidfile: %s" << m_pidfile << std::endl;
exit(EXIT_FAILURE);
}
m_status = true;
}
bool Daemon::pidfile_open()
{
char pid[10];
m_pidfd = open(m_pidfile, O_RDWR|O_CREAT, 0600);
if (m_pidfd < 0)
return false;
if (lockf(m_pidfd, F_TLOCK, 0) < 0)
return false;
sprintf(pid, "%d\n", getpid());
if (write(m_pidfd, pid, strlen(pid)) < 0)
return false;
return true;
}
bool Daemon::pidfile_close()
{
if (close(m_pidfd) < 0)
return false;
if (remove(m_pidfile) < 0)
return false;
return true;
}
+48
View File
@@ -0,0 +1,48 @@
/*
* Copyright (C) Roland Jax 2012-2014 <roland.jax@liwest.at>
*
* This file is part of ebusd.
*
* ebusd 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.
*
* ebusd 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 ebusd. If not, see http://www.gnu.org/licenses/.
*/
#ifndef DAEMON_H_
#define DAEMON_H_
class Daemon
{
public:
static Daemon& Instance();
~Daemon() {}
void run(const char* file);
void stop() { pidfile_close(); }
bool status() { return m_status; }
private:
bool m_status;
const char* m_pidfile;
int m_pidfd;
Daemon() {}
Daemon(const Daemon&);
Daemon& operator= (const Daemon&);
bool pidfile_open();
bool pidfile_close();
};
#endif // DAEMON_H_
+237
View File
@@ -0,0 +1,237 @@
/*
* Copyright (C) Roland Jax 2012-2014 <roland.jax@liwest.at>
*
* This file is part of ebusd.
*
* ebusd 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.
*
* ebusd 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 ebusd. If not, see http://www.gnu.org/licenses/.
*/
#include "logger.h"
#include <iostream>
#include <sstream>
#include <fstream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <ctime>
#include <sys/time.h>
#include <unistd.h>
static const char* AreaNames[Size_of_Area] = { "bas", "net", "bus", "cyc" };
static const char* LevelNames[Size_of_Level] = { "error", "event", "trace", "debug" };
int calcArea(const std::string area)
{
int m_area = 0;
// prepare data
std::string token;
std::istringstream stream(area);
std::vector<std::string> cmd;
while (std::getline(stream, token, ',') != 0)
cmd.push_back(token);
for (std::vector<std::string>::iterator it = cmd.begin() ; it != cmd.end(); ++it)
for (int i = 0; i < Size_of_Area; i++) {
if (strcasecmp("all", it->c_str()) == 0)
return (pow(2, (int)Size_of_Area) - 1);
if (strcasecmp(AreaNames[i], it->c_str()) == 0)
m_area += pow(2, i);
}
return m_area;
}
int calcLevel(const std::string level)
{
int m_level = event;
for (int i = 0; i < Size_of_Level; i++)
if (strcasecmp(LevelNames[i], level.c_str()) == 0)
return i;
return m_level;
}
LogMessage::LogMessage(const int area, const int level, const std::string text, const Status status)
: m_area(area), m_level(level), m_text(text), m_status(status)
{
char time[24];
struct timeval tv;
struct timezone tz;
struct tm* tm;
gettimeofday(&tv, &tz);
tm = localtime(&tv.tv_sec);
sprintf(&time[0], "%04d-%02d-%02d %02d:%02d:%02d.%03ld",
tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec, tv.tv_usec/1000);
m_time = std::string(time);
}
void LogSink::addMessage(const LogMessage& message)
{
LogMessage* tmp = new LogMessage(LogMessage(message));
m_queue.add((tmp));
}
void* LogSink::run()
{
while (1) {
LogMessage* message = m_queue.remove();
if (message->getStatus() == LogMessage::End) {
delete message;
while (m_queue.size() == true) {
LogMessage* message = m_queue.remove();
write(*message);
delete message;
}
return NULL;
}
write(*message);
delete message;
}
return NULL;
}
int LogConsole::m_numInstance = 0;
void LogConsole::write(const LogMessage& message) const
{
std::cout << message.getTime() << " ["
<< AreaNames[(int)log2(message.getArea())] << " "
<< LevelNames[message.getLevel()] << "] "
<< message.getText() << std::endl;
}
int LogFile::m_numInstance = 0;
void LogFile::write(const LogMessage& message) const
{
std::fstream file(m_filename.c_str(), std::ios::out | std::ios::app);
if (file.is_open() == true) {
file << message.getTime() << " ["
<< AreaNames[(int)log2(message.getArea())] << " "
<< LevelNames[message.getLevel()] << "] "
<< message.getText() << std::endl;
file.close();
}
}
LogInstance& LogInstance::Instance()
{
static LogInstance instance;
return (instance);
}
LogInstance::~LogInstance()
{
while (m_sinks.empty() == false)
*this -= *(m_sinks.begin());
}
LogInstance& LogInstance::operator+= (LogSink* sink)
{
sinkCI_t itEnd = m_sinks.end();
sinkCI_t it = std::find(m_sinks.begin(), itEnd, sink);
if (it == itEnd)
m_sinks.push_back(sink);
return (*this);
}
LogInstance& LogInstance::operator-= (const LogSink* sink)
{
sinkCI_t itEnd = m_sinks.end();
sinkCI_t it = std::find(m_sinks.begin(), itEnd, sink);
if (it == itEnd)
return (*this);
m_sinks.erase(it);
delete (sink);
return (*this);
}
void LogInstance::log(const int area, const int level, const std::string& data, ...)
{
if (m_running == true) {
char* tmp;
va_list ap;
va_start(ap, data);
if (vasprintf(&tmp, data.c_str(), ap) != -1) {
std::string buffer(tmp);
m_messages.add(new LogMessage(LogMessage(area, level, buffer, LogMessage::Run)));
}
va_end(ap);
free(tmp);
}
}
void* LogInstance::run()
{
m_running = true;
while (m_running == true) {
LogMessage* message = m_messages.remove();
sinkCI_t iter = m_sinks.begin();
for (; iter != m_sinks.end(); ++iter) {
if (*iter != 0) {
if (((*iter)->getAreas() & message->getArea()
&& (*iter)->getLevel() >= message->getLevel())
&& message->getStatus() == LogMessage::Run) {
(*iter)->addMessage(*message);
} else if (message->getStatus() == LogMessage::End) {
(*iter)->addMessage(*message);
m_running = false;
}
}
}
delete message;
}
return NULL;
}
void LogInstance::stop()
{
m_messages.add(new LogMessage(LogMessage(bas, error, "", LogMessage::End)));
// TODO: Improve this method
usleep(100000);
}
+181
View File
@@ -0,0 +1,181 @@
/*
* Copyright (C) Roland Jax 2012-2014 <roland.jax@liwest.at>
*
* This file is part of ebusd.
*
* ebusd 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.
*
* ebusd 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 ebusd. If not, see http://www.gnu.org/licenses/.
*/
#ifndef LOGGER_H_
#define LOGGER_H_
#include "wqueue.h"
#include "thread.h"
#include <string>
#include <functional>
#include <algorithm>
#include <vector>
#include <cstdarg>
enum Area { bas=1, net=2, bus=4, cyc=8, all=15, Size_of_Area=4 };
enum Level { error=0, event, trace, debug, Size_of_Level };
int calcArea(const std::string area);
int calcLevel(const std::string level);
class LogMessage
{
public:
enum Status { Run, End };
LogMessage(const int area, const int level, const std::string text, const Status status);
~LogMessage() {}
LogMessage(const LogMessage& src)
: m_area(src.m_area), m_level(src.m_level), m_text(src.m_text),
m_status(src.m_status), m_time(src.m_time) {}
void operator= (const LogMessage& src)
{ m_area = src.m_area; m_level = src.m_level; m_text = src.m_text;
m_status = src.m_status; m_time = src.m_time; }
int getArea() const { return (m_area); }
int getLevel() const { return(m_level); }
std::string getText() const { return (m_text.c_str()); }
Status getStatus() const { return (m_status); }
std::string getTime() const { return (m_time.c_str()); }
private:
int m_area;
int m_level;
std::string m_text;
Status m_status;
std::string m_time;
};
enum Type { Console, Logfile };
class LogSink : public Thread
{
public:
LogSink(const int areas, const int level, const Type type, const char* name)
: m_areas(areas), m_level(level), m_type(type), m_name(name) {}
virtual ~LogSink() {}
void addMessage(const LogMessage& message);
void* run();
int getAreas() const { return (m_areas); }
void setAreas(const int& areas) { m_areas = areas; }
int getLevel() const { return (m_level); }
void setLevel(const int& level) { m_level = level; }
Type getType() const { return (m_type); }
const char* getName() const { return (m_name.c_str()); }
protected:
WQueue<LogMessage*> m_queue;
private:
int m_areas;
int m_level;
Type m_type;
std::string m_name;
virtual void write(const LogMessage& message) const = 0;
};
class LogConsole : public LogSink
{
public:
LogConsole(const int areas, const int level, const char* name)
: LogSink(areas, level, Console, name), m_instance(++m_numInstance)
{ this->start(name); }
~LogConsole() {}
private:
const int m_instance;
static int m_numInstance;
void write(const LogMessage& message) const;
};
class LogFile : public LogSink
{
public:
LogFile(const int areas, const int level, const char* name, const char* filename)
: LogSink(areas, level, Logfile, name), m_filename(filename), m_instance(++m_numInstance)
{ this->start(name); }
~LogFile() {}
private:
std::string m_filename;
const int m_instance;
static int m_numInstance;
void write(const LogMessage& message) const;
};
class LogInstance : public Thread
{
public:
static LogInstance& Instance();
~LogInstance();
LogInstance& operator+= (LogSink* sink);
LogInstance& operator-= (const LogSink* sink);
void log(const int area, const int level, const std::string& text, ...);
int getNumberOfSinks() const { return(m_sinks.size()); }
LogSink* getSink(const int Index) const { return(m_sinks[Index]); }
void* run();
void stop();
private:
LogInstance() {}
LogInstance(const LogInstance&);
LogInstance& operator= (const LogInstance&);
typedef std::vector<LogSink*> sink_t;
typedef std::vector<LogSink*>::iterator sinkCI_t;
sink_t m_sinks;
WQueue<LogMessage*> m_messages;
bool m_running;
};
#endif // LOGGER_H_
+56
View File
@@ -0,0 +1,56 @@
/*
* Copyright (C) Roland Jax 2012-2014 <roland.jax@liwest.at>
*
* This file is part of ebusd.
*
* ebusd 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.
*
* ebusd 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 ebusd. If not, see http://www.gnu.org/licenses/.
*/
#ifndef NOTIFY_H_
#define NOTIFY_H_
#include <unistd.h>
#include <fcntl.h>
class Notify
{
public:
Notify()
{
int pipefd[2];
int ret = pipe(pipefd);
if (ret == 0) {
m_recvfd = pipefd[0];
m_sendfd = pipefd[1];
fcntl(m_sendfd, F_SETFL, O_NONBLOCK);
}
}
virtual ~Notify() { close(m_sendfd); close(m_recvfd); }
int notifyFD() const { return m_recvfd; }
int notify() const { return write(m_sendfd,"1",1); }
private:
int m_recvfd;
int m_sendfd;
};
#endif // NOTIFY_H_
+133
View File
@@ -0,0 +1,133 @@
/*
* Copyright (C) Roland Jax 2012-2014 <roland.jax@liwest.at>
*
* This file is part of ebusd.
*
* ebusd 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.
*
* ebusd 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 ebusd. If not, see http://www.gnu.org/licenses/.
*/
#include "tcpsocket.h"
#include <cstdlib>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <string.h>
TCPSocket::TCPSocket(int sfd, struct sockaddr_in* address) : m_sfd(sfd)
{
char ip[17];
inet_ntop(AF_INET, (struct in_addr*)&(address->sin_addr.s_addr), ip, sizeof(ip)-1);
m_ip = ip;
m_port = ntohs(address->sin_port);
}
bool TCPSocket::isValid()
{
if (fcntl(m_sfd, F_GETFL) == -1)
return false;
else
return true;
}
TCPSocket* TCPClient::connect(const std::string& server, const int& port)
{
struct sockaddr_in address;
int ret;
memset((char*) &address, 0, sizeof(address));
if (inet_addr(server.c_str()) == INADDR_NONE) {
struct hostent* he;
he = gethostbyname(server.c_str());
if (he == NULL)
return NULL;
memcpy(&address.sin_addr, he->h_addr_list[0], he->h_length);
} else {
ret = inet_aton(server.c_str(), &address.sin_addr);
if (ret == 0)
return NULL;
}
address.sin_family = AF_INET;
address.sin_port = htons(port);
int sfd = socket(AF_INET, SOCK_STREAM, 0);
if (sfd < 0)
return NULL;
ret = ::connect(sfd, (struct sockaddr*) &address, sizeof(address));
if (ret < 0)
return NULL;
return new TCPSocket(sfd, &address);
}
int TCPServer::start()
{
if (m_listening == true)
return 0;
m_lfd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in address;
memset(&address, 0, sizeof(address));
address.sin_family = AF_INET;
address.sin_port = htons(m_port);
if (m_address.size() > 0)
inet_pton(AF_INET, m_address.c_str(), &(address.sin_addr));
else
address.sin_addr.s_addr = INADDR_ANY;
int optval = 1;
setsockopt(m_lfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
int result = bind(m_lfd, (struct sockaddr*) &address, sizeof(address));
if (result != 0)
return result;
result = listen(m_lfd, 5);
if (result != 0)
return result;
m_listening = true;
return result;
}
TCPSocket* TCPServer::newSocket()
{
if (m_listening == false)
return NULL;
struct sockaddr_in address;
socklen_t len = sizeof(address);
memset(&address, 0, sizeof(address));
int sfd = accept(m_lfd, (struct sockaddr*) &address, &len);
if (sfd < 0)
return NULL;
return new TCPSocket(sfd, &address);
}
+88
View File
@@ -0,0 +1,88 @@
/*
* Copyright (C) Roland Jax 2012-2014 <roland.jax@liwest.at>
*
* This file is part of ebusd.
*
* ebusd 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.
*
* ebusd 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 ebusd. If not, see http://www.gnu.org/licenses/.
*/
#ifndef TCPSOCKET_H_
#define TCPSOCKET_H_
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string>
class TCPSocket
{
public:
friend class TCPClient;
friend class TCPServer;
~TCPSocket() { close(m_sfd); }
ssize_t recv(char* buffer, size_t len) { return read(m_sfd, buffer, len); }
ssize_t send(const char* buffer, size_t len) { return write(m_sfd, buffer, len); }
int getPort() const { return m_port; }
std::string getIP() const { return m_ip; }
int getFD() const { return m_sfd; }
bool isValid();
private:
int m_sfd;
int m_port;
std::string m_ip;
TCPSocket(int sfd, struct sockaddr_in* address);
};
class TCPClient
{
public:
TCPSocket* connect(const std::string& server, const int& port);
private:
};
class TCPServer
{
public:
TCPServer(const int port, const std::string address)
: m_lfd(0), m_port(port), m_address(address), m_listening(false) {}
~TCPServer() { if (m_lfd > 0) {close(m_lfd);} }
int start();
TCPSocket* newSocket();
int getFD() const { return m_lfd; }
private:
int m_lfd;
int m_port;
std::string m_address;
bool m_listening;
};
#endif // TCPSOCKET_H_
+78
View File
@@ -0,0 +1,78 @@
/*
* Copyright (C) Roland Jax 2012-2014 <roland.jax@liwest.at>
*
* This file is part of ebusd.
*
* ebusd 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.
*
* ebusd 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 ebusd. If not, see http://www.gnu.org/licenses/.
*/
#include "thread.h"
static void* runThread(void* arg)
{
return ((Thread *)arg)->run();
}
Thread::~Thread()
{
if (m_running == true && m_detached == false)
pthread_detach(m_threadid);
if (m_running == true)
pthread_cancel(m_threadid);
}
int Thread::start(const char* name)
{
int result = pthread_create(&m_threadid, NULL, runThread, this);
if (result == 0) {
pthread_setname_np(m_threadid, name);
m_running = true;
}
return result;
}
int Thread::join()
{
int result = -1;
if (m_running == true) {
result = pthread_join(m_threadid, NULL);
if (result == 0)
m_detached = false;
}
return result;
}
int Thread::detach()
{
int result = -1;
if (m_running == true && m_detached == false) {
result = pthread_detach(m_threadid);
if (result == 0)
m_detached = true;
}
return result;
}
+46
View File
@@ -0,0 +1,46 @@
/*
* Copyright (C) Roland Jax 2012-2014 <roland.jax@liwest.at>
*
* This file is part of ebusd.
*
* ebusd 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.
*
* ebusd 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 ebusd. If not, see http://www.gnu.org/licenses/.
*/
#ifndef THREAD_H_
#define THREAD_H_
#include <pthread.h>
class Thread
{
public:
Thread() : m_threadid(0), m_running(false), m_detached(false) {}
virtual ~Thread();
int start(const char* name);
int join();
int detach();
pthread_t self() {return m_threadid; }
virtual void* run() = 0;
private:
pthread_t m_threadid;
bool m_running;
bool m_detached;
};
#endif // THREAD_H_
+85
View File
@@ -0,0 +1,85 @@
/*
* Copyright (C) Roland Jax 2012-2014 <roland.jax@liwest.at>
*
* This file is part of ebusd.
*
* ebusd 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.
*
* ebusd 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 ebusd. If not, see http://www.gnu.org/licenses/.
*/
#ifndef WQUEUE_H_
#define WQUEUE_H_
#include <pthread.h>
#include <list>
template <typename T> class WQueue
{
public:
WQueue()
{
pthread_mutex_init(&m_mutex, NULL);
pthread_cond_init(&m_condv, NULL);
}
~WQueue()
{
pthread_mutex_destroy(&m_mutex);
pthread_cond_destroy(&m_condv);
}
void add(T item)
{
pthread_mutex_lock(&m_mutex);
m_queue.push_back(item);
pthread_cond_signal(&m_condv);
pthread_mutex_unlock(&m_mutex);
}
T remove()
{
pthread_mutex_lock(&m_mutex);
while (m_queue.size() == 0)
pthread_cond_wait(&m_condv, &m_mutex);
T item = m_queue.front();
m_queue.pop_front();
pthread_mutex_unlock(&m_mutex);
return item;
}
int size()
{
pthread_mutex_lock(&m_mutex);
int size = m_queue.size();
pthread_mutex_unlock(&m_mutex);
return size;
}
private:
std::list<T> m_queue;
pthread_mutex_t m_mutex;
pthread_cond_t m_condv;
};
#endif // WQUEUE_H_