2009-06-25

奇了怪了

在这个国度,政府以道德的名义加上行政力量来处罚能搜索出淫秽内容的搜索引擎,却全然没有去反思人们为何会搜索这些内容,更没有去积极的去处罚淫秽内容的发布者。这和藏污纳垢又有何区别!四千年前便有了“大禹治水”,至今却仍然不知疏导。这是为什么?集权暴力?集体健忘?千里之堤也有溃于蚁穴的那天。

标签:

2009-06-23

XMLRPC::Client.new2 is IPv4 only!

稍微测试了一下,用Python写一个IPv6的XML-RPC客户端比较简单:
import xmlrpclib

server = xmlrpclib.ServerProxy('http://[::1]:4444/usermgmt')
print server.list_users({'namespace' : 0})

如上,如果是loopback,只要把127.0.0.1换成IPv6的表示方式[::1]即可。对于ruby,可惜就不是这样了。如果依样画葫芦写出如下代码:
require 'xmlrpc/client'

server = XMLRPC::Client.new2('http://[::1]:4444/usermgmt')
p server.call('list_users', {'namespace'=>0})

那么我们很可能得到下面一条错误信息:
getaddrinfo: Name or service not known (SocketError)

在线文档中可以看到,XMLRPC::Client.new2的代码,可以确信它假设url是IPv4的。不过,不要气馁。我们还有一个最基本的接口:XMLRPC::Client.new,指定host为"::1"(注意,不要加中括号),path设为"/usermgmt",注意前面有个"/",如下:

server = XMLRPC::Client.new('::1', # host
'/usermgmt', # path
8010, # port
nil, # proxy_host
nil, # proxy_port
nil, # user
nil, # password
false, # use_ssl
nil) # timeout (default: 30)

标签:

少儿不宜

想用英语表达一句“我已沦为家庭妇男”。不知道如何翻译“妇男”,于是用了一下有道。翻译的结果显得有点少儿不宜。感兴趣的成年人士请猛击这里

标签:

2009-06-19

BIO_copy_next_retry

这个礼拜还是比较充实的,至少很久没有这么充实了。终于弄出一个补丁,使得我们的服务器可以支持IPv6。基本的PoC已经在上周完成。因为没法等OpenSSL 1.0.0的正式release,于是只能自己改代码。手工创建 socket然后把accept()之后的connfd包装在一个BIO里面,所谓“曲线救国”了。本周只是把那些已经验证过的逻辑加到库中。本以为没啥问题的小事,却折腾了整整五天。

第一个问题出在Buffered IO上。代码里面原来用的是BIO_gets()来读数据,而这个函数只在Buffered IO中才有效。一开始我自己写了个BIO_readline(),想想不太好,于是在自己的BIO上又chain了一个BIO_f_buffer(),这样不改变原来的逻辑。
sbio = BIO_new_ssl(server->ctx, 0);
bbio = BIO_new(BIO_f_buffer());
sbio = BIO_push(bbio, sbio);


有了这一层bbio后,HTTP连接开始正常工作,而HTTPS的时候却一直SIGSEGV,无论32/64位机器,无论OpenSSL 0.9.7/0.9.8,屡试不爽。GDB、valgrind一起祭上,确信了不是自己代码中内存管理的问题,而gdb的backtrace显示,出问题的函数乃是:BIO_copy_next_retry()。它的代码很简单:
void BIO_copy_next_retry(BIO *b)
{
BIO_set_flags(b,BIO_get_retry_flags(b->next_bio));
b->retry_reason=b->next_bio->retry_reason;
}


问题是,它没有判断b->next_bio是否为NULL!稍微搜索一下,发现03年底就有人问过类似问题,只是无人解答。折腾了很久,这个SIGSEGV如同幽灵一般如影随形。晚上躺在床上梳理建立连接的流程,百思不得其解为何它的next_bio是NULL,而PoC中写的代码几乎如出一辙,却没有这个问题,无论数据量的大小如何。几于绝望的时候却是灵光乍现的时候。当再次瞄了一眼BIO_copy_next_retry()的时候,我突然想到:虽然俺不能改这段代码,我可以在我的BIO chain中再append一个BIO嘛!这样它的bio_next就一定不是NULL啦!于是这个礼拜最出彩的一行诞生了:
sbio = BIO_push(sbio, BIO_new(BIO_f_null()));


在BIO_push(bbio, sbio)之前,我在sbio后添加了一个啥事都不做的BIO filter,于是这个BIO chain看起来是这样:
bbio -> sbio -> null


由于null这个BIO啥事都不做,对结果没什么影响。而正如我一直希望的那样,这次SIGSEGV终于消失了。

标签:

2009-06-14

无题

睁开眼睛,抬头看表,10:48pm。“哎呀,LP,明天的午餐还没做咧!”

-- “我都做好啦!”

一骨碌从床上爬起,冲往厨房。果然,明天的午餐已经ready。心里那滋味,真的叫做“美好”。晚餐在浦东,和姑父喝了点酒。回来醉醺醺的倒头便睡。

曾经对恒仁路同济中学对面的一座古建筑很好奇,不知道其功用是什么。晚上路过的时候,阴森森的,没有半点灯光,树木、青藤的掩饰之下,夜晚看上去特别恐怖。白天往里面看去野草丛生,但建筑物的标识则半点都无。下午实在按捺不住,在google地球上搜了一把,终于知道,那座建筑原来是老上海图书馆,乃是国民党“大上海计划”标志性建筑的一部分。它现在应该隶属于同济中学,看这张图。不过现在已经废弃,篮球架已经不复存在。这里是稍近一点的图片。现在建筑上的字迹其实已经都被洗去。

参考:

  1. 莫让经典成为遗憾“大上海”遗址寻访

  2. 上海散步(组图)六十四

  3. 杨浦民国遗迹暴走计划

标签:

2009-06-11

IPv6 in OpenSSL

最近的任务是让我们的XML-RPC Server能够在IPv6网络下远程访问。我们的底层数据是用OpenSSL的BIO来处理的,这意味着如果BIO_new_accept()之类直接支持了IPv6,那我的工作就容易许多。可惜的是,目前还不支持。综合搜索的结果来看,我只能手工创建socket,绑定一个IPv6地址,然后将accept之后的socket绑定到某个BIO。试了一下,确实可行。

说实话,openssl的代码不算好读,文档也有所欠缺,很多时候也只能去看源代码。网上抓了OpenSSL-1.0.0-beta2的代码看了一下,确信它在BIO层已经支持IPv6,而目前最新的版本0.9.8k则尚不支持。至于1.0.0何时发布,"The release date is to be set." 没有一个明确的schedule,这让人很郁闷。

下面是个故事:曾有一位RedHat的程序员在06年提交了让BIO支持IPv6的补丁,但被一位OpenSSL开发者拒绝了。摘录一段OpenSSL开发者的回复如下:
OK, to be absolutely sincere. It's not about what Microsoft [or RedHat] supports for the moment, but about exercising above mentioned discipline. It's not about looking for excuses, but exploring maximum possible extent of portability. Is it possible to write code which adapts itself to run-time environment? Regardless whether run-time is supported by vendor or not? How complicated is it? Forget that you're RedHat employee, become programmer instead:-) But this is getting off-topic. DSO_global_lookup was not the point I wanted to emphasize! DSO_global_lookup is mentioned only because you'll have to cope with it in HEAD branch. The main point is that changes of this haracter should be *conditional* for backward compatibility and you have to play by this rules.

现场:

  1. http://rt.openssl.org/Ticket/Display.html?id=1365&user=guest&pass=guest

  2. https://bugzilla.redhat.com/show_bug.cgi?id=198737

  3. https://www.redhat.com/archives/fedora-list/2009-March/msg00362.html


[1]里面记录了OpenSSL maintainer和提交补丁的RedHat Programmer之间的“交锋”; [2]里面记录了RedHat Programmer开发那个补丁的过程;[3]里面则是3年之后对这件事情的回顾。

仔细看了一下1.0.0-beta2的代码,现在的实现还是遵循了OpenSSL自己的discipline。我的疑问:

  1. 各个OpenSource项目有自己的discipline,但很多时候它的文档和discipline并不为成员之外的其他所熟知。出现冲突(实现的细节,风格的审美,可移植性/性能/安全因素等)的时候,patch的提供者和源代码的maintainer各自最理想的行为又是什么?

  2. 事实上,三年前如果OpenSSL的开发者在RedHat程序员的补丁只上稍加改进就能使得BIO直接支持IPv6,但直到三年之后,我们才看见它的存在,况且还是beta2。这真让人沮丧。

标签:

2009-06-09

不怕错误的猫


-- compile with: ghc --make cat.hs
import System.IO
import System.IO.Error
import System.Environment

cat :: String -> IO ()
cat fn = do
contents <- readFile fn
putStr contents

handler :: IOError -> IO ()
handler e
| isDoesNotExistError e =
case ioeGetFileName e of
Just path -> putStrLn $ path ++ ": file not found"
Nothing -> putStrLn "Oops! File unknown."
| otherwise = ioError e

main = do args <- getArgs
if null args
then interact id
else mapM_ (\fn -> cat fn `catch` handler) args

标签:

2009-06-08

A Tale of Two Cats

每学一门语言首先想做的是用它写一个类UNIX下cat命令的东西,简单但至少涉及命令行处理和文件I/O。

Scheme版本:

(define (cat . arg)
(let ((port (if (null? arg)
(current-input-port)
(car arg))))
(let loop ((c (read-char port)))
(if (not (eof-object? c))
(begin
(display c)
(loop (read-char port)))))))

(define (main args)
(if (null? (cdr args))
(cat)
(for-each (lambda (port) (cat port) (close-input-port port))
(map open-input-file (cdr args)))))


Haskell版本:

import System.Environment

cat :: String -> IO ()
cat fn = do
contents <- readFile fn
putStr contents

main = do args <- getArgs
if null args then interact id else mapM_ cat args


学了Haskell之后才知道Python里面的缩进、List Comprehension等似乎是从Haskell学来的。上面两个cat功能一样,区别是Haskell cat比较懒一点,那是因为Haskell是惰性求值的。勤快一点的版本只需要bytestring重新实现cat函数:

import qualified Data.ByteString.Lazy as B

cat :: String -> IO ()
cat fn = do
bs <- B.readFile fn
B.putStr bs

标签: ,

2009-06-04

牛不牛看名字

突然发现今天还没去reddit.com巡逻,于是直奔而去。看见一段有意思的comments,摘抄如下:
A: Just a side note: is there anyone in the CS field with more badass name than Guy Steele?

B: I assume some CS guy somewhere has legally changed his name to Max Power.

学过Scheme的不会不知道Guy Steele,他和Gerald J. Sussman在MIT共同实现了Scheme。网上有段视频,可以 "growing a language"搜索之。SICP中的脚注提到,该牛牛还和RMS共同写过一篇paper,基于约束传播系统对电子电路进行分析。

标签:

2009-06-02

What is next?

我现在的状态大概可以用“带薪学习”来形容 -- 但老实说,这种状态下的学习效率多数都很低下。

终于仔细看完"Write Yourself a Scheme in 48 Hours",为了理解里面的内容,顺便学了点Haskell。对于Monad的部分仍然似懂非懂,但整体思路还是非常清晰的,和SICP中的实现没有多少差别,只不过Haskell程序看起来像是一条条规则的堆砌。

Haskell中有我喜欢的特性,也有我不喜欢的 -- 或许是因为不习惯或者没有搞懂。对于程序员来说,语言只是最基础的东西。嗯,找个framework好好钻研钻研吧,顺便写点笔记啥的消磨消磨时间。

标签:

架着梯子来爬墙

Blogger/Blogspot被墙已是常态,而今天Twitter也被盾了!甚至连昨天刚上线的bing也被封杀了 -- 时运不济,奈其若何!好奇twitter为何一直没被封杀的童鞋们,zf终于听到咱们的心声了!

KAO!架着梯子来爬墙!Firefox的粉丝们,装上gladder,告别GFW!

标签:

2009-06-01

iwconfig

这几天网络常常莫名奇妙的会断掉,考虑到LP仍然能正常上网,这应该不是AP的问题。有点怀疑自己本本的无线网卡是不是大限将至。重载ipw2200后再重启网络,似乎一切又恢复正常。只是过段时间后,复又如是,莫名其妙。

刚突然想起,搬到新家后周围有个无线网络的essid和咱的一样,都是"TP-LINK" -- 懒人遇上懒人了。怀着“死马当活马医”的心理,把:
iwconfig eth1 essid "TP-LINK" key s:******


改成:
iwconfig eth1 ap 00:1D:0F:XX:YY:ZZ key s:******


暂时似乎一切OK.

标签: