00001 /* 00002 * Copyright (C) 2010, Edmundo Albuquerque de Souza e Silva. 00003 * 00004 * This file may be distributed under the terms of the Q Public License 00005 * as defined by Trolltech AS of Norway and appearing in the file 00006 * LICENSE.QPL included in the packaging of this file. 00007 * 00008 * THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING 00009 * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00010 * PURPOSE. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, 00011 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING 00012 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 00013 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 00014 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 00015 * 00016 */ 00017 00018 #ifndef __RIOMODULE_H_ 00019 #define __RIOMODULE_H_ 00020 00021 // Unidades usadas do apache 00022 #include <httpd.h> 00023 00024 // Unidade usada do sistema 00025 #include <pthread.h> 00026 00027 // Define a classe que implementa o modulo do apache 00028 00029 // Unidades usadas do RIO. 00030 #include "RioInterface.h" 00031 #include "RioInterfaceTypes.h" 00032 #include "CircularBuffer.h" 00033 #include "RioModuleTypes.h" 00034 00035 // Define a classe principal do modulo. 00036 class CRioModule 00037 { 00038 private: 00039 // Variavel usada para indicar se o objeto foi inicializado (ou seja, 00040 // se uma conexo ativa com o servidor RIO foi criada). 00041 bool m_Started; 00042 // Ponteiro para a requisicao com os dados do pedido HTTP. 00043 request_rec *m_Request; 00044 // Ponteiro para a sessao associada a copia. 00045 CRioSession *m_Session; 00046 // Variavel booleana que indica se uma sessao foi aberta. 00047 bool m_isSessionOpen; 00048 // Ponteiro para o stream associado a copia. 00049 CRioStream *m_Stream; 00050 // Variavel booleana que indica se um stream foi aberto. 00051 bool m_isStreamOpen; 00052 // Objeto associado ao arquivo a ser copiado. 00053 CRioObject *m_Object; 00054 // Variavel booleana que indica se um objeto foi aberto. 00055 bool m_isObjectOpen; 00056 // Variavel booleana que informa se a copia do arquivo deve ou nao ser 00057 // em tempo real. 00058 bool m_UseRealTime; 00059 // Tempo maximo da copia de um bloco, para os arquivos copiados atraves 00060 // de tempo real. 00061 int m_WaitTime; 00062 // Servidor que sera usado pela conexao. Se o arquivo .rio estiver 00063 // vazio ou nao existir, sera usado o servidor default definido pela 00064 // configuracao do modulo. 00065 char *m_ServerName; 00066 // Nome do arquivo que esta sendo copiado. Ele e passado como parametro 00067 // para o modulo (parametro args de m_Request. 00068 // Obs: Se necessario, podemos futuramente mudar isso, pois o modulo 00069 // possui acesso a todos os campos da requisicao. 00070 char *m_FileName; 00071 // Tipo de acesso ao arquivo. 00072 RioAccess m_Access; 00073 // Tamanho do arquivo a ser copiado. 00074 RioObjectSize m_FileSize; 00075 // Variaveis usadas para armazenar os erros ocorridos durante a copia 00076 // do arquivo. 00077 apr_status_t m_ApacheStatus; // Erro gerado pelas funcoes da biblioteca 00078 // do apache. 00079 int m_SystemStatus; // Erro gerado pelas funcoes da biblioteca do 00080 // sistema. 00081 RioResult m_RioStatus; // Erro gerado pelas funcoes da biblioteca do 00082 // RIO. 00083 // Buffer circular usado para armazenar os blocos lidos do servidor e 00084 // variaveis para controla-lo. 00085 CircularBuffer *m_CircularBuffer; 00086 // Buffer para armazenar o ultimo bloco lido (ou, no futuro, escrito) do 00087 // (para) o servidor RIO (antes de copia-lo para o buffer circular, no 00088 // caso da leitura? ou vamos tambem usar o buffer na escrita?). 00089 char *m_RioBuffer; 00090 // Buffer para armazenar o proximo bloco a ser enviado (ou, no futuro, 00091 // ser recebido) para (do) cliente. 00092 char *m_ApacheBuffer; 00093 // Numero do proximo bloco do arquivo a ser lido(ou escrito) do (no) 00094 // servidor RIO. 00095 RioBlock m_RioBlock; 00096 // Numero do proximo bloco do arquivo a ser enviado ao cliente. 00097 RioBlock m_SendBlock; 00098 // Numero total de blocos do arquivo a ser copiado para o cliente. 00099 unsigned int m_TotalBlocks; 00100 // Tamanho de cada bloco. 00101 unsigned int m_BlockSize; 00102 // Tamanho de cada fragmento enviado ao cliente. 00103 unsigned int m_FragmentSize; 00104 // Deslocamento em relacao ao inicio do primeiro bloco copiado para o 00105 // cliente. 00106 RioObjectSize m_StartFirstBlock; 00107 // Ultimo byte do arquivo que deve ser copiado. 00108 RioObjectSize m_EndPosition; 00109 // Valor booleano para sabermos se estamos copiando o primeiro bloco 00110 // (para o qual e possivel enviarmos somente a sua parte final) para o 00111 // cliente. 00112 bool m_isFirstBlock; 00113 // Indica se uma copia para o cliente esta em progresso. 00114 bool m_isReadingFile; 00115 // Variavel de condicao usada pela thread de copia para esperar pelo 00116 // inicio da copia de blocos para o cliente. 00117 pthread_cond_t m_ReadStarted; 00118 // Variavel de condicao usada pelas funcoes que iniciam a copia para 00119 // esperar que a thread de copia para o cliente bloqueie em 00120 // m_ReadStarted. 00121 pthread_cond_t m_ThreadBlocked; 00122 // Mutex e variavel de condicao usadas ao copiarmos os blocos atraves 00123 // de uma conexao em tempo real. O mutex somente foi criado para 00124 // podermos usar a funcao da variavel de condicao que permite uma 00125 // espera com timeout, necessaria para esperarmos pelo bloco por um 00126 // dado intervalo de tempo. 00127 pthread_mutex_t m_ReadMutex; // Mutex usado pela leitura do bloco. 00128 pthread_cond_t m_ReadCond; // Variavel de condicao usada pela leitura. 00129 // Identificador da thread usada para copiar os blocos e coloca-los no 00130 // buffer Blocks. 00131 pthread_t m_ReadThread; 00132 // Variavel usada para indicar se devemos parar a execucao da thread. 00133 bool m_ThreadCanceled; 00134 // Mutex para acesso exclusivo as variaveis da classe. 00135 pthread_mutex_t m_Mutex; 00136 00137 /** 00138 * Funcao para enviar dados ao cliente, armazenados no buffer passado 00139 * no parametro Data. O numero de bytes e dado em DataSize. Os dados 00140 * serao enviados em fragmentos de tamanho de no maximo m_FragmentSize 00141 * bytes (note que o ultimo fragmento pode ser menor, caso DataSize nao 00142 * seja multiplo de m_FragmentSize). 00143 * @param Data ponteiro para o buffer com os dados (o bloco atual). 00144 * @param DataSize tamanho dos dados (quando a implementacao estiver 00145 * completa, este tamanho sera igual ao do bloco para os blocos 00146 * intermediarios mas podera nao ser este tamanho para o bloco inicial - 00147 * caso a copia nao comece no inicio do arquivo - e para o bloco final - 00148 * pois o tamanho do arquivo nao e necessariamente multiplo do bloco-). 00149 * @return true se os dados foram enviados com sucesso e false em caso 00150 * contrario (neste caso, m_ApacheStatus indicara o erro que ocorreu). 00151 */ 00152 bool SendBlock( const char *Data, unsigned int DataSize ); 00153 /** 00154 * Funcao para receber dados do cliente, os armazenando no buffer 00155 * passado no parametro Data, sendo que no maximo DataSize bytes 00156 * serao recebidos. 00157 * @param Data ponteiro para o buffer com os dados (o bloco atual). 00158 * @param DataSize ponteiro para o tamanho maximo dos dados. Este 00159 * parametro sera alterado pela funcao para o numero de bytes 00160 * realmente lidos do cliente (este valor pode ser menor do que o 00161 * valor passado, se o cliente enviou menos dados do que o desejado). 00162 * @return true se os dados foram recebidos com sucesso e false em caso 00163 * contrario (neste caso, m_ApacheStatus indicara o erro que ocorreu). 00164 */ 00165 bool ReceiveBlock( char *Data, unsigned int DataSize ); 00166 /** 00167 * Funcao para terminar o envio de dados ao client. 00168 * @return true se a copia foi terminada com sucesso, ou false em caso 00169 * contrario (neste caso, m_ApacheStatus indicara o erro que ocorreu). 00170 */ 00171 bool TerminateCopyToClient(); 00172 /** 00173 * Funcao para abrir a sessao com o servidor RIO, com o servidor dado 00174 * pelo parametro m_ServerName. 00175 * @param ServerName ponteiro para o nome do servidor RIO. 00176 * @param UserName ponteiro para o nome do usuario do RIO. 00177 * @param UserPassword ponteiro para a senha do usuario apontado por 00178 * UserName. 00179 * @return true se a sessao foi criada com sucesso e false em caso 00180 * contrario (neste caso, m_RioStatus indicara o erro que ocorreu). 00181 */ 00182 bool OpenRioSession( char *ServerName, char *UserName, 00183 char *UserPassword ); 00184 /** 00185 * Funcao para fechar a sessao apontada por m_Session. 00186 * @return true se a sessao foi fechada com sucesso e false em caso 00187 * contrario (neste caso, m_RioStatus indicara o erro que ocorreu). 00188 */ 00189 bool CloseRioSession(); 00190 /** 00191 * Funcao para abrir um stream associado a sessao apontada pelo 00192 * ponteiro m_Session. 00193 * @return true se o stream foi criada com sucesso e false em caso 00194 * contrario (neste caso, m_RioStatus indicara o erro que ocorreu). 00195 */ 00196 bool OpenRioStream( bool UseRealTime, RioStreamDirection Direction ); 00197 /* Funcao para fechar o stream apontado por m_Stream. 00198 * @param UseRealTime true se a copia deve ser em tempo real (UDP) ou 00199 * false se a copia deve ser em tempo nao real (TCP). 00200 * @param Direction direcao do stream (leitura, escrita e 00201 * leitura/escrita). 00202 * @return true se o stream foi fechada com sucesso e false em caso 00203 * contrario (neste caso, m_RioStatus indicara o erro que ocorreu). 00204 */ 00205 bool CloseRioStream(); 00206 /* 00207 * Funcao para abrir um objeto do RIO, cujo nome de caminho no RIO e 00208 * dado pelo parametro FileName. 00209 * @param FileName ponteiro para o caminho do objeto a ser aberto. 00210 * @param Access tipo de acesso desejado ao objeto. 00211 * @return true se o objeto foi aberto com sucesso e false em caso 00212 * contrario (neste caso, m_RioStatus indicara o erro que ocorreu). 00213 */ 00214 bool OpenRioObject( char *FileName, RioAccess Access ); 00215 /* 00216 * Funcao para fechar um objeto do RIO, cujo objeto e apontado pelo 00217 * ponteiro m_Object. 00218 * @return true se o objeto foi fechado com sucesso e false em caso 00219 * contrario (neste caso, m_RioStatus indicara o erro que ocorreu). 00220 */ 00221 bool CloseRioObject(); 00222 /* 00223 * Funcao para ler um bloco do RIO, cujo objeto e apontado pelo ponteiro 00224 * m_Object. 00225 * @param Block bloco a ser lido do arquivo. 00226 * @return true se o bloco foi lido com sucesso e copiado para o buffer 00227 * apontado por m_RioBuffer, e false em caso contrario (neste caso, 00228 * m_RioStatus indicara o erro que ocorreu). 00229 */ 00230 bool ReadRioObjectBlock( RioBlock Block ); 00231 /* 00232 * Funcao para salvar um bloco no RIO, cujo objeto e apontado pelo 00233 * ponteiro m_Object. 00234 * @param Block bloco a ser salvo no arquivo. 00235 * @return true se o bloco foi salvo com sucesso, e false em caso 00236 * contrario (neste caso, m_RioStatus indicara o erro que ocorreu). 00237 */ 00238 bool WriteRioObjectBlock( RioBlock Block ); 00239 /** 00240 * Funcao usada pela thread que copia os blocos. 00241 * @param Class ponteiro para o objeto da classe que criou a thread. 00242 * @return valor nulo. 00243 */ 00244 static void *ReadThreadFunction( void *Class ); 00245 /** 00246 * Funcao para cancelar a copia. 00247 * @return true se a copia foi cancelada com sucesso ou false se algum 00248 * erro ocorreu ao cancelar a copia. 00249 */ 00250 bool CancelCopy(); 00251 /** 00252 * Funcao para enviar um cabecalho antes dos dados do arquivo, caso o 00253 * arquivo necessite do envio deste cabecalho. 00254 * @param FileName nome do arquivo que desejamos avaliar se o envio do 00255 * cabecalho e necessario. 00256 * @return true a funcao foi executada com sucesso e false, em caso 00257 * contrario, ou seja, se foi necessario enviar o cabecalho mais um 00258 * erro ocorreu ao fazermos isso. 00259 */ 00260 bool SendFileHeader( const char *FileName ); 00261 00262 public: 00263 /** 00264 * Construtor da classe RioModule, para criar um novo objeto desta 00265 * classe. 00266 * @param Request ponteiro para a requisicao associada a conexao http 00267 * com o cliente. 00268 */ 00269 CRioModule( request_rec *Request ); 00270 /** 00271 * Destrutor da classe RioModule, usado quando um objeto e removido. 00272 */ 00273 ~CRioModule(); 00274 /** 00275 * Funcao para inicializar o objeto da classe RioModule (ou seja, abrir 00276 * a conexao e o stream). 00277 * @param ServerName nome do servidor a que vamos nos conectar. 00278 * @param UserName nome do usuario para o qual desejamos abrir uma 00279 * sessao. 00280 * @param UserPassword senha do usuario UserName no servidor. 00281 * @param BufferSize numero de entradas do buffer de recepcao. 00282 * @param FragmentSize tamanho dos fragmentos enviados ao cliente. 00283 * @param BlockSize ponteiro para um inteiro nao sinalizado usado para 00284 * armazenar o tamanho de cada bloco do servidor (que sera impresso no 00285 * cabecalho do pedido). 00286 * @return true se a inicializacao do objeto foi completada com sucesso 00287 * ou false em caso contrario. 00288 */ 00289 bool Start( char *ServerName, char *UserName, char *UserPassword, 00290 unsigned int BufferSize, unsigned int FragmentSize, 00291 unsigned int *BlockSize ); 00292 /* 00293 * Funcao para parar o objeto da classe RioModule (ou seja, fechar a 00294 * conexao e o stream). 00295 * @return true se o objeto foi paradocom sucesso ou false em caso 00296 * contrario. 00297 */ 00298 bool Stop(); 00299 /** 00300 * Funcao para abrir um arquivo do servidor RIO para copiar os seus 00301 * blocos. O tipo de transmissao (tempo real ou nao) dependera do 00302 * servidor escolhido ao inicializarmos o objeto. 00303 * Obs: Os outros parametros da funcao (alem de FileName e Access), 00304 * somente serao usados se estivermos transferindo um arquivo do 00305 * servidor para o cliente. 00306 * @param FileName nome do arquivo a ser aberto. 00307 * @param Access tipo de acesso desejado ao objeto. 00308 * @param UseRealTime valor booleano que, se true, indica que a copia 00309 * do arquivo devera ser feita em tempo real. 00310 * @param WaitTime tempo de espera por cada bloco, em milisegundos, se 00311 * o arquivo for copiado em tempo real. 00312 * @param StartPosition posicao inicial do arquivo da qual a copia deve 00313 * ser comecada. Se StartPosition for positivo, entao as posicoes serao 00314 * contadas a partir do inicio do arquivo. Porem, se o valor for 00315 * negativo, as posicoes serao contadas a partir do final do arquivo 00316 * (o valor usado para implementarmos o cabecalho Range do HTTP). 00317 * @param EndPosition posicao do byte final a ser enviado. Se 00318 * EndPosition for igual a -1, entao o arquivo sera enviado da posicao 00319 * obtida ao processar StartPosition ate o seu ultimo byte. 00320 * @param SendHeader true se devemos enviar o cabecalho ou false em caso 00321 * contrario. 00322 * @param FileSize ponteiro para o tipo RioObjectSize usado para 00323 * armazenar o tamanho do arquivo. 00324 * @param TotalBlocks ponteiro para um inteiro nao sinalizado usado para 00325 * armazenar o numero de blocos do arquivo. 00326 * @return true se o arquivo foi aberto com sucesso ou false se o 00327 * arquivo nao foi aberto com sucesso. 00328 */ 00329 bool Open( const char *FileName, RioAccess Access, bool UseRealTime, 00330 unsigned int WaitTime, RioObjectSize StartPosition, 00331 RioObjectSize EndPosition, bool SendHeader, 00332 RioObjectSize *FileSize, unsigned int *TotalBlocks ); 00333 /** 00334 * Funcao para fechar o ultimo arquivo aberto, terminando qualquer 00335 * copia em andamento. 00336 * @return true se o arquivo foi fechado com sucesso ou false se algum 00337 * erro ocorreu ao fecharmos o arquivo. 00338 */ 00339 bool Close(); 00340 /** 00341 * Funcao para ler e depois enviar o proximo bloco do arquivo para o 00342 * cliente, ou receber o proximo bloco do cliente e depois grava-lo no 00343 * arquivo. A operacao executada dependera do parametro Access passado 00344 * ao abrir o arquivo. 00345 * @param HasNextBlock true se existe mais um bloco para ser copiado ou 00346 * false caso nao existam mais blocos para serem copiados. 00347 * @return true se a copia do bloco atual foi completada com sucesso ou 00348 * false se algum erro ocorreu durante esta copia. 00349 */ 00350 bool ProcessNextBlock( bool *HasNextBlock ); 00351 /** 00352 * Funcao para saltar para um outro ponto do arquivo. 00353 * @param StartPosition posicao inicial para onde desejamos saltar. 00354 * @return true se a copia foi reiniciada, nesta posicao, com sucesso, 00355 * ou false se algum erro ocorreu. 00356 */ 00357 bool JumpToPosition( RioObjectSize StartPosition ); 00358 /** 00359 * Funcao para copiar um arquivo (aberto pela funcao open para escrita) 00360 * do apache para o servidor RIO. 00361 * @return true se o arquivo foi copiado com sucesso ou false em caso 00362 * contrario. 00363 */ 00364 /** 00365 * Funcao para retornar os codigos de erro caso alguma das funcoes 00366 * acima retorne false. 00367 * @param ApacheStatus ponteiro para a variavel que recebera o codigo de 00368 * erro retorado pelas funcoes do apache. 00369 * @param SystemStatus ponteiro para a variavel que recebera o codigo de 00370 * erro retornado pelas funcoes da biblioteca do sistema. 00371 * @param RioStatus ponteiro para a variavel que recebera o codigo de 00372 * erro retornado pelas funcoes do RIO. 00373 */ 00374 void GetErrors( apr_status_t *ApacheStatus, int *SystemStatus, 00375 RioResult *RioStatus ); 00376 /** 00377 * Funcao para verificar se algum erro ocorreu ao executarmos uma das 00378 * funcoes da classe. 00379 * @return true se a funcao foi executada com sucesso ou false em caso 00380 * contrario. 00381 */ 00382 bool NoError(); 00383 /** 00384 * Funcao para gerar um sinal para a variavel de condicao m_CopyCond 00385 * (esta funcao e usada pela callback chamada apos o recebimento de 00386 * um bloco). 00387 * @return true se o sinal foi enviado com sucesso e false se algum 00388 * erro ocorreu ao enviar o sinal. 00389 */ 00390 bool SendSignal(); 00391 /** 00392 * Funcao para obter um ponteiro para a requisicao HTTP associada a 00393 * copia. 00394 * @return ponteiro para a requisicao. 00395 */ 00396 request_rec *GetRequest(); 00397 00398 }; 00399 00400 #endif /* __RIOMODULE_H_*/ 00401