summaryrefslogtreecommitdiff
path: root/bouncer
diff options
context:
space:
mode:
authorTreeki <treeki@gmail.com>2014-01-28 00:08:33 +0100
committerTreeki <treeki@gmail.com>2014-01-28 00:08:33 +0100
commitb95ed984f8bd2fe413d53d4b8677fe3d04bc1ad9 (patch)
tree5da2f4d891215fb709f7165644fd4a0c92f1aefd /bouncer
parent277c08cbc35f4cb2b72f1b00ab3e5f8efd2f8fb2 (diff)
downloadbounce4-b95ed984f8bd2fe413d53d4b8677fe3d04bc1ad9.tar.gz
bounce4-b95ed984f8bd2fe413d53d4b8677fe3d04bc1ad9.zip
implement server configuration loading/saving
Diffstat (limited to 'bouncer')
-rwxr-xr-xbouncer/build.sh2
-rwxr-xr-xbouncer/build_static.sh2
-rw-r--r--bouncer/core.h11
-rw-r--r--bouncer/ini.cpp110
-rw-r--r--bouncer/ini.h18
-rw-r--r--bouncer/ircserver.cpp28
-rw-r--r--bouncer/main.cpp1
-rw-r--r--bouncer/mobileclient.cpp6
-rw-r--r--bouncer/netcore.cpp40
9 files changed, 216 insertions, 2 deletions
diff --git a/bouncer/build.sh b/bouncer/build.sh
index 935cae6..092cca1 100755
--- a/bouncer/build.sh
+++ b/bouncer/build.sh
@@ -2,7 +2,7 @@
mkdir -p binary
NETCODE="socketcommon.cpp client.cpp mobileclient.cpp server.cpp ircserver.cpp netcore.cpp"
-SOURCES="$NETCODE main.cpp window.cpp dns.cpp"
+SOURCES="$NETCODE main.cpp window.cpp dns.cpp ini.cpp"
FLAGS="-std=c++11 -DUSE_GNUTLS -lgnutls -pthread -g"
g++ -o binary/nb4 $FLAGS $SOURCES
diff --git a/bouncer/build_static.sh b/bouncer/build_static.sh
index 6ed9183..e75d469 100755
--- a/bouncer/build_static.sh
+++ b/bouncer/build_static.sh
@@ -2,7 +2,7 @@
mkdir -p binary
NETCODE="socketcommon.cpp client.cpp mobileclient.cpp server.cpp ircserver.cpp netcore.cpp"
-SOURCES="$NETCODE main.cpp window.cpp dns.cpp"
+SOURCES="$NETCODE main.cpp window.cpp dns.cpp ini.cpp"
FLAGS="-static -static-libgcc -static-libstdc++ -std=c++11 -pthread"
g++ -o binary/nb4_static $FLAGS $SOURCES
diff --git a/bouncer/core.h b/bouncer/core.h
index 8817b77..1a13a1d 100644
--- a/bouncer/core.h
+++ b/bouncer/core.h
@@ -284,6 +284,9 @@ public:
Server(NetCore *_netCore);
virtual ~Server();
+ virtual void loadFromConfig(std::map<std::string, std::string> &data) = 0;
+ virtual void saveToConfig(std::map<std::string, std::string> &data) = 0;
+
protected:
void connect(const char *hostname, int _port, bool _useTls);
@@ -361,6 +364,9 @@ private:
public:
// This probably *shouldn't* be public... ><
void deleteQuery(Query *query);
+
+ virtual void loadFromConfig(std::map<std::string, std::string> &data);
+ virtual void saveToConfig(std::map<std::string, std::string> &data);
};
@@ -389,8 +395,12 @@ public:
Client *findClientWithSessionKey(uint8_t *key) const;
private:
virtual Client *constructClient() = 0;
+ virtual Server *constructServer(const char *type) = 0;
public:
+ void loadConfig();
+ void saveConfig();
+
int registerServer(Server *server); // THIS FUNCTION WILL BE PROTECTED LATER
protected:
void deregisterServer(int id);
@@ -400,6 +410,7 @@ protected:
class Bouncer : public NetCore {
private:
virtual Client *constructClient();
+ virtual Server *constructServer(const char *type);
};
diff --git a/bouncer/ini.cpp b/bouncer/ini.cpp
new file mode 100644
index 0000000..49ca38c
--- /dev/null
+++ b/bouncer/ini.cpp
@@ -0,0 +1,110 @@
+#include "ini.h"
+#include <stdio.h>
+#include <string.h>
+
+
+std::list<INI::Section> INI::load(const char *path) {
+ std::list<Section> sections;
+
+ FILE *f = fopen(path, "r");
+ if (!f)
+ return sections;
+
+ Section *section = 0;
+
+ for (;;) {
+ char line[4096];
+ if (!fgets(line, sizeof(line), f))
+ break;
+
+ int length = strlen(line);
+
+ // Get rid of the newline
+ if ((length > 0) && (line[length - 1] == '\n')) {
+ line[length - 1] = 0;
+ --length;
+ }
+
+ // Ignore empty lines, comments
+ if (!length)
+ continue;
+ if (line[0] == ';')
+ continue;
+ if (line[0] == '#')
+ continue;
+
+ // New section?
+ if ((length > 2) && (line[0] == '[') && (line[length - 1] == ']')) {
+ line[length - 1] = 0;
+
+ sections.push_back(Section());
+ section = &sections.back();
+ section->title = &line[1];
+
+ } else if (section) {
+ // We can only add values to a section if we have one :p
+
+ char *eq = strchr(line, '=');
+ if (eq) {
+ *eq = 0;
+ char *value = eq + 1;
+
+ section->data[line] = value;
+ }
+ }
+ }
+
+ fclose(f);
+
+ return sections;
+}
+
+
+bool INI::save(const char *path, const std::list<INI::Section> &sections) {
+ FILE *f = fopen(path, "w");
+ if (!f)
+ return false;
+
+
+ for (auto &section : sections) {
+ fputc('[', f);
+ fputs(section.title.c_str(), f);
+ fputs("]\n\n", f);
+
+ for (auto &i : section.data) {
+ fputs(i.first.c_str(), f);
+ fputc('=', f);
+ fputs(i.second.c_str(), f);
+ fputc('\n', f);
+ }
+
+ fputc('\n', f);
+ }
+
+
+ fclose(f);
+
+ return true;
+}
+
+
+
+/*
+int main(int argc, char **argv) {
+ INI::Section a, b;
+
+ a.title = "boop";
+ a.data["a"] = "b";
+ a.data["c"] = "d";
+
+ b.title = "boop2";
+ b.data["a"] = "b";
+ b.data["c"] = "d";
+
+ std::list<INI::Section> sections = { a, b };
+ INI::save("tryme.ini", sections);
+
+ std::list<INI::Section> munged = INI::load("tryme.ini");
+ INI::save("tryme2.ini", munged);
+}
+*/
diff --git a/bouncer/ini.h b/bouncer/ini.h
new file mode 100644
index 0000000..72a0e29
--- /dev/null
+++ b/bouncer/ini.h
@@ -0,0 +1,18 @@
+#ifndef INI_H
+#define INI_H
+
+#include <string>
+#include <list>
+#include <map>
+
+namespace INI {
+ struct Section {
+ std::string title;
+ std::map<std::string, std::string> data;
+ };
+
+ std::list<Section> load(const char *path);
+ bool save(const char *path, const std::list<Section> &sections);
+}
+
+#endif /* INI_H */
diff --git a/bouncer/ircserver.cpp b/bouncer/ircserver.cpp
index 8279484..c058f5c 100644
--- a/bouncer/ircserver.cpp
+++ b/bouncer/ircserver.cpp
@@ -635,3 +635,31 @@ char IRCServer::getEffectivePrefixChar(uint32_t modes) const {
return 0;
}
+
+
+
+void IRCServer::loadFromConfig(std::map<std::string, std::string> &data) {
+ config.hostname = data["hostname"];
+ config.username = data["username"];
+ config.realname = data["realname"];
+ config.nickname = data["nickname"];
+ config.altNick = data["altnick"];
+ config.password = data["password"];
+ config.useTls = (data["tls"] == "y");
+ config.port = atoi(data["port"].c_str());
+}
+
+void IRCServer::saveToConfig(std::map<std::string, std::string> &data) {
+ data["type"] = "IRCServer";
+ data["hostname"] = config.hostname;
+ data["username"] = config.username;
+ data["realname"] = config.realname;
+ data["nickname"] = config.nickname;
+ data["altnick"] = config.altNick;
+ data["password"] = config.password;
+ data["tls"] = config.useTls ? "y" : "n";
+
+ char portstr[50];
+ snprintf(portstr, sizeof(portstr), "%d", config.port);
+ data["port"] = portstr;
+}
diff --git a/bouncer/main.cpp b/bouncer/main.cpp
index 5330310..6c248c8 100644
--- a/bouncer/main.cpp
+++ b/bouncer/main.cpp
@@ -50,6 +50,7 @@ int main(int argc, char **argv) {
DNS::start();
Bouncer bounce;
+ bounce.loadConfig();
int errcode = bounce.execute();
if (errcode < 0) {
diff --git a/bouncer/mobileclient.cpp b/bouncer/mobileclient.cpp
index 0dbc35a..fc1836d 100644
--- a/bouncer/mobileclient.cpp
+++ b/bouncer/mobileclient.cpp
@@ -70,6 +70,12 @@ void MobileClient::handleDebugCommand(char *line, int size) {
} else if (strcmp(line, "addsrv") == 0) {
IRCServer *srv = new IRCServer(bouncer);
bouncer->registerServer(srv);
+ } else if (strcmp(line, "save") == 0) {
+ bouncer->saveConfig();
+
+ Buffer pkt;
+ pkt.writeStr("Bouncer configuration saved.");
+ sendPacket(Packet::B2C_STATUS, pkt);
}
}
diff --git a/bouncer/netcore.cpp b/bouncer/netcore.cpp
index dee6ef7..0dd929f 100644
--- a/bouncer/netcore.cpp
+++ b/bouncer/netcore.cpp
@@ -1,4 +1,5 @@
#include "core.h"
+#include "ini.h"
NetCore::NetCore() {
@@ -321,10 +322,49 @@ void NetCore::sendToClients(Packet::Type type, const Buffer &data) {
+
+void NetCore::loadConfig() {
+ auto sections = INI::load("config.ini");
+
+ for (auto &section : sections) {
+ if (section.title == "Server" && serverCount < SERVER_LIMIT) {
+ Server *s = constructServer(section.data["type"].c_str());
+ if (s) {
+ s->loadFromConfig(section.data);
+ registerServer(s);
+ }
+ }
+ }
+}
+
+void NetCore::saveConfig() {
+ std::list<INI::Section> sections;
+
+ for (int i = 0; i < serverCount; i++) {
+ INI::Section section;
+ section.title = "Server";
+
+ servers[i]->saveToConfig(section.data);
+
+ sections.push_back(section);
+ }
+
+ INI::save("config.ini", sections);
+}
+
+
+
+
Client *Bouncer::constructClient() {
return new MobileClient(this);
}
+Server *Bouncer::constructServer(const char *type) {
+ if (strcmp(type, "IRCServer") == 0)
+ return new IRCServer(this);
+
+ return 0;
+}