@@ -80,7 +80,33 @@ defmodule ExWebRTC.SCTPTransport do
80
80
{ events , channel , sctp_transport }
81
81
end
82
82
83
- # TODO: close channel
83
+ @ spec close_channel ( t ( ) , DataChannel . ref ( ) ) :: { [ event ( ) ] , t ( ) }
84
+ def close_channel ( sctp_transport , ref ) do
85
+ # TODO: according to spec, this should move to `closing` state
86
+ # and only then be closed, but oh well...
87
+ case Map . pop ( sctp_transport . channels , ref ) do
88
+ { nil , _channels } ->
89
+ Logger . warning ( "Trying to close non-existent channel with ref #{ inspect ( ref ) } " )
90
+ { [ ] , sctp_transport }
91
+
92
+ { % DataChannel { id: id } , channels } ->
93
+ sctp_transport = % { sctp_transport | channels: channels }
94
+
95
+ { events , sctp_transport } =
96
+ if id != nil do
97
+ :ok = ExSCTP . close_stream ( sctp_transport . ref , id )
98
+ handle_events ( sctp_transport )
99
+ else
100
+ { [ ] , sctp_transport }
101
+ end
102
+
103
+ event = { :state_change , ref , :closed }
104
+ { [ event | events ] , sctp_transport }
105
+ end
106
+ end
107
+
108
+ @ spec get_channel ( t ( ) , DataChannel . ref ( ) ) :: DataChannel . t ( ) | nil
109
+ def get_channel ( sctp_transport , ref ) , do: Map . get ( sctp_transport . channels , ref )
84
110
85
111
@ spec send ( t ( ) , DataChannel . ref ( ) , :string | :binary , binary ( ) ) :: { [ event ( ) ] , t ( ) }
86
112
def send ( sctp_transport , ref , type , data ) do
@@ -99,7 +125,10 @@ defmodule ExWebRTC.SCTPTransport do
99
125
{ [ ] , sctp_transport }
100
126
101
127
:error ->
102
- Logger . warning ( "Trying to send data over non-existing DataChannel with ref #{ ref } " )
128
+ Logger . warning (
129
+ "Trying to send data over non-existent DataChannel with ref #{ inspect ( ref ) } "
130
+ )
131
+
103
132
{ [ ] , sctp_transport }
104
133
end
105
134
end
@@ -157,6 +186,7 @@ defmodule ExWebRTC.SCTPTransport do
157
186
case handle_event ( sctp_transport , event ) do
158
187
{ :none , transport } -> { Enum . reverse ( events ) , transport }
159
188
{ nil , transport } -> handle_events ( transport , events )
189
+ { other , transport } when is_list ( other ) -> handle_events ( transport , other ++ events )
160
190
{ other , transport } -> handle_events ( transport , [ other | events ] )
161
191
end
162
192
end
@@ -171,9 +201,18 @@ defmodule ExWebRTC.SCTPTransport do
171
201
{ nil , sctp_transport }
172
202
end
173
203
174
- defp handle_event ( sctp_transport , { :stream_closed , _id } ) do
175
- # TODO: handle closing channels
176
- { nil , sctp_transport }
204
+ defp handle_event ( sctp_transport , { :stream_closed , id } ) do
205
+ Logger . debug ( "SCTP stream #{ id } has been closed" )
206
+
207
+ case Enum . find ( sctp_transport . channels , fn { _k , v } -> v . id == id end ) do
208
+ { ref , % DataChannel { ref: ref } } ->
209
+ channels = Map . delete ( sctp_transport . channels , ref )
210
+ event = { :state_change , ref , :closed }
211
+ { event , % { sctp_transport | channels: channels } }
212
+
213
+ _other ->
214
+ { nil , sctp_transport }
215
+ end
177
216
end
178
217
179
218
defp handle_event ( sctp_transport , :connected ) do
@@ -206,13 +245,23 @@ defmodule ExWebRTC.SCTPTransport do
206
245
207
246
defp handle_event ( sctp_transport , { :data , id , @ dcep_ppi , data } ) do
208
247
with { :ok , dcep } <- DCEP . decode ( data ) ,
209
- { :ok , sctp_transport , event } <- handle_dcep ( sctp_transport , id , dcep ) do
210
- { event , sctp_transport }
248
+ { :ok , sctp_transport , events } <- handle_dcep ( sctp_transport , id , dcep ) do
249
+ # events is either list or a single event
250
+ { events , sctp_transport }
211
251
else
212
252
:error ->
213
- # TODO: close the channel
214
253
Logger . warning ( "Received invalid DCEP message. Closing the stream with id #{ id } " )
215
- { nil , sctp_transport }
254
+
255
+ ExSCTP . close_stream ( sctp_transport . ref , id )
256
+
257
+ case Enum . find_value ( sctp_transport . channels , fn { _k , v } -> v . id == id end ) do
258
+ { ref , % DataChannel { } } ->
259
+ channels = Map . delete ( sctp_transport . channels , ref )
260
+ { { :state_change , ref , :closed } , % { sctp_transport | channels: channels } }
261
+
262
+ nil ->
263
+ { nil , sctp_transport }
264
+ end
216
265
end
217
266
end
218
267
@@ -228,7 +277,7 @@ defmodule ExWebRTC.SCTPTransport do
228
277
229
278
nil ->
230
279
Logger . warning (
231
- "Received data over non-existing DataChannel on stream with id #{ id } . Discarding"
280
+ "Received data over non-existent DataChannel on stream with id #{ id } . Discarding"
232
281
)
233
282
234
283
{ nil , sctp_transport }
@@ -258,28 +307,63 @@ defmodule ExWebRTC.SCTPTransport do
258
307
}
259
308
260
309
# In theory, we should also send the :open event here (W3C 6.2.3)
310
+ # TODO
261
311
channels = Map . put ( sctp_transport . channels , channel . ref , channel )
262
- { :ok , % { sctp_transport | channels: channels } , { :channel , channel } }
312
+ sctp_transport = % { sctp_transport | channels: channels }
313
+
314
+ case ExSCTP . configure_stream (
315
+ sctp_transport . ref ,
316
+ id ,
317
+ channel . ordered ,
318
+ dco . reliability ,
319
+ dco . param
320
+ ) do
321
+ :ok ->
322
+ # remote channels also result in open event
323
+ # even tho they already have ready_state open in the {:data_channel, ...} message
324
+ # W3C 6.2.3
325
+ events = [ { :state_change , channel . ref , :open } , { :channel , channel } ]
326
+ { :ok , sctp_transport , events }
327
+
328
+ { :error , _res } ->
329
+ Logger . warning ( "Unable to set stream #{ id } parameters" )
330
+ :error
331
+ end
263
332
else
264
- _other -> :error
333
+ _other ->
334
+ Logger . warning ( "Received invalid DCEP Open on stream #{ id } " )
335
+ :error
265
336
end
266
337
end
267
338
268
339
defp handle_dcep ( sctp_transport , id , % DCEP.DataChannelAck { } ) do
269
340
case Enum . find ( sctp_transport . channels , fn { _k , v } -> v . id == id end ) do
270
341
{ ref , % DataChannel { ready_state: :connecting } = channel } ->
271
342
Logger . debug ( "Locally opened DataChannel #{ id } has been negotiated succesfully" )
272
- # TODO: set the parameters
343
+
273
344
channel = % DataChannel { channel | ready_state: :open }
274
345
channels = Map . put ( sctp_transport . channels , ref , channel )
275
- event = { :state_change , ref , :open }
346
+ sctp_transport = % { sctp_transport | channels: channels }
347
+
348
+ { rel_type , rel_param } =
349
+ case channel do
350
+ % DataChannel { max_packet_life_time: nil , max_retransmits: nil } -> { :reliable , 0 }
351
+ % DataChannel { max_retransmits: v } when v != nil -> { :rexmit , v }
352
+ % DataChannel { max_packet_life_time: v } when v != nil -> { :timed , v }
353
+ end
354
+
355
+ case ExSCTP . configure_stream ( sctp_transport . ref , id , channel . ordered , rel_type , rel_param ) do
356
+ :ok ->
357
+ { :ok , sctp_transport , { :state_change , ref , :open } }
276
358
277
- { :ok , % { sctp_transport | channels: channels } , event }
359
+ { :error , _res } ->
360
+ Logger . warning ( "Unable to set stream #{ id } parameters" )
361
+ :error
362
+ end
278
363
279
364
_other ->
280
- # TODO: close the channel
281
365
Logger . warning ( "Received DCEP Ack without sending the DCEP Open message on stream #{ id } " )
282
- { :ok , sctp_transport , nil }
366
+ :error
283
367
end
284
368
end
285
369
0 commit comments