twib 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/.rspec +3 -0
- data/.travis.yml +5 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +37 -0
- data/README.md +51 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/twib.rb +152 -0
- data/lib/twib/interface.rb +23 -0
- data/lib/twib/interfaces/ITwibDebugger.rb +83 -0
- data/lib/twib/interfaces/ITwibDeviceInterface.rb +25 -0
- data/lib/twib/interfaces/ITwibMetaInterface.rb +16 -0
- data/lib/twib/switch/debug.rb +89 -0
- data/lib/twib/version.rb +3 -0
- data/twib.gemspec +25 -0
- metadata +116 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: be083ce5e43cdb183a7548ce6ad0b2eabc77e425
|
4
|
+
data.tar.gz: 58e462f9150b324ac65acdaa12dbc1fb10dc4df9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a58ca6fa102c71854d30b3b2bb4338e6425f59fd05be3392ad660816a617fb82866a5508ff3b50c542b29125ff1c1d76b6a67cee14f8d1e737780304e2835d5a
|
7
|
+
data.tar.gz: f77ef0b936b82b29b2d5e48bc803b85d37e077a7222118ee4d2c6b070f0368331744ce6ef862525b8f7746cb5a1cc75d654f606674959ec9e49cc48906c581a2
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
twib (0.1.0)
|
5
|
+
msgpack
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
diff-lcs (1.3)
|
11
|
+
msgpack (1.2.4)
|
12
|
+
rake (10.5.0)
|
13
|
+
rspec (3.8.0)
|
14
|
+
rspec-core (~> 3.8.0)
|
15
|
+
rspec-expectations (~> 3.8.0)
|
16
|
+
rspec-mocks (~> 3.8.0)
|
17
|
+
rspec-core (3.8.0)
|
18
|
+
rspec-support (~> 3.8.0)
|
19
|
+
rspec-expectations (3.8.1)
|
20
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
21
|
+
rspec-support (~> 3.8.0)
|
22
|
+
rspec-mocks (3.8.0)
|
23
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
24
|
+
rspec-support (~> 3.8.0)
|
25
|
+
rspec-support (3.8.0)
|
26
|
+
|
27
|
+
PLATFORMS
|
28
|
+
ruby
|
29
|
+
|
30
|
+
DEPENDENCIES
|
31
|
+
bundler (~> 1.16)
|
32
|
+
rake (~> 10.0)
|
33
|
+
rspec (~> 3.0)
|
34
|
+
twib!
|
35
|
+
|
36
|
+
BUNDLED WITH
|
37
|
+
1.16.1
|
data/README.md
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
# ruby-twib
|
2
|
+
|
3
|
+
[Twili](https://github.com/misson20000/twili) bridge client for Ruby, providing a way for Ruby applications to send requests to a Twili device via twibd.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'twib'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install twib
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
See the instructions on the [Twili repository](https://github.com/misson20000/twili#twili) for how to set up Twili and twibd.
|
24
|
+
|
25
|
+
First, create a Twib::TwibConnection. There is a convenience method `Twib::TwibConnection::connect_unix`
|
26
|
+
```ruby
|
27
|
+
> tc = Twib::TwibConnection.connect_unix
|
28
|
+
=> #<Twib::TwibConnection:...>
|
29
|
+
```
|
30
|
+
|
31
|
+
After that, you can list the available devices with `TwibConnection#list_devices`, which returns an array of hashes identifying each device.
|
32
|
+
```ruby
|
33
|
+
> tc.list_devices
|
34
|
+
[{"device_id"=>507914862, ...}, ...]
|
35
|
+
```
|
36
|
+
|
37
|
+
Use `TwibConnection#open_device` to get a device's `ITwibDeviceInterface`.
|
38
|
+
```ruby
|
39
|
+
> tc.open_device(507914862)
|
40
|
+
=> #<Twib::Interfaces::ITwibDeviceInterface:...>
|
41
|
+
```
|
42
|
+
|
43
|
+
## Development
|
44
|
+
|
45
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
46
|
+
|
47
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
48
|
+
|
49
|
+
## Contributing
|
50
|
+
|
51
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/misson20000/ruby-twib.
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "twib"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/lib/twib.rb
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
require "socket"
|
2
|
+
require "thread"
|
3
|
+
|
4
|
+
require "twib/version"
|
5
|
+
require "twib/interfaces/ITwibMetaInterface"
|
6
|
+
require "twib/interfaces/ITwibDeviceInterface"
|
7
|
+
|
8
|
+
module Twib
|
9
|
+
class Error < RuntimeError
|
10
|
+
end
|
11
|
+
|
12
|
+
class ResultError < Error
|
13
|
+
def initialize(code)
|
14
|
+
super("0x#{code.to_s(16)}")
|
15
|
+
@code = code
|
16
|
+
end
|
17
|
+
attr_reader :code
|
18
|
+
end
|
19
|
+
|
20
|
+
class Response
|
21
|
+
def initialize(device_id, object_id, result_code, tag, payload, object_ids)
|
22
|
+
@device_id = device_id
|
23
|
+
@object_id = object_id
|
24
|
+
@result_code = result_code
|
25
|
+
@tag = tag
|
26
|
+
@payload = payload
|
27
|
+
@object_ids = object_ids
|
28
|
+
end
|
29
|
+
|
30
|
+
attr_reader :device_id, :object_id, :result_code, :tag, :payload, :object_ids
|
31
|
+
|
32
|
+
def assert_ok
|
33
|
+
if @result_code != 0 then
|
34
|
+
raise ResultError.new(@result_code)
|
35
|
+
end
|
36
|
+
return self
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
class ActiveRequest
|
41
|
+
def initialize(tc, device_id, object_id, command_id, tag, payload, &block)
|
42
|
+
@tc = tc
|
43
|
+
@device_id = device_id
|
44
|
+
@object_id = object_id
|
45
|
+
@command_id = command_id
|
46
|
+
@tag = tag
|
47
|
+
@payload = payload
|
48
|
+
@condvar = ConditionVariable.new
|
49
|
+
@cb = block
|
50
|
+
@response = nil
|
51
|
+
end
|
52
|
+
|
53
|
+
def respond(response) # expects to be synchronized by @tc.mutex
|
54
|
+
@response = response
|
55
|
+
@condvar.broadcast
|
56
|
+
if @cb then
|
57
|
+
@tc.cb_queue.push([@cb, response])
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def wait
|
62
|
+
@tc.mutex.synchronize do
|
63
|
+
while @response == nil do
|
64
|
+
@condvar.wait(@tc.mutex)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
return @response
|
68
|
+
end
|
69
|
+
|
70
|
+
def wait_ok
|
71
|
+
wait.assert_ok
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
class TwibConnection
|
76
|
+
def self.connect_unix
|
77
|
+
return self.new(UNIXSocket.new("/var/run/twibd.sock"))
|
78
|
+
end
|
79
|
+
|
80
|
+
def initialize(socket)
|
81
|
+
@socket = socket
|
82
|
+
@itmi = Interfaces::ITwibMetaInterface.new(self, 0, 0)
|
83
|
+
@alive = true
|
84
|
+
@active_requests = {}
|
85
|
+
@mutex = Mutex.new
|
86
|
+
@thread = Thread.new do
|
87
|
+
loop do
|
88
|
+
header = @socket.recv(32)
|
89
|
+
header = header.unpack("L<L<L<L<Q<L<")
|
90
|
+
|
91
|
+
payload = String.new
|
92
|
+
object_ids = []
|
93
|
+
if header[4] > 0 then
|
94
|
+
payload = @socket.recv(header[4]) # payload size
|
95
|
+
end
|
96
|
+
if header[5] > 0 then
|
97
|
+
object_ids = @socket.recv(header[5] * 4).unpack("L<*") # object IDs
|
98
|
+
end
|
99
|
+
|
100
|
+
rs = Response.new(header[0], header[1], header[2], header[3], payload, object_ids)
|
101
|
+
@mutex.synchronize do
|
102
|
+
rq = @active_requests.delete(rs.tag)
|
103
|
+
if !rq then
|
104
|
+
puts "WARNING: got response for bad tag"
|
105
|
+
end
|
106
|
+
rq.respond(rs)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
@cb_queue = Queue.new
|
112
|
+
@cb_thread = Thread.new do # to avoid deadlocks on I/O thread, we execute callbacks here
|
113
|
+
while @alive do
|
114
|
+
cb, response = @cb_queue.pop
|
115
|
+
cb.call(response)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
attr_reader :mutex
|
121
|
+
attr_reader :cb_queue
|
122
|
+
|
123
|
+
def close
|
124
|
+
@alive = false
|
125
|
+
@socket.close
|
126
|
+
@thread.join
|
127
|
+
end
|
128
|
+
|
129
|
+
def send(device_id, object_id, command_id, payload, &block)
|
130
|
+
tag = rand(0xffffffff)
|
131
|
+
|
132
|
+
rq = ActiveRequest.new(self, device_id, object_id, command_id, tag, payload, &block)
|
133
|
+
@active_requests[tag] = rq
|
134
|
+
|
135
|
+
message = [device_id, object_id, command_id, tag, payload.size, 0, 0].pack("L<L<L<L<Q<L<L<") + payload
|
136
|
+
sz = @socket.send(message, 0)
|
137
|
+
if sz < message.size then
|
138
|
+
raise "couldn't send entire message"
|
139
|
+
end
|
140
|
+
|
141
|
+
return rq
|
142
|
+
end
|
143
|
+
|
144
|
+
def list_devices
|
145
|
+
@itmi.list_devices
|
146
|
+
end
|
147
|
+
|
148
|
+
def open_device(device_id)
|
149
|
+
return Interfaces::ITwibDeviceInterface.new(self, device_id, 0)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Twib
|
2
|
+
class Interface
|
3
|
+
def initialize(connection, device_id, object_id)
|
4
|
+
@connection = connection
|
5
|
+
@device_id = device_id
|
6
|
+
@object_id = object_id
|
7
|
+
|
8
|
+
# object id 0 is special
|
9
|
+
#if @object_id != 0 then
|
10
|
+
# ObjectSpace.define_finalizer(self, self.class.finalize(connection, device_id, object_id))
|
11
|
+
#end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.finalize(connection, device_id, object_id)
|
15
|
+
# send close request
|
16
|
+
#connection.send_sync(device_id, object_id, 0xffffffff, String.new)
|
17
|
+
end
|
18
|
+
|
19
|
+
def send(command_id, payload=String.new, &block)
|
20
|
+
@connection.send(@device_id, @object_id, command_id, payload, &block)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require "twib/interface.rb"
|
2
|
+
require "twib/switch/debug.rb"
|
3
|
+
|
4
|
+
module Twib
|
5
|
+
module Interfaces
|
6
|
+
class ITwibDebugger < Interface
|
7
|
+
module Command
|
8
|
+
QUERY_MEMORY = 10
|
9
|
+
READ_MEMORY = 11
|
10
|
+
WRITE_MEMORY = 12
|
11
|
+
LIST_THREADS = 13
|
12
|
+
GET_DEBUG_EVENT = 14
|
13
|
+
GET_THREAD_CONTEXT = 15
|
14
|
+
BREAK_PROCESS = 16
|
15
|
+
CONTINUE_DEBUG_EVENT = 17
|
16
|
+
SET_THREAD_CONTEXT = 18
|
17
|
+
GET_NSO_INFOS = 19
|
18
|
+
WAIT_EVENT = 20
|
19
|
+
end
|
20
|
+
|
21
|
+
def query_memory(addr)
|
22
|
+
Hash[
|
23
|
+
[:base, :size, :memory_type, :memory_attribute,
|
24
|
+
:permission, :device_ref_count, :ipc_ref_count].zip(
|
25
|
+
send(Command::QUERY_MEMORY, [addr].pack("Q<")).wait_ok.payload.unpack("Q<Q<L<L<L<L<L<"))]
|
26
|
+
end
|
27
|
+
|
28
|
+
def read_memory(addr, size)
|
29
|
+
send(Command::READ_MEMORY, [addr, size].pack("Q<Q<")).wait_ok.payload
|
30
|
+
end
|
31
|
+
|
32
|
+
def write_memory(addr, string)
|
33
|
+
send(Command::WRITE_MEMORY, [addr].pack("Q<") + string).wait_ok
|
34
|
+
end
|
35
|
+
|
36
|
+
def list_threads
|
37
|
+
raise "nyi"
|
38
|
+
end
|
39
|
+
|
40
|
+
def get_debug_event
|
41
|
+
rs = send(Command::GET_DEBUG_EVENT).wait
|
42
|
+
if rs.result_code == 0x8c01 then # no debug events left
|
43
|
+
return nil
|
44
|
+
end
|
45
|
+
return Switch::Debug::Event::Event.unpack(rs.payload)
|
46
|
+
end
|
47
|
+
|
48
|
+
def get_thread_context(thread_id)
|
49
|
+
raise "nyi"
|
50
|
+
end
|
51
|
+
|
52
|
+
def break_process
|
53
|
+
raise "nyi"
|
54
|
+
end
|
55
|
+
|
56
|
+
def continue_debug_event(flags, thread_ids=[])
|
57
|
+
send(Command::CONTINUE_DEBUG_EVENT, ([flags] + thread_ids).pack("L<Q<*")).wait_ok
|
58
|
+
nil
|
59
|
+
end
|
60
|
+
|
61
|
+
def set_thread_context(thread_id)
|
62
|
+
raise "nyi"
|
63
|
+
end
|
64
|
+
|
65
|
+
def get_nso_infos
|
66
|
+
response = send(Command::GET_NSO_INFOS).wait_ok.payload
|
67
|
+
count = response.unpack("Q<")[0]
|
68
|
+
count.times.map do |i|
|
69
|
+
Hash[
|
70
|
+
[:base, :size, :build_id].zip(response[8 + 0x30 * i, 0x30].unpack("Q<Q<a32"))]
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def wait_event_async(&block)
|
75
|
+
send(Command::WAIT_EVENT, String.new, &block)
|
76
|
+
end
|
77
|
+
|
78
|
+
def wait_event
|
79
|
+
send(Command::WAIT_EVENT).wait_ok
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require "twib/interface.rb"
|
2
|
+
|
3
|
+
require "twib/interfaces/ITwibDebugger.rb"
|
4
|
+
|
5
|
+
module Twib
|
6
|
+
module Interfaces
|
7
|
+
class ITwibDeviceInterface < Interface
|
8
|
+
module Command
|
9
|
+
RUN = 10
|
10
|
+
REBOOT = 11
|
11
|
+
COREDUMP = 12
|
12
|
+
TERMINATE = 13
|
13
|
+
LIST_PROCESSES = 14
|
14
|
+
UPGRADE_TWILI = 15
|
15
|
+
IDENTIFY = 16
|
16
|
+
LIST_NAMED_PIPES = 17
|
17
|
+
OPEN_NAMED_PIPE = 18
|
18
|
+
OPEN_ACTIVE_DEBUGGER = 19
|
19
|
+
end
|
20
|
+
def open_active_debugger(pid)
|
21
|
+
ITwibDebugger.new(@connection, @device_id, send(Command::OPEN_ACTIVE_DEBUGGER, [pid].pack("Q<")).wait_ok.object_ids[0])
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "msgpack"
|
2
|
+
|
3
|
+
require "twib/interface.rb"
|
4
|
+
|
5
|
+
module Twib
|
6
|
+
module Interfaces
|
7
|
+
class ITwibMetaInterface < Interface
|
8
|
+
module Command
|
9
|
+
LIST_DEVICES = 10
|
10
|
+
end
|
11
|
+
def list_devices
|
12
|
+
MessagePack.unpack(send(Command::LIST_DEVICES).wait_ok.payload)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
module Twib
|
2
|
+
module Switch
|
3
|
+
module Debug
|
4
|
+
module Event
|
5
|
+
class Event
|
6
|
+
def self.unpack(pack)
|
7
|
+
event_type, flags, thread_id, specific = pack.unpack("L<L<Q<a*")
|
8
|
+
case event_type
|
9
|
+
when AttachProcess::TYPE
|
10
|
+
return AttachProcess.new(flags, thread_id, specific)
|
11
|
+
when AttachThread::TYPE
|
12
|
+
return AttachThread.new(flags, thread_id, specific)
|
13
|
+
when ExitProcess::TYPE
|
14
|
+
return ExitProcess.new(flags, thread_id, specific)
|
15
|
+
when ExitThread::TYPE
|
16
|
+
return ExitThread.new(flags, thread_id, specific)
|
17
|
+
when Exception::TYPE
|
18
|
+
return Exception.new(flags, thread_id, specific)
|
19
|
+
else
|
20
|
+
raise "unknown debug event type: #{event_type}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
def initialize(flags, thread_id, specific)
|
24
|
+
@flags = flags
|
25
|
+
@thread_id = thread_id
|
26
|
+
unpack_specific(specific)
|
27
|
+
end
|
28
|
+
attr_reader :flags
|
29
|
+
attr_reader :thread_id
|
30
|
+
end
|
31
|
+
|
32
|
+
class AttachProcess < Event
|
33
|
+
TYPE = 0
|
34
|
+
def unpack_specific(pack)
|
35
|
+
@title_id, @process_id, @process_name, @mmu_flags = pack.unpack("Q<Q<Z12L<")
|
36
|
+
end
|
37
|
+
def event_type
|
38
|
+
:attach_process
|
39
|
+
end
|
40
|
+
attr_reader :title_id, :process_id, :process_name, :mmu_flags
|
41
|
+
end
|
42
|
+
|
43
|
+
class AttachThread < Event
|
44
|
+
TYPE = 1
|
45
|
+
def unpack_specific(pack)
|
46
|
+
@thread_id, @tls, @entrypoint = pack.unpack("Q<Q<Q<")
|
47
|
+
end
|
48
|
+
def event_type
|
49
|
+
:attach_thread
|
50
|
+
end
|
51
|
+
attr_reader :thread_id, :tls, :entrypoint
|
52
|
+
end
|
53
|
+
|
54
|
+
class ExitProcess < Event
|
55
|
+
TYPE = 2
|
56
|
+
def unpack_specific(pack)
|
57
|
+
@type = pack.unpack("L<")
|
58
|
+
end
|
59
|
+
def event_type
|
60
|
+
:exit_process
|
61
|
+
end
|
62
|
+
attr_reader :type
|
63
|
+
end
|
64
|
+
|
65
|
+
class ExitThread < Event
|
66
|
+
TYPE = 3
|
67
|
+
def unpack_specific(pack)
|
68
|
+
@type = pack.unpack("L<")
|
69
|
+
end
|
70
|
+
def event_type
|
71
|
+
:exit_thread
|
72
|
+
end
|
73
|
+
attr_reader :type
|
74
|
+
end
|
75
|
+
|
76
|
+
class Exception < Event
|
77
|
+
TYPE = 4
|
78
|
+
def unpack_specific(pack)
|
79
|
+
@type, @fault_register, @specific = pack.unpack("L<Q<a*")
|
80
|
+
end
|
81
|
+
def event_type
|
82
|
+
:exception
|
83
|
+
end
|
84
|
+
attr_reader :type, :fault_register, :specific
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
data/lib/twib/version.rb
ADDED
data/twib.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
lib = File.expand_path("../lib", __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require "twib/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "twib"
|
7
|
+
spec.version = Twib::VERSION
|
8
|
+
spec.authors = ["misson20000"]
|
9
|
+
spec.email = ["xenotoad@xenotoad.net"]
|
10
|
+
|
11
|
+
spec.summary = "Twili bridge client for Ruby"
|
12
|
+
spec.homepage = "https://github.com/misson20000/ruby-twib/"
|
13
|
+
|
14
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
15
|
+
f.match(%r{^(test|spec|features)/})
|
16
|
+
end
|
17
|
+
spec.bindir = "exe"
|
18
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.16"
|
22
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
23
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
24
|
+
spec.add_dependency "msgpack"
|
25
|
+
end
|
metadata
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: twib
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- misson20000
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-09-02 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.16'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.16'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: msgpack
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description:
|
70
|
+
email:
|
71
|
+
- xenotoad@xenotoad.net
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- ".gitignore"
|
77
|
+
- ".rspec"
|
78
|
+
- ".travis.yml"
|
79
|
+
- Gemfile
|
80
|
+
- Gemfile.lock
|
81
|
+
- README.md
|
82
|
+
- Rakefile
|
83
|
+
- bin/console
|
84
|
+
- bin/setup
|
85
|
+
- lib/twib.rb
|
86
|
+
- lib/twib/interface.rb
|
87
|
+
- lib/twib/interfaces/ITwibDebugger.rb
|
88
|
+
- lib/twib/interfaces/ITwibDeviceInterface.rb
|
89
|
+
- lib/twib/interfaces/ITwibMetaInterface.rb
|
90
|
+
- lib/twib/switch/debug.rb
|
91
|
+
- lib/twib/version.rb
|
92
|
+
- twib.gemspec
|
93
|
+
homepage: https://github.com/misson20000/ruby-twib/
|
94
|
+
licenses: []
|
95
|
+
metadata: {}
|
96
|
+
post_install_message:
|
97
|
+
rdoc_options: []
|
98
|
+
require_paths:
|
99
|
+
- lib
|
100
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ">="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
requirements: []
|
111
|
+
rubyforge_project:
|
112
|
+
rubygems_version: 2.6.12
|
113
|
+
signing_key:
|
114
|
+
specification_version: 4
|
115
|
+
summary: Twili bridge client for Ruby
|
116
|
+
test_files: []
|