• Nenhum resultado encontrado

Exemplo de envio de um elemento <features/> para o cliente

No documento IMBus: instant Messaging bus (páginas 67-73)

D.4 Descrição dos tipos de stanzas &lt;iq/&gt;

5.9 Exemplo de envio de um elemento &lt;features/&gt; para o cliente

5.2.3

Leitura de elementos XMPP

Às classes derivadas de XmppReader basta-lhes implementar o método BuildInstance. Apenas foram criadas classes para realizar o parse dos elementos que um cliente XMPP pode enviar. Estas classes estão divididas em duas categorias, as fábricas que realizam parse a elementos de negociação do stream e as fábricas que realizam parse aos stanzas e seus elementos associados. Todas estas classes são apresentadas na figura 5.2. Na primeira cat- egoria estão as classes: AuthFactory, BindFactory, ResponseFactory, SessionFactory e StartTlsFactory. Na segunda categoria estão as classes: BodyFactory, IqFactory, Mes- sageFactory, PresenceFactory, PriorityFactory, QueryFactory, ShowFactory, Status- Factory, SubjectFactory e ThreadFactory. Pelos próprios nomes é possível verificar quais os elementos a que realizam o parse.

5.2.4

Data Transfer Objects

As classes criadas para transferir a informação obtida da base de dados para quem a requisitou foram User e Contact. Estas classes contêm, respectivamente, a informação de um utilizador (para autenticação) e a informação respectiva a um item de um roster.

É possível verificar que não existem DTOs para obter a informação de mensagens offline ou stanzas para subscrição de presença. A informação obtida é directamente retornada em objectos das classes que representam os respectivos stanzas. Tendo em conta que essa infor- mação é obtida para ser entregue aos clientes, é imediatamente obtida no formato ideal para o realizar.

5.2.5

Objectos de suporte ao stream

Para auxiliar o funcionamento do servidor, tal como já foi indicado anteriormente, foram criados duas classes, Connection e Session, que são descritas em seguida.

• Connection: tem como objectivo auxiliar na escrita e leitura do stream. Funciona como um wrapper sobre o stream .NET;

• Session: representa uma sessão, com toda a informação que lhe é inerente, como por exemplo username e recurso associado. É construída ao longo da negociação do stream.

5.3

Aplicação Web para registo

Antes que um cliente se possa ligar ao bus de instant messaging, o utilizador deve registar uma conta.

Existe uma extensão para o protocolo XMPP que define uma forma de registo de um utilizador XMPP, antes que este se autentique, a XEP-0077, denominada de ”In-Band Regis- tration”.

A extensão XEP-0077 não será implementada por duas razões. Em primeiro lugar a implementação completa do protocolo XMPP não é o objectivo principal do trabalho, em segundo lugar, este tipo de registo não permite que utilizadores não XMPP efectuem o seu registo.

Com o objectivo de criar uma forma única de registo, foi criada uma pequena aplicação Web, que permite que todos os utilizadores dos serviços suportados se registem no bus de instant messaging. A figura 5.3 apresenta uma visualização da página Web desenvolvida.

Capítulo 6

Servidor XMPP

Este capítulo apresenta pormenores de implementação das principais funcionalidades do servidor XMPP, juntamente com a descrição dos componentes por elas responsáveis, ap- resentados na figura 4.1. Estas funcionalidades são apresentadas de seguida, indicando qual o componente que a implementa.

• Gestão de ligações TCP: Connection Manager;

• Gestão de sessões de instant messaging: Session Manager; • Processamento de stanzas: Request Manager.

As classes que implementam os componentes Connection Manager e Session Manager, implementam o padrão Singleton, de forma a apenas existir uma única instância da classe. O que acontece pois estas classes possuem o estado da informação vital para o funcionamento do servidor. A classe que implementa o componente Request Manager não implementa este padrão, pois tem como único objectivo processar os stanzas que lhe são entregues, não ar- mazenando qualquer tipo de informação. Desta forma é definida com uma classe estática, tendo apenas métodos estáticos.

A implementação do servidor será realizada na plataforma .NET, como já foi referido anteriormente.

6.1

Gestão de ligações TCP

A gestão das ligações TCP consiste em aceitar novas ligações e gerir as já existentes. A gestão das ligações em si consiste no armazenamento das mesmas para realizar todos os acessos de leitura e escrita. Esta funcionalidade é implementada pelo componente Connection Manager, que é um dos principais componentes do servidor.

A negociação da ligação é um processo sequencial, bem definido e independente da gestão da mesma, além de ser controlado por outro componente (Session Manager). Devido à sua natureza, este processo ocorre de forma síncrona entre o cliente e o servidor. Por outro

Figura 6.1: Ilustração de uma entrada em connections

lado, a gestão das ligações ocorre sempre de forma assíncrona, pois trata-se de um processo completamente aleatório, não existindo qualquer sequência de acções definida. O cliente pode enviar um stanza ao servidor a qualquer altura, o que torna inviável que o servidor fique bloqueado à espera de informação. As escritas podem ser muitas vezes executadas durante o processamento de um stanza, podendo implicar escritas para vários streams. De forma a acelerar o conjunto das escritas, cada uma delas será efectuada de forma assíncrona. Assim todas as leituras e escritas são iniciadas de forma assíncrona e completadas por IO completion threadsdo ThreadPool.

A gestão das ligações passa também pelo armazenamento das mesmas, tal como foi dito anteriormente, por forma a poder usá-las para receber e enviar informação a qualquer altura. Mas manter as ligações não basta, é necessário associar uma ligação a uma sessão de instant messaging, por forma a saber qual o recurso de que utilizador realizou o pedido. Assim este componente armazena um dicionário (chamado connections), em que cada entrada tem como chave o identificador da sessão e como valor o objecto ligação (instância de Connection, referida em 5.2.5). A figura 6.1 ilustra uma entrada nesse dicionário.

O acesso a este dicionário é apenas realizado na posse do lock associado ao próprio di- cionário.

A classe responsável por implementar este componente é a classe ConnectionManager.

6.1.1

Recepção de ligações

As novas ligações são recebidas pelo porto TCP 5222 (tal como referido em 2.1.2, é a porta definida pela especificação para comunicação entre servidor e cliente). O componente inicia uma espera assíncrona sobre o porto, cuja função de callback será executada por uma IO completion thread. Este callback deve ter um tempo de execução curto, de forma a libertar a IO completion threado mais rápido possível. Logo a sua execução consiste em apenas iniciar um nova espera assíncrona e iniciar a negociação do stream XML numa worker thread do ThreadPool.

Se a negociação for bem sucedida, será devolvido um par <identificador de sessão, instân- cia de Connection>, que será adicionado a connections. De seguida será iniciada a primeira leitura assíncrona sobre a ligação. A listagem 6.1 apresenta um excerto de código usado na recepção de uma ligação.

T c p C l i e n t c l i e n t = ( T c p C l i e n t ) obj ; S e s s i o n M a n a g e r m a n a g e r = S e s s i o n M a n a g e r . G e t I n s t a n c e (); K e y V a l u e P a i r < string , C o n n e c t i o n >? sp = m a n a g e r . N e g o t i a t i o n ( c l i e n t ); if ( sp . H a s V a l u e ) { // Key : s e s s i o n I d e n t i f i e r // V a l u e : c o n n e c t i o n l o c k ( c o n n e c t i o n s ) { c o n n e c t i o n s . Add ( sp . V a l u e . Key , sp . V a l u e . V a l u e ); } sp . V a l u e . V a l u e . B e g i n R e a d ( t h i s . R e a d C a l l b a c k , sp . V a l u e ); } e l s e { try { c l i e n t . C l o s e (); } c a t c h ( I O E x c e p t i o n ) { } }

No documento IMBus: instant Messaging bus (páginas 67-73)