1 /**
2  * @file srtp/stream.c  Secure Real-time Transport Protocol (SRTP) -- stream
3  *
4  * Copyright (C) 2010 Creytiv.com
5  */
6 #include <re_types.h>
7 #include <re_mem.h>
8 #include <re_mbuf.h>
9 #include <re_list.h>
10 #include <re_aes.h>
11 #include <re_srtp.h>
12 #include "srtp.h"
13 
14 
15 /** SRTP protocol values */
16 #ifndef SRTP_MAX_STREAMS
17 #define SRTP_MAX_STREAMS  (8)  /**< Maximum number of SRTP streams */
18 #endif
19 
20 
stream_destructor(void * arg)21 static void stream_destructor(void *arg)
22 {
23 	struct srtp_stream *strm = arg;
24 
25 	list_unlink(&strm->le);
26 }
27 
28 
stream_find(struct srtp * srtp,uint32_t ssrc)29 static struct srtp_stream *stream_find(struct srtp *srtp, uint32_t ssrc)
30 {
31 	struct le *le;
32 
33 	for (le = srtp->streaml.head; le; le = le->next) {
34 
35 		struct srtp_stream *strm = le->data;
36 
37 		if (strm->ssrc == ssrc)
38 			return strm;
39 	}
40 
41 	return NULL;
42 }
43 
44 
stream_new(struct srtp_stream ** strmp,struct srtp * srtp,uint32_t ssrc)45 static int stream_new(struct srtp_stream **strmp, struct srtp *srtp,
46 		      uint32_t ssrc)
47 {
48 	struct srtp_stream *strm;
49 
50 	if (list_count(&srtp->streaml) >= SRTP_MAX_STREAMS)
51 		return ENOSR;
52 
53 	strm = mem_zalloc(sizeof(*strm), stream_destructor);
54 	if (!strm)
55 		return ENOMEM;
56 
57 	strm->ssrc = ssrc;
58 	srtp_replay_init(&strm->replay_rtp);
59 	srtp_replay_init(&strm->replay_rtcp);
60 
61 	list_append(&srtp->streaml, &strm->le, strm);
62 
63 	if (strmp)
64 		*strmp = strm;
65 
66 	return 0;
67 }
68 
69 
stream_get(struct srtp_stream ** strmp,struct srtp * srtp,uint32_t ssrc)70 int stream_get(struct srtp_stream **strmp, struct srtp *srtp, uint32_t ssrc)
71 {
72 	struct srtp_stream *strm;
73 
74 	if (!strmp || !srtp)
75 		return EINVAL;
76 
77 	strm = stream_find(srtp, ssrc);
78 	if (strm) {
79 		*strmp = strm;
80 		return 0;
81 	}
82 
83 	return stream_new(strmp, srtp, ssrc);
84 }
85 
86 
stream_get_seq(struct srtp_stream ** strmp,struct srtp * srtp,uint32_t ssrc,uint16_t seq)87 int stream_get_seq(struct srtp_stream **strmp, struct srtp *srtp,
88 		   uint32_t ssrc, uint16_t seq)
89 {
90 	struct srtp_stream *strm;
91 	int err;
92 
93 	if (!strmp || !srtp)
94 		return EINVAL;
95 
96 	err = stream_get(&strm, srtp, ssrc);
97 	if (err)
98 		return err;
99 
100 	/* Set the initial sequence number once only */
101 	if (!strm->s_l_set) {
102 		strm->s_l = seq;
103 		strm->s_l_set = true;
104 	}
105 
106 	*strmp = strm;
107 
108 	return 0;
109 }
110