motion-unixsocket 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,19 @@
1
+ .repl_history
2
+ build
3
+ tags
4
+ app/pixate_code.rb
5
+ resources/*.nib
6
+ resources/*.momd
7
+ resources/*.storyboardc
8
+ .DS_Store
9
+ nbproject
10
+ .redcar
11
+ #*#
12
+ *~
13
+ *.sw[po]
14
+ .eprj
15
+ .sass-cache
16
+ .idea
17
+ .dat*.*
18
+ sock
19
+ Gemfile.lock
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ language: objective-c
2
+ before_install:
3
+ - sudo chown -R travis ~/Library/RubyMotion
4
+ - mkdir -p ~/Library/RubyMotion/build
5
+
6
+ script: bundle exec rake spec
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
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
@@ -0,0 +1,5 @@
1
+ class AppDelegate
2
+ def applicationDidFinishLaunching(notification)
3
+ return true if RUBYMOTION_ENV == 'test'
4
+ end
5
+ end
@@ -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
@@ -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
@@ -0,0 +1,3 @@
1
+ module UNIX
2
+ VERSION = "0.0.1"
3
+ end
@@ -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
@@ -0,0 +1,7 @@
1
+ require 'socket'
2
+
3
+ UNIXServer.open("sock") do |server|
4
+ s = server.accept
5
+ msg = s.readline
6
+ s.puts msg
7
+ 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