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