mirror of https://github.com/neutrinolabs/xrdp
making sesman multithread
This commit is contained in:
parent
20e26f1ccd
commit
fda836169e
|
@ -1,9 +1,9 @@
|
|||
# sesman makefile
|
||||
SESMANOBJ = sesman.o config.o tcp.o sig.o session.o env.o \
|
||||
os_calls.o d3des.o list.o file.o log.o access.o \
|
||||
scp.o scp_v0.o
|
||||
scp.o scp_v0.o thread.o lock.o
|
||||
|
||||
SESRUNOBJ = sesrun.o config.o tcp.o \
|
||||
SESRUNOBJ = sesrun.o config.o tcp.o lock.o \
|
||||
os_calls.o d3des.o list.o file.o log.o
|
||||
|
||||
DESTDIR = /usr/local/xrdp
|
||||
|
@ -15,8 +15,8 @@ DOCDIR = /usr/doc/xrdp
|
|||
DEFINES = -DSESMAN_CFG_FILE=\"$(CFGDIR)/sesman.ini\" \
|
||||
-DSESMAN_PID_FILE=\"$(PIDDIR)/sesman.pid\"
|
||||
|
||||
CFLAGS = -Wall -O2 -I../common $(DEFINES)
|
||||
LDFLAGS = -L /usr/gnu/lib $(DEFINES)
|
||||
CFLAGS = -Wall -O2 -I../common -I/usr/include/nptl $(DEFINES)
|
||||
LDFLAGS = -L /usr/gnu/lib -I/usr/include/nptl -L/usr/lib/nptl -lpthread $(DEFINES)
|
||||
C_OS_FLAGS = $(CFLAGS) -c
|
||||
CC = gcc
|
||||
|
||||
|
@ -70,4 +70,4 @@ file.o: ../common/file.c
|
|||
$(CC) $(C_OS_FLAGS) ../common/file.c
|
||||
|
||||
log.o: ../common/log.c
|
||||
$(CC) $(C_OS_FLAGS) ../common/log.c
|
||||
$(CC) $(C_OS_FLAGS) -DLOG_ENABLE_THREAD ../common/log.c
|
||||
|
|
|
@ -0,0 +1,200 @@
|
|||
/*
|
||||
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; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
xrdp: A Remote Desktop Protocol server.
|
||||
Copyright (C) Jay Sorg 2005-2006
|
||||
|
||||
session manager
|
||||
linux only
|
||||
|
||||
*/
|
||||
|
||||
#include "sesman.h"
|
||||
|
||||
#include <semaphore.h>
|
||||
#include <pthread.h>
|
||||
|
||||
pthread_mutex_t lock_chain; /* session chain lock */
|
||||
pthread_mutexattr_t lock_chain_attr; /* mutex attributes */
|
||||
|
||||
pthread_mutex_t lock_config; /* configuration access lock */
|
||||
pthread_mutexattr_t lock_config_attr; /* mutex attributes */
|
||||
|
||||
pthread_mutex_t lock_fork; /* this lock protects the counters */
|
||||
pthread_mutexattr_t lock_fork_attr; /* mutex attributes */
|
||||
sem_t lock_fork_req; /* semaphore on which the process that are going to fork suspend on */
|
||||
sem_t lock_fork_wait; /* semaphore on which the suspended process wait on */
|
||||
int lock_fork_forkers_count; /* threads that want to fork */
|
||||
int lock_fork_blockers_count; /* threads thar are blocking fork */
|
||||
int lock_fork_waiting_count; /* threads suspended until the fork finishes */
|
||||
|
||||
sem_t lock_socket;
|
||||
|
||||
void DEFAULT_CC
|
||||
lock_init()
|
||||
{
|
||||
/* initializing socket lock */
|
||||
sem_init(&lock_socket, 0, 1);
|
||||
|
||||
/* initializing chain lock */
|
||||
pthread_mutexattr_init(&lock_chain_attr);
|
||||
pthread_mutex_init(&lock_chain, &lock_chain_attr);
|
||||
|
||||
/* initializing config lock */
|
||||
pthread_mutexattr_init(&lock_config_attr);
|
||||
pthread_mutex_init(&lock_config, &lock_config_attr);
|
||||
|
||||
/* initializing fork lock */
|
||||
pthread_mutexattr_init(&lock_fork_attr);
|
||||
pthread_mutex_init(&lock_chain, &lock_fork_attr);
|
||||
sem_init(&lock_fork_req, 0, 0);
|
||||
sem_init(&lock_fork_wait, 0, 0);
|
||||
|
||||
/* here we don't use locking because lock_init() should be called BEFORE */
|
||||
/* any thread is created */
|
||||
lock_fork_blockers_count=0;
|
||||
lock_fork_waiting_count=0;
|
||||
lock_fork_forkers_count=0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
void DEFAULT_CC
|
||||
lock_chain_acquire()
|
||||
{
|
||||
/*lock the chain*/
|
||||
LOG_DBG("lock_chain_acquire()",0);
|
||||
pthread_mutex_lock(&lock_chain);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
void DEFAULT_CC
|
||||
lock_chain_release()
|
||||
{
|
||||
/*unlock the chain*/
|
||||
LOG_DBG("lock_chain_release()",0);
|
||||
pthread_mutex_unlock(&lock_chain);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
void DEFAULT_CC
|
||||
lock_socket_acquire()
|
||||
{
|
||||
/* lock socket variable */
|
||||
LOG_DBG("lock_socket_acquire()",0);
|
||||
sem_wait(&lock_socket);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
void DEFAULT_CC
|
||||
lock_socket_release()
|
||||
{
|
||||
/* unlock socket variable */
|
||||
LOG_DBG("lock_socket_release()",0);
|
||||
sem_post(&lock_socket);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
void DEFAULT_CC
|
||||
lock_fork_request()
|
||||
{
|
||||
/* lock mutex */
|
||||
pthread_mutex_lock(&lock_fork);
|
||||
if (lock_fork_blockers_count == 0)
|
||||
{
|
||||
/* if noone is blocking fork(), then we're allowed to fork */
|
||||
sem_post(&lock_fork_req);
|
||||
}
|
||||
lock_fork_forkers_count++;
|
||||
pthread_mutex_unlock(&lock_fork);
|
||||
|
||||
/* we wait to be allowed to fork() */
|
||||
sem_wait(&lock_fork_req);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
void DEFAULT_CC
|
||||
lock_fork_release()
|
||||
{
|
||||
pthread_mutex_lock(&lock_fork);
|
||||
lock_fork_forkers_count--;
|
||||
|
||||
/* if there's someone else that want to fork, we let him fork() */
|
||||
if (lock_fork_forkers_count > 0)
|
||||
{
|
||||
sem_post(&lock_fork_req);
|
||||
}
|
||||
|
||||
for (;lock_fork_waiting_count > 0; lock_fork_waiting_count--)
|
||||
{
|
||||
/* waking up the other processes */
|
||||
sem_post(&lock_fork_wait);
|
||||
}
|
||||
pthread_mutex_unlock(&lock_fork);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
void DEFAULT_CC
|
||||
lock_fork_critical_section_end(int blocking)
|
||||
{
|
||||
LOG_DBG("lock_fork_critical_secection_end()",0);
|
||||
/* lock mutex */
|
||||
pthread_mutex_lock(&lock_fork);
|
||||
|
||||
if (blocking == SESMAN_LOCK_FORK_BLOCKER)
|
||||
{
|
||||
lock_fork_blockers_count--;
|
||||
}
|
||||
|
||||
/* if there's someone who wants to fork and we're the last blocking */
|
||||
/* then we let him go */
|
||||
if ((lock_fork_blockers_count == 0) && (lock_fork_forkers_count>0))
|
||||
{
|
||||
sem_post(&lock_fork_req);
|
||||
}
|
||||
pthread_mutex_unlock(&lock_fork);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
int DEFAULT_CC
|
||||
lock_fork_critical_section_start()
|
||||
{
|
||||
LOG_DBG("lock_fork_critical_secection_start()",0);
|
||||
do
|
||||
{
|
||||
pthread_mutex_lock(&lock_fork);
|
||||
|
||||
/* someone requested to fork */
|
||||
if (lock_fork_forkers_count > 0)
|
||||
{
|
||||
lock_fork_waiting_count++;
|
||||
pthread_mutex_unlock(&lock_fork);
|
||||
|
||||
/* we wait until the fork finishes */
|
||||
sem_wait(&lock_fork_wait);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
/* no fork, so we can go on... */
|
||||
lock_fork_blockers_count++;
|
||||
pthread_mutex_unlock(&lock_fork);
|
||||
|
||||
return SESMAN_LOCK_FORK_BLOCKER;
|
||||
}
|
||||
} while (1);
|
||||
|
||||
/* we'll never get here */
|
||||
return SESMAN_LOCK_FORK_WAITING;
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
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; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
xrdp: A Remote Desktop Protocol server.
|
||||
Copyright (C) Jay Sorg 2005-2006
|
||||
*/
|
||||
|
||||
#ifndef LOCK_H
|
||||
#define LOCK_H
|
||||
|
||||
#include "sesman.h"
|
||||
|
||||
#define SESMAN_LOCK_FORK_BLOCKER 1
|
||||
#define SESMAN_LOCK_FORK_WAITING 0
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief initializes all the locks
|
||||
*
|
||||
*/
|
||||
void DEFAULT_CC
|
||||
lock_init();
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief acquires the lock for the session chain
|
||||
*
|
||||
*/
|
||||
void DEFAULT_CC
|
||||
lock_chain_acquire();
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief releases the sessiona chain lock
|
||||
*
|
||||
*/
|
||||
void DEFAULT_CC
|
||||
lock_chain_release();
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief acquires config lock
|
||||
*
|
||||
*/
|
||||
void DEFAULT_CC
|
||||
lock_cfg_acquire();
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief releases config lock
|
||||
*
|
||||
*/
|
||||
void DEFAULT_CC
|
||||
lock_cfg_release();
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief request the socket lock
|
||||
*
|
||||
*/
|
||||
void DEFAULT_CC
|
||||
lock_socket_acquire();
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief releases the socket lock
|
||||
*
|
||||
*/
|
||||
void DEFAULT_CC
|
||||
lock_socket_release();
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief requires to fork a new child process
|
||||
*
|
||||
*/
|
||||
void DEFAULT_CC
|
||||
lock_fork_request();
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief releases a fork() request
|
||||
*
|
||||
*/
|
||||
void DEFAULT_CC
|
||||
lock_fork_release();
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief starts a section that is critical for forking
|
||||
*
|
||||
* starts a section that is critical for forking, that is noone can fork()
|
||||
* while i'm in a critical section. But if someone wanted to fork we have
|
||||
* to wait until he finishes with lock_fork_release()
|
||||
*
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
int DEFAULT_CC
|
||||
lock_fork_critical_section_start();
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief closes the critical section
|
||||
*
|
||||
*/
|
||||
void DEFAULT_CC
|
||||
lock_fork_critical_section_end(int blocking);
|
||||
|
||||
#endif
|
23
sesman/scp.c
23
sesman/scp.c
|
@ -29,9 +29,11 @@
|
|||
|
||||
#include "sesman.h"
|
||||
|
||||
extern int thread_sck;
|
||||
|
||||
/******************************************************************************/
|
||||
void DEFAULT_CC
|
||||
scp_process_start(int sck)
|
||||
void* DEFAULT_CC
|
||||
scp_process_start(void* sck)
|
||||
{
|
||||
int socket;
|
||||
int version;
|
||||
|
@ -39,12 +41,14 @@ scp_process_start(int sck)
|
|||
struct stream* in_s;
|
||||
struct stream* out_s;
|
||||
|
||||
/* making a local copy of the socket */
|
||||
/* sck should NEVER be used after lock_socket_release() */
|
||||
/* probably this is just paranoia */
|
||||
socket = sck;
|
||||
#warning locking disabled
|
||||
// lock_socket_release();
|
||||
/* making a local copy of the socket (it's on the stack) */
|
||||
/* probably this is just paranoia */
|
||||
//socket = *((int*) sck);
|
||||
socket = thread_sck;
|
||||
LOG_DBG("started scp thread on socket %d", socket);
|
||||
|
||||
/* unlocking thread_sck */
|
||||
lock_socket_release();
|
||||
|
||||
make_stream(in_s);
|
||||
make_stream(out_s);
|
||||
|
@ -63,7 +67,7 @@ scp_process_start(int sck)
|
|||
scp_v0_process(socket, in_s, out_s);
|
||||
}
|
||||
#warning scp v1 is disabled
|
||||
/* this is temporarily disabled...
|
||||
/* this is temporarily disabled...
|
||||
else if (version == 1)
|
||||
{
|
||||
/ * starts processing an scp v0 connection * /
|
||||
|
@ -80,5 +84,6 @@ scp_process_start(int sck)
|
|||
g_tcp_close(socket);
|
||||
free_stream(in_s);
|
||||
free_stream(out_s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
* @param socket the connection socket
|
||||
*
|
||||
*/
|
||||
void DEFAULT_CC
|
||||
scp_process_start(int socket);
|
||||
void* DEFAULT_CC
|
||||
scp_process_start(void* sck);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -30,48 +30,9 @@
|
|||
int g_sck;
|
||||
int g_pid;
|
||||
unsigned char g_fixedkey[8] = { 23, 82, 107, 6, 35, 78, 88, 7 };
|
||||
#ifdef OLDSESSION
|
||||
struct session_item g_session_items[100]; /* sesman.h */
|
||||
extern int g_session_count;
|
||||
#endif
|
||||
struct config_sesman g_cfg; /* config.h */
|
||||
//int g_server_type = 0; /* Xvnc 0 Xrdp 10 */
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief triggered when a child process (a session) dies
|
||||
* @param s received signal
|
||||
*
|
||||
*/
|
||||
static void DEFAULT_CC
|
||||
cterm(int s)
|
||||
{
|
||||
#ifdef OLDSESSION
|
||||
int i;
|
||||
#endif
|
||||
int pid;
|
||||
|
||||
if (g_getpid() != g_pid)
|
||||
{
|
||||
return;
|
||||
}
|
||||
pid = g_waitchild();
|
||||
if (pid > 0)
|
||||
{
|
||||
#ifdef OLDSESSION
|
||||
for (i = 0; i < 100; i++)
|
||||
{
|
||||
if (g_session_items[i].pid == pid)
|
||||
{
|
||||
g_memset(g_session_items + i, 0, sizeof(struct session_item));
|
||||
g_session_count--;
|
||||
}
|
||||
}
|
||||
#else
|
||||
session_kill(pid);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
extern int thread_sck;
|
||||
|
||||
/******************************************************************************/
|
||||
/**
|
||||
|
@ -104,7 +65,10 @@ sesman_main_loop()
|
|||
while (in_sck > 0)
|
||||
{
|
||||
/* we've got a connection, so we pass it to scp code */
|
||||
scp_process_start(in_sck);
|
||||
LOG_DBG("new connection",0);
|
||||
thread_sck=in_sck;
|
||||
//scp_process_start((void*)in_sck);
|
||||
thread_scp_start(in_sck);
|
||||
|
||||
/* once we've processed the connection, we go back listening */
|
||||
in_sck = g_tcp_accept(g_sck);
|
||||
|
@ -260,17 +224,23 @@ main(int argc, char** argv)
|
|||
g_file_open("/dev/null");
|
||||
g_file_open("/dev/null");
|
||||
}
|
||||
|
||||
/* initializing locks */
|
||||
lock_init();
|
||||
|
||||
/* signal handling */
|
||||
#ifdef OLDSESSION
|
||||
g_memset(&g_session_items, 0, sizeof(g_session_items));
|
||||
#endif
|
||||
g_pid = g_getpid();
|
||||
g_signal(1, sig_sesman_reload_cfg); /* SIGHUP */
|
||||
g_signal(2, sig_sesman_shutdown); /* SIGINT */
|
||||
g_signal(9, sig_sesman_shutdown); /* SIGKILL */
|
||||
g_signal(15, sig_sesman_shutdown); /* SIGTERM */
|
||||
g_signal_child_stop(cterm); /* SIGCHLD */
|
||||
/* old style signal handling is now managed synchronously by a
|
||||
* separate thread. uncomment this block if you need old style
|
||||
* signal handling and comment out thread_sighandler_start() */
|
||||
/*
|
||||
g_signal(1, sig_sesman_reload_cfg); / * SIGHUP * /
|
||||
g_signal(2, sig_sesman_shutdown); / * SIGINT * /
|
||||
g_signal(9, sig_sesman_shutdown); / * SIGKILL * /
|
||||
g_signal(15, sig_sesman_shutdown); / * SIGTERM * /
|
||||
g_signal_child_stop(cterm); / * SIGCHLD * /
|
||||
*/
|
||||
thread_sighandler_start();
|
||||
|
||||
/* writing pid file */
|
||||
fd = g_file_open(SESMAN_PID_FILE);
|
||||
|
|
|
@ -41,6 +41,8 @@
|
|||
#include "session.h"
|
||||
#include "access.h"
|
||||
#include "scp.h"
|
||||
#include "thread.h"
|
||||
#include "lock.h"
|
||||
|
||||
#ifndef SESMAN_PID_FILE
|
||||
#define SESMAN_PID_FILE "./sesman.pid"
|
||||
|
|
|
@ -29,35 +29,18 @@
|
|||
|
||||
extern unsigned char g_fixedkey[8];
|
||||
extern struct config_sesman g_cfg; /* config.h */
|
||||
//extern int g_server_type;
|
||||
#ifdef OLDSESSION
|
||||
extern struct session_item g_session_items[100]; /* sesman.h */
|
||||
#else
|
||||
struct session_chain* g_sessions;
|
||||
#endif
|
||||
int g_session_count;
|
||||
|
||||
/******************************************************************************/
|
||||
struct session_item* DEFAULT_CC
|
||||
session_get_bydata(char* name, int width, int height, int bpp)
|
||||
{
|
||||
#ifdef OLDSESSION
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 100; i++)
|
||||
{
|
||||
if (g_strncmp(name, g_session_items[i].name, 255) == 0 &&
|
||||
g_session_items[i].width == width &&
|
||||
g_session_items[i].height == height &&
|
||||
g_session_items[i].bpp == bpp)
|
||||
{
|
||||
return g_session_items + i;
|
||||
}
|
||||
}
|
||||
#else
|
||||
struct session_chain* tmp;
|
||||
|
||||
/*THREAD-FIX require chain lock */
|
||||
lock_chain_acquire();
|
||||
|
||||
tmp=g_sessions;
|
||||
|
||||
while (tmp != 0)
|
||||
|
@ -68,13 +51,14 @@ session_get_bydata(char* name, int width, int height, int bpp)
|
|||
tmp->item->bpp == bpp)
|
||||
{
|
||||
/*THREAD-FIX release chain lock */
|
||||
lock_chain_release();
|
||||
return tmp->item;
|
||||
}
|
||||
tmp=tmp->next;
|
||||
}
|
||||
|
||||
/*THREAD-FIX release chain lock */
|
||||
#endif
|
||||
lock_chain_release();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -139,20 +123,23 @@ session_start(int width, int height, int bpp, char* username, char* password,
|
|||
char cur_dir[256];
|
||||
char text[256];
|
||||
char passwd_file[256];
|
||||
#ifndef OLDSESSION
|
||||
struct session_chain* temp;
|
||||
#endif
|
||||
|
||||
/*THREAD-FIX lock to control g_session_count*/
|
||||
lock_chain_acquire();
|
||||
/* check to limit concurrent sessions */
|
||||
if (g_session_count >= g_cfg.sess.max_sessions)
|
||||
{
|
||||
/*THREAD-FIX unlock chain*/
|
||||
lock_chain_release();
|
||||
log_message(LOG_LEVEL_INFO, "max concurrent session limit exceeded. login \
|
||||
for user %s denied", username);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef OLDSESSION
|
||||
/*THREAD-FIX unlock chain*/
|
||||
lock_chain_release();
|
||||
|
||||
temp = (struct session_chain*)g_malloc(sizeof(struct session_chain), 0);
|
||||
if (temp == 0)
|
||||
{
|
||||
|
@ -168,13 +155,15 @@ for user %s denied", username);
|
|||
username);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
g_get_current_dir(cur_dir, 255);
|
||||
display = 10;
|
||||
/*while (x_server_running(display) && display < 50)*/
|
||||
/* we search for a free display up to max_sessions */
|
||||
/* we should need no more displays than this */
|
||||
|
||||
/* block all the threads running to enable forking */
|
||||
lock_fork_request();
|
||||
while (x_server_running(display))
|
||||
{
|
||||
display++;
|
||||
|
@ -256,7 +245,7 @@ for user %s denied", username);
|
|||
g_exit(1);
|
||||
}
|
||||
/* should not get here */
|
||||
log_message(LOG_LEVEL_ALWAYS,"error doing execve for user %s - pid %d",
|
||||
log_message(LOG_LEVEL_ALWAYS,"error doing execve (%s) for user %s - pid %d",
|
||||
username, g_getpid());
|
||||
g_exit(1);
|
||||
}
|
||||
|
@ -273,32 +262,9 @@ for user %s denied", username);
|
|||
}
|
||||
else /* parent */
|
||||
{
|
||||
#ifdef OLDSESSION
|
||||
g_session_items[display].pid = pid;
|
||||
g_strcpy(g_session_items[display].name, username);
|
||||
g_session_items[display].display = display;
|
||||
g_session_items[display].width = width;
|
||||
g_session_items[display].height = height;
|
||||
g_session_items[display].bpp = bpp;
|
||||
g_session_items[display].data = data;
|
||||
|
||||
g_session_items[display].connect_time=g_time1();
|
||||
g_session_items[display].disconnect_time=(time_t) 0;
|
||||
g_session_items[display].idle_time=(time_t) 0;
|
||||
|
||||
i/*if (type==0)
|
||||
{
|
||||
g_session_items[display].type=SESMAN_SESSION_TYPE_XVNC;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_session_items[display].type=SESMAN_SESSION_TYPE_XRDP;
|
||||
}*/
|
||||
g_session_items[display].type = type;
|
||||
g_session_items[display].status = SESMAN_SESSION_STATUS_ACTIVE;
|
||||
|
||||
g_session_count++;
|
||||
#else
|
||||
/* let the other threads go on */
|
||||
lock_fork_release();
|
||||
|
||||
temp->item->pid = pid;
|
||||
temp->item->display = display;
|
||||
temp->item->width = width;
|
||||
|
@ -311,24 +277,17 @@ for user %s denied", username);
|
|||
temp->item->disconnect_time = 0;
|
||||
temp->item->idle_time = 0;
|
||||
|
||||
/* if (type==0)
|
||||
{
|
||||
temp->item->type=SESMAN_SESSION_TYPE_XVNC;
|
||||
}
|
||||
else
|
||||
{
|
||||
temp->item->type=SESMAN_SESSION_TYPE_XRDP;
|
||||
}*/
|
||||
|
||||
temp->item->type=type;
|
||||
temp->item->status=SESMAN_SESSION_STATUS_ACTIVE;
|
||||
|
||||
/*THREAD-FIX lock the chain*/
|
||||
/*THREAD-FIX lock the chain*/
|
||||
lock_chain_acquire();
|
||||
temp->next=g_sessions;
|
||||
g_sessions=temp;
|
||||
g_session_count++;
|
||||
/*THERAD-FIX free the chain*/
|
||||
#endif
|
||||
lock_chain_release();
|
||||
|
||||
g_sleep(5000);
|
||||
}
|
||||
return display;
|
||||
|
@ -371,8 +330,6 @@ struct session_chain
|
|||
};
|
||||
*/
|
||||
|
||||
#ifndef OLDSESSION
|
||||
|
||||
/******************************************************************************/
|
||||
int DEFAULT_CC
|
||||
session_kill(int pid)
|
||||
|
@ -381,6 +338,8 @@ session_kill(int pid)
|
|||
struct session_chain* prev;
|
||||
|
||||
/*THREAD-FIX require chain lock */
|
||||
lock_chain_acquire();
|
||||
|
||||
tmp=g_sessions;
|
||||
prev=0;
|
||||
|
||||
|
@ -401,6 +360,7 @@ session_kill(int pid)
|
|||
prev->next = tmp->next;
|
||||
}
|
||||
/*THREAD-FIX release chain lock */
|
||||
lock_chain_release();
|
||||
return SESMAN_SESSION_KILL_NULLITEM;
|
||||
}
|
||||
|
||||
|
@ -423,6 +383,7 @@ session_kill(int pid)
|
|||
g_free(tmp);
|
||||
g_session_count--;
|
||||
/*THREAD-FIX release chain lock */
|
||||
lock_chain_release();
|
||||
return SESMAN_SESSION_KILL_OK;
|
||||
}
|
||||
|
||||
|
@ -432,6 +393,7 @@ session_kill(int pid)
|
|||
}
|
||||
|
||||
/*THREAD-FIX release chain lock */
|
||||
lock_chain_release();
|
||||
return SESMAN_SESSION_KILL_NOTFOUND;
|
||||
}
|
||||
|
||||
|
@ -441,7 +403,9 @@ session_get_bypid(int pid)
|
|||
{
|
||||
struct session_chain* tmp;
|
||||
|
||||
/*THREAD-FIX require chain lock */
|
||||
/*THREAD-FIX require chain lock */
|
||||
lock_chain_acquire();
|
||||
|
||||
tmp = g_sessions;
|
||||
while (tmp != 0)
|
||||
{
|
||||
|
@ -450,12 +414,14 @@ session_get_bypid(int pid)
|
|||
log_message(LOG_LEVEL_ERROR, "session descriptor for pid %d is null!",
|
||||
pid);
|
||||
/*THREAD-FIX release chain lock */
|
||||
lock_chain_release();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (tmp->item->pid == pid)
|
||||
{
|
||||
/*THREAD-FIX release chain lock */
|
||||
lock_chain_release();
|
||||
return tmp->item;
|
||||
}
|
||||
|
||||
|
@ -464,8 +430,7 @@ session_get_bypid(int pid)
|
|||
}
|
||||
|
||||
/*THREAD-FIX release chain lock */
|
||||
lock_chain_release();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
77
sesman/sig.c
77
sesman/sig.c
|
@ -27,6 +27,8 @@
|
|||
|
||||
#include "sesman.h"
|
||||
|
||||
#include "signal.h"
|
||||
|
||||
extern int g_sck;
|
||||
extern int g_pid;
|
||||
extern struct config_sesman g_cfg;
|
||||
|
@ -73,3 +75,78 @@ sig_sesman_reload_cfg(int sig)
|
|||
|
||||
log_message(LOG_LEVEL_INFO, "configuration reloaded");
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
void DEFAULT_CC
|
||||
sig_sesman_session_end(int sig)
|
||||
{
|
||||
int pid;
|
||||
|
||||
if (g_getpid() != g_pid)
|
||||
{
|
||||
return;
|
||||
}
|
||||
pid = g_waitchild();
|
||||
if (pid > 0)
|
||||
{
|
||||
session_kill(pid);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
void* DEFAULT_CC
|
||||
sig_handler_thread(void* arg)
|
||||
{
|
||||
int recv_signal;
|
||||
sigset_t sigmask;
|
||||
sigset_t oldmask;
|
||||
sigset_t waitmask;
|
||||
|
||||
/* mask signals to be able to wait for them... */
|
||||
sigfillset(&sigmask);
|
||||
/* it is a good idea not to block SIGILL SIGSEGV */
|
||||
/* SIGFPE -- see sigaction(2) NOTES */
|
||||
pthread_sigmask(SIG_BLOCK, &sigmask, &oldmask);
|
||||
|
||||
/* building the signal wait mask... */
|
||||
sigemptyset(&waitmask);
|
||||
sigaddset(&waitmask, SIGHUP);
|
||||
sigaddset(&waitmask, SIGCHLD);
|
||||
sigaddset(&waitmask, SIGTERM);
|
||||
// sigaddset(&waitmask, SIGFPE);
|
||||
// sigaddset(&waitmask, SIGILL);
|
||||
// sigaddset(&waitmask, SIGSEGV);
|
||||
|
||||
do
|
||||
{
|
||||
LOG_DBG("calling sigwait()",0);
|
||||
sigwait(&waitmask, &recv_signal);
|
||||
|
||||
switch (recv_signal)
|
||||
{
|
||||
case SIGHUP:
|
||||
//reload cfg
|
||||
LOG_DBG("sesman received SIGHUP",0);
|
||||
//return 0;
|
||||
break;
|
||||
case SIGCHLD:
|
||||
/* a session died */
|
||||
LOG_DBG("sesman received SIGCHLD",0);
|
||||
sig_sesman_session_end(SIGCHLD);
|
||||
break;
|
||||
/*case SIGKILL;
|
||||
/* we die * /
|
||||
LOG_DBG("sesman received SIGKILL",0);
|
||||
sig_sesman_shutdown(recv_signal);
|
||||
break;*/
|
||||
case SIGTERM:
|
||||
/* we die */
|
||||
LOG_DBG("sesman received SIGTERM",0);
|
||||
sig_sesman_shutdown(recv_signal);
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
17
sesman/sig.h
17
sesman/sig.h
|
@ -46,5 +46,22 @@ sig_sesman_shutdown(int sig);
|
|||
void DEFAULT_CC
|
||||
sig_sesman_reload_cfg(int sig);
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief SIGCHLD handling code
|
||||
* @param sig The received signal
|
||||
*
|
||||
*/
|
||||
void DEFAULT_CC
|
||||
sig_sesman_session_end(int sig);
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief signal handling thread
|
||||
*
|
||||
*/
|
||||
void* DEFAULT_CC
|
||||
sig_handler_thread(void* arg);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
12
sesman/tcp.c
12
sesman/tcp.c
|
@ -32,6 +32,9 @@ int DEFAULT_CC
|
|||
tcp_force_recv(int sck, char* data, int len)
|
||||
{
|
||||
int rcvd;
|
||||
int block;
|
||||
|
||||
block = lock_fork_critical_section_start();
|
||||
|
||||
while (len > 0)
|
||||
{
|
||||
|
@ -57,6 +60,9 @@ tcp_force_recv(int sck, char* data, int len)
|
|||
len -= rcvd;
|
||||
}
|
||||
}
|
||||
|
||||
lock_fork_critical_section_end(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -65,7 +71,10 @@ int DEFAULT_CC
|
|||
tcp_force_send(int sck, char* data, int len)
|
||||
{
|
||||
int sent;
|
||||
int block;
|
||||
|
||||
block = lock_fork_critical_section_start();
|
||||
|
||||
while (len > 0)
|
||||
{
|
||||
sent = g_tcp_send(sck, data, len, 0);
|
||||
|
@ -90,6 +99,9 @@ tcp_force_send(int sck, char* data, int len)
|
|||
len -= sent;
|
||||
}
|
||||
}
|
||||
|
||||
lock_fork_critical_section_end(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
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; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
xrdp: A Remote Desktop Protocol server.
|
||||
Copyright (C) Jay Sorg 2005-2006
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @file thread.c
|
||||
* @brief thread stuff...
|
||||
* @author Simone Fedele
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sesman.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <pthread.h>
|
||||
|
||||
static pthread_t thread_sighandler;
|
||||
//static pthread_t thread_updater;
|
||||
|
||||
/* a variable to pass the socket of s connection to a thread */
|
||||
int thread_sck;
|
||||
|
||||
/******************************************************************************/
|
||||
int DEFAULT_CC
|
||||
thread_sighandler_start()
|
||||
{
|
||||
int ret;
|
||||
sigset_t sigmask;
|
||||
sigset_t oldmask;
|
||||
sigset_t waitmask;
|
||||
|
||||
/* mask signals to be able to wait for them... */
|
||||
sigfillset(&sigmask);
|
||||
pthread_sigmask(SIG_BLOCK, &sigmask, &oldmask);
|
||||
|
||||
/* unblock some signals... */
|
||||
sigemptyset(&waitmask);
|
||||
|
||||
/* it is a good idea not to block SIGILL SIGSEGV */
|
||||
/* SIGFPE -- see sigaction(2) NOTES */
|
||||
sigaddset(&waitmask, SIGILL);
|
||||
sigaddset(&waitmask, SIGSEGV);
|
||||
sigaddset(&waitmask, SIGFPE);
|
||||
pthread_sigmask(SIG_UNBLOCK, &waitmask, NULL);
|
||||
|
||||
log_message(LOG_LEVEL_INFO,"starting signal handling thread...");
|
||||
|
||||
ret = pthread_create(&thread_sighandler, NULL, sig_handler_thread, "");
|
||||
pthread_detach(thread_sighandler);
|
||||
|
||||
if (ret==0)
|
||||
{
|
||||
log_message(LOG_LEVEL_INFO, "signal handler thread started successfully");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if something happened while starting a new thread... */
|
||||
switch (ret)
|
||||
{
|
||||
case EINVAL:
|
||||
log_message(LOG_LEVEL_ERROR, "invalid attributes for signal handling thread (creation returned EINVAL)");
|
||||
break;
|
||||
case EAGAIN:
|
||||
log_message(LOG_LEVEL_ERROR, "not enough resources to start signal handling thread (creation returned EAGAIN)");
|
||||
break;
|
||||
case EPERM:
|
||||
log_message(LOG_LEVEL_ERROR, "invalid permissions for signal handling thread (creation returned EPERM)");
|
||||
break;
|
||||
default:
|
||||
log_message(LOG_LEVEL_ERROR, "unknown error starting signal handling thread");
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef JUST_TO_AVOID_COMPILER_ERRORS
|
||||
/******************************************************************************/
|
||||
int DEFAULT_CC
|
||||
thread_session_update_start()
|
||||
{
|
||||
int ret;
|
||||
//starts the session update thread
|
||||
//that checks for idle time, destroys sessions, ecc...
|
||||
|
||||
#warning this thread should always request lock_fork before read or write
|
||||
#warning (so we can Fork() In Peace)
|
||||
ret = pthread_create(&thread_updater, NULL, , "");
|
||||
pthread_detach(thread_updater);
|
||||
|
||||
if (ret==0)
|
||||
{
|
||||
log_message(LOG_LEVEL_INFO, "session update thread started successfully");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if something happened while starting a new thread... */
|
||||
switch (ret)
|
||||
{
|
||||
case EINVAL:
|
||||
log_message(LOG_LEVEL_ERROR, "invalid attributes for session update thread (creation returned EINVAL)");
|
||||
break;
|
||||
case EAGAIN:
|
||||
log_message(LOG_LEVEL_ERROR, "not enough resources to start session update thread (creation returned EAGAIN)");
|
||||
break;
|
||||
case EPERM:
|
||||
log_message(LOG_LEVEL_ERROR, "invalid permissions for session update thread (creation returned EPERM)");
|
||||
break;
|
||||
default:
|
||||
log_message(LOG_LEVEL_ERROR, "unknown error starting session update thread");
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/******************************************************************************/
|
||||
int DEFAULT_CC
|
||||
thread_scp_start(int skt)
|
||||
{
|
||||
int ret;
|
||||
pthread_t th;
|
||||
|
||||
/* blocking the use of thread_skt */
|
||||
lock_socket_acquire();
|
||||
thread_sck=skt;
|
||||
|
||||
/* start a thread that processes a connection */
|
||||
ret = pthread_create(&th, NULL, scp_process_start, "");
|
||||
//ret = pthread_create(&th, NULL, scp_process_start, (void*) (&thread_sck));
|
||||
pthread_detach(th);
|
||||
|
||||
if (ret==0)
|
||||
{
|
||||
log_message(LOG_LEVEL_INFO, "scp thread on sck %d started successfully", skt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if something happened while starting a new thread... */
|
||||
switch (ret)
|
||||
{
|
||||
case EINVAL:
|
||||
log_message(LOG_LEVEL_ERROR, "invalid attributes for scp thread on sck %d (creation returned EINVAL)", skt);
|
||||
break;
|
||||
case EAGAIN:
|
||||
log_message(LOG_LEVEL_ERROR, "not enough resources to start scp thread on sck %d (creation returned EAGAIN)", skt);
|
||||
break;
|
||||
case EPERM:
|
||||
log_message(LOG_LEVEL_ERROR, "invalid permissions for scp thread on sck %d (creation returned EPERM)", skt);
|
||||
break;
|
||||
default:
|
||||
log_message(LOG_LEVEL_ERROR, "unknown error starting scp thread on sck %d");
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
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; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
xrdp: A Remote Desktop Protocol server.
|
||||
Copyright (C) Jay Sorg 2005-2006
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @file thread.h
|
||||
* @brief thread stuff...
|
||||
* @author Simone Fedele
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef THREAD_H
|
||||
#define THREAD_H
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Starts the signal handling thread
|
||||
* @retval 0 on success
|
||||
* @retval 1 on error
|
||||
*
|
||||
*/
|
||||
int DEFAULT_CC
|
||||
thread_sighandler_start();
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Starts the session update thread
|
||||
*
|
||||
*/
|
||||
int DEFAULT_CC
|
||||
thread_session_update_start();
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Starts a thread to handle an incoming connection
|
||||
*
|
||||
*/
|
||||
int DEFAULT_CC
|
||||
thread_scp_start();
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue