Implemented Util::Config::serveForkedSocket(), added Socket::Connection::drop() function for dropping unused sockets.
This commit is contained in:
parent
92b7a7534d
commit
d81bc24155
4 changed files with 95 additions and 17 deletions
|
@ -5,6 +5,7 @@
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
#include "timing.h"
|
#include "timing.h"
|
||||||
#include "tinythread.h"
|
#include "tinythread.h"
|
||||||
|
#include "stream.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
|
@ -299,7 +300,7 @@ bool Util::Config::getBool(std::string optname){
|
||||||
|
|
||||||
struct callbackData{
|
struct callbackData{
|
||||||
Socket::Connection * sock;
|
Socket::Connection * sock;
|
||||||
void (*cb)(Socket::Connection &);
|
int (*cb)(Socket::Connection &);
|
||||||
};
|
};
|
||||||
|
|
||||||
static void callThreadCallback(void * cDataArg){
|
static void callThreadCallback(void * cDataArg){
|
||||||
|
@ -312,8 +313,14 @@ static void callThreadCallback(void * cDataArg){
|
||||||
DEBUG_MSG(DLVL_INSANE, "Thread for %p ended", cDataArg);
|
DEBUG_MSG(DLVL_INSANE, "Thread for %p ended", cDataArg);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Util::Config::serveThreadedSocket(void (*callback)(Socket::Connection &)){
|
int Util::Config::serveThreadedSocket(int (*callback)(Socket::Connection &)){
|
||||||
Socket::Server server_socket = Socket::Server(getInteger("listen_port"), getString("listen_interface"), false);
|
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;}
|
if (!server_socket.connected()){return 1;}
|
||||||
DEBUG_MSG(DLVL_DEVEL, "Activating threaded server: %s", getString("cmd").c_str());
|
DEBUG_MSG(DLVL_DEVEL, "Activating threaded server: %s", getString("cmd").c_str());
|
||||||
activate();
|
activate();
|
||||||
|
@ -337,6 +344,41 @@ int Util::Config::serveThreadedSocket(void (*callback)(Socket::Connection &)){
|
||||||
return 0;
|
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:
|
/// Activated the stored config. This will:
|
||||||
/// - Drop permissions to the stored "username", if any.
|
/// - Drop permissions to the stored "username", if any.
|
||||||
/// - Daemonize the process if "daemonize" exists and is true.
|
/// - Daemonize the process if "daemonize" exists and is true.
|
||||||
|
@ -425,7 +467,16 @@ void Util::Config::addBasicConnectorOptions(JSON::Value & capabilities){
|
||||||
capabilities["optional"]["username"]["help"] = "Username to drop privileges to - default if unprovided means do not drop privileges";
|
capabilities["optional"]["username"]["help"] = "Username to drop privileges to - default if unprovided means do not drop privileges";
|
||||||
capabilities["optional"]["username"]["option"] = "--username";
|
capabilities["optional"]["username"]["option"] = "--username";
|
||||||
capabilities["optional"]["username"]["type"] = "str";
|
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.null();
|
||||||
option["long"] = "daemon";
|
option["long"] = "daemon";
|
||||||
option["short"] = "d";
|
option["short"] = "d";
|
||||||
|
|
|
@ -33,9 +33,9 @@ namespace Util {
|
||||||
long long int getInteger(std::string optname);
|
long long int getInteger(std::string optname);
|
||||||
bool getBool(std::string optname);
|
bool getBool(std::string optname);
|
||||||
void activate();
|
void activate();
|
||||||
int serveThreadedSocket(void (*callback)(Socket::Connection & S));
|
int serveThreadedSocket(int (*callback)(Socket::Connection & S));
|
||||||
int serveForkedSocket(void (*callback)(Socket::Connection & S));
|
int serveForkedSocket(int (*callback)(Socket::Connection & S));
|
||||||
int servePlainSocket(void (*callback)(Socket::Connection & S));
|
int servePlainSocket(int (*callback)(Socket::Connection & S));
|
||||||
void addBasicConnectorOptions(JSON::Value & capabilities);
|
void addBasicConnectorOptions(JSON::Value & capabilities);
|
||||||
void addConnectorOptions(int port, JSON::Value & capabilities);
|
void addConnectorOptions(int port, JSON::Value & capabilities);
|
||||||
};
|
};
|
||||||
|
@ -53,4 +53,3 @@ namespace Util {
|
||||||
void Daemonize();
|
void Daemonize();
|
||||||
|
|
||||||
}
|
}
|
||||||
;
|
|
||||||
|
|
|
@ -238,11 +238,23 @@ bool Socket::Connection::isBlocking(){
|
||||||
|
|
||||||
/// Close connection. The internal socket is closed and then set to -1.
|
/// Close connection. The internal socket is closed and then set to -1.
|
||||||
/// If the connection is already closed, nothing happens.
|
/// 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(){
|
void Socket::Connection::close(){
|
||||||
|
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 (connected()){
|
||||||
DEBUG_MSG(DLVL_HIGH, "Socket %d closed", sock);
|
|
||||||
if (sock != -1){
|
if (sock != -1){
|
||||||
shutdown(sock, SHUT_RDWR);
|
DEBUG_MSG(DLVL_HIGH, "Socket %d closed", sock);
|
||||||
errno = EINTR;
|
errno = EINTR;
|
||||||
while (::close(sock) != 0 && errno == EINTR){
|
while (::close(sock) != 0 && errno == EINTR){
|
||||||
}
|
}
|
||||||
|
@ -261,7 +273,7 @@ void Socket::Connection::close(){
|
||||||
pipes[1] = -1;
|
pipes[1] = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} //Socket::Connection::close
|
} //Socket::Connection::drop
|
||||||
|
|
||||||
/// Returns internal socket number.
|
/// Returns internal socket number.
|
||||||
int Socket::Connection::getSocket(){
|
int Socket::Connection::getSocket(){
|
||||||
|
@ -846,17 +858,31 @@ bool Socket::Server::isBlocking(){
|
||||||
|
|
||||||
/// Close connection. The internal socket is closed and then set to -1.
|
/// Close connection. The internal socket is closed and then set to -1.
|
||||||
/// If the connection is already closed, nothing happens.
|
/// 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(){
|
void Socket::Server::close(){
|
||||||
if (connected()){
|
if (sock != -1){
|
||||||
DEBUG_MSG(DLVL_HIGH, "ServerSocket %d closed", sock);
|
|
||||||
shutdown(sock, SHUT_RDWR);
|
shutdown(sock, SHUT_RDWR);
|
||||||
errno = EINTR;
|
|
||||||
while (::close(sock) != 0 && errno == EINTR){
|
|
||||||
}
|
|
||||||
sock = -1;
|
|
||||||
}
|
}
|
||||||
|
drop();
|
||||||
} //Socket::Server::close
|
} //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::drop
|
||||||
|
|
||||||
/// Returns the connected-state for this socket.
|
/// Returns the connected-state for this socket.
|
||||||
/// Note that this function might be slightly behind the real situation.
|
/// Note that this function might be slightly behind the real situation.
|
||||||
/// The connection status is updated after every accept attempt, when errors occur
|
/// The connection status is updated after every accept attempt, when errors occur
|
||||||
|
|
|
@ -68,6 +68,7 @@ namespace Socket {
|
||||||
Connection(int write, int read); ///< Simulate a socket using two file descriptors.
|
Connection(int write, int read); ///< Simulate a socket using two file descriptors.
|
||||||
//generic methods
|
//generic methods
|
||||||
void close(); ///< Close connection.
|
void close(); ///< Close connection.
|
||||||
|
void drop(); ///< Close connection without shutdown.
|
||||||
void setBlocking(bool blocking); ///< Set this socket to be blocking (true) or nonblocking (false).
|
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).
|
bool isBlocking(); ///< Check if this socket is blocking (true) or nonblocking (false).
|
||||||
std::string getHost(); ///< Gets hostname for connection, if available.
|
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 connected() const; ///< Returns the connected-state for this socket.
|
||||||
bool isBlocking(); ///< Check if this socket is blocking (true) or nonblocking (false).
|
bool isBlocking(); ///< Check if this socket is blocking (true) or nonblocking (false).
|
||||||
void close(); ///< Close connection.
|
void close(); ///< Close connection.
|
||||||
|
void drop(); ///< Close connection without shutdown.
|
||||||
int getSocket(); ///< Returns internal socket number.
|
int getSocket(); ///< Returns internal socket number.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue