tinydtls 0.1.0

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
+ 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: []