Tuesday, February 3, 2009

Virtualização para servidores com VirtualBox

O que não falta agora é soluções de virtualização.

Mas a mais simples e com excelente performance na minha opinião é com o VirtualBox, dá para fazer tudo que é preciso com muita simplicidade e rapidez.

Para virtualização em desktop o VirtualBox já vem reinando a algum tempo.

E para servidor, muitos não apostam por que simplismente não sabem que é possível, mas dá! E não é preciso ter ambiente gráfico, usando o VRDP pode-se administrar a máquina remotamente. Mas convém ter o ambiente gráfico, tudo fica muito mais fácil, e hoje em dia não vejo por que não ter ambiente gráfico no servidor, pois o que não falta é ambientes gráficos levezinhos que nem afetam a performance do servidor.

Existe uma solução para máquinas virtuais usando OpenSolaris e VirtualBox, chamda xVM Server:
http://xvmserver.org/
http://www.sun.com/software/products/xvmserver/index.xml

Mas como já tenho o CentOS redondinho, agora é tarde.

Bem, então eu resolvi fazer de tudo para ter o VirtualBox trabalhando no servidor com o Windows 2003 Server em máquina virtual dentro do VirtualBox no CentOS 5.

Melhor impossível, ficou perfeito, excelente performance, fácil administração, todos serviços funcionando lindamente.

Vamos ao que interessa. Basicamente CentOS 5 com o VirtualBox instalado, com a máquina virtual para o Windows Server 2003 instalada e configurada, isto é moleza e o que não falta é tutoriais pela net ensinando como fazer isto com screenshots e tudo, e o VirtualBox é muito intuitivo. Por isso este não é o âmbito aqui.

Agora a parte mais complicada, que tive que pesquisar bastante, para fazer com que o CentOS comunicasse com o Windows Server. O que me ajudou mais a desvendar isto foi este script:

http://www.savvyadmin.com/virtualbox-host-interface-networking-with-nat/

Mas como nem tudo é perfeito, este script não serve no CentOS, é preciso algumas alterações.

Então em primeiro lugar, configurar o IP da máquina virtual, ir no Windows 2003 Server e configurar o TCP/IP assim:

IP address: 192.168.20.201
Subnet mask: 255.255.255.0
Default gateway: 192.168.20.1



Feito isto, ir no CentOS e criar uma interface de rede virtual:


# /usr/bin/VBoxTunctl -u root


Depois disto, pode verificar com o "/sbin/ifconfig -a" se aparece o tap0. Pronto ai esta a nossa interface de rede virtual.

É preciso configurar no VirtualBox para usar a nova interface de rede virtual, a tap0. Ir nos "Settings" da máquina virtual, em "Network", no "Attached to", mudar para "Host Interface", e selecionar a tap0. Para ir nos "Settings" tem que desligar a máquina virtual.

Settings da Máquina Virtual > Network > Attached to > Host Interface



Agora é preciso configurar a interface de rede virtual:


# /sbin/ip link set tap0 up
# /sbin/ip addr add 192.168.20.1/32 dev tap0
# /sbin/route add -host 192.168.20.201 dev tap0


Deverá conseguir "pingar" a máquina virtual:


# ping -c 1 192.168.20.201


Se for preciso rodar ASPX no servidor, ai esta a solução, só configuar no nginx para fazer proxy reverso do IIS no IP 192.168.20.201, e já vai funcionar perfeitamente.

A máquina virtual até aqui não tem acesso a internet. Para resolver isto é preciso fazer isto:


# /sbin/sysctl net.ipv4.ip_forward=1
# /sbin/iptables -t nat -A POSTROUTING --out-interface eth0 -j MASQUERADE
# /sbin/iptables -A FORWARD --in-interface tap0 -j ACCEPT


E também configurar os DNSs, primário e secundário, da máquina virtual, com os mesmos dados DNSs do CentOS, para ver os DNSs do CentOS:


# cat /etc/resolv.conf


Agora deverá ter a internet funcionando no Windows.

Podemos iniciar a máquina virtual pela linha de comando, só que ficamos sem acesso ao ambiente gráfico do VirtualBox. Para então ter acesso a máquina virtual convém configurar o VRDP no VirtualBox para acessar a máquina virtual remotamente:

Settings da Máquina Virtual > Remote Display > Enable VRDP Server

Settings da Máquina Virtual > Remote Display > Port = 3089



É importante mudar o número da porta, por que a porta do VRDP é a mesma do Terminal Services, da para trocar o número da porta do Terminal Services no regedit, mas é mais simples ai no VRDP, e assim já se evita um conflito.

Só que assim o VirtualBox vai deixar entrar qualquer um pelo VRDP sem autenticação, então convém bloquear a porta do VRDP para que ninguem fora do CentOS consiga controlar a máquina virtual:


# /sbin/iptables -A INPUT -p tcp -i eth0 --dport 3089 -j REJECT --reject-with tcp-reset

# /sbin/iptables -A INPUT -p tcp -i eth1 --dport 3089 -j REJECT --reject-with tcp-reset

# /sbin/iptables -A INPUT -p udp -i eth0 --dport 3089 -j REJECT

# /sbin/iptables -A INPUT -p udp -i eth1 --dport 3089 -j REJECT


Assim a porta do VRDP fica protegida para que ninguem que venha das interfaces de rede externas consiga conectar.

Para conectar via VRDP é só usar o tsclient:


# tsclient


No tsclient em computer colocar:

localhost:3089

E em protocol:

RDPv5

Clicar em "Connect", e pronto! Já conseguimos controlar a máquina virtual remotamente quando estivermos executando ela em background, isto será muito útil.

No Windows 2003 Server podemos ter o Terminal Services, e para acessar o terminal services através da internet ou rede temos que fazer uns ajustes, pois a porta do Terminal Services é a mesma do VRDP, então temos que mudar uma ou outra porta, como já mudamos a porta padrão do VRDP para 3089, então o Terminal Services vai funcionar bem na porta 3389.

Então para por o Terminal Services a funcionar é preciso ativar, no Windows Server:

Control Panel > System > Remote > Enable Remote Desktop on this computer



E agora é fazer NAT para a porta do Terminal Services:


# /sbin/iptables -t nat -A PREROUTING -p tcp -i eth0 --dport 3389 -j DNAT --to 192.168.20.201:3389

# /sbin/iptables -t nat -A PREROUTING -p tcp -i eth1 --dport 3389 -j DNAT --to 192.168.20.201:3389


E assim fica o Terminal Services disponível, e o mesmo pode ser feito para outros serviços do Windows que precisam estar disponíveis externamente, como MSSQLServer.

Há outros exemplos desta configuração usando bridges, mas acho que assim fica muito mais simples.

Para iniciar a máquina virtual pela linha de comando é assim:


/usr/bin/VBoxVRDP -startvm NOME_DA_MAQUINA_VIRTUAL_NO_VIRTUALBOX


Para quando o servidor iniciar, iniciar também a máquina virtual e carregar toda configuração, coloquei os seguintes comandos no /etc/rc.local:


/usr/bin/VBoxTunctl -u root
/sbin/sysctl net.ipv4.ip_forward=1
/sbin/ip link set tap0 up
/sbin/ip addr add 192.168.20.1/32 dev tap0
/sbin/route add -host 192.168.20.201 dev tap0
/sbin/sysctl net.ipv4.ip_forward=1
/sbin/iptables -t nat -A POSTROUTING --out-interface eth0 -j MASQUERADE
/sbin/iptables -A FORWARD --in-interface tap0 -j ACCEPT
/sbin/iptables -A INPUT -p tcp -i eth0 --dport 3089 -j REJECT --reject-with tcp-reset
/sbin/iptables -A INPUT -p tcp -i eth1 --dport 3089 -j REJECT --reject-with tcp-reset
/sbin/iptables -A INPUT -p udp -i eth0 --dport 3089 -j REJECT
/sbin/iptables -A INPUT -p udp -i eth1 --dport 3089 -j REJECT
/sbin/iptables -t nat -A PREROUTING -p tcp -i eth0 --dport 3389 -j DNAT --to 192.168.20.201:3389
/usr/bin/nohup /usr/bin/VBoxVRDP -startvm winserver > /dev/null &


Tem muita gente que acha deselegante usar o rc.local, mas eu não acho deselegante, muito pelo contrário, afinal pra que que ele serve? :P

No meu caso, em um AMD Opteron Quad-Core com 4GB de RAM, o Windows 2003 Server em máquina virtual de 512MB com o VirtualBox demora 6 segundos para estar completamente inicializado.

Wednesday, December 17, 2008

Chamando Web Services sobre HTTPS

Utilizar web service sobre HTTPS é da mesma forma que um web service HTTP.

Adicionar a referência web ao projeto, com a url HTTPS.

O uso do web service a nível de código é a mesma coisa.

Só que ao tentar chamar o web service poderá acontecer de obter esta mensagem erro:

The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.

Colocando este código antes da chamada ao web sersvice provavelmente irá resolver o problema:


System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate
{
return true;
};


Basicamente é por que o .Net esta rejeitando o certificado por não ser um certificado válido, com o código acima, mesmo não sendo um certificado válido ele irá aceitar o certificado, e conseguirá comunicar com o web service.

Thursday, November 27, 2008

Script Python para consumir Web Services em .Net

Tive um desafio a poucos dias. Que foi consumir Web Services feitos em .Net a partir de um servidor Solaris 10 via processo.

De todas as soluções possíveis que estive a ver, a melhor foi usar Python.

Encontrei este exemplo:

http://users.skynet.be/pascalbotte/rcx-ws-doc/postxmlpython.htm

Assim fiz o WebServiceGenericClientNet.py:

#!/usr/bin/python

# by eduveks

import sys, httplib, array

try:
    host = ""
    url = ""
    namespace = ""
    header = ""
    method = ""
    params = {}

    for arg in sys.argv[1:]:
        if host == "" and arg.find("host=") == 0:
            host = arg[len("host="):]
        elif url  == "" and arg.find("url=") == 0:
            url  = arg[len("url="):]
        elif namespace == "" and arg.find("namespace=") == 0:
            namespace = arg[len("namespace="):]
        elif header == "" and arg.find("header=") == 0:
            header = arg[len("header="):]
        elif method == "" and arg.find("method=") == 0:
            method = arg[len("method="):]
        elif arg.find("param_") == 0:
            params[arg[len("param_"):arg.find("=")]] = arg[arg.find("=") + 1:]

    SOAP_Request = ""
    SOAP_Request += "<soap:Envelope"
    SOAP_Request += " soap:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\""
    SOAP_Request += " xmlns:xsi=\"http://www.w3.org/1999/XMLSchema-instance\""
    SOAP_Request += " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""
    SOAP_Request += " xmlns:xsd=\"http://www.w3.org/1999/XMLSchema\">"
    if header != "":
        SOAP_Request += "<soap:Header>"
        SOAP_Request += header
        SOAP_Request += "</soap:Header>"
    SOAP_Request += "<soap:Body>"
    SOAP_Request += "<"+ method +" xmlns=\""+ namespace +"\">"
    for param in params.keys():
        SOAP_Request += "<"+ param +">"+ params[param] +"</"+ param +">"
    SOAP_Request += "</"+ method +">"
    SOAP_Request += "</soap:Body>"
    SOAP_Request += "</soap:Envelope>"

    http = httplib.HTTP(host)
    http.putrequest("POST", url)
    http.putheader("Host", host)
    http.putheader("User-Agent", "Python")
    http.putheader("Content-type", "text/xml; charset=\"UTF-8\"")
    http.putheader("Content-length", "%d" % len(SOAP_Request))
    http.putheader("SOAPAction", "\""+ namespace + method +"\"")
    http.endheaders()
    http.send(SOAP_Request)

    http_response_statuscode, http_response_statusmessage, http_response_header = http.getreply()
    SOAP_Response = http.getfile().read()
    if http_response_statuscode == 200 and http_response_statusmessage == "OK":
        print SOAP_Response[SOAP_Response.find("<"+ method +"Result>") + len("<"+ method +"Result>"):SOAP_Response.find("</"+ method +"Result>")]
    else:
        print "### ERROR ###############"
        if SOAP_Response.find("<faultstring>") > -1:
            print SOAP_Response[SOAP_Response.find("<faultstring>")  + len("<faultstring>"):SOAP_Response.find("</faultstring>")]
        print "Response: ", http_response_statuscode, http_response_statusmessage
        print http_response_header
        print SOAP_Response

except:
    print "### ERROR ###############"
    for err in sys.exc_info():
        print err


Para executar o script basta dar permissões de execução e executar:

chmod +x WebServiceGenericClientNet.py
./WebServiceGenericClientNet.py host=localhost url=/HelloWorld.asmx namespace=http://tempuri.org/ method=HelloWorld param_strSay=HelloWorld


O output é:

HelloWorld


Os parâmetros do WebServiceGenericClientNet.py são:

host: Endereço do servidor
url: Endereço do web service
namespace: Namespace do web service, que pode ser encontrado vendo o WSDL, http://localhost/HelloWorld.asmx?WSDL
method: Método do web service a ser chamado
param_*NOME_DO_PARAMETRO*: Caso o método precise de parâmetros, podem ser definidos assim, atenção a ordem.

Além de usar este script no Solaris, também acabei por usar este script para chamar web services apartir do .Net/C#, pois são web services que serão atualizados constantemente, com novos métodos e talz, e em vez de ficar atualizando o WSDL, basta chamar diretamente com o script a queima-roupa, e a configuração da chamada dos web services pode ser feita a partir de configurações em base de dados. Para fazer isto no .Net/C# foi só lançar um processo assim:

System.Diagnostics.Process process = new System.Diagnostics.Process();
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.FileName = "C:\Python26\python.exe";
process.StartInfo.Arguments = "WebServiceGenericClientNet.py host=localhost url=/HelloWorld.asmx namespace=http://tempuri.org/ method=HelloWorld param_strSay=HelloWorld";
process.StartInfo.WorkingDirectory = "C:\Python26\";
process.Start();
string output = process.StandardOutput.ReadToEnd();

O script suporta a configuração do header, passando o argumento header=... para o script.

Para explorar e ver fácilmente os SOAPs enviados e recebidos na chamada de um web service, existe o WebServiceStudio:

Monday, September 15, 2008

Nvidia vs Ubuntu

O driver da Nvidia que vem por padrão no Ubuntu tem alguns bugs, como este:

http://www.nvnews.net/vbulletin/showthread.php?t=106790

Aqui estão os screenshots do bug:

http://home.arcor.de/cziepke/ut2004/



Para instalar o driver que resolve o problema, o NVIDIA-Linux-x86-177.13-pkg1.run, não é tão simples assim, eu pensava que era...

Baixei aqui o driver:

http://www.nvnews.net/vbulletin/showthread.php?t=118602

Consegui instalar, mas o Xorg ficou todo estragado, fiquei com a resoluão de 800x600 e o driver vesa, então procurei e encontrei a solução num forum francês:

http://forum.ubuntu-fr.org/viewtopic.php?id=249234

O que fiz então foi o seguinte:

Fiz logout, e mudei para o terminal 1 (ctrl + alt + F1), fiz o login, e matei o GDM:

# sudo killall gdm

Feito isto o Xorg deverá esta morto, verifique no terminal 7 (ctrl + alt + F7), se esta tudo preto.

Agora remova tudo que esta instalado da nvidia:

$ sudo apt-get remove --purge nvidia*

Instalar os headers do kernel e o xorg-dev:

$ sudo apt-get install build-essential linux-headers-`uname -r` xserver-xorg-dev

Faça um backup da configuração do Xorg:

$ sudo cp /etc/X11/xorg.conf /etc/X11/xorg.conf.good.backup

Agora é só instalar o driver, diga Yes para tudo:

$ sudo sh NVIDIA-Linux-x86-177.13-pkg1.run


Se durante a instalação der erro, dizendo que não consegue criar alguns arquivos, veja o caminho, provavelmente como aconteceu comigo será preciso criar a pasta:

$ sudo mkdir /usr/lib/nvidia

Depois é só voltar a executar a instalação e diga Yes para tudo mais uma vez:

$ sudo sh NVIDIA-Linux-x86-177.13-pkg1.run

Reiniciar o computador, e pronto, os gráficos deverão estar muito melhores, e o UT2004 sem bugs.

Guarde o arquivo de instalação, pois sempre que for instalado um novo kernel será preciso reinstalar o driver.

Friday, September 5, 2008

Unreal Tournament 2004 - Linux Dedicated Server

Nossa como é bom voltar a jogar UT2004 :P

Downloads

Servidor:
$ wget http://downloads.unrealadmin.org/UT2004/Server/DedicatedServer3323.zip
BonusPack:
$ wget http://downloads.unrealadmin.org/UT2004/Server/dedicatedserver3339-bonuspack.zip
Anticheater:
$ wget http://downloads.unrealadmin.org/UT2004/AntiCheat/UTSecure2K4-111.zip

Quem for jogar, convêm ter o MegaPack instalado, para evitar que fique fazendo download:

MegaPack - 12/13/05 - 205 MB

Instalação

$ unzip DedicatedServer3323.zip
$ mv UT2004-Dedicated-3323 UT2004srv
$ unzip -o dedicatedserver3339-bonuspack.zip -d UT2004srv
$ unzip -o UTSecure2K4-111.zip -d UT2004srv
$ chmod +x UT2004srv/System/ucc*

Configuração

Não apague nenhuma linha do arquivo, apenas altere as linhas indicadas abaixo.

Editar o UT2004.ini:

$ vim UT2004srv/System/UT2004.ini

Habilitar a administração web:

[UWeb.WebServer]
bEnabled=True
ListenPort=7775

Alterar o nome do servidor:

[Engine.GameReplicationInfo]
ServerName=Nome Do Teu Servidor
ShortName=Nome Servidor

Liberar para quem não tem o jogo original poder jogar, e desabilitar a verificação de keys:

[IpDrv.MasterServerUplink]
DoUplink=False
UplinkToGamespy=False
SendStats=False
ServerBehindNAT=False
DoLANBroadcast=False
bIgnoreUTANBans=True


Executar

$ cd UT2004srv/System
$ sudo ./ucc-bin server DM-Gael?game=XGame.xDeathMatch?mutator=XGame.MutQuadJump?AdminName=admin?AdminPassword=XXXXX?GamePassword=XXXXX ini=UT2004.ini log=UT2004.log -nohomedir


Os XXXXX são as senhas, a senha para entrar no servidor é a ?GamePassword=XXXXX, substitua os XXXXX por uma senha mais intuitiva do seu entender. Os parametros ?Admin* são os dados para entrar na administração web pelo endereço http://servidor:7775.

Se obtiver este erro:
./ucc-bin: error while loading shared libraries: libstdc++.so.5: cannot open shared object file: No such file or directory

Para resolver este erro é preciso fazer um link simbólico para a versão 5.* da libstdc++, que fica na pasta /usr/lib/libstdc++*, no meu caso fiz assim:

$ sudo ln -s /usr/lib/libstdc++.so.5.0.7 /usr/lib/libstdc++.so.5

Agora é só executar de novo!

Jogar

Para jogar no servidor, é só ir na lista de servidores online dentro do jogo e clicar com o botão direito e no menu que aparece ir em "Open Ip", e colocar o endereço do servidor!

Quem não tem o jogo original pode jogar no teu servidor usando este crack:

Unreal Tournament 2004 v3369 PRIVATE WINDOWS SERVER PATCH

Detalhes da Configuração

Na linha de execução tem os parâmetros:

DM-Gael?game=XGame.xDeathMatch?mutator=XGame.MutQuadJump

DM-Geal se refere ao Mapa, você pode colocar o nome de outro mapa, basta ver os mapas disponíveis em UT2004srv/Maps/*.

O game= XGame.xDeathMatch é o tipo de jogo, todos os tipos de jogos:

Assault: AS-MotherShip?game=UT2k4Assault.ASGameInfo
CTF: CTF-FaceClassic?game=XGame.xCTFGame
Bombing Run: BR-Serenity?game=XGame.xBombingRun
DoubleDomination: DOM-SunTemple?game=xGame.xDoubleDom
DeahtMatch: DM-Rankin?game=XGame.xDeathMatch
Invasion: DM-Antalus?game=SkaarjPack.Invasion
LastManStanding: DM-Morpheus3?game=BonusPack.xLastManStandingGame
Mutant: DM-Deck17?game=BonusPack.xMutantGame
Onslaught: ONS-Torlan?game=Onslaught.ONSOnslaughtGame
TeamDeathMatch: DM-Rankin?game=XGame.xTeamGame

O mutator=XGame.MutQuadJump é o mutator, pode remover isto se não quiser nenhum mutator, todos os tipos de mutators:

Arena: XWeapons.MutArena
Beserk: UnrealGame.MutBerserk
Big Head: UnrealGame.MutBigHead
Delayed Spawn: UnrealGame.MutDelayedSpawn
Float-Away Corpses: XGame.MutHeliumCorpses
InstaGib: XGame.MutInstaGib
Zoom InstaGib: XGame.MutZoomInstaGib
LowGravity: UnrealGame.MutLowGrav
No Adrenaline: XGame.MutNoAdrenaline
No Super Weapons: XWeapons.MutNoSuperWeapon
Quad Jump: XGame.MutQuadJump
AutoHealing: XGame.MutRegen
Slow Motion Deaths: XGame.MutSlomoDeath
Species Specific Stats: XGame.MutSpeciesStats
UDamage Reward: XGame.MutUDamageReward
Vampire :XGame.MutVampire
UTV2004S (UTV2004 in SeeAll mode): UTV2004s.utvMutator
UT2k3 Style Weapon Throwing/Boosting: XGame.MutFastWeapSwitch
UTClassic: UTClassic.MutUTClassic
Lightning Gun 2 Sniper Rifle: UTClassic.MutUseSniper
Sniper Rifle 2 Lightning Gun: UTClassic.MutUseLightning
Camouflage Combo (RRRR): Bonuspack.MutCrateCombo
Pint-sized combo (LLLL): Bonuspack.MutPintSizeCombo
BigWheels: Onslaught.MutBigWheels
Light Weight Vehicles: Onslaught.MutLightweightVehicles
Onslaught Weapons: Onslaught.MutOnslaughtWeapons
Jumping Vehicles: Onslaught.MutWheeledVehicleStunts
Vehicle Arena: OnslaughtFull.MutVehicleArena

Referência

DragonBe - Unreal Tournament 2004 Dedicated Server

Gentoo - UT2004 Dedicated Server Installation

LINUX; UT2004-bin: error while loading shared libraries: libstdc++.so.5

Compre o jogo orignal!

Este jogo esta barato e vale a pena ter o original.

É um excelente jogo, e é dos jogos que mais se preocupa em ter suporte nativo ao Linux, por isso também, não deixe de colaborar.

Monday, September 1, 2008

Nginx

Conheci o Nginx no forum do GUJ.com.br, depois com os resultados que o Fabio Kung postou no blog da Caelum, fiquei convencido que o Nginx seria a melhor solução para os meus problemas.

E depois que conheci o Nginx já não quero mais nada, estou extremamente satisfeito, excelente robustez.

Para instalar o Nginx fiz um artigo no VivaOLinux.com.br que ensina como fazer a instalação e os links do site e da documentação.

Consegui fazer uma configuração simples para configurar multiplos domínios virtuais, segue a configuração:


worker_processes 5;
error_log logs/error.log;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
gzip on;
gzip_min_length 1100;
gzip_buffers 16 8k;
gzip_types text/plain text/html text/xml text/xhtml text/css text/js application/x-javascript application/json;
error_page 500 502 503 504 /50x.html;
server {
listen 80;
server_name _;
root /home/websites/$host;
location / {
index index.html index.htm index.jsp;
}
location ~ \.jsp$ {
proxy_pass http://localhost:8080;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
}
}
}


Repare nesta linha:


root /home/websites/$host;


Ai em /home/websites/* eu tenho os atalhos para as pastas reais dos domínios.

Então por exemplo para acrescentar um novo domínio dominio.com:

ln -s /home/dominio.com /home/websites/dominio.com
ln -s /home/dominio.com /home/websites/www.dominio.com


Assim para configurar um novo domínio no Nginx é só adicionar um novo atalho no /home/websites neste caso.

Ativar compressão gzip:


gzip on;
gzip_min_length 1100;
gzip_buffers 16 8k;
gzip_types text/plain text/html text/xml text/xhtml text/css text/js application/x-javascript application/json;


Para o Nginx encaminhar os JSPs para o Jetty:


location ~ \.jsp$
proxy_pass http://localhost:8080;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
}

Thursday, August 21, 2008

Movie Clip Fit

Um problema básico hoje em dia para fazer resize em flash é posicionar os movieclips corretamente, existe este projeto que facilita a vida para fazer resize do flash dentro do browser:

http://swffit.millermedeiros.com/

Baseado neste projeto fiz este objeto que ajuda a ajusta as posições dos movieclips dentro do flash de acordo com o resize:


var fit = {
baseStageWidth: Stage.width,
baseStageHeight: Stage.height,
oldStageWidth: Stage.width,
oldStageHeight: Stage.height,
xLeft: 0,
xRight: 1,
yTop: 0,
yBottom: 1,
xMovies: new Array(),
xs: new Array(),
xAligns: new Array(),
x: function (mv:MovieClip, align:Number, x:Number) {
if (align == null) {
align = this.xLeft;
}
this.xMovies.push(mv);
if (x == null) {
if (align == this.xLeft) {
x = mv._x;
} else if (align == this.xRight) {
x = mv._x + mv._width;
}
}
this.xs.push(x);
this.xAligns.push(align);
},
yMovies: new Array(),
ys: new Array(),
yAligns: new Array(),
y: function (mv:MovieClip, align:Number, y:Number) {
if (align == null) {
align = this.yTop;
}
this.yMovies.push(mv);
if (y == null) {
if (align == this.yTop) {
y = mv._y;
} else if (align == this.yBottom) {
y = mv._y + mv._height;
}
}
this.ys.push(y);
this.yAligns.push(align);
},
widthMovies: new Array(),
widths: new Array(),
width: function (mv:MovieClip) {
this.widthMovies.push(mv);
this.widths.push(mv._width);
},
heightMovies: new Array(),
heights: new Array(),
height: function (mv:MovieClip) {
this.heightMovies.push(mv);
this.heights.push(mv._height);
},
proportionalMovies: new Array(),
proportionalWidths: new Array(),
proportionalHeights: new Array(),
proportional: function (mv:MovieClip) {
this.proportionalMovies.push(mv);
this.proportionalWidths.push(mv._width);
this.proportionalHeights.push(mv._height);
},
fix: function () {
for (var k:Number = 0; k < this.widthMovies.length; k++) {
this.widths[k] = (Stage.width * this.widths[k]) / this.oldStageWidth;
this.xMovies[k]._width = this.widths[k];
}
for (var k:Number = 0; k < this.heightMovies.length; k++) {
this.heights[k] = (Stage.height * this.heights[k]) / this.oldStageHeight;
this.heightMovies[k]._height = this.heights[k];
}
for (var k:Number = 0; k < this.proportionalMovies.length; k++) {
var ratioW = Stage.width / this.proportionalWidths[k];
var ratioH = Stage.height / this.proportionalHeights[k];
if (ratioW < ratioH ) {
this.proportionalWidths[k] = this.proportionalWidths[k] * ratioW;
this.proportionalHeights[k] = this.proportionalHeights[k] * ratioW;
} else {
this.proportionalWidths[k] = this.proportionalWidths[k] * ratioH;
this.proportionalHeights[k] = this.proportionalHeights[k] * ratioH;
}
this.proportionalMovies[k]._width = this.proportionalWidths[k];
this.proportionalMovies[k]._height = this.proportionalHeights[k];
}
for (var k:Number = 0; k < this.xMovies.length; k++) {
this.xs[k] = (Stage.width * this.xs[k]) / this.oldStageWidth;
if (Stage.align.indexOf("L") > -1) {
this.xMovies[k]._x = this.xs[k];
} else {
this.xMovies[k]._x = ((this.baseStageWidth - Stage.width) / 2) + this.xs[k];
}
if (this.xAligns[k] == this.xRight) {
this.xMovies[k]._x -= this.xMovies[k]._width;
}
}
for (var k:Number = 0; k < this.yMovies.length; k++) {
this.ys[k] = (Stage.height * this.ys[k]) / this.oldStageHeight;
if (Stage.align.indexOf("T") > -1) {
this.yMovies[k]._y = this.ys[k];
} else {
this.yMovies[k]._y = ((this.baseStageHeight - Stage.height) / 2) + this.ys[k];
}
if (this.yAligns[k] == this.yBottom) {
this.yMovies[k]._y -= this.yMovies[k]._height;
}
}
this.oldStageWidth = Stage.width;
this.oldStageHeight = Stage.height;
}
};


Se quiser que um movieclip fique sempre na posição x e y de acordo com o resize, basta passar a referência do movieclip para as funções x e y:


fit.x(MovieClip);
fit.y(MovieClip);


Ou então se precisar que um movieclip tenha o tamanho dinâmico de acordo com o resize, basta passar a referência do movieclip para as funções width e height:


fit.width(MovieClip);
fit.height(MovieClip);


Para fazer resize em porporção, ideal para imagens, use:


fit.proportional(MovieClip);


E para fazer alinhamentos, por exemplo alinhar um movieclip colado ao lado direito:


fit.x(MovieClip, fit.xRight);


E para alinhar colado a base:


fit.y(MovieClip, fit.yBottom);


Os alinhamentos suportados para o x são fit.xLeft(padrão) e fit.xRight, e para y são fit.yTop(padrão) e fit.yBottom.

O alinhamento esta preparado apenas para a configuração padrão de alinhamento do Flash e para o "TL" (alinhamento Top/Left):


Stage.scaleMode = "noScale";
Stage.align = "TL";


Outros parâmetros de alinhamento não foram testados.

No exemplo do swffit tem a função calcSize que é chamada quando cada resize é feito, é preciso adicionar a função fix, para cada vez que for feito o resize ajustar as posições:


function calcSize() {
fit.fix();
...
}


Veja o video que demonstra como utilizar: