Update of /cvsroot/jungerl/jungerl/lib/esmb/src In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv27419 Modified Files: esmb.app.src esmb.erl esmb_app.erl esmb_browser.erl esmb_client.erl esmb_lib.hrl esmb_netbios.erl esmb_rpc.erl esmb_sup.erl iconv.erl Log Message: Fixed bug with many files in folder on Samba. Changed the recv.buffer size for trans2-next messages. Index: esmb.erl =================================================================== RCS file: /cvsroot/jungerl/jungerl/lib/esmb/src/esmb.erl,v retrieving revision 1.23 retrieving revision 1.24 diff -u -d -r1.23 -r1.24 --- esmb.erl 12 Jul 2005 11:54:17 -0000 1.23 +++ esmb.erl 24 Nov 2005 13:59:10 -0000 1.24 @@ -111,9 +111,12 @@ -include("esmb_rpc.hrl"). - +-ifdef(debug). +-define(sdbg(S,A), ?elog(S,A)). +-else. -define(sdbg(S,A), true). -%%-define(sdbg(S,A), ?elog(S,A)). +-endif. + %%% ============================================== %%% ====== T Y P E D E C L A R A T I O N S ====== @@ -909,8 +912,7 @@ %%% @end %%% connect(Host, SockOpts, Port) -> - Opts = [binary, {packet, 0}|SockOpts], - case gen_tcp:connect(Host, Port, Opts) of + case esmb_netbios:connect(Host, Port, SockOpts) of {ok,S} -> case nbss_session_request(S, "*SMBSERVER", caller()) of {ok,_} -> @@ -929,7 +931,7 @@ %%% @end %%% close(S) -> - gen_tcp:close(S), + esmb_netbios:close(S), ok. @@ -1195,6 +1197,7 @@ %%% @end %%% list_dir(S, InReq, Path) -> + ?sdbg("Enter list_dir/3~n", []), catch c_list_dir(S, InReq, Path). c_list_dir(S, InReq, Path) -> @@ -1203,7 +1206,7 @@ {Req2, X} when X#find_result.eos == true -> Req2#smbpdu{finfo = X#find_result.finfo}; {Req2, X} -> - list_dir_cont(S, Req2, Path, X#find_result.sid, X#find_result.finfo) + list_dir_cont(S, Req2, <<>>, X#find_result.sid, X#find_result.finfo) end. list_dir_cont(S, InReq, Path, Sid, Finfo) -> @@ -1291,7 +1294,11 @@ c_negotiate(S) -> {Req, Pdu} = smb_negotiate_pdu(), - decode_smb_response(Req, nbss_session_service(S, Pdu)). + Neg = decode_smb_response(Req, nbss_session_service(S, Pdu)), + %% Sigh...we want to get hold of the socket in case + %% we need to retrieve more data, e.g far down in the + %% dec_trans2_xxxxx code. + Neg#smb_negotiate_res{sock = S}. %%% @@ -1631,6 +1638,7 @@ _/binary>> = Buffer end). + dec_trans2_find_x2(Req, Pdu, SubCmd) -> Res = safe_dec_smb(Req, Pdu), % NB: may throw(Pdu) <<TotParamCount:16/little, @@ -1655,12 +1663,95 @@ LastNameOffset, Res#smbpdu.bf), <<_:DataOffset/binary, Data/binary>> = Pdu, + x2_more(Res, Sid, Data, SearchCount, EndOfSearch, + TotDataCount, DataCount + DataDisplacement). + + + +%%% We have got all the data +x2_more(Res, Sid, Data, SearchCount, EoS, TotDataCount, TotDataCount) -> + ?sdbg("x2_more - Yes, we got all data~n", []), + Finfo = dec_find_file_both_dir_info(Res, Data, SearchCount), + {Res, #find_result{sid = Sid, + eos = to_bool(EoS), + finfo = Finfo}}; +%%% We need more data +x2_more(Res, Sid, Data, SearchCount, EoS, TotDataCount, DataCount) + when TotDataCount > DataCount -> + ?sdbg("x2_more - We need more data (~w)~n", [TotDataCount - DataCount]), + X = x2_get_more(Res, Data), + Finfo = dec_find_file_both_dir_info(Res, X#smbpdu.data, SearchCount), + {Res, #find_result{sid = Sid, + eos = to_bool(EoS), + finfo = Finfo}}; +%%% Bad case, log error, and handle it gracefully !! +x2_more(Res, Sid, Data, SearchCount, EoS, TotDataCount, DataCount) -> + ?elog("+++ x2_more got error: TotDataCount=~p , DataCount=~p~n", + [TotDataCount, DataCount]), Finfo = dec_find_file_both_dir_info(Res, Data, SearchCount), %%print_fd_info(Finfo), {Res, #find_result{sid = Sid, - eos = to_bool(EndOfSearch), + eos = to_bool(EoS), finfo = Finfo}}. +x2_get_more(Req, Data) -> + S = (Req#smbpdu.neg)#smb_negotiate_res.sock, + {ok, _, Pdu} = esmb_netbios:recv(S), + Res = safe_dec_smb(Req, Pdu), % NB: may throw(Pdu) + <<TotParamCount:16/little, + TotDataCount:16/little, + _:16/little, % reserved + ParamCount:16/little, + ParamOffset:16/little, + ParamDisplacement:16/little, + DataCount:16/little, + DataOffset:16/little, + DataDisplacement:16/little, + SetupCount, + _/binary>> = Res#smbpdu.wp, + Bf = Res#smbpdu.bf, + {SetupWords, B1} = + if (SetupCount > 0) -> + <<Xsw:SetupCount/binary,Xb1/binary>> = Bf, + {Xsw, Xb1}; + true -> + {<<>>, Bf} + end, + %% We may have some pad bytes here between the + %% ByteCount parameter and the actual data. + %% Strip it off by computing how many bytes + %% we have upto and including the ByteCount param, + %% and subtract that from the DataOffset param. + %% Whatever is left is the number of pad-bytes. + Pad = DataOffset - + (?SMB_HEADER_LEN + + 1 + % WordCount == 1 byte + ((Res#smbpdu.wc + SetupCount) * 2) + + 2), % ByteCount == 2 bytes + NewData = if (Pad > 0) -> + <<SS:Pad/binary,Xdata/binary>> = B1, + Xdata; + true -> + B1 + end, + if + (TotDataCount == (DataCount + DataDisplacement)) -> + ?sdbg("x2_get_more - Yes, got it all~n", []), + Res#smbpdu{data = concat_binary([Data,NewData])}; + (TotDataCount > (DataCount + DataDisplacement)) -> + ?sdbg("x2_get_more - Need more ~n", [TotDataCount - (DataCount + DataDisplacement)]), + x2_get_more(Res, concat_binary([Data,NewData])); + true -> + %% Bad case, see comment above. + ?elog("x2_get_more: ERROR TotDataCount=~p , DataCount=~p~n", + [TotDataCount, DataCount]), + Res#smbpdu{data = concat_binary([Data,NewData])} + end. + + + + + %%% --- @@ -1696,8 +1787,10 @@ dec_find_file_both_dir_info(Rest, Ucode, Max, I) when I > Max -> []; dec_find_file_both_dir_info(Rest, Ucode, Max, I) -> - ?elog("dec_find_file_both_dir_info: <ERROR> Missing file info I=~p~n",[I]), - %%hexprint(b2l(Rest)), + {backtrace, BT} = process_info(self(), backtrace), + ?elog("dec_find_file_both_dir_info: <ERROR> Missing file info I=~p Max=~p~nBacktrace=~s~n", + [I,Max,binary_to_list(BT)]), + hexprint(b2l(Rest)), []. @@ -2193,7 +2286,7 @@ <<ParamCount:16/little, % Total parameter bytes sent 0:16/little, % Total data bytes sent 10:16/little, % Max parameter bytes to return - 4096:16/little, % Max data bytes to return + ?MAX_BUFFER_SIZE:16/little,% Max data bytes to return 0, % Max setup words to return 0, % reserved 0:16/little, % Flags Index: esmb.app.src =================================================================== RCS file: /cvsroot/jungerl/jungerl/lib/esmb/src/esmb.app.src,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- esmb.app.src 5 Jun 2005 22:26:29 -0000 1.3 +++ esmb.app.src 24 Nov 2005 13:59:10 -0000 1.4 @@ -1,14 +1,8 @@ {application,esmb, - [{description,"Erlang SMB Library"}, + [{description,"esmb handling"}, {vsn,"%VSN%"}, {modules,[%MODULES%]}, {registered,[]}, {env, []}, {mod, {esmb_app, []}}, - {applications,[kernel,stdlib,sasl]}, - {dependencies, - [{kernel, "2.9.6"}, - {stdlib, "1.12.7"}, - {fd_server, "2.3.0"}, - {sasl,"1.10.1"}]}]}. - + {applications,[kernel,stdlib,sasl]}]}. Index: esmb_lib.hrl =================================================================== RCS file: /cvsroot/jungerl/jungerl/lib/esmb/src/esmb_lib.hrl,v retrieving revision 1.16 retrieving revision 1.17 diff -u -d -r1.16 -r1.17 --- esmb_lib.hrl 12 Jul 2005 11:54:18 -0000 1.16 +++ esmb_lib.hrl 24 Nov 2005 13:59:10 -0000 1.17 @@ -220,7 +220,6 @@ -define(HEADER_SIZE, 100). % max_data_sent = max_buffer_size - header_size -%-define(MAX_BUFFER_SIZE, 8192). -define(MAX_BUFFER_SIZE, 16644). %%% This record hold the negotiation result. @@ -234,7 +233,9 @@ samba2=false, samba2_cset=?CSET_ASCII, netware=false, - flags2 % copy of the flags2 field from the neg. PDU + flags2, % copy of the flags2 field from the neg. PDU + %% --- Own, additional info + sock % The Socket fd used for this session }). %%% SecurityMode flags when LANMAN is negotiated Index: esmb_client.erl =================================================================== RCS file: /cvsroot/jungerl/jungerl/lib/esmb/src/esmb_client.erl,v retrieving revision 1.14 retrieving revision 1.15 diff -u -d -r1.14 -r1.15 --- esmb_client.erl 27 Apr 2005 10:43:00 -0000 1.14 +++ esmb_client.erl 24 Nov 2005 13:59:10 -0000 1.15 @@ -227,7 +227,7 @@ Cset = get(charset), WinPath = mk_winpath(Neg, Cwd, Cset), Udir = to_ucs2(Neg, add_wildcard(Neg, Cset, WinPath), Cset), - Pdu = esmb:list_dir(S, Pdu0, Udir), + Pdu = (catch esmb:list_dir(S, Pdu0, Udir)), print_file_info(Neg, Pdu#smbpdu.finfo), {Pdu, Cwd}. @@ -239,7 +239,8 @@ X#file_info.size, check_attr(X#file_info.attr)]) end, - lists:foreach(F, L). + lists:foreach(F, L), + io:format("Number of entries are ~w~n", [string:len(L)]). dt(X) -> {Y,M,D} = X#dt.last_access_date, Index: esmb_netbios.erl =================================================================== RCS file: /cvsroot/jungerl/jungerl/lib/esmb/src/esmb_netbios.erl,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- esmb_netbios.erl 27 Apr 2005 10:43:00 -0000 1.1 +++ esmb_netbios.erl 24 Nov 2005 13:59:10 -0000 1.2 @@ -10,7 +10,7 @@ nbss_session_service/2, nbss_datagram_service/2, nbss_src_name/1, nbss_dst_name/1, nb_dec_name/1, tt_ename/1, tt_dname/1, dec_nbns/2, positive_query_response_pdu/2, - dec_nbss_datagram/1]). + dec_nbss_datagram/1, recv/1, connect/3, close/1]). -import(esmb, [b2l/1, ip2bin/1, bin2ip/1, ip2str/1, lcase/1, sizeof/1]). @@ -30,7 +30,7 @@ nbss_datagram_service(Dgm, Pdu) -> Res = gen_udp:send(Dgm#netbios_dgm.sock, - "192.168.128.255", + "192.168.128.255", %% FIXME ?NETBIOS_DGM_PORT, nbss_datagram_pdu(Dgm, Pdu)), Res. @@ -62,27 +62,28 @@ Bin. % NYI !! -dec_msg(<<?POSITIVE_SESSION_RESPONSE,Flags,Length:16>>) -> +dec_msg(_, <<?POSITIVE_SESSION_RESPONSE,Flags,Length:16>>) -> {ok, ?POSITIVE_SESSION_RESPONSE}; -dec_msg(<<?SESSION_SERVICE, _, Length:16, SMB_pdu/binary>>) -> - {ok, ?SESSION_SERVICE, get_more(Length, sizeof(SMB_pdu), [SMB_pdu])}; -dec_msg(<<?SESSION_KEEP_ALIVE, _/binary>>) -> +dec_msg(S, <<?SESSION_SERVICE, _, Length:16, SMB_pdu/binary>>) -> + {ok, ?SESSION_SERVICE, get_more(S, Length, sizeof(SMB_pdu), [SMB_pdu])}; +dec_msg(_, <<?SESSION_KEEP_ALIVE, _/binary>>) -> {ok, ?SESSION_KEEP_ALIVE}; -dec_msg(<<?NEGATIVE_SESSION_RESPONSE,Flags,Length:16,Ecode>>) -> +dec_msg(_, <<?NEGATIVE_SESSION_RESPONSE,Flags,Length:16,Ecode>>) -> Emsg = neg_sess_resp(Ecode), {error, neg_sess_resp(Ecode)}; -dec_msg(Bin) -> +dec_msg(_, Bin) -> ?elog("dec_msg got: ~p~n",[Bin]), {error, Bin}. -get_more(Expected, Got, Bins) when Got < Expected -> - receive - {tcp,_,Bin} -> - get_more(Expected, Got + size(Bin), [Bin | Bins]) +get_more(S, Expected, Got, Bins) when Got < Expected -> + case recv(S, Expected - Got) of + {ok, Bin} -> + get_more(S, Expected, Got + size(Bin), [Bin | Bins]) end; -get_more(_, _, Bins) -> +get_more(_, Expected, _Got, Bins) -> concat_binary(lists:reverse(Bins)). + neg_sess_resp(16#80) -> "Not listening on called name"; neg_sess_resp(16#81) -> "Not listening for calling name"; neg_sess_resp(16#82) -> "Called name not present"; @@ -274,35 +275,63 @@ lcase_host(L) when list(L) -> lcase(L). +%%% +%%% We want to make sure we connect in passive mode so +%%% that we can control exactly how many bytes to be read. +%%% +connect(Host, Port, SockOpts) -> + Opts = [binary, {packet,0}, {active,false} | SockOpts], + gen_tcp:connect(Host, Port, Opts). + +close(Sock) -> + gen_tcp:close(Sock). + + send_recv(S, Packet) -> gen_tcp:send(S, [Packet]), recv(S). recv(S) -> - receive - {tcp,S,Bin} -> - case dec_msg(Bin) of - {ok, ?SESSION_KEEP_ALIVE} -> - recv(S); - Else -> - Else - end; - - {tcp,_,Bin} -> - %%?elog("recv: ignoring stale tcp msg~n",[]), - recv(S); - - {tcp_closed,S} -> - %%?elog("recv: port closed~n",[]), - exit(closed); - - {tcp_closed,_} -> - %%?elog("recv: ignoring stale port closed msg~n",[]), - recv(S); - - Else -> - %%?elog("recv: got unexpected msg: ~p~n",[Else]), - gen_tcp:close(S), - exit(Else) + case recv_4(S) of + {ok, Bin} -> + dec_msg(S, Bin); + {error, Reason} -> + ?elog("recv/1: got error, Reason=~p~n", [Reason]), + {error, Reason} end. +recv_4(S) -> + recv(S, 4). + +recv(S, Length) -> + gen_tcp:recv(S, Length). + + +%%%old_recv(S) -> +%%% receive +%%% {tcp,S,Bin} -> +%%% case dec_msg(Bin) of +%%% {ok, ?SESSION_KEEP_ALIVE} -> +%%% recv(S); +%%% Else -> +%%% Else +%%% end; +%%% +%%% {tcp,_,Bin} -> +%%% %%?elog("recv: ignoring stale tcp msg~n",[]), +%%% recv(S); +%%% +%%% {tcp_closed,S} -> +%%% %%?elog("recv: port closed~n",[]), +%%% exit(closed); +%%% +%%% {tcp_closed,_} -> +%%% %%?elog("recv: ignoring stale port closed msg~n",[]), +%%% recv(S); +%%% +%%% Else -> +%%% %%?elog("recv: got unexpected msg: ~p~n",[Else]), +%%% gen_tcp:close(S), +%%% exit(Else) +%%% end. + |