blob: 842fba388eee845089612e90c8361fada5263b10 [file] [log] [blame]
Christopher Piro094823a2007-07-18 00:26:12 +00001%%% Copyright (c) 2007- Facebook
2%%% Distributed under the Thrift Software License
Christopher Piro3121c822007-11-15 06:26:26 +00003%%%
Christopher Piro094823a2007-07-18 00:26:12 +00004%%% See accompanying file LICENSE or visit the Thrift site at:
5%%% http://developers.facebook.com/thrift/
6
7-module(tSocket).
8
9-include("oop.hrl").
10
11-include("thrift.hrl").
12-include("transport/tTransportException.hrl").
Christopher Piro094823a2007-07-18 00:26:12 +000013-include("transport/tSocket.hrl").
14
15-behavior(oop).
16
Christopher Piroc3c6c0c2007-08-01 23:42:12 +000017-export([attr/4, super/0, inspect/1]).
Christopher Piro094823a2007-07-18 00:26:12 +000018
Christopher Piro68940292007-10-02 00:35:12 +000019-export([new/0, new/1, new/2,
Christopher Piro3121c822007-11-15 06:26:26 +000020 effectful_setHandle/2, effectful_open/1,
21 isOpen/1, effectful_write/2, read/2, effectful_close/1]).
Christopher Piro094823a2007-07-18 00:26:12 +000022
23%%%
24%%% define attributes
25%%% 'super' is required unless ?MODULE is a base class
26%%%
27
28?DEFINE_ATTR(super);
29?DEFINE_ATTR(host);
30?DEFINE_ATTR(port);
31?DEFINE_ATTR(handle).
Christopher Piro3121c822007-11-15 06:26:26 +000032
Christopher Piro094823a2007-07-18 00:26:12 +000033%%%
34%%% behavior callbacks
35%%%
Christopher Piro3121c822007-11-15 06:26:26 +000036
Christopher Piro094823a2007-07-18 00:26:12 +000037%%% super() -> SuperModule = atom()
38%%% | none
39
40super() ->
41 tTransport.
42
43%%% inspect(This) -> string()
44
45inspect(This) ->
46 ?FORMAT_ATTR(host) ++ ", " ++
47 ?FORMAT_ATTR(port) ++ ", " ++
48 ?FORMAT_ATTR(handle).
49
50%%%
51%%% class methods
52%%%
53
54new(Host, Port) ->
55 Super = (super()):new(),
56 #?MODULE{super=Super, host=Host, port=Port, handle=nil}.
57
58new(Host) ->
59 new(Host, 9090).
60
61new() ->
62 new("localhost", 9090).
Christopher Piro3121c822007-11-15 06:26:26 +000063
Christopher Piro094823a2007-07-18 00:26:12 +000064%%%
65%%% instance methods
66%%%
67
68effectful_setHandle(This, Handle) ->
69 {ok, oop:set(This, handle, Handle)}.
70
Christopher Piro3121c822007-11-15 06:26:26 +000071effectful_open(This) ->
Christopher Piro094823a2007-07-18 00:26:12 +000072 Host = oop:get(This, host),
73 Port = oop:get(This, port),
eletuchy698713c2008-02-26 11:44:00 +000074 Options = [binary, {packet, 0},
75 {active, false},
76 {reuseaddr, true},
77 {nodelay, true},
78 {send_timeout, case application:get_env(thrift, socket_send_timeout) of
eletuchyf0cf2a32008-02-27 19:27:41 +000079 {ok, Millis} when is_integer(Millis), Millis > 0 -> Millis;
eletuchy698713c2008-02-26 11:44:00 +000080 _Else -> 5000
81 end}
82 ],
Christopher Piro094823a2007-07-18 00:26:12 +000083 case gen_tcp:connect(Host, Port, Options) of
Christopher Piro3121c822007-11-15 06:26:26 +000084 {error, _} ->
Christopher Pirode11d852007-11-18 02:10:20 +000085 tException:throw(tTransportException,
eletuchybd03e3e2008-02-13 00:48:15 +000086 [?tTransportException_NOT_OPEN, "Could not connect to " ++ Host ++ ":"
87 ++ integer_to_list(Port)]);
Christopher Piro3121c822007-11-15 06:26:26 +000088 {ok, Socket} ->
89 effectful_setHandle(This, Socket)
Christopher Piro094823a2007-07-18 00:26:12 +000090 end.
91
92isOpen(This) ->
93 oop:get(This, handle) /= nil.
94
Christopher Piroaa934512008-01-30 01:39:01 +000095effectful_write(This, Data) ->
Christopher Piro094823a2007-07-18 00:26:12 +000096 Handle = oop:get(This, handle),
Christopher Piro094823a2007-07-18 00:26:12 +000097
Christopher Piroaa934512008-01-30 01:39:01 +000098 case gen_tcp:send(Handle, Data) of
eletuchy698713c2008-02-26 11:44:00 +000099 {error,timeout} ->
100 effectful_close(This),
101 tException:throw(tTransportException, [?tTransportException_NOT_OPEN, "in write"]);
Christopher Piro3121c822007-11-15 06:26:26 +0000102 {error, _} ->
eletuchy698713c2008-02-26 11:44:00 +0000103 effectful_close(This),
Christopher Pirode11d852007-11-18 02:10:20 +0000104 tException:throw(tTransportException, [?tTransportException_NOT_OPEN, "in write"]);
Christopher Piro3121c822007-11-15 06:26:26 +0000105 ok ->
106 {ok, This}
Christopher Piro094823a2007-07-18 00:26:12 +0000107 end.
108
109read(This, Sz) ->
110 Handle = oop:get(This, handle),
111 case gen_tcp:recv(Handle, Sz) of
Christopher Piro3121c822007-11-15 06:26:26 +0000112 {ok, []} ->
113 Host = oop:get(This, host),
114 Port = oop:get(This, port),
eletuchy38d199b2008-02-27 19:55:15 +0000115 tException:throw(tTransportException,
116 [?tTransportException_UNKNOWN,
117 "TSocket: Could not read " ++ integer_to_list(Sz) ++
118 "bytes from " ++ Host ++ ":" ++ integer_to_list(Port)]);
Christopher Piro3121c822007-11-15 06:26:26 +0000119 {ok, Data} ->
120 %% DEBUG
121 ?INFO("tSocket: read ~p", [Data]),
122 Data;
123 {error, Error} ->
Christopher Pirode11d852007-11-18 02:10:20 +0000124 tException:throw(tTransportException, [?tTransportException_NOT_OPEN, "in tSocket:read/2: gen_tcp:recv"])
Christopher Piro3121c822007-11-15 06:26:26 +0000125 end.
126
Christopher Piro094823a2007-07-18 00:26:12 +0000127effectful_close(This) ->
128 case oop:get(This, handle) of
Christopher Piro3121c822007-11-15 06:26:26 +0000129 nil ->
130 {ok, This};
131 Handle ->
132 gen_tcp:close(Handle),
133 {ok, oop:set(This, handle, nil)}
Christopher Piro094823a2007-07-18 00:26:12 +0000134 end.