Christopher Piro | 094823a | 2007-07-18 00:26:12 +0000 | [diff] [blame] | 1 | %%% Copyright (c) 2007- Facebook |
| 2 | %%% Distributed under the Thrift Software License |
Christopher Piro | 3121c82 | 2007-11-15 06:26:26 +0000 | [diff] [blame] | 3 | %%% |
Christopher Piro | 094823a | 2007-07-18 00:26:12 +0000 | [diff] [blame] | 4 | %%% 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 Piro | 094823a | 2007-07-18 00:26:12 +0000 | [diff] [blame] | 13 | -include("transport/tSocket.hrl"). |
| 14 | |
| 15 | -behavior(oop). |
| 16 | |
Christopher Piro | c3c6c0c | 2007-08-01 23:42:12 +0000 | [diff] [blame] | 17 | -export([attr/4, super/0, inspect/1]). |
Christopher Piro | 094823a | 2007-07-18 00:26:12 +0000 | [diff] [blame] | 18 | |
Christopher Piro | 6894029 | 2007-10-02 00:35:12 +0000 | [diff] [blame] | 19 | -export([new/0, new/1, new/2, |
Christopher Piro | 3121c82 | 2007-11-15 06:26:26 +0000 | [diff] [blame] | 20 | effectful_setHandle/2, effectful_open/1, |
| 21 | isOpen/1, effectful_write/2, read/2, effectful_close/1]). |
Christopher Piro | 094823a | 2007-07-18 00:26:12 +0000 | [diff] [blame] | 22 | |
| 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 Piro | 3121c82 | 2007-11-15 06:26:26 +0000 | [diff] [blame] | 32 | |
Christopher Piro | 094823a | 2007-07-18 00:26:12 +0000 | [diff] [blame] | 33 | %%% |
| 34 | %%% behavior callbacks |
| 35 | %%% |
Christopher Piro | 3121c82 | 2007-11-15 06:26:26 +0000 | [diff] [blame] | 36 | |
Christopher Piro | 094823a | 2007-07-18 00:26:12 +0000 | [diff] [blame] | 37 | %%% super() -> SuperModule = atom() |
| 38 | %%% | none |
| 39 | |
| 40 | super() -> |
| 41 | tTransport. |
| 42 | |
| 43 | %%% inspect(This) -> string() |
| 44 | |
| 45 | inspect(This) -> |
| 46 | ?FORMAT_ATTR(host) ++ ", " ++ |
| 47 | ?FORMAT_ATTR(port) ++ ", " ++ |
| 48 | ?FORMAT_ATTR(handle). |
| 49 | |
| 50 | %%% |
| 51 | %%% class methods |
| 52 | %%% |
| 53 | |
| 54 | new(Host, Port) -> |
| 55 | Super = (super()):new(), |
| 56 | #?MODULE{super=Super, host=Host, port=Port, handle=nil}. |
| 57 | |
| 58 | new(Host) -> |
| 59 | new(Host, 9090). |
| 60 | |
| 61 | new() -> |
| 62 | new("localhost", 9090). |
Christopher Piro | 3121c82 | 2007-11-15 06:26:26 +0000 | [diff] [blame] | 63 | |
Christopher Piro | 094823a | 2007-07-18 00:26:12 +0000 | [diff] [blame] | 64 | %%% |
| 65 | %%% instance methods |
| 66 | %%% |
| 67 | |
| 68 | effectful_setHandle(This, Handle) -> |
| 69 | {ok, oop:set(This, handle, Handle)}. |
| 70 | |
Christopher Piro | 3121c82 | 2007-11-15 06:26:26 +0000 | [diff] [blame] | 71 | effectful_open(This) -> |
Christopher Piro | 094823a | 2007-07-18 00:26:12 +0000 | [diff] [blame] | 72 | Host = oop:get(This, host), |
| 73 | Port = oop:get(This, port), |
eletuchy | 698713c | 2008-02-26 11:44:00 +0000 | [diff] [blame] | 74 | 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 |
eletuchy | f0cf2a3 | 2008-02-27 19:27:41 +0000 | [diff] [blame] | 79 | {ok, Millis} when is_integer(Millis), Millis > 0 -> Millis; |
eletuchy | 698713c | 2008-02-26 11:44:00 +0000 | [diff] [blame] | 80 | _Else -> 5000 |
| 81 | end} |
| 82 | ], |
Christopher Piro | 094823a | 2007-07-18 00:26:12 +0000 | [diff] [blame] | 83 | case gen_tcp:connect(Host, Port, Options) of |
Christopher Piro | 3121c82 | 2007-11-15 06:26:26 +0000 | [diff] [blame] | 84 | {error, _} -> |
Christopher Piro | de11d85 | 2007-11-18 02:10:20 +0000 | [diff] [blame] | 85 | tException:throw(tTransportException, |
eletuchy | bd03e3e | 2008-02-13 00:48:15 +0000 | [diff] [blame] | 86 | [?tTransportException_NOT_OPEN, "Could not connect to " ++ Host ++ ":" |
| 87 | ++ integer_to_list(Port)]); |
Christopher Piro | 3121c82 | 2007-11-15 06:26:26 +0000 | [diff] [blame] | 88 | {ok, Socket} -> |
| 89 | effectful_setHandle(This, Socket) |
Christopher Piro | 094823a | 2007-07-18 00:26:12 +0000 | [diff] [blame] | 90 | end. |
| 91 | |
| 92 | isOpen(This) -> |
| 93 | oop:get(This, handle) /= nil. |
| 94 | |
Christopher Piro | aa93451 | 2008-01-30 01:39:01 +0000 | [diff] [blame] | 95 | effectful_write(This, Data) -> |
Christopher Piro | 094823a | 2007-07-18 00:26:12 +0000 | [diff] [blame] | 96 | Handle = oop:get(This, handle), |
Christopher Piro | 094823a | 2007-07-18 00:26:12 +0000 | [diff] [blame] | 97 | |
Christopher Piro | aa93451 | 2008-01-30 01:39:01 +0000 | [diff] [blame] | 98 | case gen_tcp:send(Handle, Data) of |
eletuchy | 698713c | 2008-02-26 11:44:00 +0000 | [diff] [blame] | 99 | {error,timeout} -> |
| 100 | effectful_close(This), |
| 101 | tException:throw(tTransportException, [?tTransportException_NOT_OPEN, "in write"]); |
Christopher Piro | 3121c82 | 2007-11-15 06:26:26 +0000 | [diff] [blame] | 102 | {error, _} -> |
eletuchy | 698713c | 2008-02-26 11:44:00 +0000 | [diff] [blame] | 103 | effectful_close(This), |
Christopher Piro | de11d85 | 2007-11-18 02:10:20 +0000 | [diff] [blame] | 104 | tException:throw(tTransportException, [?tTransportException_NOT_OPEN, "in write"]); |
Christopher Piro | 3121c82 | 2007-11-15 06:26:26 +0000 | [diff] [blame] | 105 | ok -> |
| 106 | {ok, This} |
Christopher Piro | 094823a | 2007-07-18 00:26:12 +0000 | [diff] [blame] | 107 | end. |
| 108 | |
| 109 | read(This, Sz) -> |
| 110 | Handle = oop:get(This, handle), |
| 111 | case gen_tcp:recv(Handle, Sz) of |
Christopher Piro | 3121c82 | 2007-11-15 06:26:26 +0000 | [diff] [blame] | 112 | {ok, []} -> |
| 113 | Host = oop:get(This, host), |
| 114 | Port = oop:get(This, port), |
eletuchy | 38d199b | 2008-02-27 19:55:15 +0000 | [diff] [blame] | 115 | tException:throw(tTransportException, |
| 116 | [?tTransportException_UNKNOWN, |
| 117 | "TSocket: Could not read " ++ integer_to_list(Sz) ++ |
| 118 | "bytes from " ++ Host ++ ":" ++ integer_to_list(Port)]); |
Christopher Piro | 3121c82 | 2007-11-15 06:26:26 +0000 | [diff] [blame] | 119 | {ok, Data} -> |
| 120 | %% DEBUG |
| 121 | ?INFO("tSocket: read ~p", [Data]), |
| 122 | Data; |
| 123 | {error, Error} -> |
Christopher Piro | de11d85 | 2007-11-18 02:10:20 +0000 | [diff] [blame] | 124 | tException:throw(tTransportException, [?tTransportException_NOT_OPEN, "in tSocket:read/2: gen_tcp:recv"]) |
Christopher Piro | 3121c82 | 2007-11-15 06:26:26 +0000 | [diff] [blame] | 125 | end. |
| 126 | |
Christopher Piro | 094823a | 2007-07-18 00:26:12 +0000 | [diff] [blame] | 127 | effectful_close(This) -> |
| 128 | case oop:get(This, handle) of |
Christopher Piro | 3121c82 | 2007-11-15 06:26:26 +0000 | [diff] [blame] | 129 | nil -> |
| 130 | {ok, This}; |
| 131 | Handle -> |
| 132 | gen_tcp:close(Handle), |
| 133 | {ok, oop:set(This, handle, nil)} |
Christopher Piro | 094823a | 2007-07-18 00:26:12 +0000 | [diff] [blame] | 134 | end. |