RioApacheModule.cpp File Reference

#include "RioApacheModule.h"
#include "RioModuleTypes.h"
#include "RioModule.h"
#include "RioServersFile.h"
#include "RioError.h"
#include "UserLogs.h"
#include "ServerInterface.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <execinfo.h>
#include <pwd.h>
#include <unistd.h>
#include <apr_strings.h>
#include <ap_compat.h>
#include <http_request.h>
#include <apr_shm.h>
#include <sys/syscall.h>

Go to the source code of this file.

Functions

void show_stackframe ()
void SignalHandler (int sig)
apr_status_t ProcessParams (request_rec *Request, apr_table_t **ParamTable)
apr_status_t SendError (request_rec *Request, apr_status_t ApacheError, int SystemError, RioResult RioError)
bool ProcessServersFile (request_rec *Request, RioModuleConfig *Config, ServerSelectionType SelectionType, char **ServerName, apr_status_t *ApacheError, int *SystemError, RioResult *RioError)
bool TransferRioFile (request_rec *Request, RioModuleConfig *Config, char *ServerName, const char *FileName, RioAccess Access, RioObjectSize StartPosition, RioObjectSize EndPosition, bool SendHeader, apr_status_t *ApacheError, int *SystemError, RioResult *RioError)
int ProcessFileOptions (request_rec *r, RioModuleConfig *Config, apr_table_t *ParamTable, bool UseRedirect, apr_status_t *ApacheError, int *SystemError, RioResult *RioError)
int ProcessUserLog (request_rec *r, RioModuleConfig *Config, apr_table_t *ParamTable, apr_status_t *ApacheError, int *SystemError, RioResult *RioError)
static apr_status_t RioModuleDestroyServerInterface (void *Param)
int ProcessExec (request_rec *r, RioModuleConfig *Config, apr_table_t *ParamTable, apr_status_t *ApacheError, int *SystemError, RioResult *RioError)
static int RioModuleRequestHandler (request_rec *r)
static apr_status_t RioModuleTerminateServerUserLogs (void *Param)
int CreateServerLogsProcess (apr_pool_t *pconf, server_rec *s, RioModuleConfig *Config, char *LogsPrefixPath, unsigned int LogPort)
static int RioModulePostConfigHandler (apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
static void RioModuleChildInitHandler (apr_pool_t *p, server_rec *s)
static void RioModuleRegisterHooks (apr_pool_t *p)
static const char * setServerName (cmd_parms *parms, void *mconfig, const char *arg)
static const char * setRealTimeExtensions (cmd_parms *parms, void *mconfig, const char *arg)
static const char * setWaitTime (cmd_parms *parms, void *mconfig, const char *arg)
static const char * setBufferSize (cmd_parms *parms, void *mconfig, const char *arg)
static const char * setLineSize (cmd_parms *parms, void *mconfig, const char *arg)
static const char * setSelectionType (cmd_parms *parms, void *mconfig, const char *arg)
static const char * setFragmentSize (cmd_parms *parms, void *mconfig, const char *arg)
static const char * setRIOUser (cmd_parms *parms, void *mconfig, const char *arg1, const char *arg2)
static const char * setServersFileName (cmd_parms *parms, void *mconfig, const char *arg)
static const char * setRedirectName (cmd_parms *parms, void *mconfig, const char *arg)
static const char * setTransferName (cmd_parms *parms, void *mconfig, const char *arg)
static const char * setMaxLogFileSize (cmd_parms *parms, void *mconfig, const char *arg)
static const char * setMaxCombinedLogFilesSize (cmd_parms *parms, void *mconfig, const char *arg)
static const char * setUserLogsPrefixPath (cmd_parms *parms, void *mconfig, const char *arg)
static const char * setUserLogName (cmd_parms *parms, void *mconfig, const char *arg)
static const char * setExecName (cmd_parms *parms, void *mconfig, const char *arg)
static const char * setUserLogPort (cmd_parms *parms, void *mconfig, const char *arg)
static const char * setExecSessionId (cmd_parms *parms, void *mconfig, const char *arg)
static const char * setExecLogsPrefixPath (cmd_parms *parms, void *mconfig, const char *arg)
static const char * setExecLogPort (cmd_parms *parms, void *mconfig, const char *arg)
static void * CreateRioModuleConfig (apr_pool_t *p, server_rec *s)

Function Documentation

static void* CreateRioModuleConfig ( apr_pool_t *  p,
server_rec *  s 
) [static]

Definition at line 3212 of file RioApacheModule.cpp.

03213 {
03214     RioModuleConfig *config;
03215 
03216     // Aloca espaco para a estrutura com a configuracao, usando o pool do 
03217     // apache.
03218     config = (RioModuleConfig *) apr_pcalloc( p, sizeof( RioModuleConfig ) );
03219 
03220     // Inicializa a estrutura de configuracao do modulo.
03221     config->Description = apr_pstrdup( p, MODULE_DESCRIPTION );
03222     config->ServerName = apr_pstrdup( p, DEFAULT_SERVERNAME );
03223     config->RealTimeExtensions = NULL;
03224     config->WaitTime = DEFAULT_WAITTIME;
03225     config->BufferSize = DEFAULT_BUFFERSIZE;
03226     config->LineSize = DEFAULT_LINESIZE;
03227     config->SelectionType = DEFAULT_SERVERSELECTION;
03228     config->FragmentSize = DEFAULT_FRAGMENTSIZE;
03229     config->User = apr_pstrdup( p, DEFAULT_USER );
03230     config->Password = apr_pstrdup( p, DEFAULT_USERPASSWORD );
03231     config->ServersFileName = NULL;
03232     config->RedirectName = apr_pstrdup( p, DEFAULT_REDIRECTNAME );
03233     config->TransferName = apr_pstrdup( p, DEFAULT_TRANSFERNAME );
03234     config->MaxLogFileSize = DEFAULT_MAXLOGFILESIZE * 1024;
03235     config->MaxCombinedLogFilesSize = DEFAULT_MAXCOMBINEDLOGFILESSIZE * 1024ull;
03236     config->UserLogName = apr_pstrdup( p, DEFAULT_USERLOGNAME );
03237     config->UserLogsPrefixPath = apr_pstrdup( p, DEFAULT_USERLOGSPREFIXPATH );
03238     config->ExecName = apr_pstrdup( p, DEFAULT_EXECNAME );
03239     config->UserLogPort = DEFAULT_USERLOGPORT;
03240     config->ExecSessionId = DEFAULT_EXECSESSIONID;
03241     config->ExecLogsPrefixPath = apr_pstrdup( p, DEFAULT_EXECLOGSPREFIXPATH );
03242     config->ExecLogPort = DEFAULT_EXECLOGPORT;
03243     // Retorna a estrutura de configuracao criada.
03244     return ( void * ) config;
03245 }

int CreateServerLogsProcess ( apr_pool_t *  pconf,
server_rec *  s,
RioModuleConfig Config,
char *  LogsPrefixPath,
unsigned int  LogPort 
)

Definition at line 2148 of file RioApacheModule.cpp.

02151 {
02152     // Armazena o codigo de erro do apache
02153     apr_status_t ApacheStatus;
02154     // Estrutura para armazenar as informacoes do processo.
02155     apr_proc_t *LogsProcessInfo;
02156     // Armazena o codigo de retorno de uma das funcoes do RIO.
02157     RioResult RioStatus;
02158     // Estruturas para o pipe.
02159     apr_file_t *InPipe, *OutPipe;
02160     // Armazena a quantidade de bytes lidos.
02161     apr_size_t TotalBytes;
02162     // Variavel com as informacoes para o termino.
02163     TFinalizeLogsInfo *LogsInfo;
02164 
02165     // Aloca a estrutura com as informacoes do processo a ser criado.
02166     LogsProcessInfo = ( apr_proc_t * ) apr_palloc( pconf, sizeof( apr_proc_t ) );
02167     if( LogsProcessInfo == NULL )
02168     {
02169         ap_log_error( APLOG_MARK, APLOG_ERR, 0, s,
02170                       "Error when creating process structure!" );
02171 
02172         return 1; // TODO: Descobrir os codigos para erro e ok e usa-los!
02173     }
02174 
02175     // Tenta criar um pipe para ser usado pelos processos.
02176     //ApacheStatus = apr_file_pipe_create_ex( &InPipe, &OutPipe, APR_FULL_BLOCK,
02177     //                                      pconf );
02178     ApacheStatus = apr_file_pipe_create( &InPipe, &OutPipe, pconf );
02179     if( ApacheStatus != APR_SUCCESS )
02180     {
02181         ap_log_error( APLOG_MARK, APLOG_ERR, ApacheStatus, s,
02182                       "Error when creating pipe!" );
02183 
02184         return 1; // TODO: Descobrir os codigos para erro e ok e usa-los!
02185     }
02186 
02187     // Tenta alocar a variavel
02188     LogsInfo = ( TFinalizeLogsInfo * ) apr_palloc( pconf,
02189                                           sizeof( TFinalizeLogsInfo ) );
02190     if( LogsInfo == NULL )
02191     {
02192         ap_log_error( APLOG_MARK, APLOG_ERR, 0, s,
02193                       "Error when allocating memory for user logs "
02194                       "finalization structure!" );
02195 
02196         return 1; // TODO: Descobrir os codigos para erro e ok e usa-los!
02197 
02198     }
02199 
02200     // Tenta criar o processo.
02201     ApacheStatus = apr_proc_fork( LogsProcessInfo, pconf );
02202     if( ( ApacheStatus != APR_INCHILD ) && ( ApacheStatus != APR_INPARENT ) )
02203     {
02204         // Fecha os dois pipes criados
02205         ApacheStatus = apr_file_close( InPipe );
02206 
02207         ap_log_error( APLOG_MARK, APLOG_ERR, ApacheStatus, s,
02208                       "Error when creating userlogs process!" );
02209 
02210         #ifdef RIO_DEBUG2
02211         if( ApacheStatus != APR_SUCCESS )
02212         {
02213             ap_log_error( APLOG_MARK, APLOG_ERR, ApacheStatus, s,
02214                           "Error closing in file of pipe!" );
02215         }
02216         #endif
02217 
02218         ApacheStatus = apr_file_close( OutPipe );
02219 
02220         #ifdef RIO_DEBUG2
02221         if( ApacheStatus != APR_SUCCESS )
02222         {
02223             ap_log_error( APLOG_MARK, APLOG_ERR, ApacheStatus, s,
02224                           "Error closing out file of pipe!" );
02225         }
02226         #endif
02227 
02228         return 1; // TODO: Descobrir os codigos para erro e ok e usa-los!
02229     }
02230 
02231     // Se for o processo pai, devemos esperar pela resposta do processo filho a
02232     // criacao do objeto da classe para o gerenciamento de logs. Se o processo
02233     // for o filho, ele deve criar o objeto, esperar pelo pai, e depois enviar
02234     // o resultado ao processo pai, que estara esperando pelo resultado.
02235     if( ApacheStatus == APR_INPARENT )
02236     {
02237         // Ponteiro para a estrutura passada a funcao de finalizacao.
02238 
02239         // Estamos no processo pai. Espera pela resposta do processo filho sobre
02240         // a criacao do objeto usado para receber os logs.
02241         #ifdef RIO_DEBUG2
02242         ap_log_error( APLOG_MARK, APLOG_ERR, 0, s,
02243                       "Executing parent process. PID = %u (apache pid = %u)",
02244                       getpid(), LogsProcessInfo->pid );
02245         #endif
02246 
02247         // Fecha o pipe de saida (o pai usara somente o pipe de entrada).
02248         ApacheStatus = apr_file_close( OutPipe );
02249 
02250         if( ApacheStatus != APR_SUCCESS )
02251         {
02252             ap_log_error( APLOG_MARK, APLOG_ERR, ApacheStatus, s,
02253                           "Error closing out file of pipe!" );
02254 
02255             return 1; // TODO: Descobrir os codigos para erro e ok e usa-los!
02256         }
02257 
02258         sleep( 3 );
02259 
02260         // Tenta abrir o arquivo associado ao stdout do processo filho,
02261         // definindo o tamanho inicial em TotalBytes.
02262         ApacheStatus = apr_file_read_full( InPipe, ( void * ) &RioStatus,
02263                                            sizeof( RioResult ), &TotalBytes );
02264         if( ( ApacheStatus != APR_SUCCESS ) ||
02265             ( TotalBytes != sizeof( RioResult ) ) )
02266         {
02267             ap_log_error( APLOG_MARK, APLOG_ERR, ApacheStatus, s,
02268                           "Error when reading stdout chid process!" );
02269 
02270             // Fecha os dois pipes criados
02271             ApacheStatus = apr_file_close( InPipe );
02272 
02273             #ifdef RIO_DEBUG2
02274             if( ApacheStatus != APR_SUCCESS )
02275             {
02276                 ap_log_error( APLOG_MARK, APLOG_ERR, ApacheStatus, s,
02277                               "Error closing in file of pipe!" );
02278             }
02279             #endif
02280 
02281             // Mata o processo filho.
02282             kill( LogsProcessInfo->pid, SIGKILL );
02283 
02284             return 1; // TODO: Descobrir os codigos para erro e ok e usa-los!
02285 
02286         }
02287 
02288         // Como recebemos corretamente o codigo pelo pipe, vamos fechar o pipe
02289         // de entrada.
02290         ApacheStatus = apr_file_close( InPipe );
02291 
02292         #ifdef RIO_DEBUG2
02293         if( ApacheStatus != APR_SUCCESS )
02294         {
02295             ap_log_error( APLOG_MARK, APLOG_ERR, ApacheStatus, s,
02296                           "Error closing in file of pipe!" );
02297         }
02298 
02299         ap_log_error( APLOG_MARK, APLOG_ERR, ApacheStatus, s,
02300                       "Recebido o codigo de erro %8X (%s) do processo filho!",
02301                       RioStatus, GetErrorDescription( RioStatus ).c_str() );
02302         #endif
02303 
02304         if( FAILED( RioStatus ) )
02305         {
02306             ap_log_error( APLOG_MARK, APLOG_ERR, ApacheStatus, s,
02307                           "Error %8X (%s) when creating user logs object!",
02308                           RioStatus, GetErrorDescription( RioStatus ).c_str() );
02309 
02310             return 1; // TODO: Descobrir os codigos para erro e ok e usa-los!
02311         }
02312         else
02313         {
02314             // Coloca a funcao de termino no pool associado a configuracao.
02315             LogsInfo->LogsServerPort = LogPort;
02316             LogsInfo->ProcessInfo = LogsProcessInfo;
02317             apr_pool_cleanup_register( pconf, ( void * ) LogsInfo,
02318                                        RioModuleTerminateServerUserLogs,
02319                                        apr_pool_cleanup_null );
02320         }
02321     }
02322     else
02323     {
02324         // Estamos no processo filho. Deveremos criar o objeto de logs, enviar o
02325         // estado da criacao ao processo pai e, em caso de sucesso, dar um join
02326         // na thread, esperando pelo termino do apache.
02327 
02328         // Armazena o ponteiro para a classe de logs a ser criada.
02329         CServerUserLogs *ServerUserLogs;
02330 
02331         #ifdef RIO_DEBUG2
02332         ap_log_error( APLOG_MARK, APLOG_ERR, 0, s,
02333                       "Executing child process. PID = %u (apache pid = %u)",
02334                       getpid(), LogsProcessInfo->pid );
02335         #endif
02336 
02337         // Diz para o novo processo ignorar o sinal SIGTERM
02338         signal( SIGTERM, SIG_IGN );
02339 
02340         // Fecha o pipe de saida (o pai usara somente o pipe de entrada).
02341         ApacheStatus = apr_file_close( InPipe );
02342 
02343         if( ApacheStatus != APR_SUCCESS )
02344         {
02345             ap_log_error( APLOG_MARK, APLOG_ERR, ApacheStatus, s,
02346                           "Error closing in file of pipe!" );
02347         }
02348 
02349         // Inicializa o codigo de erro retornado.
02350         RioStatus = S_OK;
02351 
02352         // Inicializa o ponteiro para o objeto de gerenciamento dos logs.
02353         ServerUserLogs = NULL;
02354 
02355         // Tenta criar um objeto da classe.
02356         try
02357         {
02358             // Tenta criar o objeto da classe CServerUserLogs.
02359             ServerUserLogs = new CServerUserLogs( s );
02360 
02361             #ifdef RIO_DEBUG2
02362             ap_log_error( APLOG_MARK, APLOG_ERR, 0, s, "Objeto criado com "
02363                            "sucesso! Tentando inicializar o objeto!" );
02364 
02365             #endif
02366 
02367             // Se o objeto foi criado com sucesso, tenta entao inicializa-lo.
02368             RioStatus = ServerUserLogs->Initialize( LogsPrefixPath,
02369                                                     Config->MaxLogFileSize,
02370                                                 Config->MaxCombinedLogFilesSize,
02371                                                     LogPort );
02372             if( FAILED( RioStatus ) )
02373             {
02374                 ap_log_error( APLOG_MARK, APLOG_ERR, 0, s,
02375                               "Error %8X (%s) when initializing "
02376                               "CServerUserLogs object!", RioStatus,
02377                               GetErrorDescription( RioStatus ).c_str() );
02378                 delete ServerUserLogs;
02379             }
02380             else
02381             {
02382                 #ifdef RIO_DEBUG2
02383                 ap_log_error( APLOG_MARK, APLOG_ERR, 0, s,
02384                               "Objeto inicializado com sucesso! Tentando "
02385                               "obter o IP associado ao socket UDP!" );
02386                 #endif
02387             }
02388 
02389         }
02390         catch( bad_alloc &ba )
02391         {
02392             // Define o estado do RIO como de erro de memoria.
02393             RioStatus = ERROR_RIOMODULE + ERROR_MEMORY;
02394 
02395             ap_log_error( APLOG_MARK, APLOG_ERR, 0, s,
02396                           "Error bad_alloc (%s) when creating CServerUserLogs "
02397                           "object!", ba.what() );
02398         }
02399 
02400         // Enviamos o status ao servidor pelo pipe compartilhado.
02401         // Tenta abrir o arquivo associado ao stdout do processo filho,
02402         // definindo o tamanho inicial em TotalBytes.
02403         ApacheStatus = apr_file_write_full( OutPipe, ( void * ) &RioStatus,
02404                                             sizeof( RioResult ), &TotalBytes );
02405         if( ( ApacheStatus != APR_SUCCESS ) ||
02406             ( TotalBytes != sizeof( RioResult ) ) )
02407         {
02408             // Deleta o ojeto responsavel pelo gerenciamento dos logs.
02409             if( ServerUserLogs != NULL )
02410                 delete ServerUserLogs;
02411 
02412             // Fecha o pipe usado para enviar dados.
02413             ApacheStatus = apr_file_close( OutPipe );
02414 
02415             #ifdef RIO_DEBUG2
02416             if( ApacheStatus != APR_SUCCESS )
02417             {
02418                 ap_log_error( APLOG_MARK, APLOG_ERR, ApacheStatus, s,
02419                               "Error closing out file of pipe!" );
02420             }
02421             #endif
02422 
02423             ap_log_error( APLOG_MARK, APLOG_ERR, ApacheStatus, s,
02424                           "Error when reading stdout child process!" );
02425 
02426             exit( -1 );
02427         }
02428 
02429         // Da um flush em OutPipe.
02430         ApacheStatus = apr_file_flush( OutPipe );
02431         if( ApacheStatus != APR_SUCCESS )
02432         {
02433             ap_log_error( APLOG_MARK, APLOG_ERR, ApacheStatus, s,
02434                           "Error when flushing out chid process!" );
02435 
02436             // Deleta o ojeto responsavel pelo gerenciamento dos logs.
02437             if( ServerUserLogs != NULL )
02438                 delete ServerUserLogs;
02439 
02440             // Fecha o pipe usado para enviar dados.
02441             ApacheStatus = apr_file_close( OutPipe );
02442 
02443             #ifdef RIO_DEBUG2
02444             if( ApacheStatus != APR_SUCCESS )
02445             {
02446                 ap_log_error( APLOG_MARK, APLOG_ERR, ApacheStatus, s,
02447                               "Error closing out file of pipe!" );
02448             }
02449             #endif
02450 
02451             exit( -1 );
02452         }
02453 
02454         // Como enviamos corretamente o codigo pelo pipe, vamos fechar o
02455         // descritor usado para enviar dados pelo pipe.
02456         ApacheStatus = apr_file_close( OutPipe );
02457 
02458         #ifdef RIO_DEBUG2
02459         if( ApacheStatus != APR_SUCCESS )
02460         {
02461             ap_log_error( APLOG_MARK, APLOG_ERR, ApacheStatus, s,
02462                           "Error closing out file of pipe!" );
02463         }
02464         #endif
02465 
02466         // Se nenhum ocorreu, esperamos pelo termino da thread.
02467         ServerUserLogs->JoinThread();
02468 
02469         // Termina a execucao do processo.
02470         exit( 0 );
02471     }
02472 
02473     return 0; // TODO: Descobrir os codigos para erro e ok e usa-los!
02474 }

int ProcessExec ( request_rec *  r,
RioModuleConfig Config,
apr_table_t *  ParamTable,
apr_status_t *  ApacheError,
int *  SystemError,
RioResult RioError 
)

Definition at line 1217 of file RioApacheModule.cpp.

01220 {
01221     // Armazena o ponteiro para a estrutura com as informacoes usadas pela
01222     // opcao "exec.rio". Nesta estrutura existira um campo para armazenar o
01223     // o ponteiro para o objeto da classe CServerInterface, com a sessao usada.
01224     TRioExecInfo *RioExecInfo;
01225     // Armazena o ponteiro do tipo void * (que deve ser convetido para o
01226     // ponteiro acima.
01227     void *Data;
01228     // Armazena um ponteiro para a opcao com o comando. Sera necessario
01229     // processar a opcao, porque o comando estara entre aspas na opcao.
01230     const char *SAux;
01231     // Armazena o comando apos o processamento.
01232     char *Command;
01233     // Variavel booleana indicando se devemos ou nao remover o objeto apos
01234     // executar um comando.
01235     bool RemoveObject;
01236     // Retorno da funcao para o apache2
01237     int HttpResult;
01238     // Ponteiros para o inicio e o fim do comando (ponteiro para depois da
01239     // primeira aspas e para antes do final da ultima aspas.
01240     const char *StartCommand, *EndCommand;
01241     // Tamanho em bytes do comando.
01242     unsigned int CommandSize;
01243     // Armazena o identificador da sessao lido do comando.
01244     unsigned int SessionId;
01245     // Armazena um ponteiro para o identificador da sessao. Este ponteiro sera
01246     // usado, ao executar os comandos, para verificarmos se a opcao "sessionid"
01247     // foi definida e, caso a opcao seja definida, apontara para SessionId e,
01248     // em caso contrario, sera igual a NULL.
01249     unsigned int *PSessionId;
01250 
01251     // Inicializa os erros passados como parametro.
01252     *ApacheError = APR_SUCCESS;
01253     *SystemError = 0;
01254     *RioError = S_OK;
01255 
01256     // Verifica se temos algum parametro e, caso existam, se temos a opcao
01257     // "command" com a linha do log.
01258     if( ParamTable != NULL )
01259     {
01260         // Busca pela opcao do identificador da sessao. Esta opcao
01261         SAux = apr_table_get( ParamTable, "sessionid" );
01262         if( ( SAux == NULL ) || ( strlen( SAux ) == 0 ) )
01263         {
01264             #ifdef RIO_DEBUG2
01265             ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r,
01266                            "Warning: no sessionid defined" );
01267             #endif
01268 
01269             // Como a opcao sessionId nao foi definida, setamos o ponteiro para
01270             // NULL.
01271             PSessionId = NULL;
01272         }
01273         else
01274         {
01275             // Converte a session ID para um valor inteiro.
01276             SessionId = atol( SAux );
01277             // Faz o ponteiro apontar para SessionId.
01278             PSessionId = &SessionId;
01279         }
01280 
01281         // Busca pela opcao com o comando a ser executado
01282         // Verifica se temos o parametro file (obrigatorio).
01283         SAux = apr_table_get( ParamTable, "command" );
01284         if( ( SAux == NULL ) || ( strlen( SAux ) == 0 ) )
01285         {
01286             #ifdef RIO_DEBUG2
01287             ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r,
01288                            "Error: no command defined" );
01289             #endif
01290             *RioError = ERROR_RIOMODULE + ERROR_COMMAND_NOT_DEFINED;
01291 
01292             // Gera o XML com o erro
01293             CServerInterface::GenerateXMLError( r, *ApacheError, *SystemError,
01294                                                 *RioError );
01295 
01296             // Gera a linha de log.
01297             CServerInterface::SaveExecLogLineError( r, *ApacheError,
01298                                                     *SystemError, *RioError,
01299                                                     "<command not available>",
01300                                                     Config->ExecLogPort );            return OK;
01301         }
01302         else
01303         {
01304             // Procura pelo aspas inicial.
01305             StartCommand = strchr( SAux, '\"');
01306             if( StartCommand == NULL )
01307             {
01308                 // Se nao existirem aspas, entao o comando e a string dada em
01309                 // command.
01310                 StartCommand = SAux;
01311                 CommandSize = strlen( SAux );
01312             }
01313             else
01314             {
01315                 // Temos uma aspas no inicio. Procuramos agora pela ultima aspas
01316                 // da string (note que isso permite comandos que usem aspas
01317                 // internamente).
01318                 EndCommand = strrchr( SAux, '\"' );
01319                 // Se a aspas foi a que ja achamos (note que o retorno nao
01320                 // podera ser NULL, porque ja achamos uma aspa), entao o final
01321                 // do comando sera o final da string;
01322                 if( EndCommand == StartCommand )
01323                 {
01324                     // Se tivermos somente uma aspas, entao a ignoramos. Neste
01325                     // caso, o tamanho sera igual ao restante da string apos
01326                     // a aspa.
01327                     StartCommand = &StartCommand[ 1 ]; // ignora a aspa inicial.
01328                     CommandSize = strlen( StartCommand );
01329                 }
01330                 else
01331                 {
01332                     // temos as aspas iniciais e finais. Neste caso, o inicio
01333                     // do comando tambem sera em &StartCommand[ 1 ], mas o
01334                     // tamanho do comando sera dado por
01335                     // EndCommand - StartCommand (nao e necessario somar um na
01336                     // equacao a seguir, porque EndCommand aponta para a aspa
01337                     // final).
01338                     StartCommand = &StartCommand[ 1 ]; // ignora a aspa inicial.
01339                     CommandSize = EndCommand - StartCommand;
01340                 }
01341             }
01342 
01343             // Aloca espaco para a string do comando. O tamanho alocado sera
01344             // CommandSize mais 1 devido ao caractere terminador.
01345             Command = ( char * ) apr_pcalloc( r->pool, CommandSize + 1 );
01346             if( Command == NULL )
01347             {
01348                 *SystemError = ENOMEM;
01349 
01350                 #ifdef RIO_DEBUG2
01351                 ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r,
01352                                "Insufficient memory to create the command!" );
01353                 #endif
01354 
01355                 // Gera o XML com o erro
01356                 CServerInterface::GenerateXMLError( r, *ApacheError,
01357                                                     *SystemError, *RioError );
01358 
01359                 // Gera a linha de log.
01360                 CServerInterface::SaveExecLogLineError( r, *ApacheError,
01361                                                         *SystemError, *RioError,
01362                                                       "<command not available>",
01363                                                         Config->ExecLogPort );            return OK;
01364                 return OK;
01365             }
01366             // Copia a string do comando.
01367             strncpy( Command, StartCommand, CommandSize );
01368             // Adiciona o terminador a string do comando.
01369             Command[ CommandSize ] = 0;
01370         }
01371 
01372         #ifdef RIO_DEBUG2
01373         ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r, "command param = %s, "
01374                        "module command = %s", SAux, Command );
01375         #endif
01376 
01377     }
01378     else
01379     {
01380         #ifdef RIO_DEBUG2
01381         ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r, "Nao foi definida nenhuma "
01382                        "opcao: nem a com o command com o comando a ser "
01383                        "executado, e nem a com o identificador da sessao!" );
01384         #endif
01385 
01386         // Nao temos uma opcao com o comando a ser executado.
01387         *RioError = ERROR_RIOMODULE + ERROR_COMMAND_NOT_DEFINED;
01388 
01389         // Gera o XML com o erro
01390         CServerInterface::GenerateXMLError( r, *ApacheError, *SystemError,
01391                                             *RioError );
01392 
01393         // Gera a linha de log.
01394         CServerInterface::SaveExecLogLineError( r, *ApacheError,
01395                                                 *SystemError, *RioError,
01396                                                 "<command not available>",
01397                                                 Config->ExecLogPort );            return OK;
01398         return OK;
01399     }
01400 
01401     // Depois de processar a linha de comando, verificamos se a conexao e
01402     //segura.
01403     if( apr_strnatcmp( ap_http_scheme( r ), "https" ) != 0 )
01404     {
01405         #ifdef RIO_DEBUG2
01406         ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r,
01407                        "Connection is not secure!" );
01408         #endif
01409 
01410         *RioError = ERROR_RIOMODULE + ERROR_HTTPS_REQUIRED;
01411 
01412         // Gera o XML com o erro
01413         CServerInterface::GenerateXMLError( r, *ApacheError, *SystemError,
01414                                             *RioError );
01415 
01416         // Gera a linha de log.
01417         CServerInterface::SaveExecLogLineError( r, *ApacheError,
01418                                                 *SystemError, *RioError,
01419                                                 Command, Config->ExecLogPort );
01420 
01421         return OK;
01422     }
01423 
01424     // Obtem o ponteiro do objeto da classe ServerInterface (se o retorno for
01425     // NULL, ou seja, se o objeto nao foi criado, entao deveremos cria-lo e
01426     // criar a chave com o ponteiro do objeto recem-criado). Caso contrario,
01427     // deveremos usar o ponteiro passado como parametro. Na primeira execucao
01428     // da funcao a seguir, Data sera NULL porque a chave nao tera sido criada,
01429     // mas nas outras execucoes sera NULL porque de fato o valor do ponteiro
01430     // sera NULL.
01431     *ApacheError =  apr_pool_userdata_get( &Data, SERVERINTERFACEOBJECTPOINTER,
01432                                            r->connection->pool );
01433     if( *ApacheError != APR_SUCCESS )
01434     {
01435         #ifdef RIO_DEBUG2
01436         ap_log_rerror( APLOG_MARK, APLOG_ERR, *ApacheError, r,
01437                        "Erro ao obter o ponteiro do objeto com a possivel "
01438                        "sessao ativa!");
01439         #endif
01440 
01441         // Gera o XML com o erro
01442         CServerInterface::GenerateXMLError( r, *ApacheError, *SystemError,
01443                                             *RioError );
01444 
01445         // Gera a linha de log.
01446         CServerInterface::SaveExecLogLineError( r, *ApacheError,
01447                                                 *SystemError, *RioError,
01448                                                 Command, Config->ExecLogPort );
01449 
01450         return OK;
01451     }
01452 
01453     // Se Data for NULL nenhuma estrutura foi criado e, se for diferente de
01454     // NULL, a estrutura foi criada e Data contem o ponteiro para a estrutura.
01455 
01456     if( Data == NULL )
01457     {
01458         #ifdef RIO_DEBUG2
01459         ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r,
01460                        "Tentando criar a estutura para armazenar as "
01461                        "informacoes da opcao \"%s\"!", Config->ExecName );
01462         #endif
01463 
01464         // Tenta criar o novo objeto da classe.
01465         try
01466         {
01467             RioExecInfo = new TRioExecInfo;
01468         }
01469         catch( bad_alloc &ba )
01470         {
01471             *SystemError = ENOMEM;
01472 
01473             #ifdef RIO_DEBUG2
01474             ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r,
01475                            "Insufficient memory (bad_alloc, error=%s) to "
01476                            "create a instance of TRioExecInfo structure!",
01477                            ba.what() );
01478             #endif
01479 
01480             // Gera o XML com o erro
01481             CServerInterface::GenerateXMLError( r, *ApacheError, *SystemError,
01482                                                 *RioError );
01483 
01484             // Gera a linha de log.
01485             CServerInterface::SaveExecLogLineError( r, *ApacheError,
01486                                                     *SystemError, *RioError,
01487                                                     Command,
01488                                                     Config->ExecLogPort );
01489 
01490             return OK;
01491         }
01492 
01493         // Inicializa os campos da estrutura recem-criada.
01494         RioExecInfo->ServerInterface = NULL;
01495         RioExecInfo->LocalPort = r->connection->local_addr->port;
01496         RioExecInfo->LocalIP = r->connection->local_addr->
01497                                                          sa.sin.sin_addr.s_addr;
01498         RioExecInfo->RemotePort = r->connection->remote_addr->port;
01499         RioExecInfo->RemoteIP = r->connection->remote_addr->
01500                                                          sa.sin.sin_addr.s_addr;
01501 
01502         #ifdef RIO_DEBUG2
01503         ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r,
01504                        "Tentando criar a chave %s com a estrutura com as "
01505                        "informacoes da opcao \"%s\"!",
01506                        SERVERINTERFACEOBJECTPOINTER, Config->ExecName );
01507         #endif
01508         // Cria uma chave para o ponteiro do objeto recem-criado e inicializado.
01509         *ApacheError =  apr_pool_userdata_set( ( const void * ) RioExecInfo,
01510                                                SERVERINTERFACEOBJECTPOINTER,
01511                                                RioModuleDestroyServerInterface,
01512                                                r->connection->pool );
01513         if( *ApacheError != APR_SUCCESS )
01514         {
01515             #ifdef RIO_DEBUG2
01516             ap_log_rerror( APLOG_MARK, APLOG_ERR, *ApacheError, r,
01517                            "Erro ao salvar o ponteiro da estrutura com as "
01518                            "informacoes da opcao \"%s\"!", Config->ExecName );
01519             #endif
01520 
01521             // Remove a estrutura criada.
01522             delete RioExecInfo;
01523 
01524             #ifdef RIO_DEBUG2
01525             ap_log_rerror( APLOG_MARK, APLOG_ERR, *ApacheError, r,
01526                            "Error when creating object pointer key!" );
01527             #endif
01528 
01529             // Gera o XML com o erro
01530             CServerInterface::GenerateXMLError( r, *ApacheError, *SystemError,
01531                                                 *RioError );
01532 
01533             // Gera a linha de log.
01534             CServerInterface::SaveExecLogLineError( r, *ApacheError,
01535                                                     *SystemError, *RioError,
01536                                                     Command,
01537                                                     Config->ExecLogPort );
01538 
01539             return OK;
01540         }
01541     }
01542     else
01543     {
01544         // A estrutura ja foi criada entao basta usarmos o ponteiro para ela.
01545         RioExecInfo = ( TRioExecInfo * ) Data;
01546         // Verifica as portas e IPs (locais e remotos).
01547         // Obs: Eu acho que o "local" e o IP e a porta do servidor apache usado
01548         // ao estabelecer a conexao e o "remoto" e o IP e a porta retornado pelo
01549         // accept.
01550 
01551         // Porta local.
01552         if( RioExecInfo->LocalPort != r->connection->local_addr->port )
01553         {
01554             #ifdef RIO_DEBUG2
01555             ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r,
01556                            "Incorret local port %u found! Port must be %u!",
01557                            r->connection->local_addr->port,
01558                            RioExecInfo->LocalPort );
01559             #endif
01560 
01561             // TODO: o que devemos fazer neste caso? Retornar um XML ou dar um
01562             // erro do http? Eu acho melhor usar o codigo http (mas eu deixei a
01563             // opcao de usar o XML comentada!).
01564 
01565             // Gera o XML com o erro
01566             *RioError = ERROR_RIOMODULE + ERROR_INVALID_HOST;
01567             CServerInterface::GenerateXMLError( r, *ApacheError, *SystemError,
01568                                                 *RioError );
01569 
01570             // Gera a linha de log.
01571             CServerInterface::SaveExecLogLineError( r, *ApacheError,
01572                                                     *SystemError, *RioError,
01573                                                     Command,
01574                                                     Config->ExecLogPort );
01575 
01576         }
01577 
01578         // IP local.
01579         if( RioExecInfo->LocalIP !=
01580             r->connection->local_addr->sa.sin.sin_addr.s_addr )
01581         {
01582             #ifdef RIO_DEBUG2
01583             in_addr IP;
01584             IP.s_addr = RioExecInfo->LocalIP;
01585             ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r,
01586                            "Incorret local IP %s found! IP must be %s!",
01587                            inet_ntoa( r->connection->local_addr->
01588                                       sa.sin.sin_addr ),
01589                            inet_ntoa( IP ) );
01590             #endif
01591 
01592             // TODO: o que devemos fazer neste caso? Retornar um XML ou dar um
01593             // erro do http? Eu acho melhor usar o codigo http (mas eu deixei a
01594             // opcao de usar o XML comentada!).
01595 
01596             // Gera o XML com o erro
01597             *RioError = ERROR_RIOMODULE + ERROR_INVALID_HOST;
01598             CServerInterface::GenerateXMLError( r, *ApacheError, *SystemError,
01599                                                 *RioError );
01600 
01601             // Gera a linha de log.
01602             CServerInterface::SaveExecLogLineError( r, *ApacheError,
01603                                                     *SystemError, *RioError,
01604                                                     Command,
01605                                                     Config->ExecLogPort );
01606 
01607         }
01608 
01609         // Porta remota.
01610         if( RioExecInfo->RemotePort != r->connection->remote_addr->port )
01611         {
01612             #ifdef RIO_DEBUG2
01613             ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r,
01614                            "Incorret remote port %u found! Port must be %u!",
01615                            r->connection->remote_addr->port,
01616                            RioExecInfo->RemotePort );
01617             #endif
01618 
01619             // TODO: o que devemos fazer neste caso? Retornar um XML ou dar um
01620             // erro do http? Eu acho melhor usar o codigo http (mas eu deixei a
01621             // opcao de usar o XML comentada!).
01622 
01623             // Gera o XML com o erro
01624             *RioError = ERROR_RIOMODULE + ERROR_INVALID_HOST;
01625             CServerInterface::GenerateXMLError( r, *ApacheError, *SystemError,
01626                                                 *RioError );
01627 
01628             // Gera a linha de log.
01629             CServerInterface::SaveExecLogLineError( r, *ApacheError,
01630                                                     *SystemError, *RioError,
01631                                                     Command,
01632                                                     Config->ExecLogPort );
01633 
01634         }
01635 
01636         // IP remoto.
01637         if( RioExecInfo->RemoteIP !=
01638             r->connection->remote_addr->sa.sin.sin_addr.s_addr )
01639         {
01640             #ifdef RIO_DEBUG2
01641             in_addr IP;
01642             IP.s_addr = RioExecInfo->RemoteIP;
01643             ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r,
01644                            "Incorret remote IP %s found! IP must be %s!",
01645                            inet_ntoa( r->connection->remote_addr->
01646                                       sa.sin.sin_addr ) ,
01647                            inet_ntoa( IP ) );
01648             #endif
01649 
01650             // TODO: o que devemos fazer neste caso? Retornar um XML ou dar um
01651             // erro do http? Eu acho melhor usar o codigo http (mas eu deixei a
01652             // opcao de usar o XML comentada!).
01653 
01654             // Gera o XML com o erro
01655             *RioError = ERROR_RIOMODULE + ERROR_INVALID_HOST;
01656             CServerInterface::GenerateXMLError( r, *ApacheError, *SystemError,
01657                                                 *RioError );
01658 
01659             // Gera a linha de log.
01660             CServerInterface::SaveExecLogLineError( r, *ApacheError,
01661                                                     *SystemError, *RioError,
01662                                                     Command,
01663                                                     Config->ExecLogPort );
01664 
01665         }
01666 
01667         #ifdef RIO_DEBUG2
01668         ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r,
01669                        "Corret port %u found! Executing command %s!",
01670                        RioExecInfo->LocalPort, Command );
01671         #endif
01672     }
01673 
01674     // Agora vamos verificar se precisamos criar o objeto com a sessao. Se o
01675     // campo ServerInterface da estrutura apontada por RioExecInfo for NULL,
01676     // entao o objeto ainda nao foi criado e a sessao ainda nao foi inicializada
01677     // e precisaremos criar o objeto e inicializar a sessao. Caso contrario,
01678     // simplesmente usaremos o objeto dado pelo ponteiro para executar o
01679     // comando.
01680     if( RioExecInfo->ServerInterface == NULL )
01681     {
01682         #ifdef RIO_DEBUG2
01683         ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r,
01684                        "Tentando criar o objeto que executara os comandos "
01685                        "similares ao do riosh!");
01686         #endif
01687 
01688         // Tenta criar o novo objeto da classe.
01689         try
01690         {
01691             RioExecInfo->ServerInterface = new CServerInterface( r->server );
01692         }
01693         catch( bad_alloc &ba )
01694         {
01695             *SystemError = ENOMEM;
01696 
01697             // Define que o objeto para executar os comandos nao foi criado.
01698             RioExecInfo->ServerInterface = NULL;
01699 
01700             #ifdef RIO_DEBUG2
01701             ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r,
01702                            "Insufficient memory (bad_alloc, error=%s) to "
01703                            "create a instance of CServerInterface class!",
01704                            ba.what() );
01705             #endif
01706 
01707             // Gera o XML com o erro
01708             CServerInterface::GenerateXMLError( r, *ApacheError, *SystemError,
01709                                                 *RioError );
01710 
01711             // Gera a linha de log.
01712             CServerInterface::SaveExecLogLineError( r, *ApacheError,
01713                                                     *SystemError, *RioError,
01714                                                     Command,
01715                                                     Config->ExecLogPort );
01716 
01717             return OK;
01718         }
01719 
01720         // Tenta inicializar o objeto da classe.
01721         //
01722         #ifdef RIO_DEBUG2
01723         ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r,
01724                        "Tentando inicializar o objeto que executara os comandos "
01725                        "similares ao do riosh!");
01726         #endif
01727         // Obs: Se decidirmos fazer Config->ServerName ser NULL quando nao
01728         // usarmos a opcao ServerName, precisaremos verificar isso neste ponto.
01729         if( !RioExecInfo->ServerInterface->Start( Config->ServerName,
01730                                                   Config->BufferSize,
01731                                                   Config->FragmentSize,
01732                                                   Config->ExecSessionId,
01733                                                   Config->ExecLogPort ) )
01734         {
01735             // Obtem os erros gerados pela classe.
01736             RioExecInfo->ServerInterface->GetErrors( ApacheError, SystemError,
01737                                                      RioError );
01738 
01739             // Gera o XML com o erro
01740             CServerInterface::GenerateXMLError( r, *ApacheError, *SystemError,
01741                                                 *RioError );
01742 
01743             // Gera a linha de log.
01744             CServerInterface::SaveExecLogLineError( r, *ApacheError,
01745                                                     *SystemError, *RioError,
01746                                                     Command,
01747                                                     Config->ExecLogPort );
01748 
01749             // Remove o objeto criado.
01750             delete RioExecInfo->ServerInterface;
01751             RioExecInfo->ServerInterface = NULL;
01752 
01753             #ifdef RIO_DEBUG2
01754             ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r,
01755                            "Error when starting CServerInstance object!" );
01756             #endif
01757 
01758             return OK;
01759         }
01760     }
01761     else
01762     {
01763         #ifdef RIO_DEBUG2
01764         ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r,
01765                       "Sessao ativa achada! Usando esta sessao para executar "
01766                       "o comando %s", Command );
01767         #endif
01768     }
01769 
01770     #ifdef RIO_DEBUG2
01771     ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r,
01772                    "Tentando executar o comando %s!", Command );
01773     #endif
01774 
01775     // Agora que temos um objeto valido e inicializado, e que temos uma opcao de
01776     // comando valida, entao vamos tentar executar o comando.
01777     HttpResult = RioExecInfo->ServerInterface->ExecuteCommands( r, Command,
01778                                                                 &RemoveObject,
01779                                                                 PSessionId );
01780 
01781     // Obtem os erros ao executar a funcao.
01782     RioExecInfo->ServerInterface->GetErrors( ApacheError, SystemError,
01783                                              RioError );
01784 
01785     // Remove o objeto, se for necessario.
01786     if( RemoveObject )
01787     {
01788         // Para o objeto.
01789         if( !RioExecInfo->ServerInterface->Stop() )
01790         {
01791             // Obtem os erros gerados pela classe .
01792             RioExecInfo->ServerInterface->GetErrors( ApacheError, SystemError,
01793                                                      RioError );
01794 
01795             #ifdef RIO_DEBUG2
01796             ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r,
01797                            "Error when stopping CServerInstance object!" );
01798             #endif
01799         }
01800 
01801         // Remove o objeto criado.
01802         delete RioExecInfo->ServerInterface;
01803         RioExecInfo->ServerInterface = NULL;
01804     }
01805 
01806     // Retorna o codigo de erro da funcao.
01807     return HttpResult;
01808 }

int ProcessFileOptions ( request_rec *  r,
RioModuleConfig Config,
apr_table_t *  ParamTable,
bool  UseRedirect,
apr_status_t *  ApacheError,
int *  SystemError,
RioResult RioError 
)

Definition at line 803 of file RioApacheModule.cpp.

00807 {
00808     // Armazena o ponteiro para o servidor a ser usado para copiar o arquivo,
00809     // para o nome do usuario neste servidor e para a senha deste usuario.
00810     char *ServerName;
00811     // Armazena um ponteiro para o nome do arquivo a ser acessado.
00812     const char *FileName = NULL;
00813     // Variavel booleana usada para indicar se algum erro ocorreu.
00814     bool NoError = true;
00815     // Armazena o ponteiro para a string com o deslocamento que usaremos para
00816     // obter StartPosition e EndPosition. A string e usada para convertermos
00817     // um destes valores para um inteiro.
00818     const char *StrPosition;
00819     // Posicao inicial a partir da qual iniciamos a transferencia do arquivo
00820     // (somente leitura).
00821     RioObjectSize StartPosition = 0;
00822     // Ultima posicao a enviar do arquivo (somente leitura).
00823     RioObjectSize EndPosition = -1;
00824     // Variavel booleana usada para indicar se devemos enviar um cabecalho, se
00825     // necessario, quando estamos enviando um arquivo de video para o cliente a
00826     // a partir de uma posicao que nao e a inicial (StartPosition > 0).
00827     bool SendHeader = false;
00828     // Ponteiro para a string que armazena o nome da nova URL.
00829     char *NewURL;
00830     // Variavel para armazenar o modo de escolha do servidor. Se UseRedirect for
00831     // igual a true, sera uma copia de Config->SelectionType. Porem, se
00832     // UseRedirect for false, sera igual a RIO_SELECTION_FIRST.
00833     ServerSelectionType SelectionType;
00834     // Variavel usada para retornar o resultado do tratamento do pedido ao
00835     // apache
00836     int RequestResult = OK;
00837     // Variavel para armazenar o identificador para o tipo de conexao (http ou
00838     // https).
00839     const char *HttpScheme;
00840 
00841     // Inicializa os erros passados como parametro.
00842     *ApacheError = APR_SUCCESS;
00843     *SystemError = 0;
00844     *RioError = S_OK;
00845 
00846     // Tenta processar a leitura do arquivo com as configuracoes dos servidores.
00847     if( Config->ServersFileName != NULL )
00848     {
00849         // Inicializa o ponteiro ServerName.
00850         ServerName = NULL;
00851         // O tipo de selecao dependera de usarmos ou nao a redirecao. Se a
00852         // redirecao estiver habilitada, sera o valor de Config->SelectionType.
00853         // Porem, se a redirecao nao estiver sendo usada, sera o valor
00854         // RIO_SELECTION_FIRST, usado para escolher o primeiro servidor do
00855         // arquivo de configuracao.
00856         if( UseRedirect )
00857             SelectionType = Config->SelectionType;
00858         else
00859         {
00860             SelectionType = RIO_SELECTION_FIRST;
00861             // Verifica se Config->ServerName e diferente de DEFAULT_SERVERNAME
00862             // e, caso seja, faz ServerName apontar para o mesmo endereco de
00863             // Config->ServerName, com o nome do servidor para ser usado com o
00864             // comando para transferir diretamente o arquivo.
00865             if( strcmp( Config->ServerName, DEFAULT_SERVERNAME ) != 0 )
00866                 ServerName = Config->ServerName;
00867         }
00868 
00869         // Somente usa o primeiro nome da lista se o parametro ServerName for
00870         // igual a NULL (o parametro somente sera diferente de NULL, como
00871         // podemos ver acima, se UseRedirect for false e Config->ServerName nao
00872         // for igual a DEFAULT_SERVERNAME.
00873         if( ServerName == NULL )
00874             NoError = ProcessServersFile( r, Config, SelectionType, &ServerName,
00875                                           ApacheError, SystemError, RioError );
00876     }
00877     else
00878     {
00879         // Se o arquivo nao existir, usamos entao usaremos o servidor, o usuario
00880         // a senha deste usuario, se devemos usar a copia em tempo real e o
00881         // tempo de espera pelo bloco defaults dados no arquivo de configuracao.
00882         ServerName = Config->ServerName;
00883     }
00884 
00885     // Tenta enviar o arquivo ou redirecionar o pedido, de acordo com
00886     // o valor de UseRedirect (somente se NoError e false).
00887     if( NoError )
00888     {
00889         if( UseRedirect )
00890         {
00891             // Neste caso deveremos usar a redirecao. Primeiramente deveremos
00892             // construir a nova URL, colocala na chave Location da tabela com
00893             // os cabecalhos de saida da requisicao e finalmente retornar com
00894             // HTTP_MOVED_TEMPORARILY, para informar ao apache que a nova URL
00895             // e a dada em Location.
00896 
00897             // Descobre o tipo de http (http ou https).
00898             HttpScheme = ap_http_scheme( r );
00899 
00900             // Calcula o tamanho da nova URL:
00901             //
00902             // <HttpScheme>://<ServerName>/<Config->TransferName>.rio?r->args +
00903             // '\0'.
00904             //
00905             // Tamanho:
00906             //
00907             // strlen( HttpScheme ) + 3 + strlen( ServerName ) + 1 +
00908             // strlen( Config->TransferName ) + 5 + strlen( r->arqs ) + 1.
00909             //
00910             NewURL = ( char * ) apr_pcalloc( r->pool, strlen( HttpScheme ) +
00911                                              strlen( ServerName ) +
00912                                              strlen( Config->TransferName ) +
00913                                              strlen( r->args ) + 10 );
00914             if( NewURL == NULL )
00915             {
00916                 *SystemError = ENOMEM;
00917 
00918                 #ifdef RIO_DEBUG2
00919                 ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r,
00920                                "Insufficient memory to create the redirect "
00921                                "URL: SystemError = %u (%s)", *SystemError,
00922                                strerror( *SystemError ) );
00923                 #endif
00924             }
00925             else
00926             {
00927                 // Monta a nova URL.
00928                 sprintf( NewURL, "%s://%s/%s.rio?%s", HttpScheme, ServerName,
00929                          Config->TransferName, r->args );
00930 
00931                 // Redireciona a URL, colocando a nova URL no campo Location da
00932                 // tabela r->headers_out com os cabecalhos de saida, e
00933                 // retornando o erro HTTP_MOVED_TEMPORARILY, que fara com que o
00934                 // apache informe ao cliente que ocorreu uma redirecao, e que a
00935                 // Nova URL e dada no campo Location do cabecalho da resposta.
00936                 #ifdef RIO_DEBUG2
00937                 ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r,
00938                                "Redirecionando pedido para a URI %s", NewURL );
00939                 #endif
00940 
00941                 // Coloca a nova URL no pedido
00942                 apr_table_set( r->headers_out, "Location", NewURL );
00943 
00944                 // Informa ao apache que o pedido foi redirecionado.
00945                 RequestResult = HTTP_MOVED_TEMPORARILY;
00946             }
00947         }
00948         else
00949         {
00950             // Neste caso vamos enviar o arquivo. Logo, precisamos ter, pelo
00951             // menos, a opcao "file=arquivo" com o caminho de um arquivo.
00952             if( ParamTable != NULL )
00953             {
00954                 #ifdef RIO_DEBUG2
00955                 // Imprime a tabela com os pametros (para depuracao).
00956                 ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r,
00957                                "Entradas na tabela com os parametros" );
00958                 apr_table_do( PrintHeadersIn, r, ParamTable, NULL );
00959                 #endif
00960 
00961                 // Verifica se temos o parametro opicional start.
00962                 StrPosition = apr_table_get( ParamTable, "start" );
00963                 if( StrPosition == NULL )
00964                     StartPosition = 0;
00965                 else
00966                 {
00967                     // Determina a posicao inicial.
00968                     StartPosition = atoi( StrPosition );
00969                     // Habilita o uso do cabecalho.
00970                     SendHeader = true;
00971                 }
00972 
00973                 // Verifica se temos o parametro opicional end.
00974                 StrPosition = apr_table_get( ParamTable, "end" );
00975                 if( StrPosition == NULL )
00976                     EndPosition = -1;
00977                 else
00978                     EndPosition = atoi( StrPosition );
00979 
00980                 // Verifica se temos o parametro file (obrigatorio).
00981                 FileName = apr_table_get( ParamTable, "file" );
00982                 if( FileName == NULL )
00983                 {
00984                     #ifdef RIO_DEBUG2
00985                     ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r,
00986                                    "Error: no filename defined" );
00987                     #endif
00988                     NoError = false;
00989                     *RioError = ERROR_RIOMODULE + ERROR_OBJECT_NOT_DEFINED;
00990                 }
00991                 #ifdef RIO_DEBUG2
00992                 else
00993                     ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r,
00994                                    "File name = %s, start position = %u",
00995                                    FileName, ( unsigned int ) StartPosition );
00996                 #endif
00997 
00998                 // Neste caso o arquivo deve ser enviado ao cliente, a partir do
00999                 // servidor dado em ServerName, que devera ser o mesmo servidor
01000                 // que esta tratando o pedido (note que, neste caso, somente
01001                 // usaremos o primeiro servidor da lista, porque estamos supondo
01002                 // que o servidor em que o modulo esta sendo executado sempre
01003                 // sera o primeiro da lista). A funcao somente sera executada se
01004                 // nenhum erro ocorreu anteriormente.
01005                 if( NoError )
01006                     NoError = TransferRioFile( r, Config, ServerName, FileName,
01007                                                RIO_SHARE_READ, StartPosition,
01008                                                EndPosition, SendHeader,
01009                                                ApacheError, SystemError,
01010                                                RioError );
01011             }
01012             else
01013             {
01014                 // Nao temos opcoes e, em consequencia, o nome do arquivo. Logo
01015                 // a opcao transfer esta incorreta.
01016                 *RioError = ERROR_RIOMODULE + ERROR_OBJECT_NOT_DEFINED;
01017             }
01018         }
01019     }
01020 
01021     // Retorna o estado do tratamento do pedido
01022     return RequestResult;
01023 }

apr_status_t ProcessParams ( request_rec *  Request,
apr_table_t **  ParamTable 
)

Definition at line 93 of file RioApacheModule.cpp.

00094 {
00095     // Variavel usada para armazenar a copia do parametro ParamList. Isso sera
00096     // necessario porque iremos alterar o conteudo da strinf, e eu nao sei se
00097     // e recomendavel alterar o conteudo de Request->args.
00098     char *ParamList;
00099     // Variavel para armazenar um ponteiro para o inicio do proximo parametro.
00100     char *NextParam;
00101     // Variavel para armazenar o ponto inicial do valor associado a um 
00102     // parametro nome (definido como nome=valor).
00103     char *StartParamValue;
00104     // Variavel para armazenar o valor usado pela funcao apr_strtok.
00105     char *AprStrTokVar;
00106 
00107     // Inicializa a tabela com os parametros.
00108     *ParamTable = NULL;
00109 
00110     // Verifica se nao temos parametros
00111     if( Request->args == NULL )
00112     {
00113         #ifdef RIO_DEBUG2
00114         ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, Request,  
00115                        "Warning: Request does not have arguments." );
00116         #endif
00117         return APR_SUCCESS;
00118     }
00119 
00120     // Cria uma tabela vazia do apache.
00121     *ParamTable = apr_table_make( Request->pool, 0 );
00122     if( *ParamTable == NULL )
00123     {
00124         #ifdef RIO_DEBUG2
00125         ap_log_rerror( APLOG_MARK, APLOG_ERR, APR_ENOMEM, Request,  
00126                        "Insufficient memory to allocate param table" );
00127         #endif
00128         return APR_ENOMEM;
00129     }
00130 
00131     // Cria uma copia da string com os parametros.
00132     ParamList = apr_pstrdup( Request->pool, Request->args );
00133     if( ParamList == NULL )
00134     {
00135         #ifdef RIO_DEBUG2
00136         ap_log_rerror( APLOG_MARK, APLOG_ERR, APR_ENOMEM, Request,  
00137                        "Insufficient memory to duplicate args string" );
00138         #endif
00139         return APR_ENOMEM;
00140     }
00141 
00142     #ifdef RIO_DEBUG2
00143     ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, Request,
00144                    "Original ParamList string: %s", ParamList );
00145     #endif
00146 
00147     // Tenta converter os caracteres de escape (que comecam com %).
00148     if( ap_unescape_url( ParamList ) != 0 )
00149     {
00150         #ifdef RIO_DEBUG2
00151         ap_log_rerror( APLOG_MARK, APLOG_ERR, APR_ENOMEM, Request,
00152                        "Error converting ParamList string" );
00153         #endif
00154         return APR_EGENERAL;
00155     }
00156 
00157     #ifdef RIO_DEBUG2
00158     ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, Request,
00159                    "Converted ParamList string: %s!", ParamList );
00160     #endif
00161 
00162     // Comeca a avaliacao dos parametros.
00163     
00164     NextParam = apr_strtok( ParamList, "&?", &AprStrTokVar );
00165     while( NextParam != NULL )
00166     {
00167         // Verificamos se o parametro esta no formato nome=valor, procurando 
00168         // pelo caractere "=" na string NextParam.
00169         StartParamValue = strchr( NextParam, '=' );
00170         if( StartParamValue == NULL )
00171         {
00172             #ifdef RIO_DEBUG2
00173             ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, Request,  
00174                            "Warning: invalid param %s", NextParam );
00175             #endif
00176         }
00177         else
00178         {
00179             // Separa o parametro do seu valor e obtem o ponteiro para o
00180             // parametro.
00181             *StartParamValue = 0;
00182             StartParamValue++;
00183             #ifdef RIO_DEBUG2
00184             ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, Request,  
00185                            "Found a param with name %s and with value %s", 
00186                            NextParam, StartParamValue );
00187             #endif
00188             // Insere o parametro na tabela.
00189             apr_table_add( *ParamTable, NextParam, StartParamValue );
00190  
00191         }
00192         // Obtem o proximo parametro.
00193         NextParam = apr_strtok( NULL, "&?", &AprStrTokVar );
00194     }
00195 
00196     return APR_SUCCESS;
00197 }

bool ProcessServersFile ( request_rec *  Request,
RioModuleConfig Config,
ServerSelectionType  SelectionType,
char **  ServerName,
apr_status_t *  ApacheError,
int *  SystemError,
RioResult RioError 
)

Definition at line 261 of file RioApacheModule.cpp.

00265 {
00266     // Estrutura com as informacoes do servidor escolhido.
00267     RioServerInfo ServerInfo;
00268     // Objeto da classe para ler o arquivo.
00269     CRioServersFile *ServersFile;
00270     // Armazena os possiveis erros retornados pelas funcoes do apache 
00271     // (ApacheError), da biblioteca do sistema (SystemError) e do RIO 
00272     // (RioError).
00273     apr_status_t ApacheStatus = APR_SUCCESS;
00274     int SystemStatus = 0;
00275     RioResult RioStatus = S_OK;
00276 
00277     // Inicializa o ponteiro para o nome do servidor.
00278     *ServerName = NULL;
00279  
00280     // Aloca o objeto para ler o arquivo do servidor.
00281     ServersFile = new CRioServersFile( Request, Config->LineSize );
00282     if( ServersFile == NULL )
00283     {
00284         *SystemError = ENOMEM;
00285 
00286         #ifdef RIO_DEBUG2
00287         ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, Request,
00288                        "Cannot create servers file object: SystemError %u (%s)",
00289                        *SystemError, strerror( *SystemError ) );
00290         #endif
00291 
00292         return false;
00293     }
00294     
00295     // Tenta abrir o arquivo com os servidores
00296     if( !ServersFile->Open( Config->ServersFileName ) )
00297     {
00298             // Obtem o erro gerado.
00299             ServersFile->GetErrors( &ApacheStatus, &SystemStatus, &RioStatus );
00300 
00301             #ifdef RIO_DEBUG2
00302             ap_log_rerror( APLOG_MARK, APLOG_ERR, ApacheStatus, Request,
00303                            "Errors when processing %s servers file:"
00304                            "ApacheError = %u, SystemError = %u (%s) "
00305                            "RioError = %u (%s)", Config->ServersFileName, 
00306                            ApacheStatus, SystemStatus, strerror( SystemStatus ),
00307                            RioStatus, GetErrorDescription( RioStatus ).c_str()  
00308                          );
00309             #endif
00310 
00311             // Somente altera as variaveis que geraram erros.
00312             if( ApacheStatus != APR_SUCCESS )
00313                 *ApacheError = ApacheStatus;
00314             if( SystemStatus != 0 )
00315                 *SystemError = SystemStatus;
00316             if( RioStatus != S_OK )
00317                 *RioError = RioStatus;
00318 
00319             // Deleta o objeto com os nomes dos servidores
00320             delete ServersFile;
00321 
00322             return false;
00323     }
00324 
00325     // Obtem o "melhor" servidor, segundo o criterio de escolha.
00326     if( !ServersFile->ChooseServer( SelectionType, &ServerInfo ) )
00327     {
00328         // Obtem o erro gerado.
00329         ServersFile->GetErrors( &ApacheStatus, &SystemStatus, &RioStatus );
00330 
00331         #ifdef RIO_DEBUG2
00332         ap_log_rerror( APLOG_MARK, APLOG_ERR, ApacheStatus, Request,
00333                        "Error choosing best server of file %s: "
00334                        "ApacheError = %u, SystemError = %u (%s) "
00335                        "RioError = %u (%s)", Config->ServersFileName, 
00336                        ApacheStatus, SystemStatus, strerror( SystemStatus ),
00337                        RioStatus, GetErrorDescription( RioStatus ).c_str() );
00338         #endif
00339 
00340         // Somente altera as variaveis que geraram erros.
00341         if( ApacheStatus != APR_SUCCESS )
00342             *ApacheError = ApacheStatus;
00343         if( SystemStatus != 0 )
00344             *SystemError = SystemStatus;
00345         if( RioStatus != S_OK )
00346             *RioError = RioStatus;
00347 
00348         // Deleta o objeto com os nomes dos servidores
00349         delete ServersFile;
00350 
00351         return false;
00352     }
00353 
00354     #ifdef RIO_DEBUG2            
00355     ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, Request,
00356                    "Best Server: ServerName = %s, MaxSessions = %f, "
00357                    "MaxAverage = %f", ServerInfo.ServerName, 
00358                    ServerInfo.MaxSessions, ServerInfo.MaxAverage );
00359     #endif          
00360 
00361     // Note que o nome do servidor nunca poderia ser NULL.
00362     if( ServerInfo.ServerName == NULL )
00363     {
00364         *RioError = ERROR_RIOMODULE + ERROR_SERVER_NOT_DEFINED;
00365         #ifdef RIO_DEBUG2
00366         ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, Request,
00367                        "Error choosing best server of file %s: "
00368                        "RioError = %u (%s)", Config->ServersFileName, RioStatus, 
00369                        GetErrorDescription( RioStatus ).c_str() );
00370         #endif
00371 
00372         // Deleta o objeto com os nomes dos servidores
00373         delete ServersFile;
00374 
00375         return false;
00376     }
00377 
00378     // Copia o nome do servidor para o pool, pois neste caso o apache sera o
00379     // responsavel por remove-lo.
00380     *ServerName = apr_pstrdup( Request->pool, ServerInfo.ServerName );
00381     if( *ServerName == NULL )
00382     {
00383         *SystemError = ENOMEM;
00384 
00385         #ifdef RIO_DEBUG2
00386         ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, Request,
00387                        "Error copying ServerName %s of file %s: "
00388                        "SystemError = %u (%s)", ServerInfo.ServerName,
00389                        Config->ServersFileName, *SystemError, 
00390                        strerror( *SystemError ) );
00391         #endif
00392 
00393         // Deleta o objeto com os nomes dos servidores
00394         delete ServersFile;
00395 
00396         return false;
00397     }
00398 
00399     // Deleta o objeto com os nomes dos servidores
00400     delete ServersFile;
00401    
00402     return true;
00403 }

int ProcessUserLog ( request_rec *  r,
RioModuleConfig Config,
apr_table_t *  ParamTable,
apr_status_t *  ApacheError,
int *  SystemError,
RioResult RioError 
)

Definition at line 1027 of file RioApacheModule.cpp.

01030 {
01031     // Variavel usada para retornar o resultado do tratamento do pedido ao
01032     // apache
01033     int RequestResult = OK;
01034     // Variavel usada para armazenar o objeto que enviara a mensagem com a linha
01035     // do log.
01036     CClientUserLogs *ClientUserLogs;
01037     // Armazena o valor associadao a opcao "logline"
01038     const char *SAux;
01039     // Armazena a linha com o log.
01040     char *LogLine;
01041 
01042     // Inicializa os erros passados como parametro.
01043     *ApacheError = APR_SUCCESS;
01044     *SystemError = 0;
01045     *RioError = S_OK;
01046     // Verifica se temos algum parametro e, caso existam, se temos a opcao
01047     // "logline" com a linha do log.
01048     if( ParamTable != NULL )
01049     {
01050         // Busca pela opcao com a linha do log.
01051         // Verifica se temos o parametro file (obrigatorio).
01052         SAux = apr_table_get( ParamTable, "logline" );
01053         if( ( SAux == NULL ) || ( strlen( SAux ) == 0 ) )
01054         {
01055             #ifdef RIO_DEBUG2
01056             ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r,
01057                            "Error: no log line defined" );
01058             #endif
01059             *RioError = ERROR_RIOMODULE + ERROR_LOGLINE_NOT_DEFINED;
01060         }
01061         else
01062         {
01063             // Inicializa a estrutura com o IP do cliente que fez a requisicao.
01064             // RequestIP.s_addr = r->connection->remote_ip;
01065             // Temos uma linha com os logs. Devemos entao processa-la (para
01066             // trocar os "*" por " ") e envia-la para o objeto (criado ao
01067             // inicializar o apache) responsavel por salvar as linhas no log.
01068             // Antes, duplicamos a string, para evitar problemas com a tabela.
01069             LogLine = apr_psprintf( r->pool, "%s %s", r->connection->remote_ip,
01070                                     SAux );
01071             if( LogLine != NULL )
01072             {
01073                 #ifdef RIO_DEBUG2
01074                 ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r,
01075                                "LogLine passada mais o IP = %s", LogLine );
01076                 #endif
01077 
01078                 // Converte todos os "*" para " " (verificar se e preciso copiar
01079                 // a string. Vou tentar nao fazer isso).
01080                 for( unsigned int p = 0; p < strlen( LogLine ); p++ )
01081                     if( LogLine[ p ] == '*' )
01082                         LogLine[ p ] = ' ';
01083 
01084                 #ifdef RIO_DEBUG2
01085                 ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r,
01086                                "LogLine convertida = %s", LogLine );
01087                 #endif
01088 
01089                 // Tenta criar um novo objeto para salvar os logs.
01090                 try
01091                 {
01092                     // Tenta criar o objeto do cliente.
01093                     ClientUserLogs = new CClientUserLogs( r );
01094 
01095                     *RioError = ClientUserLogs->Initialize(
01096                                                           Config->UserLogPort );
01097 
01098                     if( !FAILED( *RioError ) )
01099                     {
01100                         // Envia a linha do log, usando o objeto ClientUserLogs.
01101                         *RioError= ClientUserLogs->NewLogLine( LogLine );
01102 
01103                         #if RIO_DEBUG2
01104                         ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r,
01105                                        "Erro %8X (%s) ao tentar inserir a "
01106                                        "linha de log %s!", *RioError,
01107                                        GetErrorDescription( *RioError ).c_str(),
01108                                        LogLine );
01109                         #endif
01110 
01111                     }
01112                     #ifdef RIO_DEBUG2
01113                     else
01114                         ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r,
01115                                        "Erro %8X (%s) ao inicializar o objeto "
01116                                        "usado para enviar a linha de log %s!",
01117                                        *RioError,
01118                                        GetErrorDescription( *RioError ).c_str(),
01119                                        LogLine );
01120                     #endif
01121 
01122                     // Deleta o objeto usado para enviar a linha de log (com ou
01123                     // sem sucesso).
01124                     delete ClientUserLogs;
01125 
01126                 }
01127                 catch( bad_alloc &ba )
01128                 {
01129                     #ifdef RIO_DEBUG2
01130                     ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r, "Erro de "
01131                                    "alocacao de memoria (bad_alloc, error = %s)"
01132                                    " ao criar o objeto para enviar a linha de "
01133                                    "log %s!", ba.what(), LogLine );
01134                     #endif
01135                     // Ocorreu um erro de memoria. Devemos entao definir este
01136                     // erro, para que a funcao principal o trate corretamente.
01137                     *SystemError = ENOMEM;
01138                 }
01139 
01140             }
01141             else
01142             {
01143                 #ifdef RIO_DEBUG2
01144                 ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r, "Erro de alocacao "
01145                                "de memoria ao duplicar a string %s com a linha "
01146                                "de log nao processada!", SAux );
01147                 #endif
01148                 // Ocorreu um erro de memoria. Devemos entao definir este erro,
01149                 // para que a funcao principal o trate corretamente.
01150                 *SystemError = ENOMEM;
01151             }
01152         }
01153     }
01154     else
01155     {
01156         #ifdef RIO_DEBUG2
01157         ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r, "Nao foi definida uma "
01158                        "opcao logline com uma linha de log!" );
01159         #endif
01160         // Nao temos uma opcao com a linha do log. Logo, deveremos gerar um
01161         // erro.
01162         *RioError = ERROR_RIOMODULE + ERROR_LOGLINE_NOT_DEFINED;
01163     }
01164 
01165     // Retorna o estado do tratamento do pedido
01166     return RequestResult;
01167 }

static void RioModuleChildInitHandler ( apr_pool_t *  p,
server_rec *  s 
) [static]

Definition at line 2842 of file RioApacheModule.cpp.

02843 {
02844     // Inicializa a semente ramdomica com um valor composto pelo pid do processo
02845     // e o tempo atual (um ou exclusivo dos dois valores).
02846     srandom( ( unsigned int ) ( time( NULL ) ) ^
02847              ( unsigned int ) ( getpid() ) );
02848 }

static apr_status_t RioModuleDestroyServerInterface ( void *  Param  )  [static]

Definition at line 1169 of file RioApacheModule.cpp.

01170 {
01171     // Armazena o ponteiro para a estrutura com as informacoes da opcao
01172     // "exec.rio", incluindo o ponteiro do objeto da classe com a sessao aberta.
01173     TRioExecInfo *RioExecInfo;
01174 
01175     RioExecInfo = ( TRioExecInfo * ) Param;
01176 
01177     #ifdef RIO_DEBUG2
01178     RioErr << "RioModuleDestroyServerInterface: entrei aqui!" << endl;
01179     #endif
01180 
01181     if( RioExecInfo != NULL )
01182     {
01183         // Remove o objeto, se o ponteiro for diferente de NULL.
01184         if( RioExecInfo->ServerInterface != NULL )
01185         {
01186             #ifdef RIO_DEBUG2
01187             RioErr << "RioModuleDestroyServerInterface: parando o objeto!"
01188                    << endl;
01189             #endif
01190 
01191             // Para o objeto.
01192             if( !RioExecInfo->ServerInterface->Stop() )
01193             {
01194                 #ifdef RIO_DEBUG2
01195                 RioErr << "Error when stopping CServerInstance object!" << endl;
01196                 #endif
01197             }
01198 
01199             #ifdef RIO_DEBUG2
01200             RioErr << "RioModuleDestroyServerInterface: deletando o objeto!"
01201                    << endl;
01202             #endif
01203 
01204             // Remove o objeto criado.
01205             delete RioExecInfo->ServerInterface;
01206         }
01207 
01208         // Deleta a estrutura com a informacao da opcao "exec.rio".
01209         delete RioExecInfo;
01210     }
01211 
01212     return APR_SUCCESS;
01213 }

static int RioModulePostConfigHandler ( apr_pool_t *  pconf,
apr_pool_t *  plog,
apr_pool_t *  ptemp,
server_rec *  s 
) [static]

Definition at line 2479 of file RioApacheModule.cpp.

02481 {
02482     /*// Armazena o codigo de erro do apache
02483     apr_status_t ApacheStatus;
02484     // Estrutura para armazenar as informacoes do processo.
02485     apr_proc_t *UserProcessInfo;
02486     // Armazena o codigo de retorno de uma das funcoes do RIO.
02487     RioResult RioStatus;
02488     // Estruturas para o pipe.
02489     apr_file_t *InPipe, *OutPipe;
02490     // Armazena a quantidade de bytes lidos.
02491     apr_size_t TotalBytes;
02492     // Variavel com as informacoes para o termino.
02493     TFinalizeLogsInfo *LogsInfo;*/
02494     // Armazena o resultado da funcao CreateServerLogsProcess
02495     int Result;
02496 
02497     // Obtem a configuracao do modulo.
02498     RioModuleConfig *Config = ( RioModuleConfig * ) ap_get_module_config(
02499                                 s->module_config, &RioModule );
02500 
02501     // Tenta criar o processo para a opcao "userlog.rio", que salva o log de
02502     // comportamento do usuario.
02503     Result = CreateServerLogsProcess( pconf, s, Config,
02504                                       Config->UserLogsPrefixPath,
02505                                       Config->UserLogPort );
02506     if( Result != 0 )
02507     {
02508         ap_log_error( APLOG_MARK, APLOG_ERR, 0, s,
02509                       "Error when creating process for userlog command!" );
02510 
02511         return 1; // TODO: Descobrir os codigos para erro e ok e usa-los!
02512 
02513     }
02514 
02515     // Tenta criar o processo para a opcao "exec.rio", que salva o log dos
02516     // comandos executados.
02517     Result = CreateServerLogsProcess( pconf, s, Config,
02518                                       Config->ExecLogsPrefixPath,
02519                                       Config->ExecLogPort );
02520     if( Result != 0 )
02521     {
02522         ap_log_error( APLOG_MARK, APLOG_ERR, 0, s,
02523                       "Error when creating process for exec command!" );
02524 
02525         return 1; // TODO: Descobrir os codigos para erro e ok e usa-los!
02526 
02527     }
02528 
02529     /*
02530     // Aloca a estrutura com as informacoes do processo a ser criado.
02531     UserProcessInfo = ( apr_proc_t * ) apr_palloc( pconf, sizeof( apr_proc_t ) );
02532     if( UserProcessInfo == NULL )
02533     {
02534         ap_log_error( APLOG_MARK, APLOG_ERR, 0, s,
02535                       "Error when creating process structure!" );
02536 
02537         return 1; // TODO: Descobrir os codigos para erro e ok e usa-los!
02538     }
02539 
02540     // Tenta criar um pipe para ser usado pelos processos.
02541     //ApacheStatus = apr_file_pipe_create_ex( &InPipe, &OutPipe, APR_FULL_BLOCK,
02542     //                                      pconf );
02543     ApacheStatus = apr_file_pipe_create( &InPipe, &OutPipe, pconf );
02544     if( ApacheStatus != APR_SUCCESS )
02545     {
02546         ap_log_error( APLOG_MARK, APLOG_ERR, ApacheStatus, s,
02547                       "Error when creating pipe!" );
02548 
02549         return 1; // TODO: Descobrir os codigos para erro e ok e usa-los!
02550     }
02551 
02552     // Tenta alocar a variavel
02553     LogsInfo = ( TFinalizeLogsInfo * ) apr_palloc( pconf,
02554                                           sizeof( TFinalizeLogsInfo ) );
02555     if( LogsInfo == NULL )
02556     {
02557         ap_log_error( APLOG_MARK, APLOG_ERR, 0, s,
02558                       "Error when allocating memory for user logs "
02559                       "finalization structure!" );
02560 
02561         return 1; // TODO: Descobrir os codigos para erro e ok e usa-los!
02562 
02563     }
02564 
02565     // Tenta criar o processo.
02566     ApacheStatus = apr_proc_fork( UserProcessInfo, pconf );
02567     if( ( ApacheStatus != APR_INCHILD ) && ( ApacheStatus != APR_INPARENT ) )
02568     {
02569         // Fecha os dois pipes criados
02570         ApacheStatus = apr_file_close( InPipe );
02571 
02572         ap_log_error( APLOG_MARK, APLOG_ERR, ApacheStatus, s,
02573                       "Error when creating userlogs process!" );
02574 
02575         #ifdef RIO_DEBUG2
02576         if( ApacheStatus != APR_SUCCESS )
02577         {
02578             ap_log_error( APLOG_MARK, APLOG_ERR, ApacheStatus, s,
02579                           "Error closing in file of pipe!" );
02580         }
02581         #endif
02582 
02583         ApacheStatus = apr_file_close( OutPipe );
02584 
02585         #ifdef RIO_DEBUG2
02586         if( ApacheStatus != APR_SUCCESS )
02587         {
02588             ap_log_error( APLOG_MARK, APLOG_ERR, ApacheStatus, s,
02589                           "Error closing out file of pipe!" );
02590         }
02591         #endif
02592 
02593         return 1; // TODO: Descobrir os codigos para erro e ok e usa-los!
02594     }
02595 
02596     // Se for o processo pai, devemos esperar pela resposta do processo filho a
02597     // criacao do objeto da classe para o gerenciamento de logs. Se o processo
02598     // for o filho, ele deve criar o objeto, esperar pelo pai, e depois enviar
02599     // o resultado ao processo pai, que estara esperando pelo resultado.
02600     if( ApacheStatus == APR_INPARENT )
02601     {
02602         // Ponteiro para a estrutura passada a funcao de finalizacao.
02603 
02604         // Estamos no processo pai. Espera pela resposta do processo filho sobre
02605         // a criacao do objeto usado para receber os logs.
02606         #ifdef RIO_DEBUG2
02607         ap_log_error( APLOG_MARK, APLOG_ERR, 0, s,
02608                       "Executing parent process. PID = %u (apache pid = %u)",
02609                       getpid(), UserProcessInfo->pid );
02610         #endif
02611 
02612         // Fecha o pipe de saida (o pai usara somente o pipe de entrada).
02613         ApacheStatus = apr_file_close( OutPipe );
02614 
02615         if( ApacheStatus != APR_SUCCESS )
02616         {
02617             ap_log_error( APLOG_MARK, APLOG_ERR, ApacheStatus, s,
02618                           "Error closing out file of pipe!" );
02619 
02620             return 1; // TODO: Descobrir os codigos para erro e ok e usa-los!
02621         }
02622 
02623         sleep( 3 );
02624 
02625         // Tenta abrir o arquivo associado ao stdout do processo filho,
02626         // definindo o tamanho inicial em TotalBytes.
02627         ApacheStatus = apr_file_read_full( InPipe, ( void * ) &RioStatus,
02628                                            sizeof( RioResult ), &TotalBytes );
02629         if( ( ApacheStatus != APR_SUCCESS ) ||
02630             ( TotalBytes != sizeof( RioResult ) ) )
02631         {
02632             ap_log_error( APLOG_MARK, APLOG_ERR, ApacheStatus, s,
02633                           "Error when reading stdout chid process!" );
02634 
02635             // Fecha os dois pipes criados
02636             ApacheStatus = apr_file_close( InPipe );
02637 
02638             #ifdef RIO_DEBUG2
02639             if( ApacheStatus != APR_SUCCESS )
02640             {
02641                 ap_log_error( APLOG_MARK, APLOG_ERR, ApacheStatus, s,
02642                               "Error closing in file of pipe!" );
02643             }
02644             #endif
02645 
02646             // Mata o processo filho.
02647             kill( UserProcessInfo->pid, SIGKILL );
02648 
02649             return 1; // TODO: Descobrir os codigos para erro e ok e usa-los!
02650 
02651         }
02652 
02653         // Como recebemos corretamente o codigo pelo pipe, vamos fechar o pipe
02654         // de entrada.
02655         ApacheStatus = apr_file_close( InPipe );
02656 
02657         #ifdef RIO_DEBUG2
02658         if( ApacheStatus != APR_SUCCESS )
02659         {
02660             ap_log_error( APLOG_MARK, APLOG_ERR, ApacheStatus, s,
02661                           "Error closing in file of pipe!" );
02662         }
02663 
02664         ap_log_error( APLOG_MARK, APLOG_ERR, ApacheStatus, s,
02665                       "Recebido o codigo de erro %8X (%s) do processo filho!",
02666                       RioStatus, GetErrorDescription( RioStatus ).c_str() );
02667         #endif
02668 
02669         if( FAILED( RioStatus ) )
02670         {
02671             ap_log_error( APLOG_MARK, APLOG_ERR, ApacheStatus, s,
02672                           "Error %8X (%s) when creating user logs object!",
02673                           RioStatus, GetErrorDescription( RioStatus ).c_str() );
02674 
02675             return 1; // TODO: Descobrir os codigos para erro e ok e usa-los!
02676         }
02677         else
02678         {
02679             // Coloca a funcao de termino no pool associado a configuracao.
02680             LogsInfo->LogsServerPort = Config->UserLogPort;
02681             LogsInfo->Processinfo = UserProcessInfo;
02682             apr_pool_cleanup_register( pconf, ( void * ) LogsInfo,
02683                                        RioModuleTerminateServerUserLogs,
02684                                        apr_pool_cleanup_null );
02685         }
02686     }
02687     else
02688     {
02689         // Estamos no processo filho. Deveremos criar o objeto de logs, enviar o
02690         // estado da criacao ao processo pai e, em caso de sucesso, dar um join
02691         // na thread, esperando pelo termino do apache.
02692 
02693         // Armazena o ponteiro para a classe de logs a ser criada.
02694         CServerUserLogs *ServerUserLogs;
02695 
02696         #ifdef RIO_DEBUG2
02697         ap_log_error( APLOG_MARK, APLOG_ERR, 0, s,
02698                       "Executing child process. PID = %u (apache pid = %u)",
02699                       getpid(), UserProcessInfo->pid );
02700         #endif
02701 
02702         // Diz para o novo processo ignorar o sinal SIGTERM
02703         signal( SIGTERM, SIG_IGN );
02704 
02705         // Fecha o pipe de saida (o pai usara somente o pipe de entrada).
02706         ApacheStatus = apr_file_close( InPipe );
02707 
02708         if( ApacheStatus != APR_SUCCESS )
02709         {
02710             ap_log_error( APLOG_MARK, APLOG_ERR, ApacheStatus, s,
02711                           "Error closing in file of pipe!" );
02712         }
02713 
02714         // Inicializa o codigo de erro retornado.
02715         RioStatus = S_OK;
02716 
02717         // Inicializa o ponteiro para o objeto de gerenciamento dos logs.
02718         ServerUserLogs = NULL;
02719 
02720         // Tenta criar um objeto da classe.
02721         try
02722         {
02723             // Tenta criar o objeto da classe CServerUserLogs.
02724             ServerUserLogs = new CServerUserLogs( s );
02725 
02726             #ifdef RIO_DEBUG2
02727             ap_log_error( APLOG_MARK, APLOG_ERR, 0, s, "Objeto criado com "
02728                            "sucesso! Tentando inicializar o objeto!" );
02729 
02730             #endif
02731 
02732             // Se o objeto foi criado com sucesso, tenta entao inicializa-lo.
02733             RioStatus = ServerUserLogs->Initialize(
02734                                                  Config->UserLogsPrefixPath,
02735                                                     Config->MaxLogFileSize,
02736                                           Config->MaxCombinedLogFilesSize,
02737                                           Config->UserLogPort );
02738             if( FAILED( RioStatus ) )
02739             {
02740                 ap_log_error( APLOG_MARK, APLOG_ERR, 0, s,
02741                               "Error %8X (%s) when initializing "
02742                               "CServerUserLogs object!", RioStatus,
02743                               GetErrorDescription( RioStatus ).c_str() );
02744                 delete ServerUserLogs;
02745             }
02746             else
02747             {
02748                 #ifdef RIO_DEBUG2
02749                 ap_log_error( APLOG_MARK, APLOG_ERR, 0, s,
02750                               "Objeto inicializado com sucesso! Tentando "
02751                               "obter o IP associado ao socket UDP!" );
02752                 #endif
02753             }
02754 
02755         }
02756         catch( bad_alloc &ba )
02757         {
02758             // Define o estado do RIO como de erro de memoria.
02759             RioStatus = ERROR_RIOMODULE + ERROR_MEMORY;
02760 
02761             ap_log_error( APLOG_MARK, APLOG_ERR, 0, s,
02762                           "Error bad_alloc (%s) when creating CServerUserLogs "
02763                           "object!", ba.what() );
02764         }
02765 
02766         // Enviamos o status ao servidor pelo pipe compartilhado.
02767         // Tenta abrir o arquivo associado ao stdout do processo filho,
02768         // definindo o tamanho inicial em TotalBytes.
02769         ApacheStatus = apr_file_write_full( OutPipe, ( void * ) &RioStatus,
02770                                             sizeof( RioResult ), &TotalBytes );
02771         if( ( ApacheStatus != APR_SUCCESS ) ||
02772             ( TotalBytes != sizeof( RioResult ) ) )
02773         {
02774             // Deleta o ojeto responsavel pelo gerenciamento dos logs.
02775             if( ServerUserLogs != NULL )
02776                 delete ServerUserLogs;
02777 
02778             // Fecha o pipe usado para enviar dados.
02779             ApacheStatus = apr_file_close( OutPipe );
02780 
02781             #ifdef RIO_DEBUG2
02782             if( ApacheStatus != APR_SUCCESS )
02783             {
02784                 ap_log_error( APLOG_MARK, APLOG_ERR, ApacheStatus, s,
02785                               "Error closing out file of pipe!" );
02786             }
02787             #endif
02788 
02789             ap_log_error( APLOG_MARK, APLOG_ERR, ApacheStatus, s,
02790                           "Error when reading stdout child process!" );
02791 
02792             exit( -1 );
02793         }
02794 
02795         // Da um flush em OutPipe.
02796         ApacheStatus = apr_file_flush( OutPipe );
02797         if( ApacheStatus != APR_SUCCESS )
02798         {
02799             ap_log_error( APLOG_MARK, APLOG_ERR, ApacheStatus, s,
02800                           "Error when flushing out chid process!" );
02801 
02802             // Deleta o ojeto responsavel pelo gerenciamento dos logs.
02803             if( ServerUserLogs != NULL )
02804                 delete ServerUserLogs;
02805 
02806             // Fecha o pipe usado para enviar dados.
02807             ApacheStatus = apr_file_close( OutPipe );
02808 
02809             #ifdef RIO_DEBUG2
02810             if( ApacheStatus != APR_SUCCESS )
02811             {
02812                 ap_log_error( APLOG_MARK, APLOG_ERR, ApacheStatus, s,
02813                               "Error closing out file of pipe!" );
02814             }
02815             #endif
02816 
02817             exit( -1 );
02818         }
02819 
02820         // Como enviamos corretamente o codigo pelo pipe, vamos fechar o
02821         // descritor usado para enviar dados pelo pipe.
02822         ApacheStatus = apr_file_close( OutPipe );
02823 
02824         #ifdef RIO_DEBUG2
02825         if( ApacheStatus != APR_SUCCESS )
02826         {
02827             ap_log_error( APLOG_MARK, APLOG_ERR, ApacheStatus, s,
02828                           "Error closing out file of pipe!" );
02829         }
02830         #endif
02831 
02832         // Se nenhum ocorreu, esperamos pelo termino da thread.
02833         ServerUserLogs->JoinThread();
02834 
02835         // Termina a execucao do processo.
02836         exit( 0 );
02837     } */
02838 
02839     return 0; // TODO: Descobrir os codigos para erro e ok e usa-los!
02840 }

static void RioModuleRegisterHooks ( apr_pool_t *  p  )  [static]

Definition at line 2856 of file RioApacheModule.cpp.

02857 {
02858     // Chamada para registrar a funcao do modulo que trata das requisicoes
02859     // enviadas ao cliente para o apache e repassadas ao modulo.
02860     ap_hook_handler( RioModuleRequestHandler, NULL, NULL, APR_HOOK_LAST );
02861 
02862     ap_hook_post_config( RioModulePostConfigHandler, NULL, NULL,
02863                          APR_HOOK_LAST );
02864     // Chamada para registrar a funcao do modulo chamada para cada processo que
02865     // trata dos pedidos, e que criara, na primeira vez, a memoria compartilhada
02866     // e o mutex para acessa-la baseados em arquivos. O mutex tambem e
02867     // inicializado para cada filho.
02868     ap_hook_child_init( RioModuleChildInitHandler, NULL, NULL, APR_HOOK_LAST );
02869 }

static int RioModuleRequestHandler ( request_rec *  r  )  [static]

Definition at line 1822 of file RioApacheModule.cpp.

01823 {
01824     // Variavel booleana usada para indicar se algum erro ocorreu.
01825     bool NoError;
01826     // Variavel booleana usada para indicar se devemos usar o redirecionamento,
01827     // ou se devemos enviar o arquivo para o cliente.
01828     bool UseRedirect;
01829     // Armazena os possiveis erros retornados pelas funcoes do apache 
01830     // (ApacheError), da biblioteca do sistema (SystemError) e do RIO 
01831     // (RioError).
01832     apr_status_t ApacheError = APR_SUCCESS, status;
01833     int SystemError = 0;
01834     RioResult RioError = S_OK;
01835     // Tabela que contera os parametros.
01836     apr_table_t* ParamTable;
01837     // Variavel usada para retornar o resultado do tratamento do pedido ao
01838     // apache
01839     int RequestResult = OK;
01840     // Armazena uma copia do r->uri, que depois sera convertida para a politica
01841     // a ser usada pelo modulo (o nome que vem depois de \ e antes do .rio).
01842     char *ModulePolicy;
01843     // Armazena o ponteiro para o final da politica do modulo.
01844     char *FinalModulePolicy;
01845 
01846     #ifdef RIO_DEBUG2
01847     ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r, "MAINTHREADID %lu", 
01848                    syscall( SYS_gettid ) );
01849     #endif               
01850 
01851     signal( SIGSEGV, SignalHandler );
01852     signal( SIGILL, SignalHandler );
01853 
01854     // Obtem a configuracao do modulo.
01855     RioModuleConfig *Config = ( RioModuleConfig * ) ap_get_module_config( 
01856                               r->server->module_config, &RioModule );
01857 
01858 
01859     // Verifica se o tipo MIME da requisicao de processamento e o do RIO.
01860     if( strncmp( r->handler, RIOMODULE_MIME, RIOMODULE_MIME_SIZE ) != 0 )
01861     {
01862         #ifdef RIO_DEBUG2
01863         ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r, "O arquivo %s nao esta "
01864                        "relacionado ao modulo! Declinando o pedido!",
01865                        r->filename );
01866         #endif
01867 
01868         return DECLINED;
01869     }
01870 
01871     // Verifica se algum parametro foi passado (os valores depois do "?").
01872     if( r->args == NULL )
01873     {
01874         #ifdef RIO_DEBUG2
01875         ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r, "Requisicao invalida! Nao "
01876                        "foram passadas opcoes para o arquivo %s!",
01877                        r->filename );
01878         #endif
01879 
01880         return HTTP_BAD_REQUEST;
01881     }
01882 
01883     #ifdef RIO_DEBUG2
01884     // Imprime algumas informacoes de estado.
01885     ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r, 
01886                    "Cabecalhos (r->headers_in)" );
01887     apr_table_do( PrintHeadersIn, r, r->headers_in, NULL );
01888     ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r, "Campos request_rec (r): "
01889                    "r->handler = %s, r->method = %s, r->filename = %s, "
01890                    "r->uri = %s, r->args = %s, r->unparsed_uri = %s, "
01891                    "r->connection->id = %ld, r->connection->remote_ip = %s, "
01892                    "r->connection->local_ip = %s, "
01893                    "r->connection->remote_addr->sin.sin_addr = %s, "
01894                    "r->connection->remote_addr->sin.sin_port = %u, "
01895                    "r->connection->remote_addr->port = %u, "
01896                    "r->connection->local_addr->sin = %s, "
01897                    "r->connection->local_addr->sin.sin_port = %u, "
01898                    "r->connection->local_addr->port = %u, "
01899                    "r->connection->keepalive = %u, "
01900                    "ap_http_scheme( r ) = %s",
01901                    r->handler, r->method, r->filename, r->uri, r->args,
01902                    r->unparsed_uri, r->connection->id,
01903                    r->connection->remote_ip, r->connection->local_ip,
01904                    inet_ntoa( r->connection->remote_addr->sa.sin.sin_addr ),
01905                    ntohs( r->connection->remote_addr->sa.sin.sin_port ),
01906                    r->connection->remote_addr->port,
01907                    inet_ntoa( r->connection->local_addr->sa.sin.sin_addr ),
01908                    ntohs( r->connection->local_addr->sa.sin.sin_port ),
01909                    r->connection->local_addr->port,
01910                    r->connection->keepalive,
01911                    ap_http_scheme( r ) );
01912     ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r, "Configuracao do modulo: "
01913                    "Descricao = %s, ServerName = %s, RealTimeExtensions = %s, "
01914                    "WaitTime = %u ms, BufferSize = %u, LineSize = %u, "
01915                    "SelectionType = %u, FragmentSize = %u, User = %s, "
01916                    "Password = %s, ServersFileName = %s, RedirectName = %s, "
01917                    "TransferName = %s, MaxLogFileSize = %u, "
01918                    "MaxCombinedLogFilesSize = %llu, UserLogsPrefixPath = %s, "
01919                    "UserLogName = %s, UserLogPort = %u, ExecSessionId = %u, "
01920                    "process pid = %u",
01921                    Config->Description, Config->ServerName,
01922                    ( Config->RealTimeExtensions == NULL) ? "<not defined>" :
01923                    Config->RealTimeExtensions, Config->WaitTime, 
01924                    Config->BufferSize, Config->LineSize, Config->SelectionType, 
01925                    Config->FragmentSize, Config->User, Config->Password,
01926                    ( Config->ServersFileName == NULL ) ? "<not defined>" : 
01927                    Config->ServersFileName, Config->RedirectName, 
01928                    Config->TransferName, Config->MaxLogFileSize,
01929                    Config->MaxCombinedLogFilesSize, Config->UserLogsPrefixPath,
01930                    Config->UserLogName, Config->UserLogPort,
01931                    Config->ExecSessionId, getpid() );
01932     #endif
01933     // Inicializa a variavel que indica se algum erro ocorreu.
01934     NoError = true;
01935 
01936     // Tenta obter a tabela com os parametros, se nenhum erro ocorreu ao
01937     ApacheError = ProcessParams( r, &ParamTable );
01938     if( ApacheError != APR_SUCCESS )
01939     {
01940         #ifdef RIO_DEBUG2
01941         ap_log_rerror( APLOG_MARK, APLOG_ERR, ApacheError, r,
01942                        "Error when reading module params" );
01943         #endif
01944     } 
01945 
01946     // Separa a politica do modulo do nome restante do arquivo.
01947     FinalModulePolicy = strchr( &r->uri[ 1 ], '.' );
01948     if( FinalModulePolicy == NULL )
01949     {
01950         // Isso nao deveria ocorrer, pois sempre devemos ter a opcao .rio
01951         return DECLINED;
01952     }
01953 
01954     // Temporariamente muda o valor de FinalModulePolicyPos de '.' para '\0'.
01955     *FinalModulePolicy = 0;
01956 
01957     // Cria a string copiando somente a politica de acesso.
01958     ModulePolicy = apr_pstrcat( r->pool, &r->uri[ 1 ], NULL );
01959 
01960     // Restaura o caractere para o '.'.
01961     *FinalModulePolicy = '.';
01962 
01963     // Verifica se a politica foi criada com sucesso.
01964     if( ModulePolicy == NULL )
01965     {
01966         #ifdef RIO_DEBUG2
01967         ap_log_rerror( APLOG_MARK, APLOG_ERR, ApacheError, r,
01968                        "Memory Error when creating module policy." );
01969         #endif
01970 
01971         SystemError = ENOMEM;
01972 
01973     }
01974     else
01975     {
01976         // Verifica se o nome passado e um dos nomes validos de arquivo
01977         // (atualmente, temos opcoes para o redirecionamento, transferencia do
01978         // apache para o cliente, e a nova opcao de geracao de logs).
01979         if( ( strcmp( ModulePolicy, Config->RedirectName ) == 0 ) ||
01980             ( strcmp( ModulePolicy, Config->TransferName ) == 0 ) )
01981         {
01982             // Verifica se o metodo e o de obter algo (GET)
01983             if( strcmp( r->method, "GET" ) != 0 )
01984                 return HTTP_METHOD_NOT_ALLOWED;
01985 
01986             // Neste caso temos uma transferencia do arquivo ou um
01987             // redirecionamento. Entao, de acordo com o nome do arquivo,
01988             // definimos se temos ou nao um redirecionamento. Usamos
01989             // &r->uri[ 1 ] para remover a "/" inicial.
01990             if( strcmp( ModulePolicy, Config->RedirectName ) == 0 )
01991             {
01992                 // O nome do arquivo e redirect.rio. Deveremos entao
01993                 // redirecionar a requisicao.
01994                 UseRedirect = true;
01995 
01996                 #ifdef RIO_DEBUG2
01997                 ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r,
01998                                "Redirecionando a requicao do arquivo" );
01999                 #endif
02000             }
02001             else
02002             {
02003                 // O nome do arquivo e transfer.rio. Deveremos entao enviar o
02004                 // arquivo.
02005                 UseRedirect = false;
02006 
02007                 #ifdef RIO_DEBUG2
02008                 ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r,
02009                                "Enviando o arquivo " );
02010                 #endif
02011             }
02012 
02013             // Executa as duas opcoes (redirect e transfer).
02014             RequestResult = ProcessFileOptions( r, Config, ParamTable,
02015                                                 UseRedirect, &ApacheError,
02016                                                 &SystemError, &RioError );
02017             // Envia os erros ao cliente (se necessario).
02018             status = SendError( r, ApacheError, SystemError, RioError );
02019 
02020             #ifdef RIO_DEBUG2
02021             if( status != APR_SUCCESS )
02022                 ap_log_rerror( APLOG_MARK, APLOG_ERR, status, r,
02023                                "error sending erro information" );
02024             #endif
02025         }
02026         else if( strcmp( ModulePolicy, Config->UserLogName ) == 0 )
02027         {
02028             // Verifica se o metodo e o de obter algo (GET)
02029             if( strcmp( r->method, "GET" ) != 0 )
02030                 return HTTP_METHOD_NOT_ALLOWED;
02031 
02032             // Neste caso foi passada a nova opcao de logs. Devemos entao
02033             // salvar o que foi passado na opcao "logline" no log, trocando
02034             // todas as ocorrencias de "*" por " ".
02035             RequestResult = ProcessUserLog( r, Config, ParamTable, &ApacheError,
02036                                             &SystemError, &RioError );
02037         }
02038         else if( strcmp( ModulePolicy, Config->ExecName ) == 0 )
02039         {
02040             // Neste caso, vamos executar um comando.
02041             RequestResult = ProcessExec( r, Config, ParamTable, &ApacheError,
02042                                          &SystemError, &RioError );
02043         }
02044         else
02045         {
02046             // O nome da politica usada pelo modulo nao e nem o
02047             // redirecionamento, nem a copia e nem o uso de logs.
02048             RioError = ERROR_RIOMODULE + ERROR_INVALID_MODULE_POLICY;
02049 
02050             #ifdef RIO_DEBUG2
02051             ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r,
02052                            "Invalid policy name %s", ModulePolicy );
02053             #endif
02054         }
02055     }
02056 
02057     #ifdef RIO_DEBUG2
02058     ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r, "Codigo http do resultado do "
02059                    "tratamento da requisicao = %u", RequestResult );
02060     #endif
02061 
02062     return RequestResult;
02063 }

static apr_status_t RioModuleTerminateServerUserLogs ( void *  Param  )  [static]

Definition at line 2067 of file RioApacheModule.cpp.

02068 {
02069     // Ponteiro para os dados recebidos por parametro.
02070     TFinalizeLogsInfo *LogsInfo;
02071     // Armazena o estado do retorno das funcoes do RIO.
02072     RioResult RioStatus;
02073     // Armazena a estrutura usada para finalizar o objeto que salva os logs.
02074     CClientUserLogs FinalizeMsg( NULL );
02075     // Codigo de retorno do processo que executa o objeto que gerencia os logs.
02076     int ExitProcess;
02077     // Estado do processo filho quando o wait retornou.
02078     apr_exit_why_e ProcessStatus;
02079     // Codigo de retorno do apache.
02080     apr_status_t ApacheStatus;
02081     // Salva o codigo de erro do retorno da funcao wait.
02082     char ApacheStrError[ MAXAPACHESTRERRORSIZE ];
02083 
02084 
02085     #ifdef RIO_DEBUG2
02086     RioErr << "RioModuleTerminateServerUserLogs: entrei aqui!" << endl;
02087     #endif
02088 
02089     // Inicializa o ponteiro para a estrutura com as informacoes necessarias
02090     // para terminar o processo.
02091     LogsInfo = ( TFinalizeLogsInfo* ) Param;
02092 
02093     // Inicializa o retorno do apache.
02094     ApacheStatus = APR_SUCCESS;
02095 
02096     // Tenta inicializar a classe cliente de logs, usada para enviar a mensagem
02097     // para finalizar a classe.
02098     RioStatus = FinalizeMsg.Initialize( LogsInfo->LogsServerPort );
02099     if( FAILED( RioStatus ) )
02100     {
02101         #ifdef RIO_DEBUG2
02102         RioErr << "RioModuleTerminateServerUserLogs 0x" << hex << RioStatus
02103                << dec << " (" << GetErrorDescription( RioStatus ) << ") when "
02104                << "initializing object! Process will be killed!" << endl;
02105         #endif
02106 
02107         // Mata o processo, pois nao conseguimos finaliza-lo corretamente.
02108         kill( LogsInfo->LogsServerPort, SIGKILL );
02109     }
02110     else
02111     {
02112         RioStatus = FinalizeMsg.NewLogLine( NULL );
02113         if( FAILED( RioStatus ) )
02114         {
02115             #ifdef RIO_DEBUG2
02116             RioErr << "RioModuleTerminateServerUserLogs Erro 0x" << hex
02117                    << RioStatus << dec << " ("
02118                    << GetErrorDescription( RioStatus )
02119                    << ") when sendling finalization message! Process will be "
02120                    << "killed!" << endl;
02121             #endif
02122 
02123             // Mata o processo, pois nao conseguimos finaliza-lo corretamente.
02124             kill( LogsInfo->LogsServerPort, SIGKILL );
02125         }
02126 
02127         // Espera pelo termino do processo.
02128         ApacheStatus = apr_proc_wait( LogsInfo->ProcessInfo, &ExitProcess,
02129                                       &ProcessStatus, APR_WAIT );
02130 
02131         // Obtem o erro do apache
02132         apr_strerror( ProcessStatus, ApacheStrError,
02133                       MAXAPACHESTRERRORSIZE );
02134 
02135         #ifdef RIO_DEBUG2
02136         RioErr << "RioModuleTerminateServerUserLogs processo terminou com o "
02137                << "codigo de saida " << ExitProcess << " e codigo de status "
02138                << ProcessStatus << " (" << ApacheStrError << ")." << endl;
02139         #endif
02140    }
02141 
02142    return ApacheStatus;
02143 }

apr_status_t SendError ( request_rec *  Request,
apr_status_t  ApacheError,
int  SystemError,
RioResult  RioError 
)

Definition at line 201 of file RioApacheModule.cpp.

00203 {
00204     char ApacheStrError[ MAXAPACHESTRERRORSIZE ];
00205 
00206     // Obtem o erro do apache
00207     apr_strerror( ApacheError, ApacheStrError, MAXAPACHESTRERRORSIZE );
00208 
00209     #ifdef RIO_DEBUG2
00210     ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, Request,
00211                    "Errors when processing request: ApacheError = %u (%s), "
00212                    "SystemError = %u (%s), RioError = %08X (%s)", ApacheError,
00213                    ApacheStrError, SystemError, strerror( SystemError ), 
00214                    RioError, GetErrorDescription( RioError ).c_str() );
00215     #endif
00216 
00217     if( ( ApacheError != APR_SUCCESS ) || ( SystemError != 0 ) ||
00218         ( RioError != S_OK ) )
00219     {
00220         #ifdef RIO_DEBUG2
00221         ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, Request,
00222                        "Sending these errors to the client" );
00223         #endif
00224 
00225         ap_set_content_type( Request, RIOMODULE_MIME_ERROR );
00226         apr_table_set( Request->headers_out, RIOMODULE_HTTP_FILENAME,
00227                        "inline; filename=error.html" );
00228 
00229         ap_rprintf( Request, "<HTML>\n");
00230         ap_rprintf( Request, 
00231                  "<HEAD><TITLE>RioApacheModule Error report</TITLE></HEAD>\n" );
00232         ap_rprintf( Request, "<BODY>\n");         
00233         if( ApacheError != APR_SUCCESS )
00234             ap_rprintf( Request, "<B>Apache Error:</B> %u (%s)<BR>\n", ApacheError, 
00235                         ApacheStrError );
00236         if( SystemError != 0 )
00237             ap_rprintf( Request, "<B>System Error:</B> %u (%s)<BR>\n", SystemError, 
00238                         strerror( SystemError ) );
00239         if( RioError != S_OK )                
00240             ap_rprintf( Request, "<B>Rio Error:</B> %8X (%s)<BR>\n", RioError, 
00241                         GetErrorDescription( RioError ).c_str() );
00242         ap_rprintf( Request, "</BODY>\n");
00243         ap_rprintf( Request, "</HTML>\n");
00244     }
00245     
00246     return APR_SUCCESS;
00247 }

static const char* setBufferSize ( cmd_parms *  parms,
void *  mconfig,
const char *  arg 
) [static]

Definition at line 2921 of file RioApacheModule.cpp.

02923 {
02924     // Obtem a configuracao do modulo.
02925     RioModuleConfig *config = ( RioModuleConfig * ) ap_get_module_config( 
02926                                 parms->server->module_config, &RioModule );
02927 
02928     // Define o numero de blocos que podemos armazenar no buffer.
02929     config->BufferSize = atoi( arg );
02930 
02931     // retorna que o comando foi executado com sucesso.
02932     return NULL;
02933 }

static const char* setExecLogPort ( cmd_parms *  parms,
void *  mconfig,
const char *  arg 
) [static]

Definition at line 3194 of file RioApacheModule.cpp.

03196 {
03197     // Obtem a configuracao do modulo.
03198     RioModuleConfig *config = ( RioModuleConfig * ) ap_get_module_config(
03199                                      parms->server->module_config, &RioModule );
03200 
03201     // Define a porta UDP usada pelo objeto de geracao de logs (da opcao
03202     // "exec.rio"
03203     config->ExecLogPort = atoi( arg );
03204 
03205     // retorna que o comando foi executado com sucesso.
03206     return NULL;
03207 }

static const char* setExecLogsPrefixPath ( cmd_parms *  parms,
void *  mconfig,
const char *  arg 
) [static]

Definition at line 3178 of file RioApacheModule.cpp.

03180 {
03181     // Obtem a configuracao do modulo.
03182     RioModuleConfig *config = ( RioModuleConfig * ) ap_get_module_config(
03183                                      parms->server->module_config, &RioModule );
03184 
03185     // Define o o caminho completo de onde os arquivos de log serao armazenados.
03186     config->ExecLogsPrefixPath = apr_pstrdup( parms->pool, arg );
03187 
03188     // retorna que o comando foi executado com sucesso.
03189     return NULL;
03190 }

static const char* setExecName ( cmd_parms *  parms,
void *  mconfig,
const char *  arg 
) [static]

Definition at line 3126 of file RioApacheModule.cpp.

03128 {
03129     // Obtem a configuracao do modulo.
03130     RioModuleConfig *config = ( RioModuleConfig * ) ap_get_module_config(
03131                                 parms->server->module_config, &RioModule );
03132 
03133     // Seta o nome usado para executarmos os comandos similares ao do riosh.
03134     config->ExecName = apr_pstrdup( parms->pool, arg );
03135 
03136     // retorna que o comando foi executado com sucesso.
03137     return NULL;
03138 }

static const char* setExecSessionId ( cmd_parms *  parms,
void *  mconfig,
const char *  arg 
) [static]

Definition at line 3160 of file RioApacheModule.cpp.

03162 {
03163     // Obtem a configuracao do modulo.
03164     RioModuleConfig *config = ( RioModuleConfig * ) ap_get_module_config(
03165                                      parms->server->module_config, &RioModule );
03166 
03167     // Define o identificador default para as sessoes criadas ao executar a
03168     // opcao "exec.rio"
03169     config->ExecSessionId = atoi( arg );
03170 
03171     // retorna que o comando foi executado com sucesso.
03172     return NULL;
03173 }

static const char* setFragmentSize ( cmd_parms *  parms,
void *  mconfig,
const char *  arg 
) [static]

Definition at line 2979 of file RioApacheModule.cpp.

02981 {
02982     // Obtem a configuracao do modulo.
02983     RioModuleConfig *config = ( RioModuleConfig * ) ap_get_module_config( 
02984                                      parms->server->module_config, &RioModule );
02985 
02986     // Define o tamanho dos fragmentos enviados ao cliente.
02987     config->FragmentSize = atoi( arg );
02988 
02989     // retorna que o comando foi executado com sucesso.
02990     return NULL;
02991 }

static const char* setLineSize ( cmd_parms *  parms,
void *  mconfig,
const char *  arg 
) [static]

Definition at line 2937 of file RioApacheModule.cpp.

02939 {
02940     // Obtem a configuracao do modulo.
02941     RioModuleConfig *config = ( RioModuleConfig * ) ap_get_module_config( 
02942                                      parms->server->module_config, &RioModule );
02943 
02944     // Define o tamanho de cada linha dos arquivos .rio.
02945     config->LineSize = atoi( arg );
02946 
02947     // retorna que o comando foi executado com sucesso.
02948     return NULL;
02949 }

static const char* setMaxCombinedLogFilesSize ( cmd_parms *  parms,
void *  mconfig,
const char *  arg 
) [static]

Definition at line 3076 of file RioApacheModule.cpp.

03078 {
03079     // Obtem a configuracao do modulo.
03080     RioModuleConfig *config = ( RioModuleConfig * ) ap_get_module_config(
03081                                      parms->server->module_config, &RioModule );
03082 
03083     // Define o tamanho maximo da soma de todos os arquivos de logs.
03084     config->MaxCombinedLogFilesSize = atoll( arg ) * 1024ull;
03085 
03086     // retorna que o comando foi executado com sucesso.
03087     return NULL;
03088 }

static const char* setMaxLogFileSize ( cmd_parms *  parms,
void *  mconfig,
const char *  arg 
) [static]

Definition at line 3060 of file RioApacheModule.cpp.

03062 {
03063     // Obtem a configuracao do modulo.
03064     RioModuleConfig *config = ( RioModuleConfig * ) ap_get_module_config(
03065                                      parms->server->module_config, &RioModule );
03066 
03067     // Define o tamanho maximo do arquivo de log nao compactado.
03068     config->MaxLogFileSize = atoi( arg ) * 1024;
03069 
03070     // retorna que o comando foi executado com sucesso.
03071     return NULL;
03072 }

static const char* setRealTimeExtensions ( cmd_parms *  parms,
void *  mconfig,
const char *  arg 
) [static]

Definition at line 2888 of file RioApacheModule.cpp.

02890 {
02891     // Obtem a configuracao do modulo.
02892     RioModuleConfig *config = ( RioModuleConfig * ) ap_get_module_config( 
02893                                 parms->server->module_config, &RioModule );
02894 
02895     // Define as extensoes dos arquivos que devem ser transmitidos em tempo
02896     // real.
02897     config->RealTimeExtensions = apr_pstrdup( parms->pool, arg );
02898 
02899     // retorna que o comando foi executado com sucesso.
02900     return NULL;
02901 }

static const char* setRedirectName ( cmd_parms *  parms,
void *  mconfig,
const char *  arg 
) [static]

Definition at line 3028 of file RioApacheModule.cpp.

03030 {
03031     // Obtem a configuracao do modulo.
03032     RioModuleConfig *config = ( RioModuleConfig * ) ap_get_module_config( 
03033                                 parms->server->module_config, &RioModule );
03034 
03035     // Seta o nome usado para fazermos as redirecoes de pedidos.
03036     config->RedirectName = apr_pstrdup( parms->pool, arg );
03037 
03038     // retorna que o comando foi executado com sucesso.
03039     return NULL;
03040 }

static const char* setRIOUser ( cmd_parms *  parms,
void *  mconfig,
const char *  arg1,
const char *  arg2 
) [static]

Definition at line 2994 of file RioApacheModule.cpp.

02996 {
02997     // Obtem a configuracao do modulo.
02998     RioModuleConfig *config = ( RioModuleConfig * ) ap_get_module_config( 
02999                                 parms->server->module_config, &RioModule );
03000 
03001     // Define o nome do usuario e a senha
03002     config->User = apr_pstrdup( parms->pool, arg1 );
03003     if( arg2 != NULL )
03004         config->Password = apr_pstrdup( parms->pool, arg2 );
03005 
03006     // retorna que o comando foi executado com sucesso.
03007     return NULL;
03008 }

static const char* setSelectionType ( cmd_parms *  parms,
void *  mconfig,
const char *  arg 
) [static]

Definition at line 2953 of file RioApacheModule.cpp.

02955 {
02956     // Obtem a configuracao do modulo.
02957     RioModuleConfig *config = ( RioModuleConfig * ) ap_get_module_config( 
02958                                      parms->server->module_config, &RioModule );
02959 
02960     // Define o criterio de selecao dos servidores do arquivo .rio.
02961     if( strcasecmp( arg, "Random" ) == 0 ) 
02962         config->SelectionType = RIO_SELECTION_RANDOM;
02963     else if ( strcasecmp( arg, "Lload" ) == 0 )
02964         config->SelectionType = RIO_SELECTION_L_LOAD;
02965     else if ( strcasecmp( arg, "Mvavg" ) == 0 )
02966         config->SelectionType = RIO_SELECTION_MV_AVG;
02967     else
02968     {
02969         // Como imprimir um erro nesta funcao, ou retornar um erro?
02970         config->SelectionType = RIO_SELECTION_RANDOM;
02971     }    
02972 
02973     // retorna que o comando foi executado com sucesso.
02974     return NULL;
02975 }

static const char* setServerName ( cmd_parms *  parms,
void *  mconfig,
const char *  arg 
) [static]

Definition at line 2872 of file RioApacheModule.cpp.

02874 {
02875     // Obtem a configuracao do modulo.
02876     RioModuleConfig *config = ( RioModuleConfig * ) ap_get_module_config( 
02877                                 parms->server->module_config, &RioModule );
02878 
02879     // Define o nome do servidor.
02880     config->ServerName = apr_pstrdup( parms->pool, arg );
02881 
02882     // retorna que o comando foi executado com sucesso.
02883     return NULL;
02884 }

static const char* setServersFileName ( cmd_parms *  parms,
void *  mconfig,
const char *  arg 
) [static]

Definition at line 3011 of file RioApacheModule.cpp.

03013 {
03014     // Obtem a configuracao do modulo.
03015     RioModuleConfig *config = ( RioModuleConfig * ) ap_get_module_config( 
03016                                 parms->server->module_config, &RioModule );
03017 
03018     // Seta o caminho do arquivo com os servidores que podem ser usados.
03019     config->ServersFileName = apr_pstrdup( parms->pool, arg );
03020 
03021     // retorna que o comando foi executado com sucesso.
03022     return NULL;
03023 }

static const char* setTransferName ( cmd_parms *  parms,
void *  mconfig,
const char *  arg 
) [static]

Definition at line 3044 of file RioApacheModule.cpp.

03046 {
03047     // Obtem a configuracao do modulo.
03048     RioModuleConfig *config = ( RioModuleConfig * ) ap_get_module_config( 
03049                                 parms->server->module_config, &RioModule );
03050 
03051     // Seta o nome usado pelo modulo ao redirecionar um pedido.
03052     config->TransferName = apr_pstrdup( parms->pool, arg );
03053 
03054     // retorna que o comando foi executado com sucesso.
03055     return NULL;
03056 }

static const char* setUserLogName ( cmd_parms *  parms,
void *  mconfig,
const char *  arg 
) [static]

Definition at line 3110 of file RioApacheModule.cpp.

03112 {
03113     // Obtem a configuracao do modulo.
03114     RioModuleConfig *config = ( RioModuleConfig * ) ap_get_module_config(
03115                                 parms->server->module_config, &RioModule );
03116 
03117     // Seta o nome usado para gerarmos os logs de comportamento dos clientes.
03118     config->UserLogName = apr_pstrdup( parms->pool, arg );
03119 
03120     // retorna que o comando foi executado com sucesso.
03121     return NULL;
03122 }

static const char* setUserLogPort ( cmd_parms *  parms,
void *  mconfig,
const char *  arg 
) [static]

Definition at line 3142 of file RioApacheModule.cpp.

03144 {
03145     // Obtem a configuracao do modulo.
03146     RioModuleConfig *config = ( RioModuleConfig * ) ap_get_module_config(
03147                                      parms->server->module_config, &RioModule );
03148 
03149     // Define a porta UDP usada pelo objeto de geracao de logs (da opcao
03150     // "userlog.rio"
03151     config->UserLogPort = atoi( arg );
03152 
03153     // retorna que o comando foi executado com sucesso.
03154     return NULL;
03155 }

static const char* setUserLogsPrefixPath ( cmd_parms *  parms,
void *  mconfig,
const char *  arg 
) [static]

Definition at line 3093 of file RioApacheModule.cpp.

03095 {
03096     // Obtem a configuracao do modulo.
03097     RioModuleConfig *config = ( RioModuleConfig * ) ap_get_module_config(
03098                                      parms->server->module_config, &RioModule );
03099 
03100     // Define o o caminho completo de onde os arquivos de log serao armazenados.
03101     config->UserLogsPrefixPath = apr_pstrdup( parms->pool, arg );
03102 
03103     // retorna que o comando foi executado com sucesso.
03104     return NULL;
03105 }

static const char* setWaitTime ( cmd_parms *  parms,
void *  mconfig,
const char *  arg 
) [static]

Definition at line 2904 of file RioApacheModule.cpp.

02906 {
02907     // Obtem a configuracao do modulo.
02908     RioModuleConfig *config = ( RioModuleConfig * ) ap_get_module_config( 
02909                                 parms->server->module_config, &RioModule );
02910 
02911     // Tempo maximo que devemos esperar por um bloco ao usarmos a copia em
02912     // tempo real.
02913     config->WaitTime = atoi( arg );
02914 
02915     // retorna que o comando foi executado com sucesso.
02916     return NULL;
02917 }

void show_stackframe (  ) 

Definition at line 48 of file RioApacheModule.cpp.

00049 {
00050     void *trace[16];
00051     char **messages = (char **)NULL;
00052     int i, trace_size = 0;
00053 
00054     trace_size = backtrace( trace, 16 );
00055     messages = backtrace_symbols( trace, trace_size );
00056     RioErr << "[bt] Execution path:" << endl;
00057     for( i = 0; i < trace_size; ++i )
00058         RioErr << "[bt(" << i << "/" << trace_size << ")] " << messages[i]
00059                << endl;
00060 }

void SignalHandler ( int  sig  ) 

Definition at line 62 of file RioApacheModule.cpp.

00063 {
00064     if( sig == SIGILL )
00065         RioErr << "[RioApacheModule] ILLEGAL INSTRUCTION!. Thread id = " 
00066                << syscall( SYS_gettid ) << endl;
00067     else
00068         RioErr << "[RioApacheModule] SEGMENTATION FAULT!. Thread id = " 
00069                << syscall( SYS_gettid ) << endl;
00070        
00071     show_stackframe();
00072 
00073     _exit( 1 );
00074 }

bool TransferRioFile ( request_rec *  Request,
RioModuleConfig Config,
char *  ServerName,
const char *  FileName,
RioAccess  Access,
RioObjectSize  StartPosition,
RioObjectSize  EndPosition,
bool  SendHeader,
apr_status_t *  ApacheError,
int *  SystemError,
RioResult RioError 
)

Definition at line 411 of file RioApacheModule.cpp.

00416 {
00417     // Guarda a posicao do ultimo "." de FileName (usado para descobrir se a 
00418     // copia deve ou nao ser em tempo real, quando extensoes do arquivo sao
00419     // fornecidas no arquivo de configuracao do servidor).
00420     const char *FileExtensionPos;
00421     // Guarda a posicao do nome do arquivo no diretorio.
00422     const char *FileNamePos;
00423     // Variavel usada para armazenar o valor do campo RIOMODULE_HTTP_FILENAME.
00424     char *HttpFileNameContents;
00425     // Ponteiro para a classe do objeto do RIO.
00426     CRioModule *Rio;
00427     // Variavel booleana usada para indicar se a copia ainda nao terminou, ou 
00428     // seja, se mais blocos devem ser copiados.
00429     bool HasNextBlock; 
00430     // Variavel booleana usada para indicar se a copia deve ser feita em tempo
00431     // real.
00432     bool UseRealTime;
00433     // Variavel usada para armazenar o tamanho de cada bloco.
00434     unsigned int BlockSize;
00435     // Variavel usada para armazenar o tamanho do arquivo (em bytes) que foi
00436     // aberto.
00437     RioObjectSize FileSize;
00438     // Variavel usada para armazenar o numero de blocos do arquivo que acabou 
00439     // de ser aberto.
00440     unsigned int TotalBlocks;
00441     // Ponteiro para a string que armazena os valores covertidos para serem
00442     // colocados no cabecalho da resposta http ao cliente.
00443     char *StrValue;
00444     // Armazena os possiveis erros retornados pelas funcoes do apache 
00445     // (ApacheError), da biblioteca do sistema (SystemError) e do RIO 
00446     // (RioError).
00447     apr_status_t ApacheStatus = APR_SUCCESS;
00448     int SystemStatus = 0;
00449     RioResult RioStatus = S_OK;
00450     // Variavel booleana usada para indicar se algum erro ocorreu.
00451     bool NoError;
00452     // Variavel para criar uma subrequest (para descobrir o tipo do arquivo).
00453     request_rec *SubRequest;
00454 
00455     // Define se devemos ou nao usar a copia em tempo real ao enviar o arquivo
00456     // ao cliente.
00457     if( Config->RealTimeExtensions != NULL )
00458     {
00459         // Busca pela extensao do arquivo (se nao existir uma extensao, a copia
00460         // nao sera em tempo real).
00461         FileExtensionPos = strrchr( FileName, '.' );
00462         if( FileExtensionPos == NULL )
00463             UseRealTime = false;
00464         else 
00465             UseRealTime = ( strstr( Config->RealTimeExtensions, 
00466                                     ++FileExtensionPos ) != NULL );
00467     }
00468     else // Se as extensoes nao foram definidas, entao copiamos tudo em tempo
00469          // nao real.
00470         UseRealTime = false; 
00471  
00472     // Tenta criar o objeto usado para copiar o arquivo, caso nao tenha 
00473     // ocorrido um erro ao processarmos as opcoes ou o arquivo com as
00474     // informacoes dos servidores (se isso foi necessario).
00475     Rio = new CRioModule( Request );
00476     if( Rio == NULL )
00477     {
00478         *SystemError = ENOMEM;        
00479 
00480         #ifdef RIO_DEBUG2
00481         ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, Request,
00482                        "Insufficient memory to create the object module: "
00483                        "SystemError = %u (%s)", *SystemError, 
00484                        strerror( *SystemError ) );
00485         #endif
00486     
00487         return false;    
00488     }
00489 
00490     #ifdef RIO_DEBUG2
00491     ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, Request, 
00492                    "Configuracao para a copia: FileName = %s, ServerName = %s, "
00493                    "WaitTime = %u ms, UseRealTime = %s, User = %s,"
00494                    "Password = %s", FileName, ServerName, Config->WaitTime,
00495                    ( UseRealTime ) ? "on" : "off", Config->User,
00496                    Config->Password );
00497     #endif
00498 
00499     // Coloca o nome do servidor do qual o arquivo se originou no cabecalho da 
00500     // resposta http enviada ao cliente.
00501     apr_table_set( Request->headers_out, RIOMODULE_HTTP_RIOSERVERNAME, 
00502                    ServerName );
00503 
00504     // Coloca o nome do caminho do arquivo (objecto no RIO) que estamos 
00505     // enviando no cabecalho da resposta http enviada ao cliente.
00506     apr_table_set( Request->headers_out, RIOMODULE_HTTP_RIOOBJECTNAME, 
00507                    FileName );
00508 
00509     // Inicializa a variavel que indicando que nenhum erro ocorreu.
00510     NoError = true;
00511 
00512     // Verifica se o objeto foi criado corretamente.
00513     if( Rio->NoError() )
00514     {
00515         // Tenta abrir uma conexao com o servidor.
00516         if( Rio->Start( ServerName, Config->User, Config->Password, 
00517                         Config->BufferSize, Config->FragmentSize, 
00518                         &BlockSize ) )
00519         {
00520             // Primeiramente, vamos procurar a posicao do nome do arquivo no
00521             // seu caminho.
00522             FileNamePos = strrchr( FileName, '/' );
00523             if( FileNamePos == NULL )
00524                 FileNamePos = FileName;
00525             else
00526                 FileNamePos++;
00527 
00528             // Coloca o tipo do arquivo a ser copiado do servidor RIO.
00529             // Cria a subrequest para descobrir o tipo do arquivo.
00530 
00531             #ifdef RIO_DEBUG2
00532             ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, Request,
00533                            "Creating subrequest for file %s", FileNamePos );
00534             #endif
00535 
00536             SubRequest = ap_sub_req_lookup_uri( FileNamePos, Request, NULL );
00537             if( SubRequest == NULL ) 
00538             {
00539                 ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, Request,
00540                                "Error creating subrequest. Using default "
00541                                "type %s",  RIOMODULE_MIME );
00542                 ap_set_content_type( Request, RIOMODULE_MIME );
00543             }
00544             else
00545             {
00546                 #ifdef RIO_DEBUG2
00547                 ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, Request,
00548                                "Subrequest content-type: %s",
00549                                SubRequest->content_type );
00550                 #endif
00551 
00552                 // Define o tipo como o tipo do arquivo descoberto, setando para
00553                 // o default se o tipo nao foi descoberto.
00554                 if( SubRequest->content_type != NULL )
00555                     ap_set_content_type( Request, SubRequest->content_type );
00556                 else
00557                     ap_set_content_type( Request, RIOMODULE_MIME );
00558 
00559                 // Remove a sub-requisicao criada para descobrir o tipo do
00560                 // arquivo.
00561                 ap_destroy_sub_req( SubRequest );
00562             }
00563             // Coloca o nome do arquivo que deve ser usado quando o cliente
00564             // salvar o seu conteudo. 
00565             HttpFileNameContents = apr_psprintf( Request->pool,  
00566                                                  "inline; filename=%s", 
00567                                                  FileNamePos );
00568             if( HttpFileNameContents == NULL )
00569             {                           
00570                 #ifdef RIO_DEBUG2
00571                 ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, Request,
00572                                "Memory error when creating FileName string" );
00573                 #endif
00574             } 
00575             else
00576                 apr_table_set( Request->headers_out, RIOMODULE_HTTP_FILENAME, 
00577                                HttpFileNameContents );
00578             
00579             // Coloca o tamanho de cada bloco no cabecalho da resposta http
00580             // enviada ao cliente.
00581             StrValue = apr_psprintf( Request->pool, "%u", BlockSize );
00582             if( StrValue == NULL )
00583             {
00584                 #ifdef RIO_DEBUG2
00585                 ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, Request,
00586                                "Memory error when creating BlockSize string" );
00587                 #endif
00588             }
00589             else
00590                 apr_table_set( Request->headers_out, 
00591                                RIOMODULE_HTTP_RIOBLOCKSIZE, StrValue );
00592             
00593             // Tentaremos agora abrir o arquivo para leitura.
00594             if( Rio->Open( FileName, Access, UseRealTime, Config->WaitTime,
00595                            StartPosition, EndPosition, SendHeader, &FileSize,
00596                            &TotalBlocks ) )
00597             {
00598                 // Coloca o tamanho do arquivo no cabecalho da resposta http
00599                 // enviada ao cliente.
00600                 StrValue = apr_psprintf( Request->pool, "%lld", FileSize );
00601                 if( StrValue == NULL )
00602                 {
00603                     #ifdef RIO_DEBUG2
00604                     ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, Request,
00605                                    "Memory error when creating FileSize string" 
00606                                  );
00607                     #endif
00608                 }
00609                 else
00610                     apr_table_set( Request->headers_out, 
00611                                    RIOMODULE_HTTP_RIOOBJECTSIZE, StrValue );
00612                 
00613                 // Coloca o numero de blocos do arquivo no cabecalho da resposta
00614                 //  http enviada ao cliente.
00615                 StrValue = apr_psprintf( Request->pool, "%u", TotalBlocks );
00616                 if( StrValue == NULL )
00617                 {
00618                     #ifdef RIO_DEBUG2
00619                     ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, Request,
00620                                  "Memory error when creating TotalBlocks string" 
00621                                  );
00622                     #endif
00623                 }
00624                 else
00625                     apr_table_set( Request->headers_out, 
00626                                    RIOMODULE_HTTP_RIOOBJECTTOTALBLOCKS,  
00627                                    StrValue );
00628 
00629 
00630                 // Coloca a posicao inicial no arquivo a partir da qual enviamos 
00631                 // os dados no cabecalho da resposta http enviada ao cliente.
00632                 StrValue = apr_psprintf( Request->pool, "%lld", StartPosition );
00633                 if( StrValue == NULL )
00634                 {
00635                     #ifdef RIO_DEBUG2
00636                     ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, Request,
00637                                "Memory error when creating StartPosition string" 
00638                                  );
00639                     #endif
00640                 }
00641                 else
00642                     apr_table_set( Request->headers_out, 
00643                                    RIOMODULE_HTTP_RIOOBJECTSTARTPOSITION,  
00644                                    StrValue );
00645 
00646                 // Coloca a posicao final no arquivo a partir da qual enviamos 
00647                 // os dados no cabecalho da resposta http enviada ao cliente.
00648                 StrValue = apr_psprintf( Request->pool, "%lld", EndPosition );
00649                 if( StrValue == NULL )
00650                 {
00651                     #ifdef RIO_DEBUG2
00652                     ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, Request,
00653                                "Memory error when creating EndPosition string" 
00654                                  );
00655                     #endif
00656                 }
00657                 else
00658                     apr_table_set( Request->headers_out, 
00659                                    RIOMODULE_HTTP_RIOOBJECTENDPOSITION,  
00660                                    StrValue );
00661 
00662                 // Coloca a informacao de se enviamos um cabecalho, se 
00663                 // necessario, caso StartPosition seja maior do que 0 e 
00664                 // o arquivo requer o envio deste cabecalho.
00665                 StrValue = apr_psprintf( Request->pool, "%s", 
00666                                          ( SendHeader ) ? "on": "off" );
00667                 if( StrValue == NULL )
00668                 {
00669                     #ifdef RIO_DEBUG2
00670                     ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, Request,
00671                                "Memory error when creating SendHeader string" 
00672                                  );
00673                     #endif
00674                 }
00675                 else
00676                     apr_table_set( Request->headers_out, 
00677                                    RIOMODULE_HTTP_RIOOBJECTSENDHEADER,  
00678                                    StrValue );
00679 
00680                 // Coloca a informacao de se a copia e feita ou nao em tempo
00681                 // Real.
00682                 StrValue = apr_psprintf( Request->pool, "%s", 
00683                                          ( UseRealTime ) ? "on": "off" );
00684                 if( StrValue == NULL )
00685                 {
00686                     #ifdef RIO_DEBUG2
00687                     ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, Request,
00688                                "Memory error when creating UseRealTime string" 
00689                                  );
00690                     #endif
00691                 }
00692                 else
00693                     apr_table_set( Request->headers_out, 
00694                                    RIOMODULE_HTTP_RIOOBJECTUSEREALTIME,  
00695                                    StrValue );
00696 
00697                 // Fica em loop ate terminar a copia do arquivo (porque ela 
00698                 // terminou ou porque algum erro ocorreu).
00699                 do
00700                 {
00701                     // Copia os blocos ate terminarmos ou nao ocorrer um erro.
00702                     NoError = Rio->ProcessNextBlock( &HasNextBlock );
00703                        
00704                 } while( NoError && ( HasNextBlock ) );
00705              
00706                 #ifdef RIO_DEBUG2
00707                 if( !NoError )
00708                 {
00709                     ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, Request,
00710                                    "Error copying file %s", FileName );
00711                 }
00712                 #endif
00713 
00714                 // Tenta fechar o arquivo.
00715                 if ( !Rio->Close() )
00716                 {
00717                     #ifdef RIO_DEBUG2
00718                     ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, Request,
00719                                    "Error closing file %s", FileName );
00720                     #endif
00721                 }
00722 
00723                 // Tenta fechar a sessao com o sevidor.
00724                 if( !Rio->Stop() )
00725                 {
00726                     #ifdef RIO_DEBUG2
00727                     ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, Request,
00728                                    "Error closing session with server %s", 
00729                                    ServerName );
00730                     #endif
00731                 }
00732 
00733             }
00734             else
00735             {
00736                 NoError = false;
00737 
00738                 #ifdef RIO_DEBUG2 
00739                 ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, Request,
00740                                "Error opening file %s", FileName );
00741                 #endif
00742             }
00743         }
00744         else
00745         {
00746             NoError = false;
00747 
00748             #ifdef RIO_DEBUG2 
00749             ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, Request,
00750                            "Error opening session with server %s", 
00751                            ServerName );
00752             #endif
00753         }
00754     } 
00755     else
00756     {
00757         NoError = false;
00758 
00759         #ifdef RIO_DEBUG2 
00760         ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, Request,
00761                        "Error inicializing object of the server %s", 
00762                        ServerName );
00763         #endif
00764     }
00765 
00766     // Obtem os erros, se foram gerados.
00767     if( !NoError )
00768     {
00769         Rio->GetErrors( &ApacheStatus, &SystemStatus, &RioStatus );
00770 
00771         #ifdef RIO_DEBUG2 
00772         ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, Request,
00773                        "Errors when transfering file %s using server %s: "
00774                        "ApacheError = %u, SystemError = %u (%s), "
00775                        "RioError = %08X (%s)", FileName, ServerName, 
00776                        ApacheStatus, SystemStatus, strerror( SystemStatus ), 
00777                        RioStatus, GetErrorDescription( RioStatus ).c_str() );
00778         #endif
00779 
00780         // Somente altera as variaveis que geraram erros.
00781         if( ApacheStatus != APR_SUCCESS )
00782             *ApacheError = ApacheStatus;
00783         if( SystemStatus != 0 )
00784             *SystemError = SystemStatus;
00785         if( RioStatus != S_OK )
00786             *RioError = RioStatus;
00787     }
00788     #ifdef RIO_DEBUG2 
00789     else
00790         ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, Request,
00791                        "The file %s transfer using the server %s has completed "
00792                        "successfully.", FileName, ServerName );
00793     #endif
00794 
00795     // Remove o objeto do modulo.
00796     delete Rio;
00797 
00798     return NoError;
00799 }

Generated on Wed Jul 4 16:03:30 2012 for RIO by  doxygen 1.6.3