Commit 19476b06 authored by Romain Bignon's avatar Romain Bignon

implemented the daemon fork mode

parent 000693f2
......@@ -11,6 +11,7 @@ ADD_EXECUTABLE(${BIN_NAME}
src/caca_image.cpp
src/server_poll/poll.cpp
src/server_poll/inetd.cpp
src/server_poll/daemon_fork.cpp
src/im/im.cpp
src/im/protocol.cpp
src/im/account.cpp
......
......@@ -12,14 +12,21 @@ irc {
#hostname = localhost.localdomain
# Standalone or run by inetd?
# note: currently, only the inetd works.
# Minbif mode.
#
# 0: inetd
# 1: daemon (isn't implemented yet)
# 2: daemon fork (isn't implemented yet)
# 2: daemon fork
type = 0
# With 'daemon' and 'daemon fork' modes, set some
# parameters to listen on network.
#daemon {
# bind = 0.0.0.0
#
# port = 6667
#}
# Ping interval in seconds.
ping = 60
}
......
/*
* Minbif - IRC instant messaging gateway
* Copyright(C) 2009 Romain Bignon
*
* This program is free software; you can redistribute it and/or modify
......@@ -18,28 +19,25 @@
#include "callback.h"
#include "log.h"
void g_callback_input(void* data, gint, PurpleInputCondition i)
static bool _callback(void* data)
{
_CallBack* cb = static_cast<_CallBack*>(data);
if(!data)
_CallBack* cb;
if(!data || !(cb = static_cast<_CallBack*>(data)))
{
b_log[W_ERR] << "g_callback() handled with non CallBack instance";
return;
return false;
}
cb->run();
return cb->run();
}
gboolean g_callback(void* data)
{
_CallBack* cb = static_cast<_CallBack*>(data);
if(!data)
{
b_log[W_ERR] << "g_callback() handled with non CallBack instance";
return FALSE;
}
void g_callback_input(void* data, gint, PurpleInputCondition i)
{
_callback(data);
}
return cb->run();
gboolean g_callback(void* data)
{
return _callback(data);
}
......@@ -418,7 +418,7 @@ bool IRC::readIO(void*)
string sbuf, line;
ssize_t r;
if((r = read( 0, buf, sizeof buf - 1 )) <= 0)
if((r = read(fd, buf, sizeof buf - 1 )) <= 0)
{
if(r == 0)
this->quit("Connection reset by peer...");
......
......@@ -72,7 +72,7 @@ Log::flux::~flux()
if(b_log.getServerPoll())
b_log.getServerPoll()->log(flag, category + str);
else
std::cout << ":localhost.localdomain NOTICE AUTH :" << category << " " << str << "\r\n";
std::cout << category << " " << str << "\r\n";
}
}
......
......@@ -17,10 +17,13 @@
*/
#include <stdlib.h>
#include <iostream>
#include <cstring>
#include <sys/resource.h>
#include <libpurple/purple.h>
#include "minbif.h"
#include "version.h"
#include "config.h"
#include "log.h"
#include "util.h"
......@@ -39,9 +42,14 @@ Minbif::Minbif()
section->AddItem(new ConfigItem_int("type", "Type of daemon", 0, 2, "0"));
section->AddItem(new ConfigItem_int("ping", "Ping frequence (s)", 0, 65535, "60"));
section = section->AddSection("daemon", "Daemon information", true);
section->AddItem(new ConfigItem_string("bind", "IP address to listen on"));
section->AddItem(new ConfigItem_int("port", "Port to listen on"), true);
section = conf.AddSection("logging", "Log information", false);
section->AddItem(new ConfigItem_string("level", "Logging level"));
section->AddItem(new ConfigItem_bool("to_syslog", "Log error and warnings to syslog"));
}
Minbif::~Minbif()
......@@ -53,10 +61,16 @@ int Minbif::main(int argc, char** argv)
{
if(argc < 2)
{
b_log << "Syntax: " << argv[0] << " config_file";
std::cerr << "Syntax: " << argv[0] << " config_file" << std::endl;
return EXIT_FAILURE;
}
if(!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version"))
{
std::cout << MINBIF_VERSION << " (Build " __DATE__ " " __TIME__ ") © 2009 Romain Bignon" << std::endl;
return EXIT_SUCCESS;
}
try
{
struct rlimit rlim;
......
/*
* Minbif - IRC instant messaging gateway
* Copyright(C) 2009 Romain Bignon
*
* 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, version 2 of the License.
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <iostream>
#include <cassert>
#include <cstring>
#include <cerrno>
#include <glib/gmain.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include "daemon_fork.h"
#include "../config.h"
#include "../irc/irc.h"
#include "../irc/user.h"
#include "../config.h"
#include "../callback.h"
#include "../log.h"
#include "../minbif.h"
#include "../util.h"
DaemonForkServerPoll::DaemonForkServerPoll(Minbif* application)
: ServerPoll(application),
irc(NULL),
read_cb(NULL),
stop_cb(NULL)
{
std::vector<ConfigSection*> sections = conf.GetSection("irc")->GetSectionClones("daemon");
if(sections.empty())
{
b_log[W_ERR] << "Missing section irc/daemon";
throw ServerPollError();
}
ConfigSection* section = sections[0];
const char* bind_addr = section->GetItem("bind")->String().c_str();
uint16_t port = (uint16_t)section->GetItem("port")->Integer();
static struct sockaddr_in fsocket;
fsocket.sin_family = AF_INET;
fsocket.sin_addr.s_addr = inet_addr(bind_addr);
fsocket.sin_port = htons(port);
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(sock < 0)
{
b_log[W_ERR] << "Unable to create a socket: " << strerror(errno);
throw ServerPollError();
}
unsigned int reuse_addr = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, sizeof reuse_addr);
if(bind(sock, (struct sockaddr *) &fsocket, sizeof fsocket) < 0 ||
listen(sock, 5) < 0)
{
b_log[W_ERR] << "Unable to listen on " << bind_addr << ":" << port
<< ": " << strerror(errno);
throw ServerPollError();
}
read_cb = new CallBack<DaemonForkServerPoll>(this, &DaemonForkServerPoll::new_client_cb);
read_id = glib_input_add(sock, (PurpleInputCondition)PURPLE_INPUT_READ,
g_callback_input, read_cb);
#if 0
try
{
irc = new irc::IRC(this, 0,
conf.GetSection("irc")->GetItem("hostname")->String(),
conf.GetSection("irc")->GetItem("ping")->Integer());
}
catch(irc::AuthError &e)
{
b_log[W_ERR] << "Unable to start the IRC daemon";
throw ServerPollError();
}
#endif
}
DaemonForkServerPoll::~DaemonForkServerPoll()
{
if(read_id >= 0)
g_source_remove(read_id);
delete read_cb;
delete irc;
}
bool DaemonForkServerPoll::new_client_cb(void*)
{
struct sockaddr_in newcon;
unsigned int addrlen = sizeof newcon;
int new_socket = accept(sock, (struct sockaddr *) &newcon, &addrlen);
pid_t client_pid = fork();
if(client_pid > 0)
{
/* Parent */
b_log[W_ERR] << "Creating new process with pid " << client_pid;
close(new_socket);
return true;
}
else
{
/* Child */
close(sock);
g_source_remove(read_id);
delete read_cb;
read_cb = NULL;
read_id = -1;
try
{
irc = new irc::IRC(this, new_socket,
conf.GetSection("irc")->GetItem("hostname")->String(),
conf.GetSection("irc")->GetItem("ping")->Integer());
}
catch(irc::AuthError &e)
{
b_log[W_ERR] << "Unable to start the IRC daemon";
getApplication()->quit();
}
}
return true;
}
void DaemonForkServerPoll::log(size_t level, string msg) const
{
if(msg.find("\n") != string::npos)
msg = msg.substr(0, msg.find("\n"));
string cmd = MSG_NOTICE;
if(level & W_DEBUG)
cmd = MSG_PRIVMSG;
if(irc)
irc->getUser()->send(irc::Message(cmd).setSender(irc)
.setReceiver(irc->getUser())
.addArg(msg));
else
std::cout << msg << std::endl;
}
void DaemonForkServerPoll::kill(irc::IRC* irc)
{
assert(irc == this->irc);
stop_cb = new CallBack<DaemonForkServerPoll>(this, &DaemonForkServerPoll::stopServer_cb);
g_timeout_add(0, g_callback, stop_cb);
}
bool DaemonForkServerPoll::stopServer_cb(void*)
{
delete stop_cb;
stop_cb = NULL;
delete irc;
irc = NULL;
getApplication()->quit();
return false;
}
/*
* Minbif - IRC instant messaging gateway
* Copyright(C) 2009 Romain Bignon
*
* 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, version 2 of the License.
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef SERVER_POLL_DAEMON_FORK_H
#define SERVER_POLL_DAEMON_FORK_H
#include <vector>
#include "poll.h"
namespace irc {
class IRC;
};
class _CallBack;
class DaemonForkServerPoll : public ServerPoll
{
irc::IRC* irc;
int sock;
int read_id;
_CallBack *read_cb;
_CallBack* stop_cb;
public:
DaemonForkServerPoll(Minbif* application);
~DaemonForkServerPoll();
bool new_client_cb(void*);
void kill(irc::IRC* irc);
bool stopServer_cb(void*);
void log(size_t level, string log) const;
};
#endif /* SERVER_POLL_DAEMON_FORK_H */
......@@ -18,6 +18,7 @@
#include "poll.h"
#include "inetd.h"
#include "daemon_fork.h"
#include "../log.h"
ServerPoll* ServerPoll::build(ServerPoll::poll_type_t type, Minbif* application)
......@@ -26,13 +27,14 @@ ServerPoll* ServerPoll::build(ServerPoll::poll_type_t type, Minbif* application)
{
case ServerPoll::INETD:
return new InetdServerPoll(application);
case ServerPoll::DAEMON:
case ServerPoll::DAEMON_FORK:
return new DaemonForkServerPoll(application);
case ServerPoll::DAEMON:
default:
b_log[W_ERR] << "Type " << type << " is not implemented yet.";
return 0;
}
return 0;
throw ServerPollError();
}
ServerPoll::ServerPoll(Minbif* _app)
......
/*
* Minbif - IRC instant messaging gateway
* Copyright(C) 2009 Romain Bignon
*
* This program is free software; you can redistribute it and/or modify
......
......@@ -22,10 +22,14 @@
#define MINBIF_VERSION_NAME "minbif"
#define MINBIF_VERSION_MAJOR "1"
#define MINBIF_VERSION_MINOR "0-alpha"
#define MINBIF_VERSION_MINOR "0"
#define MINBIF_VERSION_PATCH ""
#define MINBIF_VERSION_EXTRA "-git"
#define MINBIF_VERSION MINBIF_VERSION_NAME \
MINBIF_VERSION_MAJOR "." \
MINBIF_VERSION_MINOR
MINBIF_VERSION_MINOR \
MINBIF_VERSION_PATCH \
MINBIF_VERSION_EXTRA
#endif /* VERSION_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment