br.gov.ans.tiss.nucleo
Class Conexao

java.lang.Object
  extended by br.gov.ans.tiss.nucleo.Conexao
All Implemented Interfaces:
java.io.Serializable, java.util.EventListener, javax.net.ssl.HandshakeCompletedListener

public class Conexao
extends java.lang.Object
implements java.io.Serializable, javax.net.ssl.HandshakeCompletedListener

Uma conexão bidirecional entre um prestador e uma operadora. Responde pela transmissão de mensagens de uma ponta a outra, incluindo codificação base 64 e criptografia.

See Also:
Serialized Form

Field Summary
static java.lang.String ACK
          Mensagem de controle - ACK (acusa recebimento normal de mensagem).
static int BLKSIZE
          Tamanho do bloco de recepção.
private  boolean chaveCompleta
          A chave RIJNDAEL já foi complementada?
private  java.lang.String chaveRijndael
          A chave secundária RIJNDAEL.
static java.lang.String COMMIT
          Mensagem de controle - COMMIT (mensagem armazenada com segurança).
private  AgenteRijndael criptografador
          Uma instância do agente de criptografia, usado sobre as mensagens.
static java.lang.String CTL_PREFIX
          Prefixo de todas as mensagens de controle.
static java.lang.String EOM
          Mensagem de controle - EOM (fim de mensagem).
static java.lang.String EOT
          Mensagem de controle - EOT (fim de transmissão).
private  java.io.PrintWriter gravadora
          O stream de gravação.
static java.lang.String HANDSHAKE
          Frase padrão que sinaliza um pedido de chave secundária para criptografia RIJNDAEL.
private  java.lang.String idPontaA
          O identificador do prestador ou da operadora que é a ponta local da conexão (ponta A).
private  java.lang.String idPontaB
          O identificador do prestador ou operadora que está na ponta remota da conexão (ponta B).
private  java.io.BufferedReader leitora
          O stream de leitura, sempre bufferizado.
private  java.util.Date m_timer
          Controle de timeout para o "handshake" SSL, quando se está usando este protocolo.
private  java.beans.PropertyChangeSupport propertySupport
          Suporte ao registro de listeners para mudanças de valores em propriedades deste bean.
static int SCK_TIMEOUT
          Timeout do soquete, em milisegundos.
private  java.net.Socket soquete
          O soquete comum.
private  javax.net.ssl.SSLSocket soqueteSSL
          O soquete SSL que a conexão opera.
private  java.lang.String ultimoErro
          O último erro que a conexão detectou.
private  boolean w_handshake
          Flag que indica se o handshake SSL já foi completado.
protected  BolsaPropriedadesTiss w_pb
          Uma referência à bolsa de propriedades TISS.
 
Constructor Summary
Conexao()
          Construtor vazio.
Conexao(Nodo pNodo)
          Constrói conexão a partir de um nodo.
Conexao(java.net.Socket pSock)
          Constrói uma conexão a partir de um soquete pronto.
Conexao(javax.net.ssl.SSLSocket pSock)
          Primo irmão do construtor a partir de um soquete.
 
Method Summary
 void abreConexao(Nodo pNodo)
          Estabelece uma conexão de rede com o nodo remoto, procurando detectar automaticamente as características da conexão.
 void abreConexaoComum(java.lang.String pHost, java.lang.Integer pPorta)
          Abre uma conexão sem SSL contra um host e uma porta dados.
 void addPropertyChangeListener(java.beans.PropertyChangeListener listener)
          Adiciona um listener para mudanças em propriedades do bean.
 void completaChaveRijndael()
          Completa chave RIJNDAEL de criptografia, combinando o challenge recebido com outra transformação.
 void completaChaveRijndael(java.lang.String pComplemento)
          Completa chave RIJNDAEL de criptografia, combinando o challenge recebido com outra transformação.
protected  java.lang.String decriptaMensagem(char[] pFonte)
          Decodifica (base 64), decripta e expande uma mensagem codificada.
protected  char[] encriptaMensagem(java.lang.String pFonte)
          Comprime, encripta e codifica (base 64) uma mensagem dada.
 void fechaConexao()
          Fecha o soquete e limpa o ambiente.
 void fimTransmissao()
          Transmite uma mensagem EOT (end of transmission) ao destinatário.
 java.lang.String getChaveRijndael()
          Getter para chaveRijndael.
 AgenteRijndael getCriptografador()
          Getter para criptografador.
 java.lang.String getIdPontaA()
          Getter para idPontaA.
 java.lang.String getIdPontaB()
          Getter para idPontaB.
 java.net.Socket getSoquete()
          Getter para soquete.
 java.net.Socket getSoqueteEfetivo()
          Retorna o soquete efetivamente em uso na conexão.
 javax.net.ssl.SSLSocket getSoqueteSSL()
          Getter para soquete.
 java.lang.String getUltimoErro()
          Getter para a última mensagem de erro detectada pela classe.
 void handshakeCompleted(javax.net.ssl.HandshakeCompletedEvent he)
          Implementação do método da interface HandshakeCompletedListener.
 void inicializaChaveRijndael(java.lang.String p_chaveRijndael)
          Setter para chaveRijndael.
 boolean isChaveCompleta()
          Getter para o indicador de chave complementada
static boolean isControle(java.lang.String pBase)
          Diz se uma dada mensagem recebida é ou não uma mensagem de controle.
 boolean isProxied()
          Verifica se uma conexão deve se fazer via proxy, examinando a propriedade proxy.host (se não for nula, assume que deve-se usar proxy).
 boolean proxyConnect(Nodo pNodo)
          Conecta-se a um proxy server através do soquete comum.
 java.lang.String recebeMensagem()
          Recebe uma mensagem, sempre tentando reverter a compressão/ criptografia/ codificação.
 java.lang.String recebeMensagem(boolean pDecripta)
          Recebe uma mensagem do nodo remoto, podendo-se optar por tentar ou não reverter a compressão/ criptografia/ codificação.
 void removePropertyChangeListener(java.beans.PropertyChangeListener listener)
          Remove um listener para mudanças em propriedades do bean.
protected  void setChaveRijndael(java.lang.String p_chaveRijndael)
          Setter para chaveRijndael.
 void setCriptografador(AgenteRijndael criptografador)
          Setter para criptografador.
 void setIdPontaA(java.lang.String idPontaA)
          Setter para idPontaA.
 void setIdPontaB(java.lang.String idPontaB)
          Setter para idPontaB.
 void setSoquete(java.net.Socket soquete)
          Setter para soquete.
 java.lang.String transmiteMensagem(java.lang.String pMensagem)
          Transmite uma mensagem, tentando, sempre, codificá-la antes.
 java.lang.String transmiteMensagem(java.lang.String pMensagem, boolean pEncripta)
          Transmite uma mensagem, podendo-se optar, neste caso, por forçar a transmissão em texto claro, sem compressão, criptografia ou codificação.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

propertySupport

private java.beans.PropertyChangeSupport propertySupport
Suporte ao registro de listeners para mudanças de valores em propriedades deste bean.


w_pb

protected BolsaPropriedadesTiss w_pb
Uma referência à bolsa de propriedades TISS.


BLKSIZE

public static final int BLKSIZE
Tamanho do bloco de recepção. A conexão lê do soquete em blocos deste tamanho.

See Also:
Constant Field Values

HANDSHAKE

public static final java.lang.String HANDSHAKE
Frase padrão que sinaliza um pedido de chave secundária para criptografia RIJNDAEL. O cliente manda isto para o servidor, que deve, em seguida, transmitir a chave.

See Also:
Constant Field Values

ACK

public static final java.lang.String ACK
Mensagem de controle - ACK (acusa recebimento normal de mensagem). O receptor manda para o transmissor a cada fim de mensagem.

See Also:
Constant Field Values

EOT

public static final java.lang.String EOT
Mensagem de controle - EOT (fim de transmissão). O transmissor envia para o receptor quando não tem mais nada a mandar.

See Also:
Constant Field Values

EOM

public static final java.lang.String EOM
Mensagem de controle - EOM (fim de mensagem). Não tem uso atualmente. Deve ser enviada se a mensagem está dividida em partes, ao final de todas as partes.

See Also:
Constant Field Values

COMMIT

public static final java.lang.String COMMIT
Mensagem de controle - COMMIT (mensagem armazenada com segurança). Sinaliza para o transmissor que a mensagem pode ser apagada de suas filas, pois o receptor garante tê-la armazenado de forma segura.

See Also:
Constant Field Values

CTL_PREFIX

public static final java.lang.String CTL_PREFIX
Prefixo de todas as mensagens de controle. Mensagens com este prefixo têm tratamento especial no protocolo.

See Also:
Constant Field Values

SCK_TIMEOUT

public static final int SCK_TIMEOUT
Timeout do soquete, em milisegundos. Decorrido este tempo sem que tenha havido transmissão, entende-se que a outra ponta está morta, e que a comunicação pode ter sido interrompida.

See Also:
Constant Field Values

m_timer

private java.util.Date m_timer
Controle de timeout para o "handshake" SSL, quando se está usando este protocolo. Se o "handshake" não terminar neste prazo, supõe-se que a outra ponta não suporta SSL, e tenta-se usar soquetes comuns.


soqueteSSL

private javax.net.ssl.SSLSocket soqueteSSL
O soquete SSL que a conexão opera.


leitora

private java.io.BufferedReader leitora
O stream de leitura, sempre bufferizado.


gravadora

private java.io.PrintWriter gravadora
O stream de gravação. Usamos um PrintWriter por comodidade.


ultimoErro

private java.lang.String ultimoErro
O último erro que a conexão detectou.


w_handshake

private boolean w_handshake
Flag que indica se o handshake SSL já foi completado.


soquete

private java.net.Socket soquete
O soquete comum.


chaveRijndael

private java.lang.String chaveRijndael
A chave secundária RIJNDAEL.


criptografador

private AgenteRijndael criptografador
Uma instância do agente de criptografia, usado sobre as mensagens.


idPontaA

private java.lang.String idPontaA
O identificador do prestador ou da operadora que é a ponta local da conexão (ponta A).


idPontaB

private java.lang.String idPontaB
O identificador do prestador ou operadora que está na ponta remota da conexão (ponta B).


chaveCompleta

private boolean chaveCompleta
A chave RIJNDAEL já foi complementada?

Constructor Detail

Conexao

public Conexao()
        throws java.lang.Exception
Construtor vazio. Inicializa o ambiente sem tentar abrir conexão.

Throws:
java.lang.Exception - .

Conexao

public Conexao(Nodo pNodo)
        throws java.lang.Exception
Constrói conexão a partir de um nodo. Um nodo define completamente o endereço da outra ponta. Assim, além da inicialização, tenta-se abrir uma conexão real.

Parameters:
pNodo - O nodo destinatário.
Throws:
java.lang.Exception - .

Conexao

public Conexao(java.net.Socket pSock)
        throws java.lang.Exception
Constrói uma conexão a partir de um soquete pronto. Supõe que a conexão de rede já foi aberta. Além de inicializar, cria os "streams" de leitura e de gravação a partir do soquete recebido.

Parameters:
pSock - O soquete.
Throws:
java.lang.Exception - .

Conexao

public Conexao(javax.net.ssl.SSLSocket pSock)
        throws java.lang.Exception
Primo irmão do construtor a partir de um soquete. Idêntico a ele, mas constrói a partir de um soquete SSL.

Parameters:
pSock - O soquete SSL.
Throws:
java.lang.Exception - .
Method Detail

addPropertyChangeListener

public void addPropertyChangeListener(java.beans.PropertyChangeListener listener)
Adiciona um listener para mudanças em propriedades do bean.

Parameters:
listener - O listener.

removePropertyChangeListener

public void removePropertyChangeListener(java.beans.PropertyChangeListener listener)
Remove um listener para mudanças em propriedades do bean.

Parameters:
listener - O listener a ser removido.

getSoqueteSSL

public javax.net.ssl.SSLSocket getSoqueteSSL()
Getter para soquete.

Returns:
O soquete comum em uso.

handshakeCompleted

public void handshakeCompleted(javax.net.ssl.HandshakeCompletedEvent he)
Implementação do método da interface HandshakeCompletedListener.

Specified by:
handshakeCompleted in interface javax.net.ssl.HandshakeCompletedListener
Parameters:
he - O evento.

proxyConnect

public boolean proxyConnect(Nodo pNodo)
Conecta-se a um proxy server através do soquete comum. Isto é usado sempre que se define que as conexões são via proxy

Parameters:
pNodo - O nodo destinatário.
Returns:
TRUE se a conexão com o proxy foi bem sucedida; false em caso contrário.

abreConexao

public void abreConexao(Nodo pNodo)
                 throws java.io.IOException,
                        java.net.SocketException,
                        java.net.UnknownHostException,
                        TissCommException,
                        java.security.NoSuchAlgorithmException,
                        java.security.KeyManagementException
Estabelece uma conexão de rede com o nodo remoto, procurando detectar automaticamente as características da conexão. É, de longe, o método mais complexo da classe. A abertura da conexão se faz assim: (a) Se houver proxy definido (só se suporta proxy HTTP), tenta se conectar ao proxy e pedir túnel para o destino final (transmite comando CONNECT contra o host destino). (b) Se o proxy não responder com código 200 (OK), tenta se conectar usando SSL. Neste caso, faz a conexão e transmite o pedido de chave secundária, o que provoca a entrada no handshake SSL. (c) Finalmente, se o handshake SSL não for bem sucedido, assume que o host remoto não está suportando SSL, e tenta se conectar via soquetes comuns, enviando o mesmo pedido de chave RIJNDAEL secundária. (d) Se nada disso funcionar, avisa que a conexão não é possível.

Parameters:
pNodo - O nodo destinatário.
Throws:
java.io.IOException - .
java.net.SocketException - .
java.net.UnknownHostException - .
br.gov.ans.tiss.comuns.TissCommException - .
java.security.NoSuchAlgorithmException - .
java.security.KeyManagementException - .
TissCommException

isProxied

public boolean isProxied()
Verifica se uma conexão deve se fazer via proxy, examinando a propriedade proxy.host (se não for nula, assume que deve-se usar proxy).

Returns:
TRUE ou FALSE, dependendo do caso.

abreConexaoComum

public void abreConexaoComum(java.lang.String pHost,
                             java.lang.Integer pPorta)
                      throws java.lang.Exception
Abre uma conexão sem SSL contra um host e uma porta dados. Originalmente, isto fazia parte do método de abertura de conexão. Quando o suporte a proxy com túneis foi introduzido, separamos esta parte do código, para evitar redundância.

Parameters:
pHost - Hostname ou IP do destino.
pPorta - Porta TCP destinatária.
Throws:
java.lang.Exception - .

fechaConexao

public void fechaConexao()
Fecha o soquete e limpa o ambiente.


isControle

public static boolean isControle(java.lang.String pBase)
Diz se uma dada mensagem recebida é ou não uma mensagem de controle. A classe acha que uma mensagem é de controle quando seu texto começa pelo prefixo de controle (CTL_PREFIX).

Parameters:
pBase - O texto da mensagem.
Returns:
TRUE ou FALSE, dependendo do caso.

encriptaMensagem

protected char[] encriptaMensagem(java.lang.String pFonte)
Comprime, encripta e codifica (base 64) uma mensagem dada. Note que mensagens de controle nunca são comprimidas, e que a criptografia só se faz se a chave secundária RIJNDAEL estiver definida.

Parameters:
pFonte - O texto claro da mensagem.
Returns:
A mensagem tratada.

decriptaMensagem

protected java.lang.String decriptaMensagem(char[] pFonte)
                                     throws java.util.zip.DataFormatException
Decodifica (base 64), decripta e expande uma mensagem codificada. Note que as mensagens só são decriptadas se houver chave secundária RIJNDAEL definida, e que a descompressão só se dá se não se tratar de mensagem de controle.

Parameters:
pFonte - A mensagem codificada, encriptada e comprimida.
Returns:
A mensagem em texto claro.
Throws:
java.util.zip.DataFormatException - .

transmiteMensagem

public java.lang.String transmiteMensagem(java.lang.String pMensagem)
Transmite uma mensagem, tentando, sempre, codificá-la antes. É um envelope de conveniência para um método mais primitivo.

Parameters:
pMensagem - A mensagem a transmitir.
Returns:
NULL, se a transmissão tiver sido bem sucedida, ou a mensagem de erro, se for o caso.

transmiteMensagem

public java.lang.String transmiteMensagem(java.lang.String pMensagem,
                                          boolean pEncripta)
Transmite uma mensagem, podendo-se optar, neste caso, por forçar a transmissão em texto claro, sem compressão, criptografia ou codificação.

Parameters:
pMensagem - A mensagem a transmitir.
pEncripta - Flag de compressão/ criptografia/ codificação.
Returns:
NULL, se tudo correu bem, ou a mensagem de erro.

recebeMensagem

public java.lang.String recebeMensagem()
Recebe uma mensagem, sempre tentando reverter a compressão/ criptografia/ codificação. É um envelope para um método mais primitivo.

Returns:
A mensagem recebida, ou NULL, se não foi possível recebê-la.

recebeMensagem

public java.lang.String recebeMensagem(boolean pDecripta)
Recebe uma mensagem do nodo remoto, podendo-se optar por tentar ou não reverter a compressão/ criptografia/ codificação.

Parameters:
pDecripta - Flag que pede ou não a reversão do processo de criptografia/ compressão/ codificação.
Returns:
A mensagem recebida, ou NULL, se não tiver sido possível recebê-la.

fimTransmissao

public void fimTransmissao()
                    throws TissCommException,
                           java.net.SocketException
Transmite uma mensagem EOT (end of transmission) ao destinatário.

Throws:
br.gov.ans.tiss.comuns.TissCommException - .
java.net.SocketException - .
TissCommException

getSoquete

public java.net.Socket getSoquete()
Getter para soquete.

Returns:
O soquete.

setSoquete

public void setSoquete(java.net.Socket soquete)
Setter para soquete.

Parameters:
soquete - O soquete comum.

getChaveRijndael

public java.lang.String getChaveRijndael()
Getter para chaveRijndael.

Returns:
A chave RIJNDAEL.

getCriptografador

public AgenteRijndael getCriptografador()
Getter para criptografador.

Returns:
O agente de criptografia.

setCriptografador

public void setCriptografador(AgenteRijndael criptografador)
Setter para criptografador.

Parameters:
criptografador - O agente de criptografia.

setChaveRijndael

protected void setChaveRijndael(java.lang.String p_chaveRijndael)
Setter para chaveRijndael.

Parameters:
p_chaveRijndael - O valor da chave secundária RIJNDAEL.

completaChaveRijndael

public void completaChaveRijndael()
Completa chave RIJNDAEL de criptografia, combinando o challenge recebido com outra transformação.


completaChaveRijndael

public void completaChaveRijndael(java.lang.String pComplemento)
Completa chave RIJNDAEL de criptografia, combinando o challenge recebido com outra transformação. Note que esta versão do método força a complementação. A versão sem argumentos só complementa se o indicador de complementação ocorrida estiver desligado.

Parameters:
pComplemento - O complemento a aplicar à chave existente.

inicializaChaveRijndael

public void inicializaChaveRijndael(java.lang.String p_chaveRijndael)
Setter para chaveRijndael.

Parameters:
p_chaveRijndael - O valor da chave secundária RIJNDAEL.

getSoqueteEfetivo

public java.net.Socket getSoqueteEfetivo()
Retorna o soquete efetivamente em uso na conexão. Pode ser o soquete SSL ou o comum.

Returns:
O soquete em uso.

getIdPontaA

public java.lang.String getIdPontaA()
Getter para idPontaA.

Returns:
O identificador da ponta A da conexão.

setIdPontaA

public void setIdPontaA(java.lang.String idPontaA)
Setter para idPontaA.

Parameters:
idPontaA - O identificador da ponta A.

getIdPontaB

public java.lang.String getIdPontaB()
Getter para idPontaB.

Returns:
ID da ponta B.

setIdPontaB

public void setIdPontaB(java.lang.String idPontaB)
Setter para idPontaB.

Parameters:
idPontaB - ID da ponta B.

getUltimoErro

public java.lang.String getUltimoErro()
Getter para a última mensagem de erro detectada pela classe.

Returns:
A última mensagem de erro detectada.

isChaveCompleta

public boolean isChaveCompleta()
Getter para o indicador de chave complementada

Returns:
indicador de chave complementada.