#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) |
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 }