O assunto detecção e correção de erros parece algo completamente inacessível à maioria das mentes, incluindo muita gente que trabalha com informática. Uma sugestão didática é começar a abordar o assunto usando um animal que todo mundo conhece: dígitos verificadores de contas bancárias, documentos, etc.
Todo mundo já viu um dígito verificador. Na conta bancária: 12345-7. No CPF tem dois até: 111.111.111-80. Eles parecem feitos para encher o saco, pois quase sempre são muito diferentes dos demais números. São difíceis de lembrar; você lembra de todos os números exceto o dígito, e não pode executar uma operação ou completar o formulário...
O dígito verificador (abreviado DV) existe para "pegar" erros de digitação e transcrição, de forma simples e eficiente. Via de regra, o DV é sempre resultado de um cálculo feito em cima dos números anteriores. Ou seja, o DV não adiciona informação nova ao código, ele sempre pode ser calculado de novo, desde que você saiba o algoritmo.
Supondo que o DV seja a soma dos dígitos do código original, o código 1234 torna-se 1234-0. (4+3+2+1=10, então pegamos o último dígito da soma -- "módulo 10").
Se digitarmos 4234-0, o cálculo do DV mostra imediatamente que este código é inválido, pois 4+2+3+4=13. O último dígito (3) não bate com o DV digitado (0) portanto algum número tem de estar errado.
Quantos erros um dígito verificador pode pegar?
Assumindo um algoritmo ideal, um DV pega qualquer erro de digitação simples, ou seja, onde apenas um número foi digitado erradamente. No caso dos CPFs, que têm 2 DVs, a capacidade teórica é de pegar quaisquer erros de até 2 números. Três dígitos, pega até 3 erros. É simples assim.
No caso de erros mais graves, ficamos na mão da sorte. Um DV deixará passar um entre dez (10%) de erros aleatórios. O motivo é muito simples: errando dois números, há 10% de chance de "colidirmos" com outro código perfeitamente válido. É como se digitássemos por engano a conta bancária de um amigo no NetBanking em vez da nossa; não há como o DV pegar um erro desse tipo.
O CPF possui 2 DVs, então ele é muito mais resistente a erros de muitos dígitos. Apenas um em cem (1%) desses erros passariam, pelo mesmo motivo: 1% de chance do CPF digitado errado coincidir perfeitamente com o CPF de outra pessoa.
Quanto mais dígitos verificadores, mais forte fica a resistência a erros de "burst" (rajada) onde diversos números são digitados erradamente.
Como é possível o dígito veriicador detectar erros?
A mecânica da detecção de erros é na verdade muito simples. Vamos considerar um código de 3 dígitos, digamos a conta bancária de uma agência pequena. Com 3 dígitos, temos 1.000 possíveis contas bancárias.
Adicionando um dígito verificador, a conta passa a ter 4 dígitos, perfazendo um total de 10.000 possíveis códigos. Só que, desses 10.000, apenas 10% (1.000) são realmente válidos, pois correspondem a um código principal + DV válido.
Em havendo (relativamente) poucas contas bancárias válidas numa faixa numérica relativamente grande, a chance de uma conta válida ser digitada por engano diminui muito. Isso garante que, para um DV, 90% de qualquer erro vai ser pego.
É interessante mencionar que este poder de detecção de erros independe do tamanho código, Se o código tiver 15 dígitos, o DV de 2 dígitos continua sendo capaz de pegar até 2 erros sem furo. Claro que um código de 15 dígitos tem muito mais chance de ser digitado errado...
Já a garantia que 1 DV pega 100% dos erros de 1 dígito, ou 2 DVs pegam 100% dos erros de 1 ou 2 dígitos, é um pouco mais difícil de provar, depende de análise combinatória.
Ressaltando novamente, estas capacidades do DV em pegar erros são os máximos possíveis, e assumem um algoritmo de cálculo de DV ideal. Achar esse algoritmo "ideal" é um outro problema.
Como calcular um dígito verificador?
Não é fácil achar uma fórmula de DV que entregue a proteção contra erros que foi prometida nos parágrafos anteriores. Por outro lado, é facílimo achar fórmulas imprestáveis para DV. Exemplo:
DV = último dígito do código original
1234 => 1234-4
Esta fórmula hipotética é obviamente ruim, pois só pega erros de digitação cometidos no último dígito principal. Além disso, todos os códigos válidos ficarão parecidos: 1234-4, 2344-4, 4444-4...
DV = soma dos dígitos originais, módulo 10
1234 => 1234-0
Este DV é muito melhor que o outro, pois seu valor depende de todos os dígitos. A troca de qualquer dígito gera um código inválido.
Porém ele tem uma fraqueza imperdoável: a inversão de dois dígitos passa batida. Isto é um problema pois a inversão é um erro de digitação muito, muito comum. Note que 1234-0, 4321-0, 1324-0 e 1243-0 são todos códigos válidos usando o algoritmo de somas.
Uma versão real do algoritmo módulo-10 usa um truque para detectar inversões: multiplica cada dígito original por 1 ou por 2, alternadamente, contando da direita para a esquerda. Assim:
1234 => 1*2 + 2*1 + 3*2 + 4*1 = 14 => 1234-4
1243 => 1*2 + 2*1 + 4*2 + 3*1 = 15 => 1243-5
Este algoritmo é consideravelmente mais forte que os anteriores, mas seria ainda melhor se cada dígito fosse multiplicado por um peso diferente. É exatamente isto que o famoso algoritmo "módulo-11" faz: multiplica os dígitos por 2, 3, 4, 5, 6, 7, e só então retornando a 2.
A força do módulo-11 aproxima-se muito da capacidade máxima de correção de um dígito verificador, e por este motivo é o mais utilizado.
O módulo, ou seja, o resto da divisão, é a ferramenta mais utilizada como geradora de DVs pois ela tem diversas vantagens. Se o divisor é um número primo, ela "espalha" bem os DVs, evitando que se tornem repetitivos ou previsíveis. Por sua própria natureza, o módulo retorna um resultado limitado a um campo, ou seja, uma faixa de números. O módulo-11 retorna números de 0 a 10, nem mais nem menos.
Existem outros tipos de DV mais exóticos, que levam em conta os erros de digitação mais comuns etc. Considerando que o bloco numérico é igual em todo computador, faria sentido proteger mais fortemente contra erros de digitação mais comuns. O número 1 vai ser mais facilmente por um 4 do que por um 9. Fórmulas como módulo-11 não levam isto em conta.
Mas como tais DVs "exóticos" são baseados parcialmente em tabelas, não apenas numa única fórmula simples, normalmente não vale o esforço de implementação.
Proteger contra Murphy e/ou contra Maquiavel?
É importante entender que dígitos verificadores protegem de erros de boa-fé, mas não protegem de fraudes. Há três motivos básicos para isto:
a) a fórmula do DV é publicamente conhecida, assim qualquer um pode recriar o DV sem conhecê-lo;
b) e as fórmulas comumente utilizadas para DV podem ser calculadas "de trás para frente", ou seja, dado um dígito verificador (digamos, 9), é fácil chegar a um código válido (XXXXX-9).
c) o número de dígitos verificadores normalmente utilizados (1 ou 2) é insuficiente para proteger contra a procura de códigos válidos por tentativa-e-erro.
Existem formas de resolver os 3 problemas acima e chegar a um super-DV que proteja contra fraude. Um código de correção de erros que também seja capaz de proteger contra fraude denomina-se "hash".
Mas eu nunca vi tal "hash" ser usado com números decimais. Por outro lado, hashes baseados em números binários como MD5 ou SHA1 são comuns. Ainda assim, vou mostrar as técnicas básicas de tornar um DV "inquebrável".
Uma tática é calcular o DV repetidamente, desprezando os resultados intermediários. Exemplo, usando módulo 11:
1234 => 1234-3
12343 => 12343-9
12349 => 12349-8
1234-8
Calculamos o DV em três "rounds" e chegamos a um DV final (8) completamente diferente do original (3). Executar esse cálculo cascateado de trás para frente é consideravelmente mais difícil do que a fórmula módulo 11 singela. Infelizmente, ainda é possível invertê-lo.
Hashes como MD5 usam cálculos muito mais apropriados que um módulo-11 para determinar os "dígitos verificadores", de modo a dificultar para valer o cålculo inverso.
Outra tática para reforçar o DV é adicionar o comprimento do código como um dígito extra, calcular o DV, e omitir o comprimento no resultado final:
1234 => 12344 => 12344-7 => 1234-7
Para inverter o cálculo, o atacante agora terá de levar também em conta o tamanho original do código. Se ele não sabe esse tamanho original, já dificulta bastante.
A terceira tática, menos geral por exigir segredo de um elemento, mas muito utilizada, é adicionar um sufixo "secreto" ao código. Supondo que nosso sufixo secreto é 666:
1234 => 1234666 => 1234666-2 => 1234-2
Se o atacante não souber qual é o sufixo secreto, vai ficar bem difícil para ele descobrir como "fabricar" dígitos verificadores a partir dos códigos originais "pelados". Ele também não conseguirá gerar um código válido a partir de um dígito conhecido.
Um "hash" calculado com base numa mensagem que foi "temperada" com um prefixo ou sufixo secreto, denomina-se MAC (Message Authentication Code), com aplicações muito importantes em criptografia.
Naturalmente, todos os exemplos acima usam apenas um dígito verificador, o que é insuficiente para uma proteção séria contra fraudes. Uma proteção efetiva exigiria 40 dígitos ou mais, o que equivale aos 128 bits do MD5. E sufixar uma conta bancária de 5 dígitos com um DV de 40 números não é exatamente algo prático, o que explica a pouca popularidade da técnica no reino dos números decimais...
Correção de erros
Às vezes, não basta detectar erros, é preciso corrigí-los sem exigir uma segunda digitação ou transcrição. Por exemplo, a informação mandada por um míssil, satélite, sonda espacial, bóia ou balão metereológico nunca se repete; é preciso garantir que a informação original possa ser reconstruída mesmo na presença de erros.
Parece bruxaria, mas é perfeitamente possível e nem tão difícil de entender. A idéia básica é utilizar muitos dígitos verificadores, de modo que possamos determinar a "distância" entre o valor "errado" e um valor correto, e assim assumir que a informação original era o valor correto mais próximo.
A capacidade máxima de correção de erro de um código é: metade do número de dígitos menos um. Um DV de três dígitos é capaz de corrigir erros de até 1 dígito -- embora, como já vimos, seja capaz de detectar erros de até 3 dígitos com perfeição. Um DV de 2 dígitos não consegue corrigir nenhum erro, embora detecte quase todos...
Construir um código de correção de erros não é tão difícil. Uma forma boba seria repetir duas vezes o mesmo código, ou seja, transmitir a informação original três vezes:
1234 => vira 1234-1234-1234
Neste código, qualquer erro de 1 dígito pode ser corrigido. Supondo que recebemos o código com erros, desta forma:
1234-1235-1234
Está claro que há erro, mas nós não sabemos se o erro é de apenas um dígito. Correção de erros exige um passo de fé: precisamos estimar um teto para a quantidade e erros.
Se partirmos do princípio que há apenas um dígito errado, está claro que o valor original era 1234, pois dois trechos "votam" em 1234, enquanto apenas um "vota" em 1235.
Por outro lado, se recebêssemos o código assim:
1234-1235-1237
fica difícil determinar o valor original pois não temos como determinar qual é o valor correto "mais próximo". Só sabemos que o código está errado e que o erro está no quarto dígito, mas não podemos recuperar o valor correto.
Uma coisa é certa: o algoritmo acima é muito fraco, pois adicionamos 8 dígitos a mais e apenas 2 dígitos errados já frustraram a correção do erro. Com 8 dígitos, uma fórmula realmente boa conseguiria consertar até (8-1)/2 = 3 dígitos errados, em quaisquer posições.
Uma fórmula "boa" levaria em consideração a "distância hamiltoniana" entre os números. Por exemplo, 999 é numericamente próximo de 1000, mas todos os dígitos são diferentes. Nenhum erro de digitação não-intencional transformaria 999 em 1000. Por outro lado, 1000 e 11000 estão muito distantes, mas basta repicar o 1 e a confusão está feita. Um bom código procura levar isso em conta, equilibrando (e diminuindo) as chances de erros entre quaisquer números válidos.
Finalmente, não adianta adicionar DVs a esmo, isto não é suficiente para corrigir erros. Não adianta adicionar três DVs calculados com módulo-11 e esperar que se possa corrigir quaisquer erros de 1 dígito a partir disso. A fórmula tem de visar o objetivo de corrigir erros.
De decimais para binários
Tudo que foi dito acima vale também para os números binários. Só que, usando números binários, temos uma grande vantagem: o número de dígitos cresce muito mais rapidamente. Um dígito decimal corresponde grosso modo a três dígitos binários. Assim, o nosso número de conta 1234-0, de 5 dígitos, vira um número de 18 bits em binário -- 14 para o número principal e 4 para o dígito verificador.
E por que isto é uma vantagem? Porque as garantias de um DV, ou seja, de um código de correção de erro, dependem muito do número de dígitos, não interessa se são decimais ou binários. E é fácil lidar com mensagens muito grandes em um computador, com grande número de bits.
Claro que isto não faz milagre. Supondo o exemplo da conta 1234-0 em binário, com 4 bits de DV, que chamaremos doravante de código de correção de erros (EDC), o poder de fogo é o seguinte:
* correção de 100% dos erros de até 4 bits
* deixa passar até 6% dos erros de mais de 4 bits
Como 4 bits corresponde a pouco mais de um dígito decimal, e 6% não é tão melhor que 10%, a proteção é mais ou menos a mesma que um DV decimal.
A vantagem começa a aparecer quando usamos um algoritmo de EDC de verdade, como o CRC-32, muito comum no mundo da informática. Ele tem 32 bits de comprimento, ou seja, detecta 100% dos erros de até 32 bits. Se pespegarmos um CRC-32 na conta bancária, que só tem 14 bits, garantimos que NENHUM erro passará despercebido.
Além disso, o CRC-32 só deixa passar 1 em cada 4 bilhões de erros aleatórios, envolvendo qualquer número de bits.
O CRC-32 não protege contra Maquiavel, ou seja, ele não serve para proteger contra fraude. Neste caso, podemos usar os algoritmos MD5 ou SHA1, que fornecem códigos de 128 e 160 bits respectivamente. MD5 e SHA1 são hashes de qualidade criptográfica e podem ser utilizados para gerar MACs.
Da mesma forma, existem diversos algoritmos de correção de erros (ECCs), como o Reed-Solomon que é utilizado em CDs, e permite que um CD seja tocado perfeitamente mesmo depois de alguns riscos.
As mesmas regras de contagem de dígitos também valem para correção de erros em números binários. Um código ECC de 32 bits consegue corrigir até (32-1)/2 = 15 bits errados.
Também vale a regra que o tamanho da mensagem original não importa. Não interessa se a mensagem original tem 16 bits ou 16000 bits. Um ECC de 32 bits corrige até 15 erros em ambas, e detecta quaisquer erros de 32 bits em ambas. Assim, mensagens muito grandes podem ser protegidas de forma muito "barata", com poucos bits.
Exceto pela paridade, que é um código de correção de erros de 1 bit, todas as fórmulas de EDC, ECC, hash etc. para números binários são bastante complicadas.
Assim como no caso dos dígitos verificadores decimais, o "coração" de cada fórmula costuma ser o módulo, ou seja, o resto de uma divisão. Mas no caso de números binários, por diversas razões (inclusive facilidade de implementação em hardware), é costumeiro usar divisão de polinômios num campo, e não a simples divisão de números naturais.
Por exemplo o CRC-32 é definido pelo seu "polinômio gerador", que será o divisor da operação módulo. Como o CRC-32 tem 32 bits, é necessário que o divisor possua 33 bits, de modo que o resto da divisão tenha até 32 bits. A escolha desses divisores é objeto de pesquisa ativa, pois o "poder de fogo" da detecção de erros depende da boa escolha do divisor.
EPx professional blog and repository for braindumps
2009/10/30
2009/10/21
Libraries X bundles in Mac OS X
Mac OS X has this wonderful thing: bundles, where you stuff everything an application may need to run far from its development environment, including kernel drivers. But the most common objects included in a bundle are dynamic libraries.
UNIX-style libraries are a bit difficult to move into the bundle; the executable still tries to find them in original locations. And your UNIX-style libraries may themselves refer to other UNIX libraries.
But then there is the install_name_tool tool. Here goes an example of usage:
where the first path is the original reference to a UNIX library, the second path (with the @executable) is the new reference that object must follow, and "somelibrary.dylib" is the library or executable that you are trying to convince to search the library inside the bundle, and not in an absolute path of the filesystem.
By the way, you can check which libraries an executable or library refers to by
and weed out the absolute references that are not standard Mac OS X libs.
My use case was a Qt application which depended on an external library, which itself linked to Qt too. The semi-automatic macdeployqt does much of the bundle work (it copies the Qt frameworks into the bundle and updates the executable accordingly), but I had another library that needed to be copied manually, and still referred to Qt as an absolute path.
Many thanks to Henry Vieira @ INdT for this hint which saved my day :)
UNIX-style libraries are a bit difficult to move into the bundle; the executable still tries to find them in original locations. And your UNIX-style libraries may themselves refer to other UNIX libraries.
But then there is the install_name_tool tool. Here goes an example of usage:
install_name_tool -change \
/Users/epx/Qt/lib/QtGui.framework/Versions/4/QtGui \
@executable_path/../Frameworks/QtGui.framework/Versions/4/QtGui \
somelibrary.dylib
where the first path is the original reference to a UNIX library, the second path (with the @executable) is the new reference that object must follow, and "somelibrary.dylib" is the library or executable that you are trying to convince to search the library inside the bundle, and not in an absolute path of the filesystem.
By the way, you can check which libraries an executable or library refers to by
otool -L somelibrary.dylib
and weed out the absolute references that are not standard Mac OS X libs.
My use case was a Qt application which depended on an external library, which itself linked to Qt too. The semi-automatic macdeployqt does much of the bundle work (it copies the Qt frameworks into the bundle and updates the executable accordingly), but I had another library that needed to be copied manually, and still referred to Qt as an absolute path.
Many thanks to Henry Vieira @ INdT for this hint which saved my day :)
2009/10/17
Rudix: command-line utilities for Mac OS X made The Right Way (TM)
When you come from Linux and begin to use Mac OS X, you suffer a degree of (german*) "heimweh", that is, homesickness, for a number of reasons. The BSD command-line utilities are less powerful than GNU counterparts, and a lot of utilities that Linux users take for granted are not available in Mac. It is generally possible to download the source code and compile all of them, but it takes a lot of time and effort.
The biggest cultural shock is the lack of an "apt-get", which puts every application within reach. So, most of the "ports" projects like Fink, DarwinPorts etc. offer a central repository and installation via apt-get. At principle I loved this scheme, made me feel home. I even installed some KDE apps :)
In time, you learn more about the Mac OS X way of life and ports like Fink begin to feel strange:
* Everything installed via "ports" goes into /some/folder, creating a sort of "digital ghetto" of second-class applications;
* Dependency hell, a thing that is VERY annoying in Linux, is back again (albeit confined to the ghetto), while Mac OS X applications tend to be independent of 3rd party libraries. Every application has all needed parts inside its bundle, including kernel drivers.
* Reliance on a central repository
Enter Rudix, a different approach to the problem, which mixes a lot better with Mac.
In Rudix, every application is a separate package. Since most of packages are command-line apps, they are not bundles to drag into Applications, but .pkg files that install things in /usr/local. Usage of /usr/local is another nice touch of compliance with UNIX.
Most Rudix packages don't depend on other packages. The last version I installed still had some residual interdependencies but Rudá Moura, the maintainer, has been working to make very package completely independent of the others.
So, if you want exactly one application, e.g. GNU fileutils or mpg123, you just download that package from Rudix repository, install it the normal way a package is installed and Mac, and that's it. Personally, I have the whole repository downloaded in a folder, and cherry-pick the applications from there on demand.
A secondary function of Rudix is to serve as a good sample of how Mac packages can be made out of some UNIX application.
The biggest cultural shock is the lack of an "apt-get", which puts every application within reach. So, most of the "ports" projects like Fink, DarwinPorts etc. offer a central repository and installation via apt-get. At principle I loved this scheme, made me feel home. I even installed some KDE apps :)
In time, you learn more about the Mac OS X way of life and ports like Fink begin to feel strange:
* Everything installed via "ports" goes into /some/folder, creating a sort of "digital ghetto" of second-class applications;
* Dependency hell, a thing that is VERY annoying in Linux, is back again (albeit confined to the ghetto), while Mac OS X applications tend to be independent of 3rd party libraries. Every application has all needed parts inside its bundle, including kernel drivers.
* Reliance on a central repository
Enter Rudix, a different approach to the problem, which mixes a lot better with Mac.
In Rudix, every application is a separate package. Since most of packages are command-line apps, they are not bundles to drag into Applications, but .pkg files that install things in /usr/local. Usage of /usr/local is another nice touch of compliance with UNIX.
Most Rudix packages don't depend on other packages. The last version I installed still had some residual interdependencies but Rudá Moura, the maintainer, has been working to make very package completely independent of the others.
So, if you want exactly one application, e.g. GNU fileutils or mpg123, you just download that package from Rudix repository, install it the normal way a package is installed and Mac, and that's it. Personally, I have the whole repository downloaded in a folder, and cherry-pick the applications from there on demand.
A secondary function of Rudix is to serve as a good sample of how Mac packages can be made out of some UNIX application.
2009/10/16
The end of "The MoIP Experience"
Today I finished the "mobile VoIP experience" (surviving with a cell phone without voice plan, only w/ Internet). I wanted to end it before, but the telco had refused to convert my data-only plan to a voice+data plan -- until today, when I threatened to cancel the subscription. The power of --force.
In a nutshell, using MoIP is still too painful, not usable at all by a non-nerd. It worked, it may be useful for an emergency, but data networks must improve a lot until it gets "usable".
The main tool which I used to survive meanwhile was Fring, which is a wonderful piece of software. Apart from messaging capabilities (for which I will continue to use Fring anyway), the best combination of VoIP was Vono (a Brazilian SIP VoIP service provided by a mainstream telco, GVT) and Fring. Fring's Skype gateway does not work so well for voice.
For example, I could keep a conversation using Vono even over EDGE. Skype didn't go well even over 3G. Fring compression makes voice difficult to understand in noisy environments, and that seems to compound with Skype compression too.
The best thing would have been to use the SIP stack shipped with the Nokia N85, which has a reputation of being good and easier on the battery. But it has a simple and crucial problem: it does not do access point handover easily. It would tie me to use either WiFi or 3G, while Fring exchanges back and forth automatically, giving preference to WiFi if you want. The sad thing is that probably Nokia will not make its SIP VoIP work so transparently because it would hurt some telco's feelings.
Of course, MoIP over WiFi works very well, as Skype works well on PC. If you work and live in areas with WiFi coverage, the chances of surviving with MoIP are higher. Just connect once to every WiFi spot, so it becomes a registered access point and Fring will use it whenever possible.
I expected better service from 3G. Even in 3G and 3.5G areas, phone calls over Fring are difficult. Several reasons add up to cause this. Brazilian 3G is still in development. Telcos are providing a suboptimal service. 3G is not as good as we might expect by reading the theoretical specifications, bandwidth etc.
And finally, it seems that a large percentage of Brazilians get a 3G data plan and actually use as a primary Internet connection, and the thing was simply not engineered for this usage pattern, which disrupts service for uses like me that desire a very small but reliable bandwidth for MoIP.
I have made some tests and the biggest problem with (local) 3G Internet is the bandwidth variance, from absolute zero to twice the contracted bandwidth! At least, 3G works well enough for other applications like Google Maps which fetch maps as they go.
Another reason for using WiFi is battery life. Fring is known to drain batteries fast. Actually, I think the culprit is the always-on data connection, either WiFi or 3G. At least with WiFi it endures 24h or more. With 3G it lasts 6-8h. Using the phone in a completely c00l way (GPS + Google Maps + Fring + music player), don't expect it to last more than 3-4h. Anyway, if someone had a software answer for this particular problem, would easily grab a couple Nobel prizes :)
In a nutshell, using MoIP is still too painful, not usable at all by a non-nerd. It worked, it may be useful for an emergency, but data networks must improve a lot until it gets "usable".
The main tool which I used to survive meanwhile was Fring, which is a wonderful piece of software. Apart from messaging capabilities (for which I will continue to use Fring anyway), the best combination of VoIP was Vono (a Brazilian SIP VoIP service provided by a mainstream telco, GVT) and Fring. Fring's Skype gateway does not work so well for voice.
For example, I could keep a conversation using Vono even over EDGE. Skype didn't go well even over 3G. Fring compression makes voice difficult to understand in noisy environments, and that seems to compound with Skype compression too.
The best thing would have been to use the SIP stack shipped with the Nokia N85, which has a reputation of being good and easier on the battery. But it has a simple and crucial problem: it does not do access point handover easily. It would tie me to use either WiFi or 3G, while Fring exchanges back and forth automatically, giving preference to WiFi if you want. The sad thing is that probably Nokia will not make its SIP VoIP work so transparently because it would hurt some telco's feelings.
Of course, MoIP over WiFi works very well, as Skype works well on PC. If you work and live in areas with WiFi coverage, the chances of surviving with MoIP are higher. Just connect once to every WiFi spot, so it becomes a registered access point and Fring will use it whenever possible.
I expected better service from 3G. Even in 3G and 3.5G areas, phone calls over Fring are difficult. Several reasons add up to cause this. Brazilian 3G is still in development. Telcos are providing a suboptimal service. 3G is not as good as we might expect by reading the theoretical specifications, bandwidth etc.
And finally, it seems that a large percentage of Brazilians get a 3G data plan and actually use as a primary Internet connection, and the thing was simply not engineered for this usage pattern, which disrupts service for uses like me that desire a very small but reliable bandwidth for MoIP.
I have made some tests and the biggest problem with (local) 3G Internet is the bandwidth variance, from absolute zero to twice the contracted bandwidth! At least, 3G works well enough for other applications like Google Maps which fetch maps as they go.
Another reason for using WiFi is battery life. Fring is known to drain batteries fast. Actually, I think the culprit is the always-on data connection, either WiFi or 3G. At least with WiFi it endures 24h or more. With 3G it lasts 6-8h. Using the phone in a completely c00l way (GPS + Google Maps + Fring + music player), don't expect it to last more than 3-4h. Anyway, if someone had a software answer for this particular problem, would easily grab a couple Nobel prizes :)
Assinar:
Postagens (Atom)
