UNIVERSIDADE FEDERAL DE SANTA CATARINA
JNC MOBILE – SISTEMA DE ACESSO REMOTO PARA
DISPOSITIVOS MÓVEIS
Andrei Luciano Krause
Rafael Augusto da Silva
Florianópolis – SC
2005/1
UNIVERSIDADE FEDERAL DE SANTA CATARINA
DEPARTAMENTO DE INFORMÁTICA E ESTATÍSTICA
CURSO DE CIÊNCIAS DA COMPUTAÇÃO
JNC MOBILE – SISTEMA DE ACESSO REMOTO PARA
DISPOSITIVOS MÓVEIS
Andrei Luciano Krause
Rafael Augusto da Silva
Trabalho de conclusão de curso
apresentado como parte dos
requisitos para a obtenção do grau
de Bacharel em Ciências da
Computação.
Florianópolis – SC
2005/1
Andrei Luciano Krause
Rafael Augusto da Silva
JNC MOBILE – SISTEMA DE ACESSO REMOTO PARA
DISPOSITIVOS MÓVEIS
Trabalho de conclusão de curso apresentado como parte dos requisitos
para a obtenção do grau de Bacharel em Ciências da Computação.
Orientador: Prof. Dr. José Eduardo De Lucca
Banca examinadora
Prof. MSc. Fernando Augusto da Silva Cruz
Prof. Dr. Mário Antônio Ribeiro Dantas
AGRADECIMENTOS
Agradeço aos meus pais, à minha noiva Vanessa e aos meus amigos Rafael
Augusto da Silva e Augusto Boal. Todos foram fundamentais.
Andrei Luciano Krause
Aos meus pais pelo incentivo. Ao professor De Lucca pela confiança e apoio. Ao
amigo Andrei pela grande parceria. Em especial à minha esposa Renata, pelo
auxílio, compreensão e companheirismo. Muito obrigado!
Rafael Augusto da Silva
iii
RESUMO
Os dispositivos móveis figuram atualmente no mercado como mercadorias em franca
expansão. Desta forma, é necessário que os serviços oferecidos por estes
aparelhos, sejam cada vez mais de excelência, proporcionando o máximo de
utilidade aos usuários. O objetivo desta pesquisa é justamente apresentar um
software capaz de oferecer o poder de processamento de uma estação de trabalho
com a praticidade, mobilidade e conectividade dos dispositivos móveis como
aparelhos celulares. A ferramenta neste documento apresentada, possibilita o
acesso remoto de um computador através de um simples telefone celular,
oferecendo ao seu usuário, a experiência de utilizar softwares disponíveis apenas
para máquinas com processamento mais robusto. Conheça também as ferramentas
que possibilitam a concepção deste novo paradigma de programação e criação de
softwares.
PALAVRAS-CHAVE: Computação Móvel. Computação Remota. J2ME. Dispositivos
Móveis. VNC.
iv
ABSTRACT
The mobile devices appear currently in the market as merchandises in frank
expansion. Of this form, it is necessary that the services offered for these devices,
are each time more than excellency, providing the maximum of utility to the users.
The objective of this research is exactly to present a software capable to offer the
power of processing of a workstation with the practice, mobility and connectivity of
the mobile devices as cell phones. The tool in this presented document, makes
possible the remote access of a computer through a simple cellular telephone,
offering its user, the experience to use softwares available only for machines with
more robust processing. It also knows the tools that make possible the conception of
this new paradigm of programming and software development.
KEYWORDS: Mobile computation. Remote computation. J2ME. Móbile devices.
VNC.
v
LISTA DE FIGURAS
Figura 1 – Plataforma J2ME..................................................................................
Figura 2 – Arquitetura Eclipse ...............................................................................
Figura 3 – IDE AJDT do Eclipse............................................................................
Figura 4 – Acesso remoto com VNC .....................................................................
Figura 5 – Acesso remoto através de dispositivo móvel .......................................
Figura 6 – Acesso remoto através de dispositivo móvel com servidor bridge .......
Figura 7 – Compactação da imagem enviada ao cliente.......................................
Figura 8 – Programa servidor................................................................................
Figura 9 – Programa cliente – Celular...................................................................
Figura 10 – Teclas do celular para o servidor VNC...............................................
Figura 11 – Tela do VNC para celular – módulo PC .............................................
Figura 12 – Telas do VNC para celular – módulo J2ME – Celular ........................
Figura 13 – Telas do VNC para celular – módulo J2ME – Celular ........................
Figura 14 – Telas do VNC para celular – módulo J2ME – Celular ........................
Figura 15 – Telas do VNC para celular – módulo J2ME – Celular ........................
Figura 16 – Classes da aplicação cliente ..............................................................
Figura 17 – Classes da aplicação servidor............................................................
Figura 18 – Classes da aplicação servidor............................................................
Figura 19 – Diagrama de seqüência UML .............................................................
Figura 20 – Ambiente de programação .................................................................
vi
19
23
26
27
29
30
30
35
36
38
38
39
40
40
41
42
43
44
45
46
SUMÁRIO
RESUMO .............................................................................................. iv
ABSTRACT .......................................................................................... v
LISTA DE FIGURAS ............................................................................ vi
1 INTRODUÇÃO................................................................................
1.1 Delimitação do tema ...................................................................
1.2 Objetivo geral ..............................................................................
1.3 Objetivos específicos .................................................................
1.4 Justificativa..................................................................................
1.5 Problema ......................................................................................
1.6 Metodologia .................................................................................
09
09
10
10
11
11
12
2 DISPOSITIVOS, TECNOLOGIAS E SISTEMAS MÓVEIS.............
2.1 Computação móvel .....................................................................
2.2 Dispositivos móveis....................................................................
2.2.1 Notebooks, laptops e palmtops ...................................................
2.2.2 PDAs (Personal Digital Assistants) .............................................
2.2.3 Celulares .....................................................................................
2.3 Protocolos de comunicação sem fio .........................................
2.4 Java 2 Micro Edition – J2ME ......................................................
2.4.1 Arquitetura J2ME.........................................................................
2.4.2 Configurações .............................................................................
2.4.3 Perfis ...........................................................................................
2.4.4 Pacotes .......................................................................................
2.5 Eclipse..........................................................................................
2.5.1 Plataforma Eclipse.......................................................................
2.5.2 Arquitetura ...................................................................................
2.5.3 IDEs.............................................................................................
2.6 Virtual Network Computing – VNC ............................................
13
13
14
14
15
16
17
18
18
19
20
21
21
22
23
25
26
vii
3 JNC MOBILE - SISTEMA DE ACESSO REMOTO PARA
DISPOSITIVOS MÓVEIS................................................................
3.1 Descrição do sistema .................................................................
3.2 RFB Protocol ...............................................................................
3.2.1 Entrada ........................................................................................
3.2.2 Representação dos pixels ...........................................................
3.2.3 Raw Encoding .............................................................................
3.2.4 Copy Rectangle Encoding ...........................................................
3.2.5 Mensagens de protocolo .............................................................
3.2.6 Diretivas do protocolo auxiliar .....................................................
3.3 Desenvolvimento da aplicação ..................................................
3.3.1 Programa servidor .......................................................................
3.3.2 Programa cliente .........................................................................
3.3.3 Telas do sistema ........................................................................
3.3.4 Diagrama de classes ...................................................................
3.3.5 Diagrama de seqüência UML ......................................................
3.3.6 Ambiente de desenvolvimento ...................................................
29
29
31
31
32
32
32
32
33
34
35
36
37
41
45
45
4 TRABALHOS FUTUROS ............................................................... 47
5 CONSIDERAÇÕES FINAIS............................................................ 49
REFERÊNCIAS .................................................................................... 51
APÊNDICES......................................................................................... 53
APÊNDICE A – Código Fonte da Aplicação Cliente ........................ 54
APÊNDICE B – Código Fonte da Aplicação Servidor...................... 67
APÊNDICE C – Artigo ......................................................................... 101
viii
9
1 INTRODUÇÃO
Nesta pesquisa o leitor irá realizar sua leitura em quatro capítulos. O primeiro
capítulo tem por motivação apresentar os objetivos da pesquisa, delimitar o tema por
esta proposto, justificar e apresentar a metodologia empregada neste estudo.
Dando continuidade ao documento, tem-se o segundo capítulo, que aborda
as questões referentes aos dispositivos móveis escolhidos, a computação móvel e
as tecnologias e ferramentas empregadas para o desenvolvimento da pesquisa.
Assim, é chegada a hora de apresentar o desenvolvimento da aplicação,
como se deu o processo de implementação e uma explicação mais apurada de seu
funcionamento.
Por fim, o quarto capítulo, onde são apresentados alguns trabalhos futuros
derivados desta pesquisa.
1.1 Delimitação do tema
Com a popularização dos dispositivos móveis, um novo paradigma de
serviços foi criado. Assim, para atender e suportar estes serviços os dispositivos
móveis, que têm na forma dos telefones celulares seus mais evidentes
representantes, sofreram transformações para poder corresponder aos anseios
gerados por estes novos serviços. Aparelhos que eram utilizados apenas para fazer
ligações, passaram rapidamente a figurar como agendas eletrônicas, câmeras
fotográficas digitais, gravadores de som digital, e mais recentemente, no Brasil,
computadores de mão.
10
Mesmo com estas funcionalidades sendo oferecidas, o poder computacional
destes dispositivos ainda não proporciona uma experiência muito confortável,
limitando os serviços à sua capacidade reduzida de memória e poder de
processamento.
Uma maneira de oferecer poder computacional e proporcionar acesso a
serviços exclusivos das estações de trabalho é o acesso remoto via dispositivos
móveis a estações de trabalho. Com o poder de mobilidade e conectividade dos
dispositivos móveis, aliados a inovadora tecnologia J2ME da Sun, esta pesquisa visa
apresentar uma solução capaz de conectar remotamente uma estação de trabalho a
um aparelho móvel.
1.2 Objetivo geral
Desenvolver um sistema de acesso remoto para dispositivos móveis possibilitando o
gerenciamento de estações de trabalho à distância.
1.3 Objetivos específicos
• Identificar a melhor linguagem de programação para produção de sistemas para
dispositivos móveis.
• Definir um tipo de dispositivo móvel para desenvolvimento da aplicação.
• Criar um software cliente para dispositivos móveis capaz de gerenciar uma
estação de trabalho a partir de um software servidor.
11
1.4 Justificativa
Como os dispositivos móveis atuais não proporcionam poder computacional
equiparado as estações de trabalho, e a facilidade de mobilidade e conectividade
proporcionada por aparelhos móveis é fato, a motivação desta pesquisa tem seu
alicerce em tentar unir o poder computacional das estações de trabalho, com a
facilidade de acesso a serviços dos dispositivos móveis. Para tal, é apresentado
como solução para este problema, o desenvolvimento de uma aplicação cliente –
servidor, onde um dispositivo móvel realiza uma conexão remota a uma estação de
trabalho.
1.5 Problema
Com o crescimento do número de dispositivos móveis no cotidiano da
sociedade, e do incremento de funcionalidades destes aparelhos, os anseios por
serviços mais robustos e específicos tornam-se necessários.
Um relevante serviço para profissionais da área de TI (Tecnologia e
Informação) seria a capacidade de gerenciarem remotamente diferentes dispositivos
fixos, como estações de trabalho a partir de seus celulares, PDAs (Personal Digital
Assistants), entre outros.
Assim, para esta pesquisa defini-se o seguinte questionamento: como
desenvolver um sistema de acesso remoto para dispositivos móveis possibilitando o
gerenciamento de estações de trabalho à distância?
12
1.6 Metodologia
Esta pesquisa, segundo sua natureza, classifica-se como aplicada, pois
objetiva gerar conhecimentos para aplicação prática dirigidos à solução de
problemas específicos. Envolve verdades e interesses locais. (GIL, 1991)
Quanto a abordagem do problema a pesquisa é caracterizada como
qualitativa que, segundo Gil (1991, p. 41) “possui uma relação dinâmica entre o
mundo real e o sujeito, isto é, um vínculo indissociável entre o mundo objetivo e a
subjetividade do sujeito que não pode ser traduzido em números”. A interpretação
dos fenômenos e a atribuição dos significados são básicos no processo de pesquisa
qualitativa.
De acordo com os objetivos a pesquisa é considerada explicativa, pois visa
identificar os fatores que determinam ou contribuem para a ocorrência dos
fenômenos. “Aprofunda o conhecimento da realidade porque explica arazão, o
‘porquê’ das coisas” (GIL, 1991, p. 42)
Por fim, do ponto de vista dos procedimentos técnicos, a pesquisa é de
cunho: bibliográfico, elaborada a partir de material já publicado (sites e livros);
documental, a partir de materiais que não receberam tratamento analítico (Manual
de dispositivos móveis); e experimental, através da determinação do objeto de
estudo, da seleção das variáveis, das formas de controle e da observação dos
efeitos produzidos. (GIL, 1991)
13
2 DISPOSITIVOS, TECNOLOGIAS E SISTEMAS MÓVEIS
2.1 Computação móvel
Em decorrência dos anos 90, o mercado foi invadido por um volume
crescente de desenvolvimento em áreas de tecnologia celular móvel, redes sem fios
e comunicação via satélites. De acordo com a popularização tomada por estas
tecnologias, o acesso a informações remotas cresce vertiginosamente através de
novos serviços oferecidos aos usuários.
A evolução e popularização de dispositivos móveis como celulares,
notebooks, PDAs (Personal Digital Assistants), dispositivos dedicados móveis (GPS
– Global Positional System), entre outros, torna possível a determinação do seguinte
conceito: “Computação móvel pode ser representada como um novo paradigma
computacional que permite que usuários desse ambiente tenham acesso a serviços
independentemente de sua localização, podendo inclusive, estar em movimento.”
(FIGUEIREDO; NAKAMURA, 2003, p.16)
As palavras chaves para computação móvel são: processamento, mobilidade
e comunicação.
De acordo com Mateus e Loureiro (1998 apud FIGUEIREDO; NAKAMURA,
2003, p.17) a computação móvel é denominada a quarta revolução da computação,
logo após o advento dos grandes centros de processamento na década de sessenta,
o surgimento dos terminais uma década mais tarde, e as redes de computadores
nos anos oitenta. Ampliando o conceito de computação distribuída, graças a
comunicação sem fio, que elimina a necessidade do usuário estar conectado à uma
infra-estrutura estática.
14
2.2 Dispositivos móveis
Para estar de acordo com a definição de computação móvel apresentada no
capítulo anterior, os dispositivos móveis devem possuir tamanho reduzido bem como
capacidade de trocar informações via rede, realizar processamento, ser de fácil
transporte e não fazer uso de cabos tanto para conectar-se à rede de dados como a
um suporte de energia.
Os dispositivos mais utilizados para o propósito de computação móvel são:
• Notebooks, Laptos, Palmtops;
• PDAs (Personal Digital Assistants);
• Celulares (Smartphones).
Segue abaixo um breve discurso sobre estes dispositivos.
2.2.1 Notebooks, laptops e palmtops
Equipamentos como notebooks e laptops podem ser considerados
verdadeiras estações de trabalho móvel, pois com o avanço tecnológico no processo
de miniaturização de componentes, hoje é possível encontrar estes aparelhos com
capacidades semelhantes e em alguns casos superiores ao desempenho de
estações de trabalho fixas. E com um forte aliado, proporções de tamanho bem
inferiores a um desktop completo.
Mesmo com recursos comparáveis ao de uma estação de trabalho comum,
notebooks e laptops ainda não são a solução de mobilidade ideal, pois necessitam
quase sempre de uma base onde possam ser apoiados para operarem, possuem
baterias com duração pequena (aproximadamente três horas de uso ininterrupto), o
que faz com que o usuário esteja sempre em busca de um acesso a energia elétrica.
15
Já os Palmtops, resolvem alguns destes empecilhos, por serem semelhantes
aos notebooks e laptops, entretanto, mesmo assim, não correspondem a uma
experiência
móvel
confortável.
Limitando
ainda
mais
as
capacidades
de
processamento e armazenamento, bem como dificultando os métodos de entrada e
saída de dados.
2.2.2 PDAs (Personal Digital Assistants)
Um PDA típico, pode assumir as funções de um telefone celular, aparelho de
fax, Web browser e organizador pessoal. São conhecidos também como handhelds
(dispositivos de mão). Infelizmente devido ao tamanho reduzido, suas características
de processamento e armazenamento ficam comprometidas, assim como suas
opções de entrada e saída nada confortáveis (os dados são inseridos com o auxílio
de uma caneta e um software para reconhecimento de escrita, por exemplo).
Estes aparelhos têm como objetivo real, substituir agendas eletrônicas,
oferecendo recursos mais avançados para este propósito e agregar serviços de
telefonia, fax, Internet, em um único dispositivo. Seu uso também pode ser
observado em linhas de montagem ou restaurantes, onde simples softwares para
conferência e controle podem ser facilmente utilizados para automatizar serviços em
um ambiente onde não há espaço físico para suportar uma estação de trabalho.
Imagine um garçom anotando seu pedido em um notebook apoiado sobre os pratos
de sua mesa.
Os PDAs são reconhecidos por proporcionar entretenimento multimídia com
qualidade muito satisfatória, reproduzindo vídeos e áudio, batendo fotos, etc.
As baterias também figuram como problema nestes dispositivos, mas agora
sua duração pode ir de muitas horas até alguns dias.
16
2.2.3 Celulares
Desenvolvidos inicialmente com o único propósito de levar a comunicação
além das barreiras da telefonia fixa convencional, os celulares chegaram para
transpor barreiras e permitir que qualquer indivíduo em qualquer lugar do planeta,
possa comunicar-se com qualquer outro indivíduo em um ponto qualquer do globo.
Entretanto, com o avanço tecnológico e a evolução das gerações da telefonia celular
estes aparelhos adquiriram um novo status no qual passam a figurar como
dispositivos capazes de processamento e armazenamento de dados, principalmente
junto a Internet, conforme tabela 1.
Geração
1G
2G
2,xG
3G
Características
Transmissão
de Dados
Analógica
(AMPS);
Transmissão
Digital de
Dados
(TDMA,
CDMA e
GSM);
Disponibilização
de aplicações
pré-3G
Taxas de
9600bps
Taxas de
9600bps a
14400bps;
Taxas de
até 2Mbps;
Surgimento
de
aplicações
WAP.
Surgimento
de
aplicações
multimídia.
Evolução
CDMA e
GSM;
4G
Elevação
das taxas
de
transmissão
de dados;
Tecnologias
e
aplicações
ainda em
discussão.
Quadro 1 – Gerações da telefonia celular
Fonte: Figueiredo e Nakamura, 2003, p.19
As características e problemas apresentados pelos celulares assemelham-se
com as citadas nos PDAs. Porém, com um revés a mais, a interação com o
dispositivo é ainda maior, limitando-se na maioria dos casos, as teclas do aparelho.
A solução parece ter sido incorporar aos telefones celulares as funções de um PDA,
17
gerando assim um novo dispositivo reconhecido pelo nome de Smartphone. É
apostando no custo reduzido destes aparelhos e nos serviços por eles oferecidos
que procura-se realizar uma experiência móvel de qualidade e de uso satisfatório.
2.3 Protocolos de comunicação sem fio
São duas as principais tecnologias para redes sem fio, que têm sido
utilizadas em soluções de computação móvel, o padrão IEEE 802.11 (redes infraestruturdas) e o padrão Bluetooth (redes AdHoc).
a) IEEE 802.11: O IEEE (Institute of Electrical and Electronics Engineers Inc.) é o
órgão responsável por padronizar as camadas físicas e de enlace para redes sem
fio. Seu padrão, o 802.11 ou Wi-Fi como também é chamado, em sua concepção
original, prevê velocidades de operação de 1 e 2Mbps, já a versão 802.11b,
proporciona velocidades de até 11Mbps, e por fim, a versão 802.11g, sugere
velocidades de até 54Mbps. Mecanismos de autenticação e criptografia são
suportados através do WEP (Wired Equivalent Privacy), entretanto por motivos de
falta de segurança, estuda-se a adoção de uma nova versão, o WPA (Wi-Fi
Protected Access). É a tecnologia ideal para substituir infra-estrutura cabeada.
b) Bluetooth: Padronizado pelo Bluetooth SIG, que é composto por empresas tais
como Lucent, Microsoft, IBM, Intel, Motorola, Toshiba, Nokia e mais de outras
2000 companhias, o Bluetooth é um sistema para comunicações de pequeno
alcance (menos de 10 metros). Surgiu da necessidade de se eliminar cabos de
conexão entre equipamentos. Fazendo uso de micro-rádios embutidos em um
chip, e utilizando uma tecnologia denominada transmissão por salto de freqüência,
é capaz de operar na faixa de freqüência de 2,4 Ghz. Opera no modo “full duplex”,
18
recebe e envia ao mesmo tempo, e possui taxas de transferência de até 1Mbps
com baixo consumo de energia. Promete tornar-se padrão de mercado devido as
possibilidades de aplicação e por ser suportado por dispositivos de diversos
fabricantes.
2.4 Java 2 Micro Edition – J2ME
Basicamente J2ME é um termo que refere-se a uma coleção de APIs e
máquinas virtuais que tornam possível o uso de Java em dispositivos móveis. Com o
J2ME é possível levar ao mundo dos dispositivos móveis, os benefícios da
tecnologia Java, como flexibilidade na interface com o usuário, um modelo de
segurança eficaz, suporte a diferentes tipos de aplicações , entre outros.
A plataforma J2ME está presente na maioria dos dispositivo móveis atuais,
facilitando ao usuário a aquisição de novos serviços e mais inteligentes. Assim, a
plataforma J2ME segue como propenso padrão a ser adotado no desenvolvimento
de aplicações mobile.
2.4.1 Arquitetura J2ME
Toda a arquitetura J2ME define, configurações, perfis e pacotes opcionais,
como elementos de uma aplicação Java completa. Assim, a plataforma é capaz de
atender aos requerimentos de diferentes dispositivos e mercados.
Cada
combinação
destes
elementos
otimiza
a
capacidade
de
processamento, armazenamento e interfaces de entrada e saída para cada
dispositivo particularmente. O resultado é uma plataforma de desenvolvimento Java
comum, capaz de atender a diferentes tipos de equipamentos e fabricantes.
19
Figura 1 – Plataforma J2ME
Fonte: Sun Microsystems, 2005
2.4.2 Configurações
As configurações consistem de uma máquina virtual e de um pequeno
conjunto de classes. Este conjunto provê as funcionalidades básicas de uma faixa
de dispositivos que compartilham características como conexão de rede e
gerenciamento de memória. Existem duas configurações em J2ME:
a) Connected
Limited
configurações.
Device
Desenvolvida
Configuration
para
(CLDC):
dispositivos
com
a
menor
conexões
das
duas
de
rede
20
intermitentes, processadores lentos e memória limitada. Usada em dispositivos
com CPUs de 16 ou 32 bits e com no mínimo de 128KB a 512KB de memória
disponível para suportar a plataforma Java e aplicações associadas. Os
equipamentos que costumam utilizar esta configuração são os telefones celulares,
PDAs e pagers.
b) Connected Device Configuration (CDC): esta configuração é disponibilizada em
dispositivos mais robustos, com CPUs de 32 bits ou mais e com no mínimo 2Mb
de memória disponível. Encontra-se em PDAs de alta perfomance, gateways
residenciais entre outros. Nesta configuração tem-se uma máquina virtual Java
completa, bem como muito mais recursos do J2SE.
2.4.3 Perfis
Para proporcionar uma solução completa, as configurações devem estar
vinculadas a APIs de alto nível, ou a perfis, para ser possível definir o modelo de
ciclo de vida da aplicação, a interface com o usuário e o tipo de acesso a
dispositivos específicos. Assim, tem-se como principais perfis os que seguem:
a) Mobile Information Device Profile (MIDP): desenvolvido para telefones celulares e
PDAs. Oferece o núcleo de funcionalidades requeridas por aplicações móveis,
incluindo interface com usuário, conectividade, armazenamento e gerenciamento
da aplicação. O MIDP em conjunto com o CLDC, representa uma solução
completa que maximiza as capacidades do dispositivo e minimiza o consumo de
memória e energia.
b) Foundation Profile (FP): este é o perfil de mais baixo nível para o CDC. Ele
permite uma implementação do CDC em sistemas embarcados sem o uso de
interface com o usuário. Em caso de necessidade de implementar uma interface
21
com o usuário, este perfil pode ser combinado com outros dois, o Personal Profile
e o Personal Basis Profile.
c) Personal Profile (PP): utilizado em dispositivos que exigem uma GUI completa ou
suporte a applets para internet, como PDAs de alta perfomance e consoles de
vídeo game. Inclui todas as libraries do AWT (Java Abstract Window Toolkit).
d) Personal Basis Profile (PBP): é um subconjunto do perfil Personal Profile. Provê
suporte a aplicações network-connected em dispositivos que suportam gráficos
em nível básico ou que requeiram o uso de ferramentas gráficas específicas.
Exemplos, tv set-top boxes, quiosques de informações e outros.
2.4.4 Pacotes
A plataforma J2ME pode ser estendida combinando-se vários pacotes
opcionais com CLDC ou CDC e seus perfis. Criados para mercados específicos,
vários pacotes apresentam APIs defaults para uso em tecnologias conhecidas e
tecnologias em desenvolvimento ou expansão, como o suporte a Bluetooth, Web
services, etc. Assim, os fabricantes de dispositivos podem inserir em seus produtos
os pacotes necessários para suportar as funcionalidades oferecidas por seus
dispositivos.
2.5 ECLIPSE
Criado pela extinta OTI (Object Technology International), famosa por sua
tecnologia de orientação a objetos para Smalltalk e Java, o Eclipse apresenta um
novo modelo de software open source. Com a aquisição da OTI pela IBM, o
lançamento do Eclipse deu-se com o anúncio da doação de quarenta milhões de
22
dólares (valor estimado da versão 1.0 do Eclipse) da IBM para a comunidade open
source, sob uma licença open source (a CPL). Desta forma, o Eclipse tornou-se um
dos principais exemplos de softwares open source com estrutura de softwares
proprietários. Outros casos que podem ser citados são: Linux, MySQL (MySQL AG),
NetBeans e OpenOffice (Sun), entre outros.
O projeto Eclipse fez com que o modelo “livre+comercial” chegasse a uma
nova ordem de grandeza, pois nunca um software open source obteve tanto
investimento e de forma continuada.
Os objetivos do projeto são sem fins lucrativos, descrevendo um modelo
muito semelhante a iniciativas de organismos responsáveis por padronizações como
a OMG ou a W3C. Entretanto, órgãos como a OMG e o W3C, produzem apenas
especificações, já a Fundação Eclipse cria produtos. Assim, surge uma nova
tendência na evolução do open source.
2.5.1 Plataforma Eclipse
O Eclipse costuma ser visto como apenas uma IDE Java. E efetivamente, é
este papel que presta o principal pacote oferecido pela plataforma, o Eclipse SDK.
Porém, o objetivo real e concreto da plataforma, é oferecer suporte a criação de
diversas ferramentas.
Com um microkernel capaz de gerenciar plug-ins, toda a funcionalidade real
da ferramenta é fornecida por essas extensões. Baseado nesta afirmação, a
plataforma adquire uma arquitetura peculiar, a qual é melhor explorada no item a
seguir.
23
2.5.2 Arquitetura
Os
principais
componentes
da
arquitetura
do
Eclipse
podem
ser
contemplados na figura a seguir.
Figura 2 – Arquitetura Eclipse
Fonte: Java Magazine, 2005
A plataforma é o “coração” dos IDEs. Os plug-ins assinalados em amarelo,
são específicos da linguagem Java, dependentes do JDT o compilador Java utilizado
pelo Eclipse, direta ou indiretamente.
Segue uma breve descrição dos principais componentes da arquitetura:
a) Runtime de plataforma: é o responsável por inicializar e gerenciar plug-ins. É o
programa principal.
b) Workspace: gerente de recursos (arquivos e diretórios). Do ponto de vista do
usuário final, mostra-se como uma estrutura de diretórios que contém os projetos
24
do Eclipse. Cabe ao Workspace então, gerenciar esta estrutura de diretórios,
implementando recursos como marcadores, além de projetos e eventos de
alteração de recursos (que são utilizados pelo componente Team para
manutenção do histórico local e pelos compiladores para compilação incremental).
O uso de GUIs (interfaces gráficas), não é usado em momento algum nestes
processos.
c) SWT e JFace: são de toolkits de GUI. O toolkit principal é o SWT, cabendo ao
JFace, o papel de framework MVC que permite programação de alto nível.
d) Workbench: implementa as entidades básicas de GUI, como a estrutura de
Perspectivas, Views e Editores, menus, caixas de configuração, e outros recursos
genéricos de interfaces gráficas. Oferece suporte a todas as funcionalidades de
GUI do Workspace.
e) Team: realiza o controle de versões e histórico de alterações de recursos. Não
oferece suporte a um gerenciador de versões específico, mas possui subsídios
para que plug-ins possam ser criados para qualquer gerenciador. Estende o
Workspace para gerar versionamento local de recursos, sem utilizar servidor de
repositório.
f) Debug: define a arquitetura, conceitos e suporte GUI fundamentais para
depuração de programas, tais como, processos, breakpoints, visualização de
variáveis, filtros, etc.
g) Help: compõe-se de um servidor e um visualizador de help próprios, que permite
construir help on-line a partir de conteúdo HTML. Recursos como pesquisa,
navegação e indexação também são providos pelo Help.
h) Update: onde ocorre o gerenciamento de atualizações automáticas.
25
2.5.3 IDEs
A plataforma Eclipse oferece diversos IDEs para diferentes tipos de
desenvolvimento. Assim, para construção deste projeto, foi necessário a escolha e
utilização de algumas possibilidades oferecidas pela plataforma. A seguir, segue
uma lista com os principais IDEs e ferramentas oferecidas pelo Eclipse, com
destaque para as utilizadas neste projeto.
a) JDT (Java Development Tooling): é a parte do projeto Eclipse mais conhecida. O
JDT é o IDE para aplicações Java. Possui suporte aos projetos Java, edição e
compilação dos fontes, depuração de aplicações, assistentes para criação de
classes e interfaces e etc. Para a concepção deste projeto foi esta a IDE Eclipse
utilizada.
b) PDE (Plug-in Development Environment): esta IDE suporta a criação de plug-ins
para o Eclipse em Java. Oferece assistentes para criação dos plug-ins, editores
para configuração dos mesmos, deployment, gerador de testes, entre outros.
c) CDT (C/C++ Development Tools): viabiliza a construção de projetos para as
linguagens C/C++. Atualmente esta IDE é voltada para a plataforma Linux e
ferramentas GNU.
d) AJDT (Aspect Development Tools): implementa suporte a Programação Orientada
a Aspectos (AOP).
e) COBOL: como pode-se esperar pelo nome, esta IDE traz suporte a antiga
programação praticada nos mainframes, o COBOL.
Na figura a seguir, é possível se ter uma idéia de como a plataforma Eclipse
apresenta-se graficamente, a imagem traz o IDE AJDT em funcionamento.
26
Figura 3 – IDE AJDT do Eclipse
Fonte: Java Magazine, 2005
2.6 Virtual Network Computing – VNC
O VNC foi criado pelo Laboratório de Pesquisas da Olivetti & Oracle. No ano
de 1999, a AT&T adquiriu o laboratório, e posteriormente em 2002, fechou a divisão
de pesquisas do mesmo. Seu nome deriva de um computador com rede ATM
chamado Videotile, que consistia apenas de um LCD com uma caneta e uma rápida
conexão de rede ATM. Assim o VNC é essencialmente uma versão deste
computador.
Com o VNC, é possível controlar remotamente uma estação de trabalho
apenas com o uso de um simples programa cliente ou visualizador como também é
27
chamado. Outra característica interessante é o fato de não ser necessário que os
dispositivos utilizados (cliente – servidor) sejam do mesmo tipo e/ou possuam
mesmo sistema operacional.
Figura 4 – Acesso remoto com VNC
Fonte: Real VNC, 2005
Um software de controle remoto como o VNC, possui uma gama muito
grande de benefícios, pois torna possível controlar uma estação de trabalho através
de uma rede seja ela fixa ou sem fio, como se o indivíduo estivesse operando
pessoalmente a estação acessada remotamente.
Como destaque de uso pessoal desta ferramenta, pode-se imaginar o
seguinte cenário: auxiliar ou realizar uma tarefa de atualização de software na
estação de trabalho de uma pessoa que mora em um outro país. Com o uso do
VNC, é possível que você mesmo realize a tarefa no computador da pessoa que
28
solicitou auxílio, enquanto esta acompanha todos os passos em frente seu
computador, como se ela mesma estivesse realizando todo o procedimento.
Existem dezenas de implementações deste conceito, utilizando o mesmo
protocolo (RFB - vide seção 3.2 adiante), o que permite a interoperação de clientes e
servidores de versões/origem distintas. São exemplos de implementações do VNC
os seguintes softwares:
a) realVNC [http://www.realvnc.com/]: programa original.
b) tightVNC [http://www.tightvnc.com/]: otimizado para low-bandwidth.
c) tridiaVNC [http://www.tridiavnc.com/]: mais opções de gerenciamento.
d) ultraVNC [http://www.ultravnc.com/]: possui vários extras, transferência de
arquivos, chat, drivers de vídeo, etc.
e) win2VNC [http://sourceforge.net/projects/win2vnc/]: um desktop virtual entre duas
estações de trabalho.
Assim, por constatar as facilidades que tal software proporciona, esta
pesquisa propõe-se à apresentar uma solução cliente para ser embarcada em
dispositivos móveis, para propiciar as facilidades oferecidas pelo VNC com a
liberdade e facilidade de operar-lo através de um equipamento móvel.
29
3 JNC MOBILE - SISTEMA DE ACESSO REMOTO PARA
DISPOSITIVOS MÓVEIS
3.1 Descrição do sistema
O JNC Mobile, tem como proposta, apresentar um software cliente para
dispositivos móveis capaz de controlar remotamente uma estação de trabalho ou
outro dispositivo móvel, que esteja configurado com um servidor VNC e com um
servidor Bridge escrito em Java, que realizará a comunicação entre as aplicações
cliente e servidor VNC.
Figura 5 – Acesso remoto através de dispositivo móvel
Fonte: Elaborada pelos autores, 2005
O dispositivo móvel escolhido para a implementação e testes do software foi
um telefone celular. Ainda, devido a não padronização entre os diferentes
fabricantes de celulares, a Nokia foi escolhida como fabricante para realização dos
testes em aparelhos emulados.
Como o servidor VNC é fornecido apenas em linguagem C++, e todo o
projeto visa o uso da tecnologia Java, e o conhecimento dos desenvolvedores em
C++ não é satisfatório, a solução encontrada foi o desenvolvimento de um servidor
na linguagem Java, onde as requisições do cliente são recepcionadas por este
30
servidor bridge e encaminhadas ao servidor VNC. Desta forma também foi obtida
uma certa liberdade de como os dados devem chegar ao servidor VNC,
possibilitando o tratamento de requisições e desvios de controle por parte do
servidor bridge.
Figura 6 – Acesso remoto através de dispositivo móvel com servidor bridge
Fonte: Elaborada pelos autores, 2005
As requisições recebidas pelo servidor bridge são passadas ao servidor VNC
através do Protocolo RFB (Remote Frame Buffer). Por sua vez, o servidor VNC
retorna ao bridge o status (imagem) do desktop, e este encarrega-se de transmitir a
informação ao dispositivo móvel.
O servidor bridge acumula além da responsabilidade de tradutor entre o
programa cliente e o servidor VNC, a função de compactação da imagem enviada ao
cliente.
Figura 7 – Compactação da imagem enviada ao cliente
Fonte: Elaborada pelos autores, 2005
31
A imagem fornecida pelo servidor – PC – é capturada pelo – Bridge – que
verifica as coordenadas que estão sendo requisitadas pelo dispositivo móvel e as
converte para que estas possam ser exibidas na tela. Por exemplo: o celular envia,
após efetuar conexão, comandos de zoom mais e comandos de mudança de
posição da tela, ao receber a requisição, o servidor Bridge captura a tela do PC,
“corta” a parte que o cliente requisitou e redimensiona para o tamanho da tela do
dispositivo móvel.
Assim, conclui-se o processo cliente – servidor bridge – servidor VNC.
3.2 RFB Protocol
O protocolo RFB (Remote Frame Buffer) foi desenvolvido pela AT&T para
ser usado em seu programa de Virtual Networking Computer
(VNC), porém
atualmente, vários outros programas utilizam-se do protocolo RFB para interagir com
servidores VNC.
O princípio básico do protocolo RFB é:
- Desenhe uma imagem a partir das coordenadas 0,0 até as coordenadas x,x.
Para otimizar a tarefa principal que o protocolo RFB se propõe a realizar, é
disponibilizado um conjunto de diretivas que possibilitam configurar o tipo de
codificação e compactação em que a imagem será transmitida e exibida.
3.2.1 Entrada
O protocolo entende que A “Entrada” de dados será baseada em teclado e
mouse de dois botões, portanto, para enviar eventos de teclado e mouse é
necessário que se implemente tal interface.
32
No caso de dispositivos móveis que não possuem estes recursos, é
necessário emulá-los a partir de recursos disponíveis, ou seja, o teclado numérico e
as teclas de direção. Para deixar o software mais compatível com outros dispositivos
móveis, optou-se por não utilizar as teclas de direção, e sim, emulá-las através das
teclas numéricas.
3.2.2 Representação dos pixels
Logo após a autenticação do cliente, o servidor verifica qual o tipo de
codificação será utilizada, para isso o protocolo RFB oferece 5 tipos de codificações:
Raw Encoding, Copy Rectangle Encoding, RRE encoding, CoRRE encoding e
Hextile encoding, porém apenas duas são relevantes para o trabalho em questão.
3.2.3 Raw Encoding
Consiste em escrever linha por linha os pixeis da imagem, é a forma mais
demorada (n x n pixels = n * n operações), porém é a mais simples.
3.2.4 Copy Rectangle Encoding
Desenha apenas as partes da imagem que foram modificadas, por exemplo:
- Redesenhe apenas o retângula x=15, y=15, largura =40, altura=30.
3.2.5 Mensagens de protocolo
O protocolo RFB fornece um sistema de mensagens que permitem os
programas se comunicarem de forma simples e segura, o funcionamento de um
33
programa que se conecta à um servidor VNC consiste em basicamente dois
estágios:
a) Fase de Conexão ou Handshaking: consiste em verificar a versão do protocolo,
autenticação, inicialização do cliente e inicialização do servidor.
b) Fase normal de processamento: é nesta fase que são enviadas mensagens
cliente-servidor, todas as mensagens contém o tipo de dados e o conteúdo da
mensagem propriamente dito.
As diretivas do protocolo RFB tiveram que ser parcialmente implementadas
pela equipe deste projeto para que o servidor bridge (em JAVA) tivesse a
possibilidade de acessar os comando e ler as informações vindas do Servidor VNC.
Foram utilizadas também, algumas classes JAVA disponibilizadas na internet:
a) RFBProtocol.java [http://www.tightvnc.com]: classe que implementa o protocolo
entre o servidor Bridge e o servidor VNC.
b) DesCipher.java [http://www.acme.com]: utilizada para cifrar a senha enviada ao
servidor VNC pelo servidor Bridge .
c) AnimatedMemoryImageSource.java [http://www.tightvnc.com]: responsável por
manipular a imagem enviada pelo servidor VNC.
Todas estas classes são regidas pela GPL (General Public License),
atestando assim seu uso livre.
3.2.6 Diretivas do protocolo auxiliar
Um protocolo auxiliar teve de ser implementado para que o dispositivo móvel
tivesse acesso ao servidor bridge, sendo assim algumas diretivas foram definidas e
lidas pelo programa através de variáveis statics do JAVA:
34
Quadro 2 – Diretivas do protocolo auxiliar
Fonte: Elaborado pelos autores, 2005
3.3 Desenvolvimento da aplicação
Para o desenvolvimento desta aplicação foram criados dois aplicativos, um
servidor, que deve ser instalado na estação de trabalho a ser controlada
remotamente, e um cliente, instalado no dispositivo móvel. A seguir segue uma
descrição mais apurada destas aplicações.
35
3.3.1 Programa servidor
Esta parte da aplicação deve ser instalada na máquina que se deseja
controlar remotamente. Na seqüência é apresentada uma figura com as classes que
compõe a aplicação servidor.
Figura 8 - Programa servidor
Fonte: elaborada pelos autores, 2005.
Breve descrição das funcionalidades de cada classe:
a) DP: contém apenas constantes do protocolo auxiliar implementado pela equipe,
esta classe deve ser igual para os dois programas – cliente, servidor – para que
não haja conflitos de ações entre os programas.
b) RFBProtocol: classe adaptada de versão encontrada na internet, serve para
comunicar-se com o servidor VNC original, contém programação de baixo nível
(bytes, hexadecimal, deslocamento de bits).
c) TratadorDeComandos: funciona como um processador de protocolo de ações do
cliente, tratando e devolvendo os dados requisitados, é nesta classe que é
utilizado o protocolo auxiliar.
d) PainelDeAutenticacao: classe de Interface com o usuário, contém os campos para
entrada de dados como: endereço do servidor, porta, senha, etc...
e) AnimatedMemoryImageSource: classe adaptada que facilita o redimensionamento
de imagens.
36
f) DesCipher: classe para a cifragem de senha.
g) Log: utilizado principalmente na fase de desenvolvimento para acompanhar as
ações que estavam sendo realizadas, é uma boa alternativa quando o debug não
é necessário.
h) TratadorDeImagem: utilizada para tratamento da imagem recebida do servidor, o
objeto criado a partir desta classe gerencia a posição e o ZOOM que deve ser
levado em conta na hora de fornecer a imagem ao cliente.
i) TratadorDoMouse: classe utilizada pelo tratador da imagem para calcular o
redimensionamento e posicionamento da imagem, a cada ação no celular o
tratador de mouse é acionado para informar que houve uma mudança na posição
ou no zoom da figura.
3.3.2 Programa cliente
Através desta aplicação é que o dispositivo acessa remotamente o programa
servidor instalado na estação de trabalho alvo. A exemplo da aplicação servidor,
segue a listagem de classes do programa e suas descrições.
Figura 9 - Programa cliente – Celular
Fonte: elaborada pelos autores, 2005.
37
Breve descrição das funcionalidades de cada classe:
a) Protocol: classe que sobre escreve a classe da J2ME do celular, é uma tentativa
de tornar a aplicação compatível com a MIDP 1.0, já que esta versão não suporta
sockets.
b) Conexao: responsável por manter a conexão com o servidor “ponte”, utiliza a
classe DP, implementando o protocolo auxiliar.
c) Cliente: contém a inicialização do programa, determina o tamanho da tela, e a
conexão a ser feita, atribui propriedades as telas.
d) Log: muito utilizado na fase de implementação, já que as ferramentas usadas para
desenvolvimento não possuíam um fácil debuger para J2ME.
e) Main: apenas para iniciar a aplicação, padrões para MIDP.
f) TelaAjuda: contém uma pequena figura com a explicação dos comandos.
g) TelaInicial: campos para entrada do endereço do servidor “ponte” e senha.
h) TelaPrincipal: contém a estrutura onde será exibida a tela do desktop
compartilhado.
3.3.3 Telas do sistema
A seguir estão as definições das teclas do celular, o que elas representam
para o servidor VNC:
38
Figura 10 – Teclas do celular para o servidor VNC
Fonte: elaborada pelos autores, 2005.
Tela do VNC para celular – módulo PC:
Figura 11 - Tela do VNC para celular – módulo PC
Fonte: elaborada pelos autores, 2005.
39
Na tela apresentada são informados os dados para que o Servidor VNC
fique disponível para os dispositivos móveis, a seguir a descrição dos campos:
a) Host VNC: Endereço IP ou nome do computador onde o servidor VNC se encontra
rodando, inclusive para acesso via PC.
b) Senha: Senha para acesso ao serviço VNC.
c) Porta: É a porta na qual está rodando o serviço VNC.
d) Senha externa: É a senha que terá que ser informada no celular para acessar o
serviço.
e) Porta externa: É a porta na qual rodará o serviço, a qual deverá ser informada no
celular.
Telas do VNC para celular – módulo J2ME - Celular:
Figura 12 - Telas do VNC para celular – módulo J2ME - Celular
Fonte: elaborada pelos autores, 2005.
Tela onde são informados os dados para conexão com o computador que
disponibilizará o serviço VNC para dispositivos móveis, é nescessário informar o
endereço e a senha.
40
Figura 13 - Telas do VNC para celular – módulo J2ME - Celular
Fonte: elaborada pelos autores, 2005.
Esta tela mostra a tela do computador que está com o serviço VNC rodando,
após a conexão é mostrada a tela completa, sem efeitos de ZOOM ou deslocamento
da tela.
Figura 14 - Telas do VNC para celular – módulo J2ME - Celular
Fonte: elaborada pelos autores, 2005.
Nesta figura se observa a tela do computador remoto após serem enviados
alguns comandos de ZOOM e deslocamento de tela, facilitando assim a visualização
dos itens que estão disponíveis no computador.
41
Figura 15 - Telas do VNC para celular – módulo J2ME - Celular
Fonte: elaborada pelos autores, 2005.
Tela do celular mostrando o computador remoto, neste caso foi utilizado
ZOOM máximo para exibição.
3.3.4 Diagrama de classes
Será apresentado a seguir o diagrama de classes para as aplicações cliente
e servidor.
42
a) Aplicação cliente:
Figura 16 – Classes da aplicação cliente
Fonte: elaborada pelos autores, 2005.
43
b) Aplicação servidor:
Figura 17 – Classes da aplicação servidor
Fonte: elaborada pelos autores, 2005.
44
Figura 18 – Classes da aplicação servidor
Fonte: elaborada pelos autores, 2005.
45
3.3.5 Diagrama de seqüência UML
Figura 19 – Diagrama de seqüência UML
Fonte: elaborada pelos autores, 2005.
3.3.6 Ambiente de desenvolvimento
Para o desenvolvimento da aplicação, o seguinte ambiente de programação
foi elaborado sobre um sistema operacional Windows XP:
a) J2SE (SDK) 1.5.0_02: esta é a plataforma Java fundamental. Neste pacote
encontram-se as classes Java necessárias para a criação do sistema, compilador
Java, a extensão J2ME, que evidentemente permite o uso de Java em aplicações
para dispositivos móveis, e outros requerimentos para desenvolvimento de
projetos em linguagem Java.
b) Wireless Toolkit 2.2 (WTK): Pode ser definido como uma “caixa de ferramentas”
para desenvolvimento de aplicações J2ME. O conjunto de serviços oferece:
ambiente
para
emulação,
opções
para
documentação, exemplos de aplicações, etc.
otimização
de
desempenho,
46
c) VNC: uma versão free do VNC foi utilizada para servir de servidor principal.
Assim,o servidor Bridge criado na pesquisa realizou a interface entre o servidor
VNC e o cliente instalado no dispositivo móvel.
d) Eclipse 3.1: É a versão utilizada da plataforma Eclipse. O IDE escolhido foi o JDT,
como já foi explanado anteriormente. Apenas a ferramenta Eclipse já oferece um
total ambiente de programação, e com certeza foi um dos softwares utilizados que
mais contribuiu para o desenvolvimento rápido e eficaz do JNC Móbile. Segue
abaixo uma figura demonstrando o ambiente de desenvolvimento.
Figura 20 - Ambiente de programação
Fonte: elaborada pelos autores, 2005.
47
4 TRABALHOS FUTUROS
Como trabalhos futuros, um grande número de opções pode ser explorado.
Entretanto, surge como mais claro para os autores, a abordagem dos seguintes
tópicos possíveis:
a) Possibilitar o cadastro de tarefas automáticas no servidor Bridge: ao instalar o
servidor bridge na estação de trabalho a ser controlada remotamente, o usuário
poderá cadastrar tarefas junto a esta máquina que posteriormente poderão ser
executadas pela aplicação cliente disponível no dispositivo móvel. Assim, tarefas
como shutdown, restart, ativar desfragmentador de disco, uma rotina de trabalho,
rodar anti-vírus, entre outras, poderá ser facilmente executadas com uma simples
seleção em um menu de tarefas da aplicação cliente. Com esta funcionalidade, a
experiência de uso do JNC se tornará muito mais amigável e interessante.
b) Permitir a entrada de texto a partir do cliente: com esta funcionalidade o usuário
será capaz de digitar palavras utilizando-se do teclado de seu aparelho móvel.
Assim, torna-se possível a escrita de textos ou comandos no servidor, apenas
digitando as letras da mesma maneira que se faz com a escrita de mensagens em
aparelhos celulares.
c) Construir um servidor completo em Java: infelizmente ainda é necessário para a
aplicação descrita nesta pesquisa, o uso de um servidor VNC escrito em C++.
Desta forma, o uso de um servidor bridge tornou-se indispensável. Então, como
trabalho futuro, espera-se que apenas um servidor seja requerido para o
funcionamento de todo o sistema, o que facilitaria sua instalação e configuração.
d) Implementar um protocolo genérico para controle remoto: como trabalho mais
audacioso, os pesquisadores propõe a implementação de um protocolo para
controle remoto genérico. Assim, um único protocolo poderia ser utilizado para
48
tratar o envio e recebimento de textos, imagens, comandos para dispositivos
diversos, como câmeras de vídeo, comandos para robôs domésticos, etc. Este
protocolo visaria tornar possível padronizar a utilização de recursos, agilizando o
trabalho de empresas de software no desenvolvimento de aplicações de caráter
remoto.
49
5 CONSIDERAÇÕES FINAIS
O mercado de dispositivos móveis está crescendo vertiginosamente. O
público foi acometido por uma onda de consumo onde todo equipamento ou serviço
deve ser móvel e de conectividade imediata. Aparelhos como DVDs, videogames,
computadores, assumiram novos conceitos ao serem miniaturizados e munidos de
conexão sem fios a diferentes tipos de mídia, seja esta a Internet ou outro
dispositivo. Desta forma, um novo tipo de relacionamento entre máquinas e a
sociedade está se formando. Para facilitar está transição, e dispor-se de maneira
competitiva e atual, os pesquisadores buscaram com êxito, conhecer e conceber
soluções para dispositivos móveis.
Objetivos como identificar qual tecnologia empregar para solução de
problemas móveis, foram prontamente atendidos ao definir-se o uso da tecnologia
Java 2 ME. Tecnologia que já vem embutida na maioria dos dispositivos móveis do
mercado e que visa marcar presença em mais de 90% destes dispositivos até 2007.
A escolha de aparelhos celulares para a concepção do sistema deu-se
principalmente a três fatores: são dispositivos genuinamente móveis; quando se trata
de se discutir dispositivos móveis, quase sempre são os primeiros a serem
lembrados como pertencentes a esta classe, estando assim fortemente ligados ao
que o público associa como solução móvel; era o dispositivo móvel ao alcance dos
pesquisadores para o desenvolvimento da pesquisa.
O uso de uma tecnologia nascida para realizar esta tarefa, como é o caso do
J2ME, e a utilização de ferramentas como o Wireless Toolkit da Sun, e o Eclipse,
somente não foram maiores facilitadores da pesquisa por conta da incompatibilidade
existente entre os aparelhos celulares. Este problema de padrões na indústria
50
parece estar se resolvendo com a iniciativa de atualização do profile do J2ME MIDP,
que agora figura em sua segunda versão. Entretanto, infelizmente não havia a
disposição para experimento neste trabalho um dispositivo móvel provido desta
funcionalidade. Vale lembrar que a incompatibilidade existe até mesmo entre
aparelhos do mesmo fabricante, dificultando ainda mais a criação e difusão de
soluções para dispositivos móveis como celulares.
Excluindo-se estes obstáculos, a pesquisa alcançou seus objetivos. A
implementação de um sistema para acesso remoto via dispositivos móveis foi
realizada com sucesso. Os pesquisadores tornaram possível o controle de uma
estação de trabalho utilizando-se apenas um simples aparelho celular. Desta
maneira, um imprevisto que clame por um acesso a uma máquina, devidamente
ligada e conectada a Internet e com o JNC disponível, pode facilmente ser acessada
de qualquer local e com a maior discrição possível atualmente, fazendo com que seu
usuário manipule apenas seu simples aparelho telefônico.
É importante lembrar que a fluidez do uso da aplicação é fortemente
comprometido por limitações de acessibilidade impostas pelos aparelhos celulares,
dispõe-se apenas das teclas do aparelho, e o visor reduzido também torna a
visualização de um desktop completo um desafio. Mas como caráter principalmente
acadêmico que tem esta pesquisa, e com o alcance dos objetivos almejados pelos
pesquisadores, é com satisfação que se apresenta o JNC Mobile como uma solução
real para acesso remoto para dispositivos móveis.
51
REFERÊNCIAS
AN INTRODUCTION to J2ME. Wikipedia. Disponível em:
<http://en.wikipedia.org/wiki/An_Introduction_to_J2ME> Acesso: 27 mar. 2005.
CARNIEL, Juliano D.; KÜHL, Daniel. J2ME: como começar? Web Móbile. Rio de
Janeiro. Ano 1. ed. 2. p. 58-66. Mar. 2005.
DOEDERLEIN, Osvaldo. O projeto Eclipse: arquitetura, subprojetos, planos e
ferramentas. Java Magazine. Rio de Janeiro. Ano 3. ed. 23. p. 28-44. abr. 2005.
FIGUEIREDO, Carlos M. S.; NAKAMURA, Eduardo. Computação móvel: novas
oportunidades e novos desafios. T&C Amazônia. Ano 1. n. 2. Jun. 2003.
GIL, Antônio Carlos. Como elaborar projetos de pesquisa. 3 ed. São Paulo: Atlas,
1991.
JAVATM 2 Platform, Micro Edition. Sun Microsystems. Disponível em:
<http://java.sun.com/> Acesso: 27 mar. 2005.
JAVA 2 Platform, Micro Edition (J2ME); JSR 68 Overview. Sun Microsystems.
Disponível em: <http://java.sun.com/> Acesso: 27 mar. 2005.
META VNC - a window aware VNC. Meta VNC. Disponível em:
<http://metavnc.sourceforge.net/> Acesso: 27 mar. 2005.
52
MOBILE Information Device Profile (MIDP); JSR 37, JSR 118 Overview. Sun
Microsystems. Disponível em: <http://java.sun.com/products/midp/> Acesso: 27
mar. 2005.
TAUBER, Daniel. What's J2ME? OnJava. 2001. Disponível em:
<http://www.onjava.com/pub/a/onjava/2001/03/08/J2ME.html> Acesso: 27 mar. 2005.
THE J2ME Frequently Asked Questions List. BellSouthpwp. Disponível em:
<http://bellsouthpwp.net/m/c/mcpierce/j2mefaq.html> Acesso: 27 mar. 2005.
VIRTUAL Network Computing. Wikipedia. Disponível em:
<http://pt.wikipedia.org/wiki/Virtual_Network_Computing> Acesso: 27 mar. 2005
WHAT is VNC. RealVNC. Disponível em: <http://www.realvnc.com/what.html>
Acesso: 27 mar. 2005.
APÊNDICES
APÊNDICE A – Código Fonte da Aplicação Cliente
Conexao.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
5/7/2005 19:42
package rede;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;
import javax.microedition.lcdui.Image;
import ui.Log;
import ui.TelaPrincipal;
public class Conexao extends Thread {
private int comando;
private int largura;
private int altura;
private TelaPrincipal tela;
private String host;
private String senha;
public Conexao(String _host, String _senha) {
host = _host;
senha = _senha;
}
public void run() {
iniciaValores();
while (true) {
long numMillisecondsToSleep = 500; // 1/5 segundos
try {
Thread.sleep(numMillisecondsToSleep);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (tela != null) {
atualizaTela();
}
}
}
public void iniciaValores() {
HttpConnection c = null;
InputStream input = null;
try {
String urlConexao = host + "/" + largura + "x" + altura;
Log.info(urlConexao);
c = (HttpConnection) Connector.open(urlConexao,
Connector.READ_WRITE);
c.setRequestMethod(HttpConnection.GET);
Log.info("pass2");
input = c.openInputStream();
Log.info("pass3");
} catch (Exception e) {
e.printStackTrace();
} finally {
if (input != null)
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
if (c != null)
try {
c.close();
} catch (IOException e) {
e.printStackTrace();
}
}
enviaComando(DP.INICIA_TRATADOR_DE_IMAGENS);
atualizaTela();
}
public boolean alterou() {
return true;
}
public void enviaComando(int _comando) {
comando = _comando;
Page 1 of 3
Conexao.java
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
5/7/2005 19:42
}
public void atualizaTela() {
try {
HttpConnection c;
c = (HttpConnection) Connector.open(host + "/" + comando,
Connector.READ_WRITE);
comando = DP.GET_IMAGEM;
c.setRequestMethod(HttpConnection.GET);
Log.info("pass2");
InputStream input = c.openInputStream();
Log.info(c.getType());
Log.info("pass3");
Image im;
tela.setImagem(getImage(input));
tela.repaint();
c.close();
} catch (Exception e) {
e.printStackTrace();
}
}
private Image getImage(InputStream iStrm) throws IOException {
Image im = null;
try {
Log.info("carregando imagem");
int bufferSize = 256;
byte byteInput[] = new byte[bufferSize];
ByteArrayOutputStream imageBuffer = new ByteArrayOutputStream(1024);
int size = 0;
while ((size = iStrm.read(byteInput, 0, bufferSize)) != -1) {
Log.info("escrevendo");
imageBuffer.write(byteInput, 0, size);
}
// get byte from buffer stream
byte byteImage[] = imageBuffer.toByteArray();
Log.info("read byte " + byteImage.length);
// convert byte to image ...
im = Image.createImage(byteImage, 0, byteImage.length);
return im;
// ByteArrayOutputStream bStrm = new ByteArrayOutputStream();
//
// int ch;
// while ((ch = iStrm.read()) != -1)
// bStrm.write(ch);
//
// // Place into image array
// byte imageData[] = bStrm.toByteArray();
//
// // Create the image from the byte array
// Log.info(imageData.length);
// im = Image.createImage(imageData, 0, imageData.length);
} catch (Exception e) {
e.printStackTrace();
} finally {
// Clean up
if (iStrm != null)
iStrm.close();
}
return (im == null ? null : im);
}
public void fechar() {
enviaComando(DP.FINALIZAR_CONEXAO);
}
public int getAltura() {
return altura;
}
public void setAltura(int altura) {
this.altura = altura;
}
public int getLargura() {
return largura;
Page 2 of 3
Conexao.java
153
154
155
156
157
158
159
160
161
162
163
164
165
166
5/7/2005 19:42
}
public void setLargura(int largura) {
this.largura = largura;
}
public TelaPrincipal getTela() {
return tela;
}
public void setTela(TelaPrincipal tela) {
this.tela = tela;
}
}
Page 3 of 3
DP.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
5/7/2005 19:42
package rede;
public class DP {
public static
public static
public static
public static
public static
public static
public static
public static
public static
public static
public static
public static
public static
public static
public static
public static
public static
}
final
final
final
final
final
final
final
final
final
final
final
final
final
final
final
final
final
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
INICIA_TRATADOR_DE_IMAGENS = 10;
CONEXAO_OK = 11;
GET_IMAGEM = 12;
FINALIZAR_CONEXAO = 13;
CMD_BT_MOUSE1 = 14;
CMD_BT_MOUSE2 = 15;
CMD_TELA_PARA_CIMA = 16;
CMD_TELA_PARA_BAIXO = 17;
CMD_TELA_PARA_DIREITA = 18;
CMD_TELA_PARA_ESQUERDA = 19;
CMD_MOUSE_PARA_CIMA = 20;
CMD_MOUSE_PARA_BAIXO = 21;
CMD_MOUSE_PARA_DIREITA = 22;
CMD_MOUSE_PARA_ESQUERDA = 23;
CMD_ZOOM_MAIS = 24;
CMD_ZOOM_MENOS = 25;
IMAGEM_RECEBIDA = 26;
Page 1 of 1
Cliente.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
5/7/2005 19:42
package ui;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.midlet.MIDlet;
import rede.Conexao;
public class Cliente implements CommandListener {
private Display display;
private Command cmOk;
private Command cmVoltar;
private Command cmSair;
private Command cmAjuda;
private Conexao conexao;
private TelaAjuda telaAjuda;
private TelaPrincipal telaPrincipal;
private TelaInicial telaInicial;
private MIDlet midletPrincipal;
public Cliente(Display d, MIDlet m) {
midletPrincipal = m;
display = d;
startApp();
}
private void criaComandos() {
cmOk = new Command("Ok", Command.SCREEN, 2);
cmVoltar = new Command("Voltar", Command.BACK, 1);
cmSair = new Command("Sair", Command.EXIT, 1);
cmAjuda = new Command("Ajuda", Command.HELP, 2);
}
private void preparaTelas() {
telaAjuda = new TelaAjuda("Ajuda");
telaAjuda.addCommand(cmOk);
telaAjuda.addCommand(cmVoltar);
telaAjuda.setCommandListener(this);
telaPrincipal = new TelaPrincipal();
telaPrincipal.addCommand(cmSair);
telaPrincipal.addCommand(cmAjuda);
telaPrincipal.setCommandListener(this);
telaInicial = new TelaInicial("Mobile VNC");
telaInicial.addCommand(cmSair);
telaInicial.addCommand(cmOk);
telaInicial.setCommandListener(this);
}
public void startApp() {
criaComandos();
preparaTelas();
display.setCurrent(telaInicial);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
public void commandAction(Command comando, Displayable tela) {
if (comando == cmVoltar) {
display.setCurrent(telaPrincipal);
}
if (comando == cmOk) {
if (telaAjuda.isShown()) {
display.setCurrent(telaPrincipal);
}
if (telaInicial.isShown()) {
iniciaConexao();
}
}
if (comando == cmAjuda) {
display.setCurrent(telaAjuda);
}
if (comando == cmSair) {
Page 1 of 2
Cliente.java
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
5/7/2005 19:42
conexao.fechar();
destroyApp(false);
midletPrincipal.notifyDestroyed();
}
}
private synchronized void iniciaConexao() {
Log.info("Conectando em..." + telaInicial.getTxtEndereco().getString());
conexao = new Conexao(telaInicial.getTxtEndereco().getString(),
telaInicial.getTxtSenha().getString());
conexao.setLargura(telaPrincipal.getWidth());
conexao.setAltura(telaPrincipal.getHeight());
conexao.start();
telaPrincipal.setConexao(conexao);
display.setCurrent(telaPrincipal);
}
}
Page 2 of 2
Log.java
1
2
3
4
5
6
7
8
9
10
11
12
5/7/2005 19:43
package ui;
public class Log {
public synchronized static void info(String texto) {
// Log.info("Info: "+texto);
}
public synchronized static void erro(String texto) {
Log.info("Erro: " + texto);
}
}
Page 1 of 1
Main.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
5/7/2005 19:43
package ui;
import javax.microedition.lcdui.Display;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
public class Main extends MIDlet {
public Main() {
super();
}
protected void startApp() throws MIDletStateChangeException {
Cliente c = new Cliente(Display.getDisplay(this), this);
}
protected void pauseApp() {
}
protected void destroyApp(boolean arg0) throws MIDletStateChangeException {
}
}
Page 1 of 1
TelaAjuda.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
5/7/2005 19:43
package ui;
import java.io.IOException;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.Image;
public class TelaAjuda extends Form {
public TelaAjuda(String nome) {
super(nome);
Image imagemDeAjuda = Image.createImage(5, 5);
Log.info("Carregando imagem de ajuda");
try {
imagemDeAjuda = Image.createImage("/ajuda.jpg");
} catch (IOException e) {
e.printStackTrace();
}
Log.info("Finalizando carregamento");
append(imagemDeAjuda);
}
}
Page 1 of 1
TelaInicial.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
5/7/2005 19:44
package ui;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.TextField;
public class TelaInicial extends Form {
private TextField txtEndereco;
private TextField txtSenha;
public TelaInicial(String nome) {
super(nome);
txtEndereco = new TextField("Endereço", "http://192.168.152.38:8080",
40, TextField.ANY);
txtSenha = new TextField("Senha", "testevnc", 8, TextField.ANY);
append(txtEndereco);
append(txtSenha);
}
public TextField getTxtEndereco() {
return txtEndereco;
}
public TextField getTxtSenha() {
return txtSenha;
}
}
Page 1 of 1
TelaPrincipal.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
5/7/2005 19:44
package ui;
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import rede.Conexao;
import rede.DP;
public class TelaPrincipal extends Canvas {
private Conexao conexao;
private int keyCode;
private boolean movimentaMouse;
private Image imagem;
public TelaPrincipal() {
imagem = Image.createImage(132, 100);
}
public void keyReleased(int keyCode) {
this.keyCode = keyCode;
}
public void keyRepeated(int keyCode) {
this.keyCode = keyCode;
}
public void keyPressed(int keyCode) {
this.keyCode = keyCode;
Log.info("codigo=" + keyCode);
switch (keyCode) {
case KEY_NUM1: // Clique botao esquerdo do mouse
enviaComando(DP.CMD_BT_MOUSE1);
break;
case KEY_NUM2: // Movimenta tela/mouse para cima
if (movimentaMouse) {
enviaComando(DP.CMD_MOUSE_PARA_CIMA);
} else {
enviaComando(DP.CMD_TELA_PARA_CIMA);
}
break;
case KEY_NUM3: // Clique botao direito do mouse
enviaComando(DP.CMD_BT_MOUSE2);
break;
case KEY_NUM4: // Movimenta tela/mouse para esquerda
if (movimentaMouse) {
enviaComando(DP.CMD_MOUSE_PARA_ESQUERDA);
} else {
enviaComando(DP.CMD_TELA_PARA_ESQUERDA);
}
break;
case KEY_NUM5:
break;
case KEY_NUM6: // Movimenta tela/mouse para direita
if (movimentaMouse) {
enviaComando(DP.CMD_MOUSE_PARA_DIREITA);
} else {
enviaComando(DP.CMD_TELA_PARA_DIREITA);
}
break;
case KEY_NUM7: // Zoom menos
enviaComando(DP.CMD_ZOOM_MENOS);
break;
case KEY_NUM8: // Movimenta tela/mouse para baixo
if (movimentaMouse) {
enviaComando(DP.CMD_MOUSE_PARA_BAIXO);
} else {
enviaComando(DP.CMD_TELA_PARA_BAIXO);
}
break;
case KEY_NUM9: // Zoom mais
enviaComando(DP.CMD_ZOOM_MAIS);
break;
case KEY_NUM0: // Troca movimento de tela/mouse
movimentaMouse = !movimentaMouse;
break;
default:
break;
Page 1 of 2
TelaPrincipal.java
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
5/7/2005 19:44
}
}
public Conexao getConexao() {
return conexao;
}
public void setConexao(Conexao conexao) {
this.conexao = conexao;
conexao.setTela(this);
}
protected void paint(Graphics g) {
g.drawImage(imagem, 0, 0, Graphics.LEFT | Graphics.TOP);
}
private synchronized void enviaComando(int comando) {
Log.info("Comando=" + comando);
conexao.enviaComando(comando);
}
public Image getImagem() {
return imagem;
}
public void setImagem(Image imagem) {
this.imagem = imagem;
}
}
Page 2 of 2
APÊNDICE B – Código Fonte da Aplicação Servidor
DP.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
5/7/2005 19:32
package app.rede;
public class DP {
public static
public static
public static
public static
public static
public static
public static
public static
public static
public static
public static
public static
public static
public static
public static
public static
public static
}
final
final
final
final
final
final
final
final
final
final
final
final
final
final
final
final
final
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
INICIA_TRATADOR_DE_IMAGENS = 10;
CONEXAO_OK = 11;
GET_IMAGEM = 12;
FINALIZAR_CONEXAO = 13;
CMD_BT_MOUSE1 = 14;
CMD_BT_MOUSE2 = 15;
CMD_TELA_PARA_CIMA = 16;
CMD_TELA_PARA_BAIXO = 17;
CMD_TELA_PARA_DIREITA = 18;
CMD_TELA_PARA_ESQUERDA = 19;
CMD_MOUSE_PARA_CIMA = 20;
CMD_MOUSE_PARA_BAIXO = 21;
CMD_MOUSE_PARA_DIREITA = 22;
CMD_MOUSE_PARA_ESQUERDA = 23;
CMD_ZOOM_MAIS = 24;
CMD_ZOOM_MENOS = 25;
IMAGEM_RECEBIDA = 26;
Page 1 of 1
LeitorDeComando.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
5/7/2005 19:33
package app.rede;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import app.util.Log;
public class LeitorDeComando {
ServerSocket serverSocket = null;
public LeitorDeComando(int porta) {
try {
serverSocket = new ServerSocket(porta, 100);
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
}
public void fechaFechaConexao() {
if (serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Socket socket = null;
private OutputStream output = null;
private Request request = null;
public int getComando() {
InputStream input = null;
Log.info("aguardando");
try {
socket = serverSocket.accept();
Log.info("conectado");
input = socket.getInputStream();
output = socket.getOutputStream();
request = new Request(input);
int comando = request.parse();
return comando;
} catch (IOException e) {
e.printStackTrace();
}
return 0;
}
public TelaCelular getTelaCelular() {
InputStream input = null;
Log.info("aguardando");
try {
socket = serverSocket.accept();
Log.info("conectado");
input = socket.getInputStream();
output = socket.getOutputStream();
request = new Request(input);
TelaCelular tela = request.getTela();
Response response = new Response(output);
response.setRequest(request);
response.enviaTelaDeBoasVinas();
socket.close();
return tela;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public void enviaImagem(BufferedImage imagem) {
try {
Response response = new Response(output);
response.setRequest(request);
Page 1 of 2
LeitorDeComando.java
77
78
79
80
81
82
83
84
5/7/2005 19:33
response.sendStaticResource(imagem);
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Page 2 of 2
Request.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
5/7/2005 19:34
package app.rede;
import java.io.IOException;
import java.io.InputStream;
import app.util.Log;
public class Request {
private InputStream input;
private String uri;
public Request(InputStream input) {
this.input = input;
}
public int parse() {
StringBuffer request = new StringBuffer(2048);
int i;
byte[] buffer = new byte[2048];
try {
i = input.read(buffer);
} catch (IOException e) {
e.printStackTrace();
i = -1;
}
for (int j = 0; j < i; j++) {
request.append((char) buffer[j]);
}
uri = parseUri(request.toString());
Log.info("uri=" + uri);
int comando = Integer.parseInt(uri.toString().substring(1));
return comando;
}
public TelaCelular getTela() {
// Read a set of characters from the socket
StringBuffer request = new StringBuffer(2048);
int i;
byte[] buffer = new byte[2048];
try {
i = input.read(buffer);
} catch (IOException e) {
e.printStackTrace();
i = -1;
}
for (int j = 0; j < i; j++) {
request.append((char) buffer[j]);
}
uri = parseUri(request.toString());
Log.info("URI=" + uri);
String[] valores = uri.substring(1).split("x");
TelaCelular tela = new TelaCelular();
tela.setLargura(Integer.parseInt(valores[0].trim()));
tela.setAltura(Integer.parseInt(valores[1].trim()));
return tela;
}
private String parseUri(String requestString) {
int index1, index2;
index1 = requestString.indexOf(' ');
if (index1 != -1) {
index2 = requestString.indexOf(' ', index1 + 1);
if (index2 > index1)
return requestString.substring(index1 + 1, index2);
}
return null;
}
public String getUri() {
return uri;
}
}
Page 1 of 1
Response.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
5/7/2005 19:34
package app.rede;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import javax.imageio.ImageIO;
import app.util.Log;
public class Response {
private static final int BUFFER_SIZE = 1024;
Request request;
OutputStream output;
public Response(OutputStream output) {
this.output = output;
}
public void setRequest(Request request) {
this.request = request;
}
public void sendStaticResource(BufferedImage imagemCelular) {
int leido = 0;
byte datosBytes[] = new byte[256];
try {
String respuesta = "HTTP/1.0 200 OK\n";
respuesta += "Date: Mon, 5 Nov 2008 23:59:59GMT\n";
respuesta += "Content-Type: image/jpeg\n";
respuesta += "\r\n";
output.write(respuesta.getBytes());
output.flush();
Log.info("enviando imagem");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write((RenderedImage) imagemCelular, "jpeg", baos);
byte[] bytes = baos.toByteArray();
ImageIO.write((RenderedImage) imagemCelular, "jpeg", output);
System.out.println(output.toString());
System.out.println("terminando envio");
} catch (Exception e) {
e.printStackTrace();
}
}
public void enviaTelaDeBoasVinas() {
try {
String respuesta = "HTTP/1.0 200 OK\n";
respuesta += "Date: Mon, 5 Nov 2008 23:59:59GMT\n";
respuesta += "Content-Type: text/playn\n";
respuesta += "\r\n";
output.write(respuesta.getBytes());
output.flush();
String boasVinas = "Conectado!!!";
output.write(boasVinas.getBytes(), 0, boasVinas.getBytes().length);
output.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Page 1 of 1
RFBProtocol.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
5/7/2005 19:34
//Classe retirada do site http://www.tightvnc.com/ com licensa GPL
//e modificada para atender as necessidades do programa
//Copyright (C) 2001,2002 HorizonLive.com, Inc. All Rights Reserved.
//Copyright (C) 2001,2002 Constantin Kaplinsky. All Rights Reserved.
//Copyright (C) 2000 Tridia Corporation. All Rights Reserved.
//Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
package app.rede;
import java.awt.Event;
import java.awt.event.MouseEvent;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import app.util.DesCipher;
public class RFBProtocol {
final String versionMsg = "RFB 003.003\n";
final int ConnFailed = 0, NoAuth = 1, VncAuth = 2;
final int VncAuthOK = 0, VncAuthFailed = 1, VncAuthTooMany = 2;
private static final boolean COMPARTILHAR_DESKTOP = true;
final static int FramebufferUpdate = 0, SetColourMapEntries = 1, Bell = 2,
ServerCutText = 3;
final int SetPixelFormat = 0, FixColourMapEntries = 1, SetEncodings = 2,
FramebufferUpdateRequest = 3, KeyEvent = 4, PointerEvent = 5,
ClientCutText = 6;
final static int EncodingRaw = 0, EncodingCopyRect = 1, EncodingRRE = 2,
EncodingCoRRE = 4, EncodingHextile = 5;
final int HextileRaw = (1 << 0);
final int HextileBackgroundSpecified = (1 << 1);
final int HextileForegroundSpecified = (1 << 2);
final int HextileAnySubrects = (1 << 3);
final int HextileSubrectsColoured = (1 << 4);
String vncHost;
int vncPort;
Socket sock;
DataInputStream is;
OutputStream os;
public boolean inNormalProtocol = false;
//
// Constructor. Just make TCP connection to RFB server.
//
public RFBProtocol(String vncHost, int vncPort) {
this.vncHost = vncHost;
this.vncPort = vncPort;
try {
sock = new Socket(vncHost, vncPort);
is = new DataInputStream(new BufferedInputStream(sock
.getInputStream(), 16384));
os = sock.getOutputStream();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void close() {
try {
sock.close();
} catch (Exception e) {
e.printStackTrace();
}
}
//
// Read server's protocol version message
//
int serverMajor, serverMinor;
void readVersionMsg() throws IOException {
byte[] b = new byte[12];
is.readFully(b);
if ((b[0] != 'R') || (b[1] != 'F') || (b[2] != 'B') || (b[3] != ' ')
|| (b[4] < '0') || (b[4] > '9') || (b[5] < '0') || (b[5] > '9')
Page 1 of 8
RFBProtocol.java
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
5/7/2005 19:34
|| (b[6] < '0') || (b[6] > '9') || (b[7] != '.')
|| (b[8] < '0') || (b[8] > '9') || (b[9] < '0') || (b[9] > '9')
|| (b[10] < '0') || (b[10] > '9') || (b[11] != '\n')) {
throw new IOException("Host " + vncHost + " port " + vncPort
+ " is not an RFB server");
}
serverMajor = (b[4] - '0') * 100 + (b[5] - '0') * 10 + (b[6] - '0');
serverMinor = (b[8] - '0') * 100 + (b[9] - '0') * 10 + (b[10] - '0');
}
public boolean connectAndAuthenticate(String password) throws IOException {
boolean authenticationDone = false;
readVersionMsg();
System.out.println("RFB server supports protocol version "
+ serverMajor + "." + serverMinor);
writeVersionMsg();
switch (readAuthScheme()) {
case NoAuth:
System.out.println("No authentication needed");
authenticationDone = true;
break;
case VncAuth:
byte[] challenge = new byte[16];
is.readFully(challenge);
String pw = password;
if (pw.length() > 8)
pw = pw.substring(0, 8); // truncate to 8 chars
byte[] key = new byte[8];
pw.getBytes(0, pw.length(), key, 0);
for (int i = pw.length(); i < 8; i++) {
key[i] = (byte) 0;
}
DesCipher des = new DesCipher(key);
des.encrypt(challenge, 0, challenge, 0);
des.encrypt(challenge, 8, challenge, 8);
os.write(challenge);
int authResult = is.readInt();
switch (authResult) {
case VncAuthOK:
System.out.println("VNC authentication succeeded");
authenticationDone = true;
break;
case VncAuthFailed:
System.out.println("VNC authentication failed");
break;
case VncAuthTooMany:
throw new IOException("VNC authentication failed - "
+ "too many tries");
default:
throw new IOException("Unknown VNC authentication result "
+ authResult);
}
break;
}
return authenticationDone;
}
//
// Write our protocol version message
//
void writeVersionMsg() throws IOException {
byte[] b = new byte[12];
versionMsg.getBytes(0, 12, b, 0);
os.write(b);
}
//
// Find out the authentication scheme.
//
int readAuthScheme() throws IOException {
int authScheme = is.readInt();
switch (authScheme) {
case ConnFailed:
int reasonLen = is.readInt();
byte[] reason = new byte[reasonLen];
is.readFully(reason);
Page 2 of 8
RFBProtocol.java
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
5/7/2005 19:34
throw new IOException(new String(reason, 0));
case NoAuth:
case VncAuth:
return authScheme;
default:
throw new IOException("Unknown authentication scheme from RFB "
+ "server " + authScheme);
}
}
//
// Do the rest of the protocol initialisation.
//
public void doProtocolInitialisation(int[] encodings, int nEncodings)
throws IOException {
System.out.println("sending client init");
writeClientInit();
readServerInit();
System.out.println("Desktop name is " + desktopName);
System.out.println("Desktop size is " + framebufferWidth + " x "
+ framebufferHeight);
setEncodings(encodings, nEncodings);
}
//
// setEncodings() - send the current encodings from the options frame
// to the RFB server.
//
void setEncodings(int[] encodings, int nEncodings) {
try {
if (inNormalProtocol) {
writeSetEncodings(encodings, nEncodings);
}
} catch (Exception e) {
e.printStackTrace();
}
}
//
// Write the client initialisation message
//
void writeClientInit() throws IOException {
if (COMPARTILHAR_DESKTOP) {
os.write(1);
} else {
os.write(0);
}
}
//
// Read the server initialisation message
//
public String desktopName;
public int framebufferWidth, framebufferHeight;
int bitsPerPixel, depth;
boolean bigEndian, trueColour;
int redMax, greenMax, blueMax, redShift, greenShift, blueShift;
void readServerInit() throws IOException {
framebufferWidth = is.readUnsignedShort();
framebufferHeight = is.readUnsignedShort();
bitsPerPixel = is.readUnsignedByte();
depth = is.readUnsignedByte();
bigEndian = (is.readUnsignedByte() != 0);
trueColour = (is.readUnsignedByte() != 0);
redMax = is.readUnsignedShort();
greenMax = is.readUnsignedShort();
blueMax = is.readUnsignedShort();
redShift = is.readUnsignedByte();
greenShift = is.readUnsignedByte();
blueShift = is.readUnsignedByte();
byte[] pad = new byte[3];
is.read(pad);
int nameLength = is.readInt();
byte[] name = new byte[nameLength];
is.readFully(name);
desktopName = new String(name, 0);
Page 3 of 8
RFBProtocol.java
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
5/7/2005 19:34
inNormalProtocol = true;
}
//
// Read the server message type
//
int readServerMessageType() throws IOException {
return is.read();
}
//
// Read a FramebufferUpdate message
//
int updateNRects;
void readFramebufferUpdate() throws IOException {
is.readByte();
updateNRects = is.readUnsignedShort();
}
// Read a FramebufferUpdate rectangle header
int updateRectX, updateRectY, updateRectW, updateRectH, updateRectEncoding;
void readFramebufferUpdateRectHdr() throws IOException {
updateRectX = is.readUnsignedShort();
updateRectY = is.readUnsignedShort();
updateRectW = is.readUnsignedShort();
updateRectH = is.readUnsignedShort();
updateRectEncoding = is.readInt();
if ((updateRectX + updateRectW > framebufferWidth)
|| (updateRectY + updateRectH > framebufferHeight)) {
throw new IOException("Framebuffer update rectangle too large: "
+ updateRectW + "x" + updateRectH + " at (" + updateRectX
+ "," + updateRectY + ")");
}
}
// Read CopyRect source X and Y.
int copyRectSrcX, copyRectSrcY;
void readCopyRect() throws IOException {
copyRectSrcX = is.readUnsignedShort();
copyRectSrcY = is.readUnsignedShort();
}
//
// Read a ServerCutText message
//
String readServerCutText() throws IOException {
byte[] pad = new byte[3];
is.read(pad);
int len = is.readInt();
byte[] text = new byte[len];
is.readFully(text);
return new String(text, 0);
}
//
// Write a FramebufferUpdateRequest message
//
void writeFramebufferUpdateRequest(int x, int y, int w, int h,
boolean incremental) throws IOException {
byte[] b = new byte[10];
b[0] = (byte) FramebufferUpdateRequest;
b[1] = (byte) (incremental ? 1 : 0);
b[2] = (byte) ((x >> 8) & 0xff);
b[3] = (byte) (x & 0xff);
b[4] = (byte) ((y >> 8) & 0xff);
b[5] = (byte) (y & 0xff);
b[6] = (byte) ((w >> 8) & 0xff);
b[7] = (byte) (w & 0xff);
b[8] = (byte) ((h >> 8) & 0xff);
b[9] = (byte) (h & 0xff);
os.write(b);
}
//
// Write a SetPixelFormat message
//
Page 4 of 8
RFBProtocol.java
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
5/7/2005 19:34
void writeSetPixelFormat(int bitsPerPixel, int depth, boolean bigEndian,
boolean trueColour, int redMax, int greenMax, int blueMax,
int redShift, int greenShift, int blueShift) throws IOException {
byte[] b = new byte[20];
b[0] = (byte) SetPixelFormat;
b[4] = (byte) bitsPerPixel;
b[5] = (byte) depth;
b[6] = (byte) (bigEndian ? 1 : 0);
b[7] = (byte) (trueColour ? 1 : 0);
b[8] = (byte) ((redMax >> 8) & 0xff);
b[9] = (byte) (redMax & 0xff);
b[10] = (byte) ((greenMax >> 8) & 0xff);
b[11] = (byte) (greenMax & 0xff);
b[12] = (byte) ((blueMax >> 8) & 0xff);
b[13] = (byte) (blueMax & 0xff);
b[14] = (byte) redShift;
b[15] = (byte) greenShift;
b[16] = (byte) blueShift;
os.write(b);
}
//
// Write a FixColourMapEntries message. The values in the red, green and
// blue arrays are from 0 to 65535.
//
void writeFixColourMapEntries(int firstColour, int nColours, int[] red,
int[] green, int[] blue) throws IOException {
byte[] b = new byte[6 + nColours * 6];
b[0] = (byte) FixColourMapEntries;
b[2] = (byte) ((firstColour >> 8) & 0xff);
b[3] = (byte) (firstColour & 0xff);
b[4] = (byte) ((nColours >> 8) & 0xff);
b[5] = (byte) (nColours & 0xff);
for (int i = 0; i < nColours; i++) {
b[6 + i * 6] = (byte) ((red[i] >> 8) & 0xff);
b[6 + i * 6 + 1] = (byte) (red[i] & 0xff);
b[6 + i * 6 + 2] = (byte) ((green[i] >> 8) & 0xff);
b[6 + i * 6 + 3] = (byte) (green[i] & 0xff);
b[6 + i * 6 + 4] = (byte) ((blue[i] >> 8) & 0xff);
b[6 + i * 6 + 5] = (byte) (blue[i] & 0xff);
}
os.write(b);
}
//
// Write a SetEncodings message
//
void writeSetEncodings(int[] encs, int len) throws IOException {
byte[] b = new byte[4 + 4 * len];
b[0] = (byte) SetEncodings;
b[2] = (byte) ((len >> 8) & 0xff);
b[3] = (byte) (len & 0xff);
for (int i = 0; i < len; i++) {
b[4 + 4 * i] = (byte) ((encs[i] >> 24) & 0xff);
b[5 + 4 * i] = (byte) ((encs[i] >> 16) & 0xff);
b[6 + 4 * i] = (byte) ((encs[i] >> 8) & 0xff);
b[7 + 4 * i] = (byte) (encs[i] & 0xff);
}
os.write(b);
}
//
// Write a ClientCutText message
//
public void writeClientCutText(String text) throws IOException {
byte[] b = new byte[8 + text.length()];
b[0] = (byte) ClientCutText;
b[4] = (byte) ((text.length() >> 24) & 0xff);
b[5] = (byte) ((text.length() >> 16) & 0xff);
b[6] = (byte) ((text.length() >> 8) & 0xff);
b[7] = (byte) (text.length() & 0xff);
text.getBytes(0, text.length(), b, 8);
os.write(b);
}
//
// A buffer for putting pointer and keyboard events before being sent. This
Page 5 of 8
RFBProtocol.java
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
5/7/2005 19:34
// is to ensure that multiple RFB events generated from a single Java Event
// will all be sent in a single network packet. The maximum possible
// length is 4 modifier down events, a single key event followed by 4
// modifier up events i.e. 9 key events or 72 bytes.
//
byte[] eventBuf = new byte[72];
int eventBufLen;
//
// Write a pointer event message. We may need to send modifier key events
// around it to set the correct modifier state. Also buttons 2 and 3 are
// represented as having ALT and META modifiers respectively.
//
int pointerMask = 0;
void writePointerEvent(int tipoEventoMouse, int botao, int x, int y)
throws IOException {
int mask2 = 4;
if (tipoEventoMouse == MouseEvent.MOUSE_PRESSED) {
if (botao == MouseEvent.BUTTON2) {
pointerMask = mask2;
} else {
pointerMask = 1;
}
} else {
if (tipoEventoMouse == MouseEvent.MOUSE_RELEASED) {
pointerMask = 0;
}
}
eventBufLen = 0;
if (x < 0)
x = 0;
if (y < 0)
y = 0;
eventBuf[eventBufLen++] = (byte) PointerEvent;
eventBuf[eventBufLen++] = (byte) pointerMask;
eventBuf[eventBufLen++] = (byte) ((x >> 8) & 0xff);
eventBuf[eventBufLen++] = (byte) (x & 0xff);
eventBuf[eventBufLen++] = (byte) ((y >> 8) & 0xff);
eventBuf[eventBufLen++] = (byte) (y & 0xff);
if (pointerMask == 0) {
writeModifierKeyEvents(0);
}
os.write(eventBuf, 0, eventBufLen);
}
//
// Write a key event message. We may need to send modifier key events
// around it to set the correct modifier state. Also we need to translate
// from the Java key values to the X keysym values used by the RFB protocol.
//
public void sendCtrlAltDel() {
try {
Event ctrlAltDelEvent = new Event(null, 0, null);
ctrlAltDelEvent.key = 127;
ctrlAltDelEvent.modifiers = Event.CTRL_MASK | Event.ALT_MASK;
ctrlAltDelEvent.id = Event.KEY_PRESS;
writeKeyEvent(ctrlAltDelEvent);
ctrlAltDelEvent.id = Event.KEY_RELEASE;
writeKeyEvent(ctrlAltDelEvent);
} catch (Exception e) {
e.printStackTrace();
}
}
void writeKeyEvent(Event evt) throws IOException {
int key = evt.key;
boolean down = false;
if ((evt.id == Event.KEY_PRESS) || (evt.id == Event.KEY_ACTION))
down = true;
if ((evt.id == Event.KEY_ACTION)
|| (evt.id == Event.KEY_ACTION_RELEASE)) {
//
// A KEY_ACTION event should be one of the following. If not then
// just
// ignore the event.
//
Page 6 of 8
RFBProtocol.java
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
5/7/2005 19:34
switch (key) {
case Event.HOME:
key = 0xff50;
break;
case Event.LEFT:
key = 0xff51;
break;
case Event.UP:
key = 0xff52;
break;
case Event.RIGHT:
key = 0xff53;
break;
case Event.DOWN:
key = 0xff54;
break;
case Event.PGUP:
key = 0xff55;
break;
case Event.PGDN:
key = 0xff56;
break;
case Event.END:
key = 0xff57;
break;
case Event.F1:
key = 0xffbe;
break;
case Event.F2:
key = 0xffbf;
break;
case Event.F3:
key = 0xffc0;
break;
case Event.F4:
key = 0xffc1;
break;
case Event.F5:
key = 0xffc2;
break;
case Event.F6:
key = 0xffc3;
break;
case Event.F7:
key = 0xffc4;
break;
case Event.F8:
key = 0xffc5;
break;
case Event.F9:
key = 0xffc6;
break;
case Event.F10:
key = 0xffc7;
break;
case Event.F11:
key = 0xffc8;
break;
case Event.F12:
key = 0xffc9;
break;
default:
return;
}
} else {
//
// A "normal" key press. Ordinary ASCII characters go straight
// through.
// For CTRL-<letter>, CTRL is sent separately so just send <letter>.
// Backspace, tab, return, escape and delete have special keysyms.
// Anything else we ignore.
//
if (key < 32) {
if ((evt.modifiers & Event.CTRL_MASK) != 0) {
key += 96;
} else {
Page 7 of 8
RFBProtocol.java
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
5/7/2005 19:34
switch (key) {
case 8:
key = 0xff08;
break;
case 9:
key = 0xff09;
break;
case 10:
key = 0xff0d;
break;
case 27:
key = 0xff1b;
break;
}
}
} else if (key >= 127) {
if (key == 127) {
key = 0xffff;
} else {
// JDK1.1 on X incorrectly passes some keysyms straight
// through, so
// we do too. JDK1.1.4 seems to have fixed this.
if ((key < 0xff00) || (key > 0xffff))
return;
}
}
}
eventBufLen = 0;
writeModifierKeyEvents(evt.modifiers);
writeKeyEvent(key, down);
//
// Always release all modifiers after an "up" event
//
if (!down) {
writeModifierKeyEvents(0);
}
os.write(eventBuf, 0, eventBufLen);
}
//
// Add a raw key event with the given X keysym to eventBuf.
//
void writeKeyEvent(int keysym, boolean down) throws IOException {
eventBuf[eventBufLen++] = (byte) KeyEvent;
eventBuf[eventBufLen++] = (byte) (down ? 1 : 0);
eventBuf[eventBufLen++] = (byte) 0;
eventBuf[eventBufLen++] = (byte) 0;
eventBuf[eventBufLen++] = (byte) ((keysym >> 24) & 0xff);
eventBuf[eventBufLen++] = (byte) ((keysym >> 16) & 0xff);
eventBuf[eventBufLen++] = (byte) ((keysym >> 8) & 0xff);
eventBuf[eventBufLen++] = (byte) (keysym & 0xff);
}
//
// Write key events to set the correct modifier state.
//
int oldModifiers;
void writeModifierKeyEvents(int newModifiers) throws IOException {
if ((newModifiers & Event.CTRL_MASK) != (oldModifiers & Event.CTRL_MASK))
writeKeyEvent(0xffe3, (newModifiers & Event.CTRL_MASK) != 0);
if ((newModifiers & Event.SHIFT_MASK) != (oldModifiers & Event.SHIFT_MASK))
writeKeyEvent(0xffe1, (newModifiers & Event.SHIFT_MASK) != 0);
if ((newModifiers & Event.META_MASK) != (oldModifiers & Event.META_MASK))
writeKeyEvent(0xffe7, (newModifiers & Event.META_MASK) != 0);
if ((newModifiers & Event.ALT_MASK) != (oldModifiers & Event.ALT_MASK))
writeKeyEvent(0xffe9, (newModifiers & Event.ALT_MASK) != 0);
oldModifiers = newModifiers;
}
}
Page 8 of 8
TelaCelular.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
5/7/2005 19:35
package app.rede;
public class TelaCelular {
private int altura;
private int largura;
public int getAltura() {
return altura;
}
public void setAltura(int altura) {
this.altura = altura;
}
public int getLargura() {
return largura;
}
public void setLargura(int largura) {
this.largura = largura;
}
}
Page 1 of 1
TratadorDeComandos.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
5/7/2005 19:35
package app.rede;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.awt.image.DirectColorModel;
import java.io.IOException;
import app.util.AnimatedMemoryImageSource;
import app.util.Log;
import app.util.TratadorDeImagem;
import app.util.TratadorDoMouse;
public class TratadorDeComandos extends Thread {
private String senhaLocal;
private TratadorDeImagem tratadorDeImagens;
private TratadorDoMouse tratadorDoMouse;
private int portaLocal;
private String senhaExterna;
private boolean botao1DoMousePressionado;
private boolean botao2DoMousePressionado;
private int portaExterna;
private LeitorDeComando leitor;
int largura = 0;
int altura = 0;
private BufferedImage imagemOriginal;
private BufferedImage imagemCelular;
private int[] encodings = new int[10];
private RFBProtocol protocoloRFB;
private DirectColorModel cm;
private Color[] colors;
private byte[] pixels;
private Graphics pig;
private Graphics sg;
private int comandoDoCelular;
private Image paintImage;
private boolean connected;
private boolean needToResetClip;
private int nVezes = 0;
private String hostRodandoVNC;
private boolean mouseAtivado;
public TratadorDeComandos(String _hostRodandoVNC, String _senhaLocal,
int _portaLocal, String _senhaExterna, int _portaExterna) {
senhaLocal = _senhaLocal;
senhaExterna = _senhaExterna;
portaExterna = _portaExterna;
portaLocal = _portaLocal;
hostRodandoVNC = _hostRodandoVNC;
}
private void aguardaConexaoComCelular() {
try {
leitor = new LeitorDeComando(portaExterna);
Log.info("Aguardando conexao na porta " + portaExterna);
TelaCelular telaCelular = leitor.getTelaCelular();
largura = telaCelular.getLargura();
altura = telaCelular.getAltura();
} catch (Exception e) {
e.printStackTrace();
}
}
public void run() {
Log.info("Iniciando tratamento de comandos");
while (true) {
try {
aguardaConexaoComCelular();
// Fazendo conexão local
protocoloRFB = new RFBProtocol(hostRodandoVNC, portaLocal);
// protocoloRFB = new RFBProtocol("localhost", portaLocal);
protocoloRFB.connectAndAuthenticate(senhaLocal);
protocoloRFB.writeClientInit();
protocoloRFB.readServerInit();
Page 1 of 4
TratadorDeComandos.java
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
5/7/2005 19:35
Log.info("Nome: " + protocoloRFB.desktopName);
Log.info("Resolução: " + protocoloRFB.framebufferWidth + " x "
+ protocoloRFB.framebufferHeight);
protocoloRFB.setEncodings(encodings, 1);
protocoloRFB.writeSetPixelFormat(8, 8, false, true, 7, 7, 3, 0,
3, 6);
cm = new DirectColorModel(8, 7, (7 << 3), (3 << 6));
colors = new Color[256];
for (int i = 0; i < 256; i++) {
colors[i] = new Color(cm.getRGB(i));
}
pixels = new byte[protocoloRFB.framebufferWidth
* protocoloRFB.framebufferHeight];
AnimatedMemoryImageSource amis = new AnimatedMemoryImageSource(
protocoloRFB.framebufferWidth,
protocoloRFB.framebufferHeight, cm, pixels);
Image rawPixelsImage = Toolkit.getDefaultToolkit().createImage(
amis);
imagemOriginal = new BufferedImage(
protocoloRFB.framebufferWidth,
protocoloRFB.framebufferHeight,
BufferedImage.TYPE_INT_RGB);
Graphics2D g = imagemOriginal.createGraphics();
pig = imagemOriginal.createGraphics();
sg = imagemOriginal.createGraphics();
processaProtocolo();
Log.info("Finalizando conexao");
leitor.fechaFechaConexao();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
private synchronized void processaProtocolo() throws IOException {
protocoloRFB.writeFramebufferUpdateRequest(0, 0,
protocoloRFB.framebufferWidth, protocoloRFB.framebufferHeight,
true);
while (comandoDoCelular != DP.FINALIZAR_CONEXAO) {
int msgType = protocoloRFB.readServerMessageType();
Log.info("Mensagem do Servidor: " + msgType);
// --------------------------------switch (msgType) {
case RFBProtocol.FramebufferUpdate:
protocoloRFB.readFramebufferUpdate();
for (int i = 0; i < protocoloRFB.updateNRects; i++) {
protocoloRFB.readFramebufferUpdateRectHdr();
switch (protocoloRFB.updateRectEncoding) {
case RFBProtocol.EncodingRaw:
desenhaImagem(protocoloRFB.updateRectX,
protocoloRFB.updateRectY,
protocoloRFB.updateRectW,
protocoloRFB.updateRectH);
break;
default:
throw new IOException("Unknown RFB rectangle encoding "
+ protocoloRFB.updateRectEncoding);
}
}
break;
case RFBProtocol.SetColourMapEntries:
throw new IOException(
"Can't handle SetColourMapEntries message");
case RFBProtocol.Bell:
System.out.print((char) 7);
break;
case RFBProtocol.ServerCutText:
String s = protocoloRFB.readServerCutText();
break;
case -1: // EOF, disconnect
connected = false;
break;
default:
throw new IOException("Unknown RFB message type " + msgType);
}
// --------------------------------Page 2 of 4
TratadorDeComandos.java
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
5/7/2005 19:35
comandoDoCelular = leitor.getComando();
switch (comandoDoCelular) {
case DP.CMD_ZOOM_MENOS:
tratadorDeImagens.zoomMenos(tratadorDoMouse);
break;
case DP.CMD_ZOOM_MAIS:
tratadorDeImagens.zoomMais(tratadorDoMouse);
break;
case DP.CMD_TELA_PARA_CIMA:
tratadorDeImagens.moveParaCima();
break;
case DP.CMD_TELA_PARA_BAIXO:
tratadorDeImagens.moveParaBaixo();
break;
case DP.CMD_TELA_PARA_ESQUERDA:
tratadorDeImagens.moveParaEsquerda();
break;
case DP.CMD_TELA_PARA_DIREITA:
tratadorDeImagens.moveParaDireita();
break;
case DP.CMD_MOUSE_PARA_BAIXO:
tratadorDoMouse.moveParaBaixo();
processaEventoDoMouse(MouseEvent.MOUSE_MOVED, 0);
break;
case DP.CMD_MOUSE_PARA_CIMA:
tratadorDoMouse.moveParaCima();
processaEventoDoMouse(MouseEvent.MOUSE_MOVED, 0);
break;
case DP.CMD_MOUSE_PARA_DIREITA:
tratadorDoMouse.moveParaDireita();
processaEventoDoMouse(MouseEvent.MOUSE_MOVED, 0);
break;
case DP.CMD_MOUSE_PARA_ESQUERDA:
tratadorDoMouse.moveParaEsquerda();
processaEventoDoMouse(MouseEvent.MOUSE_MOVED, 0);
break;
case DP.CMD_BT_MOUSE1:
if (botao1DoMousePressionado) {
processaEventoDoMouse(MouseEvent.MOUSE_RELEASED,
MouseEvent.BUTTON1);
} else {
processaEventoDoMouse(MouseEvent.MOUSE_PRESSED,
MouseEvent.BUTTON1);
}
botao1DoMousePressionado = !botao1DoMousePressionado;
break;
case DP.CMD_BT_MOUSE2:
if (botao2DoMousePressionado) {
processaEventoDoMouse(MouseEvent.MOUSE_RELEASED,
MouseEvent.BUTTON2);
} else {
processaEventoDoMouse(MouseEvent.MOUSE_PRESSED,
MouseEvent.BUTTON2);
}
botao2DoMousePressionado = !botao2DoMousePressionado;
break;
case DP.INICIA_TRATADOR_DE_IMAGENS:
iniciaTratador();
break;
default:
break;
}
sendImage();
// TODO ver tempo entre atualizações
protocoloRFB.writeFramebufferUpdateRequest(0, 0,
protocoloRFB.framebufferWidth,
protocoloRFB.framebufferHeight, false);
/*
* long numMillisecondsToSleep = 250; // 1/4 segundos try {
* Thread.sleep(numMillisecondsToSleep); } catch
* (InterruptedException e) { e.printStackTrace(); }
*/
}
}
private void desenhaImagem(int x, int y, int w, int h) throws IOException {
Page 3 of 4
TratadorDeComandos.java
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
5/7/2005 19:35
// TODO verificar se precisa desenhar cada um
Log.info("Desenhando x=" + x + " y=" + y + " w=" + w + " h=" + h);
Graphics2D g = imagemOriginal.createGraphics();
for (int j = 0; j < protocoloRFB.framebufferHeight; j++) {
for (int k = 0; k < protocoloRFB.framebufferWidth; k++) {
int pixel = protocoloRFB.is.read();
g.setColor(colors[pixel]);
g.fillRect(k, j, 1, 1);
}
}
g.drawImage(imagemOriginal, 0, 0, null);
if (imagemCelular != null) {
imagemCelular.getGraphics().drawImage(imagemOriginal, 0, 0,
tratadorDeImagens.getLargura(),
tratadorDeImagens.getAltura(), tratadorDeImagens.getRetX(),
tratadorDeImagens.getRetY(), tratadorDeImagens.getRetX2(),
tratadorDeImagens.getRetY2(), null);
}
nVezes++;
}
public synchronized void iniciaTratador() {
tratadorDeImagens = new TratadorDeImagem(largura, altura,
protocoloRFB.framebufferWidth, protocoloRFB.framebufferHeight);
tratadorDoMouse = new TratadorDoMouse(protocoloRFB.framebufferWidth,
protocoloRFB.framebufferHeight);
imagemCelular = new BufferedImage(tratadorDeImagens.getLargura(),
tratadorDeImagens.getAltura(), BufferedImage.TYPE_INT_RGB);
}
private synchronized void sendImage() {
try {
leitor.enviaImagem(imagemCelular);
} catch (Exception e) {
e.printStackTrace();
}
}
public void processaEventoDoMouse(int tipoEvento, int botao) {
if (protocoloRFB.inNormalProtocol) {
synchronized (protocoloRFB) {
try {
protocoloRFB.writePointerEvent(tipoEvento, botao,
tratadorDoMouse.getX(), tratadorDoMouse.getY());
} catch (Exception e) {
e.printStackTrace();
}
protocoloRFB.notify();
}
}
}
}
Page 4 of 4
PainelDeAutenticacao.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
5/7/2005 19:36
package app.ui;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import app.rede.TratadorDeComandos;
import app.util.Log;
public class PainelDeAutenticacao extends JFrame {
private javax.swing.JPanel jContentPane = null;
private JTextField txtSenhaLocal = null;
private JButton jButton = null;
private JLabel jLabel = null;
private JTextField txtSenhaExterna = null;
private JLabel jLabel1 = null;
private JTextField txtPortaLocal = null;
private JTextField txtPortaExterna = null;
private JLabel jLabel2 = null;
private JLabel jLabel3 = null;
private JButton jButton1 = null;
private TratadorDeComandos tratadorDeComandos;
private JTextField txtHost = null;
private JLabel jLabel4 = null;
private JTextField getTxtSenhaLocal() {
if (txtSenhaLocal == null) {
txtSenhaLocal = new JTextField();
txtSenhaLocal.setBounds(136, 45, 146, 20);
txtSenhaLocal.setText("testevnc");
}
return txtSenhaLocal;
}
private JButton getJButton() {
if (jButton == null) {
jButton = new JButton();
jButton.setBounds(184, 183, 95, 26);
jButton.setText("Iniciar");
jButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
tratadorDeComandos = new TratadorDeComandos(txtHost
.getText(), txtSenhaLocal.getText(), Integer
.parseInt(txtPortaLocal.getText()), txtSenhaExterna
.getText(), Integer.parseInt(txtPortaExterna
.getText()));
tratadorDeComandos.start();
jButton.setEnabled(false);
}
});
}
return jButton;
}
private void iniciarServidor() {
}
private JTextField getTxtSenhaExterna() {
if (txtSenhaExterna == null) {
txtSenhaExterna = new JTextField();
txtSenhaExterna.setBounds(135, 102, 150, 20);
txtSenhaExterna.setText("x");
}
return txtSenhaExterna;
}
private JTextField getTxtPortaLocal() {
if (txtPortaLocal == null) {
txtPortaLocal = new JTextField();
txtPortaLocal.setBounds(136, 68, 66, 20);
txtPortaLocal.setText("5900");
}
return txtPortaLocal;
}
Page 1 of 3
PainelDeAutenticacao.java
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
5/7/2005 19:36
private JTextField getTxtPortaExterna() {
if (txtPortaExterna == null) {
txtPortaExterna = new JTextField();
txtPortaExterna.setBounds(136, 128, 69, 20);
txtPortaExterna.setText("8080");
}
return txtPortaExterna;
}
private JButton getJButton1() {
if (jButton1 == null) {
jButton1 = new JButton();
jButton1.setBounds(61, 183, 92, 27);
jButton1.setText("Fechar");
jButton1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
Log.info("Saindo da aplicação");
System.exit(0);
}
});
}
return jButton1;
}
/**
* This method initializes jTextField
*
* @return javax.swing.JTextField
*/
private JTextField getTxtHost() {
if (txtHost == null) {
txtHost = new JTextField();
txtHost.setBounds(136, 19, 144, 20);
txtHost.setText("192.168.152.38");
}
return txtHost;
}
public static void main(String[] args) {
PainelDeAutenticacao painel = new PainelDeAutenticacao();
painel.initialize();
}
private void initialize() {
this.setSize(365, 270);
this.setContentPane(getJContentPane());
this.setTitle("VNC para celular - módulo PC");
this.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
Log.info("fechando aplicação");
System.exit(0);
}
});
this.show();
}
private javax.swing.JPanel getJContentPane() {
if (jContentPane == null) {
jLabel4 = new JLabel();
jLabel3 = new JLabel();
jLabel2 = new JLabel();
jLabel1 = new JLabel();
jLabel = new JLabel();
jContentPane = new javax.swing.JPanel();
jContentPane.setLayout(null);
jLabel.setBounds(79, 45, 45, 20);
jLabel.setText("Senha:");
jLabel1.setBounds(28, 98, 92, 25);
jLabel1.setText("Senha Externa:");
jLabel2.setBounds(82, 71, 39, 16);
jLabel2.setText("Porta:");
jLabel3.setBounds(30, 129, 95, 17);
jLabel3.setText("Porta Externa:");
jLabel4.setBounds(62, 19, 59, 17);
jLabel4.setText("Host VNC:");
jContentPane.add(getTxtSenhaLocal(), null);
Page 2 of 3
PainelDeAutenticacao.java
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
5/7/2005 19:36
jContentPane.add(getJButton(), null);
jContentPane.add(jLabel, null);
jContentPane.add(getTxtSenhaExterna(), null);
jContentPane.add(jLabel1, null);
jContentPane.add(getTxtPortaLocal(), null);
jContentPane.add(getTxtPortaExterna(), null);
jContentPane.add(jLabel2, null);
jContentPane.add(jLabel3, null);
jContentPane.add(getJButton1(), null);
jContentPane.add(getTxtHost(), null);
jContentPane.add(jLabel4, null);
}
return jContentPane;
}
} // @jve:decl-index=0:visual-constraint="10,10"
Page 3 of 3
AnimatedMemoryImageSource.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
5/7/2005 19:38
//
// Código com licensa GPL;
// Retirado do site http://www.tightvnc.com/
//
package app.util;
import java.awt.image.*;
public class AnimatedMemoryImageSource implements ImageProducer {
int width;
int height;
ColorModel cm;
byte[] pixels;
ImageConsumer ic;
public AnimatedMemoryImageSource(int w, int h, ColorModel c, byte[] p) {
width = w;
height = h;
cm = c;
pixels = p;
}
public void addConsumer(ImageConsumer c) {
if (ic == c)
return;
if (ic != null) {
ic.imageComplete(ImageConsumer.IMAGEERROR);
}
ic = c;
ic.setDimensions(width, height);
ic.setColorModel(cm);
ic.setHints(ImageConsumer.RANDOMPIXELORDER);
ic.setPixels(0, 0, width, height, cm, pixels, 0, width);
ic.imageComplete(ImageConsumer.SINGLEFRAMEDONE);
}
public boolean isConsumer(ImageConsumer c) {
return (ic == c);
}
public void removeConsumer(ImageConsumer c) {
if (ic == c)
ic = null;
}
public void requestTopDownLeftRightResend(ImageConsumer c) {
}
public void startProduction(ImageConsumer c) {
addConsumer(c);
}
void newPixels(int x, int y, int w, int h) {
if (ic != null) {
ic.setPixels(x, y, w, h, cm, pixels, width * y + x, width);
ic.imageComplete(ImageConsumer.SINGLEFRAMEDONE);
}
}
}
Page 1 of 1
DesCipher.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
5/7/2005 19:38
//Boa parte do código foi desenvolvido por
//Retirado do site www.acme.com
package app.util;
Dave Zimmerman <[email protected]>
public class DesCipher {
public DesCipher(byte[] key) {
setKey(key);
}
// Key routines.
private int[] encryptKeys = new int[32];
private int[] decryptKeys = new int[32];
// / Set the key.
public void setKey(byte[] key) {
deskey(key, true, encryptKeys);
deskey(key, false, decryptKeys);
}
// Turn an 8-byte key into internal keys.
private void deskey(byte[] keyBlock, boolean encrypting, int[] KnL) {
int i, j, l, m, n;
int[] pc1m = new int[56];
int[] pcr = new int[56];
int[] kn = new int[32];
for (j = 0; j < 56; ++j) {
l = pc1[j];
m = l & 07;
pc1m[j] = ((keyBlock[l >>> 3] & bytebit[m]) != 0) ? 1 : 0;
}
for (i = 0; i < 16; ++i) {
if (encrypting)
m = i << 1;
else
m = (15 - i) << 1;
n = m + 1;
kn[m] = kn[n] = 0;
for (j = 0; j < 28; ++j) {
l = j + totrot[i];
if (l < 28)
pcr[j] = pc1m[l];
else
pcr[j] = pc1m[l - 28];
}
for (j = 28; j < 56; ++j) {
l = j + totrot[i];
if (l < 56)
pcr[j] = pc1m[l];
else
pcr[j] = pc1m[l - 28];
}
for (j = 0; j < 24; ++j) {
if (pcr[pc2[j]] != 0)
kn[m] |= bigbyte[j];
if (pcr[pc2[j + 24]] != 0)
kn[n] |= bigbyte[j];
}
}
cookey(kn, KnL);
}
private
int
int
int
for
void cookey(int[] raw, int KnL[]) {
raw0, raw1;
rawi, KnLi;
i;
(i = 0, rawi = 0, KnLi = 0; i < 16; ++i) {
raw0 = raw[rawi++];
raw1 = raw[rawi++];
KnL[KnLi] = (raw0 & 0x00fc0000) << 6;
KnL[KnLi] |= (raw0 & 0x00000fc0) << 10;
KnL[KnLi] |= (raw1 & 0x00fc0000) >>> 10;
KnL[KnLi] |= (raw1 & 0x00000fc0) >>> 6;
++KnLi;
KnL[KnLi] = (raw0 & 0x0003f000) << 12;
KnL[KnLi] |= (raw0 & 0x0000003f) << 16;
KnL[KnLi] |= (raw1 & 0x0003f000) >>> 4;
KnL[KnLi] |= (raw1 & 0x0000003f);
Page 1 of 5
DesCipher.java
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
5/7/2005 19:38
++KnLi;
}
}
// Block encryption routines.
private int[] tempInts = new int[2];
// / Encrypt a block of eight bytes.
public void encrypt(byte[] clearText, int clearOff, byte[] cipherText,
int cipherOff) {
squashBytesToInts(clearText, clearOff, tempInts, 0, 2);
des(tempInts, tempInts, encryptKeys);
spreadIntsToBytes(tempInts, 0, cipherText, cipherOff, 2);
}
// / Decrypt a block of eight bytes.
public void decrypt(byte[] cipherText, int cipherOff, byte[] clearText,
int clearOff) {
squashBytesToInts(cipherText, cipherOff, tempInts, 0, 2);
des(tempInts, tempInts, decryptKeys);
spreadIntsToBytes(tempInts, 0, clearText, clearOff, 2);
}
// The DES function.
private void des(int[] inInts, int[] outInts, int[] keys) {
int fval, work, right, leftt;
int round;
int keysi = 0;
leftt = inInts[0];
right = inInts[1];
work = ((leftt >>> 4) ^ right) & 0x0f0f0f0f;
right ^= work;
leftt ^= (work << 4);
work = ((leftt >>> 16) ^ right) & 0x0000ffff;
right ^= work;
leftt ^= (work << 16);
work = ((right >>> 2) ^ leftt) & 0x33333333;
leftt ^= work;
right ^= (work << 2);
work = ((right >>> 8) ^ leftt) & 0x00ff00ff;
leftt ^= work;
right ^= (work << 8);
right = (right << 1) | ((right >>> 31) & 1);
work = (leftt ^ right) & 0xaaaaaaaa;
leftt ^= work;
right ^= work;
leftt = (leftt << 1) | ((leftt >>> 31) & 1);
for (round = 0; round < 8; ++round) {
work = (right << 28) | (right >>> 4);
work ^= keys[keysi++];
fval = SP7[work & 0x0000003f];
fval |= SP5[(work >>> 8) & 0x0000003f];
fval |= SP3[(work >>> 16) & 0x0000003f];
fval |= SP1[(work >>> 24) & 0x0000003f];
work = right ^ keys[keysi++];
fval |= SP8[work & 0x0000003f];
fval |= SP6[(work >>> 8) & 0x0000003f];
fval |= SP4[(work >>> 16) & 0x0000003f];
fval |= SP2[(work >>> 24) & 0x0000003f];
leftt ^= fval;
work = (leftt << 28) | (leftt >>> 4);
work ^= keys[keysi++];
fval = SP7[work & 0x0000003f];
fval |= SP5[(work >>> 8) & 0x0000003f];
fval |= SP3[(work >>> 16) & 0x0000003f];
fval |= SP1[(work >>> 24) & 0x0000003f];
work = leftt ^ keys[keysi++];
fval |= SP8[work & 0x0000003f];
fval |= SP6[(work >>> 8) & 0x0000003f];
fval |= SP4[(work >>> 16) & 0x0000003f];
fval |= SP2[(work >>> 24) & 0x0000003f];
right ^= fval;
}
right = (right << 31) | (right >>> 1);
work = (leftt ^ right) & 0xaaaaaaaa;
leftt ^= work;
right ^= work;
Page 2 of 5
DesCipher.java
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
5/7/2005 19:38
leftt = (leftt << 31) | (leftt >>> 1);
work = ((leftt >>> 8) ^ right) & 0x00ff00ff;
right ^= work;
leftt ^= (work << 8);
work = ((leftt >>> 2) ^ right) & 0x33333333;
right ^= work;
leftt ^= (work << 2);
work = ((right >>> 16) ^ leftt) & 0x0000ffff;
leftt ^= work;
right ^= (work << 16);
work = ((right >>> 4) ^ leftt) & 0x0f0f0f0f;
leftt ^= work;
right ^= (work << 4);
outInts[0] = right;
outInts[1] = leftt;
}
// Tables, permutations, S-boxes, etc.
private static byte[] bytebit = { (byte) 0x01, (byte) 0x02, (byte) 0x04,
(byte) 0x08, (byte) 0x10, (byte) 0x20, (byte) 0x40, (byte) 0x80 };
private static int[] bigbyte = { 0x800000, 0x400000, 0x200000, 0x100000,
0x080000, 0x040000, 0x020000, 0x010000, 0x008000, 0x004000,
0x002000, 0x001000, 0x000800, 0x000400, 0x000200, 0x000100,
0x000080, 0x000040, 0x000020, 0x000010, 0x000008, 0x000004,
0x000002, 0x000001 };
private static byte[] pc1 = { (byte) 56, (byte) 48, (byte) 40, (byte) 32,
(byte) 24, (byte) 16, (byte) 8, (byte) 0, (byte) 57, (byte) 49,
(byte) 41, (byte) 33, (byte) 25, (byte) 17, (byte) 9, (byte) 1,
(byte) 58, (byte) 50, (byte) 42, (byte) 34, (byte) 26, (byte) 18,
(byte) 10, (byte) 2, (byte) 59, (byte) 51, (byte) 43, (byte) 35,
(byte) 62, (byte) 54, (byte) 46, (byte) 38, (byte) 30, (byte) 22,
(byte) 14, (byte) 6, (byte) 61, (byte) 53, (byte) 45, (byte) 37,
(byte) 29, (byte) 21, (byte) 13, (byte) 5, (byte) 60, (byte) 52,
(byte) 44, (byte) 36, (byte) 28, (byte) 20, (byte) 12, (byte) 4,
(byte) 27, (byte) 19, (byte) 11, (byte) 3 };
private static int[] totrot = { 1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21,
23, 25, 27, 28 };
private static byte[] pc2 = { (byte) 13, (byte) 16, (byte) 10, (byte) 23,
(byte) 0, (byte) 4, (byte) 2, (byte) 27, (byte) 14, (byte) 5,
(byte) 20, (byte) 9, (byte) 22, (byte) 18, (byte) 11, (byte) 3,
(byte) 25, (byte) 7, (byte) 15, (byte) 6, (byte) 26, (byte) 19,
(byte) 12, (byte) 1, (byte) 40, (byte) 51, (byte) 30, (byte) 36,
(byte) 46, (byte) 54, (byte) 29, (byte) 39, (byte) 50, (byte) 44,
(byte) 32, (byte) 47, (byte) 43, (byte) 48, (byte) 38, (byte) 55,
(byte) 33, (byte) 52, (byte) 45, (byte) 41, (byte) 49, (byte) 35,
(byte) 28, (byte) 31, };
private static int[] SP1 = { 0x01010400, 0x00000000, 0x00010000,
0x01010404, 0x01010004, 0x00010404, 0x00000004, 0x00010000,
0x00000400, 0x01010400, 0x01010404, 0x00000400, 0x01000404,
0x01010004, 0x01000000, 0x00000004, 0x00000404, 0x01000400,
0x01000400, 0x00010400, 0x00010400, 0x01010000, 0x01010000,
0x01000404, 0x00010004, 0x01000004, 0x01000004, 0x00010004,
0x00000000, 0x00000404, 0x00010404, 0x01000000, 0x00010000,
0x01010404, 0x00000004, 0x01010000, 0x01010400, 0x01000000,
0x01000000, 0x00000400, 0x01010004, 0x00010000, 0x00010400,
0x01000004, 0x00000400, 0x00000004, 0x01000404, 0x00010404,
0x01010404, 0x00010004, 0x01010000, 0x01000404, 0x01000004,
0x00000404, 0x00010404, 0x01010400, 0x00000404, 0x01000400,
0x01000400, 0x00000000, 0x00010004, 0x00010400, 0x00000000,
0x01010004 };
private static int[] SP2 = { 0x80108020, 0x80008000, 0x00008000,
0x00108020, 0x00100000, 0x00000020, 0x80100020, 0x80008020,
0x80000020, 0x80108020, 0x80108000, 0x80000000, 0x80008000,
0x00100000, 0x00000020, 0x80100020, 0x00108000, 0x00100020,
0x80008020, 0x00000000, 0x80000000, 0x00008000, 0x00108020,
0x80100000, 0x00100020, 0x80000020, 0x00000000, 0x00108000,
0x00008020, 0x80108000, 0x80100000, 0x00008020, 0x00000000,
0x00108020, 0x80100020, 0x00100000, 0x80008020, 0x80100000,
0x80108000, 0x00008000, 0x80100000, 0x80008000, 0x00000020,
0x80108020, 0x00108020, 0x00000020, 0x00008000, 0x80000000,
0x00008020, 0x80108000, 0x00100000, 0x80000020, 0x00100020,
0x80008020, 0x80000020, 0x00100020, 0x00108000, 0x00000000,
0x80008000, 0x00008020, 0x80000000, 0x80100020, 0x80108020,
0x00108000 };
private static int[] SP3 = { 0x00000208, 0x08020200, 0x00000000,
0x08020008, 0x08000200, 0x00000000, 0x00020208, 0x08000200,
0x00020008, 0x08000008, 0x08000008, 0x00020000, 0x08020208,
Page 3 of 5
DesCipher.java
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
private
private
private
private
private
5/7/2005 19:38
0x00020008, 0x08020000, 0x00000208, 0x08000000, 0x00000008,
0x08020200, 0x00000200, 0x00020200, 0x08020000, 0x08020008,
0x00020208, 0x08000208, 0x00020200, 0x00020000, 0x08000208,
0x00000008, 0x08020208, 0x00000200, 0x08000000, 0x08020200,
0x08000000, 0x00020008, 0x00000208, 0x00020000, 0x08020200,
0x08000200, 0x00000000, 0x00000200, 0x00020008, 0x08020208,
0x08000200, 0x08000008, 0x00000200, 0x00000000, 0x08020008,
0x08000208, 0x00020000, 0x08000000, 0x08020208, 0x00000008,
0x00020208, 0x00020200, 0x08000008, 0x08020000, 0x08000208,
0x00000208, 0x08020000, 0x00020208, 0x00000008, 0x08020008,
0x00020200 };
static int[] SP4 = { 0x00802001, 0x00002081, 0x00002081,
0x00000080, 0x00802080, 0x00800081, 0x00800001, 0x00002001,
0x00000000, 0x00802000, 0x00802000, 0x00802081, 0x00000081,
0x00000000, 0x00800080, 0x00800001, 0x00000001, 0x00002000,
0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002001,
0x00002080, 0x00800081, 0x00000001, 0x00002080, 0x00800080,
0x00002000, 0x00802080, 0x00802081, 0x00000081, 0x00800080,
0x00800001, 0x00802000, 0x00802081, 0x00000081, 0x00000000,
0x00000000, 0x00802000, 0x00002080, 0x00800080, 0x00800081,
0x00000001, 0x00802001, 0x00002081, 0x00002081, 0x00000080,
0x00802081, 0x00000081, 0x00000001, 0x00002000, 0x00800001,
0x00002001, 0x00802080, 0x00800081, 0x00002001, 0x00002080,
0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002000,
0x00802080 };
static int[] SP5 = { 0x00000100, 0x02080100, 0x02080000,
0x42000100, 0x00080000, 0x00000100, 0x40000000, 0x02080000,
0x40080100, 0x00080000, 0x02000100, 0x40080100, 0x42000100,
0x42080000, 0x00080100, 0x40000000, 0x02000000, 0x40080000,
0x40080000, 0x00000000, 0x40000100, 0x42080100, 0x42080100,
0x02000100, 0x42080000, 0x40000100, 0x00000000, 0x42000000,
0x02080100, 0x02000000, 0x42000000, 0x00080100, 0x00080000,
0x42000100, 0x00000100, 0x02000000, 0x40000000, 0x02080000,
0x42000100, 0x40080100, 0x02000100, 0x40000000, 0x42080000,
0x02080100, 0x40080100, 0x00000100, 0x02000000, 0x42080000,
0x42080100, 0x00080100, 0x42000000, 0x42080100, 0x02080000,
0x00000000, 0x40080000, 0x42000000, 0x00080100, 0x02000100,
0x40000100, 0x00080000, 0x00000000, 0x40080000, 0x02080100,
0x40000100 };
static int[] SP6 = { 0x20000010, 0x20400000, 0x00004000,
0x20404010, 0x20400000, 0x00000010, 0x20404010, 0x00400000,
0x20004000, 0x00404010, 0x00400000, 0x20000010, 0x00400010,
0x20004000, 0x20000000, 0x00004010, 0x00000000, 0x00400010,
0x20004010, 0x00004000, 0x00404000, 0x20004010, 0x00000010,
0x20400010, 0x20400010, 0x00000000, 0x00404010, 0x20404000,
0x00004010, 0x00404000, 0x20404000, 0x20000000, 0x20004000,
0x00000010, 0x20400010, 0x00404000, 0x20404010, 0x00400000,
0x00004010, 0x20000010, 0x00400000, 0x20004000, 0x20000000,
0x00004010, 0x20000010, 0x20404010, 0x00404000, 0x20400000,
0x00404010, 0x20404000, 0x00000000, 0x20400010, 0x00000010,
0x00004000, 0x20400000, 0x00404010, 0x00004000, 0x00400010,
0x20004010, 0x00000000, 0x20404000, 0x20000000, 0x00400010,
0x20004010 };
static int[] SP7 = { 0x00200000, 0x04200002, 0x04000802,
0x00000000, 0x00000800, 0x04000802, 0x00200802, 0x04200800,
0x04200802, 0x00200000, 0x00000000, 0x04000002, 0x00000002,
0x04000000, 0x04200002, 0x00000802, 0x04000800, 0x00200802,
0x00200002, 0x04000800, 0x04000002, 0x04200000, 0x04200800,
0x00200002, 0x04200000, 0x00000800, 0x00000802, 0x04200802,
0x00200800, 0x00000002, 0x04000000, 0x00200800, 0x04000000,
0x00200800, 0x00200000, 0x04000802, 0x04000802, 0x04200002,
0x04200002, 0x00000002, 0x00200002, 0x04000000, 0x04000800,
0x00200000, 0x04200800, 0x00000802, 0x00200802, 0x04200800,
0x00000802, 0x04000002, 0x04200802, 0x04200000, 0x00200800,
0x00000000, 0x00000002, 0x04200802, 0x00000000, 0x00200802,
0x04200000, 0x00000800, 0x04000002, 0x04000800, 0x00000800,
0x00200002 };
static int[] SP8 = { 0x10001040, 0x00001000, 0x00040000,
0x10041040, 0x10000000, 0x10001040, 0x00000040, 0x10000000,
0x00040040, 0x10040000, 0x10041040, 0x00041000, 0x10041000,
0x00041040, 0x00001000, 0x00000040, 0x10040000, 0x10000040,
0x10001000, 0x00001040, 0x00041000, 0x00040040, 0x10040040,
0x10041000, 0x00001040, 0x00000000, 0x00000000, 0x10040040,
0x10000040, 0x10001000, 0x00041040, 0x00040000, 0x00041040,
0x00040000, 0x10041000, 0x00001000, 0x00000040, 0x10040040,
0x00001000, 0x00041040, 0x10001000, 0x00000040, 0x10000040,
Page 4 of 5
DesCipher.java
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
5/7/2005 19:38
0x10040000, 0x10040040,
0x00000000, 0x10041040,
0x10001000, 0x10001040,
0x00041000, 0x00001040,
0x10041000 };
0x10000000,
0x00040040,
0x00000000,
0x00001040,
0x00040000,
0x10000040,
0x10041040,
0x00040040,
0x10001040,
0x10040000,
0x00041000,
0x10000000,
// Routines taken from other parts of the Acme utilities.
// / Squash bytes down to ints.
public static void squashBytesToInts(byte[] inBytes, int inOff,
int[] outInts, int outOff, int intLen) {
for (int i = 0; i < intLen; ++i)
outInts[outOff + i] = ((inBytes[inOff + i * 4] & 0xff) << 24)
| ((inBytes[inOff + i * 4 + 1] & 0xff) << 16)
| ((inBytes[inOff + i * 4 + 2] & 0xff) << 8)
| (inBytes[inOff + i * 4 + 3] & 0xff);
}
// / Spread ints into bytes.
public static void spreadIntsToBytes(int[] inInts, int inOff,
byte[] outBytes, int outOff, int intLen) {
for (int i = 0; i < intLen; ++i) {
outBytes[outOff + i * 4] = (byte) (inInts[inOff + i] >>> 24);
outBytes[outOff + i * 4 + 1] = (byte) (inInts[inOff + i] >>> 16);
outBytes[outOff + i * 4 + 2] = (byte) (inInts[inOff + i] >>> 8);
outBytes[outOff + i * 4 + 3] = (byte) inInts[inOff + i];
}
}
}
Page 5 of 5
Log.java
1
2
3
4
5
6
7
8
9
10
11
12
5/7/2005 19:38
package app.util;
public class Log {
public static void info(String texto) {
// System.out.println("Info: "+texto);
}
public static void erro(String texto) {
System.out.println("Erro: " + texto);
}
}
Page 1 of 1
TratadorDeImagem.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
5/7/2005 19:39
package app.util;
import java.awt.image.BufferedImage;
public class TratadorDeImagem {
private int largura;
private int fatorDeMovimento;
private int altura;
private int alturaOriginal;
private int larguraOriginal;
private int retX;
private int retY;
private int retX2;
private int retY2;
private int fatorDeZoomX;
private int fatorDeZoomY;
public TratadorDeImagem(int _largura, int _altura, int _larguraOriginal,
int _alturaOriginal) {
int t = _larguraOriginal / _largura;
largura = _largura;
altura = (int) Math.round(_alturaOriginal / t);
alturaOriginal = _alturaOriginal;
larguraOriginal = _larguraOriginal;
retX = 0;
retY = 0;
retY2 = alturaOriginal;
retX2 = larguraOriginal;
fatorDeMovimento = 100;
fatorDeZoomX = 100;
fatorDeZoomY = (int) Math.round(((fatorDeZoomX * altura) / largura));
}
public BufferedImage redimensionaImagem(BufferedImage imagem) {
BufferedImage image = new BufferedImage(largura, altura,
BufferedImage.TYPE_INT_RGB);
image.getGraphics().drawImage(imagem, 0, 0, largura, altura, retX,
retY, retX2, retY2, null);
// imagem.getGraphics().drawImage(image, 0, 0,largura,altura, null);
// Graphics g=image.getGraphics();
// / g.drawImage(imagem,x,y,width,height,this);
return image;
}
public synchronized void moveParaEsquerda() {
if (retX != 0) {
if ((retX - fatorDeMovimento) >= 0) {
retX = retX - fatorDeMovimento;
retX2 = retX2 - fatorDeMovimento;
} else {
int fatorTemporario = fatorDeMovimento - retX;
retX = 0;
retX2 = retX2 - fatorTemporario;
}
}
}
public synchronized void moveParaDireita() {
if (retX2 != larguraOriginal) {
if ((fatorDeMovimento + retX2) <= larguraOriginal) {
retX = retX + fatorDeMovimento;
retX2 = retX2 + fatorDeMovimento;
} else {
int fatorTemporario = larguraOriginal - retX2;
retX2 = larguraOriginal;
retX = retX + fatorTemporario;
}
}
}
public synchronized void moveParaBaixo() {
if (retY2 != alturaOriginal) {
if ((fatorDeMovimento + retY2) <= alturaOriginal) {
retY = retY + fatorDeMovimento;
retY2 = retY2 + fatorDeMovimento;
} else {
int fatorTemporario = alturaOriginal - retY2;
Page 1 of 3
TratadorDeImagem.java
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
5/7/2005 19:39
retY2 = alturaOriginal;
retY = retY + fatorTemporario;
}
}
}
public synchronized void moveParaCima() {
if (retY != 0) {
if ((retY - fatorDeMovimento) >= 0) {
retY = retY - fatorDeMovimento;
retY2 = retY2 - fatorDeMovimento;
} else {
int fatorTemporario = fatorDeMovimento - retY;
retY = 0;
retY2 = retY2 - fatorTemporario;
}
}
}
public synchronized void zoomMais(TratadorDoMouse tMouse) {
if (((retX2 - retX) - fatorDeZoomX) >= largura) {
int fatorX = fatorDeZoomX / 2;
int fatorY = fatorDeZoomY / 2;
retX2 = retX2 - fatorX;
retY2 = retY2 - fatorY;
retX = retX + fatorX;
retY = retY + fatorY;
tMouse.zoomMais();
} else {
int fatorDeZoomTemporario = (retX2 - retX) - largura;
if (fatorDeZoomTemporario != 0) {
int fatorX = (int) Math.round(fatorDeZoomTemporario / 2);
int fatorDeZoomTemporarioY = (int) Math
.round(((fatorDeZoomTemporario * altura) / largura));
int fatorY = (int) Math.round(fatorDeZoomTemporarioY / 2);
retX2 = retX2 - fatorX;
retY2 = retY2 - fatorY;
retX = retX + fatorX;
retY = retY + fatorY;
}
}
}
public synchronized void zoomMenos(TratadorDoMouse tMouse) {
if (((retX2 - retX) + fatorDeZoomX) <= larguraOriginal) {
int fatorX = fatorDeZoomX / 2;
int fatorY = fatorDeZoomY / 2;
retX2 = retX2 + fatorX;
retY2 = retY2 + fatorY;
retX = retX - fatorX;
retY = retY - fatorY;
tMouse.zoomMenos();
}
}
public int getAltura() {
return altura;
}
public void setAltura(int altura) {
this.altura = altura;
}
public int getAlturaOriginal() {
return alturaOriginal;
}
public void setAlturaOriginal(int alturaOriginal) {
this.alturaOriginal = alturaOriginal;
}
public int getFatorDeMovimento() {
return fatorDeMovimento;
}
public void setFatorDeMovimento(int fatorDeMovimento) {
Page 2 of 3
TratadorDeImagem.java
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
5/7/2005 19:39
this.fatorDeMovimento = fatorDeMovimento;
}
public int getFatorDeZoomX() {
return fatorDeZoomX;
}
public void setFatorDeZoomX(int fatorDeZoomX) {
this.fatorDeZoomX = fatorDeZoomX;
}
public int getFatorDeZoomY() {
return fatorDeZoomY;
}
public void setFatorDeZoomY(int fatorDeZoomY) {
this.fatorDeZoomY = fatorDeZoomY;
}
public int getLargura() {
return largura;
}
public void setLargura(int largura) {
this.largura = largura;
}
public int getLarguraOriginal() {
return larguraOriginal;
}
public void setLarguraOriginal(int larguraOriginal) {
this.larguraOriginal = larguraOriginal;
}
public int getRetX() {
return retX;
}
public void setRetX(int retX) {
this.retX = retX;
}
public int getRetX2() {
return retX2;
}
public void setRetX2(int retX2) {
this.retX2 = retX2;
}
public int getRetY() {
return retY;
}
public void setRetY(int retY) {
this.retY = retY;
}
public int getRetY2() {
return retY2;
}
public void setRetY2(int retY2) {
this.retY2 = retY2;
}
}
Page 3 of 3
TratadorDoMouse.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
5/7/2005 19:39
package app.util;
public class TratadorDoMouse {
private int fatorDeMovimento;
private int alturaOriginal;
private int larguraOriginal;
private int x;
private int y;
private int fatorDeZoom;
private int fatorDeMovimentoInicial;
public TratadorDoMouse(int _larguraOriginal, int _alturaOriginal) {
alturaOriginal = _alturaOriginal;
larguraOriginal = _larguraOriginal;
x = (int) (Math.round(larguraOriginal) / 2);
y = (int) (Math.round(alturaOriginal) / 2);
fatorDeMovimento = 60;
fatorDeMovimentoInicial = 60;
fatorDeZoom = 10;
}
public synchronized void moveParaEsquerda() {
if ((x - fatorDeMovimento) > 0) {
x = x - fatorDeMovimento;
} else {
x = 0;
}
}
public synchronized void moveParaDireita() {
if ((x + fatorDeMovimento) < larguraOriginal) {
x = x + fatorDeMovimento;
} else {
x = larguraOriginal;
}
}
public synchronized void moveParaBaixo() {
if ((y + fatorDeMovimento) < alturaOriginal) {
y = y + fatorDeMovimento;
} else {
y = alturaOriginal;
}
}
public synchronized void moveParaCima() {
if ((y - fatorDeMovimento) > 0) {
y = y - fatorDeMovimento;
} else {
y = 0;
}
}
public synchronized void zoomMais() {
if ((fatorDeMovimento - fatorDeZoom) > fatorDeZoom) {
fatorDeMovimento = fatorDeMovimento - fatorDeZoom;
} else {
fatorDeMovimento = fatorDeZoom;
}
Log.info("Fator de mov em:" + fatorDeMovimento);
}
public synchronized void zoomMenos() {
if ((fatorDeMovimento + fatorDeZoom) < fatorDeMovimento) {
fatorDeMovimento = fatorDeMovimento + fatorDeZoom;
} else {
fatorDeMovimento = fatorDeMovimentoInicial;
}
Log.info("Fator de mov em:" + fatorDeMovimento);
}
public int getX() {
return x;
}
public void setX(int x) {
Page 1 of 2
TratadorDoMouse.java
77
78
79
80
81
82
83
84
85
86
87
5/7/2005 19:39
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
Page 2 of 2
APÊNDICE C – Artigo
JNC MOBILE – SISTEMA DE ACESSO REMOTO PARA
DISPOSITIVOS MÓVEIS
Andrei L. Krause e Rafael A. da Silva 1
RESUMO
Apesar de a popularização dos dispositivos móveis ter corroborado para o
desenvolvimento de vários serviços e funcionalidades, o poder de processamento e a
capacidade de armazenamento destes dispositivos ainda são muito limitados. Em
razão disso, os aplicativos desenvolvidos para estes tipos de dispositivos devem
manter uma certa simplicidade. Este trabalho propõe uma aplicação que viabiliza o
acesso remoto a estações de trabalho via um dispositivo móvel. Com a mobilidade e
a conectividade dos dispositivos móveis aliados ao poder de processamento de
estações de trabalho, é possível executar tarefas complexas a partir de um dispositivo
móvel.
Palavras-chave: Computação móvel. Computação remota. J2ME. Dispositivos
móveis. VNC.
ABSTRACT
The mobile devices appear currently in the market as merchandises in frank
expansion. Of this form, it is necessary that the services offered for these devices, are
each time more than excellency, providing the maximum of utility to the users. The
objective of this research is exactly to present a software capable to offer the power of
processing of a workstation with the practice, mobility and connectivity of the mobile
devices as cell phones. The tool in this presented document, makes possible the
remote access of a computer through a simple cellular telephone, offering its user, the
experience to use softwares available only for machines with more robust processing.
It also knows the tools that make possible the conception of this new paradigm of
programming and software development.
Keywords: Mobile computation. Remote computation. J2ME. Móbile devices. VNC.
1
[email protected]; [email protected]. Acadêmicos do Curso de Bacharelado em Ciências da
Computação da Universidade Federal de Santa Catarina.
1. INTRODUÇÃO
A evolução e a popularização de dispositivos móveis como celulares,
notenooks, PDAs (Personal Digital Assistants), dispositivos discados móveis (GPS –
Global Positional System), entre outros, têm oferecido uma gama de serviços e
funcionalidades. Para suportar estes serviços, os dispositivos móveis, que têm na
forma dos telefones celulares seus mais evidentes representantes, evoluiram
consideravelmente. Aparelhos que eram utilizados apenas para fazer ligações,
passaram rapidamente a figurar como agendas eletrônicas, câmeras fotográficas
digitais, gravadores de som digital e computadores de mão.
Mesmo com tantas funcionalidades sendo oferecidas, o poder de
processamento e a capacidade de armazenamento destes dispositivos ainda são
muito limitados. Uma maneira de oferecer poder computacional e proporcionar
acesso a serviços exclusivos das estações de trabalho é o acesso remoto via
dispositivos móveis a estações de trabalho. Com o poder de mobilidade e
conectividade dos dispositivos móveis, aliados a inovadora tecnologia J2ME da Sun,
esta pesquisa visa apresentar uma solução capaz de conectar remotamente uma
estação de trabalho a um aparelho móvel.
Inicialmente, o capítulo 2 discorre sobre os dispositivos móveis e suas
características. O capítulo 3 apresenta o Java 2 Micro Edition (J2ME) e trata da
importância desta API para o desenvolvimento do trabalho. O capítulo 4 apresenta os
princípios do VNC (Virtual Network Computing) que serviram como base para a idéia
proposta. Por fim, o capítulo 5 apresenta o trabalho desenvolvido.
2. DISPOSITIVOS MÓVEIS
Em geral, os dispositivos móveis possuem as seguintes características:
tamanho reduzido, capacidade de trocar informações via rede, poder de
processamento limitado, facilidade de transporte e ausência de cabos para conexão à
rede e à energia. Os dispositivos mais utilizados para o propósito de computação
móvel são notebooks, laptos, palmtops, PDAs (Personal Digital Assistants) e
celulares (smartphones).
Mesmo com recursos comparáveis ao de uma estação de trabalho comum,
notebooks e laptops não são soluções de mobilidade ideal, pois necessitam de uma
base de apoio para serem operados e possuem baterias de curta duração. Os
Palmtops resolvem alguns destes empecilhos, mas limitam ainda mais as
capacidades de processamento e armazenamento e dificultam os métodos de
entrada e saída de dados. Apesar de assumirem funções de um telefone celular,
aparelho de fax, Web browser e organizador pessoal, os PDAs também têm pouco
poder de processamento e armazenamento, além de apresentarem opções de
entrada e saída pouco práticas.
Desenvolvidos inicialmente com o único propósito de levar a comunicação
além das barreiras da telefonia fixa convencional, os celulares chegaram para
transpor barreiras. A tabela 1 apresenta a evolução dos celulares a cada geração.
Geração
Transmisão de
1G
dados analógica
(AMPS).
Transmissão Digital
2G
de Dados (TDMA,
CDMA e GSM).
Disponibilização de
2,xG
aplicações pré-3G.
Evolução CDMA e
3G
GSM.
Elevação das taxas
4G
de transmissão de
dados.
Características
Taxas de 9600bps
Taxas de 9600bps a
14400bps.
Surgimento de
aplicações WAP.
Taxas de até 2Mbps. Surgimento de
aplicações multimídia.
Tecnologias e
aplicações ainda em
discussão.
Quadro 1 – Gerações da telefonia celular
Fonte: Figueiredo e Nakamura, 2003, p.19.
As características e problemas apresentados pelos celulares assemelham-se
com os citados nos PDAs. Além disso, a interação com o dispositivo é ainda maior,
limitando-se na maioria dos casos, as teclas do aparelho. A solução foi incorporar aos
celulares as funções de um PDA, gerando assim um novo dispositivo reconhecido
pelo nome de Smartphone.
3. JAVA 2 MICRO EDITION – J2ME
Basicamente J2ME é um termo que se refere a uma coleção de APIs e
máquinas virtuais que tornam possível o uso de Java em dispositivos móveis. Com o
J2ME é possível levar ao mundo dos dispositivos móveis, os benefícios da tecnologia
Java, como flexibilidade na interface com o usuário, um modelo de segurança eficaz,
suporte a diferentes tipos de aplicações, entre outros.
Figura 1 – Plataforma J2ME
Fonte: Sun Microsystems, 2005
A plataforma J2ME está presente na maioria dos dispositivos móveis atuais,
facilitando ao usuário a aquisição de novos serviços. A figura 1 ilustra a plataforma
J2ME.
Toda a arquitetura J2ME define configurações, perfis e pacotes opcionais
como elementos de uma aplicação Java completa. Assim, a plataforma é capaz de
atender aos requisitos de diferentes dispositivos e mercados. A combinação destes
elementos otimiza a capacidade de processamento, armazenamento e interfaces de
entrada e saída para cada dispositivo particular. O resultado é uma plataforma de
desenvolvimento Java comum, capaz de atender a diferentes tipos de equipamentos
e fabricantes.
4. VIRTUAL NETWORK COMPUTING – VNC
O VNC possibilita que uma estação de trabalho seja controlada remotamente
apenas com o uso de um simples programa cliente (visualizador). Outra característica
interessante é o fato de não ser necessário que os dispositivos utilizados (cliente –
servidor) sejam do mesmo tipo e/ou possuam mesmo sistema operacional.
Figura 2 – Acesso remoto com VNC
Fonte: Real VNC, 2005
Um software de controle remoto como o VNC, proporciona uma variedade de
benefícios, pois torna possível controlar uma estação de trabalho através de uma
rede, fixa ou sem fio, como se o indivíduo estivesse operando pessoalmente a
estação acessada remotamente.
Constatando as facilidades que tal software proporciona, esta pesquisa
propõe-se à apresentar uma solução cliente para ser embarcada em dispositivos
móveis.
5. JNC MOBILE – SISTEMA
DOSPOSITIVOS MÓVEIS
DE
ACESSO
REMOTO
PARA
O JNC Mobile é uma aplicação que possibilita a um dispositivo móvel
controlar remotamente uma estação de trabalho. O dispositivo móvel escolhido foi um
telefone celular da fabricante Nokia. Como é ilustrado na figura 3, o acesso remoto
necessita da seguinte arquitetura: um sofware cliente, um software servidor VNC e
um bridge. Esse último é responsável por receber as requisições do cliente e
encaminhá-las ao servidor VNC.
Figura 3 – Acesso remoto através de dispositivo móvel com servidor bridge
Fonte: Elaborada pelos autores, 2005
As requisições recebidas pelo bridge são encaminhadas ao servidor VNC
através do Protocolo RFB (Remote Frame Buffer). Por sua vez, o servidor VNC
retorna ao bridge o status (imagem) do desktop, e este encarrega-se de transmitir a
informação ao dispositivo móvel. Como ilustra a figura 4, o bridge acumula, além da
responsabilidade de tradutor entre o programa cliente e o servidor VNC, a função de
compactação da imagem enviada ao cliente.
Figura 4 – Compactação da imagem enviada ao cliente
Fonte: Elaborada pelos autores, 2005
A imagem fornecida pelo servidor VNC é capturada pelo bridge, que verifica
as coordenadas que estão sendo requisitadas pelo dispositivo móvel e as converte
para que possam ser exibidas na tela.
A figura 5 apresenta um exemplo de utilização da aplicação. O celular mostra
a tela do computador que está sendo acessado remotamente. O usuário tem opções
para, através das convenções criadas para as teclas do celular, realizar as operações
de zoom in e zoom out, além de movimentar o mouse e gerar cliques.
Figura 5 – Teclas do celular para o servidor VNC
Fonte: elaborada pelos autores, 2005.
CONSIDERAÇÕES FINAIS
A tecnologia Java 2 ME mostrou-se de grande importância no
desenvolvimento do trabalho, oferecendo uma série de facilidades. Além disso,
apresenta-se como uma forte tendência, visto que está embutida na maioria dos
dispositivos móveis do mercado e visa marcar presença em mais de 90% destes
dispositivos até 2007.
Uma dificuldade encontrada durante o desenvolvimento do trabalho foi a falta
de padronização na indústria. Constatou-se incompatibilidade até mesmo entre
aparelhos do mesmo fabricante. Este problema parece estar sendo resolvido com a
iniciativa de atualização do profile do J2ME MIDP, que agora figura em sua segunda
versão.
Apesar das limitações de acessibilidade impostas pelos aparelhos celulares,
da dificuldade de manipular as teclas do aparelho, e do tamanho reduzido do visor, e,
considerando o caráter acadêmico do trabalho, é com satisfação que se apresenta o
JNC Mobile como uma solução real para acesso remoto para dispositivos móveis.
REFERÊNCIAS
FIGUEIREDO, Carlos M. S.; NAKAMURA, Eduardo. Computação móvel: novas
oportunidades e novos desafios. T&C Amazônia. Ano 1. n. 2. Jun. 2003.
JAVATM 2 Platform, Micro Edition. Sun Microsystems. Disponível em:
<http://java.sun.com/> Acesso: 27 mar. 2005.
MOBILE Information Device Profile (MIDP); JSR 37, JSR 118 Overview. Sun
Microsystems. Disponível em: <http://java.sun.com/products/midp/> Acesso: 27 mar.
2005.
WHAT is VNC. RealVNC. Disponível em: <http://www.realvnc.com/what.html>
Acesso: 27 mar. 2005.
Download

veja o trabalho - Projetos