motion-unixsocket 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/.travis.yml +6 -0
- data/Gemfile +3 -0
- data/LICENSE +21 -0
- data/README.md +72 -0
- data/Rakefile +16 -0
- data/app/app_delegate.rb +5 -0
- data/lib/motion-unixsocket.rb +15 -0
- data/lib/unix/socket.rb +86 -0
- data/lib/unix/type.rb +16 -0
- data/lib/unix/version.rb +3 -0
- data/motion-unixsocket.gemspec +20 -0
- data/spec/type_spec.rb +15 -0
- data/spec/unixsocket_spec.rb +40 -0
- data/spec_helpers/echo.rb +7 -0
- metadata +89 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6441edd9d5c8e6390b3b605591401f5c1ed24bc2
|
4
|
+
data.tar.gz: 03fde8297f247caeba8d68feb6f574b807cfc48e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 04087fa399915a1c3911b3f614ec49e7517a0cd74fc36575cff33e6fc7fa50b3160d888e82262ba2be4ca924599702148264588b0be933834118c12b9788b576
|
7
|
+
data.tar.gz: f6173057c03d85e7ef6bf14eeb0dbb37884557695dcd522e0abbaaca7e74fe9c334d9b18e6d1848db97da911c2aa26340b94a2ffc5d7efcbaffc722c45c5a79f
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2014 Marcus Gartner
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
Motion-UNIXSocket
|
2
|
+
=================
|
3
|
+
|
4
|
+
RubyMotion doesn't provide the convenient UNIXSocket class for interacting with
|
5
|
+
Unix domain sockets. Motion-UNIXSocket is a replacement for UNIXSocket built
|
6
|
+
on top of C's socket library and Objective-C's NSFileHandle.
|
7
|
+
|
8
|
+
Installation
|
9
|
+
------------
|
10
|
+
|
11
|
+
Add this to your Gemfile:
|
12
|
+
|
13
|
+
```
|
14
|
+
gem "motion-unixsocket", "~> 0.0.1"
|
15
|
+
```
|
16
|
+
|
17
|
+
Run bundle install:
|
18
|
+
|
19
|
+
```
|
20
|
+
$ bundle install
|
21
|
+
```
|
22
|
+
|
23
|
+
Usage
|
24
|
+
-----
|
25
|
+
|
26
|
+
You can communicate with Unix domain sockets synchronously by reading and
|
27
|
+
writing NSData objects.
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
sock = UNIX::Socket.new('/path/to/socket')
|
31
|
+
msg = "Put a sock in it!\n"
|
32
|
+
sock.write(msg.to_data)
|
33
|
+
|
34
|
+
response = sock.read
|
35
|
+
puts NSString.stringWithUTF8String(response.bytes)
|
36
|
+
# => "Some message sent back."
|
37
|
+
```
|
38
|
+
|
39
|
+
You can read from the socket asynchronously by passing a block to the constructor.
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
sock = UNIX::Socket.new('/path/to/socket') do |data|
|
43
|
+
puts data # => prints and NSData object
|
44
|
+
end
|
45
|
+
|
46
|
+
msg = "Put a sock in it!\n"
|
47
|
+
sock.write(msg.to_data)
|
48
|
+
```
|
49
|
+
|
50
|
+
Support
|
51
|
+
-------
|
52
|
+
|
53
|
+
I've only tested this gem on OS X.
|
54
|
+
|
55
|
+
Status
|
56
|
+
------
|
57
|
+
|
58
|
+
This gem is very young and I'm sure there's some unknown bugs and gotchas. I'll try to fix any issues brought up, but pull requests for bug fixes, optimizations, and API changes are always welcome.
|
59
|
+
|
60
|
+
Ideally the UNIX::Socket class would inherit from IO, but when I tried to piece together what methods needed to be implemented to get the full features of IO, I nearly lost my mind. If anyone can point me in the right direction for this, please let me know.
|
61
|
+
|
62
|
+
Tests
|
63
|
+
-----
|
64
|
+
|
65
|
+
Writing tests for this was a bit tricky. I ended up using an MRI Ruby process to create a socket server. Each test spawns this simple Unix domain socket server which echos a message sent to it and then closes. The tests check that the value written to the socket via UNIX::Socket (RubyMotion version) is the same as the value read back.
|
66
|
+
|
67
|
+
I was unable to get the asynchronous version working in the tests, but it works fine in an application and in the REPL.
|
68
|
+
|
69
|
+
License
|
70
|
+
-------
|
71
|
+
|
72
|
+
MIT License
|
data/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
$:.unshift("/Library/RubyMotion/lib")
|
3
|
+
require 'motion/project/template/osx'
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'bundler'
|
7
|
+
Bundler.require
|
8
|
+
rescue LoadError
|
9
|
+
end
|
10
|
+
|
11
|
+
Motion::Project::App.setup do |app|
|
12
|
+
app.name = 'motion-unixsocket'
|
13
|
+
|
14
|
+
app.include 'sys/socket.h'
|
15
|
+
app.include 'sys/un.h'
|
16
|
+
end
|
data/app/app_delegate.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'unix/version'
|
2
|
+
require 'motion.h'
|
3
|
+
|
4
|
+
unless defined?(Motion::Project::Config)
|
5
|
+
raise "This file must be required within a RubyMotion project Rakefile."
|
6
|
+
end
|
7
|
+
|
8
|
+
Motion::Project::App.setup do |app|
|
9
|
+
Dir.glob(File.join(File.dirname(__FILE__), "unix/**/*.rb")).each do |file|
|
10
|
+
app.files.unshift(file)
|
11
|
+
end
|
12
|
+
|
13
|
+
app.include 'sys/socket.h'
|
14
|
+
app.include 'sys/un.h'
|
15
|
+
end
|
data/lib/unix/socket.rb
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
# A UNIXSocket can interact as a client with Unix domain sockets.
|
2
|
+
module UNIX
|
3
|
+
class Socket
|
4
|
+
|
5
|
+
# Creates a new Unix socket connection.
|
6
|
+
def initialize(path, &block)
|
7
|
+
@path = path
|
8
|
+
@addr = socket_addr(@path)
|
9
|
+
@on_read = block
|
10
|
+
connect
|
11
|
+
end
|
12
|
+
|
13
|
+
# Reads available data on the communication channel and returns it as an
|
14
|
+
# NSData object. If no data is available, the method blocks.
|
15
|
+
def read
|
16
|
+
data = @handle.availableData
|
17
|
+
return data
|
18
|
+
end
|
19
|
+
|
20
|
+
# Writes the given data to the socket.
|
21
|
+
def write(data)
|
22
|
+
@handle.writeData(data)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Closes the socket connection.
|
26
|
+
def close
|
27
|
+
@handle.closeFile
|
28
|
+
@handle = nil
|
29
|
+
end
|
30
|
+
|
31
|
+
# Cleans up the socket.
|
32
|
+
def dealloc
|
33
|
+
notification_center.removeObserver(self)
|
34
|
+
close
|
35
|
+
super
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
# Returns a pointer to a Sockaddr corresponding to the given path.
|
41
|
+
def socket_addr(path)
|
42
|
+
addr = Sockaddr_un.new
|
43
|
+
addr.sun_family = AF_UNIX
|
44
|
+
path.each_char.each_with_index do |c, i|
|
45
|
+
addr.sun_path[i] = c
|
46
|
+
end
|
47
|
+
addr.sun_len = Type.sizeof(Sockaddr_un.type)
|
48
|
+
addr_ptr = Pointer.new(Sockaddr_un.type, 1)
|
49
|
+
addr_ptr[0] = addr
|
50
|
+
addr_ptr.cast!(Sockaddr.type)
|
51
|
+
return addr_ptr
|
52
|
+
end
|
53
|
+
|
54
|
+
# Connects to the socket.
|
55
|
+
# When the socket is read from, the on_read callback will be called.
|
56
|
+
def connect
|
57
|
+
@sockfd = socket(AF_UNIX, SOCK_STREAM, 0)
|
58
|
+
connect(@sockfd, @addr, @addr.value.sa_len)
|
59
|
+
@handle = NSFileHandle.alloc.initWithFileDescriptor(@sockfd)
|
60
|
+
|
61
|
+
if @on_read
|
62
|
+
notification_center.addObserver(self, selector: "msg_received:",
|
63
|
+
name: NSFileHandleReadCompletionNotification,
|
64
|
+
object: @handle)
|
65
|
+
@handle.readInBackgroundAndNotify
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Called when an asynchronous message is received on the socket.
|
70
|
+
# Passes the data on the communication channel to the block provided.
|
71
|
+
def msg_received(notification)
|
72
|
+
data = notification.userInfo.objectForKey(NSFileHandleNotificationDataItem)
|
73
|
+
if data.length > 0
|
74
|
+
NSLog("msg_received")
|
75
|
+
@on_read.call(data)
|
76
|
+
end
|
77
|
+
@handle.readInBackgroundAndNotify
|
78
|
+
end
|
79
|
+
|
80
|
+
# Returns the default notification center.
|
81
|
+
def notification_center
|
82
|
+
NSNotificationCenter.defaultCenter
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
end
|
data/lib/unix/type.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# Contains helper methods for C-struct types.
|
2
|
+
module UNIX
|
3
|
+
module Type
|
4
|
+
extend self
|
5
|
+
|
6
|
+
# Returns the size of a C-struct type.
|
7
|
+
# A replacement for C's sizeof() function.
|
8
|
+
def sizeof(type)
|
9
|
+
size_ptr = Pointer.new(:ulong_long)
|
10
|
+
align_ptr = Pointer.new(:ulong_long)
|
11
|
+
NSGetSizeAndAlignment(type, size_ptr, align_ptr)
|
12
|
+
size_ptr[0]
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
data/lib/unix/version.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/unix/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Marcus Gartner"]
|
6
|
+
gem.email = ["magartner@gmail.com"]
|
7
|
+
gem.description = "A Unix domain socket library for RubyMotion."
|
8
|
+
gem.summary = "A Unix domain socket library for RubyMotion."
|
9
|
+
gem.license = "MIT"
|
10
|
+
gem.homepage = "https://github.com/mgartner/motion-unixsocket"
|
11
|
+
|
12
|
+
gem.files = `git ls-files`.split($\)
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "motion-unixsocket"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = UNIX::VERSION
|
17
|
+
|
18
|
+
gem.add_development_dependency 'rake'
|
19
|
+
gem.add_dependency 'motion.h', '~> 0.0.4'
|
20
|
+
end
|
data/spec/type_spec.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
describe UNIX::Type do
|
2
|
+
|
3
|
+
describe "#sizeof" do
|
4
|
+
it "returns the size of a bool" do
|
5
|
+
UNIX::Type.sizeof('B').should == 1
|
6
|
+
end
|
7
|
+
it "returns the size of an int" do
|
8
|
+
UNIX::Type.sizeof('i').should == 4
|
9
|
+
end
|
10
|
+
it "returns the size of a sockaddr_un" do
|
11
|
+
UNIX::Type.sizeof(Sockaddr_un.type).should == 106
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
describe UNIX::Socket do
|
2
|
+
|
3
|
+
SOCKET_FILE = File.expand_path('../../sock', __FILE__)
|
4
|
+
|
5
|
+
before do
|
6
|
+
system("rm #{SOCKET_FILE}")
|
7
|
+
end
|
8
|
+
|
9
|
+
context "without a block given to the initializer" do
|
10
|
+
it "should write and read data from the socket" do
|
11
|
+
message = "hello\n"
|
12
|
+
Process.spawn("ruby spec_helpers/echo.rb")
|
13
|
+
sleep(0.5)
|
14
|
+
s = UNIX::Socket.new(SOCKET_FILE)
|
15
|
+
s.write(message.to_data)
|
16
|
+
data = s.read
|
17
|
+
response = NSString.stringWithUTF8String(data.bytes)
|
18
|
+
response.should == message
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# TODO: I can't seem to get these tests working. UNIX::Socket works fine with
|
23
|
+
# a block when I use it in the REPL, so this is weird.
|
24
|
+
# context "with a block given to the initializer" do
|
25
|
+
# it "should write and read data from the socket" do
|
26
|
+
# message = "hello\n"
|
27
|
+
# #Process.spawn("ruby spec_helpers/echo.rb")
|
28
|
+
# sleep(0.5)
|
29
|
+
# response = nil
|
30
|
+
# s = UNIX::Socket.new(SOCKET_FILE) do |data|
|
31
|
+
# puts data
|
32
|
+
# response = NSString.stringWithUTF8String(data.bytes)
|
33
|
+
# end
|
34
|
+
# s.write(message.to_data)
|
35
|
+
# sleep(1)
|
36
|
+
# response.should == message
|
37
|
+
# end
|
38
|
+
# end
|
39
|
+
|
40
|
+
end
|
metadata
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: motion-unixsocket
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Marcus Gartner
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-09-12 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rake
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: motion.h
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.0.4
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.0.4
|
41
|
+
description: A Unix domain socket library for RubyMotion.
|
42
|
+
email:
|
43
|
+
- magartner@gmail.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- .gitignore
|
49
|
+
- .travis.yml
|
50
|
+
- Gemfile
|
51
|
+
- LICENSE
|
52
|
+
- README.md
|
53
|
+
- Rakefile
|
54
|
+
- app/app_delegate.rb
|
55
|
+
- lib/motion-unixsocket.rb
|
56
|
+
- lib/unix/socket.rb
|
57
|
+
- lib/unix/type.rb
|
58
|
+
- lib/unix/version.rb
|
59
|
+
- motion-unixsocket.gemspec
|
60
|
+
- spec/type_spec.rb
|
61
|
+
- spec/unixsocket_spec.rb
|
62
|
+
- spec_helpers/echo.rb
|
63
|
+
homepage: https://github.com/mgartner/motion-unixsocket
|
64
|
+
licenses:
|
65
|
+
- MIT
|
66
|
+
metadata: {}
|
67
|
+
post_install_message:
|
68
|
+
rdoc_options: []
|
69
|
+
require_paths:
|
70
|
+
- lib
|
71
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - '>='
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0'
|
81
|
+
requirements: []
|
82
|
+
rubyforge_project:
|
83
|
+
rubygems_version: 2.2.2
|
84
|
+
signing_key:
|
85
|
+
specification_version: 4
|
86
|
+
summary: A Unix domain socket library for RubyMotion.
|
87
|
+
test_files:
|
88
|
+
- spec/type_spec.rb
|
89
|
+
- spec/unixsocket_spec.rb
|