UNIVERSIDADE FEDERAL DO RIO GRANDE DO NORTE
CENTRO DE CIÊNCIAS EXATAS E DA TERRA
DEPARTAMENTO DE INFORMÁTICA E MATEMÁTICA APLICADA
BACHARELADO EM ENGENHARIA DE SOFTWARE
Âmbar: Desenvolvimento de um Serviço
Multiplataforma e Descentralizado de Foto
Memórias
Paulo Leonardo Souza Brizolara
NatalRN
Novembro de 2017
Paulo Leonardo Souza Brizolara
Âmbar: Desenvolvimento de um Serviço
Multiplataforma e Descentralizado de Foto
Memórias
Monografia de Graduação apresentada aoDepartamento de Informática e MatemáticaAplicada do Centro de Ciências Exatas e daTerra da Universidade Federal do Rio Grandedo Norte como requisito parcial para aobtenção do grau de bacharel em Engenhariade Software.
Orientador
Prof. Dr. Leonardo Cunha de Miranda
Universidade Federal do Rio Grande do Norte – UFRN
Departamento de Informática e Matemática Aplicada – DIMAp
NatalRN
Novembro de 2017
Universidade Federal do Rio Grande do Norte – UFRNSistema de Bibliotecas – SISBI
Catalogação da Publicação na Fonte. UFRN - Biblioteca Setorial Prof. Ronaldo Xavier deArruda - CCET
Brizolara, Paulo Leonardo Souza. Âmbar: desenvolvimento de um serviço multiplataforma e descentralizado de foto-memórias / Paulo Leonardo Souza Brizolara. – 2017. 124f.: il.
Monografia (graduação) – Universidade Federal do Rio Grande do Norte.Centro de Ciências Exatas e da Terra. Departamento de Informática e MatemáticaAplicada. Bacharelado em Engenharia de Software. Natal, RN, 2017. Orientador: Leonardo Cunha de Miranda.
1. Sistemas distribuídos – Monografia. 2. Sistemas descentralizados –Monografia. 3. Fotografia – Monografia. 4. Memória – Monografia. I. Miranda,Leonardo Cunha de. II. Título.
RN/UF/BSE-CCET CDU: 004.475
Monografia de Graduação sob o título Âmbar: Desenvolvimento de um Serviço
Multiplataforma e Descentralizado de FotoMemórias apresentada por Paulo
Leonardo Souza Brizolara e aceita pelo Departamento de Informática e
Matemática Aplicada do Centro de Ciências Exatas e da Terra da
Universidade Federal do Rio Grande do Norte, sendo aprovada por todos os
membros da banca examinadora abaixo especificada:
__________________________________________
Prof. Dr. Leonardo Cunha de Miranda
Orientador
Departamento de Informática e Matemática Aplicada
Universidade Federal do Rio Grande do Norte
__________________________________________
Prof.ª Dra. Lyrene Fernandes da Silva
Departamento de Informática e Matemática Aplicada
Universidade Federal do Rio Grande do Norte
__________________________________________
Prof. Dr. Marcos Cesar Madruga Alves Pinheiro
Departamento de Informática e Matemática Aplicada
Universidade Federal do Rio Grande do Norte
__________________________________________
Prof.ª Dra. Monica Magalhães Pereira
Departamento de Informática e Matemática Aplicada
Universidade Federal do Rio Grande do Norte
NatalRN, 27 de Novembro de 2017.
Agradecimentos
Gostaria de agradecer a todos aqueles que contribuíram, direta ou
indiretamente, com a realização deste trabalho e toda minha trajetória.
Em especial, gostaria de agradecer ao meu orientador, por todos os
anos em que tem me acompanhado e contribuído com a minha formação,
pelo seu esforço e dedicação incansáveis, não só comigo, mas com todos
seus orientandos.
Gostaria de agradecer aos membros da banca porque aceitaram
contribuir com o trabalho, apesar do tempo restrito.
À minha família eu agradeço pelo apoio que me dão sempre, pela
preocupação que tem comigo e por esses anos de estrada divididos.
À minha companheira e melhor amiga, sou grato pelo seu carinho e
compreensão, e por toda felicidade que me traz.
Aos meus camaradasirmãos que encontrei neste curso, agradeço
pelas alegrias e experiências divididas, e a amizade mútua.
A todos do PAIRG, eu agradeço por formarem comigo essa “família
universitária”.
Eu gostaria de agradecer, enfim, a todos os companheiros de jornada
que fizeram e fazem parte da minha vida: amigos, familiares, professores,
colegas. Vocês contribuíram para que eu seja quem eu sou e, portanto,
fazem parte do que eu sou. Obrigado!
Portanto, tornai a levantar as mãos cansadas e os joelhos desconjuntados.
Paulo. (Hebreus, 12:12)
Âmbar: Desenvolvimento de um Serviço
Multiplataforma e Descentralizado de Foto
Memórias
Autor: Paulo Leonardo Souza Brizolara
Orientador(a): Prof. Dr. Leonardo Cunha de Miranda
RESUMO
Fotografias são utilizadas como recursos para registrar memórias. Através
da proliferação de dispositivos computacionais multimídia se tornou muito
mais simples capturar e compartilhar fotografias. No entanto, essa grande
quantidade de dispositivos também torna as coleções de foto mais dispersas,
o que dificulta sua manutenção por longos períodos de tempo. Sistemas em
nuvem possibilitam integrar dispositivos e usuários de forma distribuída,
mas também restringem o controle dos usuários sobre seus dados e
levantam preocupações quanto a privacidade. Sistemas descentralizados
podem contribuir para a solução desses problemas, pois permitem aos
usuários manterem controle sobre seus dados e, ao mesmo tempo,
possibilitam a integração entre dispositivos e a cooperação entre pessoas.
Existem, no entanto, diversos desafios tecnológicos para o desenvolvimento
desse tipo de sistema. Neste trabalho identificamos alguns destes desafios e
desenvolvemos uma biblioteca para contribuir com a solução de parte deles,
relacionados à conexão descentralizada entre pares e à localização e
identificação de serviços de forma descentralizada. Apresentamos ainda,
nesse trabalho, uma plataforma que desenvolvemos para permitir o uso e
preservação de registros fotográficos de memórias (fotomemórias).
Utilizamos a biblioteca desenvolvida para permitir a comunicação
descentralizada entre clientes e servidores da plataforma.
Palavraschave: Sistemas distribuídos. Sistemas descentralizados.
Fotografia. Memória.
Âmbar: Development of a Decentralized and
Multiplatform PhotoMemories Service
Author: Paulo Leonardo Souza Brizolara
Advisor: Prof. Dr. Leonardo Cunha de Miranda
ABSTRACT
Photographs are used to record memories. Through the proliferation of
multimedia computing devices it has become much simpler to capture and
share photographs. However, this large number of devices also makes photo
collections more dispersed, making it difficult to maintain them for long
periods of time. Cloud systems enable to integrate devices and users in a
distributed way, but also restrict users' control over their data and raise
privacy concerns. Decentralized systems can contribute to solve these
problems by allowing users to maintain control over their data while
enabling the integration between devices and cooperation between people.
There are, however, several technological challenges for the development of
this type of system. In this work, we identify some of these challenges and
develop a software library to contribute with the solution of part of them,
related to the decentralized connection between peers, and the decentralized
location and identification of services. We also present, in this work, a
platform we have developed to allow the use and preservation of photography
records of memories (photomemories). We applied the developed library to
allow the decentralized communication between the platform’s clients and
services
Keywords: Distributed systems. Decentralized systems. Photography.
Memory.
Lista de figuras
Figura 1: Travessia de NAT através do encaminhamento de portas.............30
Figura 2: Travessia de NAT utilizando hole punching com protocolo STUN. 32
Figura 3: Travessia de NAT através de um servidor de relay........................34
Figura 4: Modelo de domínio da plataforma................................................68
Figura 5: Arquitetura do núcleo..................................................................71
Figura 6: Estrutura geral de rotas da API e alguns exemplos......................75
Figura 7: Exemplo do uso de parâmetros em requisições à API...................76
Figura 8: Aplicações da plataforma Âmbar executando em diferentes tipos de
dispositivos.................................................................................................87
Figura 9: Arquitetura geral da biblioteca.....................................................92
Figura 10: Classe Peer: fachada da biblioteca warptopeer........................93
Figura 11: Exemplos de uso da classe Peer.................................................93
Figura 12: Módulo de conectividade............................................................94
Figura 13: Ciclo de vida das conexões e eventos relacionados.....................95
Figura 14: Principais classes do módulo de identidade...............................99
Figura 15: túnel criado entre um cliente e um servidor, utilizando as pontes
da biblioteca.............................................................................................100
Figura 16: Principais classes do módulo de pontes...................................101
Figura 17: Diagrama de classes do módulo ICE........................................103
Figura 18: Classes dos módulos Signaller.................................................105
Figura 19: DhtSignaller: envio de requisição de conexão...........................107
Figura 20: DhtSignaller: requisição de conexão recebida..........................108
Figura 21: DhtSignaller: resposta de uma requisição de conexão recebida109
Figura 22: Componentes para integração entre o Âmbar Mobile e a Warpto
peer..........................................................................................................111
Figura 23: Processo de inicialização de uma ponte Warp2p, durante login no
Âmbar Mobile...........................................................................................112
Lista de tabelas
Tabela 1: Classificações de características do NAT......................................28
Tabela 2: Categorias de NAT.......................................................................29
Tabela 3: Comportamento geral para interagir com rotas da API.................75
Tabela 4: Papéis e funcionalidades dos clientes da plataforma....................81
Lista de abreviaturas e siglas
AP – access point
API – Application Programming Interface
ASP – Application Service Platform
BD – banco de dados
CDN – Content Delivery Network
CoAP – Constrained Application Protocol
CORS – CrossOrigin Resource Sharing
DA – directory agent
DAO – Data Access Object
DHT – distributed hash tables
DIAL – Discovery and Launch
DNS – Domain Name System
DNSSD – DNS Service Discovery
GENA – General Event Notification Architecture
GNS – Gnu Name System
GO – P2P Group Owner
HTTP – HyperText Transfer Protocol
HTTPS – HyperText Transfer Protocol Secure
ICE – Interactive Connectivity Establishment
IETF – Internet Engineering Task Force
IGD – Internet Gateway Device Protocol
IP – Internet Protocol
IPv4 – Internet Protocol version 4
JNI – Java Native Interface
JSON – JavaScript Object Notation
mDNS – multicast DNS
NAT – Network Address Translator
NATPMP – NAT Port Mapping Protocol
NFC – Near Field Communication
NMC – namecoins
PCP – Port Control Protocol
PKI – Public Key Infrastructury
REST – Representational State Transfer
SLP – Service Location Protocol
SOAP – Simple Object Access Protocol
SQL – Structured Query Language
SSDP – Simple Service Discovery Protocol
STUN – Session Traversal Utilities for NAT
TCP – Transmission Control Protocol
TLD – TopLevel Domain
TURN – Traversal Using Relays around NAT
UDP – User Datagram Protocol
UPnP – Universal Plug and Play
UUIDs – Universally Unique IDentifiers
VPN – Virtual Private Network
VR – Virtual Reality
Sumário
1 Introdução......................................................................................14
1.1 Objetivos............................................................................................15
1.2 Metodologia.......................................................................................16
1.3 Estrutura...........................................................................................16
2 Referencial Teórico.........................................................................18
2.1 Sistemas Descentralizados.................................................................18
2.2 Desafios.............................................................................................20
2.2.1 Conectividade..............................................................................20
2.2.1.1 Localização de Serviços..........................................................21
2.2.1.2 Conexão.................................................................................22
2.2.2 Identidade....................................................................................23
2.2.3 Outros desafios............................................................................25
2.3 Soluções Descentralizadas.................................................................26
2.3.1 Conectividade..............................................................................26
2.3.1.1 Técnicas para travessia de NAT..............................................26
2.3.1.1.1 Tipos de NAT....................................................................27
2.3.1.1.2 Protocolos para encaminhamento automático de portas...29
2.3.1.1.3 Hole punching e STUN.....................................................31
2.3.1.1.4 Técnicas baseadas em relays...........................................34
2.3.1.1.5 ICE..................................................................................36
2.3.1.1.6 WebRTC...........................................................................39
2.3.1.1.7 Redes Overlay PeertoPeer..............................................39
2.3.1.2 Protocolos para descoberta de serviços descentralizada.........42
2.3.1.2.1 Técnicas de curto alcance................................................43
2.3.1.2.2 Técnicas para descoberta de serviços de alcance local......46
2.3.1.2.3 Técnicas para descoberta de serviços de alcance global....51
2.3.2 Identidade Descentralizada..........................................................52
2.3.2.1 Criptografia para gerenciar identidades descentralizadas.......53
2.3.2.2 Blockchain e Identidade.........................................................55
2.3.2.3 Petnames...............................................................................57
2.3.2.4 Técnicas auxiliares para representar e transmitir identidades.58
3 Âmbar: Serviço Multiplataforma de FotoMemórias..........................60
3.1 Fotomemórias...................................................................................60
3.2 Desafios computacionais...................................................................62
3.2.1 Desafio #1: Manutenção de fotomemórias a longo prazo.............62
a) Localização e organização de fotomemórias...................................62
b) Armazenamento de fotomemórias através de múltiplos dispositivos
...................................................................................................................63
3.2.2 Desafio #2: Representação de fotomemórias...............................64
3.2.3 Desafio #3: Uso de fotos através de múltiplos dispositivos...........64
3.2.4 Desafio #4: Uso colaborativo........................................................65
3.2.5 Desafio #5: Controle/propriedade sobre fotomemórias................66
3.3 Âmbar................................................................................................67
3.3.1 Modelo de domínio.......................................................................67
3.3.2 Núcleo.........................................................................................70
3.3.2.1 API do serviço........................................................................73
3.3.2.2 Aplicações do núcleo..............................................................77
3.3.2.2.1 Âmbar Daemon................................................................78
3.3.2.2.2 Âmbar Android Server......................................................78
3.3.3 Clientes do serviço.......................................................................79
3.3.3.1 Papéis dos clientes.................................................................80
3.3.3.2 Âmbar mobile........................................................................82
3.3.3.3 Outras aplicaçõescliente.......................................................84
3.3.3.3.1 Âmbar display..................................................................84
3.3.3.3.2 Âmbar desktop viewer......................................................86
3.3.3.3.3 Âmbar VR........................................................................86
4 Warptopeer: Biblioteca para Conexões PeertoPeer........................88
4.1 Arquitetura........................................................................................90
4.1.1 Conectividade..............................................................................92
4.1.2 Identidade....................................................................................98
4.1.3 Pontes........................................................................................100
4.2 Implementações...............................................................................102
4.2.1 Módulo ICE................................................................................102
4.2.2 Signalling...................................................................................104
4.3 Âmbar descentralizado.....................................................................110
4.4 Discussão........................................................................................112
5 Conclusão......................................................................................115
5.1 Contribuições..................................................................................115
5.2 Limitações.......................................................................................116
5.3 Trabalhos Futuros...........................................................................117
Referências......................................................................................119
14
1 Introdução
A fotografia é um recurso importante pata registrar memórias e
comunicar experiências. Capturamos através da fotografia aquilo que nos
chama atenção, o que queremos mostrar a outros ou o que queremos
preservar para o futuro.
A computação provê hoje a base para isso. Utilizamos computadores
desde a captura da imagem, seja através de dispositivos de propósito
específico, como as câmeras digitais, ou utilizando dispositivos de propósito
geral, como smartphones ou tablets. Através de ferramentas computacionais
podemos manipular essas imagens, para satisfazer as nossas necessidades,
e distribuílas ao redor do mundo para quem quiser acessar, ou apenas,
para aqueles a quem concedemos permissão. Por sua vez, podemos
visualizar diariamente dezenas de fotos, ou mais, através da tela de nossos
dispositivos.
A computação tornou os processos de captura, armazenamento e
compartilhamento de fotos baratos, rápidos e eficientes. Contraditoriamente,
entretanto, isso tem tornado o registro de memórias mais difícil. A
quantidade de fotos capturadas e a variedade de dispositivos e serviços,
através dos quais elas são utilizadas, cria obstáculos para a organização e
manutenção de coleções de fotos por longos períodos de tempo, i.e. anos ou
até décadas. Dessa forma, há o risco de que esses registros de memórias se
percam com o tempo. Além disso, a dispersão dessas fotografias prejudica o
próprio uso delas, pois torna difícil a sua localização.
Serviços em nuvem oferecem soluções para alguns desses problemas.
Eles permitem a integração entre dispositivos e usuários, através de bases
de dados unificadas. Frequentemente, eles proveem também uma grande
quantidade de espaço de armazenamento, altas taxas de disponibilidade,
com baixo custo para os seus usuários. Entretanto, esses serviços levantam
diversas preocupações quanto ao controle e propriedade sobre os dados
armazenados, e a privacidade de seus usuários. A falta de controle sobre os
15
serviços e os recursos armazenados também torna difícil garantir a
manutenção dos dados a longo prazo, e a migração ou reuso deles em outros
serviços.
O desenvolvimento de sistemas descentralizados é uma das soluções
para lidar com os problemas de privacidade e controle presentes nos
serviços em nuvem. Esses sistemas permitem aos usuários manter um
maior controle sobre seus dados e proveem soluções para o
compartilhamento de recursos entre usuários e dispositivos através da rede.
Sistemas descentralizados podem também oferecer oportunidades para
inovação e criação, ao reduzir barreiras para que serviços possam ser
desenvolvidos e oferecidos, mesmo com recursos reduzidos.
Existem, entretanto, desafios computacionais para o desenvolvimento
desses sistemas. Técnicas tem sido utilizadas para solucionar esses desafios,
com maior ou menor êxito. No entanto, o desenvolvimento desses sistemas é
ainda relativamente reduzido. Alguns fatores que podem influenciar para
isso são: o conhecimento ainda pouco difundido sobre esses sistemas e as
técnicas que permitem seu desenvolvimento; a relativa complexidade para
aplicação de algumas dessas técnicas; e a escassez de componentes de
software, e.g. frameworks e bibliotecas, que permitam a adoção de forma
simples dessas técnicas no desenvolvimento de ferramentas e aplicações.
1.1 Objetivos
Definimos como objetivo principal deste trabalho, o desenvolvimento
de um sistema descentralizado para permitir o uso e manutenção de
registros fotográficos de memórias. Para isso, delimitamos os seguintes
objetivos específicos:
• Identificar os desafios existentes para o desenvolvimento de sistemas
descentralizados
• Identificar as soluções existentes para esses desafios
• Desenvolver componentes de software que permitam reutilizar essas
soluções em aplicações
16
• Utilizar os componentes desenvolvidos em uma aplicação para o uso e
manutenção de registros fotográficos de memórias.
1.2 Metodologia
O ponto de partida do trabalho realizado foi o Âmbar, uma plataforma
que desenvolvemos, em trabalhos anteriores, para permitir o uso e
manutenção de fotografias como registros de memória. A partir do Âmbar
identificamos necessidades que precisariam ser atendidas por soluções
descentralizadas.
Realizamos, então, pesquisas para determinar os desafios, que
precisariam ser solucionados para atender às necessidades definidas, e as
soluções existentes para esses desafios. Essas pesquisas foram realizadas a
partir de aplicações definidas como descentralizadas e a partir de textos
científicos. Para localizar as primeiras foi utilizada uma lista de aplicações
descentralizadas1, organizada pela iniciativa “redecentralize.org”, e foram
realizadas buscas em repositórios de software. A busca por trabalhos
científicos relacionados foi feita em bases da área de computação ou
relacionadas, como ACM Digital Library2, IEEE Xplore3, e Springer4, e em
indexadores de trabalhos científicos, como Google Acadêmico5 e Web of
Science6.
A partir dos desafios e soluções levantadas, delimitamos um escopo
para desenvolvimento nesse trabalho e determinamos um conjunto de
soluções para serem aplicadas. Para analisar a viabilidade do uso dessas
soluções, no contexto do projeto, foi desenvolvida uma prova de conceito
com a integração delas. A partir disso, construímos uma biblioteca (a Warp
toPeer) e aplicamos ela à plataforma Âmbar.
1.3 Estrutura
Esse trabalho esta organizado na seguinte estrutura:
Capítulo 2 – Referencial Teórico: apresenta a definição adotada para1 redecentralize.github.io/alternative-internet2 dl.acm.org3 ieeexplore.ieee.org4 springer.com5 scholar.google.com.br6 ipscience.thomsonreuters.com/product/web-of-science
17
sistemas descentralizados, e os desafios e soluções pesquisados.
Capítulo 3 – Âmbar: Serviço Multiplataforma de FotoMemórias:
descreve a plataforma Âmbar e os elementos relacionados ao seu
domínio (as fotomemórias).
Capítulo 4 – Warptopeer: Biblioteca para Conexões PeertoPeer:
apresenta a biblioteca warptopeer desenvolvida para permitir
estabelecer comunicações em sistemas descentralizados e sua
aplicação na plataforma Âmbar.
Capítulo 5 – Conclusão: descreve resumidamente as contribuições e
limitações do trabalho e aponta para trabalhos futuros.
18
2 Referencial Teórico
Neste capítulo apresentamos um conjunto de desafios relacionados ao
desenvolvimento de sistemas descentralizados (seção 2.2) e soluções
existentes para tratar esses desafios (seção 2.3). Para descrever o nosso
entendimento do que são sistemas descentralizados, e diante da ausência de
uma definição na literatura pesquisada, apresentamos também, na seção
2.1, a definição para sistemas descentralizados utilizada neste trabalho,
derivada do conceito de descentralização.
2.1 Sistemas Descentralizados
Descentralização pode ser definida como “a distribuição ou dispersão
de funções e poderes”7. Esse conceito está presente em diferentes áreas do
conhecimento, tais como política, economia e administração. A democracia,
por exemplo, surge da descentralização do poder, de um indivíduo
(monarquia) ou grupo (oligarquia) para uma coletividade.
Na computação, a descentralização é um aspecto associado
geralmente à arquitetura de sistemas distribuídos. Tanenbaum e
Steen(2016), por exemplo, utilizam a descentralização como um critério de
classificação para essas arquiteturas. Entretanto, outros aspectos de um
sistema podem também ser descentralizados. Raval (2016) discute, por
exemplo, a descentralização de identidades, do armazenamento de dados e
de computação (processamento). A própria infraestrutura da rede pode
também ser descentralizada, através do uso de redes mesh, por exemplo.
Assim, a ideia de sistemas (computacionais) descentralizados pode
estar associada a um ou mais desses aspectos. Para o contexto deste
trabalho, caracterizamos sistemas descentralizados como sistemas
distribuídos em que não há uma entidade ou grupo restrito que detenha o
controle, direta ou indiretamente, sobre todos os recursos ou serviços do
sistema.7 Tradução do Merriam-webster : https://www.merriamwebster.com/dictionary/decentralization
19
Entendemos, que não faz sentido considerar sistemas descentralizados
compostos por único dispositivo isolado. Dessa forma, podemos identificá
los como uma subclasse de sistemas distribuídos.
Consideramos, entretanto, que o aspecto fundamental está no quanto
o controle sobre o sistema está distribuído entre as partes independentes
que o compõe. Isto é, a “dispersão de funções e poderes”. Distinguimos,
assim, esses sistemas de outros sistemas distribuídos.
CDNs (Content Delivery Networks), por exemplo, podem apresentar um
grande número de nós distribuídos, que podem atuar de forma mais ou
menos independente uns dos outros. Entretanto, o controle sobre a rede
está, geralmente, concentrado em uma única organização, o que torna o
sistema centralizado. No DNS (Domain Name System), por sua vez, o controle
é exercido de forma indireta e hierárquica, a partir dos servidores raiz, que
por sua vez, são controlados por um pequeno número de organizações. Já o
Bittorrent é um exemplo de sistema descentralizado, pois não há uma única
entidade ou grupo fechado que possa controlar a rede. Ele permite,
inclusive, que várias redes independentes se formem. Além disso, se um nó,
ou mesmo vários, forem removidos da rede, isso não impedirá que ela
continue funcionando ou se forme novamente.
Destacamos, no entanto, que a descentralização de um sistema (ou de
um aspecto dele) não é uma propriedade binária. Ou seja, podemos
considerar “graus de descentralização” para sistemas distribuídos distintos.
Sistemas peertopeer e redes federadas, por exemplo, podem ser tipos de
sistemas descentralizados. Entretanto, os primeiros podem ser considerados
mais descentralizados. Podemos utilizar a definição, entretanto, como uma
forma de simplificar a análise dos sistemas descentralizados e como guia
para outros aspectos deste trabalho.
Algumas características desejáveis ou necessárias para sistemas
descentralizados podem também ser destacadas, a partir da definição
formulada. Uma delas é a capacidade de novos nós se integrarem ao
sistema, de forma mais ou menos autônoma. Pois, se um grupo ou entidade
puder controlar ou restringir quem pode se integrar ao sistema, na prática
20
eles tem controle sobre o sistema como um todo.
Outra característica relacionada é a relativa independência entre os
nós e a capacidade de autoreconfiguração do sistema como um todo. Pois,
quanto maior a dependência do sistema para um único nó, maior influência
esse nó terá sobre o sistema, i.e. maior controle. Portanto, quanto maior a
descentralização de um sistema, maior tende a ser a independência entre os
nós, e maior a capacidade do sistema se readaptar à saída ou falha dos nós
que o compõem.
Dessa forma, podemos entender que a descentralização de um sistema
pode contribuir, dentre outras propriedades, para a sua extensibilidade,
escalabilidade e tolerância a falhas. As características identificadas estão
também relacionadas aos conceitos de “sistemas autônomos
descentralizados” (MORI, 1993) e “autonomic computing” (KEPHART;
CHESS, 2003).
2.2 Desafios
Para a construção de sistemas descentralizados existem ainda
diversos desafios específicos. Buscamos identificar e apresentar alguns deles
a seguir.
2.2.1 Conectividade
Um dos primeiros desafios para o desenvolvimento de sistemas
descentralizados está em determinar como estabelecer a comunicação entre
os nós que compõem o sistema. Para que um nó estabeleça a comunicação
com outro, duas principais etapas podem ser identificadas: localizar o nó
desejado, e o serviço presente nele, e estabelecer uma conexão com este
serviço.
21
2.2.1.1 Localização de Serviços
Localizar um serviço, em um determinado nó da rede, envolve
identificar um endereço que permita estabelecer uma comunicação com ele.
Isso pode ser feito, de acordo com as tecnologias utilizadas, a partir de um
identificador único ou utilizando outros critérios de busca que permitam
localizar um ou mais serviços que atendam aos critérios desejados. O escopo
da busca pode variar desde a mesma máquina, e.g. comunicação entre
processos, até escala global, i.e. através da Internet.
Protocolos para a localização de serviços também podem prover um
meio de mais alto nível para identificar um dado serviço. No caso da
Internet, por exemplo, um endereço IP pode não ser suficiente para localizar
um dispositivo ou serviço de forma confiável. Pois, provedores de internet
podem não garantir que um mesmo IP seja entregue a um mesmo cliente.
Além disso, há questões quanto a mobilidade e volatilidade dos dispositivos.
Isto é, um mesmo dispositivo pode se conectar à Internet através de
diferentes redes ao longo do tempo ou ter seu endereço modificado, devido a
atribuição dinâmica de endereços por exemplo.
O DNS é a principal tecnologia utilizada para localizar dispositivos e
serviços através da Internet. Ele provê uma estrutura distribuída
globalmente para localizar recursos e permite desacoplar um serviço de um
endereço ou dispositivo específico. Entretanto, o DNS impõe diversas
barreiras para o desenvolvimento de aplicações descentralizadas.
A estrutura do DNS em si, impõe uma “cadeia de autoridade”
hierárquica que limita a autonomia e a capacidade de registrar novos nós ou
serviços dinamicamente. Isto é, como a autoridade sobre um subdomínio é
delegada a partir de um outro domínio “pai”, criase uma relação de
dependência entre eles. Ou seja, um domínio pode revogar um subdomínio
ou, em caso de falhas, prejudicar o seu funcionamento.
O próprio serviço acaba dependendo, mesmo que indiretamente, do
servidor de nomes e de toda a hierarquia, pois se o serviço não puder ser
localizado corretamente, seus clientes não poderão utilizálo. Essa estrutura
hierárquica também torna o DNS mais sensível a censura ou interferências
22
de agências governamentais.
O processo de registro e manutenção de nomes também dificulta o uso
do DNS por sistemas descentralizados. Esse processo é, geralmente, custoso
e não automatizado. Isso pode inviabilizar o uso do DNS por serviços
efêmeros ou “domésticos”.
2.2.1.2 Conexão
A Internet, i.e. o protocolo IP, foi projetada para permitir a conexão
fimafim entre qualquer par de nós conectados à rede. Isto é, para se
comunicar com um outro dispositivo, bastaria conhecer o seu endereço IP e
a porta do serviço a ser utilizado.
Entretanto, com o crescimento no número de dispositivos conectados
à Internet e a consequente redução no número de endereços IPv4
disponíveis, um novo modelo de comunicação foi adotado. A partir do uso de
tecnologias como o NAT(Network Address Translation), criouse uma
distinção entre nós ou serviços públicos e privados. Os primeiros podem ser
acessados por qualquer dispositivo na Internet. Enquanto os segundos
podem receber conexões apenas de dispositivos na mesma rede local ou
intranet em que se encontram.
O NAT é uma tecnologia utilizada para lidar com a escassez nos
endereços IPv4. Ele permite que um nó da rede compartilhe um endereço IP
com um conjunto de outros nós. Para isso, geralmente é utilizada uma faixa
de endereços privados, que não são roteáveis através da Internet. Esses
endereços são alocados para os nós “internos”. Esses nós, então, quando
desejam se comunicar com outros nós da internet, enviam o tráfego para o
nó responsável pelo NAT, que redireciona os pacotes. Nesse processo ele
modifica o endereço de origem pelo seu próprio endereço, i.e. do ponto de
vista dos outros nós da Internet, todos os pacotes vem de um único
dispositivo. Ao receber uma resposta, o pacote é encaminhado para máquina
que fez a requisição originalmente.
Como consequência da estrutura do NAT, esses nós “internos” não
podem mais ser acessados diretamente por outros nós da Internet, já que
23
eles não possuem um endereço público. Isso impossibilita, a princípio, que
um nó sobre NAT receba conexões de outros nós através da Internet.
Nesse modelo, aplicações peertopeer precisam utilizar de técnicas
para “burlar” as restrições do NAT e, em alguns casos, precisam utilizar
outros nós, acessíveis publicamente, como intermediários para encaminhar
as mensagens. Isso termina por aumentar a complexidade e reduzir o
desempenho dessas aplicações.
A implantação do protocolo IPv6 em larga escala deve contribuir para
solucionar esse problema, pois ele elimina a necessidade do NAT.
Além das limitações descritas, restrições impostas por firewalls podem
também impedir a comunicação entre nós através da Internet. Embora isso
seja, frequentemente, um aspecto de segurança importante, usuários e
aplicações deveriam ter a capacidade de determinar quando desejam expor
um serviço ou receber comunicações através da Internet.
Outras discussões, entretanto, podem ser levantadas quanto a
capacidade de usuários “leigos” lidarem com essas tecnologias de segurança
ou até onde administradores de rede devem controlar quais aplicações
podem ser executadas através da rede, em especial em ambientes públicos
ou corporativos. Essas discussões, no entanto, fogem ao escopo deste
trabalho.
2.2.2 Identidade
Além de estabelecer a conexão entre nós da rede, sistemas distribuídos
precisam, frequentemente, determinar a identidade de usuários e serviços
que se comunicam, tanto por questões de segurança quanto, em alguns
casos, por requisitos da aplicação.
Para isso, é preciso garantir que os identificadores utilizados sejam
únicos. Além disso, é preciso prover meios para validar esses identificadores,
assim como evitar a falsificação ou roubo de identidades. Em alguns casos
também pode ser necessário impedir ou dificultar a geração arbitrária ou
infinita de novas identidades. Por exemplo, para evitar fraudes em sistemas
24
com mecanismos de votação ou spam em sistemas de comunicação.
A geração e validação da identidade de usuários em sistemas
distribuídos centralizados pode ser controlada pelo próprio provedor do
serviço. Um modo difundido para isso é utilizar de um nome de usuário e
senha, definidos pelo usuário. O primeiro é utilizado como identificador, e
deve ser único no escopo do sistema. Enquanto a senha é utilizada para
validar a propriedade de um usuário sobre a conta.
Contas de email e números de telefone são outros recursos
amplamente utilizados para o gerenciamento de identidades de usuário
nesses sistemas. Eles podem prover um identificador único para os usuários
e um meio para recuperar o acesso à conta, além de dificultar a geração de
identidades de forma arbitrária.
Outra solução utilizada é delegar o processo de autenticação e
gerenciamento de identidades à trusted third parts. Para isso é possível
utilizar serviços específicos daquele provedor ou protocolos genéricos como o
OpenID .
Na Web, a identificação de sites e serviços é feita através do DNS e de
uma Public Key Infrastructury(PKI). Os nomes de domínio são utilizados
como identificadores. Cada servidor de nomes deve garantir que os nomes
sejam únicos internamente e a estrutura hierárquica do DNS garante que
eles sejam únicos globalmente.
Entretanto, o DNS está exposto a ataques como DNS spoofing que
podem modificar respostas recebidas por um cliente DNS para apontar para
direcionar um nome a um endereço de interesse do atacante.
Dessa forma, para validar a identidade de um site acessado na Web, o
protocolo HTTPS(HyperText Transfer Protocol Secure) utiliza de autoridades
certificadoras. Durante o processo de conexão, cada site deve retornar um
certificado que contenha, dentre outras informações, o nome de domínio
apropriado. Para validar o certificado, o cliente deverá verificar a cadeia de
certificados. Isto é, o cliente irá verificar qual autoridade certificadora
assinou o certificado. Caso ela não seja conhecida, o cliente irá verificar o
25
certificado dela e assim iterativamente até chegar a uma autoridade
conhecida. Os navegadores incluem, já durante a instalação, uma lista de
autoridades certificadoras conhecidas.
Uma limitação desses esquemas para gerenciamento de identidades é
a necessidade de confiar em uma, ou um grupo de “autoridades”. Caso uma
delas seja comprometida ou apresente um comportamento inadequado, pode
comprometer a todo o sistema. Além disso, clientes não podem verificar ou
garantir que essas autoridades apresentem um comportamento adequado.
Para sistemas descentralizados é preciso utilizar de protocolos que
negociem entre as partes a geração e validade dessas identidades. Há ainda
um desafio em como gerar identidades que sejam seguras, únicas e
significativas para humanos, referenciado como triângulo de Zooko.
2.2.3 Outros desafios
Por uma questão de escopo, nos limitamos a tratar neste trabalho dos
desafios descritos anteriormente. Entretanto, visualizamos alguns outros
que listamos a seguir. Mas acreditamos que outros ainda podem ser
levantados em trabalhos futuros.
Um desses desafios é a manutenção de dados de forma
descentralizada. Em sistemas distribuídos em que há o compartilhamento
de recursos, tornase necessário lidar com a concorrência entre os nós,
buscando garantir uma consistência na visão dos recursos compartilhados.
Em sistemas descentralizados há um desafio maior, pois não há um ponto
central que estabeleça uma visão “canônica” para todos. Invés disso, os nós
precisam coordenar entre si para chegar a um consenso ou prover meios
para lidar com as divergências.
Outro desafio importante para construir sistemas descentralizados, é
a necessidade de estabelecer a confiança entre pares. Ao estabelecer
comunicações e utilizar identidades de forma segura, é possível reconhecer
pares conhecidos e interagir com eles. Entretanto, em sistemas em que é
preciso relacionarse a entidades desconhecidas, como determinar se elas
são confiáveis? Em sistemas centralizados, relações entre desconhecidos
26
podem ser intermediadas ou a confiabilidade deles verificada por
“autoridades” ou “terceiros confiáveis”. Em sistemas descentralizados,
entretanto, podem ser necessárias outras estratégias, como a análise do
comportamento dos pares e incentivos para cooperação (OUALHA;
ROUDIER, 2010).
2.3 Soluções Descentralizadas
Para solucionar os desafios identificados na seção 2.2 de forma
descentralizada, existem diferentes soluções. Cada uma delas trás
características diferentes e podem ser mais apropriadas para contextos e
aplicações distintas, ou serem utilizadas em conjunto. Nesta seção
descrevemos a soluções encontradas, organizadas de acordo com os desafios
descritos na seção 2.2, i.e. soluções para conectividade (seção 2.3.1) e
soluções para criação e uso de identidades descentralizadas (seção 2.3.2).
2.3.1 Conectividade
O desafio de estabelecer conexões de forma descentralizada se reflete
em dois problemas práticos. O primeiro, a travessia de NAT, reflete a questão
de estabelecer a conexão entre nós através da Internet, ou em subredes
distintas, na presença de NAT. O segundo problema, a descoberta ou
localização de serviços, trata de como localizar um determinado serviço a
que se deseja conectar, ou algum serviço que satisfaça um determinado
critério. As subseções 2.3.1.1 e 2.3.1.2, respectivamente, apresentam
soluções a esses problemas.
2.3.1.1 Técnicas para travessia de NAT
Identificamos três tipos principais de técnicas para travessia de NAT:
encaminhamento de portas (seção 2.3.1.1.2), hole punching (seção 2.3.1.1.3)
e relay (seção 2.3.1.1.4). Para entender melhor as técnicas para a travessia
de NAT, apresentamos na seção 2.3.1.1.1 os tipos diferentes de NAT que
existem e as características relacionadas a eles. Descrevemos também, nas
seções 2.3.1.1.5, 2.3.1.1.6 e 2.3.1.1.7, soluções construídas a partir das
27
outras técnicas de travessia ou que podem ser utilizadas para auxiliálas.
2.3.1.1.1 Tipos de NAT
Embora o uso do NAT esteja bem difundido, não há um protocolo ou
abordagem comum para sua implementação. Com isso, o comportamento do
NAT pode variar de acordo com cada dispositivo que o implementa
(MÜLLER; CARLE, 2008).
Apesar disso, classificações podem ser utilizadas para agrupar essas
implementações, de acordo com características comuns. Isso é importante
para entender a aplicabilidade e limitações das diferentes técnicas de
travessia de NAT.
Müller e Carle (2008) apresentam classificações para três diferentes
aspectos do comportamento de implementações do NAT: port binding, NAT
binding e Endpoint filtering (Tabela I).
Port Binding diz respeito à estratégia utilizada pelo NAT para atribuir
portas a cada nova conexão. Para isso o NAT pode realizar ou não
preservação de porta (port preservation). Isso corresponde a tentar manter o
mesmo número de porta, se possível, utilizado na porta interna para a porta
externa.
Implementações de NAT podem também realizar “port overloading”.
Nesse caso, é permitido que diferentes conexões utilizem a mesma porta de
saída (mesmo que o endereço de origem seja distinto). Entretanto, algumas
aplicações podem não funcionar adequadamente nesse cenário (AUDET;
JENNINGS, 2017). Uma outra estratégia (port multiplexing) permite que uma
porta externa seja reaproveitada por diferentes conexões. Nesse caso, as
conexões são diferenciadas com base no endereço de destino.
Outro aspecto que influencia no port binding é se a seleção de novas
portas é aleatória ou se segue uma estratégia determinística. A faixa de
portas externas escolhidas para criação de bindings é também variável e
pode considerar a classificação de faixas de portas feita pela IANA (AUDET;
28
JENNINGS, 2007), i.e. portas “wellknown” (0 a 1023), “registered” (1024 a
49151) e dinâmicas (49152 a 65535).
A estratégia utilizada para NAT binding determina quando uma nova
conexão, feita a partir de uma porta e endereço internos que já tem um
binding ativo, utilizará ou não o mesmo binding, isto é, a mesma porta
externa. Para isso, podem ser considerados se as informações do destino
equivalem às utilizadas no binding anterior. De acordo com as informações
utilizadas para isso, é possível classificar o NAT como: dependente do
endereço, quando o endereço é considerado; dependente de endereço e
porta, quando essas duas informações são utilizadas; ou independente de
endpoint, quando o mesmo binding é utilizado independente do destino.
Além disso, uma implementação de NAT pode ainda utilizar um novo binding
para cada nova conexão.
O NAT pode variar ainda de acordo com a estratégia utilizada para
filtrar pacotes recebidos para um binding ativo. Para isso o NAT poderá
observar se o endereço e porta de origem do pacote recebido correspondem
aos dados de destino de um pacote enviado anteriormente através daquela
porta externa. Podem ser considerados tanto endereço e porta, apenas o
endereço ou nenhum dos dois. De acordo com isso, o NAT é classificado,
respectivamente, em: “Address and Port restricted”, “Address restricted”, ou
“Independent Filtering”.
Tabela 1: Classificações de características do NAT
Características Classificações
Port Binding
Port preservation
sim/não
Port overloading
sim/não
Port multiplexing
sim/não
Seleção de portas
aleatória/determinística
NAT BindingIndependente de endpointDependente de endereço
29
Dependente de endereço e porta
Endpoint Filtering
Independent FilteringAddress Restricted
Address and Port Restricted
Fonte: o autor
Uma outra forma de classificação (MEYE, 2011) divide os tipos de NAT
em 4 categorias: Full Cone NAT, Restricted Cone NAT, Port Restricted NAT e
Symmetric NAT. Essas categorias podem ser descritas com base nas
classificações dadas anteriormente, como apresentado na tabela 2.
Tabela 2: Categorias de NAT
Categoria NAT Binding Endpoint Filtering
Full cone Endpoint Independent IndependentRestricted cone
Endpoint Independent Address Restricted
Port restricted cone
Endpoint Independent Address and Port Restricted
Symmetric Address and Port Restricted
Address and Port Restricted
Fonte: o autor
2.3.1.1.2 Protocolos para encaminhamento automático de portas
Para fazer a travessia de NAT, alguns protocolos interagem com o
roteador NAT para realizar o encaminhamento automático de portas, tais
como o Internet Gateway Device Protocol(IGD), o NAT Port Mapping
Protocol(NATPMP) e o Port Control Protocol (PCP).
O encaminhamento de portas (port forwarding) consiste na criação de
um mapeamento no roteador NAT que permita encaminhar tráfego recebido
em uma porta externa do roteador para uma porta de um dispositivo da rede
interna, e viceversa, sem necessitar que o dispositivo interno estabeleça a
comunicação com um endereço externo previamente (Figura 1).
30
Figura 1: Travessia de NAT através do encaminhamento de portas
Fonte: o autor
O protocolo IGD faz parte do padrão UPnP (Universal Plug and Play).
Assim, ele utiliza de outros protocolos definidos pelo padrão para localizar e
interagir com o roteador NAT, como SOAP (Simple Object Access Protocol), e
SSDP (Simple Service Discovery Protocol). Através desses protocolos,
aplicações podem, além de encaminhar portas, localizar e controlar
dispositivos na rede, incluindo o roteador NAT (Gateway Device).
Apesar da conveniência para usuários e aplicações, esses protocolos
também podem permitir a atacantes, através de vulnerabilidades, expor e
controlar dispositivos na rede interna.
NATPMP e seu sucessor, PCP, são alternativas para o IGD
desenvolvidas inicialmente pela Apple e propostas para padronização através
do IETF (RFCs 6886 e 6887, respectivamente). No entanto, eles não tem uma
adoção tão grande quanto o IGD.
Uma limitação nessas soluções é que elas não permitem realizar a
travessia através de múltiplas camadas de NAT. Além disso, elas dependem
que o protocolo esteja implementado e habilitado no roteador utilizado.
31
Alguns modelos, por questões de segurança, exigem que os usuários
habilitem o protocolo (manualmente), o que pode impor barreiras para
usuários leigos.
2.3.1.1.3 Hole punching e STUN
Hole punching é uma técnica para travessia de NAT que permite
estabelecer uma comunicação direta entre dois nós, com o auxílio de, pelo
menos, um servidor acessível pelos dois (rendezvous server ou signalling
server) (FORD et al, 2005).
O processo de hole punching (Figura 2) pode ser dividido em três
principais etapas: (i) determinar o endereço e porta externos (em relação ao
NAT); (ii) trocar com o outro nó o endereço obtido; e (iii) tentar se conectar ao
endereço obtido do outro nó.
Para descobrir o seu endereço e porta externos, um nó 'A' precisa se
conectar a um outro nó 'S' que esteja fora do NAT, isto é, possua um
endereço publicamente acessível. Ao estabelecer a conexão, 'S' poderá
identificar de qual endereço e porta ele recebeu a mensagem, e informar de
volta a 'A'.
Esse processo pode ser feito através do protocolo STUN (Session
Traversal Utilities for NAT). O STUN provê uma solução padronizada para
que um nó determine seu endereço externo, com a ajuda de um servidor.
Isso permite reduzir a duplicação de código e esforço. Aplicações podem
também compartilhar servidores STUN, e disponibilizálos publicamente, ou
embutir o protocolo como parte da própria aplicação. O STUN pode também
ser utilizado para manter um binding NAT ativo (evitar que ele expire) e
permitir checar a conectividade entre dois endpoints (ROSENBERG et al,
2008).
32
Figura 2: Travessia de NAT utilizando hole punching com protocolo STUN
Fonte: o autor
Tendo identificado o seu endereço externo, o nó 'A' precisa comunicá
lo ao nó 'B', a que ele deseja se conectar. Como ele não tem acesso direto a
'B', ele precisa rotear a mensagem através de um nó 'R'. Esse nó deve ser
capaz de localizar 'B', através de um identificador fornecido por 'A', e
encaminhar a mensagem para ele. Após receber a mensagem de 'A', 'B' irá
realizar o mesmo processo de descoberta de endereço e encaminhar a
resposta para 'A'.
Uma forma comum e relativamente simples de implementar essa
“troca de sinais” é através do uso de um servidor central. Os nós que
desejem se comunicar, podem se registrar neste servidor e ele se torna
responsável por localizar outros nós e encaminhar mensagens a eles.
33
Entretanto, é possível utilizar de outros mecanismos para realizar essa
“troca de sinais”, incluindo soluções descentralizadas, contanto que
permitam aos pares trocarem mensagens entre si.
Após a troca de endereços, os dois nós irão tentar iniciar a
comunicação. Quando o nó 'A' enviar um pacote para o endereço de 'B', cria
se um binding no NAT de 'A' para aquele endereço. Ao ser recebido no NAT
de 'B', entretanto, esse pacote pode ser considerado como uma
“comunicação indesejada” e descartado. Entretanto, quando o NAT de 'A',
receber um pacote de 'B', ele irá considerálo uma resposta à mensagem
enviada inicialmente. Dessa forma a conexão é estabelecida.
Existem diferenças entre a implementação do hole punching para TCP
e UDP, embora o processo descrito se aplique, de forma geral, a ambos. No
caso do TCP, há maiores restrições, devido ao processo de conexão utilizado
por ele (threeway handshake). Por isso, o UDP hole punching é geralmente
mais facilmente implementado e, em alguns casos, relatado com uma taxa
de sucesso superior (FORD et al, 2005). Entretanto, a aplicação de técnicas
mais robustas poderia tornar o hole punching TCP tão eficiente quanto com
UDP (SRISURESH et al, 2008).
O hole punching é considerada uma técnica eficaz para travessia de
NAT (SRISURESH et al, 2008) (HU, 2005). Ela é capaz de atravessar
diferentes camadas de NAT e não depende do conhecimento da topologia da
rede ou do suporte de um protocolo específico pelo dispositivo de NAT.
Entretanto, esta técnica não funciona com dispositivos que utilizam
NAT simétrico, ou outras formas de mapeamento de NAT (NAT binding)
dependente do endpoint. Pois, nesses tipos de NAT, o endereço externo
identificado pelo servidor STUN (ou soluções similares) será diferente do
utilizado para se comunicar com o outro nó, já que um novo binding será
criado pelo NAT (pois o endereço de destino é diferente).
Uma alternativa utilizada com esse tipo de NAT é a previsão de portas.
Ela se baseia na tentativa de identificar qual porta será alocada para um
binding posterior de um mesmo dispositivo. Entretanto, ela está restrita a
34
dispositivos de NAT que utilizem mecanismos determinísticos para seleção
de portas e pode ser influenciada por outros dispositivos sobre o mesmo
NAT.
2.3.1.1.4 Técnicas baseadas em relays
Técnicas baseadas em relay(retransmissão) utilizam um ou mais
servidores que atuam como intermediários entre os nós da rede,
retransmitindo a comunicação entre eles. O processo se assemelha ao
roteamento, porém é feito a um nível de aplicação.
Figura 3: Travessia de NAT através de um servidor de relay
Fonte: o autor
Essas técnicas permitem realizar a travessia para qualquer tipo de
NAT, pois do ponto de vista do dispositivo de NAT, elas não se diferenciam
da comunicação com outros servidores na Internet. Entretanto, elas são
35
mais custosas e tendem a oferecer um desempenho inferior em relação a
técnicas que realizam a comunicação direta, pois elas exigem que todo o
tráfego passe por um ou mais intermediários. Isso introduz latência na
comunicação e dificulta a escalabilidade da solução, além de exigir a
manutenção dos servidores.
Uma técnica simples de relay consiste no uso de um servidor de
aplicação. Esse servidor interage com os clientes de uma determinada
aplicação para retransmitir o tráfego entre eles. O servidor pode ser
implantado na rede pública ou na rede interna (MEYE, 2011).
O gateway de nível de aplicação (Application Level Gateway) é também
uma solução específica de uma aplicação, porém ele pode atuar diretamente
sobre o dispositivo de NAT ou modificar os pacotes da rede para permitir
uma comunicação transparente entre os clientes (SRISURESH, P.;
HOLDREGE, 1999) .
TURN(Traversal Using Relays around NAT) é um protocolo de relay
com propósito geral definido pelo IETF (MAHY et al, 2010). Isto é, servidores
TURN podem ser utilizados por diferentes aplicações. Para tanto, porém, elas
devem implementar o lado cliente do protocolo.
Para estabelecer a comunicação com outros pares, um cliente TURN se
conecta a um servidor e envia uma requisição para alocar um endereço. Para
isso, o cliente deve se autenticar com o servidor. O servidor, então, associa
um endereço de transporte (IP e porta) àquele cliente. Esse endereço,
chamado de serverreflexive, pode então ser passado a outros pares, os
meios para isso, entretanto, estão fora do escopo do protocolo. Uma vez
alocado o endereço, um cliente precisa mantêlo ativo através de requisições
períodicas ao servidor.
Mensagens enviadas para o endereço serverreflexive são encapsuladas
em uma mensagem TURN e encaminhadas para o cliente. Por sua vez, para
que um cliente envie dados para um par através do servidor, ele deve
encapsulálos em uma mensagem TURN. Essas mensagens contém o
endereço do par a que devem ser encaminhadas (ou que enviou a
mensagem), isso permite a um cliente TURN se conectar a vários pares
36
através de um mesmo endereço.
TURN foi definido como uma extensão ao protocolo STUN. Isto é, sua
operação é feita através de métodos e atributos adicionados ao STUN. Isso
permite simplificar a implementação do protocolo para clientes e servidores
que já utilizem o STUN.
Uma limitação do protocolo é que ele suporta apenas UDP para a
comunicação entre pares com o servidor (utilizando um endereço reflexivo).
Entretanto, clientes TURN podem se conectar ao servidor através de UDP,
TCP ou TLS.
Outra solução que permite a travessia de NAT de forma independente
de aplicação é o protocolo Teredo, desenvolvido pela Microsoft e padronizado
junto ao IETF (HUITEMA, 2006). Ele permite que nós na rede IPv4 obtenham
conectividade IPv6. Isto é, ele encapsula pacotes IPv6 em pacotes IPv4 (6to4)
e encaminha eles através de servidores publicamente acessíveis (servidores
Teredo) e roteadores IPv6 com suporte ao protocolo (relays Teredo).
Retransmissão de pacotes pode ser realizada também em soluções
descentralizadas, é o caso de algumas redes overlay, i.e. redes construídas
sobre outras redes. Esse é o caso das redes Tor, I2P e Freenet. Essas redes
permitem o roteamento de pacotes entre nós da rede e, em alguns casos,
para nós fora da rede (como no Tor).
2.3.1.1.5 ICE
ICE (Interactive Connectivity Establishment) é um protocolo para
travessia de NAT que permite a dois pares (agentes ICE) estabelecerem uma
conexão a partir de um conjunto de endereços candidatos. O protocolo se
baseia no STUN e TURN para obter esses endereços, mas permite o uso de
outras soluções, como o UPnP IGD, NATPMP, ou VPNs (Virtual Private
Networks).
O processo de conexão do ICE pode ser dividido em três etapas que
correspondem às utilizadas no hole punching e STUN. São elas: (i) obtenção
37
dos endereços candidatos; (ii) troca de endereços entre os agentes; e (iii)
estabelecimento da conexão através de um dos endereços obtidos.
Entretanto, diferente do processo de hole punching básico, descrito na seção
2.3.1.1.3, ICE utiliza múltiplos endereços candidatos e provê um mecanismo
para priorizar e selecionar qual par desses candidatos será utilizado para
manter a comunicação.
ICE identifica 4 tipos de endereços candidatos: host, serverreflexive,
peer reflexive e relayed. O primeiro tipo corresponde a endereços obtidos
através da alocação de portas nos endereços IP do host. Eles podem incluir
tanto endereços UDP quanto TCP. Outros mecanismos também podem ser
utilizados para obter esse tipo de endereço, como VPNs ou encaminhamento
de portas.
Endereços serverreflexive e relayed são obtidos, respectivamente,
utilizando o protocolo STUN e TURN. Eles podem não ser obtidos caso não
haja um servidor correspondente disponível. Candidatos serverreflexive e
relayed podem ser obtidos para cada candidato de host. Candidatos
redundantes são removidos.
Os endereços peerreflexive são obtidos durante as verificações de
conectividade com o outro agente, caso o endereço observado por ele seja
diferente do esperado, por isso não são incluídos na lista inicial de
candidatos.
Cada candidato deve incluir uma prioridade única, que será utilizada
para selecionar qual par de endereços será utilizado, caso mais de uma
conexão seja estabelecida. Essa prioridade deveria levar em conta o tipo do
candidato e características de cada IP obtido. É recomendável que sejam
priorizados candidatos cuja conexão seja estabelecida diretamente, por
exemplo, candidatos de tipo host são preferidos em relação a serverreflexive
e estes em relação a candidatos relayed. As prioridades também permitem
selecionar uma família de IP sobre a outra, e.g. IPv6 sobre IPv4, mas
permitindo um fallback.
O par que inicia a conexão deve enviar para o outro par os candidatos
38
obtidos, junto com outros dados, formando uma “oferta”. Assim como no
STUN e TURN, esses dados precisam ser enviados através de um terceiro.
O par que recebe a “oferta”, caso deseje realizar a conexão, deverá
realizar também o processo de obtenção de candidatos e envio ao outro par.
Após um agente receber os candidatos do outro (remotos) e ter enviado
os seus (locais), ele pode iniciar o processo de verificação de conectividade.
Para tanto, ele irá formar pares de candidatos, combinando os candidatos
locais com os remotos compatíveis, i.e. considerando tipo de transporte e
família IP. Os endereços reflexivos locais serão substituídos pelos endereços
que deram origem a eles, e.g. o endereço utilizado para fazer a requisição
STUN.
Esses pares são ordenados, em cada agente, pela maior prioridade e
para cada um deles, o agente irá enviar uma requisição a partir do endereço
local para o remoto. Essa requisição utiliza uma mensagem de binding do
STUN. Quando um agente receber uma requisição ele deve enviar uma
resposta, o que permite identificar que a verificação de conectividade foi bem
sucedida para aquele par.
A indicação de qual par foi selecionado é feita através de um atributo
que é incluído na mensagem STUN (“USECANDIDATE”). Para evitar
conflitos, apenas um dos agentes é responsável por esta seleção. Este é
identificado como “controlador”, e outro como “controlado”. Em cada
requisição enviada, um agente inclui o papel adotado por ele, para permitir
tratar possíveis conflitos.
De acordo com a estratégia adotada, o primeiro par de candidatos cuja
verificação de conectividade seja bem sucedida pode ser utilizado. Ou é
possível esperar um tempo para evitar que um par com menor prioridade
seja selecionado no lugar de outro, com maior prioridade, cuja verificação
sofra um atraso maior.
Os mecanismos utilizados pelo ICE, que permitem a seleção de um
canal a partir de múltiplos endereços, provêem a ele flexibilidade para lidar
com diferentes topologias de rede e se integrar a outros protocolos de
39
travessia de NAT. Entretanto, ele também sofre de limitações presentes nos
protocolos que dão suporte a ele, como a necessidade de utilizar um outro
meio para transmissão de candidatos e de manter servidores STUN e TURN
para, respectivamente, auxiliar no processo de hole punching e permitir a
travessia na presença de NATs simétricos e firewalls.
2.3.1.1.6 WebRTC
WebRTC é uma tecnologia baseada no ICE para permitir a
comunicação peertopeer entre clientes Web. Ela foi criada com o foco em
comunicações multimídia, i.e. imagem e vídeo em tempo real, mas também
pode ser utilizada para trocar outros tipos de dados.
O diferencial no WebRTC é sua capacidade de executar tanto no
navegador quanto em aplicações “nativas”. Isso simplifica a criação e
implementação de aplicações peertopeer. Webtorrent8, por exemplo, é uma
implementação do protocolo torrent para a Web.
Essas aplicações, no entanto, ainda estão expostas às limitações e
restrições do navegador, devido a aspectos de segurança ou tecnológicos.
Elas não podem, por exemplo, utilizar UDP ou abrir portas diretamente,
além de depender, geralmente, de um servidor Web que irá hospedar a
página. O Webtorrent, por exemplo, não provê todas as funcionalidades de
um cliente, devido a restrições do navegador.
Apesar dessas limitações, o uso de tecnologias descentralizadas como
o WebRTC pode reduzir a dependência para servidores centrais e aumentar
a escalabilidade de aplicações web. As CDNs (Content Delivery Networks)
peertopeer, por exemplo, podem utilizar o WebRTC para permitir distribuir
entre um servidor e os seus clientes a responsabilidade de prover recursos
presentes em uma página. Isto é, clientes irão realizar o download de certos
recursos através do servidor e de outros clientes conectados. Isso é
especialmente útil para arquivos grandes.
2.3.1.1.7 Redes Overlay PeertoPeer
Redes overlay são formadas a nível de software, i.e. sobre outras
8 webtorrent.io
40
redes. Seus nós são processos e seus links são os canais de comunicação,
e.g. conexões TCP/IP, através dos quais eles se comunicam (TANENBAUM e
STEEN, 2016). As redes overlay podem ser utilizadas para rotear dados
entre nós, bem como armazenar e localizar recursos de forma distribuída.
Redes overlay peertopeer são aquelas em que cada nó assume
essencialmente o mesmo papel. Nessas redes, cada nó irá se conectar
diretamente a um conjunto de nós “vizinhos”. Para se comunicar com outros
eles irão encaminhar mensagens através destes. Estratégias diferentes são
utilizadas, de acordo com o tipo da rede, para formar e manter esses
vizinhos, de modo a garantir o bom funcionamento da rede e lidar com a
entrada e saída de nós.
De acordo com o modo com que esses vizinhos são formados e
organizados, essas redes podem ser classificadas em estruturadas ou não
estruturadas. As primeiras utilizam de procedimentos determinísticos para
organização dos nós, enquanto as outras se baseiam em algoritmos de
aleatorização para formar a estrutura da rede (TANENBAUM e STEEN,
2016).
Essa estrutura irá influenciar diretamente na capacidade e eficiência
da localização de recursos e roteamento de dados. Em redes não
estruturadas, por exemplo, considerase que os recursos e nós estão
distribuídos de forma aleatória. Para localizar um recurso, então, uma
consulta poderá ter de ser propagada por toda a rede ou parte significativa
dela (flooding), o que pode produzir um overhead significativo (MESHKOVA
et al, 2008). Já redes estruturadas permitem consultas de forma mais
eficiente. Isso exige, entretanto, que os recursos sejam distribuídos entre os
nós de forma “organizada”.
Redes overlay podem permitir a comunicação entre nós que estão
sobre NAT, através do roteamento de dados. Isso depende, no entanto, que
haja uma rota entre eles formada por nós que possam se comunicar
diretamente. Isso faz com que nós que possam ser acessados publicamente,
i.e. estejam fora do NAT ou utilizem outras técnicas de travessia, assumam
papel crucial para infraestrutura da rede. Enquanto a presença de muitos
41
nós sobre NATs restritivos poderão prejudicar a eficiência da rede, além de
terem a própria conectividade reduzida.
Redes overlay podem também ser utilizadas para auxiliar na conexão
direta entre nós sobre NAT. Algumas redes, como a MaidSafe DHT, já
incluem soluções para auxiliar no processo de travessia de NAT (IRVINE,
2010). Além disso, essas redes podem ser utilizadas para auxiliar protocolos
de travessia de NAT, como ICE, STUN e TURN, permitindo transmitir, de
forma descentralizada, os “sinais” utilizados nesses protocolos.
a) DHTs
Tabelas hash distribuídas ou DHTs (do inglês distributed hash tables)
são uma das formas mais comuns de organizar redes overlay estruturadas
(TANENBAUM e STEEN, 2016). Elas recebem esse nome pois apresentam
operações similares às de uma tabela hash, porém realizadas sobre um
sistema distribuído. Isto é, elas utilizam de identificadores numéricos
(chaves) para permitir buscar e inserir valores na rede (operações de get e
put).
Esses identificadores tem geralmente um tamanho fixo que permita
um conjunto grande de valores possíveis, e.g. 15 ou 20 bytes. Uma forma
comum de gerar os identificadores é utilizar funções hash criptográficas
sobre um determinado valor, e.g. os próprios dados armazenados ou
informações relacionadas a eles. Essas funções geram um valor de tamanho
fixo e tem chances pequenas de colisão. Isto é, dois valores diferentes
produzirem o mesmo hash.
Os nós que armazenam os recursos também são identificados na DHT
com o mesmo tipo de identificadores. Isso é utilizado para permitir distribuir
e localizar os recursos. Isto é, um recurso com um determinado identificador
será armazenado pelos nós com identificadores mais próximos a ele. A
função de proximidade e a taxa de replicação poderão variar de acordo com
os algoritmos e implementações utilizados. Quando um novo nó se conecta à
rede, ele assume parte dos recursos próximos ao do seu identificador. Por
42
sua vez, quando ele se desconecta, os recursos armazenados por ele são
repassados a outros nós.
A forma de organizar recursos na DHT também permite localizálos de
forma eficiente. Para buscar um recurso, um nó contacta o seu vizinho que
esteja mais próximo àquele recurso, segundo a função de proximidade
adotada. Então, dependendo do modo com que a DHT realiza as buscas, i.e.
recursivo ou iterativo, o vizinho pode, ele mesmo, repassar a consulta para o
vizinho conhecido por ele que esteja mais próximo ao recurso ou devolver ao
cliente o endereço desse vizinho. Consultas recursivas tendem a ser mais
resistentes a problemas com NAT, pois a comunicação ocorre apenas entre
peers que já tem uma conexão estabelecida. A busca prossegue até que o
recurso seja encontrado, ou seja determinado que ele não está presente. A
organização dos vizinhos é feita de tal forma que essa busca pode ser feita
contactando até log(N) nós (dependendo do algoritmo adotado, esse valor
pode variar), sendo N o número de nós na rede (MESHKOVA et al, 2008).
2.3.1.2 Protocolos para descoberta de serviços descentralizada
Existem diferentes técnicas para localização de serviços ou recursos.
Podemos agrupar as técnicas identificadas de acordo com o alcance ou
escopo em que atuam: técnicas de curto alcance, técnicas de alcance local e
técnicas de alcance global. As primeiras estão associadas a tecnologias de
comunicação específicas, dependem do suporte de protocolos ou tecnologias
a nível de hardware e geralmente não operam sobre IP. As técnicas de
alcance local executam sobre as camadas TCP/IP e por isso podem atuar
sobre diferentes tipos de rede. Porém elas tem um alcance limitado à rede
local ou a uma Intranet. Por fim, as técnicas de alcance global podem operar
através da Internet.
Vale destacar que essas técnicas não são mutuamente excludentes.
Isto é, elas podem ser usadas em conjunto. Pois, embora as primeiras
possam apresentar um alcance reduzido em relação as últimas, elas podem
ser mais eficientes no escopo em que atuam ou depender de uma
43
infraestrutura menor. Isto é, cada conjunto de técnicas pode ajudar a
atender cenários de uso distintos. E mesmo técnicas similares podem
coexistir em um determinado sistema para garantir maior
interoperabilidade, por exemplo.
2.3.1.2.1 Técnicas de curto alcance
Técnicas para descoberta de protocolos de curto alcance dependem de
tecnologias de rede específicas, isto é, não podem atuar entre redes
diferentes. Elas operam com alcance reduzido (de alguns centímetros a
algumas dezenas de metros). Em compensação, elas tendem a apresentar
um consumo menor de recursos, como bateria e processamento.
a) Bluetooth Service Discovery
O Bluetooth é uma tecnologia utilizada para a comunicação entre
dispositivos em redes de curto alcance. O Bluetooth permite a descoberta de
dispositivos e serviços na rede. Para isso, um dispositivo (master) envia
primeiramente uma mensagem para todos os dispositivos na área. Aqueles
que estiverem disponíveis para receber conexões irão responder, permitindo
a descoberta de seus endereços. Outras requisições são enviadas para
permitir identificar os serviços presentes nesses dispositivos e obter os
nomes legíveis por humanos.
Os serviços em redes Bluetooth são descritos a partir de atributos.
Cada atributo possui um identificador, um token de 16 bits, e um valor.
Esses atributos permitem identificar dados do serviço, como nome, tipo e ID.
UUIDs (Universally Unique IDentifiers) de 128 bits são utilizados em alguns
atributos, como tipo e ID de um serviço, para permitir identificálos
unicamente.
As consultas por serviços Bluetooth permitem obter os identificadores
dos serviços que satisfazem aos critérios utilizados, ou os atributos de um
serviço desejado. Essas buscas, no entanto, tem capacidades restritas. Para
44
reduzir o uso de recursos, o Bluetooth não suporta consultas complexas ou
utilizando matching parcial. Buscas podem ser feitas apenas utilizando
atributos com identificadores únicos.
O bluetooth também pode ser utilizado em conjunto com outras
tecnologias para permitir localizar serviços e estabelecer conexões. Em
(SCHREINER et al, 2015), por exemplo, é apresentado o framework
Connichiwa, que utiliza Bluetooth Low Energy para permitir a detectação e
conexão com outros dispositivos. Porém, a comunicação em si ocorre através
de HTTP, sobre TCP/IP.
b) WiFi Direct
WiFi Direct é uma tecnologia desenvolvida para simplificar a conexão
de dispositivos através de WiFi. Ela possibilita a descoberta e conexão entre
dispositivos através de WiFi, sem precisar de um access point(AP) ou
roteador como intermediário.
Para isso, essa tecnologia se baseia na criação de access points de
forma dinâmica, chamados SoftAPs. Isto é, um dispositivo WiFi cliente
passa a atuar também temporariamente como um AP. A rede formada por
ele é chamada de grupo P2P, e o dispositivo que atua como AP é chamado de
“dono do grupo”(GO, do inglês P2P Group Owner). Com essa arquitetura,
mesmo dispositivos que não implementem o WiFi Direct podem também
utilizar da tecnologia. Para eles, não há distinção entre um SoftAP e APs
tradicionais. No entanto, se dois dispositivos que se conectam através do Wi
Fi Direct possuem suporte à tecnologia, eles irão negociar quem irá atuar
como GO. Após a formação de um grupo P2P, geralmente entre dois pares,
outros dispositivos podem se conectar.
Além da descoberta de dispositivos, o WiFi Direct permite também a
descoberta de serviços. Para isso a especificação define um componente, o
ASP (Application Service Platform), que permite a aplicações anunciarem ou
buscarem por serviços (WIFI ALLIANCE, 2014). Cada tipo de serviço é
identificado por um nome de serviço, representado como uma string UTF8.
45
Instâncias diferentes de um mesmo serviço podem ser oferecidas. Cada uma
delas terá um “identificador de anúncio” (advertisement ID) único, e pode ter,
opcionalmente, um conjunto de informações específicas do serviço. A
especificação define ainda um conjunto de serviços “padrão”, que proveem
um funções comuns, são eles: send, play, display e print. Esses serviços são
baseados em outras tecnologias bem estabelecidas, respectivamente: HTTP,
DLNA9, Miracast e IPP10 (TIEU e YE, 2014).
c) NFC
NFC (Near Field Communication) é uma tecnologia para estabelecer
comunicação de curto alcance entre dispositivos, i.e. na faixa de poucos
centímetros(TIEU e YE, 2014). A velocidade de comunicação é também
restrita, chegando a uma velocidade máxima de 424kbits/s. O NFC pode ser
utilizado tanto em dispositivos ativos, i.e. capazes de transmitir e receber
dados, quanto em dispositivos passivos (tags NFC), i.e. que apenas reagem a
comunicações. As tags NFC são uma solução de relativo baixo custo e
podem ser usadas para armazenar pequenas quantidades de dados.
Devido às limitações descritas, o NFC não é adequado a comunicações
extensas. Entretanto, ele provê uma forma conveniente de trocar pequenas
quantidades de informação entre dispositivos, pois permite estabelecer uma
conexão entre dois dispositivos NFC apenas aproximandoos. O NFC é
também considerado uma solução segura, e, embora vulnerabilidades
existam, ele tem sido utilizado inclusive em aplicações bancárias, para
pagamento com smartphone (COSKUN, 2013). A pequena distância de
atuação do NFC também contribui para a segurança, pois dificulta que o
dispositivo de um terceiro possa interceptar ou interferir na comunicação.
O NFC pode ser utilizado também para auxiliar na descoberta de
serviços, como um meio para facilitar a conexão utilizando outras
tecnologias. O Bluetooth e WiFi Direct, por exemplo, podem ser utilizados em
conjunto com NFC para auxiliar a estabelecer conexões de forma segura. O
9 Digital Living Network Alliance10 Internet Printing Protocol
46
NFC também pode ser utilizado para transmitir dados para localizar um
outro serviço, e.g. IP e porta, ou recurso. Em (XU et al, 2013), por exemplo, é
apresentado um sistema para migrar o estado do navegador de um
dispositivo para outro. Ele utiliza NFC para transmitir o IP de dispositivos e,
a partir disso, estabelecer uma conexão entre eles, através de WiFi.
2.3.1.2.2 Técnicas para descoberta de serviços de alcance local
As técnicas utilizadas para descoberta de serviços em redes locais
recorrem frequentemente ao uso de comunicações multicast e broadcast,
pois elas permitem contactar nós da rede sem conhecer seus endereços.
Essas comunicações, no entanto, exigem medidas para evitar picos de
comunicação ou overhead excesso na rede.
Como essas técnicas atuam sobre IP, elas facilitam a integração com
serviços existentes e também não exigem equipamentos especiais.
Entretanto, exigem que os equipamentos estejam em uma mesma rede.
a) UPnP SSDP
O SSDP (Simple Service Discovery Protocol) é um protocolo para
descoberta de serviços que faz parte da pilha de protocolos do UPnP. Ele
utiliza uma versão modificada do HTTP executada sobre UDP, o que permite
o envio de mensagens HTTP multicast e a redução no overhead das
comunicações, em comparação ao TCP.
Consultas por serviços são enviadas através de mensagens
“ssdp:discover”, utilizando HTTP multicast, com “MSEARCH” como método.
Essas consultas podem buscar por todos os serviços e dispositivos na rede
ou utilizar de filtros, tais como: tipo do serviço, tipo do dispositivo ou id do
dispositivo (UPnP FORUM, 2015). Respostas são enviadas via unicast ao
dispositivo que fez a consulta. Além de consultas explícitas, serviços e
dispositivos podem também ser descobertos através de anúncios feitos pelos
dispositivos que provêem os serviços (controlled points). Esses anúncios são
47
também enviados via multicast, através de mensagens “ssdp:alive”,
utilizando “NOTIFY” como método HTTP.
Ao descobrir um serviço através de um anúncio ou de uma resposta a
uma requisição, uma URL é recebida. Essa deve apontar para um
documento XML que descreve o serviço. Este serviço pode então ser utilizado
através dos protocolos SOAP (Simple Object Access Protocol) e GENA
(General Event Notification Architecture). Eles permitem, respectivamente,
enviar mensagens RPC para controlar o serviço e receber eventos do serviço
para identificar mudanças ocorridas.
Uma das limitações do UPnP é o acoplamento entre os protocolos. Para
utilizar o protocolo de descoberta de serviços (SSDP), por exemplo, o serviço
deve ser oferecido através do SOAP. Isso dificulta interoperabilidade com
serviços já existentes. Além disso, a criação de novos serviços depende do
“Fórum UPnP” que controla a especificação e projeto dos protocolos, embora,
em tese, as tecnologias possam ser adaptadas para uso por protocolos “não
oficiais”.
b) DNSSD e mDNS
O DNSSD (DNS Service Discovery), especificado no RFC 6763, é um
protocolo que utiliza mensagens DNS para permitir publicar e descobrir
serviços. Ele pode ser utilizado sobre o DNS tradicional, i.e. centralizado,
mas é mais comumente utilizado em conjunto com o multicast DNS (mDNS).
O mDNS adapta as funções e mensagens do DNS para permitir a resolução e
atribuição de nomes em redes locais, para hosts e serviços, de forma
autônoma e descentralizada. Isto é, ele adota estratégias para permitir a
atribuição de nomes a IPs e resolução de possíveis conflitos, sem necessitar
de configuração ou de entidades centrais para regulação (CHESHIRE;
KROCHMAL, 2013).
Serviços são descritos no DNSSD por um “nome de instância de
serviço” (Service Instance Name), composto pelo protocolo de transporte
utilizado (e.g. udp ou tcp), o tipo do serviço e o nome da instância. Consultas
48
podem ser feitas para localizar serviços combinando essas informações ou
parte delas (utilizando matching parcial). As consultas são enviadas através
de multicast. Nós que satisfaçam a consulta enviarão respostas, i.e. anúncios
de serviço, também em multicast (CHESHIRE; KROCHMAL, 2013), para
permitir o aprendizado por outros nós da rede. Além disso, anúncios de
serviços não solicitados podem também ser enviados na rede para permitir,
por exemplo, notificar a entrada de um novo serviço. A partir de um nome de
serviço, um nó pode fazer a resolução do nome para obter os endereços
associados a esse serviço.
Com o mDNS é utilizado o pseudotopleveldomain (TLD) “.local”, no
nome de domínio. Já com o DNS, é possível utilizar qualquer domínio, como
“example.org” ou “minhaempresa.com”. Assim, o nome “servidor do
departamento._http._tcp.local”, por exemplo, pode ser utilizado para
identificar um servidor Web (tipo “http”), que executa sobre tcp, e tem nome
“servidor do departamento”. Os nomes de serviço no DNSSD podem conter
não apenas espaços, mas qualquer caractere unicode, o que permite a
criação de nomes “amigáveis” (CHESHIRE, 2006).
Os tipos de serviço não são definidos pelo protocolo, mas pelas
aplicações, embora a IANA mantenha um registro deles. O tipo de um
serviço deve ser definido não apenas do que é oferecido, mas da interface
adotada (CHESHIRE, 2006). O tipo ‘ipp’, por exemplo, representa um serviço
de impressão que utiliza o protocolo “Internet Printing Protocol”. Dessa
forma, clientes de uma aplicação podem identificar serviços compatíveis
apenas a partir do seu tipo.
O DNSSD utiliza nomes “legíveis por humanos” para identificar
instâncias de serviços. A intenção é que o nome e a identidade de um serviço
sejam a mesma coisa (CHESHIRE, 2006). Entretanto, como esses nomes são
definidos arbitrariamente pelos usuários, podem haver conflitos. O mDNS
utiliza estratégias para lidar com esses conflitos. Para verificar se o nome já
não foi atribuído a outro nó da rede, ele envia mensagens multicast
consultando por aquele nome. Caso não haja resposta, ele passa a anunciar
que o nome está sendo atribuído a si mesmo. Se um conflito for detectado,
49
um novo nome pode ser solicitado ao usuário ou ele pode ser modificado
automaticamente até que não haja mais conflito.
Dessa forma, entretanto, não há garantia de que um nome seja
atribuído de forma persistente a um serviço. Caso as aplicações não
ofereçam um outro nível de verificação, elas podem estar expostas a
problemas de segurança. Um serviço malicioso pode se fazer passar por
outro para roubar dados ou interceptar tráfego na rede, por exemplo. Isso
decorre de uma decisão de design do mDNS, que assume um ambiente de
participantes cooperativos (CHESHIRE; KROCHMAL, 2013). Embora essa
suposição possa ser aceitável, considerando o contexto para o qual o
protocolo foi projetado, e.g. ambientes domésticos e de escritório, ameaças
podem surgir se, por exemplo, uma máquina for infectada por um vírus.
Soluções sugeridas são o uso de IPsec ou DNSSEC (CHESHIRE;
KROCHMAL, 2013). Aplicações, entretanto, deveriam também prover
soluções para dificultar ataques nesses contextos.
Apesar das questões de segurança, o mDNS e o DNSSD são
protocolos flexíveis e eficazes. Eles podem ser adaptados a outros protocolos
existentes e incluem um conjunto de medidas para reduzir o impacto na
rede, como o uso de cache e supressão de respostas conhecidas (CHESHIRE,
2006).
c) Outros protocolos
Outros protocolos podem ser identificados para descoberta de serviços,
de forma descentralizada, em redes locais. Estes, porém não são tão
populares quanto os apresentados anteriormente ou tem um propósito
distinto.
O SLP(Service Location Protocol) foi um dos primeiros protocolos bem
conhecidos para descoberta de serviços, mas não teve uma adoção tão
grande quanto outros (MESHKOVA et al, 2008). O protocolo utiliza de URLs
para identificar serviços, seguindo o formato:
service:servicename:protocolname://hostname. Serviços podem também
conter um tipo e atributos.
50
Consultas SLP podem ser feitas utilizando o tipo e/ou atributos do
serviço. Respostas incluem a URL que descreve o serviço. As mensagens do
SLP são enviadas através de multicast. No entanto, o protocolo pode operar
também de forma centralizada, se um directory agent(DA) do protocolo for
detectado na rede. Nesse caso os outros nós passam a fazer consultas por
serviços através do DA, utilizando unicast.
O DIAL11 (Discovery and Launch) é um protocolo que permite descobrir
e iniciar aplicações em outros dispositivos na rede local. Ele foi projetado
para permitir a criação de aplicações de segunda tela. Isto é aplicações que
são executadas em dispositivos como smarphones e tablets e permitem
interagir com televisores e settop boxes. O DIAL não é uma solução genérica
para descoberta de serviços, mas provê uma forma simples, do ponto de
vista dos usuários, de integrar serviços entre dispositivos. O DIAL utiliza o
SSDP para localização de serviços e REST para permitir interagir com o
outro dispositivo e inicializar aplicações (NETFLIX, 2017).
CoAP (Constrained Application Protocol) também não é um protocolo
específico para descoberta de serviços, mas ele possibilita localizar e
interagir com serviços em uma rede local. Além disso, ele pode ser utilizado
por dispositivos com recursos limitados, incluindo, por exemplo,
microcontroladores. O CoAP provê conceitos e recursos baseados no HTTP.
Porém ele utiliza cabeçalhos binários, invés de textuais, e envia mensagens
através de UDP (SHELBY et al, 2017). Ele também reduz o conjunto de
cabeçalhos utilizados em relação ao HTTP e a quantidade mínima de
informações para uma requisição ou resposta. O CoAP inclui um mecanismo
simples que permite a descoberta de serviços através de multicast. Para isso,
aplicações podem enviar requisições para um endereço de multicast,
previamente definido, e esperar por respostas dos servidores localizados na
rede. O protocolo define ainda um mecanismo para descobrir recursos em
um servidor CoAP e uma extensão do protocolo para lidar com a interação
com grupos de dispositivos (RFC 7390).
11www.dial-multiscreen.org
51
2.3.1.2.3 Técnicas para descoberta de serviços de alcance global
Uma das principais ferramentas para realizar a descoberta de serviços,
de forma descentralizada, através da Internet são as redes overlay peerto
peer (ver seção 2.3.1.1.7). Elas proveem a estrutura necessária para
registrar recursos ou serviços e meios para localizálos. De acordo com o tipo
da rede, entretanto, as técnicas utilizadas para isso irão variar. Além disso,
como muitas dessas redes são específicas de uma determinada aplicação,
elas não precisam prover soluções genéricas para descoberta de serviços.
Isso permite reduzir informações necessárias e assumir certas informações
sobre os nós da rede, tornando a comunicação mais simples. Entretanto,
isso faz com que as redes de diferentes aplicações sejam incompatíveis, e
acaba por criar esforços duplicados para desenvolver e manter essas redes.
a) DHT
DHTs (introduzidas na seção 2.3.1.1.7 a) são utilizadas,
principalmente, para registrar e obter recursos de forma descentralizada. O
mesmo processo, entretanto, pode ser utilizado para anunciar e localizar
serviços. Para isso podem ser utilizadas as operações de put e get,
respectivamente. Ambas se baseiam na capacidade de localizar o nó
responsável por uma determinada chave, mas a primeira insere um valor,
enquanto a segunda obtém o(s) valor(es) associado(s) atualmente àquela
chave. O processo de busca é descrito em linhas gerais na seção 2.3.1.1.7 a.
Os algoritmos relacionados a DHT não impõem restrições quanto aos dados
que podem ser armazenados nela, embora possam restringir as chaves.
Entretanto, implementações da DHT, podem impor maiores restrições, de
modo a adequar ou otimizar seu uso para uma determinada aplicação.
O BitTorrent é um exemplo de uso da DHT para a localização de
serviços. Ele utiliza uma implementação de DHT (Mainline DHT) com
propósito específico. Isto é, operações dela são adaptadas para uso apenas
com o protocolo torrent. Por isso, apenas instâncias do “serviço de torrent”,
i.e. peers torrent, podem ser localizadas ou anunciadas através dessa DHT.
52
As principais operações definidas na DHT do Torrent são ‘get_peers’ e
‘announce_peer’. Elas permitem, respectivamente, localizar os pares que
podem conter um arquivo desejado, e anunciar que um peer está fazendo
download ou compartilhando um determinado arquivo. Além dessas
operações, a DHT permite também: verificar a conectividade com um outro
nó da DHT (ping) e obter uma lista de nós para conexão na DHT(find_node)
(XINXING et al, 2016).
A DHT utiliza o info_hash de um arquivo torrent como chave para
localizar ou registrar os pares que estão compartilhando esse arquivo. O
info_hash é o hash SHA1 gerado a partir dos metadados de um arquivo
torrent (COHEN, 2008). Ele pode ser obtido a partir de um arquivo “.torrent”
ou de um “magnet link”.
Ring, uma aplicação descentralizada para troca de mensagens
instantâneas, é um outro exemplo de uso da DHT para auxiliar na
descoberta de nós e no estabelecimento de conexões. As soluções
empregadas, entretanto, diferem das utilizadas no Bittorrent. Ring utiliza
uma DHT de propósito geral, a OpenDHT12. Ela permite aos clientes
registrarem listeners para monitorar endereços na DHT. Dessa forma, a DHT
pode ser utilizada para enviar mensagens e, com isso, permitir iniciar
conexões. Além disso, a OpenDHT permite registrar valores arbitrários (não
apenas IPs), o que é utilizado pela aplicação para, por exemplo, publicar a
chave pública dos clientes.
Diversas outras aplicações descentralizadas utilizam de DHTs para
auxiliar na comunicação e descoberta de dispositivos ou recursos, tais como
Tox13, Twister14 e YaCy15.
2.3.2 Identidade Descentralizada
As técnicas para prover identidades descentralizadas buscam
construir identificadores que sejam únicos e possam ser verificados de
12 github.com/savoirfairelinux/opendht13 tox.chat/faq.html#techfaq14 twister.net.co/?page_id=2515 yacy.net/en/Technology.html
53
forma segura, e que não dependam de uma entidade ou organização central
para a geração ou verificação delas. Além disso essas técnicas buscam
construir meios para associar a esses identificadores, nomes significativos
para humanos e que possam ser lembrados por eles. A base principal para
essas técnicas são algoritmos de criptografia (seção 2.3.2.1). Eles proveem os
aspectos de segurança e unicidade dessas identidades. Sobre eles outras
soluções são criadas para permitir associar nomes significativos a humanos,
como as apresentadas nas seções 2.3.2.2 e 2.3.2.3. Além disso, são
apresentadas algumas técnicas complementares na seção 2.3.2.4.
2.3.2.1 Criptografia para gerenciar identidades descentralizadas
A criptografia pública ou assimétrica é o principal fundamento para a
criação de identidades descentralizadas. Ela permite que usuários gerem
identidades de forma independente, com chances mínimas de conflito, e
provê meios para que essas identidades possam ser comprovadas, sem
precisar de uma “terceira parte confiável”.
A base da criptografia assimétrica está na capacidade de utilizar pares
de chaves, uma chave pública e uma privada, que permitem a dois pares
trocarem dados encriptados sem precisar concordar em uma chave secreta
previamente. Além de algoritmos de encriptação, duas outras classes de
algoritmos estão relacionadas a esse tipo de criptografia: algoritmos de
assinatura e algoritmos de troca de chaves (HOUTVEN, 2017).
Algoritmos de assinatura permitem utilizar uma chave privada para
autenticar uma determinada mensagem. Isto é, um valor (a assinatura) é
gerado a partir de uma entrada, de modo que é possível verificar, através da
chave pública relacionada e da entrada utilizada, que a assinatura foi gerada
a partir daquela chave. Simultaneamente, a assinatura permite verificar a
integridade dos dados assinados.
Os algoritmos de troca de chaves permitem a dois pares
compartilharem uma chave secreta, de forma confidencial, através de um
meio inseguro. Eles devem ser utilizados em conjunto com técnicas de
54
autenticação para garantir que a troca de chaves foi efetuada com o par
desejado. Caso contrário, ataques de interceptação (maninthemiddle)
poderão ser efetuados. Isto é, um atacante pode interferir na comunicação
de dois pares durante a troca de chaves, de modo a permitir monitorar e até
alterar os dados enviados.
Além desses algoritmos, o uso de criptografia pública requer
algoritmos para geração do par de chaves utilizado. Esses algoritmos
permitem gerar uma chave privada e, a partir dela, uma chave pública
matematicamente relacionada. O oposto, entretanto, não deve ser possível.
Isto é, a partir de uma chave pública não deve ser viável gerar a chave
privada correspondente. A geração dessas chaves também deve ser
resistente a colisões, acidentais ou intencionais. Isto é, as chances para
duas chaves idênticas serem geradas devem ser mínimas. Além disso, uma
mesma chave pública não deve poder ser gerada a partir de chaves privadas
diferentes.
Um outro elemento importante utilizado em conjunto com os
algoritmos descritos, e como base de alguns deles, são as funções hash
criptográficas. Elas permitem gerar, a partir de uma entrada arbitrária, um
valor binário (hash ou digest) com um tamanho fixo de acordo com o
algoritmo. Esse valor é gerado de tal forma que para uma mesma entrada
sempre será produzida a mesma saída. Porém, qualquer mudança na
entrada tende a gerar várias mudanças na saída. Além disso, os algoritmos
utilizados tornam muito difícil que a entrada possa ser obtida a partir do seu
hash, ou que seja gerada uma entrada tal que possua o mesmo valor de
hash de uma outra. Essas propriedades fazem com que as funções hash
criptográficas sejam utilizadas, dentre outras coisas, para: prover um
identificador único e compacto para arquivos e outros tipos de dados; e
verificar a integridade de dados.
O Bitcoin16, uma moeda digital descentralizada, é um exemplo do uso
de técnicas de criptografia para gerenciar identidades. No Bitcoin a
identidade de um usuário é dada em função de sua “carteira digital”. Cada
carteira está associada a pelo menos um par de chaves criptográficas. A16 bitcoin.org
55
partir de uma chave pública é gerado um identificador, utilizando funções de
hash, que serve de endereço para as transações monetárias. Além disso, a
chave privada de uma carteira é utilizada para assinar as transações, que
podem ser verificadas através das respectivas chaves públicas.
2.3.2.2 Blockchain e Identidade
A blockchain é uma tecnologia desenvolvida para o Bitcoin que atua
como um registro público, global e descentralizado de transações. Através de
um processo chamado de mining (mineração), as transações são agrupadas
em blocos e publicadas através de uma rede peertopeer. Cada bloco
referencia o anterior, formando uma cadeia ou corrente de blocos (em inglês,
blockchain).
A blockchain provê um mecanismo que permite com que todos os nós
da rede utilizem uma base de dados consistente, sem que uma entidade
central precise regular as operações. Para isso, todos os nós da rede
verificam a validade dos blocos publicados e descartam blocos inválidos
(ANTONOPOULOS, 2015). Dessa forma, possíveis erros ou falsificações
apenas não seriam propagados. Em alguns casos, entretanto, podem ocorrer
divergências (forks), i.e. mais de um bloco ou cadeia válidos, com um
antecessor comum. Eventualmente, entretanto, a blockchain converge, pois
os nós da rede passam a adotar um único caminho, aquele com maior
“computação acumulada”, i.e. com maior número de blocos
(ANTONOPOULOS, 2015). Isso poderá ser decidido pela velocidade com que
novos blocos forem adicionados a um fork ou outro.
O mecanismo da blockchain embora tenha sido desenvolvido para
armazenar transações financeiras, pode ser adaptado a outros aplicações.
Uma delas é o registro de nomes. Namecoin é um fork do Bitcoin que foi
desenvolvido para isso, i.e. permitir registrar nomes em uma blockchain.
Assim, ele segue o mesmo princípio de funcionamento do bitcoin, porém ele
permite registrar na blockchain nomes arbitrários e, associados a eles,
valores de até 520 bytes (NAMECOIN). Isso permite vincular a um nome
56
dados de uma identidade, como uma chave pública, ou mesmo um endereço
de email.
Para permitir gerenciar os nomes, e.g. registrálos ou atualizálos, o
Namecoin utiliza também chaves criptográficas e uma moeda própria,
análogas às do Bitcoin. A chave permite verificar a autoria do nome. A
moeda permite “comprar nomes”, mas também pode ser utilizada para
trocar por outras mercadorias, i.e. como uma moeda digital. A cada novo
registro de nome é cobrada uma taxa fixa de 0.01 NMC (namecoins), o que
equivale, no momento da escrita, a poucos centavos de Real. Esse valor é
uma forma de limitar o “name squashing”, isto é, a aquisição de múltiplos
nomes ou nomes desejados para permitir revender no futuro. A taxa de
registro é destruída após o registro. Isto é, ela não é transferida para mais
ninguém. Além dessa taxa, é pago um valor pela transação, assim como no
Bitcoin, como uma recompensa aos mineradores, que verificam as
transações da rede. Essa taxa é variável, i.e. definida pelos usuários, mas
influencia o quão rápido a transação será inclusa na blockchain. Para
atualizar ou renovar um nome é cobrada apenas a taxa da transação
(NAMECOIN).
Graças ao uso da blockchain, o Namecoin permite solucionar o
triângulo de Zooko. Isto é, através dele é possível registrar nomes
significativos para humanos, de forma segura e descentralizada. O Namecoin
provê ainda uma alternativa ao DNS e às entidades certificadoras. Ele inclui
um TLD alternativo, o “.bit”, que pode ser utilizado para resolver nomes
registrados na blockchain do Namecoin (utilizando um namespace específico
para isso) em endereços, contanto que o cliente esteja configurado e possua
os softwares adequados.
O Namecoin apresenta, entretanto, algumas limitações. Uma delas é o
tempo de atualização da blockchain. Devido a questões de segurança, cada
bloco na blockchain precisa ser validado através de um algoritmo de “prova
de trabalho” (Proof of Work), que é intencionalmente lento e custoso (sua
verificação, entretanto é rápida). Isso faz com que atualizações possam
demorar a ser consideradas válidas. Além disso, o próprio custo em registrar
57
e manter os nomes, embora seja pequeno, pode servir de barreira para
usuários. Esse custo, por sua vez, não soluciona por completo o problema de
name squashing, já que mesmo com um custo maior, o custo de revenda
será ainda maior (NAMECOIN).
2.3.2.3 Petnames
Um petname é um nome que é utilizado para se referir a uma
determinada entidade, mas que é único e significativo apenas de forma local,
i.e. para aquele que o definiu. Sistemas de nome seguros podem ser
construídos utilizando petnames, ao associálos a identificadores que são
únicos (globalmente) e que não podem ser forjados ou falsificados, e.g.
chaves criptográficas. Petnames funcionam de forma similar aos contatos de
uma agenda telefônica. Mas, invés de facilitar o uso de números telefônicos,
eles simplificam o uso de chaves criptográficas. Petnames devem ter, no
contexto em que são utilizados, uma associação bidirecional um para um
com uma chave (STIEGLER, 2005), de modo que o nome possa ser
substituído pela chave e viceversa. Isso evita possíveis ambiguidades para
os usuários, e para o sistema.
Petnames provêem uma solução alternativa para o triângulo de Zooko.
Isto é, eles combinam as características de chaves criptográficas, i.e. são
globais e seguros, com o uso de nomes que são fáceis de lembrar
significativos para humanos, mas com escopo local.
Uma das limitações dos petnames, é a necessidade dos usuários
definirem nomes para cada “entidade”, com qual eles interagem. Uma forma
de lidar com isso é através do uso de “nomes propostos” (alleged names).
Isto é, cada entidade pode definir uma sugestão de nome para associar a sua
identidade. Outros usuários podem adotar ou não o nome sugerido como
um petname.
Um outro mecanismo que pode contribuir para solucionar essa
limitação é a possibilidade de importar nomes a partir de contatos
conhecidos. Para lidar com os possíveis conflitos gerados, o Gnu Name
58
System(GNS) adota o conceito de delegação de nomes. Isto é, os petnames de
um “contato” podem ser referenciados utilizado o petname desse contanto
como um namespace. Por exemplo, se Bob for um contato registrado e ele
tiver Alice como contato, ela pode ser referenciada por “alice.bob.gnu”. Os
nomes definidos no GNS são compatíveis com o DNS. Eles utilizam o
pseudotld “.gnu” como base. O GNS utiliza uma DHT para registrar nomes
públicos e permitir a resolução “transitiva”. Validade dos nomes é verificada
através de assinaturas criptográficas (WACHS et al, 2014).
O uso de petnames pode ainda apresentar limitações, como a
necessidade de gerenciar os contatos adicionados, e a dificuldade de se
referenciar a uma entidade em um contexto global, e.g. na Web, já que o
nomes são relativos a cada usuário. Entretanto, essa solução não impõe
nenhum custo para registrar ou manter nomes, como no Namecoin ou DNS,
e permite potencialmente aos usuários utilizarem identificadores mais
significativos para eles. Além disso, ela não está exposta ao problema de
name squashing, nem pode sofrer censura por um governo ou organização.
O Namecoin, especificamente, pode estar vulnerável ao controle de uma
organização ou governo caso ele obtenha mais de 50% do poder
computacional dos mineradores. Mas isso é considerado improvável, devido
ao poder computacional exigido. Além disso, interferências poderiam vir a
ser percebidas através da análise da blockchain.
2.3.2.4 Técnicas auxiliares para representar e transmitir identidades
Além das soluções descritas, outras técnicas podem ser utilizadas em
conjunto para simplificar a representação, transmissão e verificação de
chaves criptográficas (especialmente) por usuários. Elas podem ajudar aos
usuários transmitirem chaves de um sistema ou dispositivo para outro e
verificarem a validade dessas chaves e se elas correspondem ao esperado,
para evitar, por exemplo, erros ou ataques de phishing.
O Base58check é um formato utilizado pelo Bitcoin para representar
valores binários. Ele provê uma representação que é menos ambígua para
59
usuários e cuja validade pode ser verificada por software, além de incluir
metadados de forma compacta. Esse formato é similar ao base64, i.e. utiliza
caracteres ASCII para representar valores binários. Entretanto, ele elimina
caracteres que possam ser confundidos, como zero e a letra 'O' ou um e letra
'l' minúscula. Dessa forma, usuários podem verificar e copiar os dados
representados, quando necessário, de uma forma mais simples. Para
verificar a validade do conteúdo, um prefixo é incluso com um checksum,
calculado com base em funções hash. Além disso, o formato inclui um byte
de versão que permite identificar o conteúdo representado
(ANTONOPOULOS, 2015).
Outra forma de representar chaves, endereços, ou outros dados
binários, é através do uso de mnemônicos. Eles permitem converter uma
quantidade de bytes em um conjunto de palavras ou frases. 4 little words17,
por exemplo, é uma proposta para representar endereços IPv4 utilizando
quatro palavras da língua inglesa, de modo a facilitar a memorização deles.
Para isso, cada valor possível de um byte, i.e. 256 valores, é mapeado a uma
palavra diferente. Dessa forma, um endereço como “210.55.180.158”, por
exemplo, poderia ser representado como “ROOM RED LULU IDEA”. Uma
proposta similar foi feita para utilizar com endereços '.onion' do Tor18. Como
esses endereços tem um comprimento maior (80 bits), a proposta sugere, o
uso de frases. Para isso, seriam utilizados “templates” com uma estrutura
fixa de tipos de palavras, e.g. “<substantivo> e <substantivo> <verbo>
<adjetivo> <objeto>”, o que permitiria gerar sentenças mais legíveis.
Uma possibilidade para auxiliar usuários a reconhecerem chaves
criptográficos ou outros identificadores binários é o uso de técnicas para
visualização de hashs (PERRIG e SONG, 1999), como os Identicons19. Essas
técnicas permitem criar representações gráficas de um valor binário. Elas
podem ser utilizadas para verificar chaves criptográficas e com isso ajudar a
prevenir ataques como maninthemiddle e phising.
Outras técnicas podem ser usadas para facilitar a transmissão de
chaves criptográficas ou outros identificadores, e.g. QR Code ou tags NFC.17 blog.rabidgremlin.com/2010/11/28/4-little-words18 gitweb.torproject.org/torspec.git/tree/proposals/194-mnemonic-urls.txt19 en.wikipedia.org/wiki/Identicon
60
3 Âmbar: Serviço Multiplataforma De
FotoMemórias
Neste capítulo a plataforma Âmbar é apresentada (seção 3.3), assim
como o conceito de fotomemórias relacionado a ela (seção 3.1) e os desafios
relacionados à construção de sistemas que dêem suporte a fotomemórias
(seção 3.2).
3.1 Fotomemórias
Fotografias são utilizadas em diferentes aspectos das atividades
humanas e com diferentes propósitos de uso, tais como, jornalístico,
artístico e publicitário. Segundo Van Dijck (2008), as fotos pessoais,
especificamente, apresentam três principais usos: como meio para
comunicarse e compartilhar experiências, como forma de representar e
construir a própria identidade, e como um instrumento para capturar
memórias.
A importância das fotografias como registros de memórias está no
valor dado a essas memórias. Pessoas utilizam fotos para registrar eventos
que elas consideram importantes, como viagens, aniversários e formaturas.
Assim como outros momentos do cotidiano que para elas são significativos,
como um momento em família ou entre amigos. Elas também se preocupam
em preservar esses registros, embora as práticas adotadas para isso se
diferenciem (WOLTERS, 2015).
Outras fotografias, entretanto, tem um uso mais efêmero. Elas não são
capturadas com a intenção de registrar memórias, mas são utilizadas, por
exemplo, para comunicar a outros uma experiência vivida, retratar (para si
ou para outros) uma representação de sua identidade ou, até mesmo, como
uma forma de anotação (capturar um quadro de aula ou uma anotação em
papel, por exemplo). Terminado o seu propósito de uso, essas fotografias
podem ser descartadas ou, mais frequentemente, “esquecidas”.
61
O papel das fotografias, entretanto, não é imutável. A forma com que
as pessoas percebem uma fotografia, e o valor que dão a ela, podem ser
modificados ao longo do tempo. Acontecimentos como a ausência de um ente
querido ou o passar dos anos podem fazer, por exemplo, com que uma
fotografia que registra um fato antes corriqueiro, se torne um registro
precioso de um momento ou de uma pessoa. Por outro lado, fotos
capturadas com a intenção de registrar uma memória podem também deixar
de ser relevantes com o passar do tempo.
Essas diferentes formas de utilizar fotografias levantam demandas
específicas para as ferramentas que lhes dão suporte, e podem até exigir o
uso de diferentes ferramentas.
A aplicação de fotos para comunicar experiências, por exemplo,
envolve principalmente atividades centradas no compartilhamento. Essas
atividades podem ser atendidas por ferramentas com foco na comunicação,
como chats ou redes sociais. Já no uso de fotos como registros de memória,
há a necessidade de manter essas imagens, como arquivos, por longos
períodos de tempo, bem como prover meios para acessar e organizar essas
fotografias.
Tendo em vista as diferentes necessidades associadas a esses usos da
fotografia, utilizamos neste trabalho, o termo “fotomemórias” para nos
referirmos às fotografias quando utilizadas como meio para registrar
memórias.
Para manter esses registros, no entanto, nem sempre apenas a
fotografia é suficiente. Informações associadas ao contexto ou à vivência das
pessoas relacionadas à foto não podem ser resgatadas diretamente da
imagem. Assim, dados complementares podem ser necessários, seja para
relembrar ou para comunicar as memórias associadas a uma foto.
Em práticas sociais colocadas20 esses dados podem ser passados pela
comunicação oral (LINDLEY, 2009). No uso de fotos impressas, alguns
desses dados podem ser registrados de forma escrita no verso da foto, ao seu
redor, quando inseridas em um álbum ou outro meio, e até mesmo sobre a
20 Tradução livre do inglês “collocated”
62
própria foto. Em meios digitais é possível registrar informações adicionais
através de metadados no próprio arquivo de imagem, ou de dados
relacionados, tais como, textos, links e voz.
3.2 Desafios computacionais
São muitos os desafios relacionados à construção de soluções
computacionais para o uso de fotomemórias. Destacamos a seguir alguns
deles: (i) manutenção de fotomemórias a longo prazo, (ii) representação de
fotomemórias, (iii) uso de fotomemórias através de múltiplos dispositivos,
(iv) uso colaborativo de fotomemórias, e (v) controle/propriedade sobre
fotomemórias.
3.2.1 Desafio #1: Manutenção de fotomemórias a longo prazo
Fotos impressas podem ser preservadas por décadas e, até mesmo,
entre gerações. Da mesma forma, fotos digitais devem poder ser preservadas
por longos períodos de tempo (por exemplo, algumas dezenas de anos). Além
do uso de meios de armazenamento que auxiliem nisso, sistemas de
software precisam também contribuir para manter essas fotos “utilizáveis”
ao longo do tempo.
Para a manutenção de fotomemórias a longo prazo podemos
identificar duas principais questões: (a) localização e organização de foto
memórias, e (b) armazenamento de fotomemórias através de múltiplos
dispositivos e serviços.
a) Localização e organização de fotomemórias
Para utilizar uma foto é necessário primeiro localizála. Portanto,
sistemas que dêem suporte a fotomemórias precisam prover ferramentas
que facilitem a localização de fotos relacionadas às memórias de seus
usuários.
A localização dessas fotos pode ser feita através de mecanismos de
63
busca e/ou navegação sobre coleções de fotos. A eficiência da navegação
será influenciada por aspectos como a organização das fotografias e o modo
com que são dispostas para serem acessadas pelos usuários. Já a busca
pode ser afetada, dentre outras coisas, pelas informações que estão
associadas a uma foto e a capacidade de relacionálas com as informações
de busca, oferecidas pelos usuários.
Dessa forma, sistemas para fotomemórias precisam também prover
recursos para organizar fotografias e permitir associar ou extrair dados que
possibilitem sua localização.
Esses sistemas podem também permitir aos usuários “descobrirem”
fotos relevantes ou relacionadas mesmo sem uma busca explícita (conceito
conhecido como serendipity (RAHMAN 2015). Desse modo, os usuários
podem encontrar fotos que não lembrem ou, até mesmo, que não conheçam,
mas que sejam de seu interesse.
Localizar e organizar dados é um problema maior da computação.
Mas, no contexto de fotomemórias ele é agravado pelo crescente tamanho
das coleções de fotos pessoais, a dificuldade que usuários têm para
organizálas (WHITTAKER; BERGMAN; CLOUGH, 2009), e as dificuldades
para extrair dados das imagens e prover meios para organização e busca
automatizadas.
b) Armazenamento de fotomemórias através de múltiplos dispositivos
Fotografias estão frequentemente dispersas através de múltiplos
dispositivos ou serviços. E, dentro deles, em diferentes pastas ou coleções de
dados. Essa dispersão torna difícil a localização, uso e preservação dessas
fotos.
Bases de dados distribuídas permitem que diferentes dispositivos e
usuários compartilhem uma mesma base de dados. Entretanto, quando
essas bases não permitem a interoperabilidade de dados entre diferentes
serviços e aplicações, o uso desses dados fica restrito ao que é oferecido pelo
serviço e aplicações relacionadas a ele. Isso acaba contribuindo também
para a dispersão de dados, porém a nível de serviços. Esse cenário é comum
64
em serviços comerciais, o chamado problema dos jardins murados
(CABELLO; FRANCO; HACHÉ, 2013).
Outro problema relacionado a dispersão de dados está no uso de
dispositivos de armazenamento que não possuem recursos de
processamento, tais como, pen drives ou discos rígidos externos. Esses
dispositivos podem ser usados para armazenar fotografias, e os sistemas de
fotomemória deveriam prover meios de importar e exportar dados para eles,
bem como integrálos com outras bases de dados.
3.2.2 Desafio #2: Representação de fotomemórias
Relacionada ao armazenamento e localização de fotomemórias está a
própria representação delas. Isso se dá em dois principais níveis: na escolha
dos dados utilizados para representar fotomemórias, e na forma com que
essas são apresentadas na interface de usuário dos sistemas.
Como apenas as imagens não são suficientes, frequentemente, para
representar as memórias associadas a uma fotografia, é preciso utilizar
dados complementares que ajudem a prestar estas informações. A
determinação de quais dados são suficientes ou desejados para representar
e comunicar uma fotomemória é um problema que parece ainda estar em
aberto. A escolha desses dados irá delimitar as próprias capacidades do
sistema e de expressão de seus usuários.
Além dos dados utilizados, a forma com que eles são apresentados aos
usuários, irá influenciar na experiência de uso como um todo e, a partir
disso, na capacidade e facilidade de preservar e utilizar fotomemórias.
3.2.3 Desafio #3: Uso de fotos através de múltiplos dispositivos
De acordo com Neustaedter e Fedorovskaya (2009), o uso de
fotografias digitais envolve um conjunto de diferentes dispositivos que se
relacionam, formando um ecossistema digital, tais como, câmeras
fotográficas digitais, computadores pessoais e móveis, e servidores e
65
dispositivos de armazenamento. Através deles, usuários podem realizar
atividades diversas sobre fotos, tais como, captura, armazenamento, edição
e exibição.
Sistemas que manipulam fotomemórias deveriam considerar esses
diferentes dispositivos para dar suporte às atividades realizadas sobre eles.
Isso envolve não apenas criar soluções multiplataforma ou replicar uma
mesma experiência através de diferentes dispositivos, mas identificar as
interaçõeschave para cada dispositivo e prover meios que simplifiquem a
transição entre esses dispositivos para realizar as tarefas desejadas (LEVIN
2014; ROWLAND 2015).
3.2.4 Desafio #4: Uso colaborativo
Fotografias tem frequentemente um aspecto coletivo. Seja em relação
ao conteúdo da foto, que pode retratar ou ser do interesse de um conjunto
de pessoas, ou pelas atividades em grupo realizadas a partir das fotos.
A participação dos indivíduos nessas atividades pode se dar de forma
simultânea ou sequencial. E, no caso das fotos digitais, essa participação
pode ocorrer tanto em espaços distintos, i.e. remotamente, quanto
compartilhados.
Para dar suporte ao uso colaborativo de fotomemórias é preciso,
portanto, prover um acesso distribuído a essas fotos. Além disso, sistemas
deveriam permitir um uso compartilhado, como também a construção
colaborativa de fotomemórias por múltiplos usuários, incluindo os meios
para evitar e/ou lidar com conflitos entre esses usuários.
O uso colaborativo de fotomemórias pode envolver uma única
fotografia com memórias compartilhadas entre os usuários, isto é, uma
única descrição das memórias é construída em conjunto pelos usuários.
Além disso, esse uso colaborativo pode também envolver um conjunto de
fotografias diferentes mas relacionadas a um mesmo conjunto de memórias.
Isto é, elas podem apresentar um mesmo evento, pessoa ou época. É
possível, ainda, que uma mesma foto apresente descrições divergentes, de
66
acordo com as perspectivas de cada usuário.
Para dar suporte a esses diferentes modos de uso colaborativo,
sistemas deveriam permitir descrições alternativas para uma mesma foto,
mas que possam também ser mescladas ou integradas em uma única
descrição. Além disso, sistemas poderiam prover meios para localizar e
agrupar conjuntos de fotos relacionadas a um mesmo conjunto de
memórias. Esses requisitos se relacionam também aos desafios #1 (questão
a) e #2.
3.2.5 Desafio #5: Controle/propriedade sobre fotomemórias
Outro aspecto importante para sistemas que dão suporte ao uso de
fotomemórias, devido ao caráter pessoal desses artefatos, é a necessidade
de controle dos usuários sobre seus dados. Isto é, usuários devem poder
decidir quem terá acesso aos seus dados e quais usos farão com esses
dados. Isso se reflete em requisitos não funcionais como segurança e
privacidade, mas também na capacidade de adaptação, extensão e
repurposing (definir um novo propósito para um artefato existente).
Soluções computacionais com arquiteturas centralizadas tradicionais
tendem a reduzir o controle que os usuários tem sobre seus dados. Quando
os dados e/ou serviços são mantidos por uma organização ou entidade sob a
qual o usuário não tem controle, tornase difícil garantir sua privacidade ou
adaptar as funções do serviço para atender às suas necessidades.
Essas questões também impactam na capacidade de os usuários
manterem suas fotomemórias a longo prazo (Desafio #1), pois se os dados
e/ou o serviço que dão valor a elas, estão sob o controle de um determinado
provedor, a manutenção deles por longos períodos de tempo, depende dos
interesses e capacidades desse provedor. Mudanças de interesses ou
dificuldades enfrentadas por esse provedor, podem levar o serviço a ser
interrompido ou fazer com que este deixe de atender às necessidades de
seus usuários. Isso, por sua vez, pode levar à perda de dados ou exigir a
migração para outras soluções.
67
3.3 Âmbar
Âmbar é uma plataforma de software opensource desenvolvida para
permitir que fotomemórias sejam usadas de forma descentralizada e
colaborativa. A plataforma foi projetada com o intuito de servir de base à
criação de aplicações e, até mesmo, dispositivos para visualizar e gerenciar
fotomemórias. O nome adotado para a plataforma remete ao seu propósito,
ou seja, ajudar as pessoas a conservarem fotografias e as memórias
associadas a elas por longos períodos de tempo, de forma análoga ao âmbar,
encontrado na natureza, que é capaz de preservar fósseis de organismos, ou
partes deles, por até milhões de anos.
A plataforma é composta por dois diferentes tipos de softwares:
servidores e clientes. Os primeiros oferecem o serviço da plataforma,
responsável pelas camadas de dados e de negócios. Esse serviço é
implementado através de uma biblioteca, o núcleo, que permite o reuso
desse serviço em diferentes soluções. Os clientes são aplicações que
consomem este serviço. Eles tratam dos aspectos de interação com o
usuário.
Cada aplicaçãocliente pode se conectar a diferentes instâncias do
serviço. Para o usuário final da plataforma uma instância do serviço é vista,
simplesmente, como um âmbar, ou seja, quando o usuário final for se
conectar via rede a um âmbar o que ele está fazendo, de fato, é se
conectando a uma instância do serviço, que está rodando em algum
dispositivo. Isso permite com que bases de dados independentes possam ser
criadas e usuários possam escolher onde preferem armazenar suas foto
memórias.
3.3.1 Modelo de domínio
Os conceitos presentes na plataforma e refletidos, consequentemente,
no serviço e nas aplicaçõescliente vêm de um entendimento dos elementos e
68
problemas no domínio e de uma solução projetada para eles, formando um
modelo do domínio (Figura 4). Esse modelo termina por determinar as
funcionalidades e recursos da plataforma e aplicações desenvolvidas a partir
dela.
Figura 4: Modelo de domínio da plataforma
Fonte: o autor
Neste modelo, a foto é um conceito central. Cada foto é representada
na plataforma como a associação de uma imagem às descrições dadas pelos
usuários, e os metadados extraídos da imagem automaticamente pela
plataforma. As descrições de uma foto permitem que os usuários registrem
as memórias associadas a ela. Essas descrições são representadas na
plataforma através de um conjunto de “atributos” textuais, com significados
determinados, e uma coleção de marcadores (descrições associadas a
pontos na imagem).
Os atributos escolhidos remetem a anotações encontradas no verso de
fotografias impressas. O “título” identifica e resume o que a foto representa,
o “período” e o “lugar” descrevem respectivamente, quando e onde teriam
ocorrido o evento registrado na foto. E o atributo “descrição” permite
adicionar detalhes sobre o conteúdo ou o contexto da foto. Há ainda um
atributo para descrever os autores da foto.
69
As descrições de uma foto incluem também uma coleção de
marcadores. Cada marcador consiste em uma descrição textual que é
associada a um ponto específico da imagem. Eles simplificam a descrição de
pessoas, animais ou objetos retratados na foto.
A separação da descrição de uma foto nesses diversos atributos, ao
invés de utilizar uma descrição textual única, dá maior flexibilidade a
representação dessas descrições na interface das aplicaçõescliente. Por
exemplo, alguns desses atributos podem ser omitidos ou representados com
características diferentes (como fonte, tamanho e posicionamento).
Os metadados da foto são informações extraídas da própria imagem. O
núcleo extrai um subconjunto de metadados que tem utilidade para o
desenvolvimento das aplicações ou para o uso das fotos em si. Outros,
entretanto, podem estar presentes nas imagens. Os metadados utilizados
podem conter informações sobre a imagem em si ou sobre o contexto em que
ela foi capturada, como dados sobre a câmera, geolocalização e o timestamp
(data e hora) da captura.
Alguns desses dados podem, parcialmente, se sobrepor a informações
presentes nas descrições, como as informações de tempo e lugar.
Entretanto, enquanto os metadados podem ser mais precisos, as descrições
permitem uma visão de mais alto nível e também mais pessoal. Por exemplo,
invés de utilizar coordenadas de GPS ou um endereço para descrever um
local, um usuário pode utilizar o nome com que ele se refere àquele lugar,
como “casa dos meus pais” ou “campus da universidade”.
A plataforma utiliza o conceito de álbuns como uma forma de
organizar conjuntos de fotos relacionadas. Álbuns são identificados, para os
usuários, através de um nome e uma imagem de capa.
Além de agrupar fotos, álbuns podem conter outros álbuns. Isto
permite organizar as fotos utilizando diferentes níveis de detalhamento. Por
sua vez, um mesmo álbum ou foto pode estar contido em diferentes outros
álbuns. Dessa forma, usuários podem aplicar diferentes critérios de
classificação, sem ter de lidar com fotos ou álbuns duplicados.
70
A plataforma provê ainda um outro nível para o agrupamento de fotos,
os contextos. Os contextos permitem separar grupos de fotos e álbuns
compartilhados entre diferentes conjuntos de usuários. Isto é, para cada
contexto pode haver um conjunto diferente de usuários que pode acessálo.
Para tanto, contextos permitem associar níveis de permissão a
usuários. O menor nível, o de leitura, permite a visualização do contexto e de
seu conteúdo. O segundo nível (escrita) adiciona a permissão para alterar o
conteúdo do contexto. Isto é, modificar, remover ou adicionar fotos e álbuns.
O último nível inclui permissões para gerenciar o contexto. Isto inclui
adicionar e remover usuários e modificar as permissões deles.
Além das permissões por usuário, um contexto possui um nível de
visibilidade, que define o nível de permissão padrão, naquele contexto, para
outros usuários da mesma instância do serviço. A visibilidade pode ser
“privada”, que restringe o acesso apenas aos usuários com permissões
definidas, “Visível para outros” ou “Editável por outros”, que permite que
outros usuários visualizem ou editem o contexto, respectivamente.
Para ajudar no uso colaborativo das fotomemórias, a plataforma
registra também um conjunto de “eventos”, que representam alterações
feitas pelos usuários nos elementos de um contexto, tais como adição e
remoção de fotos. Esses registros são importantes para permitir a usuários
identificarem as mudanças realizadas por outros usuários em um contexto
compartilhado.
Cada usuário é representado na plataforma em função de sua
identidade. Do ponto de vista do sistema, esta corresponde, essencialmente,
aos seus dados de autenticação. Mas, para que os usuários possam
reconhecer uns aos outros, os dados de usuário incluem também um nome
e foto de perfil.
3.3.2 Núcleo
O núcleo é o componente de software responsável por oferecer o
serviço da plataforma. Ele provê uma API RESTful como interface do serviço
71
para as aplicaçõescliente. O núcleo está organizado em uma arquitetura em
camadas (Figura 5) e foi implementado como uma biblioteca em C++. Além
de facilitar eventuais expansões, essa estrutura também potencializa o reuso
do serviço, já que uma instância do serviço é facilmente criada através do
uso dessa biblioteca.
Figura 5: Arquitetura do núcleo
Fonte: o autorA camada de domínio reúne as entidades que representam o modelo
de domínio da plataforma. Essas entidades são utilizadas por todas as
outras camadas do núcleo. A camada de persistência é responsável pelo
armazenamento de dados. Para tanto, esta camada é dividida em dois
módulos. O primeiro realiza a interação com o banco de dados (BD) e expõe
uma interface de mais alto nível. Já o segundo é composto por um conjunto
de DAOs (Data Access Objects), que interagem com o primeiro módulo para
realizar a persistência das entidades do domínio.
A camada de serviços é responsável por realizar as operações que são
oferecidas pelo serviço da plataforma e garantir que as regras de negócio
sejam cumpridas. Essa camada provê ainda componentes responsáveis pela
manipulação de imagens e configurações do serviço. A camada da API provê
uma interface RESTful para os clientes do serviço. Esta camada é composta
por controladores, que proveem as diferentes operações expostas pela API.
72
Estes controladores utilizam de um conjunto de componentes de serialização
que realizam a conversão entre as classes que representam as entidades do
domínio e um formato que pode ser exposto ou recebido pela API. Essa
camada abrange também componentes responsáveis por tratar elementos do
protocolo HTTP e aspectos da comunicação em rede.
Além dos componentes presentes no núcleo, aplicações precisam
prover outros elementos para permitir o uso do serviço: uma interface que
permita aos usuários controlar o serviço (pelo menos iniciálo e finalizálo); e
componentes para realizar a configuração do serviço de acordo com as
características da plataforma de uso e da aplicação.
Para implementar as camadas do núcleo foram escolhidas tecnologias
e bibliotecas que fossem portáveis e tivessem um uso reduzido de recursos
computacionais, de modo a permitir o uso da solução em um conjunto
amplo de dispositivos e plataformas. Assim, por exemplo, o SQLite21 foi
utilizado pois é uma solução leve para persistência de dados. Além disso, ele
provê uma engine SQL que executa no mesmo processo da aplicação,
através de uma biblioteca. Isso evita a dependência a outros processos ou
serviços, o que contribui para tornar o núcleo do Âmbar autocontido. A
biblioteca Civetweb22 também contribui para isso. Ela provê um servidor
HTTP(S) que pode ser embarcado junto com a aplicação, em um mesmo
processo.
Assim, o núcleo pode ser adaptado a diferentes dispositivos, sistemas
operacionais e linguagens de programação. As tecnologias, bibliotecas e a
linguagem adotadas permitem que o serviço seja utilizado mesmo em
dispositivos com recursos de hardware limitados, tais como, dispositivos
móveis (e.g. tablets e smartphones) ou single board computers (e.g.
Raspyberry Pi23 e, possivelmente, até algumas versões de Arduino que
executam Linux, como o Arduino Yún24) e através dos principais sistemas
operacionais da atualidade. É possível, ainda, portar o núcleo para
diferentes linguagens de programação, utilizando bindings. Através do
21sqlite.org.22github.com/civetweb/civetweb.23raspberrypi.org.24arduino.cc/en/Guide/ArduinoYunLin.
73
projeto swig25, por exemplo, é possível construir bindings de C++ para mais
de 20 linguagens.
O desenvolvimento do núcleo como uma biblioteca permite ainda
embarcar o serviço junto a uma aplicaçãocliente em um mesmo software.
Além de poder simplificar a implantação dessas aplicações, isto possibilita a
criação de soluções “auto contidas”, isto é, que não dependam de serviços
externos e, portanto, possam ser utilizadas mesmo sem conectividade. O
acesso direto ao núcleo pode também simplificar a administração pelos
usuários, pois a aplicação possui um acesso privilegiado aos dados e ao
próprio serviço.
O uso embarcado do núcleo facilita também o desenvolvimento de
appliances, visto que é possível oferecer, em um único dispositivo com
propósito específico, tanto uma interface direta para os usuários, quanto
uma instância do serviço. Consequentemente, isso permitiria a outras
aplicações controlarem remotamente a instância do serviço que está
embarcada.
3.3.2.1 API do serviço
A API é a interface que expõe o serviço implementado no núcleo para
as aplicaçõescliente. A API utiliza o protocolo HTTP para comunicação com
as aplicaçõescliente e adota uma arquitetura RESTful. O uso desse estilo de
arquitetura simplifica a representação do modelo do domínio na API, e
permite também criar um modo uniforme de interagir com as entidades
representadas.
Em arquiteturas RESTful, as capacidades do serviço são
representadas através de resources, que podem ser acessados por meio de
URLs (Universal Resource Locators). Ações podem ser executadas sobre esses
resources através de um conjunto restrito de verbos. Em serviços que
utilizam o protocolo HTTP, esses verbos são mapeados para os métodos do
protocolo26, tais como, GET, POST e DELETE.
25swig.org.26restfulapi.net
74
As rotas de uma API RESTful correspondem à parte da URL que
permite localizar um resource dentro de um servidor. Elas apresentam uma
estrutura hierárquica que permite representar relações entre conceitos.
A rota base da API do serviço, a “raiz”, apresenta informações sobre a
instância do serviço, como a versão da API e do núcleo e um identificador
para usuários dessa instância. Como a API utiliza versionamento
semântico27, isso permite que usuários e sistemas de terceiros identifiquem o
serviço que está sendo executado e se o mesmo é compatível com a
aplicaçãocliente.
Versionamento semântico, é uma forma de indicar através do número
de versão de um software informações sobre sua compatibilidade com outras
versões. Para isso é utilizado um formato com três números separados por
pontos (‘X.Y.Z’), onde o primeiro número identifica mudanças sem retro
compatibilidade, o segundo número marca adição de features com retro
compatibilidade e o terceiro número representa correções.
A raiz da API também lista o conjunto de rotas acessíveis através dela,
o que funciona como autodocumentação. Cada uma dessas rotas
representa uma coleção de entidades de um mesmo tipo. Elas seguem um
“arquétipo” de resouce (collection). Esses arquétipos atuam como padrões de
design, mas aplicados a modelagem de APIs RESTful. Outros três arquétipos
são identificados por Massé (2012): document, store e controller.
Cada membro de uma coleção pode ser acessado através de uma “sub
rota” dela, utilizando um identificador único da entidade ou, em alguns
casos, um nome que referencia a entidade de forma relativa a outros dados
da requisição. A rota “/users/me”, por exemplo, permite acessar dados do
próprio usuário que fez a requisição. Essas entidades seguem o arquétipo
“document”.
Propriedades de uma entidade podem, por sua vez, ser acessadas
através de “subrotas” da entidade, utilizando o nome da propriedade.
Algumas dessas propriedades podem ser também coleções, sob as quais o
mesmo padrão de acesso, definido anteriormente, se aplica.
27 semver.org.
75
Dessa forma, é possível identificar um padrão geral para as rotas da
API (Figura 6). Isto é, na base da API são referenciadas as diferentes
coleções. Abaixo delas é possível acessar as entidades ou itens das coleções
que podem ter um conjunto de propriedades.
A interação com essas coleções e entidades da API também é feita de
modo uniforme, de acordo com o tipo da rota (Tabela 3). Cada coleção provê
operações para listar e adicionar itens, através dos métodos GET e POST,
respectivamente. Já a atualização ou remoção de cada item é feita através da
rota que o identifica, utilizando os métodos POST e DELETE,
respectivamente. Esta rota também pode ser utilizada para acessar dados de
uma entidade, usando o método GET.
Figura 6: Estrutura geral de rotas da API e alguns exemplos
/<coleção>/<entidade>/<propriedade>
/photos/1/image
/contexts/123/photos
Fonte: o autor
A interação com as propriedades de uma entidade, dependendo de sua
semântica, pode ocorrer de forma similar a uma entidade ou coleção. Em
ambos os casos, uma propriedade não pode ser removida, apenas alterada
ou lida.
Os dados trocados entre as aplicaçõescliente e a API são
representados no formato JSON28 (JavaScript Object Notation), exceto quando
são utilizados tipos específicos, como imagens.
Tabela 3: Comportamento geral para interagir com rotas da API
Tipo darota
Método Operação Exemplos de rota
ColeçãoGET Lista todos os membros /events
/contextsPOST Adiciona membro
EntidadeGET Obtém entidade /albums/1
/photos/123POST Altera entidade
28json.org.
76
DELETE Remove entidade
Propriedade(entidade)
GET Obtém propriedade /users/me/profile-image
POST Altera propriedade
Propriedade(coleção)
GET Lista todos os membros/photos/1/markersPOST Adiciona membro
Fonte: o autor
Algumas rotas da API permitem o uso de parâmetros na url (Figura 7)
para filtrar a coleção de itens retornados ou solicitar mudanças na
representação deles.
Nem todas operações feitas através da API podem ser mapeadas
diretamente ao padrão descrito. É o caso das operações em lote feitas sobre
os álbuns, uma vez que elas atuam sobre os itens de um ou mais álbuns
para permitir copiar, mover ou excluir esses itens de forma atômica.
Além dos verbos e rotas utilizados, os dados retornados pela API e
operações realizadas através dela também são modificados de acordo com o
usuário que está autenticado, seguindo as permissões definidas no modelo
de dados do serviço.
Figura 7: Exemplo do uso de parâmetros em requisições à API.
a) /albums/123/photos?query="família"
b) /albums/456?expand-items=true
a) representa uma busca por fotos no álbum '123' que contenham o termo "família". Já em b), a representação do álbum '456' é modificada para incluir também dados das fotos e álbuns contidos nele, de forma a reduzir número de consultas.
Fonte: o autor
Para se autenticar, clientes requisitam a criação de uma nova sessão,
passando suas credenciais de acesso, i.e., login e senha. Após validar as
credenciais, o núcleo cria a sessão para aquele cliente e gera um token. Isto
é, um identificador da sessão que será utilizado pelo cliente para realizar as
requisições futuras.
77
O token é enviado ao cliente através de um cookie e no corpo da
requisição. Isso permite um gerenciamento automático da sessão por
clientes que tem suporte a cookies. Mas também dá suporte aqueles que
tenham restrições de acesso aos cookies. Esse é o caso de clientes Javascript
que executam no navegador. Devido a questões de segurança, o navegador
impede que eles acessem cookies que não venham do seu servidor de origem.
Também para permitir esse tipo de cliente, a API dá suporte a
requisições CORS29 (CrossOrigin Resource Sharing), um protocolo que
permite a páginas web acessarem alguns tipos de recursos “restritos”
provenientes de domínios diferentes da origem.
Sem essas medidas, clientes Web não poderiam acessar uma instância
do serviço em um domínio ou servidor diferente. Isso dificultaria o
desenvolvimento desses clientes de forma independente, bem como o seu
acesso a diferentes instâncias do serviço.
Para acessar resources não públicos da API, os clientes precisam
enviar a cada requisição o token recebido. A partir dele, o núcleo irá verificar
as permissões do usuário. Caso o usuário não possua as permissões
suficientes ou não esteja autenticado (token expirou, está inválido ou
ausente), a API irá retornar uma mensagem de erro. Os status codes (códigos
de estado) do protocolo HTTP são utilizados para comunicar a causa do erro.
No caso de coleções a que o cliente tenha acesso a apenas uma parte
dos itens, o núcleo oculta automaticamente os dados que o cliente não tenha
permissão para visualizar. Ao acessar a coleção de contextos, por exemplo,
são listados apenas aqueles que o usuário tem pelo menos permissão de
leitura.
29 developer.mozilla.org/en-US/docs/Web/HTTP/CORS
78
3.3.2.2 Aplicações do núcleo
Para prover os serviços da plataforma, o núcleo, por ser uma
biblioteca, precisa estar presente em uma aplicação. Essa aplicação é
responsável por controlar a execução do serviço, i.e. inicialização e
finalização. Além disso, ela irá prover uma interface para os usuários de
modo a permitir a configuração do serviço.
3.3.2.2.1 Âmbar Daemon
O Âmbar Daemon é uma aplicação de linha de comando para a
execução do serviço Âmbar. Ela foi desenvolvida para executar
primariamente em background, i.e. como um daemon, de modo a poder ser
implantada em servidores ou dispositivos embarcados. Mas ela também
pode ser utilizada em computadores pessoais, e.g. desktops e notebooks,
sem interferir nas atividades do usuário. A aplicação é compatível com
sistemas Unix, e.g. Linux e MacOS, e com Windows, mas atualmente foi
testada apenas no Linux.
O Âmbar Daemon utiliza o framework Poco30, que permite a execução
dele como um daemon Unix ou como um Windows service, de acordo com o
sistema operacional. Ele pode também ser executada em modo interativo,
i.e. conectado à linha de comando.
A interface do Âmbar Daemon provê opções para definir as
configurações do serviço, e.g. porta utilizada, diretórios para armazenamento
de dados, configurações de log, etc. Essas mesmas configurações podem
também ser fornecidas através de um arquivo de configuração (utilizando
formato JSON). Isso permite persistir as configurações entre execuções.
Caso as configurações não sejam informadas, o núcleo utiliza valores
padrão.
3.3.2.2.2 Âmbar Android Server
O Âmbar Android Server é um componente criado para permitir30pocoproject.org
79
executar o serviço Âmbar em dispositivos Android. Ele é oferecido através de
uma biblioteca Android para permitir seu uso integrado a um aplicativo
cliente (ver seção 3.3.3.2) ou em uma aplicação isolada.
O componente principal da biblioteca é um serviço Android31
(AmbarAndroidService), que é responsável por configurar, iniciar e finalizar o
serviço Âmbar. Para isso, ele interage com o núcleo, com ajuda de outros
componentes, utilizando bindings JNI (Java Native Interface).
O AmbarAndroidService provê ainda a integração necessária com a
plataforma Android. Ele permite receber comandos de uma aplicação para
iniciar ou finalizar o serviço Âmbar, e pode, por sua vez, notificála em
relação a mudanças no estado desse serviço. O AmbarAndroidService
também apresenta um ciclo de vida, gerenciado pelo Android, que permite a
ele reagir, por exemplo, à finalização da aplicação ou serviço, por um
usuário ou pelo sistema.
Para reduzir a chance do serviço Âmbar ser finalizada pelo Android
enquanto estiver em uso, e.g. devido a baixa memória, e permitir aos
usuários identificarem quando ele está ativo, o AmbarAndroidService utiliza
o recurso de “foreground service”32 do Android. Esse recurso indica ao
Android que o usuário está interagindo ativamente com o serviço. Ele
também cria uma notificação que permite aos usuários visualizarem que o
serviço está em execução. Essa notificação também inclui um controle que
permite ao usuário finalizar o serviço, caso deseje. Quando o serviço é
finalizado (pelo usuário ou pelo sistema), ou caso saia de “foreground”, a
notificação é removida.
3.3.3 Clientes do serviço
As aplicaçõescliente da plataforma são os componentes de software
responsáveis por prover a interação com os usuários. Elas atuam como
clientes do serviço e proveem acesso a um subconjunto dos recursos
oferecidos pela plataforma. Cada uma dessas aplicações pode adotar
31developer.android.com/guide/components/services.html32developer.android.com/guide/components/services.html#Foreground
80
diferentes soluções de projeto de software. Entretanto, podemos identificar
alguns elementos comuns a elas, que podem ajudar no entendimento e
desenvolvimento dessas aplicações.
Para interagir com o serviço, cada aplicação deverá ter pelo menos um
módulo que deve possuir componentes para permitir a realização de
requisições para a API, isto é, um cliente HTTP. Além disso, a aplicação
precisará de componentes responsáveis pela serialização e desserialização
entre as mensagens JSON e os elementos utilizados para representar, nas
aplicaçõescliente, o modelo de dados da API, ou parte dele. Um componente
de mais alto nível pode ser utilizado para integrar esses outros elementos e
lidar com a semântica das requisições da API.
As aplicaçõescliente também precisam de componentes para lidar
com a interface de usuário e manipulação de imagens. Além disso, elas
podem precisar de recursos para persistir, no lado cliente, alguns dados
relativos à aplicação, como preferências, configurações, dados sobre as
instâncias do serviço acessadas, e.g. endereço e nome, e os usuários
utilizados para acessálas.
Caso uma aplicaçãocliente também ofereça uma instância do serviço,
através do núcleo, ela precisará interagir com a biblioteca para, ao menos,
iniciar e finalizar o serviço.
Outros recursos ainda são necessários, de acordo com cada aplicação.
A arquitetura adotada para integrálos também pode variar.
3.3.3.1 Papéis dos clientes
Uma aplicaçãocliente não precisa utilizar todos os recursos oferecidos
pelo serviço da plataforma. Ao invés disso, cada aplicação pode escolher o
conjunto mais adequado de acordo com suas características e requisitos. Os
usuários poderão alcançar seus objetivos através do uso coordenado dessas
aplicações.
De acordo com as funcionalidades oferecidas pelas aplicações, elas
podem assumir um ou mais de três papéis: visualizador, editor e
81
administrador (Tabela 4).
Tabela 4: Papéis e funcionalidades dos clientes da plataforma
Papeis Funcionalidades
Visualizador
Exibir foto e dados associados a elaExibir conjuntos de fotos em sequência (slideshow)Navegação através da estrutura de álbuns, fotos e contextosBuscar fotos a partir de sua descrição
Editor
Adicionar e excluir fotografiasEditar descrições de uma fotografiaModificar itens de álbuns (adicionar, excluir, mover)Gerenciar contextos e álbunsGerenciar permissões de usuários sobre um contextoEditar perfil de um usuário
Administrador
Configurar serviço da plataformaGerenciar usuários
Fonte: o autor
Cada papel apresenta demandas diferentes para as aplicações, tanto
em termos de funcionalidades quanto em capacidades dos dispositivos para
os quais a aplicação é projetada.
Assim, a escolha de quais papéis serão adotados ou enfatizados em
uma aplicação pode ajudar a definir o conjunto de funcionalidades mais
importantes, bem como, outros requisitos funcionais para seu
desenvolvimento. Essa escolha, por sua vez, pode ser influenciada por
fatores como: o propósito da aplicação, o contexto de uso e também
restrições dos dispositivos em que a aplicação será executada.
O papel de visualizador está relacionado ao acesso e consumo, i.e.
exibição e visualização, do conteúdo. Esse papel pode ser implementado
mesmo em dispositivos que possuam capacidades de interação limitadas,
contanto que permitam visualizar e navegar no conteúdo.
Para esse tipo de dispositivo com capacidades de interação limitadas,
como televisores ou portaretratos digitais, pode ser importante também
prover aplicações auxiliares, em outros aparelhos, que atuem como
“controles remotos”, de modo a suprir as limitações de interação. No
82
entanto, é recomendável evitar que a aplicação se torne excessivamente
dependente de outro dispositivo, pois isso pode também dificultar seu uso,
já que impõe maiores restrições aos seus usuários.
Por estar relacionado aos objetivos principais da plataforma, o papel
de visualizador tende a estar presente na maior parte das aplicaçõescliente
da plataforma. Entretanto, algumas aplicações podem prover
funcionalidades de visualização, mas com o objetivo de atender um dos
outros papéis.
O papel de editor diz respeito à criação e modificação de conteúdo da
plataforma. Isso envolve tarefas como a organização e descrição de foto
memórias, ou adição e compartilhamento de conteúdo. Portanto,
funcionalidades relacionadas a esse papel são mais adequadas a dispositivos
com maior capacidade de interação, tais como, desktops e dispositivos
móveis.
A administração do sistema, embora possa se assemelhar, a princípio,
à edição de conteúdo, apresenta demandas específicas. Este papel, o de
administrador, está relacionado a configuração e monitoramento do serviço
e, em alguns casos, do dispositivo em que ele executa.
As aplicaçõescliente que também oferecem o serviço devem prover
funcionalidades para administração, mesmo que mínimas, de modo a
permitir controlar e configurar o serviço. Essas funcionalidades podem ser
acessíveis remotante, entretanto, é desejável que elas também possam ser
utilizadas diretamente através do dispositivo que executa o serviço. Isso
torna o dispositivo mais “autônomo” e pode simplificar correções em
situações excepcionais, como na perda de conectividade, além de reduzir as
restrições de segurança necessárias para administrar o serviço.
3.3.3.2 Âmbar mobile
Âmbar mobile é uma aplicaçãocliente da plataforma, desenvolvida
como um aplicativo móvel para Android. Essa aplicação foi projetada para
ser utilizada como um aplicativo autônomo, i.e. sem necessitar de um
83
serviço remoto. Para isso, além de implementar os três papéis de clientes da
plataforma (visualizador, editor e administrador), ela também embarca o
núcleo, utilizando o Âmbar Android Server. Desse modo, ela permite a
execução de uma instância local (no próprio dispositivo móvel) do serviço da
plataforma. Com isso, o aplicativo pode utilizar as funcionalidades providas
pela plataforma sem necessitar de um serviço “externo”/remoto e, até
mesmo, estando sem conexão com a rede local ou a Internet. O aplicativo
pode se conectar tanto à instância local do serviço, que executa no mesmo
dispositivo, ou a instâncias remotas. Com a primeira, entretanto, ele tem
uma integração maior. O aplicativo é capaz de inicializar o serviço local,
automaticamente, e detectar quando este é finalizado. Essa integração
também permite simplificar a criação de contas e gerenciamento do serviço
local.
A criação de contas em uma instância do serviço pode ser feita por um
usuário com permissão de administrador sobre o serviço ou diretamente
pelo novo usuário, sem precisar de autenticação. Nesse último caso,
entretanto, a conta fica inativa até ser habilitada por um administrador.
O modelo de segurança adotado assume que usuários com acesso ao
dispositivo tem autorização para controlar o serviço local e permitir, ou não,
o seu acesso por outros usuários.
Entretanto, mesmo podendo gerenciar o serviço, o aplicativo não
permite que esses usuários, com acesso ao dispositivo, personifiquem outros
usuários ou acessem dados privados deles. Isso reflete o entendimento de
que os administradores ou provedores do serviço não devem ter controle
também sobre os dados dos usuários, mas apenas sobre o serviço.
Para prover o “acesso privilegiado” ao serviço local, o núcleo provê um
“usuário local”, que tem poder de administrador, mas cuja sessão não pode
ser iniciada através da API, apenas diretamente pela biblioteca.
O Âmbar mobile provê também funcionalidades para acessar e
modificar o conteúdo de uma instância do serviço Âmbar, tais como: navegar
na estrutura de álbuns de um contexto e modificála, gerenciar contextos e
as permissões de usuário associadas a eles, buscar fotos a partir de um
84
álbum ou de todo um contexto, e visualizar fotos em sequência na forma de
slideshow ou individualmente.
A representação de fotomemórias no aplicativo busca fazer uma
metáfora às fotos impressas. Elas são representadas possuindo um “verso”,
no qual são exibidas as informações que descrevem a imagem e o contexto
relacionado a ela, como a localização e momento que ela representa.
Entretanto, por serem artefatos digitais, a representação das fotomemórias
na plataforma permite incluir também informações que não são, facilmente,
representadas em fotos impressas. Assim, o aplicativo inclui também
informações dos marcadores da imagem e uma terceira “camada” com
metadados, como: geolocalização, data da captura da foto e autor.
No aplicativo, contextos são tratados como escopos de visualizações
diferentes. Isto é, para acessar dados de outro contexto, o usuário precisa
modificar o “contexto atual”. Essa separação ajuda a evitar confusões e deixa
clara a delimitação entre os contextos. Além de ser um recurso para
organização, isso contribui para privacidade dos usuários. Pois, permite aos
usuários separar fotos relacionadas a grupos disjuntos de “contatos”, como
por exemplo: trabalho, amigos e família, e exibilas ou compartilhálas
apenas nos grupos adequados. Outras aplicações, entretanto, podem reduzir
essa separação entre contextos para privilegiar aspectos como a facilidade
para visualização e navegação no conteúdo.
3.3.3.3 Outras aplicaçõescliente
Outras aplicaçõescliente estão sendo projetadas e desenvolvidas para
a plataforma, em diferentes níveis de maturidade e etapas de
desenvolvimento. Estas aplicações estão sendo construídas em cooperação
com outros membros do grupo de pesquisa. São elas: o Âmbar display, o
Âmbar desktop viewer e o Âmbar VR.
85
3.3.3.3.1 Âmbar display
O Âmbar display é um projeto para uma aplicaçãocliente da
plataforma com o objetivo de reduzir barreiras para visualizar fotomemórias
fora do “mundo digital”. Essa aplicação foi projetada para dispositivos
voltados à exibição de conteúdo, mas com capacidades de interação
limitadas, tais como, Smart TVs, portaretratos digitais e quadros digitais.
As limitações de interação nesses dispositivos impõem certas
restrições sobre a aplicação. Aspectos como a navegação e elementos de
interface, além da própria escolha de funcionalidades, devem ser adaptados
aos componentes de interação disponíveis. Esses geralmente são limitados a
botões físicos na carcaça do dispositivo e, em alguns casos, controles
remotos.
Outra característica que influencia no projeto da aplicação é a
distância e posição relativa entre usuário e dispositivos. Ao utilizar
dispositivos como televisores ou quadros digitais, por exemplo, usuários não
estarão em contato direto com o dispositivo. Os quadros, em especial, podem
estar em uma altura ou posição de difícil acesso. Esses fatores podem
inviabilizar o uso de botões físicos para interações frequentes nesses
dispositivos. Para reduzir o impacto dessas limitações, é possível utilizar de
outros dispositivos para interagir com a aplicação. Para tanto, o Âmbar
display deve prover um serviço que será utilizado por outras aplicações
para, remotamente, configurar a aplicação ou modificar o conteúdo exibido
por ela. Essas duas aplicações deverão também interagir com uma ou mais
instâncias do serviço da plataforma, que é o responsável por armazenar e
prover o conteúdo exibido.
O Âmbar display deveria ainda permitir a integração com instâncias
do serviço locais, isto é, no mesmo dispositivo ou embarcadas junto com a
aplicação.
Para viabilizar a conexão das aplicações de controle com o Âmbar
display e, por sua vez, dele com o núcleo, deveria haver um suporte na
plataforma para protocolos de localização de serviços. Esses protocolos
possibilitam localizar automaticamente um serviço, seja em um escopo local
86
(intranet ou rede local) ou global (através da Internet).
3.3.3.3.2 Âmbar desktop viewer
O Âmbar desktop viewer é uma aplicaçãocliente, em desenvolvimento,
cujo objetivo é prover um visualizador da plataforma para computadores
desktop. Esta aplicação implementa as principais funções do papel de
visualizador, isto é, ela deve permitir navegar através da estrutura de
contextos e álbuns, buscar fotografias, e visualizar essas fotos,
individualmente, ou em conjunto, unido às suas descrições.
Esta aplicação deve também prover uma navegação mais simples entre
contextos distintos e permitir a visualização de sequências de fotos, em
formato de slideshow, provenientes de diversos contextos e, até mesmo, de
diferentes instâncias do serviço. Para isso, esta aplicação deve permitir
manter múltiplas sessões ativas, com diferentes instâncias e usuários do
serviço.
3.3.3.3.3 Âmbar VR
O Âmbar desktop viewer deve ser integrado a uma outra aplicação
cliente, ainda no estágio inicial de projeto, o Âmbar VR. Essa aplicação
busca prover um modo de visualização mais imersivo para as fotomemórias,
através do uso de tecnologias de Realidade Virtual (VR, do inglês Virtual
Reality).
O Âmbar VR está sendo projetado para ser utilizado com óculos de
realidade virtual, como o Cardboard33 ou Daydream34, da Google. Esses
“óculos” são, efetivamente, dispositivos móveis adaptados através de lentes
especiais e um suporte que segura o dispositivo e é preso à cabeça.
Esses dispositivos apresentam recursos de interação relativamente
limitados. Isto é, a interação através dos óculos está restrita, geralmente,
aos movimentos feitos com a cabeça, detectados através dos sensores no
33 vr.google.com/cardboard.34 vr.google.com/daydream.
87
dispositivo móvel, e a um botão magnético (magnet switch), que faz a função
de click.
Para lidar com essas limitações, o Âmbar desktop viewer deve ser
utilizado, e possivelmente outras aplicações da plataforma, para realizar
tarefas como a seleção de quais fotos serão visualizadas na aplicação VR.
Figura 8: Aplicações da plataforma Âmbar executando em diferentes tipos de dispositivos
Fonte: o autor
88
4 Warptopeer: Biblioteca Para
Conexões PeertoPeer
Warptopeer (Warp2p) é uma biblioteca de código aberto desenvolvida
em c++ para simplificar a conexão, de forma descentralizada, entre nós de
redes IP.
O nome escolhido para a biblioteca busca refletir esse propósito. O
termo “warp” é utilizado, em jogos, para indicar portais que permitem o
transporte automático entre diferentes locais. O uso é, provavelmente, uma
referência à “space and time warps”(distorções no tempo e espaço), um meio
comum na ficção científica e teorizado na física35 para permitir viajar longas
distâncias e até através do tempo.
Assim, o nome da biblioteca referencia a ideia de poder criar portais
para a comunicação entre pares na rede. Isto é, do ponto de vista do
desenvolvedor, ela deveria abstrair o processo de comunicação peertopeer e
apenas prover um canal para isso.
Para atender ao propósito definido para a biblioteca, foram definidos,
ao longo da sua concepção e desenvolvimento, um conjunto de objetivos e
restrições, como os descritos a seguir, que nortearam o seu projeto e
implementação.
a) facilitar a adoção de tecnologias descentralizadas
Embora novos tipos de aplicações possam vir a surgir a partir das
tecnologias descentralizadas, há hoje um grande número de aplicações
existentes que podem se beneficiar do seu uso. Por isso, soluções de
software precisam ser desenvolvidas que facilitem a evolução e adaptação
das bases de código existentes à essas novas tecnologias, sem que essas
bases precisem ser reescritas. Para isso, o projeto da biblioteca deveria
considerar os dois eixos: técnico e humano. Em relação ao primeiro, ela
deveria buscar reduzir as alterações necessárias para que pudesse ser
35 hawking.org.uk/space-and-time-warps
89
integrada a sistemas distribuídos existentes. Sobre o segundo eixo, a
biblioteca deveria expor uma API simples, que não exigisse dos
desenvolvedores um conhecimento aprofundado sobre as tecnologias
utilizadas por ela.
b) permitir adaptação a diferentes tecnologias e implementações para
comunicação entre nós da rede
Diferentes tecnologias e soluções podem permitir a conexão entre os
nós de um sistema. Entretanto, cada uma delas pode ser capaz de funcionar
em cenários distintos ou apresentar desempenhos variados. Dessa forma,
para que a biblioteca possa se adaptar aos cenários de comunicação e
requisitos das aplicações, ela deve prover meios para que diferentes
tecnologias e implementações possam ser escolhidas, segundo a
necessidade.
c) permitir referenciar e localizar serviços de forma permanente
Serviços descentralizados podem ser referenciados através de
diferentes endereços ou identificadores, seja em um mesmo instante ou ao
longo do tempo. Isso pode ocorrer devido a diferentes fatores, tais como:
mobilidade do dispositivo; uso de endereços alocados dinamicamente; ou
uso de diferentes stacks de tecnologias para prover o mesmo serviço. Dessa
forma, para que esses serviços possam ser acessados de forma confiável, é
preciso prover um meio de identificálos que não varie com o tempo ou as
tecnologias de comunicação utilizadas. Esses identificadores devem poder
ser gerados de forma descentralizada e não devem poder ser facilmente
falsificados. Além disso, é preciso prover meios para localizar e estabelecer
comunicação com esses serviços a partir de seu identificador;
d) contribuir para segurança e privacidade dos usuários
Segurança e privacidade são aspectos importantes para a construção
de sistemas distribuídos confiáveis. No contexto da biblioteca desenvolvida, é
preciso considerar como estabelecer e manter comunicações seguras e
privativas. Isso envolve preocupações como: garantir que uma conexão seja
estabelecida com o par que se deseja (evitar hijacking de conexão ou
90
falsificação de identidade); evitar que os dados transmitidos sejam
interceptados ou modificados indevidamente; reduzir as possibilidades de
monitoramento dos pares que se comunicam.
Vale salientar, no entanto, que segurança e privacidade são aspectos
complexos e transversais ao desenvolvimento de uma aplicação. Os níveis de
segurança e privacidade considerados “aceitáveis” também podem variar de
acordo com usuários e aplicações. Além disso, características das diferentes
tecnologias de comunicação utilizadas (objetivo II) podem também
influenciar nesses requisitos.
Dessa forma, a biblioteca não pode, por si só, garantir comunicações
seguras ou privativas. Entretanto, ela pode oferecer soluções que
contribuam e não prejudiquem a segurança e privacidade dos sistemas
desenvolvidos a partir dela.
Isso pode ser feito através de medidas como: prover meios que
facilitem a verificação da identidade dos pares que se conectam; prover
recursos que facilitem a criação de canais criptograficamente seguros; evitar
publicar (em aberto) informações que facilitem rastrear usuários ou
monitorar suas atividades.
4.1 Arquitetura
A biblioteca é organizada através de módulos (Figura 9). Cada módulo
é composto por classes e interfaces, que proveem um conjunto de
funcionalidades coesas. As interfaces são utilizadas em conjunto com um
um mecanismo de injeção de dependências para permitir a adaptação do
comportamento da biblioteca a diferentes implementações e tecnologias
(objetivo II).
Módulos mais abstratos utilizam a injeção de dependências para obter
implementações das interfaces definidas. Enquanto módulos mais concretos
proveem implementações a essas interfaces (princípio da inversão de
dependência). Os módulos proveem interfaces simples para registrar as
implementações providas por eles no mecanismo de injeção de
91
dependências. Dessa forma, as aplicações podem escolher quais
implementações serão utilizadas (objetivo II).
Um dos módulos principais é o módulo de conectividade. Ele define as
abstrações e classes base relacionadas ao propósito da biblioteca. A
biblioteca inclui também implementações das interfaces definidas por ele
que permitem a travessia de NAT e comunicação descentralizada.
Através de um outro módulo, o módulo de identidade, a biblioteca
provê um mecanismo de identidades baseado em criptografia, o que
contribui para requisitos de segurança (objetivo IV) e possibilita identificar
serviços de forma única e descentralizada (objetivo III).
Essas funcionalidades são abstraídas através de uma fachada simples,
que facilita o entendimento e uso da biblioteca (objetivo I). A biblioteca inclui
ainda um mecanismo de “pontes”, que permite aos componentes de um
sistema distribuído “tradicional”, e.g.: clienteservidor, se conectarem, sem
que o código destes precise ser alterado (objetivo I).
Os módulos são agrupados, de acordo com suas dependências
externas, em arquivos de biblioteca, e.g. arquivos ‘.so’ ou ‘.dll’ (dependendo
do sistema). Aqueles que formam a parte central da biblioteca, e não
dependem de bibliotecas de terceiros são agrupados em um arquivo de
biblioteca central (warp2pcore). A Figura 9 apresenta os módulos que
compõem a biblioteca, agrupados de acordo com seus arquivos de biblioteca.
A imagem destaca também algumas das classes e interfaces que compõem
esses módulos.
A seguir são descritos em detalhes os elementos principais da
biblioteca. Na seção 4.2 são apresentadas implementações relacionadas a
eles.
92
Figura 9: Arquitetura geral da biblioteca
Fonte: o autor
4.1.1 Conectividade
A fachada para utilizar os serviços da biblioteca é provida através da
classe Peer (Figura 10). Ela representa um elemento de um sistema
distribuído com uma identidade fixa. Cada peer é capaz de ofertar ou
consumir serviços.
Peers permitem estabelecer conexões para utilizar um dado serviço.
Por sua vez, peers que oferecem serviços irão receber “ofertas” de conexão
que eles podem, ou não, aceitar. Conexões e serviços são representados,
respectivamente, pelas interfaces Connection e Service (detalhadas a seguir).
Para que um peer crie instâncias dessas interfaces ele utiliza uma instância
de Connector, obtida através de injeção de dependências. Um peer irá
também manter uma instância da classe Identity (descrita na seção 4.1.2),
93
que é utilizada para gerar o identificador do peer e dos serviços oferecidos
por ele. A Figura 10 apresenta os principais métodos da classe Peer e
entidades relacionadas a ela. Na Figura 11 são apresentados exemplos do
seu uso para (a) criar um serviço e esperar por conexões, e (b) se conectar a
um serviço existente.
Figura 10: Classe Peer: fachada da biblioteca warptopeer
Fonte: o autor
Figura 11: Exemplos de uso da classe Peer
Peer myPeer;//...myPeer.listenTo({"ambar-core"}) //tipo do serviço criado .onConnection([](ConnectionPtr conn){ //Tratar conexão recebida (ex.: registrar listeners) ... return true; //ou false para rejeitar conexão });
(a)
Peer myPeer;//...myPeer.connectTo(ServiceDesc::parse("warp://0xa9137cf2de/ambar-core")) .onConnected([](Connection &, Stream &){ // Conexão foi estabelecida }) .onData([](Connection &, Stream &, const Bytes &){ //tratar dados recebidos }) .onClose([](Connection &){ //Conexão finalizada });
(b)
Fonte: o autor
94
O módulo de conectividade (Figura 12) agrupa as interfaces e classes
que permitem estabelecer comunicações entre peers.
A interface Connector representa uma fábrica de conexões e serviços
relacionadas a uma mesma tecnologia de comunicação. Cada
implementação dessa interface irá prover os métodos para iniciar um serviço
ou conectarse a um serviço existente.
As conexões estabelecidas entre pares são representadas pela interface
Connection. Implementações dessa interface encapsulam os passos
necessários para estabelecer um canal de comunicação com um outro Peer.
Isto é, elas implementam um “ciclo de vida da conexão”.
De acordo com a tecnologia adotada, esse ciclo de vida, e os passos
relacionados a ele, poderão variar. Entretanto, a biblioteca define eventos
comuns, que podem permitir a “entidades interessadas” observarem as
transições de estado de uma conexão. São eles: “onConnected”, que ocorre
quando a conexão é estabelecida; “onData”, disparado quando a conexão
recebe dados do outro peer conectado; e “onClose”, que notifica o
encerramento da conexão.
Para receber esses eventos, são utilizados listeners que devem ser
registrados em uma instância de Connection. Múltiplos listeners podem ser
registrados para cada evento. É possível utilizar uma “interface fluente”
(FluentConnection), que permite encadear chamadas a uma Connection, com
Figura 12: Módulo de conectividade
Fonte: o autor
95
intuito de tornar a sua configuração mais fluída e legível.
Cada implementação de uma conexão é responsável por disparar os
eventos associados a ela. A biblioteca oferece, no entanto, classes que podem
servir de base e implementam comportamentos comuns às conexões.
A biblioteca assume que os estados de uma conexão seguem um “fluxo
linear” (Figura 13). Isto é, uma conexão que ocorra com sucesso segue do
estado inicial para o conectado e deste para o finalizado. Ela pode,
entretanto, ser finalizada a qualquer momento, mesmo antes da conexão ser
estabelecida. Ela não deve, porém, retornar a um estado anterior. Uma
conexão finalizada, por exemplo, não deve voltar ao estado de conectada.
Invés disso, uma nova conexão pode ser criada. Esse fluxo simplifica o
entendimento e o tratamento dessas conexões.
Figura 13: Ciclo de vida das conexões e eventos relacionados.
Fonte: o autor
Ao iniciar uma conexão para um determinado serviço (método
connectTo da classe Peer), o processo de conexão deve ser iniciado
imediatamente, de forma assíncrona. Isso permite, potencialmente, um
melhor desempenho. Entretanto, isso cria um possível problema de
concorrência, pois os eventos associados a uma conexão podem ocorrer
antes que um listener possa ser registrado.
96
Para solucionar isso, as conexões devem manter o estado atual e
chamar os listeners correspondentes que forem registrados após um evento
ocorrer. Isso possibilita também a criação de conexões que já estejam
conectadas ou mesmo já finalizadas (no caso de erro, por exemplo).
No caso do evento de dados (onData), entretanto, é necessário um
comportamento especial, pois não é viável manter todos os dados recebidos
para entrega futura, devido ao consumo de memória. Nesse caso, é possível
utilizar de estratégias diferentes. Uma delas é limitar a quantidade de dados
a serem mantidos, utilizando buffers, ou restringir o tempo de
armazenamento. Além disso, podese descartar os dados já entregues a
algum listener daquela conexão. Listeners registrados posteriormente
receberiam, nesse caso, apenas os dados após seu registro.
Para enviar dados a um outro peer, é utilizada uma outra interface:
Stream. Ela representa o canal de comunicação entre dois pares. Ela é
responsável também pelo recebimento de dados. Para isso ela permite
também registrar listeners para um evento (esse mesmo evento é
encapsulado pelas implementações de Connection, por “comodidade”).
Conexões são responsáveis por criar e gerenciar as Streams, de forma
relacionada ao seu ciclo de vida. Isto é, quando uma conexão é estabelecida,
ela deve prover uma instância válida de Stream no evento relacionado
(onConnected). O entendimento é que uma conexão estabelecida deve prover
um meio para que um peer troque mensagens com outro.
Uma conexão provê também acesso à Stream nos listeners de dados
(onData), por conveniência e para permitir o reuso desses listeners (com
diferentes Streams). Além disso cada conexão provê um getter para a Stream
relacionada, o que permite o seu uso fora das callbacks da conexão.
Entretanto, a Stream retornada pelo getter deve ser válida (não nula) apenas
após o estabelecimento da conexão.
Para que um peer possa receber conexões ele utiliza de serviços,
representados pela interface Service. Eles encapsulam os comportamentos
necessários de uma determinada tecnologia para permitir registrar um
97
listener para receber conexões.
Ao receber uma conexão, um serviço dispara um evento (onConnection)
passando uma instância de Connection, criada por ele, que representa a
conexão iniciada. Isso permite a um listener registrado a esse evento
associar callbacks para os eventos da conexão e, assim, estabelecer a
comunicação através dela. Esse listener pode também rejeitar a conexão
recebida, que será, nesse caso, encerrada.
Vale destacar que a conexão criada pelo serviço é também uma
instância de Connection. Para um mesmo conector é possível que a
implementação desses dois tipos de conexão varie ou seja a mesma, podendo
estar em estados diferentes. Isso possibilita o reuso de código tanto na
implementação das conexões quanto no seu uso. Para sistemas peertopeer,
em especial, o papel assumido por cada par pode ser o mesmo após
estabelecida a conexão, assim é conveniente que eles possam reutilizar as
mesmas abstrações.
Protocolos que não são baseados em conexão (ex.: Udp) podem ainda
utilizar essas abstrações. Nesse caso, a instância de Connection é iniciada já
conectada, pois não há processo de conexão. Sua criação, no caso dos
serviços, pode ser disparada a partir da primeira interação proveniente do
outro peer, como o recebimento de uma mensagem. Isso exige, entretanto,
que o serviço mantenha um registro de quais peers já se conectaram a ele. É
recomendável também utilizar de timeouts, nesse tipo de serviço, para
finalizar conexões inativas.
Para identificar um serviço é utilizado um “descritor do serviço” (classe
ServiceDesc). Esse descritor é composto por um identificador único do peer
que provê o serviço, por um nome que identifica o tipo do serviço e,
opcionalmente, um identificador para a instância daquele serviço. Esse
descritor possibilita identificar um serviço de forma única e permanente,
contanto que o identificador do peer seja único e persistente globalmente, e
que o par dos outros dois dados seja também único e persistente, porém de
forma local. O tipo do serviço permite ainda às aplicações identificarem
serviços compatíveis. Já o nome de instância é um meio de permitir a um
98
peer prover mais de um serviço do mesmo tipo.
O descritor de um serviço é formado durante a criação do serviço,
juntando os dados que caracterizam o serviço (tipo e nome de instância),
providos pela aplicação, e o identificador associado ao peer.
Para facilitar a transmissão desse descritor, a biblioteca permite
representálo como uma URI. Dessa forma, ele pode ser passado mais
facilmente entre usuários e aplicações. Além disso, URIs podem ser
utilizadas em algumas plataformas para abrir aplicações associadas àquele
tipo de URI. Com isso, é possível simplificar o uso dos serviços e aplicações
baseados na biblioteca.
4.1.2 Identidade
Para permitir identificar serviços de modo permanente e
descentralizado (objetivo III), a biblioteca inclui um mecanismo de identidade
baseado em criptografia assimétrica. Esse mecanismo é utilizado pelos peers
e conectores para prover um identificador e poder verificar a identidade de
um outro peer.
A classe Identity (Figura 14) representa a identidade de um peer. Ela
atua como um container de um par de chaves pública e privada,
representadas pelas interfaces PublicKey e PrivateKey, respectivamente.
Essas duas interfaces proveem uma abstração sobre os algoritmos de
criptografia assimétrica e dos dados associados a eles, i.e. algoritmos de
assinatura e criptografia de dados. Além disso, implementações de PublicKey
devem também permitir gerar um identificador globalmente único e
imutável, i.e. um identificador com chances muitos pequenas de colisão para
chaves públicas distintas e que produza sempre o mesmo resultado para
uma determinada chave.
Esse identificador deve também ter um tamanho relativamente
reduzido (até poucas dezenas de bytes), pois ele será utilizado como
identificador de um peer e compor o descritor de um serviço.
99
Através das chaves pública e privada também é possível verificar a
identidade de um peer ou de um dado publicado por ele, através do uso de
criptografia e assinaturas. Essas verificações podem ser feitas a nível de
aplicação ou, preferencialmente, diretamente pelo conector. Por isso, a
identidade de um peer é passada aos conectores criados por ele, utilizando
uma instância de ConnectionFactory para isso.
Por sua vez, para permitir a criação de identidades, e das chaves
associadas a ela, peers irão utilizar implementações de IdentityManager.
Essa classe permite gerar pares de chaves pública e privada, bem como
serializar ou deserializar essas chaves.
A (de)serialização dessas chaves possibilita persistilas ou transmiti
las através da rede. Para chaves privadas é possível utilizar uma senha para
impedir que a chave seja carregada por aqueles que não conhecem a senha.
Figura 14: Principais classes do módulo de identidade
Fonte: o autor
100
4.1.3 Pontes
A biblioteca implementa um mecanismo de “pontes” para permitir a
tradução entre conexões TCP/IP “tradicionais”, i.e. utilizando TCP ou UDP
diretamente, e conexões criadas através da biblioteca. O objetivo é
simplificar a adaptação de sistemas distribuídos “tradicionais” às tecnologias
utilizadas na biblioteca.
Cada ponte (interface Bridge) recebe comunicações de um conjunto de
clientes e as reencaminha para um determinado serviço, que utiliza um
protocolo diferente. Dessa forma, a ponte atua tanto como servidor, quanto
como cliente.
O uso de pontes nos “dois lados” da comunicação pode ser usado para
criar um "túnel" com tecnologias descentralizadas (Figura 15) e, dessa
forma, permitir adaptar sistemas “tradicionais” a essas tecnologias,
potencialmente sem ter de modificálos.
Figura 15: túnel criado entre um cliente e um servidor, utilizando as pontes da biblioteca
Fonte: o autor
Cada ponte está associada a um servidor, para o qual ela irá
transmitir as conexões. A ponte, por sua vez, também cria um serviço para
receber conexões dos clientes. Quando um novo cliente se conecta, a ponte
inicia uma conexão com o servidor a qual ela está associada. Estabelecidas
ambas conexões, a ponte passa a redirecionar os dados recebidos de um
lado, para o outro. Caso uma das conexões seja encerrada, a ponte irá
finalizar a conexão com o outro lado.
Para criar os serviços e conexões descentralizadas, as pontes irão
utilizar de uma instância de Peer. A tecnologia empregada para essas
conexões irá depender do conector em uso. Já para criar serviços ou
conexões TCP/IP, a biblioteca utiliza uma instância de SocketConnector.
Similar a um Connector, essa interface define a criação de serviços e
conexões, porém com algumas diferenças nos parâmetros adotados. O uso
101
das mesmas abstrações (Service e Connection) facilita o reuso e possibilita
que as pontes sejam adaptadas, futuramente, para uso com outros tipos de
tecnologias.
Figura 16: Principais classes do módulo de pontes
Fonte: o autor
As pontes permitem uma comunicação transparente através delas.
Entretanto, é natural que ocorram alterações nas propriedades da
comunicação devido a variações de protocolos e à retransmissão de dados.
Além da performance, fatores como a confiabilidade podem ser afetados se,
por exemplo, protocolos sem garantias de confiabilidade forem utilizados,
e.g. UDP.
Vale salientar também que ambos os pontos que se comunicam
através da ponte precisam utilizar o mesmo protocolo a nível de aplicação, já
que as pontes não alteram as mensagens enviadas através delas.
102
4.2 Implementações
O mecanismo de injeção de dependências utilizado (baseado na
biblioteca Hypodermic36), possibilita desacoplar interfaces e implementações.
Com isso, aplicações podem selecionar ou desenvolver as tecnologias e
implementações adequadas ao seus contextos de uso.
Para tanto, cada aplicação irá registrar, durante sua inicialização,
para cada interface requerida, as classes concretas que serão utilizadas, ou
functors que irão construir instâncias dessas interfaces. Para simplificar
isso, cada módulo que implementa interfaces, provê funções que permitem
registrar as implementações definidas por ele. Isso evita que às aplicações
estejam acopladas a detalhes de implementação desses módulos. Não
impede porém que as classes concretas sejam utilizadas, por exemplo, para
definir novos módulos.
Módulos que precisem de algum tipo de configuração especial ou que
desejem prover uma integração maior com elementos internos, podem
receber componentes, durante o registro do módulo, que serão chamados
posteriormente pelos componentes desse módulo.
Alguns dos módulos definidos na biblioteca podem depender de
bibliotecas de terceiros. Para evitar que aplicações que não utilizem esses
módulos dependam também dessas outras bibliotecas, eles são separados
em outros arquivos de biblioteca.
Por comodidade, entretanto, a biblioteca permite gerar um bundle que
inclui todos os módulos, selecionados em tempo de compilação, em um
único arquivo.
A seguir são detalhados alguns dos módulos utilizados na biblioteca.
4.2.1 Módulo ICE
A biblioteca inclui um módulo para permitir estabelecer conexões
36 github.com/ybainier/Hypodermic
103
peertopeer, e realizar a travessia de NAT, utilizando o protocolo ICE. Esse
módulo define um conjunto de classes base relacionadas ao processo de
conexão através do ICE (Figura 17), troca de sinais (signalling) e seleção de
um servidor STUN. Ele também inclui componentes para permitir a
verificação da identidade dos peers que se conectam.
As funcionalidades do módulo são oferecidas através de uma
implementação de Connector (ICEConnector). A partir dele são criados
serviços (ICEService), que recebem e tratam ofertas ICE (ICEOffer). Através
do conector também são iniciadas conexões ICE com outros peers (ICECall).
Esses componentes interagem com uma instância de Signaller, uma
interface que define a API para a troca dos “sinais” utilizados em conexões
ICE. Ela permite o envio de “requisições de conexão” (ConnectionRequest),
bem como o registro de listeners para receber essas requisições. Essa
interface define também um método para responder às requisições
recebidas.
Figura 17: Diagrama de classes do módulo ICE.
Fonte: o autor
Através dessas requisições são enviados os candidatos ICE que serão
utilizados para tentar estabelecer uma conexão. Por sua vez, as respostas
irão conter os candidatos do outro peer, caso a requisição seja aceita. Para
indicar o sucesso ou não da requisição, a resposta inclui também um status.
104
Em caso de falha ou de rejeição da conexão esse status irá indicar o tipo do
erro e poderá incluir um identificador e uma mensagem para especificar a
causa.
Os passos relativos ao protocolo ICE , i.e. obtenção de endereços
candidatos e verificação de conectividade, são implementados através das
conexões. A classe ICEConnection estende Connection e define um conjunto
de métodos, que devem ser implementados por subclasses, para executar
esses passos. Para abstrair a construção de instâncias concretas dessa
classe, é utilizada uma outra interface (ICEConnectionBuilder).
A biblioteca oferece um outro módulo que provê a implementação
desses componentes, utilizando a “libnice”37. Algumas das classes desse
módulo estão representada na Figura 17, em vermelho. Essa biblioteca,
desenvolvida em C com base na glib38, implementa o protocolo ICE e, como
parte dele, um cliente STUN. Ela também possui integração com o protocolo
UPnPIGD, através da biblioteca gupnpigd.
O módulo ICE define também uma interface para seleção de servidores
STUN (STUNSelector). Ela permite que diferentes estratégias sejam utilizadas
para obter o endereço para um desses servidores. Atualmente, entretanto,
está implementada apenas uma estratégia, que utiliza uma lista fixa de
servidores STUN.
4.2.2 Signalling
Signaller é o componente utilizado pelo módulo ICE para enviar e
receber as requisições de conexão (ConnectionRequest) e às respostas a essas
requisições (ConnectionResponse). Ele abstrai, no entanto, a forma com que
esses dados serão transmitidos, permitindo diferentes soluções.
A biblioteca provê uma implementação para esse componente dividida
em dois módulos (Figura 18). O primeiro (DhtSignaller), mais
genérico/abstrato, provê a base da implementação e trata da validação e
autenticação dos dados, utilizando os componentes de identidade definidos
37 nice.freedesktop.org/libnice38 developer.gnome.org/glib
105
na biblioteca.
Esse módulo é integrado ao core da biblioteca e define alguns outros
componentes que são implementados pelo segundo módulo. Dentre esses,
destacamse dois principais: o DhtSignallerParser e Dht. Eles são
responsáveis, respectivamente, pela serialização e a transmissão e recepção
dos dados de conexão. A construção desses componentes é feita através de
uma factory (DhtFactory), o que simplifica o uso deles através do mecanismo
de injeção de dependências e garante coerência entre as implementações.
Figura 18: Classes dos módulos Signaller
Em amarelo, classes base do módulo ICE. Em verde, classes do módulo DhtSignaller e em azul, classes do módulo OpenDhtSignaller.
Fonte: o autor
Uma implementação do “módulo de transmissão” foi feita utilizando
uma DHT (através da biblioteca OpenDHT). Isso permite realizar o processo
de signalling de forma descentralizada. Há, no entanto, a limitação do
106
bootstrapping. Hoje, a implementação depende que um ou mais nós de
boostrapping “conhecidos” sejam fornecidos durante o registro do módulo.
Ela permite, no entanto, que outras estratégias sejam implementadas para
tornar o processo mais descentralizado.
Antes de iniciar o processo de signalling propriamente dito, um
listener deve ser registrado para receber as requisições de conexão. Isso é
feito como parte da criação de um serviço ICE. O registro do listener utiliza
um endereço que deve ser derivado do descritor do serviço, de modo que os
clientes desse serviço possam gerar seu endereço, conhecendo apenas o
descritor. O tipo do endereço, assim como o componente responsável pela
sua geração (DhtSignallerParser) são definidos pelo “módulo de
transmissão”.
Na implementação com a OpenDHT, esse endereço corresponde a um
hash, gerado a partir da URL do descritor do serviço. Para monitorar o
endereço, a OpenDHT provê um recurso de listen. Em outras DHTs, isso
poderia ser implementado através de consultas regulares ao endereço.
Quando uma conexão ICE é criada para um serviço, uma requisição
de conexão é iniciada através do Signaller (Figura 19). Para isso, ele recebe o
descritor do serviço para qual a requisição será enviada, os dados utilizados
pelo ICE (endereços candidatos e “credenciais” para validar conexão),
representados pela classe PeerInfo, a identidade do peer que está enviando a
requisição e listeners que receberão a resposta ou notificações de erro, caso
ocorram.
O Signaller, então, constrói uma requisição de conexão
(ConnectionRequest), contendo os dados necessários para o ICE. Ele
também inclui um timestamp que indica o tempo em que a requisição irá
expirar. Além disso, ele inclui a chave pública do peer que envia a
requisição. Ela será utilizada para permitir criptografar a resposta e validar
a requisição.
107
Figura 19: DhtSignaller: envio de requisição de conexão
Fonte : o autor
Para poder receber a resposta, um endereço é gerado também para o
cliente (o peer que envia a requisição) e incluso na requisição. Esse endereço
pode ser derivado do descritor do serviço e da identidade do cliente. Além
disso, para evitar conflitos entre outras requisições enviadas ao mesmo
servidor, um fator aleatório é utilizado na geração do endereço. Tendo o
endereço gerado, o cliente registra também um listener para esse endereço.
Ao receber uma resposta, entretanto, ou se a requisição for cancelada, ele
deverá remover o listener para aquele endereço.
Para permitir o envio da requisição de conexão, ela é serializada. Uma
assinatura é, então, gerada a partir da requisição serializada, utilizando a
chave privada do peer cliente. Ambos os dados são agrupados em um
componente (SignedData), que é, por sua vez, serializado e enviado para o
outro peer. Utilizando a DHT, esse envio corresponde a uma operação de put
no endereço monitorado pelo serviço.
108
Ao receber os dados do peer cliente (Figura 20), o Signaller irá fazer o
processo de deserialização. Para isso, ele irá extrair os dados assinados
(SignedData) e em seguida deserializar a requisição de conexão. A assinatura
dos dados será, então, validada utilizando a chave pública contida na
requisição. Com isso, a integridade dos dados é garantida, assim como sua
autoria.
Caso algum dos dados obrigatórios esteja faltando, como os endereços
candidatos, ou a assinatura não seja válida, uma resposta de erro é enviada.
Se no entanto, a requisição tiver expirado ou não contiver um endereço de
resposta válido, a requisição será descartada.
Figura 20: DhtSignaller: requisição de conexão recebida
Fonte: o autor
Se a requisição for válida, ela será entregue ao serviço ICE, que irá
iniciar uma conexão a partir dos dados recebidos. Essa conexão, por sua
109
vez, será entregue ao listener do serviço. Caso ela não seja rejeitada por ele,
os candidatos do peer do serviço serão obtidos e enviados em uma resposta
através do Signaller.
A resposta do serviço é criptografada, utilizando a chave pública do
peer cliente e assinada com a chave privada do peer servidor. A resposta
também inclui os dados utilizados no ICE e a chave pública do servidor.
Além disso ela irá conter um status da resposta (ResponseStatus) que pode
indicar se um erro ocorreu e a sua causa.
Quando o peer cliente recebe a resposta (Figura 21), ele irá
descriptografála, com sua chave privada, deserializála e irá validar a
assinatura em relação a chave recebida. Além disso, o peer deve verificar se
a chave recebida apresenta o mesmo id do serviço presente no escritor. Isso
é feito gerando o id da chave pública recebida. Dessa forma, o peer pode
garantir que se conectou ao serviço desejado.
Figura 21: DhtSignaller: resposta de uma requisição de conexão recebida
Fonte: o autor
110
Tendo recebido uma resposta válida, o peer pode então iniciar o
processo de verificação de conectividade do ICE, para poder estabelecer a
conexão.
4.3 Âmbar descentralizado
Para integrar o Âmbar com o Warp2p foi utilizado o mecanismo de
pontes da biblioteca. Dessa forma, não foi necessário realizar nenhuma
mudança ao núcleo da plataforma.
Aplicações cliente podem também utilizar as pontes sem precisar de
modificação, se as pontes forem executadas através de um processo
separado. Para as aplicações elas estariam apenas se conectando a um outro
servidor. Entretanto, isso impediria o gerenciamento das pontes por essas
aplicações, e poderia comprometer a experiência do usuário. Além disso, a
aplicação terminaria dependendo desse processo externo. Dessa forma, é
necessário prover uma integração dessas aplicações com, pelo menos, o
mecanismo de pontes da biblioteca.
Como forma de validação, foi desenvolvida uma biblioteca Android, a
mobilewarp, para realizar a integração entre o Ambar Mobile e a Warp2p
(Figura 22). Além disso, foi criada uma pequena biblioteca em C++ (warp
bridge) para encapsular algumas etapas comuns para o uso das pontes em
aplicações e, com isso, simplificar o desenvolvimento da MobileWarp. Outras
integrações podem ser desenvolvidas futuramente para outros clientes da
plataforma, possivelmente reutilizando a warpbridge.
O uso da MobileWarp no aplicativo Android é feito através de um
serviço Android oferecido por ela (WarpService). O serviço permite a criação
de pontes pela aplicação. Para isso, a aplicação envia um Intent ao
WarpService, contendo o descritor do serviço a qual ela deseja se conectar e
o tipo do transporte que os clientes irão utilizar para se conectar à ponte, i.e.
TCP ou UDP. Quando a ponte é criada, o WarpService envia para a aplicação
o endereço do serviço criado pela ponte, com o qual ela pode se conectar.
Isso é feito através do broadcast de um Intent, que será recebido por um
111
BroadcastReceiver registrado pela aplicação.
Figura 22: Componentes para integração entre o Âmbar Mobile e a Warptopeer
Fonte: o autor
O processo de criação da ponte é feito durante o login na aplicação
(Figura 23). Quando o usuário utiliza um endereço que corresponde a um
descritor de um serviço, i.e. uma url “warp://”, a aplicação inicializa a ponte
para aquele serviço. Quando a ponte é criada, a aplicação prossegue com o
processo de login, utilizando o endereço da ponte. Para o cliente da API não
há alterações.
Para criar as pontes, a MobileWarp irá utilizar a biblioteca warp
bridge, através de bindings criados com JNI (Java Native Interface). Essa
biblioteca apresenta uma fachada, através da classe BridgeService, que
simplifica o uso das pontes da Warp2p. Ela também realiza o registro e
configuração dos módulos desenvolvidos na Warp2p, de modo a prover uma
“solução completa” para conectividade, e realiza a criação e o carregamento
dos dados de uma identidade, i.e. a chave criptográfica.
A configuração da warpbridge e inicialização dos módulos é feita
sobre demanda. Isto é, quando o WarpService recebe um Intent para criar
uma ponte, ele realiza, com a ajuda de outros componentes, o processo de
112
configuração e inicialização, caso não tenham sido feitos ainda. Isso evita
que recursos sejam utilizados sem necessidade. Entretanto, pode fazer com
que a criação da ponte seja mais lenta.
Figura 23: Processo de inicialização de uma ponte Warp2p, durante login no Âmbar Mobile
Fonte: o autor
4.4 Discussão
Warp2p provê uma solução para travessia de NAT de forma
descentralizada. Entretanto, a solução ainda apresenta dependências com o
servidor de STUN e com o nó de bootstrap. Esses nós, entretanto, não são
fixos. Eles podem ser modificados durante a execução. Outras estratégias
podem ser implementadas, e providas durante configuração dos módulos,
para selecionar esses nós de forma a evitar dependências estáticas.
O mecanismo de travessia de NAT adotado, assim como outras
soluções baseadas em STUN e hole punching, não é capaz de fazer a
travessia de NATs simétricos ou alguns tipos de Firewall. Soluções para isso
113
envolvem o uso de relays. Soluções mais descentralizadas podem ser
implementadas, futuramente, utilizando redes overlay, como a rede Tor.
O mecanismo de signalling implementado provê recursos de
segurança, que permitem verificar a identidade dos pares que se
comunicam, utilizando técnicas de criptografia. Além disso, ele busca evitar
expor publicamente o endereço dos pares que se conectam, diferente de
outras soluções, como o Bittorrent que armazena diretamente na DHT o
endereço dos pares.
A implementação adotada, entretanto, pode ser evoluída para
melhorar a segurança, performance e privacidade dos usuários. Isso pode
ser feito através da publicação da chave pública dos pares na DHT, em uma
etapa anterior ao estabelecimento das conexões. Isso evitará o envio das
chaves no estabelecimento da conexão, o que deverá melhorar a performance
do sistema. Além disso, será possível aos clientes criptografarem a
requisição de conexão enviada a um peer servidor. Isso evitará que seus
endereços candidatos sejam publicados na DHT, o que irá aumentar a
privacidade e segurança da solução.
O mecanismo de pontes desenvolvido permite adaptar a conexão e
comunicação de sistemas distribuídos “tradicionais” para permitir a
travessia de NAT. Ele também pode ser usado para criar “túneis” entre
servidores e clientes TCP ou UDP, como é utilizado com o Âmbar, para
permitir a travessia de NAT. Esses túneis permitem, a princípio, que
qualquer sistema distribuído TCP/IP seja adaptado para se conectar através
do protocolo utilizado na biblioteca, e.g. ICE. Entretanto, alguns protocolos a
nível de aplicação podem não se adaptar facilmente. Em especial, aqueles
que transmitam o próprio endereço através da conexão, e.g. Bittorrent.
Outros casos também podem ser identificados. O protocolo HTTP, por
exemplo, utiliza um cabeçalho “Host”, que o cliente envia com o hostname do
servidor a qual ele está se conectando. Esse cabeçalho é utilizado por alguns
servidores para permitir que vários hosts compartilhem o mesmo endereço
IP. Dessa forma, ao utilizar o mecanismo de pontes, o cliente enviará como
host o endereço que ele utilizou para se conectar a ponte, que não será
114
reconhecido pelo servidor.
Vale destacar que o mecanismo de pontes, e a biblioteca como um
todo, não modificam aspectos arquiteturais das aplicações, eles lidam
apenas com os aspectos de conectividade. Assim, uma aplicação cliente
servidor, por exemplo, não passará a ser peertopeer através do uso desse
mecanismo. Entretanto, ele possibilita, por exemplo, que uma aplicação
como essa realize a travessia de NAT sem precisar de alterações invasivas.
115
5 Conclusão
Nesse trabalho, realizamos o estudo de desafios e técnicas
relacionados à construção de sistemas descentralizados, e aplicamos essas
técnicas para descentralizar a conexão entre clientes e servidores do Âmbar,
uma plataforma desenvolvida, em trabalhos anteriores, para permitir o uso e
manutenção de fotomemórias. Para isso, desenvolvemos a Warptopeer,
uma biblioteca modular e extensível para permitir a conexão e comunicação
de forma descentralizada entre pares de nós em redes IP.
5.1 Contribuições
Nesse trabalho fizemos o levantamento de desafios e soluções para o
desenvolvimento de sistemas descentralizados em duas principais áreas: a
conectividade entre nós e o uso de identidades descentralizadas.
A partir desses desafios e soluções, foi desenvolvida a biblioteca Warp
topeer para facilitar a conexão de sistemas distribuídos de forma
descentralizada. A biblioteca provê um conjunto de abstrações e um design
modular que permitem a adoção de diferentes tecnologias e implementações
para o estabelecimento de conexões e oferta de serviços. Um conjunto de
implementações foi definido para essas abstrações que permitem realizar a
travessia de NAT e estabelecer conexões de forma descentralizada.
A biblioteca inclui também um mecanismo de identidades que permite
identificar serviços de forma segura e persistente; e um mecanismo de
“pontes” que permite a integração de sistemas distribuídos tradicionais com
as soluções desenvolvidas na biblioteca, bem como uma forma de
tunelamento para permitir a travessia de conexões TCP/IP. As
funcionalidades da biblioteca são expostas através de uma interface simples
que facilita o seu uso e entendimento.
Descrevemos também a aplicação da Warptopeer no Âmbar, através
do mecanismo de pontes, para permitir prover a conexão entre aplicações
116
cliente e servidores Âmbar de forma descentralizada e através de NAT.
5.2 Limitações
Algumas limitações podem ser identificadas para o trabalho
desenvolvido. Uma delas é a ausência de uma avaliação da biblioteca como
um todo e de sua integração com o Âmbar. Embora testes automatizados
tenham sido utilizados para guiar o desenvolvimento da biblioteca, aplicando
a metodologia de BDD39 (Behaviour Driven Development), avaliações ainda
são necessárias para verificar a eficácia da biblioteca, e da sua integração
com o Âmbar, em contextos reais. Aspectos que podem ser avaliados
incluem a facilidade de uso, do ponto de vista dos desenvolvedores para a
biblioteca e do ponto de vista do usuários para o Âmbar; a eficácia da
travessia de NAT sobre diferentes tipos de NATs; o desempenho e a
escalabilidade da solução.
Outra limitação está no uso de uma identidade compartilhada entre
múltiplos dispositivos. Isto é, como a identidade de um peer ou serviço é
independente do dispositivo ou processo em que ele é executado, se uma
mesma identidade for utilizada por mais de um dispositivo ou processo para
oferecer um mesmo serviço simultaneamente, os clientes não poderão
determinar com qual instância do serviço irão se conectar.
Outro aspecto relacionado ao uso de identidades descentralizadas,
está na interoperabilidade dos algoritmos de criptografia empregados. Como
existem diferentes tipos de algoritmos, é preciso prover meios para que os
pares identifiquem quais algoritmos estão sendo utilizados e comuniquem
quais algoritmos são suportados por eles.
Quanto ao mecanismo de pontes desenvolvido, identificamos algumas
limitações quanto ao suporte de protocolos a nível de aplicação,
performance e confiabilidade. Como as pontes foram projetadas para ser
independentes de um protocolo de aplicação específico, alguns protocolos
podem não operar bem sobre ela, por exemplo, aqueles que dependam de
informações sobre os endereços dos pares que se comunicam. Além disso,39 dannorth.net/introducing-bdd
117
esses protocolos podem sofrer de problemas de performance. Tanto em
virtude do overhead introduzido pelas pontes, mas em especial nos
protocolos que criam um grande conjunto de conexões de curta duração
(como HTTP), devido ao overhead do processo de conexão.
5.3 Trabalhos Futuros
Trabalhos futuros podem ser desenvolvidos para tratar das limitações
apontadas e evoluir a biblioteca. É possível expandir a Warp2p para realizar
a descoberta de serviços em nível local, através de soluções como mDNS e
DNSSD. Podemos também expandir o uso da DHT para prover maior
flexibilidade na descoberta de serviços. Ela poderia ser utilizada, por
exemplo, para localizar serviços de um mesmo tipo ou de um mesmo peer.
Além disso, a biblioteca poderia permitir o uso de múltiplos tipos de
conectores, para aumentar as possibilidades de conexão. O mecanismo de
identidade poderia ser expandido para permitir seu uso na autenticação de
clientes.
Outros trabalhos podem ser realizados para aumentar a
descentralização da plataforma Âmbar e lidar melhor com os desafios
identificados para suporte a fotomemórias. A plataforma poderia ser
adaptada, por exemplo, para permitir a troca de dados entre servidores
Âmbar, criando uma rede federada, de modo a facilitar a migração de dados
entre dispositivos. Outras soluções poderiam ser utilizadas para permitir
descentralizar os dados do sistema, provendo a identificação e tratamento de
conflitos, bem como a replicação de dados conforme necessário. Uso de
identidades descentralizadas poderia simplificar a autenticação de clientes, e
prover a migração de dados entre dispositivos. Além disso, novos clientes
podem ser desenvolvidos para atender a diferentes necessidades e permitir o
uso do sistema em diferentes plataformas.
Outros estudos podem também ser feitos sobre o desenvolvimento de
sistemas descentralizados. É possível estudar e aplicar soluções para outros
desafios identificados, como o armazenamento descentralizado de dados e o
118
estabelecimento da confiança entre pares. Seria interessante também
analisar o impacto de sistemas descentralizados sobre as áreas da
engenharia de software, como o desenvolvimento de técnicas para testar
esse tipo de sistema, ou identificar o impacto de arquiteturas
descentralizadas na construção de interfaces de usuário.
119
Referências
AUDET, Ed. F.; JENNINGS, C. RFC 4787 – Network Address Translation
(NAT) Behavioral Requirements for Unicast UDP. an. 2007. Disponível em:
<https://tools.ietf.org/html/rfc4787>.
ANTONOPOULOS, Andreas M. Mastering Bitcoin. 2015. Oreilly.
CABELLO, F.; FRANCO, M. G.; HACHÉ, A. The social web beyond “walled
gardens”: interoperability, federation and the case of Lorea/N1.
PsychNology Journal. 11(1), 43 – 65. 2013. Disponível em:
<http://www.psychnology.org/File/PNJ11(1)/PSYCHNOLOGY_JOURNAL_11
_1_CABELLO.pdf >.
CHESHIRE, Stuart. Zero Configuration Network: The Definitive Guide.
Sebastopol: O'reilly, 2006.
CHESHIRE, S.; KROCHMAL, M. RFC 6762 – Multicast DNS. Fev. 2013.
Disponível em: <https://tools.ietf.org/html/rfc6762>. Acesso em 16 nov.
2017.
CHESHIRE, S.; KROCHMAL, M. RFC 6763 DNSBased Service Discovery.
Fev. 2013. Disponível em: <https://tools.ietf.org/html/rfc6763>.
COHEN, Bram. The BitTorrent Protocol Specification. Jan2008. Disponível
em: <bittorrent.org/beps/bep_0003.html>
COSKUN, Vedat; OZDENIZCI, Busra; OK, Kerem. A Survey on Near Field
Communication (NFC) Technology. Wireless Personal Communications. v.71,
n.3, p. 22592294. ago. 2013. Disponível em:
<http://dx.doi.org/10.1007/s1127701209355>.
FORD, B.; SRISURESH, P.; KEGEL, D. Peertopeer communication across
network address translators. In: 2005 USENIX Annual Technical Conference.
Usenix Association, 2005. p. 179–192. Disponível em:
<https://www.usenix.org/legacy/event/usenix05/tech/general/full_papers
/ford/ford.pdf>.
120
FORUM UPnP. UPnP Device Architecture 2.0. Disponível em
<https://web.archive.org/web/20151107123618/http://upnp.org/specs/ar
ch/UPnParchDeviceArchitecturev2.0.pdf > . Acesso em 14 nov. 2017
HOUTVEN, Laurens Van. Crypto101. 20132017. Disponível em:
<https://www.crypto101.io/>.
HU, Zhou. NAT Traversal Techniques and PeertoPeer Applications. In:
HUT T110.551 Seminar on Internetworking, Apr. 2005. Disponível em:
<http://www.tml.tkk.fi/Publications/C/18/>.
HUITEMA, C. RFC 4380 – Teredo: Tunneling IPv6 over UDP through Network
Address Translations (NATs). Fev. 2006. Disponível em:
<https://tools.ietf.org/html/rfc4380>.
IRVINE, David. DHTbased NAT Traversal. Disponível em:
<https://github.com/maidsafe/MaidSafe/wiki/unpublished_papers/DHTba
sedNATTraversal.pdf?raw=true>. Acesso em: 16 nov. 2017.
LEVIN, Michal. Designing MultiDevice Experiences. Sebastopol: O’reilly
Media, 2014.
LINDLEY, Siân E.; DURRANT, Abigail; KIRK, David; TAYLOR, Alex.
Collocated social practices surrounding photos. International Journal of
HumanComputer Studies. v.67. i.12. p. 9951004. dez. 2009.
DOI=http://dx.doi.org/10.1016/j.ijhcs.2009.08.004
KEPHART, Jeffrey O.; CHESS David M. The vision of autonomic computing,
in Computer, vol. 36, no. 1, pp. 4150, Jan 2003
DOI=https://dx.doi.org/10.1109/MC.2003.1160055
MAHY, R.; MATTHEWS, P.; ROSENBERG, J. RFC 5766 Traversal Using
Relays around NAT (TURN): Relay Extensions to Session Traversal Utilities for
NAT (STUN). Abr. 2010. Disponível em:
<https://tools.ietf.org/html/rfc5766>.
MASSÉ, Mark. Identifier Design with URIs. In: MASSÉ, Mark. REST API
Design Rulebook. Sebastopol: O’reilly Media, 2012. p. 1421.
MESHKOVA, Elena. Et al. A survey on resource discovery mechanisms,
121
peertopeer and service discovery frameworks. Computer Networks, [s.l.],
v. 52, n. 11, p.20972128, 8 ago. 2008.
DOI=10.1016/j.comnet.2008.03.006. Disponível em:
<http://www.sciencedirect.com/science/article/pii/S138912860800100X>.
Acesso em: 16 nov. 2017.
MEYE, Pierre Obame. NAT Traversal and DHT transmission of H264 stream
on P2P networks. 2011. 42. f. Dissertação (Mestrado) – Laboratoire Bordelais
de Recherche em Informatique. Université Bordeaux 1 Siences Technologies.
Disponível em: <http://citeseerx.ist.psu.edu/viewdoc/download?
doi=10.1.1.436.4655&rep=rep1&type=pdf>.
MORI, Kinji. Autonomous decentralized systems: Concept, data field
architecture and future trends. In: Proceedings of International Symposium
on Autonomous Decentralized Systems (ISAD 93). Kawasaki, 1993, pp. 28
34. DOI=https://dx.doi.org/10.1109/ISADS.1993.262725
MÜLLER, Andreas; CARLE, George. Behavior and classification of NAT
Devices. IEEE Network Magazine. v.22, n.5, set.out. 2008. Disponível em:
<http://ieeexplore.ieee.org/document/4626227/?reload=true>.
NAMECOIN. FAQ. Disponível em: <https://namecoin.org/docs/faq>
NETFLIX. DIAL: DIscovery And Launch protocol specification, version 2.1.
Disponível em: <http://www.dialmultiscreen.org/dialprotocol
specification>. Acesso em 16 nov. 2017.
NEUSTAEDTER, Carman; FEDOROVSKAYA, Elena. Understanding and
Improving Flow in Digital Photo Ecosystems. In: Proceedings of Graphics
Interface Conference, 09., 2009, Kelowna, British Columbia, Canada.
Toronto: Canadian Information Processing Society, 2009. p. 191 198.
Disponível em: <http://dl.acm.org/citation.cfm?id=1555880.1555922>.
Acesso em: 27 jul. 2015.
OUALHA, Nouha; ROUDIER, Yves. Trust Establishment. In: ___. PeertoPeer
Storage: Security and Protocols. New York: Nova Science Publishers, Inc,
2010. p. 711.
122
PERRIG, Adrian; SONG, Dawn. Hash Visualization: a New Technique to
improve RealWorld Security. In: International Workshop on Cryptographic
Techniques and ECommerce. 1999. p 131138.
RAHMAN, M. Ataur; WILSON, Max L.. Exploring Opportunities to Facilitate
Serendipity in Search. In: Proceedings of SIGIR Conference On Research and
Development in Information Retrieval, 38., 2015. Santiago. New York: Acm,
2015. p. 939 – 942. DOI=http://dx.doi.org/10.1145/2766462.2767783.
RAVAL, Siraj. Decentralized Applications. Sebastopol: O’Reilly Media, 2016.
ROSENBERG, J.; MAHY, R.; MATTHEWS, P.; WING, D. RFC 5389 Session
Traversal Utilities for NAT (STUN). Out. 2008. Disponível em:
<https://tools.ietf.org/html/rfc5389>.
ROWLAND, Claire. CrossDevice Interactions and Interusability. In:
ROWLAND, Claire et al. Designing Connected Products: UX for the Consumer
Internet of Things. Sebastopol: O'reilly Media, 2015. Cap. 9. p. 337380.
SCHREINER, Mario. et al. 2015. Connichiwa: A Framework for CrossDevice
Web Applications. In: Proceedings of 33rd Annual ACM Conference Extended
Abstracts on Human Factors in Computing Systems (CHI EA '15). ACM, New
York, NY, USA, 21632168.
DOI=http://dx.doi.org/10.1145/2702613.2732909.
SHELBY, Z.; HARTKE, K.; BORMANN, C. RFC 7252 – The Constrained
Application Protocol (CoAP). Disponível em
<https://tools.ietf.org/html/rfc7252>. Acesso em 16 nov. 2017.
SRISURESH, P.; FORD, B.; KEGEL, D. RFC 5128 – State of PeertoPeer (P2P)
Communication across Network Address Translators (NATs). Mar. 2008.
Disponível em: <https://tools.ietf.org/html/rfc5128>.
SRISURESH, P.; HOLDREGE, M. RFC 2663 – IP Network Address Translator
(NAT) Terminology and Considerations. Ago. 1999. Disponível em:
<https://tools.ietf.org/html/rfc2663>.
STIEGLER, Marc. An introduction to petname systems. 2005 (atualizado em
Junho 2010). Disponível em:
123
<http://www.skyhunter.com/marcs/petnames/IntroPetNames.html>
TANENBAUM, Andrews S.; STEEN, Maarten van. Distributed Systems:
Principles and Paradigms. 2. ed. London, UK: Pearsons, 2016.
TIEU, Jimmy; YE, Sihan. WiFi Direct Services: Design and Investigation of
an Emerging Wireless Technology. 2014. 73. f. Dissertação (Mestrado) –
Department of Eletrical and Information Technology of Lund University,
Lund, Suécia, 2014. Disponível em: <http://www.eit.lth.se/index.php?
gpuid=288&L=1&eauid=818>.
VAN DIJCK, J.. Digital photography: communication, identity, memory.
Visual Communication, SAGE Publications. [s.l.], v. 7, n. 1, p.5776, 1 fev.
2008. DOI=http://dx.doi.org/10.1177/1470357207084865
WACHS, M; SCHANZENBACH, M; GROTHOFF, C. A CensorshipResistant,
PrivacyEnhancing and Fully Decentralized Name System. International
Conference on Cryptology and Network Security (CANS). Springer Verlag.
2014. Disponível em: <https://gnunet.org/gnspaper>.
WANG, Yufeng; et. al. Devicetodevice based proximity services. Boca Ratón:
CRC Press.
WHITTAKER, Steve; BERGMAN, Ofer; CLOUGH, Paul. Easy on that trigger
dad: a study of long term family photo retrieval. Personal and Ubiquitous
Computing, [s.l.], v. 14, n. 1, p.3143, 10 mar. 2009. Springer Science +
Business Media. DOI=http://dx.doi.org/10.1007/s0077900902187.
WIFI ALLIANCE. WiFi PeertoPeer Services Technical Specification. V1.1.
Texas. U.S.A. 2014. Disponível em: <https://www.wifi.org/downloads
registeredguest/WiFi_Peerto
Peer_Services_Technical_Spec_Package_v1.1.zip/29561>.
WOLTERS, Maria K. et al. Personal Photo Preservation for the Smartphone
Generation. In: Proceedings of 33rd Annual Acm Conference Extended
Abstracts On Human Factors In Computing Systems Chi Ea '15. Seoul:
Association for Computing Machinery (ACM), p.15491554, abr. 2015. DOI=
http://dx.doi.org/10.1145/2702613.2732793.
124
XINXING,Zhang. ZHIHONG ,Tian. LUCHEN, Zhang. A Measurement Study
on Mainline DHT and Magnet Link. In: 2016 IEEE First International
Conference on Data Science in Cyberspace (DSC). Changsha, China: IEEE,
2016. Disponível em: <http://ieeexplore.ieee.org/document/7866102/>.
YUQIONG Xu. et al. 2013. TaskShadowW: NFCtriggered migration of web
browsing across personal devices. In: Proceedings of 2013 ACM conference
on Pervasive and ubiquitous computing adjunct publication (UbiComp '13
Adjunct). ACM, New York, NY, USA, 99102.
DOI=http://dx.doi.org/10.1145/2494091.2494119.
Top Related