-
Notifications
You must be signed in to change notification settings - Fork 13
/
socket.ex
131 lines (104 loc) · 3.58 KB
/
socket.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
defmodule Kayrock.Socket do
@moduledoc """
This module handle all socket related operations.
NOTE this is a copy of KafkaEx.Socket:
https://github.com/kafkaex/kafka_ex/blob/master/lib/kafka_ex/socket.ex
It is duplicated here to avoid creating a circular dependency.
"""
defstruct socket: nil, ssl: false
@type t :: %Kayrock.Socket{
socket: :gen_tcp.socket() | :ssl.sslsocket(),
ssl: boolean
}
@doc """
Creates a socket.
For more information about the available options, see `:ssl.connect/3` for ssl
or `:gen_tcp.connect/3` for non ssl.
"""
@spec create(:inet.ip_address(), non_neg_integer, [] | [...]) ::
{:ok, Kayrock.Socket.t()} | {:error, any}
def create(host, port, socket_options \\ [], is_ssl \\ false) do
case create_socket(host, port, is_ssl, socket_options) do
{:ok, socket} -> {:ok, %Kayrock.Socket{socket: socket, ssl: is_ssl}}
{:error, reason} -> {:error, reason}
end
end
@doc """
Closes the socket.
For more information, see `:ssl.close/1` for ssl or `:gen_tcp.send/1` for non ssl.
"""
@spec close(Kayrock.Socket.t()) :: :ok
def close(%Kayrock.Socket{ssl: true} = socket), do: :ssl.close(socket.socket)
def close(socket), do: :gen_tcp.close(socket.socket)
@doc """
Sends data over the socket.
It handles both, SSL and non SSL sockets.
For more information, see `:ssl.send/2` for ssl or `:gen_tcp.send/2` for non ssl.
"""
@spec send(Kayrock.Socket.t(), iodata) :: :ok | {:error, any}
def send(%Kayrock.Socket{ssl: true} = socket, data) do
:ssl.send(socket.socket, data)
end
def send(socket, data) do
:gen_tcp.send(socket.socket, data)
end
@doc """
Set options to the socket.
For more information, see `:ssl.setopts/2` for ssl or `:inet.setopts/2` for non ssl.
"""
@spec setopts(Kayrock.Socket.t(), list) :: :ok | {:error, any}
def setopts(%Kayrock.Socket{ssl: true} = socket, options) do
:ssl.setopts(socket.socket, options)
end
def setopts(socket, options) do
:inet.setopts(socket.socket, options)
end
@doc """
Receives data from the socket.
For more information, see `:ssl.recv/2` for ssl or `:gen_tcp.recv/2` for non ssl.
"""
@spec recv(Kayrock.Socket.t(), non_neg_integer) ::
{:ok, String.t() | binary | term} | {:error, any}
def recv(%Kayrock.Socket{ssl: true} = socket, length) do
:ssl.recv(socket.socket, length)
end
def recv(socket, length) do
:gen_tcp.recv(socket.socket, length)
end
@spec recv(Kayrock.Socket.t(), non_neg_integer, timeout) ::
{:ok, String.t() | binary | term} | {:error, any}
def recv(%Kayrock.Socket{ssl: true} = socket, length, timeout) do
:ssl.recv(socket.socket, length, timeout)
end
def recv(socket, length, timeout) do
:gen_tcp.recv(socket.socket, length, timeout)
end
@doc """
Returns true if the socket is open
"""
@spec open?(Kayrock.Socket.t()) :: boolean
def open?(%Kayrock.Socket{} = socket) do
info(socket) != nil
end
@doc """
Returns the information about the socket.
For more information, see `Port.info`
"""
@spec info(Kayrock.Socket.t()) :: list | nil
def info(socket) do
socket
|> extract_port
|> Port.info()
end
defp extract_port(%Kayrock.Socket{ssl: true} = socket) do
{:sslsocket, {:gen_tcp, port, _, _}, _} = socket.socket
port
end
defp extract_port(socket), do: socket.socket
defp create_socket(host, port, true, socket_options) do
:ssl.connect(host, port, socket_options)
end
defp create_socket(host, port, false, socket_options) do
:gen_tcp.connect(host, port, socket_options)
end
end