winix/core/requestcontroller.cpp

194 lines
3.6 KiB
C++
Executable File

/*
* This file is a part of CMSLU -- Content Management System like Unix
* and is not publicly distributed
*
* Copyright (c) 2008, Tomasz Sowa
* All rights reserved.
*
*/
#include "requestcontroller.h"
RequestController::RequestController()
{
}
RequestController::~RequestController()
{
Close();
}
void RequestController::Close()
{
// don't call close(0)
// it will be closed next time during dup(s,0)
// if you closed the descriptor here
// then the database would have that descriptor (during connecting)
// and there'll be a problem in the next loop (after SIGHUP)
}
bool RequestController::Init()
{
const char * sock = data.fcgi_socket.c_str();
unlink(sock);
int s = FCGX_OpenSocket(sock, 10);
if( s < 0 )
{
log << log1 << "An error during creating a socket" << logend;
return false;
}
chmod(sock, data.fcgi_socket_chmod);
passwd * pw = getpwnam(data.fcgi_socket_user.c_str());
if( !pw )
{
log << log1 << "There is no user: " << data.fcgi_socket_user << logend;
return false;
}
group * gr = getgrnam(data.fcgi_socket_group.c_str());
if( !gr )
{
log << log1 << "There is no group: " << data.fcgi_socket_group << logend;
return false;
}
chown(sock, pw->pw_uid, gr->gr_gid);
if( setuid(pw->pw_uid) < 0 )
{
log << log1 << "I can't change the user into: " << data.fcgi_socket_user << logend;
return false;
}
/*
if( setgid(gr->gr_gid) < 0 )
{
int e = errno;
log << log1 << "I can't change the group into: " << data.fcgi_socket_group << " " << gr->gr_gid << logend;
log << log1 << "errno: " << e << logend;
return false;
}
*/
dup2(s, 0);
//
data.dirs.ReadDirs();
data.users.ReadUsers();
data.groups.ReadGroups();
data.functions.ReadFunctions();
//
if( !content.Init() )
return false;
return true;
}
bool RequestController::BaseUrlRedirect()
{
if( data.base_url_http_host.empty() )
return false;
if( data.base_url_http_host == request.env_http_host )
return false;
request.result = Request::redirect;
request.str = data.base_url + request.env_request_uri;
log << log3 << "RC: BaseUrlRedirect from: " << request.env_http_host << logend;
return true;
}
void RequestController::Loop()
{
while( FCGX_Accept(&request.in, &request.out, &request.err, &request.env) == 0 )
{
log << log2 << "---------------------------------------------------------------------------------" << logend;
try
{
request.Clear();
request.Read();
// when BaseUrlRedirect() return true we didn't have to set everything in request.Read()
// in the future request.Read() can be split and at the beginning only environment variables will be read
// and then BaseUrlRedirect() will be called (for performance)
if( !BaseUrlRedirect() )
{
session_manager.DeleteOldSessions();
session_manager.SetSession(); // set request.session as well
request.session->CheckTimers();
function_parser.Parse();
content.Make();
}
request.SendAll();
}
catch(const std::exception & e)
{
log << log1 << "uncaught std exception: " << e.what() << logend;
}
catch(const Error & e)
{
log << log1 << "uncaught exception: Error: " << e << logend;
}
catch(...)
{
log << log1 << "uncaught exception" << logend;
}
// !! this should be immediately after FCGX_Accept() but signals don't want to break FCGX_Accept
if( data.signal_hup )
{
FCGX_Finish();
return;
}
}
}
SessionContainer::Iterator RequestController::SessionBegin()
{
return session_manager.SessionBegin();
}
SessionContainer::Iterator RequestController::SessionEnd()
{
return session_manager.SessionEnd();
}