5252 | {timeout , timeout ()}
5353 | list
5454 | binary
55- | {binary , boolean ()}.
55+ | {binary , boolean ()}
56+ | {inet_backend , inet | socket }.
5657
5758-type listen_option () :: option ().
5859-type connect_option () :: option ().
5960-type packet () :: string () | binary ().
6061
61- -define ( DEFAULT_PARAMS , [{ active , true }, { buffer , 512 }, { timeout , infinity }] ).
62+ -include ( " inet-priv.hrl " ).
6263
6364% %-----------------------------------------------------------------------------
6465% % @param Address the address to which to connect
9192 Options :: [connect_option ()]
9293) ->
9394 {ok , Socket :: inet :socket ()} | {error , Reason :: reason ()}.
94- connect (Address , Port , Params0 ) ->
95- Socket = open_port ({spawn , " socket" }, []),
96- Params = merge (Params0 , ? DEFAULT_PARAMS ),
97- connect (Socket , normalize_address (Address ), Port , Params ).
95+ connect (Address , Port , Options ) ->
96+ Module = get_inet_backend_module (Options ),
97+ case Module :connect (Address , Port , Options ) of
98+ {ok , Socket } ->
99+ {ok , {? GEN_TCP_MONIKER , Socket , Module }};
100+ Other ->
101+ Other
102+ end .
98103
99104% %-----------------------------------------------------------------------------
100105% % @param Socket The Socket obtained via connect/3
@@ -107,13 +112,8 @@ connect(Address, Port, Params0) ->
107112% % @end
108113% %-----------------------------------------------------------------------------
109114-spec send (Socket :: inet :socket (), Packet :: packet ()) -> ok | {error , Reason :: reason ()}.
110- send (Socket , Packet ) ->
111- case call (Socket , {send , Packet }) of
112- {ok , _Len } ->
113- ok ;
114- Error ->
115- Error
116- end .
115+ send ({? GEN_TCP_MONIKER , Socket , Module }, Packet ) ->
116+ Module :send (Socket , Packet ).
117117
118118% %-----------------------------------------------------------------------------
119119% % @equiv recv(Socket, Length, infinity)
@@ -122,8 +122,8 @@ send(Socket, Packet) ->
122122% %-----------------------------------------------------------------------------
123123-spec recv (Socket :: inet :socket (), Length :: non_neg_integer ()) ->
124124 {ok , packet ()} | {error , Reason :: reason ()}.
125- recv (Socket , Length ) ->
126- recv (Socket , Length , infinity ).
125+ recv ({ ? GEN_TCP_MONIKER , Socket , Module } , Length ) ->
126+ Module : recv (Socket , Length ).
127127
128128% %-----------------------------------------------------------------------------
129129% % @param Socket the socket over which to receive a packet
@@ -146,8 +146,8 @@ recv(Socket, Length) ->
146146% %-----------------------------------------------------------------------------
147147-spec recv (Socket :: inet :socket (), Length :: non_neg_integer (), Timeout :: non_neg_integer ()) ->
148148 {ok , packet ()} | {error , Reason :: reason ()}.
149- recv (Socket , Length , Timeout ) ->
150- call (Socket , { recv , Length , Timeout } ).
149+ recv ({ ? GEN_TCP_MONIKER , Socket , Module } , Length , Timeout ) ->
150+ Module : recv (Socket , Length , Timeout ).
151151
152152% %-----------------------------------------------------------------------------
153153% % @param Port the port number on which to listen. Specify 0 to use an OS-assigned
@@ -161,24 +161,14 @@ recv(Socket, Length, Timeout) ->
161161% % @end
162162% %-----------------------------------------------------------------------------
163163-spec listen (Port :: inet :port_number (), Options :: [listen_option ()]) ->
164- {ok , ListeningSocket :: inet :socket ()} | {error , Reason :: reason ()}.
164+ {ok , Socket :: inet :socket ()} | {error , Reason :: reason ()}.
165165listen (Port , Options ) ->
166- Socket = open_port ({spawn , " socket" }, []),
167- Params = merge (Options , ? DEFAULT_PARAMS ),
168- InitParams = [
169- {proto , tcp },
170- {listen , true },
171- {controlling_process , self ()},
172- {port , Port },
173- {backlog , 5 }
174- | Params
175- ],
176- case call (Socket , {init , InitParams }) of
177- ok ->
178- {ok , Socket };
179- ErrorReason ->
180- % % TODO close port
181- ErrorReason
166+ Module = get_inet_backend_module (Options ),
167+ case Module :listen (Port , Options ) of
168+ {ok , Socket } ->
169+ {ok , {? GEN_TCP_MONIKER , Socket , Module }};
170+ Other ->
171+ Other
182172 end .
183173
184174% %-----------------------------------------------------------------------------
@@ -187,10 +177,15 @@ listen(Port, Options) ->
187177% % @doc Accept a connection on a listening socket.
188178% % @end
189179% %-----------------------------------------------------------------------------
190- -spec accept (ListenSocket :: inet :socket ()) ->
180+ -spec accept (Socket :: inet :socket ()) ->
191181 {ok , Socket :: inet :socket ()} | {error , Reason :: reason ()}.
192- accept (ListenSocket ) ->
193- accept (ListenSocket , infinity ).
182+ accept ({? GEN_TCP_MONIKER , Socket , Module }) ->
183+ case Module :accept (Socket , infinity ) of
184+ {ok , ConnectedSocket } ->
185+ {ok , {? GEN_TCP_MONIKER , ConnectedSocket , Module }};
186+ Error ->
187+ Error
188+ end .
194189
195190% %-----------------------------------------------------------------------------
196191% % @param ListenSocket the listening socket.
@@ -199,15 +194,14 @@ accept(ListenSocket) ->
199194% % @doc Accept a connection on a listening socket.
200195% % @end
201196% %-----------------------------------------------------------------------------
202- -spec accept (ListenSocket :: inet :socket (), Timeout :: timeout ()) ->
197+ -spec accept (Socket :: inet :socket (), Timeout :: timeout ()) ->
203198 {ok , Socket :: inet :socket ()} | {error , Reason :: reason ()}.
204- accept (ListenSocket , Timeout ) ->
205- case call (ListenSocket , {accept , Timeout }) of
206- {ok , Socket } when is_pid (Socket ) ->
207- {ok , Socket };
208- ErrorReason ->
209- % % TODO close port
210- ErrorReason
199+ accept ({? GEN_TCP_MONIKER , Socket , Module }, Timeout ) ->
200+ case Module :accept (Socket , Timeout ) of
201+ {ok , ConnectedSocket } ->
202+ {ok , {? GEN_TCP_MONIKER , ConnectedSocket , Module }};
203+ Error ->
204+ Error
211205 end .
212206
213207% %-----------------------------------------------------------------------------
@@ -217,8 +211,8 @@ accept(ListenSocket, Timeout) ->
217211% % @end
218212% %-----------------------------------------------------------------------------
219213-spec close (Socket :: inet :socket ()) -> ok .
220- close (Socket ) ->
221- inet :close (Socket ).
214+ close ({ ? GEN_TCP_MONIKER , Socket , Module } ) ->
215+ Module :close (Socket ).
222216
223217% %-----------------------------------------------------------------------------
224218% % @param Socket the socket to which to assign the pid
@@ -236,77 +230,20 @@ close(Socket) ->
236230% %-----------------------------------------------------------------------------
237231-spec controlling_process (Socket :: inet :socket (), Pid :: pid ()) ->
238232 ok | {error , Reason :: reason ()}.
239- controlling_process (Socket , Pid ) ->
240- call (Socket , {controlling_process , Pid }).
241-
242- % % internal operations
243-
244- % % @private
245- connect (DriverPid , Address , Port , Params ) ->
246- InitParams = [
247- {proto , tcp },
248- {connect , true },
249- {controlling_process , self ()},
250- {address , Address },
251- {port , Port }
252- | Params
253- ],
254- case call (DriverPid , {init , InitParams }) of
255- ok ->
256- {ok , DriverPid };
257- ErrorReason ->
258- % % TODO close port
259- ErrorReason
260- end .
261-
262- % % TODO implement this in lists
263-
264- % % @private
265- merge (Config , Defaults ) ->
266- merge (Config , Defaults , []) ++ Config .
267-
268- % % @private
269- merge (_Config , [], Accum ) ->
270- Accum ;
271- merge (Config , [H | T ], Accum ) ->
272- Key =
273- case H of
274- {K , _V } -> K ;
275- K -> K
276- end ,
277- case proplists :get_value (Key , Config ) of
278- undefined ->
279- merge (Config , T , [H | Accum ]);
280- Value ->
281- merge (Config , T , [{Key , Value } | Accum ])
282- end .
283-
284- % % @private
285- normalize_address (localhost ) ->
286- " 127.0.0.1" ;
287- normalize_address (loopback ) ->
288- " 127.0.0.1" ;
289- normalize_address (Address ) when is_list (Address ) ->
290- Address ;
291- normalize_address ({A , B , C , D }) when
292- is_integer (A ) and is_integer (B ) and is_integer (C ) and is_integer (D )
293- ->
294- integer_to_list (A ) ++
295- " ." ++
296- integer_to_list (B ) ++
297- " ." ++
298- integer_to_list (C ) ++
299- " ." ++ integer_to_list (D ).
300-
301- % % TODO IPv6
233+ controlling_process ({? GEN_TCP_MONIKER , Socket , Module }, Pid ) ->
234+ Module :controlling_process (Socket , Pid ).
302235
303236% %
304- % % Internal operations
237+ % % Internal implementation
305238% %
306239
307- call (Port , Msg ) ->
308- case port :call (Port , Msg ) of
309- {error , noproc } -> {error , closed };
310- out_of_memory -> {error , enomem };
311- Result -> Result
240+ % % @private
241+ get_inet_backend_module (Options ) ->
242+ case proplists :get_value (inet_backend , Options ) of
243+ undefined ->
244+ gen_tcp_inet ;
245+ inet ->
246+ gen_tcp_inet ;
247+ socket ->
248+ gen_tcp_socket
312249 end .
0 commit comments