本帖最后由 江威 于 2016-12-1 17:45 编辑
--[[ 做法是保存认证消息,然后根据消息类型做读写分离; 在分离到不同的服务器之前,发送认证消息,并保存当前请求; 当接收到认证应答后,发送之前保存的请求。
LDAP的PDU使用ASN1进行编码 第一个字节必然是0x30(00 1 11000) 第二个字节是短编码长度,或者长编码的字节数 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Always 0x30 | Total Len ... | Always 0x02 | MsgID Len ... | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | MsgID ... | Protocol Op | Msg Len ... | Always 0x02 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | LDAP Ver Len | LDAP Ver ... | Always 0x04 | BINDDN Len ...| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | BIND DN ... | Always 0x80 | Password Len | Password ... | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 主要是看消息类型 TCP.enable_mblb(); --用来分辨读写操作 local ldap_write_class={[6]=true,[8]=true,[10]=true,[12]=true}; --这个数组用来记录支持的消息类型 local ldap_msg_types={ [0]="bind request", [1]= "bind response", [2]= "unbind request", [3]= "search request", [4]= "search response", [6]= "modify request", [7]= "modify response", [8]= "add request", [9]= "add response", [10]= "delete request", [11]= "delete response", [12]= "modifydn request", [13]= "modifydn response", [14]= "compare request", [15]= "compare response", [16]= "abandon request", [23]= "extended request", [24]= "extended response", } --读写节点池 local switch_map={["read_pool"]="pool_r",["write_pool"]="pool_w"} --调试日志开关 local debug_log_switch=true;
local rebind=false; local binding="";--保存的认证消息 local replayop="";--切换节点池而保存的其他消息 local writing=false;
--这函数只返回消息类型 local function ldap_parse(msg) local ldap_magic,next_off=struct.unpack(">I1",msg); if ldap_magic~=0x30 then return nil; end --看第二个字节的最高位是否为0 --是则跳过(len_bytes&127)个字节 local len_bytes=0; len_bytes,next_off=struct.unpack(">I1",msg,next_off); if len_bytes>128 then len_bytes=len_bytes-128; next_off=next_off+len_bytes; end local msg_type,msg_len,msg_id=0; msg_type,msg_len,next_off=struct.unpack(">I1I1",msg,next_off); --仍然要判断长度是长编码还是短编码 if msg_len>128 then msg_len=msg_len-128; next_off=next_off+msg_len; else msg_len=1; end msg_id,next_off=struct.unpack(">I"..msg_len,msg,next_off); --终于到达请求类型的偏移了,第一个字节的低5位就是消息类型 local msgtype=struct.unpack(">I1",msg,next_off); msgtype=bit.band(msgtype,31); return msgtype; end event CLIENT_ACCEPT{ TCP.collect(); } event CLIENT_DATA{ --默认一个包里的数据就是一个完整的请求 local payload=TCP.payload(); local msgtype=ldap_parse(payload); if not msgtype then TCP.close(); end if ldap_msg_types[msgtype] then if debug_log_switch then LOG.log(LOG.DEBUG,"message type is :"..ldap_msg_types[msgtype]); end else if debug_log_switch then LOG.log(LOG.DEBUG,"unknow message type:"..msgtype); end TCP.close(); end --处理认证消息 if msgtype==0 then writing=false; rebind=false; binding=payload; pool(switch_map["read_pool"]); --由读切换到写 elseif ldap_write_class[msgtype] and writing==false then if debug_log_switch then LOG.log(LOG.DEBUG,"rebind with ldap_write"); end rebind=true; writing=true; replayop=payload; TCP.replace(1,TCP.offset()+1,binding) pool(switch_map["write_pool"]); --由写切换到读 elseif not ldap_write_class[msgtype] and writing then rebind=true; writing=false; replayop=payload; TCP.replace(1,TCP.offset()+1,binding); pool(switch_map["read_pool"]); end TCP.release(); TCP.collect(); } event SERVER_CONNECTED{ TCP.collect(); } event SERVER_DATA{ if rebind then rebind=false; local payload =TCP.payload(); local msgtype=ldap_parse(payload); TCP.respond(replayop); --隔断其数据,不向客户端发 TCP.replace(1,TCP.offset()+1,""); TCP.collect(); return ; end TCP.release(); TCP.collect(); } |