Implemented Util::Config::serveForkedSocket(), added Socket::Connection::drop() function for dropping unused sockets.

This commit is contained in:
Thulinma 2014-01-27 18:02:58 +01:00
parent 92b7a7534d
commit d81bc24155
4 changed files with 95 additions and 17 deletions

View file

@ -5,6 +5,7 @@
#include "defines.h"
#include "timing.h"
#include "tinythread.h"
#include "stream.h"
#include <string.h>
#include <signal.h>
@ -299,7 +300,7 @@ bool Util::Config::getBool(std::string optname){
struct callbackData{
Socket::Connection * sock;
void (*cb)(Socket::Connection &);
int (*cb)(Socket::Connection &);
};
static void callThreadCallback(void * cDataArg){
@ -312,8 +313,14 @@ static void callThreadCallback(void * cDataArg){
DEBUG_MSG(DLVL_INSANE, "Thread for %p ended", cDataArg);
}
int Util::Config::serveThreadedSocket(void (*callback)(Socket::Connection &)){
Socket::Server server_socket = Socket::Server(getInteger("listen_port"), getString("listen_interface"), false);
int Util::Config::serveThreadedSocket(int (*callback)(Socket::Connection &)){
Socket::Server server_socket;
if (vals.isMember("socket")){
server_socket = Socket::Server(Util::getTmpFolder() + getString("socket"));
}
if (vals.isMember("listen_port") && vals.isMember("listen_interface")){
server_socket = Socket::Server(getInteger("listen_port"), getString("listen_interface"), false);
}
if (!server_socket.connected()){return 1;}
DEBUG_MSG(DLVL_DEVEL, "Activating threaded server: %s", getString("cmd").c_str());
activate();
@ -337,6 +344,41 @@ int Util::Config::serveThreadedSocket(void (*callback)(Socket::Connection &)){
return 0;
}
int Util::Config::serveForkedSocket(int (*callback)(Socket::Connection & S)){
Socket::Server server_socket;
if (vals.isMember("socket")){
server_socket = Socket::Server(Util::getTmpFolder() + getString("socket"));
}
if (vals.isMember("listen_port") && vals.isMember("listen_interface")){
server_socket = Socket::Server(getInteger("listen_port"), getString("listen_interface"), false);
}
if (!server_socket.connected()){
DEBUG_MSG(DLVL_DEVEL, "Failure to open socket");
return 1;
}
DEBUG_MSG(DLVL_DEVEL, "Activating forked server: %s", getString("cmd").c_str());
activate();
while (is_active && server_socket.connected()){
Socket::Connection S = server_socket.accept();
if (S.connected()){ //check if the new connection is valid
pid_t myid = fork();
if (myid == 0){ //if new child, start MAINHANDLER
server_socket.drop();
return callback(S);
}else{ //otherwise, do nothing or output debugging text
DEBUG_MSG(DLVL_DEVEL, "Forked new process %i for socket %i", (int)myid, S.getSocket());
S.drop();
}
}else{
Util::sleep(10); //sleep 10ms
}
}//main loop
server_socket.close();
DEBUG_MSG(DLVL_DEVEL, "Forked server exiting: %s", getString("cmd").c_str());
return 0;
}
/// Activated the stored config. This will:
/// - Drop permissions to the stored "username", if any.
/// - Daemonize the process if "daemonize" exists and is true.
@ -426,6 +468,15 @@ void Util::Config::addBasicConnectorOptions(JSON::Value & capabilities){
capabilities["optional"]["username"]["option"] = "--username";
capabilities["optional"]["username"]["type"] = "str";
if (capabilities.isMember("socket")){
option.null();
option["arg"] = "string";
option["help"] = "Socket name that can be connected to for this connector.";
option["value"].append(capabilities["socket"]);
addOption("socket", option);
}
option.null();
option["long"] = "daemon";
option["short"] = "d";

View file

@ -33,9 +33,9 @@ namespace Util {
long long int getInteger(std::string optname);
bool getBool(std::string optname);
void activate();
int serveThreadedSocket(void (*callback)(Socket::Connection & S));
int serveForkedSocket(void (*callback)(Socket::Connection & S));
int servePlainSocket(void (*callback)(Socket::Connection & S));
int serveThreadedSocket(int (*callback)(Socket::Connection & S));
int serveForkedSocket(int (*callback)(Socket::Connection & S));
int servePlainSocket(int (*callback)(Socket::Connection & S));
void addBasicConnectorOptions(JSON::Value & capabilities);
void addConnectorOptions(int port, JSON::Value & capabilities);
};
@ -53,4 +53,3 @@ namespace Util {
void Daemonize();
}
;

View file

@ -238,11 +238,23 @@ bool Socket::Connection::isBlocking(){
/// Close connection. The internal socket is closed and then set to -1.
/// If the connection is already closed, nothing happens.
/// This function calls shutdown, thus making the socket unusable in all other
/// processes as well. Do not use on shared sockets that are still in use.
void Socket::Connection::close(){
if (connected()){
DEBUG_MSG(DLVL_HIGH, "Socket %d closed", sock);
if (sock != -1){
shutdown(sock, SHUT_RDWR);
}
drop();
} //Socket::Connection::close
/// Close connection. The internal socket is closed and then set to -1.
/// If the connection is already closed, nothing happens.
/// This function does *not* call shutdown, allowing continued use in other
/// processes.
void Socket::Connection::drop(){
if (connected()){
if (sock != -1){
DEBUG_MSG(DLVL_HIGH, "Socket %d closed", sock);
errno = EINTR;
while (::close(sock) != 0 && errno == EINTR){
}
@ -261,7 +273,7 @@ void Socket::Connection::close(){
pipes[1] = -1;
}
}
} //Socket::Connection::close
} //Socket::Connection::drop
/// Returns internal socket number.
int Socket::Connection::getSocket(){
@ -846,16 +858,30 @@ bool Socket::Server::isBlocking(){
/// Close connection. The internal socket is closed and then set to -1.
/// If the connection is already closed, nothing happens.
/// This function calls shutdown, thus making the socket unusable in all other
/// processes as well. Do not use on shared sockets that are still in use.
void Socket::Server::close(){
if (connected()){
DEBUG_MSG(DLVL_HIGH, "ServerSocket %d closed", sock);
if (sock != -1){
shutdown(sock, SHUT_RDWR);
}
drop();
} //Socket::Server::close
/// Close connection. The internal socket is closed and then set to -1.
/// If the connection is already closed, nothing happens.
/// This function does *not* call shutdown, allowing continued use in other
/// processes.
void Socket::Server::drop(){
if (connected()){
if (sock != -1){
DEBUG_MSG(DLVL_HIGH, "ServerSocket %d closed", sock);
errno = EINTR;
while (::close(sock) != 0 && errno == EINTR){
}
sock = -1;
}
} //Socket::Server::close
}
} //Socket::Server::drop
/// Returns the connected-state for this socket.
/// Note that this function might be slightly behind the real situation.

View file

@ -68,6 +68,7 @@ namespace Socket {
Connection(int write, int read); ///< Simulate a socket using two file descriptors.
//generic methods
void close(); ///< Close connection.
void drop(); ///< Close connection without shutdown.
void setBlocking(bool blocking); ///< Set this socket to be blocking (true) or nonblocking (false).
bool isBlocking(); ///< Check if this socket is blocking (true) or nonblocking (false).
std::string getHost(); ///< Gets hostname for connection, if available.
@ -114,6 +115,7 @@ namespace Socket {
bool connected() const; ///< Returns the connected-state for this socket.
bool isBlocking(); ///< Check if this socket is blocking (true) or nonblocking (false).
void close(); ///< Close connection.
void drop(); ///< Close connection without shutdown.
int getSocket(); ///< Returns internal socket number.
};