blob: f23cdee9785b3597a1ebb530989c808a8a249d74 [file] [log] [blame]
%%% Copyright (c) 2007- Facebook
%%% Distributed under the Thrift Software License
%%%
%%% See accompanying file LICENSE or visit the Thrift site at:
%%% http://developers.facebook.com/thrift/
-module(tSocket).
-include("oop.hrl").
-include("thrift.hrl").
-include("transport/tTransportException.hrl").
-include("transport/tSocket.hrl").
-behavior(oop).
-export([attr/4, super/0, inspect/1]).
-export([new/0, new/1, new/2,
effectful_setHandle/2, effectful_open/1,
isOpen/1, effectful_write/2, read/2, effectful_close/1]).
%%%
%%% define attributes
%%% 'super' is required unless ?MODULE is a base class
%%%
?DEFINE_ATTR(super);
?DEFINE_ATTR(host);
?DEFINE_ATTR(port);
?DEFINE_ATTR(handle).
%%%
%%% behavior callbacks
%%%
%%% super() -> SuperModule = atom()
%%% | none
super() ->
tTransport.
%%% inspect(This) -> string()
inspect(This) ->
?FORMAT_ATTR(host) ++ ", " ++
?FORMAT_ATTR(port) ++ ", " ++
?FORMAT_ATTR(handle).
%%%
%%% class methods
%%%
new(Host, Port) ->
Super = (super()):new(),
#?MODULE{super=Super, host=Host, port=Port, handle=nil}.
new(Host) ->
new(Host, 9090).
new() ->
new("localhost", 9090).
%%%
%%% instance methods
%%%
effectful_setHandle(This, Handle) ->
{ok, oop:set(This, handle, Handle)}.
effectful_open(This) ->
Host = oop:get(This, host),
Port = oop:get(This, port),
Options = [binary, {packet, 0}, {active, false}, {reuseaddr, true},
{nodelay, true}],
case gen_tcp:connect(Host, Port, Options) of
{error, _} ->
tException:throw(tTransportException,
[?tTransportException_NOT_OPEN, "Could not connect to " ++ Host ++ ":" ++ Port]);
{ok, Socket} ->
effectful_setHandle(This, Socket)
end.
isOpen(This) ->
oop:get(This, handle) /= nil.
effectful_write(This, Data) ->
Handle = oop:get(This, handle),
case gen_tcp:send(Handle, Data) of
{error, _} ->
tException:throw(tTransportException, [?tTransportException_NOT_OPEN, "in write"]);
ok ->
{ok, This}
end.
read(This, Sz) ->
Handle = oop:get(This, handle),
case gen_tcp:recv(Handle, Sz) of
{ok, []} ->
Host = oop:get(This, host),
Port = oop:get(This, port),
tException:throw(tTransportException, [?tTransportException_UNKNOWN, "TSocket: Could not read " ++ Sz ++ "bytes from " ++ Host ++ ":" ++ Port]);
{ok, Data} ->
%% DEBUG
?INFO("tSocket: read ~p", [Data]),
Data;
{error, Error} ->
tException:throw(tTransportException, [?tTransportException_NOT_OPEN, "in tSocket:read/2: gen_tcp:recv"])
end.
effectful_close(This) ->
case oop:get(This, handle) of
nil ->
{ok, This};
Handle ->
gen_tcp:close(Handle),
{ok, oop:set(This, handle, nil)}
end.