cpp-v1.5.1 - Tecgraf JIRA / Confluence - PUC-Rio

Transcrição

cpp-v1.5.1 - Tecgraf JIRA / Confluence - PUC-Rio
Tutorial Openbus C++ 1.5.1
R. Cosme
Tecgraf
Pontifı́cia Universidade Católica do Rio de Janeiro (PUC-Rio)
[email protected]
22 de janeiro de 2011
1
Introdução
Este documento tem por objetivo servir como ponto de partida para os usuários
desenvolvedores de aplicações C++ que estão interessados em programar utilizando o Openbus. O processo de deployment do barramento não é coberto aqui
neste tutorial. Considera-se como pré-requisitos para um bom entendimento
deste texto um conhecimento básico dos seguintes assuntos:
• Linguagem de programação C++.
• CORBA.
• Modelo de Componentes SCS.
• Conceitos básicos do Openbus.
Maiores informações podem ser obtidas em: http://www.tecgraf.puc-rio.br/openbus
2
Preparação do Ambiente
O Openbus C++ suporta os ORB‘s Mico 2.3.13 e Orbix 6.3 Service Pack 3. O
usuário Mico pode escolher entre a versão singlethread ou multithread. Abaixo
explicamos o que deveria ser feito na configuração destes ORB‘s para que o
usuário possa utilizar o Openbus. Assumimos que o usuário tenha adquirido o
ORB através de um pacote Openbus SDK C++ obtido em nosso site.
2.1
Mico 2.3.13
Para que se possa utilizar o Mico, deveria somente ser necessário carregar no
shell do usuário o arquivo de configuração mico−setup.sh, para usuários que
usam *bash* ou mico−setup.csh para usuários que usam *csh*. Este script
pode ser encontrado no diretório specs/ shell da instalação do pacote. O usuário
que já tem o Mico instalado, deve verificar se este arquivo está sendo carregado
no seu ambiente. Este script fica localizado na pasta lib da instalação do Mico.
Atenção, não recomendamos a utilização de um Mico que não aquele fornecido
1
em nosso pacote. Mantemos algumas alterações proprietárias do Mico que são
necessárias para o correto funcionamento de todas as funcionalidades ofertadas
pela API Openbus C++.
2.2
Orbix 6.3 sp3
No Orbix o usuário precisa habilitar o mecanismo de interceptação de CORBA,
pois o mesmo não está habilitado por padrão. O Openbus utiliza este recurso no
processo de controle de acesso aos serviços. O usuário também precisa carregar
um script de configuração do ambiente no seu shell.
Este ORB é configurável através de domı́nios de configuração que por sua
vez formam um ambiente. O domı́nio é formado por escopos que são representados através de um arquivo textual que pode ser editado diretamente pelo
administrador. Não vamos abordar aqui como criar um domı́nio, para tal o
usuário deve consultar a documentação do Orbix.
Considerando-se que o usuário tenha o seu domı́nio, as seguintes linhas
abaixo devem ser adicionadas no arquivo de configuração do domı́nio:
tecgraf {
openbus {
p o l i c i e s : giop : i n t e r o p p o l i c y : ignore message not consumed
= ” true ” ;
orb plugins = [
” local log stream ” ,
”iiop profile” ,
” giop ” ,
” iiop ” ,
” portable interceptor ”
];
binding : s e r v e r b i n d i n g l i s t = [
”OTS+A c c e s s C o n t r o l ” ,
” AccessControl ” ,
”OTS” ,
””
];
binding : c l i e n t b i n d i n g l i s t = [
” A c c e s s C o n t r o l+OTS+POA Coloc” ,
” A c c e s s C o n t r o l+POA Coloc” ,
”OTS+POA Coloc” ,
”POA Coloc” ,
” A c c e s s C o n t r o l+OTS+GIOP+IIOP” ,
” A c c e s s C o n t r o l+GIOP+IIOP” ,
”OTS+GIOP+IIOP” ,
”GIOP+IIOP”
];
};
};
2
As quatro diretivas necessárias para o correto funcionamento do Openbus
são definidas no escopo tecgraf .openbus. A primeira define uma polı́tica necessária para que IIOP.NET possa se comunicar com o Openbus Orbix. A
segunda carrega o plugin responsável pelo mecanismo de interceptação. As
duas últimas registram o interceptador (AccessControl).
Por último, o usuário deve se certificar que o script shell que configura o
domı́nio a ser utilizado foi carregado. Este arquivo é gerado como resultado do
processo de configuração.
3
Testando o ambiente
Antes de se começar a programação, é aconselhável que o usuário coloque em
funcionamento a demo Hello que acompanha o pacote. O pacote inclui a demo
já compilada para uma plataforma em especı́fico. O correto funcionamento da
demo elimina possı́veis problemas que o desenvolvedor possa enfrentar durante
o seu projeto, como por exemplo: falhas de comunicação com o barramento,
mecanismo de interceptação não habilitado e ausência de bibliotecas dinâmicas
externas. Naturalmente a execução da demo necessita de um barramento em
operação. A demo pode ser executada seguindo os seguintes passos:
1. Definir a variável de ambiente OPENBUS HOME como o caminho absoluto da instalação do pacote Openbus SDK C++.
2. Definir a variável de ambiente TEC UNAME com o identificador da plataforma, que é a última sequência de caracteres após o último hı́fen do
nome do pacote, por exemplo: Linux26, SunOS510 ou Linux26g4.
3. Disponibilizar na variável de ambiente LD LIBRARY PATH o caminho
$OPENBUS HOME/libpath/$TEC UNAME.
4. Entrar no diretório demo/hello/orbix ou demo/hello/mico, que está disponı́vel na árvore do pacote.
5. Gerar uma chave privada e um certificado digital. Os arquivos devem ser
disponibilizados no diretório da demo. O arquivo referente ao certificado
deve ser colocado na pasta certificates do barramento, e o certificado
referente ao serviço de acesso deve ser obtido junto ao administrador do
barramento e colocado na pasta atual, em conjunto da chave privada que
foi gerada. Geracao de Chaves e Certificados Digitais
6. Editar o arquivo democonfig e configurar a localização do barramento
como também o nome da chave privada e do certificado do serviço de
controle de acesso.
7. Executar o processo servidor: ./runserver
A mensagem ”Servico IHello registrado.”deve ser retornada.
8. Executar o processo cliente: ./ runclient
3
Após a execução do cliente, no terminal do processo servidor a seguinte
mensagem deve ser retornada: ”Servant diz: HELLO!”.
Aconselha-se que o primeiro teste seja feito com o processo servidor e cliente na mesma máquina. O arquivo democonfig apresenta por padrão as configurações para este tipo de teste. É interessante que este teste também seja
realizado, se possı́vel, utilizando-se as máquinas finais que serão utilizadas no
projeto do desenvolvedor. Problemas de comunicação podem ocorrer por conta
das configurações de rede das máquinas envolvidas.
4
Desenvolvimento
4.1
Compilação
As demos disponibilizadas no pacote possuem um arquivo Makefile (GNU) para
compilação. Este arquivo pode e deve ser utilizado como ponto de partida para
as modificações necessárias a serem realizadas no processo de compilação do
projeto do usuário. Neste quesito existem algumas particularidades entre o uso
Orbix e Mico.
4.1.1
Mico
O projeto do usuário deve utilizar as seguintes bibliotecas:
openbusmico Biblioteca Openbus para Mico.
scsmico Biblioteca SCS para Mico.
logger Biblioteca de logging.
As bibliotecas acima requerem: dl , crypto, ssl , lua5.1 e pthread (no caso de
uso de uma versão multithread). O Openbus SDK C++ Mico permite a escolha entre uso singlethread ou multithread, como também 32 ou 64bits. Estas
duas configurações podem ser definidas através das macros MULTITHREAD e
MICO 64.
4.1.2
Orbix
O projeto deve ser compilado utilizando as seguintes bibliotecas:
openbusorbix Biblioteca Openbus para Orbix.
scsorbix Biblioteca SCS para Mico.
logger Biblioteca de logging.
As bibliotecas acima requerem: it poa , it art , it ifc , it portable interceptor ,
dl , crypto ssl e lua5.1. É necessário que o usuário defina as seguintes macros:
SCS ORBIX e OPENBUS ORBIX. Estas macros são necessárias para habilitar
o código referente ao uso com Orbix, pois por padrão o Openbus SDK C++
espera o uso do Mico.
4
4.2
API
A API C++ do Openbus é representada pelo arquivo openbus.h e pelo stub do
serviço de registro, que no caso do Mico é o arquivo stubs/mico/ registry service .h
e no Orbix o arquivo stubs/orbix/ registry service .hh. A documentação da API
também está presente na forma de comentários nos arquivos citados acima.
4.2.1
openbus.h
s t a t i c Openbus : : g e t I n s t a n c e ( )
Fornece a única instância do barramento.
void Openbus : : i n i t (
int argc ,
char ∗∗ argv )
Inicializa uma referência a um barramento.
Um ORB e um POA são criados implicitamente. A fábrica de componentes
SCS é criada. Os argumentos Openbus de linha de comando (argc e argv) são
tratados. Parâmetros de linha de comando:
-OpenbusHost Máquina em que se encontra o barramento.
-OpenbusPort Porta do barramento.
-OpenbusDebug ALL - Ativa todos os nı́veis de verbose. ERROR - Ativa o
nı́vel ERROR do debug. INFO - Ativa o nı́vel INFO do debug. WARNING - Ativa o nı́vel WARNING do debug.
-OpenbusDebugFile Caminho completo ou relativo do arquivo que armazenará as mensagens de verbose. Se este parâmetro não for definido, a saı́da
do verbose será a saı́da padrão. OBS.: Se for definido, o verbose somente
será armazenado no arquivo em questão, ou seja, a saı́da padrão não será
mais utilizada.
-OpenbusValidationPolicy Define uma polı́tica de validação das credenciais.
Por padrão, a polı́tica ALWAYS é adotada. NONE: Não há validação de
credenciais. ALWAYS: Sempre valida cada credencial no ACS. CACHED:
Primeiro tenta validar a credencial consultando um cache local, se não
conseguir, a validação transcorre normalmente através de uma chamada
remota ao ACS.
-OpenbusValidationTime Define o intervalo de tempo(em milisegundos) de
validação do cache de credenciais. O tempo padrão é de 30000ms.
-OpenbusFTConfigFilename Caminho completo ou relativo do arquivo que
descreve as réplicas a serem utilizadas pelo mecanismo de tolerância a
falhas.
-OpenbusTimeRenewing Tempo em segundos de renovação da credencial.
5
void Openbus : : i n i t (
int argc ,
char ∗∗ argv ,
char∗ host ,
unsigned short p o r t )
Inicializa uma referência a um barramento.
Um ORB e um POA são criados implicitamente. A fábrica de componentes
SCS é criada. Os argumentos Openbus de linha de comando (argc e argv) são
tratados. Parâmetros de linha de comando:
-OpenbusHost Máquina em que se encontra o barramento.
-OpenbusPort Porta do barramento.
-OpenbusDebug ALL - Ativa todos os nı́veis de verbose. ERROR - Ativa o
nı́vel ERROR do debug. INFO - Ativa o nı́vel INFO do debug. WARNING - Ativa o nı́vel WARNING do debug.
-OpenbusDebugFile Caminho completo ou relativo do arquivo que armazenará as mensagens de verbose. Se este parâmetro não for definido, a saı́da
do verbose será a saı́da padrão. OBS.: Se for definido, o verbose somente
será armazenado no arquivo em questão, ou seja, a saı́da padrão não será
mais utilizada.
-OpenbusValidationPolicy Define uma polı́tica de validação das credenciais.
Por padrão, a polı́tica ALWAYS é adotada. NONE: Não há validação de
credenciais. ALWAYS: Sempre valida cada credencial no ACS. CACHED:
Primeiro tenta validar a credencial consultando um cache local, se não
conseguir, a validação transcorre normalmente através de uma chamada
remota ao ACS.
-OpenbusValidationTime Define o intervalo de tempo(em milisegundos) de
validação do cache de credenciais. O tempo padrão é de 30000ms.
-OpenbusFTConfigFilename Caminho completo ou relativo do arquivo que
descreve as réplicas a serem utilizadas pelo mecanismo de tolerância a
falhas.
-OpenbusTimeRenewing Tempo em segundos de renovação da credencial.
bool Openbus : : i s C o n n e c t e d ( )
Informa o estado de conexão com o barramento.
s t a t i c void Openbus : : t e r m i n a t i o n H a n d l e r C a l l b a c k ( long
signalType )
Disponibiliza um termination handler que desconecta o usuário do barramento e finaliza a execução do Openbus::run().
Essa callback pode ser utlizada em uma implementação de um termination
handler a ser escrito pelo usuário. No caso do Orbix, o método pode ser registrado diretamente na classe IT TerminationHandler(), e.g.:
6
IT TerminationHandler termination handler(openbus::Openbus::terminationHandlerCallback)
O método desconecta o usuário do barramento, se este estiver conectado,
executa um Openbus::stop() seguido por um Openbus::finish(), e, por último
faz delete da instanciação do Openbus.
CORBA: : ORB∗ Openbus : : getORB ( )
Retorna o ORB utilizado.
P o r t a b l e S e r v e r : : POA∗ getRootPOA ( ) ;
Retorna o RootPOA.
s c s : : c o r e : : ComponentBuilder ∗
Openbus : : getComponentBuilder ( )
Retorna a fábrica de componentes.
C r e d e n t i a l v a r Openbus : : g e t I n t e r c e p t e d C r e d e n t i a l ( )
Retorna a credencial interceptada pelo interceptador servidor. !Atenção!
Esta operação somente deve ser chamada durante o processo de tratamento de
requisição do serviço implementado.
openbusidl : : acs : : IAccessControlService ∗
Openbus : : g e t A c c e s s C o n t r o l S e r v i c e ( )
Retorna o serviço de acesso.
registry service : : IRegistryService ∗
getRegistryService () ;
Retorna o serviço de registro.
access control service : : Credential ∗
Openbus : : g e t C r e d e n t i a l ( )
Retorna a credencial de identificação do usuário frente ao barramento.
interceptors : : CredentialValidationPolicy
getCredentialValidationPolicy ()
Retorna a polı́tica de validação de credenciais.
void
setThreadCredential ( a c c e s s c o n t r o l s e r v i c e : : Credential ∗
credential )
Define uma credencial a ser utilizada no lugar da credencial corrente. Útil
para fornecer uma credencial com o campo delegate preenchido. !Atenção! Na
versão Orbix este método não considera um comportamento multithread, sendo
assim a alteração de credencial será válida para todas as threads.
class LeaseExpiredCallback {
public :
v i r t u a l void e x p i r e d ( ) = 0 ;
};
7
Representa uma callback para a notificação de que o lease da credencial de
indentificação do usuário expirou. O usuário deve fornecer a implementação da
callback implementando o método expired().
void s e t L e a s e E x p i r e d C a l l b a c k ( L e a s e E x p i r e d C a l l b a c k ∗
leaseExpiredCallback )
Registra uma callback para a notificação de lease expirado através de um
objeto do tipo LeaseExpiredCallback. Este método deve ser chamado após o
estabelecimento da conexão com o barramento.
void r e m o v e L e a s e E x p i r e d C a l l b a c k ( )
Remove uma callback previamente registrada para a notificação de lease
expirado.Este método deve ser chamado após o estabelecimento da conexão
com o barramento.
s e r v i c e s : : R e g i s t r y S e r v i c e ∗ Openbus : : c o n n e c t (
const char∗ u s e r ,
const char∗ password )
throw (CORBA: : SystemException , LOGIN FAILURE)
Realiza uma tentativa de conexão com o barramento. Se a tentativa for
bem sucedida, uma instância que representa o serviço de registro é retornada,
caso contrário duas exceções podem ser lançadas:
LOGIN FAILURE O par nome de usuário e senha não foram validados.
CORBA::SystemException Alguma falha de comunicação com o barramento ocorreu. Possı́veis causas:
• Os valores que definem a localização do barramento(máquina e porta)
estão incorretos.
• O mecanismo de interceptação não está sendo ativado. (rever o ı́tem
1)
s e r v i c e s : : R e g i s t r y S e r v i c e ∗ Openbus : : c o n n e c t (
const char∗ e n t i t y ,
const char∗ privateKeyFilename ,
const char∗ A C S C e r t i f i c a t e F i l e n a m e )
throw (CORBA: : SystemException , LOGIN FAILURE ,
SECURITY EXCEPTION)
Realiza uma tentativa de conexão com o barramento utilizando o mecanismo
de certificação para o processo de autenticação. Se a tentativa for bem sucedida,
uma instância que representa o serviço de registro é retornada, caso contrário
duas exceções podem ser lançadas:
LOGIN FAILURE O par nome de usuário e senha não foram validados.
8
CORBA::SystemException Alguma falha de comunicação com obarramento
ocorreu. Possı́veis causas: Os valores que definem a localização do barramento(host e porta) estão incorretos. O mecanismo de interceptação não
está sendo ativado. (rever o ı́tem 1)
SECURITY EXCEPTION Falha no mecanismo de autenticação por certificado digital. Algumas possı́veis causas:
Não foi possı́vel obter o desafio. Falha na manipulação de uma chave
privada ou pública. Falha na manipulação de um certificado.
bool Openbus : : d i s c o n n e c t ( )
Desfaz a conexão atual. Caso a conexão seja desfeita, true é retornado, caso
contrário, o valor de retorno é false.
void Openbus : : run ( )
Loop que processa requisições CORBA. !Atenção! Este método na versão
Mico multithread faz um wait() na RunThread.
void s t o p ( )
Pára de processar requisições CORBA. Finaliza a execução do run. !Atenção!
Não faz nada na versão Mico multithread.
void f i n i s h ( bool f o r c e ) ;
Finaliza a execução do ORB.
void s e t I n t e r c e p t a b l e (
s t r i n g interfaceRepID ,
s t r i n g method ,
bool i s I n t e r c e p t a b l e )
Define se os métodos de uma determinada interface devem ou não ser interceptados pelo interceptador servidor.
bool i s I n t e r c e p t a b l e (
s t r i n g interfaceRepID ,
s t r i n g method )
Consulta se o método está sendo interceptado.
bool i s F a u l t T o l e r a n c e E n a b l e ( )
Consulta se o mecanismo de tolerância a falhas está ativado.
4.3
Tolerância a falhas
O usuário Orbix pode habilitar um mecanismo de tolerância a falhas em requisições remotas destinadas aos serviços básicos do barramento. Para isto, é
necessário ter em mãos a lista de réplicas disponı́veis para o serviço de acesso,
e, descrevê-las em um arquivo do tipo Lua. Um exemplo:
9
−− r e p l i c a s . l u a
ACSHosts = {
{ ”nomeMaquinaA” , 2 0 8 9 } ,
{ ”nomeMaquinaB” , 4 0 8 9 } ,
}
Essas informações devem ser obtidas com o administrador do barramento.
A habilitação do mecanismo é através do parâmetro de linha de comando
−OpenbusFTConfigFilename, que deve receber o caminho relativo ou absoluto
do arquivo acima.
4.4
Dinâmica da Programação
Basicamente há dois tipos de aplicações Openbus. Uma que oferta serviços e
outra que consome serviços. Sendo possı́vel e natural uma aplicação hı́brida
que assuma as duas posições. Para ambos os tipos, existe uma certa dinâmica
de programação já definida. Justamente a explicitação dessa dinâmica que será
o objetivo deste tópico. Como facilitador, os processos serão demonstrados
com base na demo Hello. Esta demo é composta de um módulo cliente e de
outro servidor. O servidor oferta um serviço do tipo Hello num determinado
barramento, já o cliente procura por este serviço no barramento em questão e
o utiliza.
4.5
Conexão com o barramento
O primeiro passo é firmar uma conexão autenticada com o barramento, o que
é necessário tanto para o cliente como para o servidor. Para isto é preciso:
1. Adquirir a instância que representa o barramento
openbus : : Openbus∗ bus = Openbus : : g e t I n s t a n c e ( ) ;
2. Inicializar essa referência que foi adquirida anteriormente:
bus−>i n i t ( argc , argv ) ;
3. Efetuar uma autenticação no barramento através de um certificado digital
ou um par usuário e senha:
services : : RegistryService ∗ registryService =
bus−>c o n n e c t (
” HelloService ” ,
” H e l l o S e r v i c e . key ” ,
” AccessControlService . crt ”) ;
ou
services : : RegistryService ∗ registryService =
bus−>c o n n e c t ( ” t e s t e r ” , ” t e s t e r ” ) ;
Existem dois modos de autenticação frente ao barramento:
10
1. Par usuário e senha.
2. Certificado digital.
O primeiro é destinado normalmente aos clientes que estão acessando o barramento através de uma identificação pessoal e intransferı́vel, já o segundo é
mais adequado a um serviço ou uma aplicação que não necessita distinguir os
usuários que acessam o barramento. No segundo caso, o responsável pelo serviço
deve encaminhar ao administrador do barramento o certificado do serviço, ou
seja, um arquivo especial que contenha a chave pública do serviço. Em contrapartida o administrador deve fornecer o certificado do serviço de controle de
acesso.
4.6
Registro de serviço
Um serviço pode ser disponibilizado no barramento através de uma oferta de
serviço (ServiceOffer), que é uma estrutura que representa o serviço através de
uma lista de propriedades (properties) e de uma referência para um componente
(member) SCS.
t y p e d e f sequence <s t r i n g > Pr op ert yV alu e ;
s t r u c t Property {
s t r i n g name ;
Pr op ert yV alu e v a l u e ;
};
t y p e d e f sequence <Property> P r o p e r t y L i s t ;
struct ServiceOffer {
PropertyList properties ;
s c s : : c o r e : : IComponent member ;
};
Através da lista de propriedades é possı́vel caracterizar o serviço. A arquitetura do Openbus é baseada no modelo de componentes SCS. O serviço é
representado por um componente que pode apresentar distintas facetas (interfaces). Sendo assim, o primeiro passo para o registro de um serviço é
criar um componente que represente o serviço desejado. Uma fábrica de componentes (componentBuilder) pode ser adquirida através do método Openbus::getComponentBuilder(). De posse desta fábrica, o usuário pode criar um
componente atribuindo uma ou mais facetas:
/∗ F a b r i c a de componentes ∗/
s c s : : c o r e : : ComponentBuilder ∗ componentBuilder =
bus−>getComponentBuilder ( ) ;
/∗ D e f i n i c a o do componente . ∗/
s c s : : c o r e : : ComponentId componentId ;
componentId . name = ” HelloComponent ” ;
11
componentId . m a j o r v e r s i o n
componentId . m i n o r v e r s i o n
componentId . p a t c h v e r s i o n
componentId . p l a t f o r m s p e c
=
=
=
=
’1 ’;
’0 ’;
’0 ’;
”nenhuma” ;
/∗ D e s c r i c a o das f a c e t a s . ∗/
s t d : : l i s t <s c s : : c o r e : : E x t e n d e d F a c e t D e s c r i p t i o n >
extFacets ;
scs : : core : : ExtendedFacetDescription helloDesc ;
h e l l o D e s c . name = ” I H e l l o ” ;
helloDesc . interface name =
”IDL : demoidl / h e l l o / I H e l l o : 1 . 0 ” ;
helloDesc . i n s t a n t i a t o r = HelloImpl : : i n s t a n t i a t e ;
helloDesc . destructor = HelloImpl : : destruct ;
e x t F a c e t s . push back ( h e l l o D e s c ) ;
componentContext =
componentBuilder−>newComponent ( e x t F a c e t s ,
componentId ) ;
O serviço a ser registrado no barramento deve ser descrito através de uma
oferta de serviço, que é representada pela estrutura ServiceOffer. Pendura-se
nesta estrutura o serviço em si, que é representado através de um componente
SCS e opcionalmente uma lista de propriedades referentes ao mesmo. As propriedades devem ser descritas através de uma estrutura do tipo lista. Como
esta lista é uma sequence de uma estrutura que possui uma outra lista, que
é justamente a lista de valores, pois uma chave pode estar relacionada a mais
de um valor, o preenchimento dos valores desejados envolve um número de linhas de código um tanto indesejável. Por este motivo, há a classe de auxı́lio
PropertyListHelper que tem por objetivo facilitar o trabalho de construção das
listas de propriedades. Por exemplo, se o usuário desejar criar uma lista que
contenha somente uma propriedade do tipo chave/valor, o mesmo deveria entrar
com algo do tipo:
o p e n b u s i d l : : r s : : P r o p e r t y L i s t v a r p = new
openbusidl : : rs : : PropertyList (1) ;
p−>l e n g t h ( 1 ) ;
o p e n b u s i d l : : r s : : P r o p e r t y v a r p r o p e r t y = new
openbusidl : : r s : : Property ;
p r o p e r t y −>name = ” d e s c r i p t i o n ” ;
openbusidl : : rs : : PropertyValue var propertyValue =
new o p e n b u s i d l : : r s : : P rop er tyV al ue ( 1 ) ;
p r o p e r t y V a l u e −>l e n g t h ( 1 ) ;
p r o p e r t y V a l u e [ 0 ] = ” S e r v i ç o I H e l l o ” ;
p r o p e r t y −>v a l u e = p r o p e r t y V a l u e ;
p [ 0 ] = property ;
Agora, se a classe de auxı́lio for utilizada, reduzimos este código para:
12
openbus : : u t i l : : P r o p e r t y L i s t H e l p e r ∗ p r o p e r t y L i s t H e l p e r =
new openbus : : u t i l : : P r o p e r t y L i s t H e l p e r ( ) ;
/∗ C r i a ç ã o de uma ∗ o f e r t a de s e r v i ç o ∗ . ∗/
registry service : : ServiceOffer serviceOffer ;
serviceOffer . properties =
p r o p e r t y L i s t H e l p e r −>g e t P r o p e r t y L i s t ( ) ;
s e r v i c e O f f e r . member =
componentContext−>getIComponent ( ) ;
delete propertyListHelper ;
De posse da lista de propriedades e do componente que representa o serviço,
é possı́vel requisitar o registro do serviço:
registryId =
r e g i s t r y S e r v i c e −> c x x r e g i s t e r ( s e r v i c e O f f e r ) ;
Até este ponto, o servidor basicamente se autenticou ao barramento e registrou o serviço. O último passo necessário para se finalizar o código do servidor
é habilitar o processo servidor a escutar as requisições CORBA que serão direcionadas para o serviço ofertado:
bus−>run ( ) ;
4.7
Processo cliente
Como o servidor, o cliente necessita se autenticar no barramento, portanto os
mesmos passos aplicados no servidor para a autenticação devem ser repetidos,
com exceção de que o cliente provavelmente vai desejar se autenticar com o
barramento através do mecanismo usuário e senha:
r e g i s t r y S e r v i c e = bus−>c o n n e c t ( ” t e s t e r ” , ” t e s t e r ” ) ;
Após a conexão bem sucedida com o barramento, o próximo passo é obter
o serviço desejado. Isso pode ser feito através de uma chamada ao método
services::RegistryService::find(), que retorna uma lista de ofertas de serviço que
implementam a faceta que o usuário deseja.
Busca do serviço:
/∗ D e f i n e a l i s t a de f a c e t a s que c a r a c t e r i z a o s e r v i ç o
implementado .
∗ O t r a b a l h o de c r i a ç ã o da l i s t a é f a c i l i t a d o p e l o uso
da c l a s s e
∗ FacetListHelper .
∗/
openbus : : u t i l : : F a c e t L i s t H e l p e r ∗ f a c e t L i s t H e l p e r =
new openbus : : u t i l : : F a c e t L i s t H e l p e r ( ) ;
f a c e t L i s t H e l p e r −>add ( ” I H e l l o ” ) ;
/∗ Busca no barramento o s e r v i ç o d e s e j a d o .
13
∗
∗
∗/
Uma l i s t a de ∗ o f e r t a s de s e r v i ç o ∗ é r e t o r n a d a para o
u s u á r i o .
OBS . : Neste demo somente há uma o f e r t a de s e r v i ç o .
registry service : : ServiceOfferList var
serviceOfferList =
r e g i s t r y S e r v i c e −>f i n d ( f a c e t L i s t H e l p e r −>g e t F a c e t L i s t ( ) ) ;
delete facetListHelper ;
registry service : : ServiceOffer serviceOffer =
s e r v i c e O f f e r L i s t [ (CORBA: : ULong ) 0 ] ;
Como visto acima, a oferta de serviço armazena o serviço através de um
componente SCS. Como este componente pode apresentar diversas facetas, o
usuário deve informar qual faceta deseja utilizar. No exemplo utilizado, somente
há uma faceta IHello. O componente oferece um método(getFacet) para que o
usuário possa obter um objeto CORBA que represente o serviço desejado:
s c s : : c o r e : : IComponent var component =
s e r v i c e O f f e r . member ;
CORBA: : O b j e c t v a r o b j =
component−>g e t F a c e t ( ”IDL : demoidl / h e l l o / I H e l l o : 1 . 0 ” ) ;
De posse do objeto CORBA, o usuário deve efetuar um narrow para mapeálo para a interface desejada:
demoidl : : h e l l o : : I H e l l o v a r h e l l o =
demoidl : : h e l l o : : I H e l l o : : narrow ( o b j ) ;
Daqui em diante o programador estará apto a utilizar o serviço.
14
4.8
Código servidor
/∗
∗∗ OpenBus Demo − Mico
∗∗ s e r v e r . cpp
∗/
#i n c l u d e
#i n c l u d e
#i n c l u d e
#i n c l u d e
<f s t r e a m >
<i o s t r e a m >
<CORBA. h>
<c s i g n a l >
#i n c l u d e <openbus . h>
#i n c l u d e <ComponentBuilder . h>
#i n c l u d e ” s t u b s / h e l l o . h”
u s i n g namespace s t d ;
u s i n g namespace t e c g r a f : : openbus : : c o r e : : v 1 0 5 ;
u s i n g namespace
t e c g r a f : : openbus : : c o r e : : v 1 0 5 : : r e g i s t r y s e r v i c e ;
openbus : : Openbus∗ bus ;
registry service : : IRegistryService ∗ registryService = 0;
char ∗ r e g i s t r y I d ;
s c s : : c o r e : : ComponentContext ∗ componentContext ;
c o n s t c h a r ∗ entityName ;
const char ∗ privateKeyFilename ;
const char ∗ ACSCertificateFilename ;
c o n s t c h a r ∗ facetName ;
c l a s s HelloImpl : v i r t u a l public
POA demoidl : : h e l l o : : I H e l l o {
private :
s c s : : c o r e : : ComponentContext ∗ componentContext ;
H e l l o I m p l ( s c s : : c o r e : : ComponentContext ∗
componentContext ) {
t h i s −>componentContext = componentContext ;
}
public :
s t a t i c P o r t a b l e S e r v e r : : Se rvantBase ∗ i n s t a n t i a t e (
s c s : : c o r e : : ComponentContext ∗ componentContext )
{
return ( P o r t a b l e S e r v e r : : ServantBase ∗ ) new
H e l l o I m p l ( componentContext ) ;
}
s t a t i c void destruct ( void ∗ obj ) {
15
d e l e t e ( HelloImpl ∗) obj ;
}
v o i d s a y H e l l o ( ) throw (CORBA: : SystemException ) {
c o u t << ” S e r v a n t d i z : HELLO! ” << e n d l ;
access control service : : Credential var credential =
bus−>g e t I n t e r c e p t e d C r e d e n t i a l ( ) ;
c o u t << ” U s u a r i o OpenBus que f e z a chamada : ” <<
c r e d e n t i a l −>owner . i n ( )
<< e n d l ;
};
};
void termination handler ( i n t p) {
c o u t << ” Encerrando o p r o c e s s o s e r v i d o r . . . ” << e n d l ;
openbus : : Openbus : : t e r m i n a t i o n H a n d l e r C a l l b a c k ( ( l o n g )
signal ) ;
}
v o i d commandLineParse ( i n t argc , c h a r ∗ argv [ ] ) {
fo r ( s h o r t i = 1 ; i < a r g c ; i ++) {
i f ( ! strcmp ( argv [ i ] , ”−EntityName ” ) ) {
i ++;
entityName = argv [ i ] ;
} e l s e i f ( ! strcmp ( argv [ i ] , ”−PrivateKeyFilename ” ) ) {
i ++;
p r i v a t e K e y F i l e n a m e = argv [ i ] ;
} e l s e i f ( ! strcmp ( argv [ i ] ,
”−A C S C e r t i f i c a t e F i l e n a m e ” ) ) {
i ++;
A C S C e r t i f i c a t e F i l e n a m e = argv [ i ] ;
} e l s e i f ( ! strcmp ( argv [ i ] , ”−FacetName” ) ) {
i ++;
facetName = argv [ i ] ;
}
}
}
i n t main ( i n t argc , c h a r ∗ argv [ ] ) {
s i g n a l ( SIGINT , t e r m i n a t i o n h a n d l e r ) ;
bus = openbus : : Openbus : : g e t I n s t a n c e ( ) ;
bus−>i n i t ( argc , argv ) ;
commandLineParse ( argc , argv ) ;
c o u t << ” Conectando no barramento . . . ” << e n d l ;
16
/∗ Conexao com o barramento a t r a v e s de c e r t i f i c a d o . ∗/
try {
r e g i s t r y S e r v i c e = bus−>c o n n e c t (
entityName ,
privateKeyFilename ,
ACSCertificateFilename ) ;
} c a t c h (CORBA: : SystemException& e ) {
c o u t << ” ∗∗ Nao f o i p o s s i v e l s e c o n e c t a r ao
barramento . ∗∗ ” << e n d l \
<< ”∗ Falha na comunicacao . ∗” << e n d l ;
exit ( 1) ;
} c a t c h ( openbus : : LOGIN FAILURE& e ) {
c o u t << ” ∗∗ Nao f o i p o s s i v e l s e c o n e c t a r ao
barramento . ∗∗ ” << e n d l \
<< ”∗ Par u s u a r i o / senha i n v a l i d o . ∗” << e n d l ;
exit ( 1) ;
} c a t c h ( openbus : : SECURITY EXCEPTION& e ) {
c o u t << e . what ( ) << e n d l ;
exit ( 1) ;
}
c o u t << ” Conexao com o barramento e s t a b e l e c i d a com
s u c e s s o ! ” << e n d l ;
/∗ F a b r i c a de componentes ∗/
s c s : : c o r e : : ComponentBuilder ∗ componentBuilder =
bus−>getComponentBuilder ( ) ;
/∗ D e f i n i c a o do componente . ∗/
s c s : : c o r e : : ComponentId componentId ;
componentId . name = ” HelloComponent ” ;
componentId . m a j o r v e r s i o n = ’ 1 ’ ;
componentId . m i n o r v e r s i o n = ’ 0 ’ ;
componentId . p a t c h v e r s i o n = ’ 0 ’ ;
componentId . p l a t f o r m s p e c = ”nenhuma” ;
/∗ D e s c r i c a o das f a c e t a s . ∗/
s t d : : l i s t <s c s : : c o r e : : E x t e n d e d F a c e t D e s c r i p t i o n >
extFacets ;
scs : : core : : ExtendedFacetDescription helloDesc ;
h e l l o D e s c . name = facetName ;
helloDesc . interface name =
”IDL : demoidl / h e l l o / I H e l l o : 1 . 0 ” ;
helloDesc . i n s t a n t i a t o r = HelloImpl : : i n s t a n t i a t e ;
helloDesc . destructor = HelloImpl : : destruct ;
e x t F a c e t s . push back ( h e l l o D e s c ) ;
17
componentContext =
componentBuilder−>newComponent ( e x t F a c e t s ,
componentId ) ;
openbus : : u t i l : : P r o p e r t y L i s t H e l p e r ∗ p r o p e r t y L i s t H e l p e r
= \
new openbus : : u t i l : : P r o p e r t y L i s t H e l p e r ( ) ;
/∗ C r i a c a o de uma ∗ o f e r t a de s e r v i c o ∗ . ∗/
registry service : : ServiceOffer serviceOffer ;
serviceOffer . properties =
p r o p e r t y L i s t H e l p e r −>g e t P r o p e r t y L i s t ( ) ;
s e r v i c e O f f e r . member =
componentContext−>getIComponent ( ) ;
delete propertyListHelper ;
c o u t << ” R e g i s t r a n d o s e r v i c o I H e l l o no barramento . . . ”
<< e n d l ;
/∗ R e g i s t r o do s e r v i c o no barramento . ∗/
try {
if ( registryService ) {
registryId =
r e g i s t r y S e r v i c e −> c x x r e g i s t e r ( s e r v i c e O f f e r ) ;
} else {
c o u t << ”Nao f o i p o s s i v e l a d q u i r i r um proxy para o
s e r v i c o de r e g i s t r o . ”
<< e n d l ;
exit ( 1) ;
}
} c a t c h ( U n a t h o r i z e d F a c e t s& e ) {
c o u t << ”Nao f o i p o s s i v e l r e g i s t r a r I H e l l o . ” << e n d l ;
CORBA: : ULong i d x ;
CORBA: : ULong l e n g t h = e . f a c e t s . l e n g t h ( ) ;
f o r ( i d x = 0 ; i d x < l e n g t h ; i d x++) {
c o u t << ” Faceta nao a u t o r i z a d a : ” << e . f a c e t s [ i d x ]
<< e n d l ;
}
exit ( 1) ;
}
c o u t << ” S e r v i c o I H e l l o r e g i s t r a d o . ” << e n d l ;
c o u t << ” Aguardando r e q u i s i c o e s . . . ” << e n d l ;
bus−>run ( ) ;
return 0 ;
}
18
4.9
Código cliente
/∗
∗∗ OpenBus Demo − Mico
∗∗ c l i e n t . cpp
∗/
#i n c l u d e <f s t r e a m >
#i n c l u d e <i o s t r e a m >
#i n c l u d e ” s t u b s / h e l l o . h”
#i n c l u d e <openbus . h>
u s i n g namespace s t d ;
u s i n g namespace t e c g r a f : : openbus : : c o r e : : v 1 0 5 ;
c o n s t c h a r ∗ busUser ;
c o n s t c h a r ∗ busPassword ;
c o n s t c h a r ∗ facetName ;
v o i d commandLineParse ( i n t argc , c h a r ∗ argv [ ] ) {
fo r ( s h o r t i = 1 ; i < a r g c ; i ++) {
i f ( ! strcmp ( argv [ i ] , ”−BusUser ” ) ) {
i ++;
busUser = argv [ i ] ;
} e l s e i f ( ! strcmp ( argv [ i ] , ”−BusPassword ” ) ) {
i ++;
busPassword = argv [ i ] ;
} e l s e i f ( ! strcmp ( argv [ i ] , ”−FacetName” ) ) {
i ++;
facetName = argv [ i ] ;
}
}
}
i n t main ( i n t argc , c h a r ∗ argv [ ] ) {
openbus : : Openbus∗ bus ;
registry service : : IRegistryService ∗ registryService ;
bus = openbus : : Openbus : : g e t I n s t a n c e ( ) ;
bus−>i n i t ( argc , argv ) ;
commandLineParse ( argc , argv ) ;
19
c o u t << ” Conectando no barramento . . . ” << e n d l ;
/∗ Conexão com o barramento . ∗/
try {
r e g i s t r y S e r v i c e = bus−>c o n n e c t (
busUser ,
busPassword ) ;
} c a t c h (CORBA: : SystemException& e ) {
c o u t << ” ∗∗ Nao f o i p o s s i v e l s e c o n e c t a r ao
barramento . ∗∗ ” << e n d l \
<< ”∗ Falha na comunicacao . ∗” << e n d l ;
e x i t ( −1) ;
} c a t c h ( openbus : : LOGIN FAILURE& e ) {
c o u t << ” ∗∗ Nao f o i p o s s i v e l s e c o n e c t a r ao
barramento . ∗∗ ” << e n d l \
<< ”∗ Par u s u a r i o / senha i n v á l i d o . ∗” << e n d l ;
e x i t ( −1) ;
}
c o u t << ” Conexão com o barramento e s t a b e l e c i d a com
s u c e s s o ! ” << e n d l ;
/∗ D e f i n e a l i s t a de f a c e t a s que c a r a c t e r i z a o s e r v i ç o
implementa .
∗ O t r a b a l h o de c r i a ç ã o da l i s t a é f a c i l i t a d o p e l o uso
da c l a s s e
∗ FacetListHelper .
∗/
openbus : : u t i l : : F a c e t L i s t H e l p e r ∗ f a c e t L i s t H e l p e r =
new openbus : : u t i l : : F a c e t L i s t H e l p e r ( ) ;
f a c e t L i s t H e l p e r −>add ( facetName ) ;
/∗ Busca no barramento o s e r v i ç o d e s e j a d o .
∗ Uma l i s t a de ∗ o f e r t a s de s e r v i ç o ∗ é r e t o r n a d a para o
u s u á r i o .
∗ OBS . : Neste demo somente há uma o f e r t a de s e r v i ç o .
∗/
registry service : : ServiceOfferList var
serviceOfferList =
r e g i s t r y S e r v i c e −>f i n d ( f a c e t L i s t H e l p e r −>g e t F a c e t L i s t ( ) ) ;
delete facetListHelper ;
i f ( s e r v i c e O f f e r L i s t −>l e n g t h ( ) > 0 ) {
registry service : : ServiceOffer serviceOffer =
s e r v i c e O f f e r L i s t [ (CORBA: : ULong ) 0 ] ;
20
s c s : : c o r e : : IComponent var component =
s e r v i c e O f f e r . member ;
CORBA: : O b j e c t v a r o b j =
component−>g e t F a c e t ( ”IDL : demoidl / h e l l o / I H e l l o : 1 . 0 ” ) ;
demoidl : : h e l l o : : I H e l l o v a r h e l l o =
demoidl : : h e l l o : : I H e l l o : : narrow ( o b j ) ;
c o u t << ” Fazendo chamada remota s a y H e l l o ( ) . . . ” <<
endl ;
h e l l o −>s a y H e l l o ( ) ;
} else {
c o u t << ”Nenhuma o f e r t a e n c o n t r a d a . ” << e n d l ;
}
c o u t << ” Desconectando−s e do barramento . . . ” << e n d l ;
bus−>d i s c o n n e c t ( ) ;
d e l e t e bus ;
return 0 ;
}
21