David Reiss | ea2cba8 | 2009-03-30 21:35:00 +0000 | [diff] [blame] | 1 | %% |
| 2 | %% Licensed to the Apache Software Foundation (ASF) under one |
| 3 | %% or more contributor license agreements. See the NOTICE file |
| 4 | %% distributed with this work for additional information |
| 5 | %% regarding copyright ownership. The ASF licenses this file |
| 6 | %% to you under the Apache License, Version 2.0 (the |
| 7 | %% "License"); you may not use this file except in compliance |
| 8 | %% with the License. You may obtain a copy of the License at |
| 9 | %% |
| 10 | %% http://www.apache.org/licenses/LICENSE-2.0 |
| 11 | %% |
| 12 | %% Unless required by applicable law or agreed to in writing, |
| 13 | %% software distributed under the License is distributed on an |
| 14 | %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| 15 | %% KIND, either express or implied. See the License for the |
| 16 | %% specific language governing permissions and limitations |
| 17 | %% under the License. |
| 18 | %% |
| 19 | |
David Reiss | ac54955 | 2008-06-10 22:56:59 +0000 | [diff] [blame] | 20 | -module(thrift_transport). |
| 21 | |
David Reiss | 3b9c342 | 2008-06-11 00:59:19 +0000 | [diff] [blame] | 22 | -export([behaviour_info/1]). |
alisdair sullivan | a559f8d | 2014-11-17 20:28:35 -0800 | [diff] [blame] | 23 | %% constructors |
| 24 | -export([new/1, new/2]). |
| 25 | %% transport callbacks |
| 26 | -export([read/2, read_exact/2, write/2, flush/1, close/1]). |
David Reiss | ac54955 | 2008-06-10 22:56:59 +0000 | [diff] [blame] | 27 | |
alisdair sullivan | a559f8d | 2014-11-17 20:28:35 -0800 | [diff] [blame] | 28 | -export_type([t_transport/0]). |
| 29 | |
David Reiss | ac54955 | 2008-06-10 22:56:59 +0000 | [diff] [blame] | 30 | |
| 31 | behaviour_info(callbacks) -> |
alisdair sullivan | a559f8d | 2014-11-17 20:28:35 -0800 | [diff] [blame] | 32 | [{read, 2}, {write, 2}, {flush, 1}, {close, 1}]. |
David Reiss | ac54955 | 2008-06-10 22:56:59 +0000 | [diff] [blame] | 33 | |
alisdair sullivan | a559f8d | 2014-11-17 20:28:35 -0800 | [diff] [blame] | 34 | |
| 35 | -record(t_transport, { |
| 36 | module, |
| 37 | state |
| 38 | }). |
| 39 | |
| 40 | -type state() :: #t_transport{}. |
| 41 | -type t_transport() :: #t_transport{}. |
| 42 | |
David Reiss | ac54955 | 2008-06-10 22:56:59 +0000 | [diff] [blame] | 43 | |
David Reiss | 9b170eb | 2010-08-30 22:05:44 +0000 | [diff] [blame] | 44 | -ifdef(transport_wrapper_module). |
| 45 | -define(debug_wrap(Transport), |
alisdair sullivan | a559f8d | 2014-11-17 20:28:35 -0800 | [diff] [blame] | 46 | case Transport#t_transport.module of |
| 47 | ?transport_wrapper_module -> Transport; |
| 48 | _Else -> |
| 49 | {ok, Result} = ?transport_wrapper_module:new(Transport), |
| 50 | Result |
| 51 | end |
| 52 | ). |
David Reiss | 9b170eb | 2010-08-30 22:05:44 +0000 | [diff] [blame] | 53 | -else. |
| 54 | -define(debug_wrap(Transport), Transport). |
| 55 | -endif. |
| 56 | |
Bryan Duxbury | d3879f8 | 2010-08-19 05:06:02 +0000 | [diff] [blame] | 57 | |
alisdair sullivan | a559f8d | 2014-11-17 20:28:35 -0800 | [diff] [blame] | 58 | -type wrappable() :: |
| 59 | binary() | |
| 60 | list() | |
| 61 | {membuffer, binary() | list()} | |
| 62 | {tcp, port()} | |
| 63 | {tcp, port(), list()} | |
| 64 | {file, file:io_device()} | |
| 65 | {file, file:io_device(), list()} | |
| 66 | {file, file:filename()} | |
| 67 | {file, file:filename(), list()}. |
David Reiss | ac54955 | 2008-06-10 22:56:59 +0000 | [diff] [blame] | 68 | |
alisdair sullivan | a559f8d | 2014-11-17 20:28:35 -0800 | [diff] [blame] | 69 | -spec new(wrappable()) -> {ok, #t_transport{}}. |
David Reiss | 90b4083 | 2008-06-10 22:58:52 +0000 | [diff] [blame] | 70 | |
alisdair sullivan | a559f8d | 2014-11-17 20:28:35 -0800 | [diff] [blame] | 71 | new({membuffer, Membuffer}) when is_binary(Membuffer); is_list(Membuffer) -> |
| 72 | thrift_membuffer_transport:new(Membuffer); |
| 73 | new({membuffer, Membuffer, []}) when is_binary(Membuffer); is_list(Membuffer) -> |
| 74 | thrift_membuffer_transport:new(Membuffer); |
| 75 | new({tcp, Socket}) when is_port(Socket) -> |
| 76 | new({tcp, Socket, []}); |
| 77 | new({tcp, Socket, Opts}) when is_port(Socket) -> |
| 78 | thrift_socket_transport:new(Socket, Opts); |
| 79 | new({file, Filename}) when is_list(Filename); is_binary(Filename) -> |
| 80 | new({file, Filename, []}); |
| 81 | new({file, Filename, Opts}) when is_list(Filename); is_binary(Filename) -> |
| 82 | {ok, File} = file:open(Filename, [raw, binary]), |
| 83 | new({file, File, Opts}); |
| 84 | new({file, File, Opts}) -> |
| 85 | thrift_file_transport:new(File, Opts). |
David Reiss | c11734e | 2008-06-11 00:59:48 +0000 | [diff] [blame] | 86 | |
alisdair sullivan | a559f8d | 2014-11-17 20:28:35 -0800 | [diff] [blame] | 87 | -spec new(Module::module(), State::any()) -> {ok, #t_transport{}}. |
| 88 | |
| 89 | new(Module, State) when is_atom(Module) -> |
| 90 | {ok, ?debug_wrap(#t_transport{module = Module, state = State})}. |
| 91 | |
| 92 | |
| 93 | -include("thrift_transport_behaviour.hrl"). |
| 94 | |
| 95 | |
| 96 | read(Transport = #t_transport{module = Module}, Len) |
| 97 | when is_integer(Len), Len >= 0 -> |
| 98 | {NewState, Result} = Module:read(Transport#t_transport.state, Len), |
| 99 | {Transport#t_transport{state = NewState}, Result}. |
| 100 | |
| 101 | |
| 102 | read_exact(Transport = #t_transport{module = Module}, Len) |
| 103 | when is_integer(Len), Len >= 0 -> |
Nobuaki Sukegawa | 97a4898 | 2015-11-14 18:49:45 +0900 | [diff] [blame] | 104 | case lists:keyfind(read_exact, 1, Module:module_info(exports)) of |
| 105 | {read_exact, 2} -> |
Nobuaki Sukegawa | 97a4898 | 2015-11-14 18:49:45 +0900 | [diff] [blame] | 106 | {NewState, Result} = Module:read_exact(Transport#t_transport.state, Len), |
| 107 | {Transport#t_transport{state = NewState}, Result}; |
| 108 | _ -> |
Nobuaki Sukegawa | 97a4898 | 2015-11-14 18:49:45 +0900 | [diff] [blame] | 109 | read(Transport, Len) |
Nobuaki Sukegawa | 149ecc1 | 2015-10-31 12:17:31 +0900 | [diff] [blame] | 110 | end. |
alisdair sullivan | a559f8d | 2014-11-17 20:28:35 -0800 | [diff] [blame] | 111 | |
| 112 | |
| 113 | write(Transport = #t_transport{module = Module}, Data) -> |
| 114 | {NewState, Result} = Module:write(Transport#t_transport.state, Data), |
| 115 | {Transport#t_transport{state = NewState}, Result}. |
| 116 | |
| 117 | |
| 118 | flush(Transport = #t_transport{module = Module}) -> |
| 119 | {NewState, Result} = Module:flush(Transport#t_transport.state), |
| 120 | {Transport#t_transport{state = NewState}, Result}. |
| 121 | |
| 122 | |
| 123 | close(Transport = #t_transport{module = Module}) -> |
| 124 | {NewState, Result} = Module:close(Transport#t_transport.state), |
| 125 | {Transport#t_transport{state = NewState}, Result}. |
| 126 | |