unix_socks 0.2.3 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 215ee14acc29cc75bc5bd6005d4b73afbc6612c0147e28362ccad7fb4d72694d
4
- data.tar.gz: '05698df412aab41c8b546c96576d9d99ec5ede18e968166ba8d710f909e47927'
3
+ metadata.gz: d67e7734f17aa0c0215570741c0d28c24a977e4d5468e35b35b8b51fda5ce3ce
4
+ data.tar.gz: 2aec1808e4c26b8b3948d9aa7d51ed25a641cd72aca74cf4dc611e5a951cf95a
5
5
  SHA512:
6
- metadata.gz: 7ab4adacdbe6eed5c3c9e8f8df41cf10589901c77e8f7d7f8a29866ddb826f22825a76a07884a2739b088f0aac9449cd2ad32f5c0bb6ceb0ef4ebaa1526b071e
7
- data.tar.gz: f5141f414e1962c7cf6d8881ccadad9003daff74da2b21a74fa18a24bab16e03ea3a8ae29e511596acc8bebd44503ede98238b218e1caa48f0462e65a1c79c11
6
+ metadata.gz: 41f9a5ca91d3f57866b204174f1c95c91c56345a040d3cd59513144081a6cfe39124a3dc0e42646b3d9983eff59c139c7d5ec29a89c708b70f6aa688225420f0
7
+ data.tar.gz: 198eccdfe7d548b9c0bbd161afde90e2aa526bdb7540c804998f804177aa212da37429cd1979de56a47ba1e5df178f7e5b79bcf1010048b91965472129cc7519
data/CHANGES.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # Changes
2
2
 
3
+ ## 2025-12-24 v0.3.0
4
+
5
+ - Refactored socket server architecture by splitting `UnixSocks::Server` into
6
+ `UnixSocks::DomainSocketServer` and `UnixSocks::TCPSocketServer`
7
+ - Added `UnixSocks::ServerShared` module to encapsulate common functionality
8
+ shared between socket server implementations
9
+ - Implemented `to_url` method for both server types to generate `unix://path`
10
+ and `tcp://host:port` URLs
11
+ - Introduced `UnixSocks::ServerError` marker module for consistent error
12
+ handling across the library
13
+ - Updated all documentation and tests to reflect the new dual socket server
14
+ architecture
15
+ - Maintained backward compatibility for core communication patterns
16
+ - Added comprehensive test coverage for both `UnixSocks::DomainSocketServer`
17
+ and `UnixSocks::TCPSocketServer` implementations
18
+ - Added `.rspec` file to configure RSpec with detailed output format (`--format
19
+ d`) for improved test output readability
20
+
3
21
  ## 2025-12-23 v0.2.3
4
22
 
5
23
  - Handle `Errno::ENOENT` errors in the background socket server thread to
@@ -7,7 +25,7 @@
7
25
  - Add test case to verify background thread execution and `ENOENT` error
8
26
  handling
9
27
  - Maintain existing `at_exit` cleanup behavior to ensure socket file removal
10
- - Update `UnixSocks::Server` to be more resilient to temporary file system
28
+ - Update `UnixSocks::DomainSocketServer` to be more resilient to temporary file system
11
29
  conditions
12
30
  - Update `gem_hadar` development dependency to version **2.16.0**
13
31
 
@@ -47,7 +65,7 @@
47
65
 
48
66
  ## 2025-09-07 v0.1.0
49
67
 
50
- - Introduced `UnixSocks::Server.default_runtime_dir` class method
68
+ - Introduced `UnixSocks::DomainSocketServer.default_runtime_dir` class method
51
69
  - Simplified coverage configuration by using `GemHadar::SimpleCov.start`
52
70
 
53
71
  ## 2025-07-13 v0.0.1
data/README.md CHANGED
@@ -2,14 +2,22 @@
2
2
 
3
3
  ## Description
4
4
 
5
- A Ruby library for handling Unix socket-based communication.
5
+ A Ruby library for handling inter-process communication via Unix sockets and
6
+ TCP sockets.
6
7
 
7
8
  ## Features
8
9
 
9
- - **Message Handling**: Simplify sending and receiving messages over Unix sockets.
10
- - **Dynamic Method Access**: Access message body values using method names (e.g., `message.key`).
11
- - **Background Processing**: Run the server in a background thread to avoid blocking main execution.
12
- - **Robust Error Handling**: Gracefully handle socket disconnections and JSON parsing errors.
10
+ - **Dual Socket Support**: Handle both Unix domain sockets and TCP sockets with
11
+ a consistent API
12
+ - **Message Handling**: Simplify sending and receiving messages over sockets
13
+ - **Dynamic Method Access**: Access message body values using method names
14
+ (e.g., `message.key`)
15
+ - **Background Processing**: Run servers in background threads to avoid
16
+ blocking main execution
17
+ - **Robust Error Handling**: Gracefully handle socket disconnections and JSON
18
+ parsing errors
19
+ - **URL Interface**: Servers can be represented as URL strings for easy
20
+ configuration and discovery
13
21
 
14
22
  ## Installation
15
23
 
@@ -40,10 +48,14 @@ Create a server instance and start listening for connections:
40
48
  ```ruby
41
49
  require 'unix_socks'
42
50
 
43
- server = UnixSocks::Server.new(socket_name: 'my_socket')
51
+ # For Unix sockets
52
+ server = UnixSocks::DomainSocketServer.new(socket_name: 'my_socket')
53
+
54
+ # For TCP sockets
55
+ server = UnixSocks::TCPSocketServer.new(hostname: 'localhost', port: 8080)
44
56
 
45
57
  # Run the server in the background to avoid blocking
46
- thread = server.receive_in_background(force: true) do |message|
58
+ thread = server.receive_in_background do |message|
47
59
  puts "Received message: #{message.inspect}"
48
60
  end
49
61
 
@@ -55,7 +67,11 @@ thread.join
55
67
  Transmit messages to connected clients:
56
68
 
57
69
  ```ruby
58
- client = UnixSocks::Server.new(socket_name: 'my_socket')
70
+ # For Unix sockets
71
+ client = UnixSocks::DomainSocketServer.new(socket_name: 'my_socket')
72
+
73
+ # For TCP sockets
74
+ client = UnixSocks::TCPSocketServer.new(hostname: 'localhost', port: 8080)
59
75
 
60
76
  # Prepare your message
61
77
  message = { status: 'success', data: [1, 2, 3] }
@@ -71,7 +87,11 @@ Handle incoming messages and send responses:
71
87
  ```ruby
72
88
  require 'unix_socks'
73
89
 
74
- server = UnixSocks::Server.new(socket_name: 'my_socket')
90
+ # For Unix sockets
91
+ server = UnixSocks::DomainSocketServer.new(socket_name: 'my_socket')
92
+
93
+ # For TCP sockets
94
+ server = UnixSocks::TCPSocketServer.new(hostname: 'localhost', port: 8080)
75
95
 
76
96
  def handle_message(message)
77
97
  # Access message body values using method names
@@ -82,7 +102,7 @@ def handle_message(message)
82
102
  end
83
103
 
84
104
  # Use in your server setup
85
- thread = server.receive_in_background(force: true) do |message|
105
+ thread = server.receive_in_background do |message|
86
106
  handle_message(message)
87
107
  end
88
108
 
@@ -91,23 +111,69 @@ thread.join
91
111
 
92
112
  And in the client:
93
113
  ```ruby
94
- client = UnixSocks::Server.new(socket_name: 'my_socket')
114
+ # For Unix sockets
115
+ client = UnixSocks::DomainSocketServer.new(socket_name: 'my_socket')
116
+
117
+ # For TCP sockets
118
+ client = UnixSocks::TCPSocketServer.new(hostname: 'localhost', port: 8080)
95
119
 
96
120
  # Prepare your message
97
121
  message = { status: 'success', data: [1, 2, 3] }
98
122
 
99
- # Send the message
123
+ # Send the message and get a response
100
124
  response = client.transmit_with_response(message)
101
125
 
102
126
  # Receive the response
103
127
  puts "Received server response status: #{response.status}"
104
128
  ```
105
129
 
106
- ### 4. Message Object Features
130
+ ### 4. Force Parameter Behavior
131
+
132
+ The `force` parameter is only applicable to Unix domain socket servers and
133
+ controls whether existing socket files should be overwritten:
134
+
135
+ - **Unix Socket Servers**: When `force: true` is specified, existing socket
136
+ files will be overwritten without raising an error. Otherwise a
137
+ `UnixSocks::ServerError` is raised.
138
+ - **TCP Socket Servers**: The `force` parameter is accepted for interface
139
+ compatibility but has no effect since TCP sockets don't use filesystem-based
140
+ socket files
141
+
142
+ ```ruby
143
+ # Unix socket - force parameter works
144
+ server = UnixSocks::DomainSocketServer.new(socket_name: 'my.sock')
145
+ server.receive(force: true) # Overwrites existing socket file if it exists
146
+
147
+ # TCP socket - force parameter is ignored
148
+ server = UnixSocks::TCPSocketServer.new(hostname: 'localhost', port: 8080)
149
+ server.receive(force: true) # Parameter has no effect
150
+ ```
151
+
152
+ ### 5. Server URL Interface
153
+
154
+ Both server types support URL representation for easy configuration and discovery:
155
+
156
+ ```ruby
157
+ # Unix socket server URL
158
+ unix_server = UnixSocks::DomainSocketServer.new(socket_name: 'my.sock')
159
+ unix_url = unix_server.to_url # => "unix:///full/path/to/my.sock"
160
+
161
+ # TCP socket server URL
162
+ tcp_server = UnixSocks::TCPSocketServer.new(hostname: 'localhost', port: 8080)
163
+ tcp_url = tcp_server.to_url # => "tcp://localhost:8080"
164
+
165
+ # Use URLs for configuration
166
+ server = UnixSocks.from_url(tcp_url)
167
+ ```
168
+
169
+ ### 6. Message Object Features
107
170
 
108
- - **Dynamic Access**: Methods like `message.status` automatically map to the message body.
109
- - **Disconnect Handling**: Safely close socket connections using `disconnect`.
110
- - **Error Resilience**: The `respond` method handles disconnections gracefully.
171
+ - **Dynamic Access**: Methods like `message.status` automatically map to the
172
+ message body
173
+ - **Disconnect Handling**: Safely close socket connections using `disconnect`
174
+ - **Error Resilience**: The `respond` method handles disconnections gracefully
175
+ - **Consistent Error Handling**: All server errors are wrapped in
176
+ `UnixSocks::ServerError`
111
177
 
112
178
  ## Author
113
179
 
@@ -115,4 +181,4 @@ puts "Received server response status: #{response.status}"
115
181
 
116
182
  ## License
117
183
 
118
- [MIT License](./LICENSE)
184
+ [MIT License](LICENSE)
@@ -1,9 +1,10 @@
1
1
  # Manages Unix socket-based communication, providing both server and client
2
2
  # functionality.
3
- class UnixSocks::Server
3
+ class UnixSocks::DomainSocketServer
4
4
  include FileUtils
5
+ include UnixSocks::ServerShared
5
6
 
6
- # Initializes a new UnixSocks::Server instance.
7
+ # Initializes a new UnixSocks::DomainSocketServer instance.
7
8
  #
8
9
  # @param socket_name [ String ] The name of the server socket file.
9
10
  # @param runtime_dir [ String, nil ] The path to the runtime directory where
@@ -13,6 +14,17 @@ class UnixSocks::Server
13
14
  @socket_name, @runtime_dir = socket_name, runtime_dir
14
15
  end
15
16
 
17
+ # Returns the URL representation of the server socket configuration.
18
+ #
19
+ # This method constructs and returns a URL string in the format "unix://path"
20
+ # that represents the Unix socket server's file path
21
+ # configuration.
22
+ #
23
+ # @return [ String ] A URL string in the format "unix://path"
24
+ def to_url
25
+ "unix://#{server_socket_path}"
26
+ end
27
+
16
28
  # Returns the default runtime directory path based on the XDG_RUNTIME_DIR
17
29
  # environment variable.
18
30
  #
@@ -47,29 +59,23 @@ class UnixSocks::Server
47
59
  File.expand_path(File.join(@runtime_dir, @socket_name))
48
60
  end
49
61
 
50
- # The transmit method sends a message over the Unix socket connection.
62
+ # The transmit method sends a message over the Unix socket connection
51
63
  #
52
- # It first prepares the message by converting it to JSON format, and then
53
- # establishes a connection to the server socket using UNIXSocket.new.
64
+ # This method prepares a message by converting it to JSON format, establishes
65
+ # a connection to the server socket using UNIXSocket.new, writes the
66
+ # prepared message to the socket, and then returns the created socket
54
67
  #
55
- # Finally, it writes the prepared message to the socket using socket.puts,
56
- # ensuring that the socket is properly closed after use.
68
+ # @param message [ Object ] The message to be sent over the Unix socket
69
+ # @param close [ TrueClass, FalseClass ] Whether to close the socket after sending
57
70
  #
58
- # @param message [ Message ] The message to be sent over the Unix socket.
59
- def transmit(message)
71
+ # @return [ UNIXSocket ] The socket connection that was used to transmit the message
72
+ def transmit(message, close: false)
60
73
  mkdir_p @runtime_dir
61
74
  socket = UNIXSocket.new(server_socket_path)
62
75
  socket.puts JSON(message)
63
76
  socket
64
- end
65
-
66
- # Sends a message and returns the parsed JSON response.
67
- #
68
- # @param message [Object] The message to be sent as JSON.
69
- # @return [Hash, nil] The parsed JSON response or nil if parsing fails.
70
- def transmit_with_response(message)
71
- socket = transmit(message)
72
- parse_json_message(socket.gets, socket)
77
+ ensure
78
+ close and socket.close
73
79
  end
74
80
 
75
81
  # Receives messages from clients connected to the server socket.
@@ -87,7 +93,9 @@ class UnixSocks::Server
87
93
  def receive(force: false, &block)
88
94
  mkdir_p @runtime_dir
89
95
  if !force && socket_path_exist?
90
- raise Errno::EEXIST, "Path already exists #{server_socket_path.inspect}"
96
+ raise UnixSocks::ServerError.build(
97
+ Errno::EEXIST, "Path already exists #{server_socket_path.inspect}"
98
+ )
91
99
  end
92
100
  Socket.unix_server_loop(server_socket_path) do |socket, client_addrinfo|
93
101
  message = pop_message(socket) and block.(message)
@@ -107,7 +115,9 @@ class UnixSocks::Server
107
115
  # @return [Thread] The background thread running the receiver
108
116
  def receive_in_background(force: false, &block)
109
117
  if !force && socket_path_exist?
110
- raise Errno::EEXIST, "Path already exists #{server_socket_path.inspect}"
118
+ raise UnixSocks::ServerError.build(
119
+ Errno::EEXIST, "Path already exists #{server_socket_path.inspect}"
120
+ )
111
121
  end
112
122
  Thread.new do
113
123
  receive(force:, &block)
@@ -128,47 +138,4 @@ class UnixSocks::Server
128
138
  def remove_socket_path
129
139
  FileUtils.rm_f server_socket_path
130
140
  end
131
-
132
- private
133
-
134
- # Parses a JSON message from the socket and associates it with the socket
135
- # connection
136
- #
137
- # This method retrieves a line of data from the socket, strips whitespace,
138
- # and attempts to parse it as JSON. If successful, it creates a
139
- # UnixSocks::Message object with the parsed data and assigns the socket
140
- # connection to the message. If parsing fails, it logs a warning and
141
- # returns nil.
142
- #
143
- # @param socket [ Socket ] the socket connection to read from
144
- #
145
- # @return [ UnixSocks::Message, nil ] the parsed message object or nil if
146
- # parsing fails
147
- def pop_message(socket)
148
- parse_json_message(socket.gets, socket)
149
- end
150
-
151
- # Parses a JSON message from the given data and associates it with the
152
- # provided socket connection.
153
- #
154
- # This method processes the input data by stripping whitespace and attempting
155
- # to parse it as JSON. If parsing is successful, it creates a
156
- # UnixSocks::Message object with the parsed data and assigns the socket
157
- # connection to the message. In case of a JSON parsing error, it
158
- # logs a warning and returns nil.
159
- #
160
- # @param data [ String ] The raw data string to be parsed as JSON.
161
- # @param socket [ Socket ] The socket connection associated with the message.
162
- #
163
- # @return [ UnixSocks::Message, nil ] The parsed message object or nil if
164
- # parsing fails.
165
- def parse_json_message(data, socket)
166
- data = data.strip
167
- data.empty? and return nil
168
- obj = JSON.parse(data, object_class: UnixSocks::Message)
169
- obj.socket = socket
170
- obj
171
- rescue JSON::ParserError => e
172
- warn "Caught #{e.class}: #{e} for #{data[0, 512].inspect}"
173
- end
174
141
  end
@@ -0,0 +1,40 @@
1
+ # Marker module for UnixSocks server-related errors.
2
+ #
3
+ # This module is mixed into exceptions raised by UnixSocks server
4
+ # implementations to provide a common rescue clause for server-related
5
+ # errors.
6
+ #
7
+ # @example Handling server errors
8
+ # begin
9
+ # server.receive { |message| process_message(message) }
10
+ # rescue UnixSocks::ServerError
11
+ # # Handle all UnixSocks server errors consistently
12
+ # end
13
+ module UnixSocks::ServerError
14
+ # Builds a server error exception with the given exception class and message.
15
+ #
16
+ # This method creates a new exception instance of the specified exception
17
+ # class with the provided message, marks it with the ServerError module, and
18
+ # returns the marked exception.
19
+ #
20
+ # @param exception [ Class ] The exception class to be instantiated
21
+ # @param message [ String ] The error message for the exception
22
+ #
23
+ # @return [ Exception ] A new exception instance marked with ServerError module
24
+ def self.build(exception, message)
25
+ mark(exception.new(message))
26
+ end
27
+
28
+ # Marks the given exception with the ServerError module.
29
+ #
30
+ # This method extends the provided exception object with the ServerError
31
+ # module, effectively tagging it as a server-related error for consistent
32
+ # handling.
33
+ #
34
+ # @param e [ Exception ] The exception object to be marked
35
+ #
36
+ # @return [ Exception ] The same exception object, now extended with ServerError
37
+ def self.mark(e)
38
+ e.extend(self)
39
+ end
40
+ end
@@ -0,0 +1,70 @@
1
+ # Shared server functionality for UnixSocks implementations
2
+ #
3
+ # This module provides common methods for transmitting messages and parsing
4
+ # JSON responses that are used by both Unix domain socket and TCP socket
5
+ # server implementations.
6
+ module UnixSocks::ServerShared
7
+ # Sends a message and returns the parsed JSON response.
8
+ #
9
+ # @param message [Object] The message to be sent as JSON.
10
+ # @return [Hash, nil] The parsed JSON response or nil if parsing fails.
11
+ def transmit_with_response(message, close: true)
12
+ socket = transmit(message, close: false)
13
+ parse_json_message(socket.gets, socket)
14
+ ensure
15
+ close and socket.close
16
+ end
17
+
18
+ # Converts the server's URL representation into a URI object.
19
+ #
20
+ # This method takes the URL string returned by #to_url and parses it into
21
+ # a URI object for convenient access to the server's address components.
22
+ #
23
+ # @return [ URI ] A URI object representing the server's address configuration.
24
+ def to_uri
25
+ URI.parse(to_url)
26
+ end
27
+
28
+ private
29
+
30
+ # Parses a JSON message from the socket and associates it with the socket
31
+ # connection
32
+ #
33
+ # This method retrieves a line of data from the socket, strips whitespace,
34
+ # and attempts to parse it as JSON. If successful, it creates a
35
+ # UnixSocks::Message object with the parsed data and assigns the socket
36
+ # connection to the message. If parsing fails, it logs a warning and
37
+ # returns nil.
38
+ #
39
+ # @param socket [ Socket ] the socket connection to read from
40
+ #
41
+ # @return [ UnixSocks::Message, nil ] the parsed message object or nil if
42
+ # parsing fails
43
+ def pop_message(socket)
44
+ parse_json_message(socket.gets, socket)
45
+ end
46
+
47
+ # Parses a JSON message from the given data and associates it with the
48
+ # provided socket connection.
49
+ #
50
+ # This method processes the input data by stripping whitespace and attempting
51
+ # to parse it as JSON. If parsing is successful, it creates a
52
+ # UnixSocks::Message object with the parsed data and assigns the socket
53
+ # connection to the message. In case of a JSON parsing error, it
54
+ # logs a warning and returns nil.
55
+ #
56
+ # @param data [ String ] The raw data string to be parsed as JSON.
57
+ # @param socket [ Socket ] The socket connection associated with the message.
58
+ #
59
+ # @return [ UnixSocks::Message, nil ] The parsed message object or nil if
60
+ # parsing fails.
61
+ def parse_json_message(data, socket)
62
+ data = data.strip
63
+ data.empty? and return nil
64
+ obj = JSON.parse(data, object_class: UnixSocks::Message)
65
+ obj.socket = socket
66
+ obj
67
+ rescue JSON::ParserError => e
68
+ warn "Caught #{e.class}: #{e} for #{data[0, 512].inspect}"
69
+ end
70
+ end
@@ -0,0 +1,109 @@
1
+ # Provides TCP socket-based communication for inter-process messaging.
2
+ #
3
+ # This class enables sending and receiving messages over TCP connections,
4
+ # supporting both client and server functionality for network-based
5
+ # communication.
6
+ #
7
+ # @example
8
+ # server = UnixSocks::TCPSocketServer.new(hostname: 'localhost', port: 8080)
9
+ # server.receive { |message| puts message.inspect }
10
+ # server.transmit({ message: 'hello' })
11
+ class UnixSocks::TCPSocketServer
12
+ include UnixSocks::ServerShared
13
+
14
+ # Initializes a new UnixSocks::TCPSocketServer instance.
15
+ #
16
+ # Sets up the server with the specified hostname and port for TCP
17
+ # communication.
18
+ #
19
+ # @param hostname [ String ] The hostname to bind to, defaults to 'localhost'
20
+ # @param port [ Integer ] The port number to bind to
21
+ def initialize(hostname: 'localhost', port:)
22
+ @hostname, @port = hostname, port
23
+ end
24
+
25
+ # Returns the hostname associated with this TCP socket server instance.
26
+ #
27
+ # @return [ String ] The hostname that the server binds to for TCP communication.
28
+ attr_reader :hostname
29
+
30
+ # Returns the port number associated with this TCP socket server instance.
31
+ #
32
+ # @return [ Integer ] The port number that the server binds to for TCP communication.
33
+ attr_reader :port
34
+
35
+ # Returns the URL representation of the TCP socket server configuration.
36
+ #
37
+ # This method constructs and returns a URL string in the format
38
+ # "tcp://hostname:port" that represents the TCP socket server's address and
39
+ # port configuration.
40
+ #
41
+ # @return [ String ] A URL string in the format "tcp://hostname:port"
42
+ def to_url
43
+ "tcp://#@hostname:#@port"
44
+ end
45
+
46
+ # Sends a message over a TCP connection to the configured hostname and port.
47
+ #
48
+ # This method establishes a TCP socket connection to the specified hostname
49
+ # and port, serializes the provided message to JSON format, and writes it to
50
+ # the socket. The socket connection is returned after the message is sent.
51
+ #
52
+ # @param message [Object] The message to be sent, which will be converted to JSON
53
+ # @param close [TrueClass, FalseClass] Whether to close the socket after sending
54
+ #
55
+ # @return [TCPSocket] The socket connection that was used to transmit the message
56
+ def transmit(message, close: false)
57
+ socket = TCPSocket.new(@hostname, @port)
58
+ socket.puts JSON(message)
59
+ socket
60
+ ensure
61
+ close and socket.close
62
+ end
63
+
64
+ # Receives messages from clients connected to the TCP socket.
65
+ #
66
+ # This method binds to the configured hostname and port, listens for incoming
67
+ # connections, and processes messages from connected clients. It accepts a
68
+ # single connection at a time and handles each message by parsing it from
69
+ # JSON and yielding it to the provided block. The socket connection is closed
70
+ # after processing each message.
71
+ #
72
+ # @param force [ nil ] This parameter is accepted for interface compatibility
73
+ # but is unused in the TCP implementation.
74
+ # @yield [ UnixSocks::Message ] The received message parsed from JSON.
75
+ #
76
+ # @raise [ Errno::EADDRINUSE ] If the address is already in use.
77
+ def receive(force: nil, &block)
78
+ Addrinfo.tcp(@hostname, @port).bind do |server|
79
+ server.listen(1)
80
+ loop do
81
+ socket, = server.accept
82
+ message = pop_message(socket) and block.(message)
83
+ socket.close
84
+ end
85
+ end
86
+ rescue Errno::EADDRINUSE => e
87
+ raise UnixSocks::ServerError.mark(e)
88
+ end
89
+
90
+ # Runs the message receiver in a background thread to prevent blocking.
91
+ #
92
+ # This method starts a new thread that continuously listens for incoming
93
+ # messages from connected clients. The server socket is created in the
94
+ # background, allowing the main execution flow to continue without
95
+ # waiting for messages.
96
+ #
97
+ # @param force [ nil ] This parameter is accepted for interface compatibility
98
+ # but is unused in the TCP implementation.
99
+ # @yield [UnixSocks::Message] The received message
100
+ #
101
+ # @return [Thread] The background thread running the receiver
102
+ def receive_in_background(force: nil, &block)
103
+ Thread.new do
104
+ receive(&block)
105
+ rescue Errno::EADDRINUSE => e
106
+ raise UnixSocks::ServerError.mark(e)
107
+ end
108
+ end
109
+ end
@@ -1,6 +1,6 @@
1
1
  module UnixSocks
2
2
  # UnixSocks version
3
- VERSION = '0.2.3'
3
+ VERSION = '0.3.0'
4
4
  VERSION_ARRAY = VERSION.split('.').map(&:to_i) # :nodoc:
5
5
  VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc:
6
6
  VERSION_MINOR = VERSION_ARRAY[1] # :nodoc:
data/lib/unix_socks.rb CHANGED
@@ -1,14 +1,48 @@
1
1
  require 'json'
2
2
  require 'fileutils'
3
3
  require 'socket'
4
+ require 'uri'
4
5
  require 'tins'
5
6
 
6
7
  # Provides classes for handling inter-process communication via Unix 🧦🧦.
7
8
  # Supports dynamic message handling, background processing, and robust error
8
9
  # management.
9
10
  module UnixSocks
11
+ # Creates a server instance from a URL string.
12
+ #
13
+ # This method parses a URL and constructs the appropriate server instance
14
+ # based on the scheme. For 'unix' URLs, it creates a DomainSocketServer,
15
+ # and for 'tcp' URLs, it creates a TCPSocketServer.
16
+ #
17
+ # @param url [String, URI] The URL string or URI object representing the
18
+ # server configuration
19
+ #
20
+ # @return [UnixSocks::DomainSocketServer, UnixSocks::TCPSocketServer] The
21
+ # constructed server instance
22
+ #
23
+ # @raise [ArgumentError] If the URL scheme is not 'unix' or 'tcp'
24
+ def self.from_url(url)
25
+ uri = url.is_a?(URI) ? url : URI.parse(url.to_s)
26
+ case uri.scheme
27
+ when 'unix'
28
+ DomainSocketServer.new(
29
+ socket_name: File.basename(uri.path),
30
+ runtime_dir: File.dirname(uri.path)
31
+ )
32
+ when 'tcp'
33
+ TCPSocketServer.new(
34
+ hostname: uri.host,
35
+ port: uri.port
36
+ )
37
+ else
38
+ raise ArgumentError, "Invalid URL #{url.to_s.inspect} for UnixSocks"
39
+ end
40
+ end
10
41
  end
11
42
 
12
43
  require 'unix_socks/version'
44
+ require 'unix_socks/server_error'
13
45
  require 'unix_socks/message'
14
- require 'unix_socks/server'
46
+ require 'unix_socks/server_shared'
47
+ require 'unix_socks/domain_socket_server'
48
+ require 'unix_socks/tcp_socket_server'
@@ -1,10 +1,12 @@
1
1
  require 'spec_helper'
2
2
  require 'tins/xt/expose'
3
3
 
4
- describe UnixSocks::Server do
4
+ describe UnixSocks::DomainSocketServer do
5
5
  let(:socket_name) { 'test_socket' }
6
6
  let(:runtime_dir) { './tmp' }
7
- let(:server) { UnixSocks::Server.new(socket_name: socket_name, runtime_dir: runtime_dir).expose }
7
+ let(:server) {
8
+ described_class.new(socket_name: socket_name, runtime_dir: runtime_dir).expose
9
+ }
8
10
 
9
11
  describe '#initialize' do
10
12
  it 'sets the socket name and runtime directory' do
@@ -46,9 +48,18 @@ describe UnixSocks::Server do
46
48
  it 'sends a message over the Unix socket' do
47
49
  expect(server).to receive(:mkdir_p).with(runtime_dir)
48
50
  expect(UNIXSocket).to receive(:new).with(server.server_socket_path).
49
- and_return(double('socket', puts: nil, close: nil))
51
+ and_return(double('socket', puts: nil))
50
52
  server.transmit(message)
51
53
  end
54
+
55
+ it 'sends a message over the Unix socket and close' do
56
+ expect(server).to receive(:mkdir_p).with(runtime_dir)
57
+ socket = double('socket', puts: nil)
58
+ expect(UNIXSocket).to receive(:new).with(server.server_socket_path).
59
+ and_return(socket)
60
+ expect(socket).to receive(:close)
61
+ server.transmit(message, close: true)
62
+ end
52
63
  end
53
64
 
54
65
  describe '#transmit_with_response' do
@@ -56,7 +67,12 @@ describe UnixSocks::Server do
56
67
 
57
68
  it 'parses a valid JSON response' do
58
69
  allow(server).to receive(:mkdir_p)
59
- mock_socket = double('socket', puts: nil, gets: '{"status": "success"}')
70
+ mock_socket = double(
71
+ 'socket',
72
+ puts: nil,
73
+ gets: '{"status": "success"}',
74
+ close: true
75
+ )
60
76
  expect(UNIXSocket).to receive(:new).and_return(mock_socket)
61
77
 
62
78
  response = server.transmit_with_response(message)
@@ -66,7 +82,12 @@ describe UnixSocks::Server do
66
82
 
67
83
  it 'handles JSON parsing errors' do
68
84
  allow(server).to receive(:mkdir_p)
69
- mock_socket = double('socket', puts: nil, gets: 'invalid_json')
85
+ mock_socket = double(
86
+ 'socket',
87
+ puts: nil,
88
+ gets: 'invalid_json',
89
+ close: true
90
+ )
70
91
  expect(server).to receive(:warn).
71
92
  with(/Caught JSON::ParserError: unexpected character: 'invalid_json'/)
72
93
  expect(UNIXSocket).to receive(:new).and_return(mock_socket)
@@ -77,7 +98,12 @@ describe UnixSocks::Server do
77
98
 
78
99
  it 'handles empty responses' do
79
100
  allow(server).to receive(:mkdir_p)
80
- mock_socket = double('socket', puts: nil, gets: '')
101
+ mock_socket = double(
102
+ 'socket',
103
+ puts: nil,
104
+ gets: '',
105
+ close: true
106
+ )
81
107
  expect(UNIXSocket).to receive(:new).and_return(mock_socket)
82
108
 
83
109
  response = server.transmit_with_response(message)
@@ -89,7 +115,7 @@ describe UnixSocks::Server do
89
115
  it 'raises an error if the socket already exists and force is false' do
90
116
  allow(server).to receive(:socket_path_exist?).and_return(true)
91
117
  expect { server.receive(force: false) }.to\
92
- raise_error(Errno::EEXIST, /Path already exists/)
118
+ raise_error(UnixSocks::ServerError, /Path already exists/)
93
119
  end
94
120
 
95
121
  it 'does not raise an error if force is true' do
@@ -120,15 +146,15 @@ describe UnixSocks::Server do
120
146
 
121
147
  describe '#receive_in_background' do
122
148
  it 'runs the receiver in a background thread' do
123
- expect(Thread).to receive(:new).and_yield
149
+ expect(Thread).to receive(:new).and_yield.and_return(double(join: true))
124
150
  expect(FileUtils).to receive(:rm_f).with(server.server_socket_path)
125
151
  expect(server).to receive(:at_exit) { |&block| block.call }
126
152
  expect(server).to receive(:receive).with(force: true)
127
153
 
128
- server.receive_in_background(force: true)
154
+ server.receive_in_background(force: true).join
129
155
  end
130
156
 
131
- it 'it raises Errno::EEXIST if socket already exists' do
157
+ it 'it raises UnixSocks::ServerError if socket already exists' do
132
158
  expect(Thread).not_to receive(:new).and_yield
133
159
  expect(FileUtils).not_to receive(:rm_f).with(server.server_socket_path)
134
160
  expect(server).to receive(:socket_path_exist?).and_return true
@@ -136,22 +162,28 @@ describe UnixSocks::Server do
136
162
  expect(server).not_to receive(:receive).with(force: false)
137
163
 
138
164
  expect {
139
- server.receive_in_background(force: false)
140
- }.to raise_error(Errno::EEXIST)
165
+ server.receive_in_background(force: false).join
166
+ }.to raise_error(UnixSocks::ServerError)
141
167
  end
142
168
 
143
- it 'runs the receiver in a background thread' do
144
- expect(Thread).to receive(:new).and_yield
169
+ it 'runs the receiver in a background thread ignoring existing sockets' do
170
+ expect(Thread).to receive(:new).and_yield.and_return(double(join: true))
145
171
  expect(FileUtils).to receive(:rm_f).with(server.server_socket_path)
146
172
  expect(server).to receive(:at_exit) { |&block| block.call }
147
173
  expect(server).to receive(:receive).and_raise Errno::ENOENT
148
174
 
149
175
  expect {
150
- server.receive_in_background(force: true)
176
+ server.receive_in_background(force: true).join
151
177
  }.not_to raise_error
152
178
  end
153
179
  end
154
180
 
181
+ describe '#to_uri' do
182
+ it 'displays address' do
183
+ expect(server.to_url).to match %r(\Aunix://.*test_socket\z)
184
+ end
185
+ end
186
+
155
187
  describe '#socket_path_exist?' do
156
188
  it 'returns false if the socket file does not exist' do
157
189
  FileUtils.rm_f(server.server_socket_path)
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'UnixSocks::Server Interface' do
4
+ shared_examples 'sufficient interface' do
5
+ it 'supports transmit' do
6
+ expect(described_class).to be_method_defined :transmit
7
+ end
8
+
9
+ it 'supports transmit_with_response' do
10
+ expect(described_class).to be_method_defined :transmit_with_response
11
+ end
12
+
13
+ it 'supports receive' do
14
+ expect(described_class).to be_method_defined :receive
15
+ end
16
+
17
+ it 'supports receive_in_background' do
18
+ expect(described_class).to be_method_defined :receive_in_background
19
+ end
20
+
21
+ it 'supports to_uri' do
22
+ expect(described_class).to be_method_defined :to_url
23
+ end
24
+ end
25
+
26
+ context UnixSocks::DomainSocketServer do
27
+ it_behaves_like 'sufficient interface'
28
+ end
29
+
30
+ context UnixSocks::TCPSocketServer do
31
+ it_behaves_like 'sufficient interface'
32
+ end
33
+ end
@@ -0,0 +1,137 @@
1
+ require 'spec_helper'
2
+ require 'tins/xt/expose'
3
+
4
+ describe UnixSocks::TCPSocketServer do
5
+ let(:server) { described_class.new(hostname: 'localhost', port: 1234).expose }
6
+
7
+ describe '#initialize' do
8
+ it 'sets the socket name and runtime directory' do
9
+ expect(server.instance_variable_get(:@hostname)).to eq('localhost')
10
+ expect(server.instance_variable_get(:@port)).to eq(1234)
11
+ end
12
+ end
13
+
14
+ describe '#transmit' do
15
+ let(:message) { { test: 'message' } }
16
+
17
+ it 'sends a message over the Unix socket' do
18
+ expect(TCPSocket).to receive(:new).with(server.hostname, server.port).
19
+ and_return(double('socket', puts: nil))
20
+ server.transmit(message)
21
+ end
22
+
23
+ it 'sends a message over the Unix socket and close' do
24
+ socket = double('socket', puts: nil)
25
+ expect(TCPSocket).to receive(:new).with(server.hostname, server.port).
26
+ and_return(socket)
27
+ expect(socket).to receive(:close)
28
+ server.transmit(message, close: true)
29
+ end
30
+ end
31
+
32
+ describe '#transmit_with_response' do
33
+ let(:message) { { test: 'message' } }
34
+
35
+ it 'parses a valid JSON response' do
36
+ allow(server).to receive(:mkdir_p)
37
+ socket = double(
38
+ 'socket',
39
+ puts: nil,
40
+ gets: '{"status": "success"}',
41
+ close: true
42
+ )
43
+ expect(TCPSocket).to receive(:new).and_return(socket)
44
+
45
+ response = server.transmit_with_response(message)
46
+ expect(response).to be_a UnixSocks::Message
47
+ expect(response.status).to eq 'success'
48
+ end
49
+
50
+ it 'handles JSON parsing errors' do
51
+ allow(server).to receive(:mkdir_p)
52
+ socket = double(
53
+ 'socket',
54
+ puts: nil,
55
+ gets: 'invalid_json',
56
+ close: true
57
+ )
58
+ expect(server).to receive(:warn).
59
+ with(/Caught JSON::ParserError: unexpected character: 'invalid_json'/)
60
+ expect(TCPSocket).to receive(:new).and_return(socket)
61
+
62
+ response = server.transmit_with_response(message)
63
+ expect(response).to be nil
64
+ end
65
+
66
+ it 'handles empty responses' do
67
+ allow(server).to receive(:mkdir_p)
68
+ socket = double(
69
+ 'socket',
70
+ puts: nil,
71
+ gets: '',
72
+ close: true
73
+ )
74
+ expect(TCPSocket).to receive(:new).and_return(socket)
75
+
76
+ response = server.transmit_with_response(message)
77
+ expect(response).to be nil
78
+ end
79
+ end
80
+
81
+ describe '#receive' do
82
+ it 'does bind to hostname:port' do
83
+ expect(Addrinfo).to receive(:tcp).with(server.hostname, server.port).
84
+ and_return(double(bind: true))
85
+ server.receive
86
+ end
87
+
88
+ it 'raises UnixSocks::ServerError if already bound' do
89
+ socket = double('socket')
90
+ expect(Addrinfo).to receive(:tcp).with(server.hostname, server.port).
91
+ and_return(socket)
92
+ expect(socket).to receive(:bind).and_raise Errno::EADDRINUSE
93
+ expect { server.receive }.to raise_error(UnixSocks::ServerError)
94
+ end
95
+ end
96
+
97
+ describe 'pop_message' do
98
+ it 'parses a valid JSON message' do
99
+ socket = double('socket')
100
+ allow(socket).to receive(:gets).and_return('{"test": "message"}')
101
+
102
+ message = server.pop_message(socket)
103
+ expect(message).to be_a(UnixSocks::Message)
104
+ expect(message.test).to eq 'message'
105
+ end
106
+
107
+ it 'handles a JSON parsing error' do
108
+ socket = double('socket')
109
+ allow(socket).to receive(:gets).and_return('invalid_json')
110
+ expect(server).to receive(:warn).
111
+ with(/Caught JSON::ParserError: unexpected character: 'invalid_json'/)
112
+ expect(server.pop_message(socket)).to be nil
113
+ end
114
+ end
115
+
116
+ describe '#receive_in_background' do
117
+ it 'runs the receiver in a background thread' do
118
+ expect(Thread).to receive(:new).and_yield.and_return(double(join: true))
119
+ expect(server).to receive(:receive)
120
+
121
+ server.receive_in_background.join
122
+ end
123
+
124
+ it 'it raises UnixSocks::ServerError if socket already exists' do
125
+ expect(server).to receive(:receive).and_raise(Errno::EADDRINUSE)
126
+ expect {
127
+ server.receive_in_background.join
128
+ }.to raise_error(UnixSocks::ServerError)
129
+ end
130
+ end
131
+
132
+ describe '#to_uri' do
133
+ it 'displays address' do
134
+ expect(server.to_url).to eq 'tcp://localhost:1234'
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,101 @@
1
+ require 'spec_helper'
2
+
3
+ describe UnixSocks do
4
+ describe '.from_url' do
5
+ context 'with unix URL' do
6
+ it 'creates a DomainSocketServer' do
7
+ server = UnixSocks.from_url('unix:///tmp/my.sock')
8
+ expect(server).to be_a(UnixSocks::DomainSocketServer)
9
+ end
10
+
11
+ it 'sets correct socket name and runtime directory' do
12
+ server = UnixSocks.from_url('unix:///tmp/my.sock')
13
+ expect(server.instance_variable_get(:@socket_name)).to eq('my.sock')
14
+ expect(server.instance_variable_get(:@runtime_dir)).to eq('/tmp')
15
+ end
16
+
17
+ it 'handles unix URL with different runtime directory' do
18
+ server = UnixSocks.from_url('unix:///var/run/my.sock')
19
+ expect(server.instance_variable_get(:@socket_name)).to eq('my.sock')
20
+ expect(server.instance_variable_get(:@runtime_dir)).to eq('/var/run')
21
+ end
22
+
23
+ it 'works with URI objects' do
24
+ uri = URI.parse('unix:///tmp/test.sock')
25
+ server = UnixSocks.from_url(uri)
26
+ expect(server).to be_a(UnixSocks::DomainSocketServer)
27
+ expect(server.instance_variable_get(:@socket_name)).to eq('test.sock')
28
+ end
29
+ end
30
+
31
+ context 'with tcp URL' do
32
+ it 'creates a TCPSocketServer' do
33
+ server = UnixSocks.from_url('tcp://localhost:8080')
34
+ expect(server).to be_a(UnixSocks::TCPSocketServer)
35
+ end
36
+
37
+ it 'sets correct hostname and port' do
38
+ server = UnixSocks.from_url('tcp://example.com:9000')
39
+ expect(server.instance_variable_get(:@hostname)).to eq('example.com')
40
+ expect(server.instance_variable_get(:@port)).to eq(9000)
41
+ end
42
+
43
+ it 'works with default port' do
44
+ server = UnixSocks.from_url('tcp://localhost:80')
45
+ expect(server.instance_variable_get(:@hostname)).to eq('localhost')
46
+ expect(server.instance_variable_get(:@port)).to eq(80)
47
+ end
48
+
49
+ it 'works with URI objects' do
50
+ uri = URI.parse('tcp://localhost:8080')
51
+ server = UnixSocks.from_url(uri)
52
+ expect(server).to be_a(UnixSocks::TCPSocketServer)
53
+ expect(server.instance_variable_get(:@hostname)).to eq('localhost')
54
+ expect(server.instance_variable_get(:@port)).to eq(8080)
55
+ end
56
+ end
57
+
58
+ context 'with invalid URL' do
59
+ it 'raises ArgumentError for unsupported scheme' do
60
+ expect {
61
+ UnixSocks.from_url('ftp://example.com/file')
62
+ }.to raise_error(ArgumentError, /Invalid URL.*ftp/)
63
+ end
64
+
65
+ it 'raises ArgumentError for invalid URL format' do
66
+ expect {
67
+ UnixSocks.from_url('not_a_url')
68
+ }.to raise_error(ArgumentError)
69
+ end
70
+ end
71
+
72
+ context 'with edge cases' do
73
+ it 'handles URLs with query parameters' do
74
+ server = UnixSocks.from_url('unix:///tmp/test.sock?param=value')
75
+ expect(server).to be_a(UnixSocks::DomainSocketServer)
76
+ expect(server.instance_variable_get(:@socket_name)).to eq('test.sock')
77
+ end
78
+
79
+ it 'handles URLs with fragments' do
80
+ server = UnixSocks.from_url('tcp://localhost:8080#fragment')
81
+ expect(server).to be_a(UnixSocks::TCPSocketServer)
82
+ expect(server.instance_variable_get(:@hostname)).to eq('localhost')
83
+ expect(server.instance_variable_get(:@port)).to eq(8080)
84
+ end
85
+ end
86
+ end
87
+
88
+ describe 'integration test' do
89
+ it 'can create and use unix server from URL' do
90
+ server = UnixSocks.from_url('unix:///tmp/test.sock')
91
+ expect(server).to be_a(UnixSocks::DomainSocketServer)
92
+ expect(server.to_url).to match(%r{^unix://.*test\.sock$})
93
+ end
94
+
95
+ it 'can create and use tcp server from URL' do
96
+ server = UnixSocks.from_url('tcp://localhost:8080')
97
+ expect(server).to be_a(UnixSocks::TCPSocketServer)
98
+ expect(server.to_url).to eq('tcp://localhost:8080')
99
+ end
100
+ end
101
+ end
data/unix_socks.gemspec CHANGED
@@ -1,9 +1,9 @@
1
1
  # -*- encoding: utf-8 -*-
2
- # stub: unix_socks 0.2.3 ruby lib
2
+ # stub: unix_socks 0.3.0 ruby lib
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "unix_socks".freeze
6
- s.version = "0.2.3".freeze
6
+ s.version = "0.3.0".freeze
7
7
 
8
8
  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
9
9
  s.require_paths = ["lib".freeze]
@@ -11,15 +11,15 @@ Gem::Specification.new do |s|
11
11
  s.date = "1980-01-02"
12
12
  s.description = "This library enables communication between processes using Unix sockets. It\nhandles message transmission, socket management, and cleanup, supporting\nboth synchronous and asynchronous operations while providing error handling\nfor robust development.\n".freeze
13
13
  s.email = "flori@ping.de".freeze
14
- s.extra_rdoc_files = ["README.md".freeze, "lib/unix_socks.rb".freeze, "lib/unix_socks/message.rb".freeze, "lib/unix_socks/server.rb".freeze, "lib/unix_socks/version.rb".freeze]
15
- s.files = ["CHANGES.md".freeze, "Gemfile".freeze, "LICENSE".freeze, "README.md".freeze, "Rakefile".freeze, "lib/unix_socks.rb".freeze, "lib/unix_socks/message.rb".freeze, "lib/unix_socks/server.rb".freeze, "lib/unix_socks/version.rb".freeze, "spec/spec_helper.rb".freeze, "spec/unix_socks/message_spec.rb".freeze, "spec/unix_socks/server_spec.rb".freeze, "unix_socks.gemspec".freeze]
14
+ s.extra_rdoc_files = ["README.md".freeze, "lib/unix_socks.rb".freeze, "lib/unix_socks/domain_socket_server.rb".freeze, "lib/unix_socks/message.rb".freeze, "lib/unix_socks/server_error.rb".freeze, "lib/unix_socks/server_shared.rb".freeze, "lib/unix_socks/tcp_socket_server.rb".freeze, "lib/unix_socks/version.rb".freeze]
15
+ s.files = ["CHANGES.md".freeze, "Gemfile".freeze, "LICENSE".freeze, "README.md".freeze, "Rakefile".freeze, "lib/unix_socks.rb".freeze, "lib/unix_socks/domain_socket_server.rb".freeze, "lib/unix_socks/message.rb".freeze, "lib/unix_socks/server_error.rb".freeze, "lib/unix_socks/server_shared.rb".freeze, "lib/unix_socks/tcp_socket_server.rb".freeze, "lib/unix_socks/version.rb".freeze, "spec/spec_helper.rb".freeze, "spec/unix_socks/domain_socket_server_spec.rb".freeze, "spec/unix_socks/message_spec.rb".freeze, "spec/unix_socks/server_interface_spec.rb".freeze, "spec/unix_socks/tcp_socket_server_spec.rb".freeze, "spec/unix_socks_spec.rb".freeze, "unix_socks.gemspec".freeze]
16
16
  s.homepage = "https://github.com/flori/unix_socks".freeze
17
17
  s.licenses = ["MIT".freeze]
18
18
  s.rdoc_options = ["--title".freeze, "UnixSocks - A Ruby library for inter-process communication via Unix sockets with\ndynamic message handling\n".freeze, "--main".freeze, "README.md".freeze]
19
19
  s.required_ruby_version = Gem::Requirement.new(">= 3.1".freeze)
20
20
  s.rubygems_version = "4.0.2".freeze
21
21
  s.summary = "A Ruby library for inter-process communication via Unix sockets with dynamic message handling".freeze
22
- s.test_files = ["spec/spec_helper.rb".freeze, "spec/unix_socks/message_spec.rb".freeze, "spec/unix_socks/server_spec.rb".freeze]
22
+ s.test_files = ["spec/spec_helper.rb".freeze, "spec/unix_socks/domain_socket_server_spec.rb".freeze, "spec/unix_socks/message_spec.rb".freeze, "spec/unix_socks/server_interface_spec.rb".freeze, "spec/unix_socks/tcp_socket_server_spec.rb".freeze, "spec/unix_socks_spec.rb".freeze]
23
23
 
24
24
  s.specification_version = 4
25
25
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: unix_socks
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Florian Frank
@@ -132,8 +132,11 @@ extensions: []
132
132
  extra_rdoc_files:
133
133
  - README.md
134
134
  - lib/unix_socks.rb
135
+ - lib/unix_socks/domain_socket_server.rb
135
136
  - lib/unix_socks/message.rb
136
- - lib/unix_socks/server.rb
137
+ - lib/unix_socks/server_error.rb
138
+ - lib/unix_socks/server_shared.rb
139
+ - lib/unix_socks/tcp_socket_server.rb
137
140
  - lib/unix_socks/version.rb
138
141
  files:
139
142
  - CHANGES.md
@@ -142,12 +145,18 @@ files:
142
145
  - README.md
143
146
  - Rakefile
144
147
  - lib/unix_socks.rb
148
+ - lib/unix_socks/domain_socket_server.rb
145
149
  - lib/unix_socks/message.rb
146
- - lib/unix_socks/server.rb
150
+ - lib/unix_socks/server_error.rb
151
+ - lib/unix_socks/server_shared.rb
152
+ - lib/unix_socks/tcp_socket_server.rb
147
153
  - lib/unix_socks/version.rb
148
154
  - spec/spec_helper.rb
155
+ - spec/unix_socks/domain_socket_server_spec.rb
149
156
  - spec/unix_socks/message_spec.rb
150
- - spec/unix_socks/server_spec.rb
157
+ - spec/unix_socks/server_interface_spec.rb
158
+ - spec/unix_socks/tcp_socket_server_spec.rb
159
+ - spec/unix_socks_spec.rb
151
160
  - unix_socks.gemspec
152
161
  homepage: https://github.com/flori/unix_socks
153
162
  licenses:
@@ -179,5 +188,8 @@ summary: A Ruby library for inter-process communication via Unix sockets with dy
179
188
  message handling
180
189
  test_files:
181
190
  - spec/spec_helper.rb
191
+ - spec/unix_socks/domain_socket_server_spec.rb
182
192
  - spec/unix_socks/message_spec.rb
183
- - spec/unix_socks/server_spec.rb
193
+ - spec/unix_socks/server_interface_spec.rb
194
+ - spec/unix_socks/tcp_socket_server_spec.rb
195
+ - spec/unix_socks_spec.rb