| Christopher Piro | 2f5afce | 2007-06-29 07:17:33 +0000 | [diff] [blame^] | 1 | -module(tSocket). | 
|  | 2 |  | 
|  | 3 | -include("thrift/thrift.hrl"). | 
|  | 4 | -include("thrift/transport/tTransportException.hrl"). | 
|  | 5 | % -include("thrift/transport/tTransport.hrl"). | 
|  | 6 | -include("thrift/transport/tSocket.hrl"). | 
|  | 7 |  | 
|  | 8 | -export([new/0, new/1, new/2, setHandle_MUTABLE/2, open_MUTABLE/1, isOpen/1, write/2, read/2, close_MUTABLE/1, readAll/2]). | 
|  | 9 |  | 
|  | 10 | new(Host, Port) -> | 
|  | 11 | #tSocket{host=Host, port=Port, handle=nil}. % WATCH | 
|  | 12 |  | 
|  | 13 | new()     -> new("localhost", 9090). | 
|  | 14 | new(Host) -> new(Host, 9090). | 
|  | 15 |  | 
|  | 16 | setHandle_MUTABLE(This, Handle) -> | 
|  | 17 | This#tSocket{handle=Handle}. | 
|  | 18 |  | 
|  | 19 | open_MUTABLE(This) -> | 
|  | 20 | Host = This#tSocket.host, | 
|  | 21 | Port = This#tSocket.port, | 
|  | 22 | Options = [], | 
|  | 23 |  | 
|  | 24 | case gen_tcp:connect(Host, Port, Options) of | 
|  | 25 | {error, _} -> | 
|  | 26 | throw(tTransportException:new( | 
|  | 27 | ?tTransportException_NOT_OPEN, | 
|  | 28 | "Could not connect to " ++ Host ++ ":" ++ Port) | 
|  | 29 | ), | 
|  | 30 | {error, This}; % cpiro not reached? | 
|  | 31 | {ok, Socket} -> | 
|  | 32 | {ok, This#tSocket{handle=Socket}} | 
|  | 33 | end. | 
|  | 34 |  | 
|  | 35 | handle(This) -> | 
|  | 36 | This#tSocket.handle. | 
|  | 37 |  | 
|  | 38 | isOpen(This) -> | 
|  | 39 | handle(This) /= nil. | 
|  | 40 |  | 
|  | 41 | write(This, Str) -> | 
|  | 42 | Val = gen_tcp:send(handle(This), Str), | 
|  | 43 |  | 
|  | 44 | %% io:format("WRITE |~p|(~p)~n", [Str,Val]), | 
|  | 45 |  | 
|  | 46 | case Val of | 
|  | 47 | {error, _} -> | 
|  | 48 | throw(tTransportException:new(?tTransportException_NOT_OPEN, "in write")); | 
|  | 49 | ok -> | 
|  | 50 | ok | 
|  | 51 | end. | 
|  | 52 |  | 
|  | 53 | read(This, Sz) -> | 
|  | 54 | case gen_tcp:recv(handle(This), Sz) of | 
|  | 55 | {ok, []} -> | 
|  | 56 | { Host, Port } = { This#tSocket.host, This#tSocket.port }, | 
|  | 57 | throw(tTransportException:new(?tTransportException_UNKNOWN, "TSocket: Could not read " ++ Sz ++ "bytes from " ++ Host ++ ":" ++ Port)); | 
|  | 58 | {ok, Data} -> | 
|  | 59 | Data; | 
|  | 60 | {error, Error} -> | 
|  | 61 | io:format("in tSocket:read/2: gen_tcp:recv(~p, ~p) => {error, ~p}~n", | 
|  | 62 | [handle(This), Sz, Error]), | 
|  | 63 | throw(tTransportException:new(?tTransportException_NOT_OPEN, "in tSocket:read/2: gen_tcp:recv")) | 
|  | 64 | end. | 
|  | 65 |  | 
|  | 66 | close_MUTABLE(This) -> | 
|  | 67 | if | 
|  | 68 | This#tSocket.handle == nil -> | 
|  | 69 | This; | 
|  | 70 | true -> | 
|  | 71 | gen_tcp:close(handle(This)), | 
|  | 72 | This#tSocket{handle=nil} | 
|  | 73 | end. | 
|  | 74 |  | 
|  | 75 | readAll(This, Sz) -> | 
|  | 76 | readAll_loop(This, Sz, "", 0). | 
|  | 77 |  | 
|  | 78 | readAll_loop(This, Sz, Buff, Have) -> | 
|  | 79 | if | 
|  | 80 | Have < Sz -> | 
|  | 81 | Chunk = ?M1(This, read, Sz - Have), | 
|  | 82 |  | 
|  | 83 | %% man gen_tcp: | 
|  | 84 | %% exactly Length bytes are returned, or an error; | 
|  | 85 | %% possibly discarding less than Length bytes of data when | 
|  | 86 | %% the socket gets closed from the other side. | 
|  | 87 |  | 
|  | 88 | %% io:format("READ |~p|~n", [Chunk]), | 
|  | 89 |  | 
|  | 90 | Have1 = Have + (Sz-Have), % length(Chunk) | 
|  | 91 | Buff1 = Buff ++ Chunk, % TODO: ++ efficiency? | 
|  | 92 | readAll_loop(This, Sz, Buff1, Have1); | 
|  | 93 | true -> | 
|  | 94 | Buff | 
|  | 95 | end. | 
|  | 96 |  |