tinydtls 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 2e326a7a3bf6820d5596c83553eb9d0cd9c2309ffbb00e24d3045e5a2b69e8c5
4
+ data.tar.gz: b446f4a18ca71e313bf5ad06d651e89442ac847526ac181b826fa9fac1d1d99c
5
+ SHA512:
6
+ metadata.gz: 3e1a1a8fe929488102db4cdf3d2d0ef3ec9dec8518fb74d00ed29afb868ea60010d7ee0b5fe64300a61f6b0cd7633293ccca4cdef4bb3122f6e2e70a27118319
7
+ data.tar.gz: 5b873f6d31d0ce0ba9cc3f0795bc8a95b078761ceab382c719acb3a19a1de2a3231873b4cdd86bc419db79682ea154532928261b3503d6906bd58e7c810906c1
data/lib/tinydtls.rb ADDED
@@ -0,0 +1,16 @@
1
+ require "socket"
2
+ require "ffi"
3
+
4
+ require "tinydtls/wrapper"
5
+ require "tinydtls/context"
6
+ require "tinydtls/session"
7
+ require "tinydtls/security_conf"
8
+ require "tinydtls/session_manager"
9
+ require "tinydtls/udpsocket"
10
+
11
+ module TinyDTLS
12
+ # Map used to map `object_ids` passed as void pointers to the tinydtls
13
+ # callback functions to actually ruby UDPSockets. This is neccessary
14
+ # since we can't pass pointers to ruby objects to C functions.
15
+ CONTEXT_MAP = Hash.new
16
+ end
@@ -0,0 +1,35 @@
1
+ module TinyDTLS
2
+ # The class Context stores all per-connection information,
3
+ # it is exclusively used in the `TinyDTLS::CONTEXT_MAP`.
4
+ class Context
5
+ # The method used for sending data on the socket.
6
+ attr_reader :sendfn
7
+
8
+ # The queue used for communication with the receive thread.
9
+ attr_reader :queue
10
+
11
+ # An instance of the security configuration class.
12
+ attr_reader :secconf
13
+
14
+ # Create a new instance of this class with a given function to send
15
+ # message on the transport layer, a queue for storing received
16
+ # messages and a security configuration containing a key to identity
17
+ # mapping.
18
+ def initialize(sendfn, queue, secconf)
19
+ @sendfn = sendfn
20
+ @queue = queue
21
+ @secconf = secconf
22
+ end
23
+
24
+ # Create a new instance of this class from a pointer to a `struct
25
+ # dtls_context_t`. Such a pointer is, for instance, passed to the
26
+ # various tinydtls callback functions.
27
+ #
28
+ # The `struct dtls_context_t` which the given pointer points to must
29
+ # have been created by TinyDTLS::UDPSocket#initialize.
30
+ def self.from_ptr(ptr)
31
+ obj = Wrapper::DTLSContextStruct.new(ptr)
32
+ return CONTEXT_MAP[Wrapper::dtls_get_app_data(obj).to_i]
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,83 @@
1
+ module TinyDTLS
2
+ # This class is used to map user identity for pre-shared keys to their
3
+ # actual keys. It provides an implementation of the `get_psk_info`
4
+ # function pointer used in the `dtls_handler_t` struct which is used
5
+ # by tinydtls to retrieve keys and identities.
6
+ #
7
+ # XXX: Currently this function doesn't map IP address to keys/identities.
8
+ class SecurityConfig
9
+ # Implementation of the `get_psk_info` function pointer as used by
10
+ # the `dtls_handler_t` struct.
11
+ #
12
+ # If tinydtls requests a key for a given identity the key is
13
+ # returned if the identity exists. If no identity was specified the
14
+ # #default_key is returned.
15
+ #
16
+ # If tinydtls requests an id the #default_id is always returned.
17
+ #
18
+ # TODO: It would be nice to return an id depending on the
19
+ # `session_t` passad to this callback.
20
+ GetPSKInfo = Proc.new do |ctx, sess, type, desc, dlen, result, rlen|
21
+ secconf = TinyDTLS::Context.from_ptr(ctx).secconf
22
+ if desc.null?
23
+ key = secconf.default_key
24
+ end
25
+
26
+ if type == :DTLS_PSK_KEY
27
+ key ||= secconf.get_key(desc.read_string(dlen))
28
+ if key.nil?
29
+ Wrapper::dtls_alert_fatal_create(
30
+ Wrapper::Alert[:DTLS_ALERT_DECRYPT_ERROR])
31
+ elsif key.bytesize > rlen
32
+ Wrapper::dtls_alert_fatal_create(
33
+ Wrapper::Alert[:DTLS_ALERT_INTERNAL_ERROR])
34
+ else
35
+ result.put_bytes(0, key)
36
+ key.bytesize
37
+ end
38
+ elsif type == :DTLS_PSK_IDENTITY
39
+ identity = secconf.default_id
40
+ result.put_bytes(0, identity)
41
+ identity.bytesize
42
+ else
43
+ 0
44
+ end
45
+ end
46
+
47
+ # Create a new instance of this class. A #default_key and a
48
+ # #default_id can be optionally specified. If they are not specified
49
+ # the first key/identity added is used as the default value.
50
+ def initialize(default_id = nil, default_key = nil)
51
+ @default_id = default_id
52
+ @default_key = default_key
53
+
54
+ @identity_map = Hash.new
55
+ end
56
+
57
+ # Adds a security configuration for the given identity.
58
+ def add_client(id, key)
59
+ @identity_map[id] = key
60
+ end
61
+
62
+ # Retrieves the key associated with the given identity.
63
+ def get_key(id)
64
+ @identity_map[id]
65
+ end
66
+
67
+ def default_id
68
+ if @default_id.nil?
69
+ @identity_map.to_a.first.first
70
+ else
71
+ @default_id
72
+ end
73
+ end
74
+
75
+ def default_key
76
+ if @default_key.nil?
77
+ @identity_map.to_a.first.last
78
+ else
79
+ @default_key
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,47 @@
1
+ module TinyDTLS
2
+ # This class offers a higher-level abstraction for the `session_t` type.
3
+ class Session
4
+ attr_reader :addrinfo
5
+
6
+ # Creates a new instance of this class from the given Addrinfo.
7
+ def initialize(addrinfo)
8
+ @addrinfo = addrinfo
9
+ unless @addrinfo.is_a? Addrinfo
10
+ raise TypeError
11
+ end
12
+
13
+ sockaddr = @addrinfo.to_sockaddr
14
+ @session = Wrapper::dtls_new_session(sockaddr, sockaddr.bytesize)
15
+ if @session.null?
16
+ raise Errno::ENOMEM
17
+ end
18
+ end
19
+
20
+ # Creates a new instance of this class from a pointer to a
21
+ # `session_t` tinydtls type. Such a pointer is, for instance, passed
22
+ # to the various tinydtls callback functions.
23
+ def self.from_ptr(ptr)
24
+ lenptr = Wrapper::SocklenPtr.new
25
+ sockaddr = Wrapper::dtls_session_addr(ptr, lenptr)
26
+
27
+ addrinfo = Addrinfo.new(sockaddr.read_string(lenptr[:value]))
28
+ return Session.new(addrinfo)
29
+ end
30
+
31
+ # Converts the object into a C pointer to a `session_t` tinydtls
32
+ # type. This pointer can be passed to various functions provided by
33
+ # TinyDTLS::Wrapper.
34
+ def to_ptr
35
+ @session
36
+ end
37
+
38
+ # Frees all resources associated with the underlying `session_t`
39
+ # tinydtls type and reset any existing connections.
40
+ def destroy!(ctx)
41
+ peer = Wrapper::dtls_get_peer(ctx, @session)
42
+ unless peer.null?
43
+ Wrapper::dtls_reset_peer(ctx, peer)
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,88 @@
1
+ module TinyDTLS
2
+ # This class is used to manage established tinydtls sessions. It
3
+ # stores instances of the TinyDTLS::Session class.
4
+ #
5
+ # While memory allocated for sessions is automatically freed by
6
+ # tinydtls, if it receive an alert from the peer associated with that
7
+ # session, memory isn't freed if the peer doesn't send an alert.
8
+ # Therefore this class starts a background thread automatically
9
+ # freeing memory associated with sessions which haven't been used
10
+ # since a specified duration.
11
+ class SessionManager
12
+ # Default timeout for the cleanup thread in seconds.
13
+ DEFAULT_TIMEOUT = (5 * 60).freeze
14
+
15
+ attr_accessor :timeout
16
+
17
+ # Creates a new instance of this class. A tinydtls `context_t`
18
+ # pointer is required to free sessions in the background thread.
19
+ def initialize(ctx, timeout = DEFAULT_TIMEOUT)
20
+ @store = {}
21
+ @mutex = Mutex.new
22
+ @timeout = timeout
23
+
24
+ start_thread(ctx)
25
+ end
26
+
27
+ # Retrieve a session from the session manager.
28
+ def [](addrinfo, &f)
29
+ unless addrinfo.is_a? Addrinfo
30
+ raise TypeError
31
+ end
32
+
33
+ key = addrinfo.getnameinfo
34
+ if @store.has_key? key
35
+ sess, _ = @store[key]
36
+ else
37
+ sess = Session.new(addrinfo)
38
+ @store[key] = [sess, true]
39
+ end
40
+
41
+ @mutex.synchronize { f.call(sess) }
42
+ end
43
+
44
+ # Frees all ressources associated with this class.
45
+ def destroy!
46
+ @mutex.lock
47
+ @store.clear
48
+ @thread.kill
49
+ end
50
+
51
+ private
52
+
53
+ # Creates a thread responsible for freeing ressources assigned to
54
+ # stale connection. This thread implements the clock hand algorithm
55
+ # as described in Modern Operating Systems, p. 212.
56
+ #
57
+ # The thread is only created once.
58
+ def start_thread(ctx)
59
+ @thread ||= Thread.new do
60
+ while true
61
+ # XXX: How does concurrent access to variables work in ruby?
62
+ # as known as: Is this a concurrency problems since the value
63
+ # of @timeout might be changed by a different thread since an
64
+ # attr_accessor for it is declared.
65
+ sleep @timeout
66
+
67
+ @mutex.lock
68
+ @store.transform_values! do |value|
69
+ sess, used = value
70
+ if used
71
+ [sess, !used]
72
+ else # Not used since we've been here last time → free resources
73
+ sess.destroy!(ctx)
74
+ nil
75
+ end
76
+ end
77
+
78
+ # We can't delete elements from the map in the #transform_values!
79
+ # block, we just assign nil to them. Thus we need to filter
80
+ # the map again here.
81
+ @store.reject! { |_, v| v.nil? }
82
+
83
+ @mutex.unlock
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,206 @@
1
+ module TinyDTLS
2
+ # This class implements a DTLS socket on top of a ruby UDPSocket. It
3
+ # isn't currently nowhere near being API compatible with the ruby
4
+ # UDPSocket. Being 100% backwards compatible with the ruby UDPSocket
5
+ # is not possible to to tinydtls internals. For instance we can't
6
+ # properly implement IO#select. It should thus be considered if it is
7
+ # really a good idea to extend the ruby UDPSocket in the long run.
8
+ #
9
+ # Basic send and receive methods are implemented and should work.
10
+ class UDPSocket < ::UDPSocket
11
+ Write = Proc.new do |ctx, sess, buf, len|
12
+ addrinfo = Session.from_ptr(sess).addrinfo
13
+
14
+ ctxobj = TinyDTLS::Context.from_ptr(ctx)
15
+ ctxobj.sendfn.call(buf.read_string(len),
16
+ Socket::MSG_DONTWAIT,
17
+ addrinfo.ip_address, addrinfo.ip_port)
18
+ end
19
+
20
+ Read = Proc.new do |ctx, sess, buf, len|
21
+ addrinfo = Session.from_ptr(sess).addrinfo
22
+
23
+ # We need to perform a reverse lookup here because
24
+ # the #recvfrom function needs to return the DNS
25
+ # hostname.
26
+ sender = Socket.getaddrinfo(addrinfo.ip_address,
27
+ addrinfo.ip_port, nil, :DGRAM,
28
+ 0, 0, true).first
29
+
30
+ ctxobj = TinyDTLS::Context.from_ptr(ctx)
31
+ ctxobj.queue.push([buf.read_string(len), sender])
32
+
33
+ # It is unclear to me why this callback even needs a return value,
34
+ # the `tests/dtls-client.c` program in the tinydtls repository
35
+ # simply uses 0 as a return value, so let's do that as well.
36
+ 0
37
+ end
38
+
39
+ def initialize(address_family = Socket::AF_INET, timeout = nil)
40
+ super(address_family)
41
+ Wrapper::dtls_init
42
+
43
+ @timeout = timeout.freeze
44
+ @queue = Queue.new
45
+ @family = address_family
46
+ @sendfn = method(:send).super_method
47
+ @secconf = SecurityConfig.new
48
+
49
+ id = object_id
50
+ CONTEXT_MAP[id] = TinyDTLS::Context.new(@sendfn, @queue, @secconf)
51
+
52
+ cptr = Wrapper::dtls_new_context(FFI::Pointer.new(id))
53
+ @ctx = Wrapper::DTLSContextStruct.new(cptr)
54
+
55
+ if timeout.nil?
56
+ @sessions = SessionManager.new(@ctx)
57
+ else
58
+ @sessions = SessionManager.new(@ctx, timeout)
59
+ end
60
+
61
+ @handler = Wrapper::DTLSHandlerStruct.new
62
+ @handler[:write] = UDPSocket::Write
63
+ @handler[:read] = UDPSocket::Read
64
+ @handler[:get_psk_info] = SecurityConfig::GetPSKInfo
65
+ Wrapper::dtls_set_handler(@ctx, @handler)
66
+ end
67
+
68
+ def add_client(id, key)
69
+ @secconf.add_client(id, key)
70
+ end
71
+
72
+ def bind(host, port)
73
+ super(host, port)
74
+ start_thread
75
+ end
76
+
77
+ # TODO: close_{read,write}
78
+
79
+ def close
80
+ @sessions.destroy!
81
+ @thread.kill unless @thread.nil?
82
+
83
+ # DTLS free context sends messages to peers so we need to
84
+ # call it before we actually close the underlying socket.
85
+ Wrapper::dtls_free_context(@ctx)
86
+ super
87
+
88
+ # Assuming the @thread is already stopped at this point
89
+ # we can safely access the CONTEXT_MAP without running
90
+ # into any kind of concurrency problems.
91
+ CONTEXT_MAP.delete(object_id)
92
+ end
93
+
94
+ def connect(host, port)
95
+ @defhost = host
96
+ @defport = port
97
+ end
98
+
99
+ def recvfrom(len = -1, flags = 0)
100
+ ary = @queue.pop
101
+ return [byteslice(ary.first, len), ary.last]
102
+ end
103
+
104
+ def recvfrom_nonblock(len = -1, flag = 0, outbuf = nil, exception: true)
105
+ ary = nil
106
+ begin
107
+ ary = @queue.pop(true)
108
+ rescue ThreadError
109
+ if exception
110
+ raise IO::EAGAINWaitReadable
111
+ else
112
+ return :wait_readable
113
+ end
114
+ end
115
+
116
+ pay = byteslice(ary.first, len)
117
+ unless outbuf.nil?
118
+ outbuf << pay
119
+ end
120
+
121
+ return [pay, ary.last]
122
+ end
123
+
124
+ # TODO: The recvmsg functions only implement a subset of the
125
+ # functionallity of the UDP socket class, e.g. they don't return
126
+ # ancillary data.
127
+
128
+ def recvmsg(maxmesglen = nil, flags = 0, maxcontrollen = nil, opts = {})
129
+ mesg, sender = recvfrom(maxmesglen.nil? ? -1 : maxmesglen, flags)
130
+ return [mesg, to_addrinfo(*sender), 0, nil]
131
+ end
132
+
133
+ def recvmsg_nonblock(maxdatalen = nil, flags = 0, maxcontrollen = nil, opts = {})
134
+ mesg, sender = recvfrom_nonblock(maxdatalen.nil? ? -1 : maxdatalen, flags)
135
+ return [mesg, to_addrinfo(*sender), 0, nil]
136
+ end
137
+
138
+ def send(mesg, flags, host = nil, port = nil)
139
+ start_thread
140
+
141
+ if host.nil? and port.nil?
142
+ if @defport.nil? or @defhost.nil?
143
+ raise Errno::EDESTADDRREQ
144
+ end
145
+
146
+ host = @defhost
147
+ port = @defport
148
+ elsif port.nil? # host is not nil and must be a sockaddr_to
149
+ port, host = Socket.unpack_sockaddr_in(host)
150
+ end
151
+
152
+ addr = Addrinfo.getaddrinfo(host, port, nil, :DGRAM).first
153
+
154
+ # If a new thread has been started above a new handshake needs to
155
+ # be performed by it. We need to block here until the handshake
156
+ # was completed.
157
+ #
158
+ # The current approach is calling `Wrapper::dtls_write` until it
159
+ # succeeds which is suboptimal because it doesn't take into
160
+ # account that the handshake may fail.
161
+ until (res = dtls_send(addr, mesg)) > 0
162
+ sleep 1
163
+ end
164
+
165
+ return res
166
+ end
167
+
168
+ private
169
+
170
+ def to_addrinfo(*args)
171
+ af, port, _, addr = args
172
+ Addrinfo.getaddrinfo(addr, port, af, :DGRAM).first
173
+ end
174
+
175
+ def byteslice(str, len)
176
+ return len >= 0 ? str.byteslice(0, len) : str
177
+ end
178
+
179
+ # Sends a dtls message to a specified address. It also takes care
180
+ # of locking the session manager and is thus thread-safe.
181
+ def dtls_send(addr, mesg)
182
+ @sessions[addr] do |sess|
183
+ res = Wrapper::dtls_write(@ctx, sess.to_ptr, mesg, mesg.bytesize)
184
+ res == -1 ? raise(Errno::EIO) : res
185
+ end
186
+ end
187
+
188
+ # Creates a thread responsible for reading from reciving messages
189
+ # from the underlying socket and passing them to tinydtls.
190
+ #
191
+ # The thread is only created once.
192
+ def start_thread
193
+ @thread ||= Thread.new do
194
+ while true
195
+ data, addr = method(:recvfrom).super_method
196
+ .call(Wrapper::DTLS_MAX_BUF)
197
+ addrinfo = to_addrinfo(*addr)
198
+
199
+ @sessions[addrinfo] do |sess|
200
+ Wrapper::dtls_handle_message(@ctx, sess.to_ptr, data, data.bytesize)
201
+ end
202
+ end
203
+ end
204
+ end
205
+ end
206
+ end
@@ -0,0 +1,125 @@
1
+ module TinyDTLS
2
+ # This module provides a low level FFI wrapper for the relevant
3
+ # tinydtls functions. It might be subject to change thus it is highly
4
+ # recommended to use the high level abstraction layer instead.
5
+ module Wrapper
6
+ extend FFI::Library
7
+ ffi_lib "libtinydtls.so"
8
+
9
+ # Constants defined as macros in the tinydtls header files
10
+ DTLS_COOKIE_SECRET_LENGTH = 12
11
+ DTLS_MAX_BUF = 1400
12
+
13
+ Alert = enum(
14
+ :DTLS_ALERT_CLOSE_NOTIFY, 0,
15
+ :DTLS_ALERT_UNEXPECTED_MESSAGE, 10,
16
+ :DTLS_ALERT_BAD_RECORD_MAC, 20,
17
+ :DTLS_ALERT_RECORD_OVERFLOW, 22,
18
+ :DTLS_ALERT_DECOMPRESSION_FAILURE, 30,
19
+ :DTLS_ALERT_HANDSHAKE_FAILURE, 40,
20
+ :DTLS_ALERT_BAD_CERTIFICATE, 42,
21
+ :DTLS_ALERT_UNSUPPORTED_CERTIFICATE, 43,
22
+ :DTLS_ALERT_CERTIFICATE_REVOKED, 44,
23
+ :DTLS_ALERT_CERTIFICATE_EXPIRED, 45,
24
+ :DTLS_ALERT_CERTIFICATE_UNKNOWN, 46,
25
+ :DTLS_ALERT_ILLEGAL_PARAMETER, 47,
26
+ :DTLS_ALERT_UNKNOWN_CA, 48,
27
+ :DTLS_ALERT_ACCESS_DENIED, 49,
28
+ :DTLS_ALERT_DECODE_ERROR, 50,
29
+ :DTLS_ALERT_DECRYPT_ERROR, 51,
30
+ :DTLS_ALERT_PROTOCOL_VERSION, 70,
31
+ :DTLS_ALERT_INSUFFICIENT_SECURITY, 71,
32
+ :DTLS_ALERT_INTERNAL_ERROR, 80,
33
+ :DTLS_ALERT_USER_CANCELED, 90,
34
+ :DTLS_ALERT_NO_RENEGOTIATION, 100,
35
+ :DTLS_ALERT_UNSUPPORTED_EXTENSION, 110
36
+ )
37
+
38
+ LogLevel = enum(
39
+ :DTLS_LOG_EMERG, 0,
40
+ :DTLS_LOG_ALERT,
41
+ :DTLS_LOG_CRIT,
42
+ :DTLS_LOG_WARN,
43
+ :DTLS_LOG_NOTICE,
44
+ :DTLS_LOG_INFO,
45
+ :DTLS_LOG_DEBUG
46
+ )
47
+
48
+ enum :alert_level, [
49
+ :DTLS_ALERT_LEVEL_WARNING, 1,
50
+ :DTLS_ALERT_LEVEL_FATAL, 2,
51
+ ]
52
+
53
+ enum :credential_type, [
54
+ :DTLS_PSK_HINT,
55
+ :DTLS_PSK_IDENTITY,
56
+ :DTLS_PSK_KEY,
57
+ ]
58
+
59
+ class DTLSContextStruct < FFI::Struct
60
+ layout :cookie_secret, [:uchar, DTLS_COOKIE_SECRET_LENGTH],
61
+ :cookie_secret_age, :uint32,
62
+ :peers, :pointer,
63
+ :sendqueue, :pointer,
64
+ :app, :pointer,
65
+ :h, :pointer,
66
+ :readbuf, [:uchar, DTLS_MAX_BUF]
67
+ end
68
+
69
+ class DTLSHandlerStruct < FFI::Struct
70
+ layout :write,
71
+ callback([:pointer, :pointer, :pointer, :size_t], :int),
72
+ :read,
73
+ callback([:pointer, :pointer, :pointer, :size_t], :int),
74
+ :event_function,
75
+ callback([:pointer, :pointer, :alert_level, :ushort], :int),
76
+ :get_psk_info,
77
+ callback([:pointer, :pointer, :credential_type,
78
+ :pointer, :size_t, :pointer, :size_t], :int),
79
+ :get_ecdsa_key,
80
+ callback([:pointer, :pointer, :pointer], :int),
81
+ :verify_ecdsa_key,
82
+ callback([:pointer, :pointer, :uchar, :uchar, :size_t], :int)
83
+ end
84
+
85
+ attach_function :dtls_init, [], :void
86
+ attach_function :dtls_new_context, [:pointer], :pointer
87
+ attach_function :dtls_free_context, [:pointer], :void
88
+ attach_function :dtls_handle_message,
89
+ [:pointer, :pointer, :pointer, :int], :int
90
+ attach_function :dtls_write,
91
+ [:pointer, :pointer, :pointer, :size_t], :int
92
+ attach_function :dtls_connect,
93
+ [:pointer, :pointer], :int
94
+ attach_function :dtls_set_log_level, [LogLevel], :void
95
+
96
+ attach_function :dtls_get_peer, [:pointer, :pointer], :pointer
97
+ attach_function :dtls_reset_peer, [:pointer, :pointer], :void
98
+
99
+ def self.dtls_alert_fatal_create(desc)
100
+ return -((2 << 8) | desc)
101
+ end
102
+
103
+ # This type is needed for the `dtls_session_addr` wrapper.
104
+ # See https://github.com/ffi/ffi/wiki/Pointers#passing-by-reference
105
+ class SocklenPtr < FFI::Struct
106
+ layout :value, :socklen_t
107
+ end
108
+
109
+ # These functions are not available in vanilla tinydtls.
110
+ # They are required to make interaction with the tinydtls `session_t`
111
+ # type possible without creating a ruby wrapper for `struct
112
+ # sockaddr_in{,6}`.
113
+ attach_function :dtls_new_session,
114
+ [:pointer, :socklen_t], :pointer
115
+ attach_function :dtls_session_addr, [:pointer, SocklenPtr], :pointer
116
+
117
+ def self.dtls_get_app_data(ctx)
118
+ return ctx[:app]
119
+ end
120
+
121
+ def self.dtls_set_handler(ctx, handler)
122
+ ctx[:h] = handler
123
+ end
124
+ end
125
+ end
metadata ADDED
@@ -0,0 +1,79 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tinydtls
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Sören Tempel
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-07-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: ffi
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.9'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.9'
27
+ - !ruby/object:Gem::Dependency
28
+ name: minitest
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '5.11'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '5.11'
41
+ description: tinydtls provides a DTLS implementation
42
+ email:
43
+ - tempel@uni-bremen.de
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - lib/tinydtls.rb
49
+ - lib/tinydtls/context.rb
50
+ - lib/tinydtls/security_conf.rb
51
+ - lib/tinydtls/session.rb
52
+ - lib/tinydtls/session_manager.rb
53
+ - lib/tinydtls/udpsocket.rb
54
+ - lib/tinydtls/wrapper.rb
55
+ homepage: https://github.com/ruby-dtls/rb-tinydtls
56
+ licenses:
57
+ - MIT
58
+ metadata: {}
59
+ post_install_message:
60
+ rdoc_options: []
61
+ require_paths:
62
+ - lib
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: 2.2.0
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ requirements: []
74
+ rubyforge_project:
75
+ rubygems_version: 2.7.3
76
+ signing_key:
77
+ specification_version: 4
78
+ summary: It wraps the tinydtls library
79
+ test_files: []