blob: 4b940edcc0e5eefa2094b91cb714761506fedf43 [file] [log] [blame]
James Kuszmaul4cb043c2021-01-17 11:25:51 -08001/*-
2 * Copyright (C) 2012-2013 Michael Tuexen
3 * Copyright (C) 2012-2013 Irene Ruengeler
4 *
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
31 * $Id: rtcweb.c,v 1.26 2012-07-17 13:50:02 tuexen Exp $
32 */
33
34/*
35 * gcc -Wall -std=c99 -pedantic -o rtcweb rtcweb.c -lusrsctp
36 */
37
38#include <sys/types.h>
39#ifdef _WIN32
40#define _CRT_SECURE_NO_WARNINGS
41#include <WinSock2.h>
42#include <WS2tcpip.h>
43#include <crtdbg.h>
44#else
45#include <sys/socket.h>
46#include <sys/select.h>
47#include <netinet/in.h>
48#include <arpa/inet.h>
49#include <pthread.h>
50#include <unistd.h>
51#include <stdint.h>
52#endif
53#include <stdarg.h>
54#include <stdio.h>
55#include <stdlib.h>
56#include <string.h>
57#include <errno.h>
58#include <usrsctp.h>
59
60#define LINE_LENGTH (1024)
61#define BUFFER_SIZE (1<<16)
62#define NUMBER_OF_CHANNELS (100)
63#define NUMBER_OF_STREAMS (100)
64
65#define DATA_CHANNEL_PPID_CONTROL 50
66#define DATA_CHANNEL_PPID_DOMSTRING 51
67#define DATA_CHANNEL_PPID_BINARY 52
68
69#define DATA_CHANNEL_CLOSED 0
70#define DATA_CHANNEL_CONNECTING 1
71#define DATA_CHANNEL_OPEN 2
72#define DATA_CHANNEL_CLOSING 3
73
74#define DATA_CHANNEL_FLAGS_SEND_REQ 0x00000001
75#define DATA_CHANNEL_FLAGS_SEND_RSP 0x00000002
76#define DATA_CHANNEL_FLAGS_SEND_ACK 0x00000004
77
78struct channel {
79 uint32_t id;
80 uint32_t pr_value;
81 uint16_t pr_policy;
82 uint16_t i_stream;
83 uint16_t o_stream;
84 uint8_t unordered;
85 uint8_t state;
86 uint32_t flags;
87};
88
89struct peer_connection {
90 struct channel channels[NUMBER_OF_CHANNELS];
91 struct channel *i_stream_channel[NUMBER_OF_STREAMS];
92 struct channel *o_stream_channel[NUMBER_OF_STREAMS];
93 uint16_t o_stream_buffer[NUMBER_OF_STREAMS];
94 uint32_t o_stream_buffer_counter;
95#ifdef _WIN32
96 CRITICAL_SECTION mutex;
97#else
98 pthread_mutex_t mutex;
99#endif
100 struct socket *sock;
101} peer_connection;
102
103#define DATA_CHANNEL_OPEN_REQUEST 0
104#define DATA_CHANNEL_OPEN_RESPONSE 1
105#define DATA_CHANNEL_ACK 2
106
107#define DATA_CHANNEL_RELIABLE 0
108#define DATA_CHANNEL_RELIABLE_STREAM 1
109#define DATA_CHANNEL_UNRELIABLE 2
110#define DATA_CHANNEL_PARTIAL_RELIABLE_REXMIT 3
111#define DATA_CHANNEL_PARTIAL_RELIABLE_TIMED 4
112
113#define DATA_CHANNEL_FLAG_OUT_OF_ORDER_ALLOWED 0x0001
114
115#ifndef _WIN32
116#define SCTP_PACKED __attribute__((packed))
117#else
118#pragma pack (push, 1)
119#define SCTP_PACKED
120#endif
121
122struct rtcweb_datachannel_open_request {
123 uint8_t msg_type; /* DATA_CHANNEL_OPEN_REQUEST */
124 uint8_t channel_type;
125 uint16_t flags;
126 uint16_t reliability_params;
127 int16_t priority;
128 char label[];
129} SCTP_PACKED;
130
131struct rtcweb_datachannel_open_response {
132 uint8_t msg_type; /* DATA_CHANNEL_OPEN_RESPONSE */
133 uint8_t error;
134 uint16_t flags;
135 uint16_t reverse_stream;
136} SCTP_PACKED;
137
138struct rtcweb_datachannel_ack {
139 uint8_t msg_type; /* DATA_CHANNEL_ACK */
140} SCTP_PACKED;
141
142#ifdef _WIN32
143#pragma pack()
144#endif
145
146#undef SCTP_PACKED
147
148static void
149init_peer_connection(struct peer_connection *pc)
150{
151 uint32_t i;
152 struct channel *channel;
153
154 for (i = 0; i < NUMBER_OF_CHANNELS; i++) {
155 channel = &(pc->channels[i]);
156 channel->id = i;
157 channel->state = DATA_CHANNEL_CLOSED;
158 channel->pr_policy = SCTP_PR_SCTP_NONE;
159 channel->pr_value = 0;
160 channel->i_stream = 0;
161 channel->o_stream = 0;
162 channel->unordered = 0;
163 channel->flags = 0;
164 }
165 for (i = 0; i < NUMBER_OF_STREAMS; i++) {
166 pc->i_stream_channel[i] = NULL;
167 pc->o_stream_channel[i] = NULL;
168 pc->o_stream_buffer[i] = 0;
169 }
170 pc->o_stream_buffer_counter = 0;
171 pc->sock = NULL;
172#ifdef _WIN32
173 InitializeCriticalSection(&(pc->mutex));
174#else
175 pthread_mutex_init(&pc->mutex, NULL);
176#endif
177}
178
179static void
180lock_peer_connection(struct peer_connection *pc)
181{
182#ifdef _WIN32
183 EnterCriticalSection(&(pc->mutex));
184#else
185 pthread_mutex_lock(&pc->mutex);
186#endif
187}
188
189static void
190unlock_peer_connection(struct peer_connection *pc)
191{
192#ifdef _WIN32
193 LeaveCriticalSection(&(pc->mutex));
194#else
195 pthread_mutex_unlock(&pc->mutex);
196#endif
197}
198
199static struct channel *
200find_channel_by_i_stream(struct peer_connection *pc, uint16_t i_stream)
201{
202 if (i_stream < NUMBER_OF_STREAMS) {
203 return (pc->i_stream_channel[i_stream]);
204 } else {
205 return (NULL);
206 }
207}
208
209static struct channel *
210find_channel_by_o_stream(struct peer_connection *pc, uint16_t o_stream)
211{
212 if (o_stream < NUMBER_OF_STREAMS) {
213 return (pc->o_stream_channel[o_stream]);
214 } else {
215 return (NULL);
216 }
217}
218
219static struct channel *
220find_free_channel(struct peer_connection *pc)
221{
222 uint32_t i;
223
224 for (i = 0; i < NUMBER_OF_CHANNELS; i++) {
225 if (pc->channels[i].state == DATA_CHANNEL_CLOSED) {
226 break;
227 }
228 }
229 if (i == NUMBER_OF_CHANNELS) {
230 return (NULL);
231 } else {
232 return (&(pc->channels[i]));
233 }
234}
235
236static uint16_t
237find_free_o_stream(struct peer_connection *pc)
238{
239 struct sctp_status status;
240 uint32_t i, limit;
241 socklen_t len;
242
243 len = (socklen_t)sizeof(struct sctp_status);
244 if (usrsctp_getsockopt(pc->sock, IPPROTO_SCTP, SCTP_STATUS, &status, &len) < 0) {
245 perror("getsockopt");
246 return (0);
247 }
248 if (status.sstat_outstrms < NUMBER_OF_STREAMS) {
249 limit = status.sstat_outstrms;
250 } else {
251 limit = NUMBER_OF_STREAMS;
252 }
253 /* stream id 0 is reserved */
254 for (i = 1; i < limit; i++) {
255 if (pc->o_stream_channel[i] == NULL) {
256 break;
257 }
258 }
259 if (i == limit) {
260 return (0);
261 } else {
262 return ((uint16_t)i);
263 }
264}
265
266static void
267request_more_o_streams(struct peer_connection *pc)
268{
269 struct sctp_status status;
270 struct sctp_add_streams sas;
271 uint32_t i, o_streams_needed;
272 socklen_t len;
273
274 o_streams_needed = 0;
275 for (i = 0; i < NUMBER_OF_CHANNELS; i++) {
276 if ((pc->channels[i].state == DATA_CHANNEL_CONNECTING) &&
277 (pc->channels[i].o_stream == 0)) {
278 o_streams_needed++;
279 }
280 }
281 len = (socklen_t)sizeof(struct sctp_status);
282 if (usrsctp_getsockopt(pc->sock, IPPROTO_SCTP, SCTP_STATUS, &status, &len) < 0) {
283 perror("getsockopt");
284 return;
285 }
286 if (status.sstat_outstrms + o_streams_needed > NUMBER_OF_STREAMS) {
287 o_streams_needed = NUMBER_OF_STREAMS - status.sstat_outstrms;
288 }
289 if (o_streams_needed == 0) {
290 return;
291 }
292 memset(&sas, 0, sizeof(struct sctp_add_streams));
293 sas.sas_instrms = 0;
294 sas.sas_outstrms = (uint16_t)o_streams_needed; /* XXX eror handling */
295 if (usrsctp_setsockopt(pc->sock, IPPROTO_SCTP, SCTP_ADD_STREAMS, &sas, (socklen_t)sizeof(struct sctp_add_streams)) < 0) {
296 perror("setsockopt");
297 }
298 return;
299}
300
301static int
302send_open_request_message(struct socket *sock, uint16_t o_stream, uint8_t unordered, uint16_t pr_policy, uint32_t pr_value)
303{
304 /* XXX: This should be encoded in a better way */
305 struct rtcweb_datachannel_open_request req;
306 struct sctp_sndinfo sndinfo;
307
308 memset(&req, 0, sizeof(struct rtcweb_datachannel_open_request));
309 req.msg_type = DATA_CHANNEL_OPEN_REQUEST;
310 switch (pr_policy) {
311 case SCTP_PR_SCTP_NONE:
312 /* XXX: What about DATA_CHANNEL_RELIABLE_STREAM */
313 req.channel_type = DATA_CHANNEL_RELIABLE;
314 break;
315 case SCTP_PR_SCTP_TTL:
316 /* XXX: What about DATA_CHANNEL_UNRELIABLE */
317 req.channel_type = DATA_CHANNEL_PARTIAL_RELIABLE_TIMED;
318 break;
319 case SCTP_PR_SCTP_RTX:
320 req.channel_type = DATA_CHANNEL_PARTIAL_RELIABLE_REXMIT;
321 break;
322 default:
323 return (0);
324 }
325 req.flags = htons(0);
326 if (unordered) {
327 req.flags |= htons(DATA_CHANNEL_FLAG_OUT_OF_ORDER_ALLOWED);
328 }
329 req.reliability_params = htons((uint16_t)pr_value); /* XXX Why 16-bit */
330 req.priority = htons(0); /* XXX: add support */
331 memset(&sndinfo, 0, sizeof(struct sctp_sndinfo));
332 sndinfo.snd_sid = o_stream;
333 sndinfo.snd_flags = SCTP_EOR;
334 sndinfo.snd_ppid = htonl(DATA_CHANNEL_PPID_CONTROL);
335 if (usrsctp_sendv(sock,
336 &req, sizeof(struct rtcweb_datachannel_open_request),
337 NULL, 0,
338 &sndinfo, (socklen_t)sizeof(struct sctp_sndinfo),
339 SCTP_SENDV_SNDINFO, 0) < 0) {
340 perror("sctp_sendv");
341 return (0);
342 } else {
343 return (1);
344 }
345}
346
347static int
348send_open_response_message(struct socket *sock, uint16_t o_stream, uint16_t i_stream)
349{
350 /* XXX: This should be encoded in a better way */
351 struct rtcweb_datachannel_open_response rsp;
352 struct sctp_sndinfo sndinfo;
353
354 memset(&rsp, 0, sizeof(struct rtcweb_datachannel_open_response));
355 rsp.msg_type = DATA_CHANNEL_OPEN_RESPONSE;
356 rsp.error = 0;
357 rsp.flags = htons(0);
358 rsp.reverse_stream = htons(i_stream);
359 memset(&sndinfo, 0, sizeof(struct sctp_sndinfo));
360 sndinfo.snd_sid = o_stream;
361 sndinfo.snd_flags = SCTP_EOR;
362 sndinfo.snd_ppid = htonl(DATA_CHANNEL_PPID_CONTROL);
363 if (usrsctp_sendv(sock,
364 &rsp, sizeof(struct rtcweb_datachannel_open_response),
365 NULL, 0,
366 &sndinfo, (socklen_t)sizeof(struct sctp_sndinfo),
367 SCTP_SENDV_SNDINFO, 0) < 0) {
368 perror("sctp_sendv");
369 return (0);
370 } else {
371 return (1);
372 }
373}
374
375static int
376send_open_ack_message(struct socket *sock, uint16_t o_stream)
377{
378 /* XXX: This should be encoded in a better way */
379 struct rtcweb_datachannel_ack ack;
380 struct sctp_sndinfo sndinfo;
381
382 memset(&ack, 0, sizeof(struct rtcweb_datachannel_ack));
383 ack.msg_type = DATA_CHANNEL_ACK;
384 memset(&sndinfo, 0, sizeof(struct sctp_sndinfo));
385 sndinfo.snd_sid = o_stream;
386 sndinfo.snd_flags = SCTP_EOR;
387 sndinfo.snd_ppid = htonl(DATA_CHANNEL_PPID_CONTROL);
388 if (usrsctp_sendv(sock,
389 &ack, sizeof(struct rtcweb_datachannel_ack),
390 NULL, 0,
391 &sndinfo, (socklen_t)sizeof(struct sctp_sndinfo),
392 SCTP_SENDV_SNDINFO, 0) < 0) {
393 perror("sctp_sendv");
394 return (0);
395 } else {
396 return (1);
397 }
398}
399
400static void
401send_deferred_messages(struct peer_connection *pc)
402{
403 uint32_t i;
404 struct channel *channel;
405
406 for (i = 0; i < NUMBER_OF_CHANNELS; i++) {
407 channel = &(pc->channels[i]);
408 if (channel->flags & DATA_CHANNEL_FLAGS_SEND_REQ) {
409 if (send_open_request_message(pc->sock, channel->o_stream, channel->unordered, channel->pr_policy, channel->pr_value)) {
410 channel->flags &= ~DATA_CHANNEL_FLAGS_SEND_REQ;
411 } else {
412 if (errno != EAGAIN) {
413 /* XXX: error handling */
414 }
415 }
416 }
417 if (channel->flags & DATA_CHANNEL_FLAGS_SEND_RSP) {
418 if (send_open_response_message(pc->sock, channel->o_stream, channel->i_stream)) {
419 channel->flags &= ~DATA_CHANNEL_FLAGS_SEND_RSP;
420 } else {
421 if (errno != EAGAIN) {
422 /* XXX: error handling */
423 }
424 }
425 }
426 if (channel->flags & DATA_CHANNEL_FLAGS_SEND_ACK) {
427 if (send_open_ack_message(pc->sock, channel->o_stream)) {
428 channel->flags &= ~DATA_CHANNEL_FLAGS_SEND_ACK;
429 } else {
430 if (errno != EAGAIN) {
431 /* XXX: error handling */
432 }
433 }
434 }
435 }
436 return;
437}
438
439static struct channel *
440open_channel(struct peer_connection *pc, uint8_t unordered, uint16_t pr_policy, uint32_t pr_value)
441{
442 struct channel *channel;
443 uint16_t o_stream;
444
445 if ((pr_policy != SCTP_PR_SCTP_NONE) &&
446 (pr_policy != SCTP_PR_SCTP_TTL) &&
447 (pr_policy != SCTP_PR_SCTP_RTX)) {
448 return (NULL);
449 }
450 if ((unordered != 0) && (unordered != 1)) {
451 return (NULL);
452 }
453 if ((pr_policy == SCTP_PR_SCTP_NONE) && (pr_value != 0)) {
454 return (NULL);
455 }
456 if ((channel = find_free_channel(pc)) == NULL) {
457 return (NULL);
458 }
459 o_stream = find_free_o_stream(pc);
460 channel->state = DATA_CHANNEL_CONNECTING;
461 channel->unordered = unordered;
462 channel->pr_policy = pr_policy;
463 channel->pr_value = pr_value;
464 channel->o_stream = o_stream;
465 channel->flags = 0;
466 if (o_stream == 0) {
467 request_more_o_streams(pc);
468 } else {
469 if (send_open_request_message(pc->sock, o_stream, unordered, pr_policy, pr_value)) {
470 pc->o_stream_channel[o_stream] = channel;
471 } else {
472 if (errno == EAGAIN) {
473 pc->o_stream_channel[o_stream] = channel;
474 channel->flags |= DATA_CHANNEL_FLAGS_SEND_REQ;
475 } else {
476 channel->state = DATA_CHANNEL_CLOSED;
477 channel->unordered = 0;
478 channel->pr_policy = 0;
479 channel->pr_value = 0;
480 channel->o_stream = 0;
481 channel->flags = 0;
482 channel = NULL;
483 }
484 }
485 }
486 return (channel);
487}
488
489static int
490send_user_message(struct peer_connection *pc, struct channel *channel, char *message, size_t length)
491{
492 struct sctp_sendv_spa spa;
493
494 if (channel == NULL) {
495 return (0);
496 }
497 if ((channel->state != DATA_CHANNEL_OPEN) &&
498 (channel->state != DATA_CHANNEL_CONNECTING)) {
499 /* XXX: What to do in other states */
500 return (0);
501 }
502
503 memset(&spa, 0, sizeof(struct sctp_sendv_spa));
504 spa.sendv_sndinfo.snd_sid = channel->o_stream;
505 if ((channel->state == DATA_CHANNEL_OPEN) &&
506 (channel->unordered)) {
507 spa.sendv_sndinfo.snd_flags = SCTP_EOR | SCTP_UNORDERED;
508 } else {
509 spa.sendv_sndinfo.snd_flags = SCTP_EOR;
510 }
511 spa.sendv_sndinfo.snd_ppid = htonl(DATA_CHANNEL_PPID_DOMSTRING);
512 spa.sendv_flags = SCTP_SEND_SNDINFO_VALID;
513 if ((channel->pr_policy == SCTP_PR_SCTP_TTL) ||
514 (channel->pr_policy == SCTP_PR_SCTP_RTX)) {
515 spa.sendv_prinfo.pr_policy = channel->pr_policy;
516 spa.sendv_prinfo.pr_value = channel->pr_value;
517 spa.sendv_flags |= SCTP_SEND_PRINFO_VALID;
518 }
519 if (usrsctp_sendv(pc->sock,
520 message, length,
521 NULL, 0,
522 &spa, (socklen_t)sizeof(struct sctp_sendv_spa),
523 SCTP_SENDV_SPA, 0) < 0) {
524 perror("sctp_sendv");
525 return (0);
526 } else {
527 return (1);
528 }
529}
530
531static void
532reset_outgoing_stream(struct peer_connection *pc, uint16_t o_stream)
533{
534 uint32_t i;
535
536 for (i = 0; i < pc->o_stream_buffer_counter; i++) {
537 if (pc->o_stream_buffer[i] == o_stream) {
538 return;
539 }
540 }
541 pc->o_stream_buffer[pc->o_stream_buffer_counter++] = o_stream;
542 return;
543}
544
545static void
546send_outgoing_stream_reset(struct peer_connection *pc)
547{
548 struct sctp_reset_streams *srs;
549 uint32_t i;
550 size_t len;
551
552 if (pc->o_stream_buffer_counter == 0) {
553 return;
554 }
555 len = sizeof(sctp_assoc_t) + (2 + pc->o_stream_buffer_counter) * sizeof(uint16_t);
556 srs = (struct sctp_reset_streams *)malloc(len);
557 if (srs == NULL) {
558 return;
559 }
560 memset(srs, 0, len);
561 srs->srs_flags = SCTP_STREAM_RESET_OUTGOING;
562 srs->srs_number_streams = pc->o_stream_buffer_counter;
563 for (i = 0; i < pc->o_stream_buffer_counter; i++) {
564 srs->srs_stream_list[i] = pc->o_stream_buffer[i];
565 }
566 if (usrsctp_setsockopt(pc->sock, IPPROTO_SCTP, SCTP_RESET_STREAMS, srs, (socklen_t)len) < 0) {
567 perror("setsockopt");
568 } else {
569 for (i = 0; i < pc->o_stream_buffer_counter; i++) {
570 srs->srs_stream_list[i] = 0;
571 }
572 pc->o_stream_buffer_counter = 0;
573 }
574 free(srs);
575 return;
576}
577
578static void
579close_channel(struct peer_connection *pc, struct channel *channel)
580{
581 if (channel == NULL) {
582 return;
583 }
584 if (channel->state != DATA_CHANNEL_OPEN) {
585 return;
586 }
587 reset_outgoing_stream(pc, channel->o_stream);
588 send_outgoing_stream_reset(pc);
589 channel->state = DATA_CHANNEL_CLOSING;
590 return;
591}
592
593static void
594handle_open_request_message(struct peer_connection *pc,
595 struct rtcweb_datachannel_open_request *req,
596 size_t length,
597 uint16_t i_stream)
598{
599 struct channel *channel;
600 uint32_t pr_value;
601 uint16_t pr_policy;
602 uint16_t o_stream;
603 uint8_t unordered;
604
605 if ((channel = find_channel_by_i_stream(pc, i_stream))) {
606 printf("handle_open_request_message: channel %d is in state %d instead of CLOSED.\n",
607 channel->id, channel->state);
608 /* XXX: some error handling */
609 return;
610 }
611 if ((channel = find_free_channel(pc)) == NULL) {
612 /* XXX: some error handling */
613 return;
614 }
615 switch (req->channel_type) {
616 case DATA_CHANNEL_RELIABLE:
617 pr_policy = SCTP_PR_SCTP_NONE;
618 break;
619 /* XXX Doesn't make sense */
620 case DATA_CHANNEL_RELIABLE_STREAM:
621 pr_policy = SCTP_PR_SCTP_NONE;
622 break;
623 /* XXX Doesn't make sense */
624 case DATA_CHANNEL_UNRELIABLE:
625 pr_policy = SCTP_PR_SCTP_TTL;
626 break;
627 case DATA_CHANNEL_PARTIAL_RELIABLE_REXMIT:
628 pr_policy = SCTP_PR_SCTP_RTX;
629 break;
630 case DATA_CHANNEL_PARTIAL_RELIABLE_TIMED:
631 pr_policy = SCTP_PR_SCTP_TTL;
632 break;
633 default:
634 pr_policy = SCTP_PR_SCTP_NONE;
635 /* XXX error handling */
636 break;
637 }
638 pr_value = ntohs(req->reliability_params);
639 if (ntohs(req->flags) & DATA_CHANNEL_FLAG_OUT_OF_ORDER_ALLOWED) {
640 unordered = 1;
641 } else {
642 unordered = 0;
643 }
644 o_stream = find_free_o_stream(pc);
645 channel->state = DATA_CHANNEL_CONNECTING;
646 channel->unordered = unordered;
647 channel->pr_policy = pr_policy;
648 channel->pr_value = pr_value;
649 channel->i_stream = i_stream;
650 channel->o_stream = o_stream;
651 channel->flags = 0;
652 pc->i_stream_channel[i_stream] = channel;
653 if (o_stream == 0) {
654 request_more_o_streams(pc);
655 } else {
656 if (send_open_response_message(pc->sock, o_stream, i_stream)) {
657 pc->o_stream_channel[o_stream] = channel;
658 } else {
659 if (errno == EAGAIN) {
660 channel->flags |= DATA_CHANNEL_FLAGS_SEND_RSP;
661 pc->o_stream_channel[o_stream] = channel;
662 } else {
663 /* XXX: Signal error to the other end. */
664 pc->i_stream_channel[i_stream] = NULL;
665 channel->state = DATA_CHANNEL_CLOSED;
666 channel->unordered = 0;
667 channel->pr_policy = 0;
668 channel->pr_value = 0;
669 channel->i_stream = 0;
670 channel->o_stream = 0;
671 channel->flags = 0;
672 }
673 }
674 }
675}
676
677static void
678handle_open_response_message(struct peer_connection *pc,
679 struct rtcweb_datachannel_open_response *rsp,
680 size_t length, uint16_t i_stream)
681{
682 uint16_t o_stream;
683 struct channel *channel;
684
685 o_stream = ntohs(rsp->reverse_stream);
686 channel = find_channel_by_o_stream(pc, o_stream);
687 if (channel == NULL) {
688 /* XXX: improve error handling */
689 printf("handle_open_response_message: Can't find channel for outgoing steam %d.\n", o_stream);
690 return;
691 }
692 if (channel->state != DATA_CHANNEL_CONNECTING) {
693 /* XXX: improve error handling */
694 printf("handle_open_response_message: Channel with id %d for outgoing steam %d is in state %d.\n", channel->id, o_stream, channel->state);
695 return;
696 }
697 if (find_channel_by_i_stream(pc, i_stream)) {
698 /* XXX: improve error handling */
699 printf("handle_open_response_message: Channel collision for channel with id %d and streams (in/out) = (%d/%d).\n", channel->id, i_stream, o_stream);
700 return;
701 }
702 channel->i_stream = i_stream;
703 channel->state = DATA_CHANNEL_OPEN;
704 pc->i_stream_channel[i_stream] = channel;
705 if (send_open_ack_message(pc->sock, o_stream)) {
706 channel->flags = 0;
707 } else {
708 channel->flags |= DATA_CHANNEL_FLAGS_SEND_ACK;
709 }
710 return;
711}
712
713static void
714handle_open_ack_message(struct peer_connection *pc,
715 struct rtcweb_datachannel_ack *ack,
716 size_t length, uint16_t i_stream)
717{
718 struct channel *channel;
719
720 channel = find_channel_by_i_stream(pc, i_stream);
721 if (channel == NULL) {
722 /* XXX: some error handling */
723 return;
724 }
725 if (channel->state == DATA_CHANNEL_OPEN) {
726 return;
727 }
728 if (channel->state != DATA_CHANNEL_CONNECTING) {
729 /* XXX: error handling */
730 return;
731 }
732 channel->state = DATA_CHANNEL_OPEN;
733 return;
734}
735
736static void
737handle_unknown_message(char *msg, size_t length, uint16_t i_stream)
738{
739 /* XXX: Send an error message */
740 return;
741}
742
743static void
744handle_data_message(struct peer_connection *pc,
745 char *buffer, size_t length, uint16_t i_stream)
746{
747 struct channel *channel;
748
749 channel = find_channel_by_i_stream(pc, i_stream);
750 if (channel == NULL) {
751 /* XXX: Some error handling */
752 return;
753 }
754 if (channel->state == DATA_CHANNEL_CONNECTING) {
755 /* Implicit ACK */
756 channel->state = DATA_CHANNEL_OPEN;
757 }
758 if (channel->state != DATA_CHANNEL_OPEN) {
759 /* XXX: What about other states? */
760 /* XXX: Some error handling */
761 return;
762 } else {
763 /* Assuming DATA_CHANNEL_PPID_DOMSTRING */
764 /* XXX: Protect for non 0 terminated buffer */
765 printf("Message received of length %zu on channel with id %d: %.*s\n",
766 length, channel->id, (int)length, buffer);
767 }
768 return;
769}
770
771static void
772handle_message(struct peer_connection *pc, char *buffer, size_t length, uint32_t ppid, uint16_t i_stream)
773{
774 struct rtcweb_datachannel_open_request *req;
775 struct rtcweb_datachannel_open_response *rsp;
776 struct rtcweb_datachannel_ack *ack, *msg;
777
778 switch (ppid) {
779 case DATA_CHANNEL_PPID_CONTROL:
780 if (length < sizeof(struct rtcweb_datachannel_ack)) {
781 return;
782 }
783 msg = (struct rtcweb_datachannel_ack *)buffer;
784 switch (msg->msg_type) {
785 case DATA_CHANNEL_OPEN_REQUEST:
786 if (length < sizeof(struct rtcweb_datachannel_open_request)) {
787 /* XXX: error handling? */
788 return;
789 }
790 req = (struct rtcweb_datachannel_open_request *)buffer;
791 handle_open_request_message(pc, req, length, i_stream);
792 break;
793 case DATA_CHANNEL_OPEN_RESPONSE:
794 if (length < sizeof(struct rtcweb_datachannel_open_response)) {
795 /* XXX: error handling? */
796 return;
797 }
798 rsp = (struct rtcweb_datachannel_open_response *)buffer;
799 handle_open_response_message(pc, rsp, length, i_stream);
800 break;
801 case DATA_CHANNEL_ACK:
802 if (length < sizeof(struct rtcweb_datachannel_ack)) {
803 /* XXX: error handling? */
804 return;
805 }
806 ack = (struct rtcweb_datachannel_ack *)buffer;
807 handle_open_ack_message(pc, ack, length, i_stream);
808 break;
809 default:
810 handle_unknown_message(buffer, length, i_stream);
811 break;
812 }
813 break;
814 case DATA_CHANNEL_PPID_DOMSTRING:
815 case DATA_CHANNEL_PPID_BINARY:
816 handle_data_message(pc, buffer, length, i_stream);
817 break;
818 default:
819 printf("Message of length %zu, PPID %u on stream %u received.\n",
820 length, ppid, i_stream);
821 break;
822 }
823}
824
825static void
826handle_association_change_event(struct sctp_assoc_change *sac)
827{
828 unsigned int i, n;
829
830 printf("Association change ");
831 switch (sac->sac_state) {
832 case SCTP_COMM_UP:
833 printf("SCTP_COMM_UP");
834 break;
835 case SCTP_COMM_LOST:
836 printf("SCTP_COMM_LOST");
837 break;
838 case SCTP_RESTART:
839 printf("SCTP_RESTART");
840 break;
841 case SCTP_SHUTDOWN_COMP:
842 printf("SCTP_SHUTDOWN_COMP");
843 break;
844 case SCTP_CANT_STR_ASSOC:
845 printf("SCTP_CANT_STR_ASSOC");
846 break;
847 default:
848 printf("UNKNOWN");
849 break;
850 }
851 printf(", streams (in/out) = (%u/%u)",
852 sac->sac_inbound_streams, sac->sac_outbound_streams);
853 n = sac->sac_length - sizeof(struct sctp_assoc_change);
854 if (((sac->sac_state == SCTP_COMM_UP) ||
855 (sac->sac_state == SCTP_RESTART)) && (n > 0)) {
856 printf(", supports");
857 for (i = 0; i < n; i++) {
858 switch (sac->sac_info[i]) {
859 case SCTP_ASSOC_SUPPORTS_PR:
860 printf(" PR");
861 break;
862 case SCTP_ASSOC_SUPPORTS_AUTH:
863 printf(" AUTH");
864 break;
865 case SCTP_ASSOC_SUPPORTS_ASCONF:
866 printf(" ASCONF");
867 break;
868 case SCTP_ASSOC_SUPPORTS_MULTIBUF:
869 printf(" MULTIBUF");
870 break;
871 case SCTP_ASSOC_SUPPORTS_RE_CONFIG:
872 printf(" RE-CONFIG");
873 break;
874 default:
875 printf(" UNKNOWN(0x%02x)", sac->sac_info[i]);
876 break;
877 }
878 }
879 } else if (((sac->sac_state == SCTP_COMM_LOST) ||
880 (sac->sac_state == SCTP_CANT_STR_ASSOC)) && (n > 0)) {
881 printf(", ABORT =");
882 for (i = 0; i < n; i++) {
883 printf(" 0x%02x", sac->sac_info[i]);
884 }
885 }
886 printf(".\n");
887 if ((sac->sac_state == SCTP_CANT_STR_ASSOC) ||
888 (sac->sac_state == SCTP_SHUTDOWN_COMP) ||
889 (sac->sac_state == SCTP_COMM_LOST)) {
890 exit(0);
891 }
892 return;
893}
894
895static void
896handle_peer_address_change_event(struct sctp_paddr_change *spc)
897{
898 char addr_buf[INET6_ADDRSTRLEN];
899 const char *addr;
900 struct sockaddr_in *sin;
901 struct sockaddr_in6 *sin6;
902
903 switch (spc->spc_aaddr.ss_family) {
904 case AF_INET:
905 sin = (struct sockaddr_in *)&spc->spc_aaddr;
906 addr = inet_ntop(AF_INET, &sin->sin_addr, addr_buf, INET_ADDRSTRLEN);
907 break;
908 case AF_INET6:
909 sin6 = (struct sockaddr_in6 *)&spc->spc_aaddr;
910 addr = inet_ntop(AF_INET6, &sin6->sin6_addr, addr_buf, INET6_ADDRSTRLEN);
911 break;
912 default:
913#ifdef _WIN32
914 _snprintf(addr_buf, INET6_ADDRSTRLEN, "Unknown family %d", spc->spc_aaddr.ss_family);
915#else
916 snprintf(addr_buf, INET6_ADDRSTRLEN, "Unknown family %d", spc->spc_aaddr.ss_family);
917#endif
918 addr = addr_buf;
919 break;
920 }
921 printf("Peer address %s is now ", addr);
922 switch (spc->spc_state) {
923 case SCTP_ADDR_AVAILABLE:
924 printf("SCTP_ADDR_AVAILABLE");
925 break;
926 case SCTP_ADDR_UNREACHABLE:
927 printf("SCTP_ADDR_UNREACHABLE");
928 break;
929 case SCTP_ADDR_REMOVED:
930 printf("SCTP_ADDR_REMOVED");
931 break;
932 case SCTP_ADDR_ADDED:
933 printf("SCTP_ADDR_ADDED");
934 break;
935 case SCTP_ADDR_MADE_PRIM:
936 printf("SCTP_ADDR_MADE_PRIM");
937 break;
938 case SCTP_ADDR_CONFIRMED:
939 printf("SCTP_ADDR_CONFIRMED");
940 break;
941 default:
942 printf("UNKNOWN");
943 break;
944 }
945 printf(" (error = 0x%08x).\n", spc->spc_error);
946 return;
947}
948
949static void
950handle_adaptation_indication(struct sctp_adaptation_event *sai)
951{
952 printf("Adaptation indication: %x.\n", sai-> sai_adaptation_ind);
953 return;
954}
955
956static void
957handle_shutdown_event(struct sctp_shutdown_event *sse)
958{
959 printf("Shutdown event.\n");
960 /* XXX: notify all channels. */
961 return;
962}
963
964static void
965handle_stream_reset_event(struct peer_connection *pc, struct sctp_stream_reset_event *strrst)
966{
967 uint32_t n, i;
968 struct channel *channel;
969
970 n = (strrst->strreset_length - sizeof(struct sctp_stream_reset_event)) / sizeof(uint16_t);
971 printf("Stream reset event: flags = %x, ", strrst->strreset_flags);
972 if (strrst->strreset_flags & SCTP_STREAM_RESET_INCOMING_SSN) {
973 if (strrst->strreset_flags & SCTP_STREAM_RESET_OUTGOING_SSN) {
974 printf("incoming/");
975 }
976 printf("incoming ");
977 }
978 if (strrst->strreset_flags & SCTP_STREAM_RESET_OUTGOING_SSN) {
979 printf("outgoing ");
980 }
981 printf("stream ids = ");
982 for (i = 0; i < n; i++) {
983 if (i > 0) {
984 printf(", ");
985 }
986 printf("%d", strrst->strreset_stream_list[i]);
987 }
988 printf(".\n");
989 if (!(strrst->strreset_flags & SCTP_STREAM_RESET_DENIED) &&
990 !(strrst->strreset_flags & SCTP_STREAM_RESET_FAILED)) {
991 for (i = 0; i < n; i++) {
992 if (strrst->strreset_flags & SCTP_STREAM_RESET_INCOMING_SSN) {
993 channel = find_channel_by_i_stream(pc, strrst->strreset_stream_list[i]);
994 if (channel != NULL) {
995 pc->i_stream_channel[channel->i_stream] = NULL;
996 channel->i_stream = 0;
997 if (channel->o_stream == 0) {
998 channel->pr_policy = SCTP_PR_SCTP_NONE;
999 channel->pr_value = 0;
1000 channel->unordered = 0;
1001 channel->flags = 0;
1002 channel->state = DATA_CHANNEL_CLOSED;
1003 } else {
1004 if (channel->state == DATA_CHANNEL_OPEN) {
1005 reset_outgoing_stream(pc, channel->o_stream);
1006 channel->state = DATA_CHANNEL_CLOSING;
1007 } else {
1008 /* XXX: What to do? */
1009 }
1010 }
1011 }
1012 }
1013 if (strrst->strreset_flags & SCTP_STREAM_RESET_OUTGOING_SSN) {
1014 channel = find_channel_by_o_stream(pc, strrst->strreset_stream_list[i]);
1015 if (channel != NULL) {
1016 pc->o_stream_channel[channel->o_stream] = NULL;
1017 channel->o_stream = 0;
1018 if (channel->i_stream == 0) {
1019 channel->pr_policy = SCTP_PR_SCTP_NONE;
1020 channel->pr_value = 0;
1021 channel->unordered = 0;
1022 channel->flags = 0;
1023 channel->state = DATA_CHANNEL_CLOSED;
1024 }
1025 }
1026 }
1027 }
1028 }
1029 return;
1030}
1031
1032static void
1033handle_stream_change_event(struct peer_connection *pc, struct sctp_stream_change_event *strchg)
1034{
1035 uint16_t o_stream;
1036 uint32_t i;
1037 struct channel *channel;
1038
1039 printf("Stream change event: streams (in/out) = (%u/%u), flags = %x.\n",
1040 strchg->strchange_instrms, strchg->strchange_outstrms, strchg->strchange_flags);
1041 for (i = 0; i < NUMBER_OF_CHANNELS; i++) {
1042 channel = &(pc->channels[i]);
1043 if ((channel->state == DATA_CHANNEL_CONNECTING) &&
1044 (channel->o_stream == 0)) {
1045 if ((strchg->strchange_flags & SCTP_STREAM_CHANGE_DENIED) ||
1046 (strchg->strchange_flags & SCTP_STREAM_CHANGE_FAILED)) {
1047 /* XXX: Signal to the other end. */
1048 if (channel->i_stream != 0) {
1049 pc->i_stream_channel[channel->i_stream] = NULL;
1050 }
1051 channel->unordered = 0;
1052 channel->pr_policy = SCTP_PR_SCTP_NONE;
1053 channel->pr_value = 0;
1054 channel->i_stream = 0;
1055 channel->o_stream = 0;
1056 channel->flags = 0;
1057 channel->state = DATA_CHANNEL_CLOSED;
1058 } else {
1059 o_stream = find_free_o_stream(pc);
1060 if (o_stream != 0) {
1061 channel->o_stream = o_stream;
1062 pc->o_stream_channel[o_stream] = channel;
1063 if (channel->i_stream == 0) {
1064 channel->flags |= DATA_CHANNEL_FLAGS_SEND_REQ;
1065 } else {
1066 channel->flags |= DATA_CHANNEL_FLAGS_SEND_RSP;
1067 }
1068 } else {
1069 /* We will not find more ... */
1070 break;
1071 }
1072 }
1073 }
1074 }
1075 return;
1076}
1077
1078static void
1079handle_remote_error_event(struct sctp_remote_error *sre)
1080{
1081 size_t i, n;
1082
1083 n = sre->sre_length - sizeof(struct sctp_remote_error);
1084 printf("Remote Error (error = 0x%04x): ", sre->sre_error);
1085 for (i = 0; i < n; i++) {
1086 printf(" 0x%02x", sre-> sre_data[i]);
1087 }
1088 printf(".\n");
1089 return;
1090}
1091
1092static void
1093handle_send_failed_event(struct sctp_send_failed_event *ssfe)
1094{
1095 size_t i, n;
1096
1097 if (ssfe->ssfe_flags & SCTP_DATA_UNSENT) {
1098 printf("Unsent ");
1099 }
1100 if (ssfe->ssfe_flags & SCTP_DATA_SENT) {
1101 printf("Sent ");
1102 }
1103 if (ssfe->ssfe_flags & ~(SCTP_DATA_SENT | SCTP_DATA_UNSENT)) {
1104 printf("(flags = %x) ", ssfe->ssfe_flags);
1105 }
1106 printf("message with PPID = %d, SID = %d, flags: 0x%04x due to error = 0x%08x",
1107 ntohl(ssfe->ssfe_info.snd_ppid), ssfe->ssfe_info.snd_sid,
1108 ssfe->ssfe_info.snd_flags, ssfe->ssfe_error);
1109 n = ssfe->ssfe_length - sizeof(struct sctp_send_failed_event);
1110 for (i = 0; i < n; i++) {
1111 printf(" 0x%02x", ssfe->ssfe_data[i]);
1112 }
1113 printf(".\n");
1114 return;
1115}
1116
1117static void
1118handle_notification(struct peer_connection *pc, union sctp_notification *notif, size_t n)
1119{
1120 if (notif->sn_header.sn_length != (uint32_t)n) {
1121 return;
1122 }
1123 switch (notif->sn_header.sn_type) {
1124 case SCTP_ASSOC_CHANGE:
1125 handle_association_change_event(&(notif->sn_assoc_change));
1126 break;
1127 case SCTP_PEER_ADDR_CHANGE:
1128 handle_peer_address_change_event(&(notif->sn_paddr_change));
1129 break;
1130 case SCTP_REMOTE_ERROR:
1131 handle_remote_error_event(&(notif->sn_remote_error));
1132 break;
1133 case SCTP_SHUTDOWN_EVENT:
1134 handle_shutdown_event(&(notif->sn_shutdown_event));
1135 break;
1136 case SCTP_ADAPTATION_INDICATION:
1137 handle_adaptation_indication(&(notif->sn_adaptation_event));
1138 break;
1139 case SCTP_PARTIAL_DELIVERY_EVENT:
1140 break;
1141 case SCTP_AUTHENTICATION_EVENT:
1142 break;
1143 case SCTP_SENDER_DRY_EVENT:
1144 break;
1145 case SCTP_NOTIFICATIONS_STOPPED_EVENT:
1146 break;
1147 case SCTP_SEND_FAILED_EVENT:
1148 handle_send_failed_event(&(notif->sn_send_failed_event));
1149 break;
1150 case SCTP_STREAM_RESET_EVENT:
1151 handle_stream_reset_event(pc, &(notif->sn_strreset_event));
1152 send_deferred_messages(pc);
1153 send_outgoing_stream_reset(pc);
1154 request_more_o_streams(pc);
1155 break;
1156 case SCTP_ASSOC_RESET_EVENT:
1157 break;
1158 case SCTP_STREAM_CHANGE_EVENT:
1159 handle_stream_change_event(pc, &(notif->sn_strchange_event));
1160 send_deferred_messages(pc);
1161 send_outgoing_stream_reset(pc);
1162 request_more_o_streams(pc);
1163 break;
1164 default:
1165 break;
1166 }
1167}
1168
1169static void
1170print_status(struct peer_connection *pc)
1171{
1172 struct sctp_status status;
1173 socklen_t len;
1174 uint32_t i;
1175 struct channel *channel;
1176
1177 len = (socklen_t)sizeof(struct sctp_status);
1178 if (usrsctp_getsockopt(pc->sock, IPPROTO_SCTP, SCTP_STATUS, &status, &len) < 0) {
1179 perror("getsockopt");
1180 return;
1181 }
1182 printf("Association state: ");
1183 switch (status.sstat_state) {
1184 case SCTP_CLOSED:
1185 printf("CLOSED\n");
1186 break;
1187 case SCTP_BOUND:
1188 printf("BOUND\n");
1189 break;
1190 case SCTP_LISTEN:
1191 printf("LISTEN\n");
1192 break;
1193 case SCTP_COOKIE_WAIT:
1194 printf("COOKIE_WAIT\n");
1195 break;
1196 case SCTP_COOKIE_ECHOED:
1197 printf("COOKIE_ECHOED\n");
1198 break;
1199 case SCTP_ESTABLISHED:
1200 printf("ESTABLISHED\n");
1201 break;
1202 case SCTP_SHUTDOWN_PENDING:
1203 printf("SHUTDOWN_PENDING\n");
1204 break;
1205 case SCTP_SHUTDOWN_SENT:
1206 printf("SHUTDOWN_SENT\n");
1207 break;
1208 case SCTP_SHUTDOWN_RECEIVED:
1209 printf("SHUTDOWN_RECEIVED\n");
1210 break;
1211 case SCTP_SHUTDOWN_ACK_SENT:
1212 printf("SHUTDOWN_ACK_SENT\n");
1213 break;
1214 default:
1215 printf("UNKNOWN\n");
1216 break;
1217 }
1218 printf("Number of streams (i/o) = (%u/%u)\n",
1219 status.sstat_instrms, status.sstat_outstrms);
1220 for (i = 0; i < NUMBER_OF_CHANNELS; i++) {
1221 channel = &(pc->channels[i]);
1222 if (channel->state == DATA_CHANNEL_CLOSED) {
1223 continue;
1224 }
1225 printf("Channel with id = %u: state ", channel->id);
1226 switch (channel->state) {
1227 case DATA_CHANNEL_CLOSED:
1228 printf("CLOSED");
1229 break;
1230 case DATA_CHANNEL_CONNECTING:
1231 printf("CONNECTING");
1232 break;
1233 case DATA_CHANNEL_OPEN:
1234 printf("OPEN");
1235 break;
1236 case DATA_CHANNEL_CLOSING:
1237 printf("CLOSING");
1238 break;
1239 default:
1240 printf("UNKNOWN(%d)", channel->state);
1241 break;
1242 }
1243 printf(", flags = 0x%08x, stream id (in/out): (%u/%u), ",
1244 channel->flags,
1245 channel->i_stream,
1246 channel->o_stream);
1247 if (channel->unordered) {
1248 printf("unordered, ");
1249 } else {
1250 printf("ordered, ");
1251 }
1252 switch (channel->pr_policy) {
1253 case SCTP_PR_SCTP_NONE:
1254 printf("reliable.\n");
1255 break;
1256 case SCTP_PR_SCTP_TTL:
1257 printf("unreliable (timeout %ums).\n", channel->pr_value);
1258 break;
1259 case SCTP_PR_SCTP_RTX:
1260 printf("unreliable (max. %u rtx).\n", channel->pr_value);
1261 break;
1262 default:
1263 printf("unkown policy %u.\n", channel->pr_policy);
1264 break;
1265 }
1266 }
1267}
1268
1269static int
1270receive_cb(struct socket *sock, union sctp_sockstore addr, void *data,
1271 size_t datalen, struct sctp_rcvinfo rcv, int flags, void *ulp_info)
1272{
1273 struct peer_connection *pc;
1274
1275 pc = (struct peer_connection *)ulp_info;
1276
1277 if (data) {
1278 lock_peer_connection(pc);
1279 if (flags & MSG_NOTIFICATION) {
1280 handle_notification(pc, (union sctp_notification *)data, datalen);
1281 } else {
1282 handle_message(pc, data, datalen, ntohl(rcv.rcv_ppid), rcv.rcv_sid);
1283 }
1284 unlock_peer_connection(pc);
1285 }
1286 return (1);
1287}
1288
1289void
1290debug_printf(const char *format, ...)
1291{
1292 va_list ap;
1293
1294 va_start(ap, format);
1295 vprintf(format, ap);
1296 va_end(ap);
1297}
1298
1299int
1300main(int argc, char *argv[])
1301{
1302 struct socket *sock;
1303 struct sockaddr_in addr;
1304 socklen_t addr_len;
1305 char line[LINE_LENGTH + 1];
1306 unsigned int unordered, policy, value, id, seconds;
1307 unsigned int i;
1308 struct channel *channel;
1309 const int on = 1;
1310 struct sctp_assoc_value av;
1311 struct sctp_event event;
1312 struct sctp_udpencaps encaps;
1313 struct sctp_initmsg initmsg;
1314 uint16_t event_types[] = {SCTP_ASSOC_CHANGE,
1315 SCTP_PEER_ADDR_CHANGE,
1316 SCTP_REMOTE_ERROR,
1317 SCTP_SHUTDOWN_EVENT,
1318 SCTP_ADAPTATION_INDICATION,
1319 SCTP_SEND_FAILED_EVENT,
1320 SCTP_STREAM_RESET_EVENT,
1321 SCTP_STREAM_CHANGE_EVENT};
1322 char addrbuf[INET_ADDRSTRLEN];
1323
1324 if (argc > 1) {
1325 usrsctp_init(atoi(argv[1]), NULL, debug_printf);
1326 } else {
1327 usrsctp_init(9899, NULL, debug_printf);
1328 }
1329#ifdef SCTP_DEBUG
1330 usrsctp_sysctl_set_sctp_debug_on(SCTP_DEBUG_NONE);
1331#endif
1332 usrsctp_sysctl_set_sctp_blackhole(2);
1333
1334 if ((sock = usrsctp_socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP, receive_cb, NULL, 0, &peer_connection)) == NULL) {
1335 perror("socket");
1336 }
1337 init_peer_connection(&peer_connection);
1338 if (argc > 2) {
1339 memset(&encaps, 0, sizeof(struct sctp_udpencaps));
1340 encaps.sue_address.ss_family = AF_INET6;
1341 encaps.sue_port = htons(atoi(argv[2]));
1342 if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_REMOTE_UDP_ENCAPS_PORT, (const void*)&encaps, (socklen_t)sizeof(struct sctp_udpencaps)) < 0) {
1343 perror("setsockopt");
1344 }
1345 }
1346 if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_RECVRCVINFO, &on, sizeof(int)) < 0) {
1347 perror("setsockopt SCTP_RECVRCVINFO");
1348 }
1349 if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_EXPLICIT_EOR, &on, sizeof(int)) < 0) {
1350 perror("setsockopt SCTP_EXPLICIT_EOR");
1351 }
1352 /* Allow resetting streams. */
1353 av.assoc_id = SCTP_ALL_ASSOC;
1354 av.assoc_value = SCTP_ENABLE_RESET_STREAM_REQ | SCTP_ENABLE_CHANGE_ASSOC_REQ;
1355 if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_ENABLE_STREAM_RESET, &av, sizeof(struct sctp_assoc_value)) < 0) {
1356 perror("setsockopt SCTP_ENABLE_STREAM_RESET");
1357 }
1358 /* Enable the events of interest. */
1359 memset(&event, 0, sizeof(event));
1360 event.se_assoc_id = SCTP_ALL_ASSOC;
1361 event.se_on = 1;
1362 for (i = 0; i < sizeof(event_types)/sizeof(uint16_t); i++) {
1363 event.se_type = event_types[i];
1364 if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(event)) < 0) {
1365 perror("setsockopt SCTP_EVENT");
1366 }
1367 }
1368 memset(&initmsg, 0, sizeof(struct sctp_initmsg));
1369 initmsg.sinit_num_ostreams = 5;
1370 initmsg.sinit_max_instreams = 65535;
1371 if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_INITMSG, &initmsg, sizeof(struct sctp_initmsg)) < 0) {
1372 perror("setsockopt SCTP_INITMSG");
1373 }
1374
1375 if (argc == 5) {
1376 /* operating as client */
1377 memset(&addr, 0, sizeof(struct sockaddr_in));
1378 addr.sin_family = AF_INET;
1379#ifdef HAVE_SIN_LEN
1380 addr.sin_len = sizeof(struct sockaddr_in);
1381#endif
1382 if (!inet_pton(AF_INET, argv[3], &addr.sin_addr.s_addr)){
1383 printf("error: invalid address\n");
1384 exit(1);
1385 }
1386 addr.sin_port = htons(atoi(argv[4]));
1387 if (usrsctp_connect(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) {
1388 perror("connect");
1389 }
1390
1391 printf("Connected to %s:%d.\n", inet_ntop(AF_INET, &(addr.sin_addr), addrbuf, INET_ADDRSTRLEN), ntohs(addr.sin_port));
1392 } else if (argc == 4) {
1393 struct socket *conn_sock;
1394
1395 /* operating as server */
1396 memset(&addr, 0, sizeof(struct sockaddr_in));
1397 addr.sin_family = AF_INET;
1398#ifdef HAVE_SIN_LEN
1399 addr.sin_len = sizeof(struct sockaddr_in);
1400#endif
1401 addr.sin_addr.s_addr = INADDR_ANY;
1402 addr.sin_port = htons(atoi(argv[3]));
1403 if (usrsctp_bind(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) {
1404 perror("bind");
1405 }
1406 if (usrsctp_listen(sock, 1) < 0) {
1407 perror("listen");
1408 }
1409 addr_len = (socklen_t)sizeof(struct sockaddr_in);
1410 memset(&addr, 0, sizeof(struct sockaddr_in));
1411 if ((conn_sock = usrsctp_accept(sock, (struct sockaddr *)&addr, &addr_len)) == NULL) {
1412 perror("accept");
1413 }
1414 usrsctp_close(sock);
1415 sock = conn_sock;
1416 printf("Connected to %s:%d.\n", inet_ntop(AF_INET, &(addr.sin_addr), addrbuf, INET_ADDRSTRLEN), ntohs(addr.sin_port));
1417 } else {
1418 printf("Usage: %s local_udp_port remote_udp_port local_port when operating as server\n"
1419 " %s local_udp_port remote_udp_port remote_addr remote_port when operating as client\n",
1420 argv[0], argv[0]);
1421 return (0);
1422 }
1423
1424 lock_peer_connection(&peer_connection);
1425 peer_connection.sock = sock;
1426 unlock_peer_connection(&peer_connection);
1427
1428 for (;;) {
1429#ifdef _WIN32
1430 if (gets_s(line, LINE_LENGTH) == NULL) {
1431#else
1432 if (fgets(line, LINE_LENGTH, stdin) == NULL) {
1433#endif
1434 if (usrsctp_shutdown(sock, SHUT_WR) < 0) {
1435 perror("usrsctp_shutdown");
1436 }
1437 while (usrsctp_finish() != 0) {
1438#ifdef _WIN32
1439 Sleep(1000);
1440#else
1441 sleep(1);
1442#endif
1443 }
1444 break;
1445 }
1446 if (strncmp(line, "?", strlen("?")) == 0 ||
1447 strncmp(line, "help", strlen("help")) == 0) {
1448 printf("Commands:\n"
1449 "open unordered pr_policy pr_value - opens a channel\n"
1450 "close channel - closes the channel\n"
1451 "send channel:string - sends string using channel\n"
1452 "status - prints the status\n"
1453 "sleep n - sleep for n seconds\n"
1454 "help - this message\n");
1455 } else if (strncmp(line, "status", strlen("status")) == 0) {
1456 lock_peer_connection(&peer_connection);
1457 print_status(&peer_connection);
1458 unlock_peer_connection(&peer_connection);
1459 } else if (strncmp(line, "quit", strlen("quit")) == 0) {
1460 if (usrsctp_shutdown(sock, SHUT_WR) < 0) {
1461 perror("usrsctp_shutdown");
1462 }
1463 while (usrsctp_finish() != 0) {
1464#ifdef _WIN32
1465 Sleep(1000);
1466#else
1467 sleep(1);
1468#endif
1469 }
1470 break;
1471 } else if (sscanf(line, "open %u %u %u", &unordered, &policy, &value) == 3) {
1472 lock_peer_connection(&peer_connection);
1473 channel = open_channel(&peer_connection, (uint8_t)unordered, (uint16_t)policy, (uint32_t)value);
1474 unlock_peer_connection(&peer_connection);
1475 if (channel == NULL) {
1476 printf("Creating channel failed.\n");
1477 } else {
1478 printf("Channel with id %u created.\n", channel->id);
1479 }
1480 } else if (sscanf(line, "close %u", &id) == 1) {
1481 if (id < NUMBER_OF_CHANNELS) {
1482 lock_peer_connection(&peer_connection);
1483 close_channel(&peer_connection, &peer_connection.channels[id]);
1484 unlock_peer_connection(&peer_connection);
1485 }
1486 } else if (sscanf(line, "send %u", &id) == 1) {
1487 if (id < NUMBER_OF_CHANNELS) {
1488 char *msg;
1489
1490 msg = strstr(line, ":");
1491 if (msg) {
1492 msg++;
1493 lock_peer_connection(&peer_connection);
1494#ifdef _WIN32
1495 if (send_user_message(&peer_connection, &peer_connection.channels[id], msg, strlen(msg))) {
1496#else
1497 if (send_user_message(&peer_connection, &peer_connection.channels[id], msg, strlen(msg) - 1)) {
1498#endif
1499 printf("Message sent.\n");
1500 } else {
1501 printf("Message sending failed.\n");
1502 }
1503 unlock_peer_connection(&peer_connection);
1504 }
1505 }
1506 } else if (sscanf(line, "sleep %u", &seconds) == 1) {
1507#ifdef _WIN32
1508 Sleep(seconds * 1000);
1509#else
1510 sleep(seconds);
1511#endif
1512 } else {
1513 printf("Unknown command: %s", line);
1514 }
1515 }
1516 return (0);
1517}