domingo, 12 de agosto de 2012

Explorando o NeonMika.Webserver - Parte 2

Agora acredito que devo mudar o nome dessa sequência de artigos para: "modificando o NeonMika.Webserver" porque o que eu já fiz de modificação está dando mais trabalho do que eu imaginava, já estou quase implementando tudo outra vez.

Demorei umas duas semanas para postar algo novo sobre o servidor porque precisei de tempo para aprender como um servidor web realmente funciona, tive que aprender HTML, Javascript (outra vez), protocolo de rede, métodos (POST e GET) e por ai vai. Depois muita luta consegui trazer um código novo, ainda sem a parte de configuração, mas com a página de login.

A parte de login realmente deu um trabalho do cão para fazer, isso porque tive que lutar com as página de web para fazer uma que me me fosse conveniente para embarcar no cartão microSD e que o Netduino Plus pudesse processar. Primeiro baixei o NVU para criar a página de web, como não sabia como utilizar, parti para um tutorial mas a minha anciedade não permitiu que eu o termina-se de ler e tive que abandonar aquela coisa chata e que no final de tudo não iria me ajudar para o que eu desejava então parti para "mão grande" e começei a fazer com o editor de texto mesmo e consultando tudo na www.w3schools.com que hoje é referência básica para HTML e afins.


Através dos meus novos conhecimentos consegui fazer a página de login e uma página de configuração, o que precisava seguida era animar isso tudo. Nesse ponto vem a parte do Javascript, tentei por várias horas ontem criar uma forma de logar independente do servidor, ou seja, todo o tratamento do login ficasse na página, mas isso foi em vão... até consegui ter algum sucesso colocando um código Javascript na parte no cabeçalho da página para que tova vez que uma página fosse aberta solicitasse uma senha, o grande problema é que toda página tinha que ser "logada" sempre ao acessar a página e o tratamento do login incorreto era abrir outra janela de login e mais ainda, toda a vez que a página fosse aberta poderia revelar a senha no código fonte da página. Com todos esses percalços tive mesmo é que abandonar essa ideia e passar para uma requisição de login dentro do servidor.

/// <summary>
/// microSD card webpage how are the login webpage
/// </summary>
public const string REQUEST_LOGIN_URL = "login.html";
 
Que faz referência a página onde se encontra o formulário de login em página de web. Essa página que no meu exemplo se chama "login.html" trata-se de uma página de web com um formulário que passa os seus parâmetro pelo método POST. Utilizei o método POST para enviar os dados através do corpo da mensagem o que dificulta levemente a maneira de descobrir a senha de segurança para acessar o servidor na placa.

O formulário com o método POST deve ser escrito da seguinte maneira:


<form method="post">
<span style="color: rgb(255, 255, 255);">Usuário : </span><input type="text" name="Username">
<br>
<span style="color: rgb(255, 255, 255);">Senha  : </span><input type="password" name="Password">
<br>
<br>
<input type="submit" value="Login" onClick="sendlogin1()">
</form>

O tratamento é feito de tal forma que quando uma requisição de uma página chega ao Netduino Plus, verifica-se se o IP de onde vem a requisição ainda não fez login, caso afirmativo, envia a página de login para que o usuário informe a senha.  Uma vez recebida as informações de usuário e senha o servidor torna-se aberto para o cliente acessar as páginas.

A função que manipula a requisição de páginas ficou assim:

/// <summary>
/// Checks an incoming request against the possible responses
/// </summary>
/// <param name="e"></param>
private void HandleRequest(RequestReceivedEventArgs e)
{
    ////Debug("Start checking requests");
    Response response = null;
    if (_Loged)
    {
        //normal file response
        if (_Responses.Contains(e.Request.URL))
        {
            //Trata as repostas personalizadas criadas na aplicação
            response = (Response)_Responses[e.Request.URL];
        }
        else
        {
           response = (Response)_Responses["FileResponse"];
        }
    }
    else
    {
        //Test if it's a Login post message
        if(e.Request.Method == "POST")
        {
            int validation = 2;
            foreach (DictionaryEntry entry in e.Request.PostArguments  )
            {
                if ((entry.Key.ToString() == "Password") && (entry.Value.ToString() == _Password))
                {
                    validation--;
                }
                if ((entry.Key.ToString() == "Username") && (entry.Value.ToString() == _UserName))
                {
                    validation--;
                }
                if (validation == 0) { 
                    // login and load the Webpage that user Requested
                    _Loged = true;
                    e.Request.LoadWebpageRequested();
                    response = (Response)_Responses["FileResponse"];
                }
            }
        }
        else
        {
            //Set to call Login webpage - for load Netduino icon e don't load other webpages
            if (e.Request.URL.Length > 5)
            {
                if (e.Request.URL.Substring(e.Request.URL.Length - 5) == "html")
                {
                    e.Request.RequestLogin();
                }
            }
            else
            {
                e.Request.RequestLogin();
            }
            //Go to fileResponse to send the webpage as default
            response = (Response)_Responses["FileResponse"];
        }
    }

    if (response != null)
    {
        if (response.ConditionsCheckAndDataFill(e))
        {
            Thread ledThread = new Thread(new ThreadStart(delegate()
            {
                for (int i = 0; i < 3; i++)
                {
                    _OnboardLed.Write(true); Thread.Sleep(5);
                    _OnboardLed.Write(false); Thread.Sleep(20);
                }
            }));
            ledThread.Start();
        }
    }
}

Link para download do código fonte.
Link para download dos arquivos para cartão micro SD (para rodar o exemplo basta colocar na raiz)

O problema das Imagens

Um problema que eu resolvi nessa segunda parte sobre o NeonMika.Webserver foi o problema das imagens que não carregavam, pois bem, o problema é que as imagens eram muito pesadas... míseros 500kB já é uma coisa pesada para o nosso pequeno webserver mas tive bons resultados com o logo do netduino, como podem ver pelos screenshot's do servidor e a imagem da placa, cerca de 70kB.


O jeito por enquanto é tratar de usar figuras pequenas ou coleção de imagens bem pequenas, mas estou vendo através do forum do Netduino alguma maneira para passar um ponteiro para o cartão microSD transferir o arquivo sem precisar colocá-lo em uma variável interna. A vantagem disso seria não gastar memória do processador para buffer de página de HTML e arquivos além de permitir que arquivos de qualquer tamanho sejam transferidos. O problema agora é alguém me dizer se existe a solução ou vou ter que garimpar muito...

 O problema de timeout das páginas

Isso é um problema chato que está acontecendo e está prejudicando o envido do POST do login. Muitas vezes a placa está muito lenta para tratar as requisições do navegador e com isso á página não é carregada necessitando atualizar a página para que numa segunda requisição a placa inicie e envie a página.

Esse problema não é só nosso, mas todos de um modo geral tem tido esse problema porque a camada de código está muito acima e acaba demorando muito apara responder, mas estão trabalhando para melhorar isso no .NETMF.

___


Na terceira parte vou falar sobre os métodos XML e JSON e sobre a configuração do IP utilizando o servidor NeoMika.Webserver.

Nenhum comentário:

Postar um comentário