urban terror, udp proxy

A internet é mesmo um lugar maluco. Eu não sou muito de jogar, mas nos últimos meses um amigo me mostrou o urban terror, um jogo no estilo counter strike que é gratuito, baseado na engine do quake3 arena.

Dias depois fui banido de um dos servidores mais populares do negócio, o bashfull, e então desencanei e nunca mais joguei lá. Porém, várias vezes que fui jogar, não havia ninguém nos outros servidores, e lá estava sempre cheio de gente.

ut, banned

Tentei o meio normal da coisa e mandei 2 emails pro admin, nos últimos 20 dias. Como fui ignorado, e meu IP do virtua é fixo, não sobrou outra alternativa a não ser usar um proxy no estilo BNC, tipo os que eu usava a uns 10 anos atrás nas épocas do irc.

Pra terminar, não achei nada que preste pra fazer proxy Nx1 via udp – talvez eu seja burro de mais pra procurar essas bobeiras – e então acabei escrevendo um em python.

Em 20 minutos, fiz tudo e testei em um ubuntu. Ficou bem simples, veja ai:

#!/usr/bin/env python
# coding: utf-8
# 20081225 AF
#
# urban terror asynchronous udp proxy
# requires python 2.5 (linux, bsd, etc)
# configuration
maxclients = 10
proxyport = 27960
ut_server_addr = ‘189.38.63.196’
ut_server_port = 27962

# don’t touch anything below.
import os, sys, time, syslog, socket, select, threading

clients = {}
timeout = 15
pktsize = 4096
infolog = lambda msg: syslog.syslog(syslog.LOG_INFO, msg)

def daemonize():
    # double fork, ignore exceptions
    pid = os.fork()
    if not pid:
        os.setsid()
        pid = os.fork()
        if not pid:
            os.chdir(‘/’)
            [k.close() for k in sys.stdin, sys.stdout, sys.stderr]
        else:
            os._exit(0)
    else:
        os._exit(0)

def cleaner():
    # remove inactive slots
    while 1:
        now = time.time()
        for slot in clients.values():
            if now – slot.time > timeout:
                infolog(‘client %s disconnected’ % str(slot.addr))
                del clients[slot.addr]
        time.sleep(5.0)

class proxy:
    def __init__(self, addr):
        self.addr = addr
        self.time = time.time()
        self.fd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.fd.connect((ut_server_addr, ut_server_port))

    def send(self, chunk):
        self.time = time.time()
        return self.fd.send(chunk)

if __name__ == ‘__main__’:
    fd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    fd.bind((”, proxyport))

    daemonize()
    syslog.openlog(‘utproxy’, syslog.LOG_PID, syslog.LOG_DAEMON)
    threading.Thread(target=cleaner).start()

    while 1:
        current = [k.fd for k in clients.values()] + [fd]
        rr, rw, er = select.select(current, [], [])

        if fd in rr:
            chunk, addr = fd.recvfrom(pktsize)
            if addr in clients.keys(): # from proxy (cli=addr) to server
                clients[addr].send(chunk)
            else:
                if len(clients) < maxclients:                     infolog('client %s connected' % str(addr))                     clients[addr] = proxy(addr)                     clients[addr].send(chunk)                 else:                     syslog.syslog(syslog.LOG_INFO,                         'client %s rejected: proxy is full' % str(addr))         for cli in clients.values():             if cli.fd in rr: # from server to proxy (cli=addr)                 chunk = cli.fd.recv(pktsize)                 fd.sendto(chunk, cli.addr)[/sourcecode] Como o proxy não precisa fazer absolutamente nenhum processamento, todo o repasse de pacotes é feito de modo assíncrono, em um único processo, e uma thread verifica as conexões inativas para removê-las da lista. Até poderia fazer o proxy de outras maneiras, talvez usando asynchat ou mesmo twisted, mas acabei optando pelo modo tradicional e o resultado é que ele não depende de nenhum módulo externo, apenas coisas básicas do python 2.5.

ut, favorite

Agora, quando entrar lá, só vou matar o bashfull. Meu nick é /dev/null.


levelhead: o jogo mais 3d !

Sem palavras. Veja o video, acesse o site, compile o fonte.


pro evolution soccer

Por falar em jogo, vai aí uma série de gols ao som de Horace Silver.

PS: winning eleven e pro evolution soccer não podem ser considerados jogos. É futebol com os dedos!


teste de turing

Com certeza você já ouviu falar na tal Máquina de Turing. Depois de umas aulas lá no Prandiano, vários anos atrás, escrevi um programa que faz aquela brincadeira de criança: pense em um número de 0 a 10 – e aí consigo advinhar o número.

Respostas de SIM e NÃO determinam o resultado. Tudo que você precisa é ser capaz de responder de maneira adequada.

Veja aí, pensei no número 13:

$ ./turingame
pense em um número de 1 a 31 e pressione enter...

01 03 05 07 09 11 13 15 17 19 21 23 25 27 29 31
esta número está aqui? [s/n]: s

02 03 06 07 10 11 14 15 18 19 22 23 26 27 30 31
esta número está aqui? [s/n]: n

04 05 06 07 12 13 14 15 20 21 22 23 28 29 30 31
esta número está aqui? [s/n]: s

08 09 10 11 12 13 14 15 24 25 26 27 28 29 30 31
esta número está aqui? [s/n]: s

16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
esta número está aqui? [s/n]: n

o número é 13!

Legal, né. Talvez o código não seja tão legal, nem tão intuitivo. Sabe como é… mas, pra mais informações, você pode ver os detalhes da Máquina de Turing e Teste de Turing (inglês) no wikipédia, nos links abaixo:

Máquina de Turing
Turing Test

Na sequência, o código do programa. É de 2004, tem até goto. Nem adianta torcer o nariz, porque duvido que um programador nunca tenha usado coisas como goto, system() e popen() – este último usa /bin/sh -c pra executar, exatamente como o você-sabe-quem.

/*
 * para compilar:
 * cc -Wall turingame.c -o turingame -lm
 *
 * turingame.c 20040726 AF
 */

#include <math.h>
#include <stdio.h>
#include <stdlib.h>

int getlist(int i, int max_num)
{
   int j, n = pow(2, i);

   for(j = 1; j < max_num/n; j+=2) {
      int r = j * n;

      for(i = 0; i < n; i++, r++)
        fprintf(stdout, "%02d ", r);
   }

   fprintf(stdout, "\n");
   return n;
}

int main(int argc, char **argv)
{
   int i, r = 0, max_pow = 5, max_num = 0;

   if(argc > 1) {
      if(*argv[1] == '-' && argv[1][1] != 'h') {
         char s[2] = { argv[1][1], 0 };
         max_pow = atoi(s);
         if(!max_pow) goto help;
      } else {
help:
         fprintf(stderr, "uso: %s [-h|-potência(padrao=%d)\n", *argv, max_pow);
         return 0;
      }

   }

   max_num = pow(2, max_pow);
   fprintf(stdout, "pense em um número de 1 a %d e pressione enter...\n",
         max_num-1); fflush(stdout);
   getchar();

   for(i = 0; i < max_pow; i++) {
      int n;
      char c;
      n = getlist(i, max_num);
      fprintf(stdout, "esta número está aqui? [s/n]: "); fflush(stdout);
      c = getc(stdin); getc(stdin);
      if(c == 's') r+=n;
      fprintf(stdout, "\n");
   }

   fprintf(stdout, "o número é %d!\n", r);

   return 0;
}