Protomake: um compilador de protocolos

Fábio Guerra, Igor Cananéa, Rodrigo Araújo, Thiago Souto Maior, Djamel Sadok

UFPE, Centro de Informática
Av. Prof. Luiz Freire, S/N, Cidade Universitária – Recife, PE

{fga, icc, rca4, tsmcf, jamel} @cin.ufpe.br

Abstract. This is a quite simple StarOffice document where I used "Styles" to create all the text formats needed when submiting an article to the SBC. xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Resumo. O projeto e desenvolvimento de protocolos é uma tarefa não trivial que demanda tempo e esforço. As ferramentas disponíveis atualmente não são suficientemente completas para descrever protocolos complexos, que podem utilizar TCP e UDP. Além disso, fornecem pouca ajuda na criação um produto próximo do que foi projetado inicialmente, principalmente pelo fato de suas linguagens de descrição serem muito abstratas. Protomake é um compilador de protocolos, previsto para se tornar um ambiente completo de desenvolvimento de protocolos, que facilita a criação de novos protocolos da camada de aplicação podendo funcionar através de UDP e/ou TCP. A partir de uma descrição do protocolo, ele gera código-fonte equivalente em C e JAVA, além de gerar um plugin que descreve as mensagens do seu protocolo para o analisador de protocolos Ethereal.

Introdução

Não está escrita ainda!

Não há muito o que dizer. Apenas use o "Estilista" teclando <F11> ou chamando-o diretamente através do menu Formatar -> Estilista e experimente os estilos identificados por SBC-nome_do_estilo.

Observe que o estilo do primeiro parágrafo de uma seção é diferente do segundo. O do primeiro parágrafo é chamado SBC-Padrão, e o de todos os subseqüentes é chamado SBC-Parágrafo. Normalmente, o "Estilo Seguinte" está configurado para que você não precise se preocupar muito com isto.

Trabalhos Relacionados

Serão relacionados nesta seção os trabalhos de maior relevância na área de geração automática de protocolos ou aqueles que influenciaram o desenvolvimento do Protomake.

APC

O protomake foi inicialmente desnvolvido como uma extensão do APC [ref] (Austin Protocol Compiler). Este compilador utiliza uma linguagem chamada TAP (Timed Abstract Protocol), que é baseada em AP(Abstract Protocol), para estruturar o protocolo. O APC é baseado em eventos de recepção e timeout que desencandeiam uma sequência de ações e estados que serão acionados. O código é gerado em C e é possível usar funções escritas em C na especificação do protocolo.

Os protocolos gerados são de aplicação sobre o protocolo de transporte UDP. O APC encontra-se atualmente na versão 0.5 e é o único compilador que efetivamente gera uma aplicação entre os que são descritos neste trabalho. Segundo seu autor, até o presente momento, não existe a intenção de fazer uma versão para TCP.

Esterel

Esterel [ref] é uma linguagem para programar sistemas reativos e síncronos também utilizada para validação de protocolos. Permite a verificação e validação de sistemas reativos e o seu compilador cria sistemas para simular o protocolo criado. Pode ser utilizada para gerar implementações de programas reativos em software ou hardware. O compilador de Esterel também gera código C para ser incorporado como núcleo de um programa maior que manipula dados e interface com o usuário. Embora possa ser usado para construir servidores e clientes de rede, não é uma linguagem projetada especificamente para isso.

Prolacc

Prolac [ref] é uma linguagem orientada a objetos criada para desenvolver protocolos de rede do mais simples ao mais complexo. Para compilar códigos escritos em prolac foi desenvolvido o compilador prolacc. O objetivo da linguagem é facilitar o desenvolvimento de protocolos sem um compromisso com a corretude do mesmo, deixando isso a cargo do desenvolvedor. O protocolo TCP foi implementado como exemplo de utilização dessa linguagem. Embora seja possível criar protocolos complexos, a descrição é apenas um pouco melhor do que programar o protocolo diretamente em uma linguagem de propósito geral pelo fato dela ser uma linguagem orientada a objetos. Ainda é uma linguagem complexa para desenvolver protocolos mais simples.

Promela++

Promela++[ref] é baseada em uma linguagem de descrição abstrata de protocolos chamada Promela[ref] e sua sintaxe é semalhante a de C. É possível criar protocolos integrados (mais de uma camada) e o código gerado é eficiente, em alguns casos mais até do que se houvesse sido escrito em uma linguagem de propósito geral. Permite a verificação e validação do protocolo ao convertê-lo para Promella. Apesar de ser semelhante à linguagem C, não dispõe de alocação dinâmica de variáveis nem tem suporte a temporizadores.

Funcionalidades

Nesta seção descrevemos sucintamente a forma de especificar protocolos no Protomake, o seu funcionamento e o que é gerado após a compilação do protocolo. O manual[ref] do compilador possui uma descrição mais detalhada.

Definição do protocolo

O Protomake gera código nas linguagens alvo a partir de uma descrição simples do protocolo. A linguagem utilizada para escrever este arquivo de descrição é a EAPT( Extended APT[ref]), que será detalhada ao longo desta seção.

A linguagem possui cinco seções de definição dadas por PLUGIN, IMPORTS, MESSAGES, BEHAVIORS e PROCESSES, necessariamente nesta ordem, dos quais apenas MESSAGES e PROCESSES são obrigatórios. Em PLUGIN ficam as definições que são usadas para gerar o plugin para o ethereal. Na seção seguinte, são declarados os arquivos de definição que são importados. Em MESSAGES especifica-se as mensagens do protocolo. Abaixo, um exemplo:

!@Author "Igor Chaves Cananea"

!@Email "icc@cin.ufpe.br"

!@Name "ProtoMake Temporary Test Protocol"

!@Acronym "PTTP"

!@Port 9986

!@Transport tcp

import “pcp.pm”

import “../sctp.pm”

message one

begin

flags : 3 bits,

length : 8 bits,

msg : length bytes,

command : 4 bytes

end

Os cabeçalhos começam com o símbol “!@” seguidos de uma palavra chave e um valor. As possíveis palavras chaves são Author, Email, Name, Acronym, Port e Transport. Com exceção de Port (que deve ser um inteiro) e de Transport (que deve ser tcp ou udp), todas as palavras chaves devem ser seguidas por um string. Se não existirem cabeçalhos, o plugin não é gerado. Caso exista, apenas os cabeçalhos Author e Email são opcionais.

As mensagens são definidas utilizando a palavra-chave message seguida pelo nome da mensagem. Logo após seguem os campos da mensagem agrupados num bloco begin / end. Os tipos de campos possíveis são bits e bytes que devem ser antecedidos pela quantidade respectiva de bits ou bytes. Poderá ser utilizado como quantificador também o nome de um campo previamente descrito; neste caso, o valor do campo vai ser utilizado como número.

Para utilizar código externo na definição do protocolo, construções do tipo behaviors podem ser usados. Ao declarar um, quaquer construção da forma behavior.função(expressões) são consideradas ações válidas dentro de um processo. Dessa forma, é possível inserir funcionalidades no protocolo que não estão previstas na linguagem de especificação.

Os processos descrevem o protocolo e devem ser definidos logo após as mensagens. Um processo chamado main é requerido como o mínimo. Outros processos definidos devem ser explicitamente iniciados pelo processo main através da ação start proc, onde “proc” é o nome do processo. A seguir, um exemplo:

behavior Command

process main

var client: address

var a : integer

begin

rcv one from client -> Command.procces(one.command);

one.msg = "Ok!";

one.length = 3;

send one to client

end

O process main é responsável pelo loop principal do protocolo e pode ser definido como um bloco begin / end precedido de declarações de variáveis. As variáveis podem ser dos tipos integer, range (Intervalo de numeros: 1..10, 0..255), address (endereço para envio e recepção de mensagens por UDP), client_address, server_address (mesmo que address porém através de TCP) e array, que por sua vez pode ter elementos dos tipos listados anteriormente. O corpo do process é formado por ações que serão executadas caso suas guardas sejam satisfeitas. As guardas consistem em expressões booleanas, guardas timeout ou guardas rcv.

As guardas timeout são ativadas toda vez que o contador representado pelo identificador na guarda chega a zero. Estes contadores são inicializados com o comando act. As guardas rcv são ativadas quando uma mensagem (do tipo descrito na guarda) chega no buffer e é devidamente identificada. A prioridade de ativação dessas guardas é a seguinte: se nenhuma guarda com expressão booleana for satisfeita, o protocolo espera que alguma mensagem chegue para verificar se uma guarda de rcv pode ser satisfeita.

Os comandos permitidos na ação podem executar atribuições, diretivas send, diretivas rcv, behaviors, if (teste de expressão booleana), do (laço de repetição) e expressões aritméticas simples. A diretiva send é utilizada para enviar mensagens e a rcv para recebê-las, sendo escritas da seguinte forma:

send mensagem to endereço

rcv mensagem from endereço

O comando if consiste de guardas seguidas de ações. A primeira guarda satisfeita é a que terá sua sequência de ações executada. Exemplo:

if expr1 ->

ações1

[] expr2 ->

ações2

...

[] exprN ->

açõesN

fi

O laço de repetição é representado nesta linguagem como o comando do. Sua sintaxe é similar ao do comando if, diferindo apenas pela quantidade de guardas permitidas, que no caso do do é só uma. As ações são executadas enquanto a guarda for satisfeita. Exemplo:

do a < 3 ->

a := a + 1;

b := b * b;

b := b + 1

od

Geração de código

Ao compilar a especificação, o código poderá ser gerado em Java ou em C. O código gerado inclui a estrutura da mensagem e funções para codificar e decodificar a mensagem. É gerado também o plugin, caso seus dados tenham sido preenchidos no cabeçalho do arquivo.

Atualmente, apenas as estruturas das mensagens, suas funções de serialização e o plugin para o Ethereal são gerados. O motor do protocolo foi definido porém ainda está sendo implementado. Com o código gerado, é possível escrever um programa que implemente o protocolo e usar as funções de serialização e deserialização para enviar e receber corretamente as mensagens.

Motor do protocolo

O motor do protocolo é composto de dois linhas de execução: a de recepção de mensagens e a da máquina de estados. As duas linhas são executadas segundo o modelo concorrente produtor-consumidor, no qual o produtor é a da recepção, que coloca as mensagens recebidas numa fila, e o consumidor é a da máquina de estados, que remove as mensagens da fila quando é necessário. A remoção de uma mensagem da fila é feita quando:

Nenhuma guarda está ativa, ou seja, nenhuma expressão booleana é verdadeira. A mensagem é retirada da fila e a maquina de estados verifica se ela satisfaz alguma guarda rcv.

Um comando rcv é encontrado nas ações (lado direito das guardas).

Se não houver mensagens para serem consumidas o programa espera bloqueado até que chegue alguma mensagem ou até uma guarda timeout ser ativada.

O loop principal do protocolo verifica a cada passo os estados para determinar o próximo a ser executado. Diferentes fluxos de estados ativos podem ocorrer dependendo das prioridades dadas pelo usuário do programa. Temos como opção dar prioridade à recepção de mensagens. Isso faria com que toda mensagem que chegasse fosse imediatamente processada e os estado ativo antes da chegada da mensagem seria colocado um uma fila para ser executado depois do tratamento da mesma. Com isso os estados poderiam ser executados intercaladamente (estados de tratamento de mensagem e estados ativos anteriormente, colocando na mesma fila também os seus respectivos próximos estados), porém esta prioridade pode causar starvation ao processo decorrente dos estados ativos anteriormente. A outra opção seria dar prioridade à execução do fluxo até que nenhuma guarda fique ativa. Assim, quando uma mensagem chega, ela fica esperando na fila até que o fluxo ativo termine, ou que um comando rcv contido no fluxo seja executado.

Plugin do Ethereal

O Ethereal é um analisador de protocolos muito usado para monitorar pacotes que estão trafegando pela rede. Ele permite uma visualização detalhada do pacote com descrições de seu campos através de plugins de dissecação. O protomake pode gerar uma plugin para o protocolo especificado. Este plugin é simples porém útil o suficiente para visualizar as mensagens geradas pelo protocolo.

Especificando um protocolo

Especificaremos um servidor de echo para melhor ilustrar a criação de um protocolo. Esse servidor possui a característica de cifrar as mensagens antes de devolvê-las à sua origem.

Ao receber a mensagem, ela é cifrada pela função encript, pertencente ao behavior Crypt para só depois ser devolvida. Se não for possível cifrar a mensagem, uma mensagem de erro é enviada:

Em primeiro lugar, é definido um cabeçalho para que o plugin para o Ethereal seja gerado, como descrito na seção 3.1:

!@Author "Igor Chaves Cananea"

!@Email "icc@cin.ufpe.br"

!@Name "ProtoMake Crypt Protocol"

!@Acrynom "PCP"

!@Port 9986

!@Transport tcp

Em seguida, a mensagem que será usada no protocolo:

message text

begin

length : 8 bits,

msg : length bytes

end

Um behavior que será usado para cifrar a mensagem:

behavior Crypt

O processo principal que irá iniciar o processo de criptografia, caso uma mensagem seja recebida:

process main

var client : address

begin

rcv text from client -> start cryptMsg

end

O processo auxiliar que irá cifrar e enviar a mensagem de volta para o cliente caso não ocorra nenhum erro, caso contrário, o protocolo enviará uma mensagem padrão de erro:

process cryptMsg

var client : address;

const started : integer = 1

begin

started = 1 -> Crypt.encrypt(text.msg, text.length);

if text.length <> 0 ->

send text to client

[] text.length = 0 ->

text.msg := "error";

text.length := 5;

send text to client

fi;

stop

end

Conclusão

Este artigo apresentou a ferramenta Protomake, que é um compilador de protocolos baseado na linguagem APT utilizado pelo compilador de protocolos APC. O protomake apresenta as vantgens de Acelerar o processo de desenvolvimento de protocolos provendo ferramentas para depurar e gerar o codigo de mensagens e funções de apoio, e futuramente a própria máquina de estados do protocolo.

Foi apresentado um exemplo da utilização do protomake para uma aplicação simples de um servidor de echo que cifra as mesnagens antes de devolvê-las a sua origem. A definição do protocolo é enxuta o que significa que a escrita de um protocolo na linguagem EAPT é rápida e prática. Torna-se aparente a vantagem da utilização do protomake, uma vez que o desenvolvimento deste protocolo em uma linguagem de programação é lento e sujeito a falhas (de implementação), já que o código do protocolo a ser gerado é bem maior que sua descrição.

Como trabalhos futuros serão desenvolidas extensões para o protomake, que irão disponibilizar uma interface para geração de protocolos de outras camadas, tais como transporte e enlace. Além disso, é previsto um módulo para provar alcançabilidade de estados numa maquina de estados, tal como se um protocolo entra em deadlock através de uma descrição LTS[ref] utilizando a ferramenta LTS Analyser. Outro ponto interessante a ser ressaltado é a construção de uma interface gráfica amigável, para tornar mais simples a interação com os usuários.

Referências

MCGUIRE, Tommy Marcus and GOUDA, Mohamed G. The Austin Protocol Compiler, November 17, 2002

BASU, Anindya and MORRISETT, J. Gregory and EICKEN, Thorsten von. Promela++: A Language for Constructing Correct and Efficient Protocols, 1998

KOHLER, Eddie. Prolac: A language for protocol compilatiion, http://www.pdos.lcs.mit.edu/prolac/prolac-the.pdf

BERRY, Gérard. The Foundations of Esterel, MIT Press – Foundations of Computing Series, 2000

HOLZMANN, Gerard J. Design and Validation of Computer Protocols, Prentice Hall, 1991

Cesar Brod

2002-02-26T16:13:42

Cesar Brod