source: trunk/sources/thelib/src/protocols/rtmp/header_le_sa.cpp @ 749

Revision 749, 8.6 KB checked in by shiretu, 2 months ago (diff)

-- added JSON Variant protocol to the list of Variant protocols
-- added inbound HTTPS variants to the Variant protocol
-- tolerate EINTR when doing kqueue/epoll/select
-- fix for switching from indexvaluexxx to 0xXXXXXXXX notation for Variant indexes
-- fix for invoke id when returning _error and _result
-- support for RTMP Adobe authentication second style (the one without opaque)
-- properly send FCSubscribe and FCPublish invokes
-- fix for RTMP protocol ser/deser to return the parameters as an array for invokes
-- remove the query string from the stream name when FMLE (or someone else) is doing RTMP publish
-- fixed the upstream.tv disconnect problem

Line 
1/*
2 *  Copyright (c) 2010,
3 *  Gavriloaie Eugen-Andrei (shiretu@gmail.com)
4 *
5 *  This file is part of crtmpserver.
6 *  crtmpserver is free software: you can redistribute it and/or modify
7 *  it under the terms of the GNU General Public License as published by
8 *  the Free Software Foundation, either version 3 of the License, or
9 *  (at your option) any later version.
10 *
11 *  crtmpserver is distributed in the hope that it will be useful,
12 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 *  GNU General Public License for more details.
15 *
16 *  You should have received a copy of the GNU General Public License
17 *  along with crtmpserver.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#ifdef HAS_PROTOCOL_RTMP
21#ifdef LITTLE_ENDIAN_SHORT_ALIGNED
22
23#include "protocols/rtmp/header_le_sa.h"
24#include "protocols/rtmp/channel.h"
25
26bool Header::Read(uint32_t channelId, uint8_t type, IOBuffer &buffer,
27                uint32_t availableBytes) {
28        ht = type;
29        ci = channelId;
30
31        switch (ht) {
32                case HT_FULL:
33                {
34                        isAbsolute = true;
35                        if (availableBytes < 11) {
36                                readCompleted = false;
37                                return true;
38                        }
39                        memcpy(hf.datac + 1, GETIBPOINTER(buffer), 11);
40                        hf.s.ts = ENTOHL(hf.s.ts)&0x00ffffff; //----MARKED-LONG---
41                        hf.s.ml = ENTOHL(hf.s.ml) >> 8; //----MARKED-LONG---
42
43                        if (hf.s.ts == 0x00ffffff) {
44                                skip4bytes = true;
45                                if (availableBytes < 15) {
46                                        readCompleted = false;
47                                        return true;
48                                }
49                                hf.s.ts = ENTOHLP(GETIBPOINTER(buffer) + 11);
50                                readCompleted = true;
51                                return buffer.Ignore(15);
52                        } else {
53                                skip4bytes = false;
54                                readCompleted = true;
55                                return buffer.Ignore(11);
56                        }
57                }
58                case HT_SAME_STREAM:
59                {
60                        isAbsolute = false;
61                        if (availableBytes < 7) {
62                                readCompleted = false;
63                                return true;
64                        }
65                        memcpy(hf.datac + 1, GETIBPOINTER(buffer), 7);
66                        hf.s.ts = ENTOHL(hf.s.ts)&0x00ffffff; //----MARKED-LONG---
67                        hf.s.ml = ENTOHL(hf.s.ml) >> 8; //----MARKED-LONG---
68
69                        if (hf.s.ts == 0x00ffffff) {
70                                skip4bytes = true;
71                                if (availableBytes < 11) {
72                                        readCompleted = false;
73                                        return true;
74                                }
75                                hf.s.ts = ENTOHLP(GETIBPOINTER(buffer) + 7);
76                                readCompleted = true;
77                                return buffer.Ignore(11);
78                        } else {
79                                skip4bytes = false;
80                                readCompleted = true;
81                                return buffer.Ignore(7);
82                        }
83                }
84                case HT_SAME_LENGTH_AND_STREAM:
85                {
86                        isAbsolute = false;
87                        if (availableBytes < 3) {
88                                readCompleted = false;
89                                return true;
90                        }
91                        memcpy(hf.datac + 1, GETIBPOINTER(buffer), 3);
92                        hf.s.ts = ENTOHL(hf.s.ts)&0x00ffffff; //----MARKED-LONG---
93
94                        if (hf.s.ts == 0x00ffffff) {
95                                skip4bytes = true;
96                                if (availableBytes < 7) {
97                                        readCompleted = false;
98                                        return true;
99                                }
100                                hf.s.ts = ENTOHLP(GETIBPOINTER(buffer) + 3);
101                                readCompleted = true;
102                                return buffer.Ignore(7);
103                        } else {
104                                skip4bytes = false;
105                                readCompleted = true;
106                                return buffer.Ignore(3);
107                        }
108                }
109                case HT_CONTINUATION:
110                {
111                        isAbsolute = false;
112                        if (skip4bytes) {
113                                if (availableBytes < 4) {
114                                        readCompleted = false;
115                                        return true;
116                                }
117                                readCompleted = true;
118                                return buffer.Ignore(4);
119                        } else {
120                                readCompleted = true;
121                                return true;
122                        }
123                }
124                default:
125                {
126                        FATAL("Invalid header type: %hhu", ht);
127                        return false;
128                }
129        }
130}
131
132Variant Header::GetVariant() {
133
134        Variant result;
135
136
137        result[RM_HEADER_HEADERTYPE] = (uint8_t) ht;
138        result[RM_HEADER_CHANNELID] = (uint32_t) ci;
139        result[RM_HEADER_TIMESTAMP] = (uint32_t) hf.s.ts;
140        result[RM_HEADER_MESSAGELENGTH] = (uint32_t) hf.s.ml;
141        result[RM_HEADER_MESSAGETYPE] = (uint8_t) hf.s.mt;
142        result[RM_HEADER_STREAMID] = (uint32_t) hf.s.si;
143        result[RM_HEADER_ISABSOLUTE] = isAbsolute;
144
145
146        return result;
147}
148
149bool Header::GetFromVariant(Header &header, Variant &variant) {
150        if (variant != V_MAP) {
151                FATAL("Variant is not a map: %s", STR(variant.ToString()));
152                return false;
153        }
154
155        if ((variant[RM_HEADER_HEADERTYPE] != _V_NUMERIC) ||
156                        (variant[RM_HEADER_CHANNELID] != _V_NUMERIC) ||
157                        (variant[RM_HEADER_TIMESTAMP] != _V_NUMERIC) ||
158                        (variant[RM_HEADER_MESSAGELENGTH] != _V_NUMERIC) ||
159                        (variant[RM_HEADER_MESSAGETYPE] != _V_NUMERIC) ||
160                        (variant[RM_HEADER_STREAMID] != _V_NUMERIC) ||
161                        (variant[RM_HEADER_ISABSOLUTE] != V_BOOL)
162                        ) {
163                FATAL("Variant is not a valid RTMP header: %s", STR(variant.ToString()));
164                return false;
165        }
166
167        header.ht = (uint8_t) variant[RM_HEADER_HEADERTYPE];
168        header.ci = (uint32_t) variant[RM_HEADER_CHANNELID];
169        header.hf.s.ts = (uint32_t) variant[RM_HEADER_TIMESTAMP];
170        header.hf.s.ml = (uint32_t) variant[RM_HEADER_MESSAGELENGTH];
171        header.hf.s.mt = (uint8_t) variant[RM_HEADER_MESSAGETYPE];
172        header.hf.s.si = (uint32_t) variant[RM_HEADER_STREAMID];
173        header.readCompleted = true;
174        header.isAbsolute = (bool) variant[RM_HEADER_ISABSOLUTE];
175
176        return true;
177}
178
179bool Header::Write(Channel &channel, IOBuffer &buffer) {
180        //1. Compute the header size
181        if (channel.lastOutStreamId == H_SI(*this)) {
182                if (H_IA(*this)) {
183                        if (channel.lastOutProcBytes == 0) {
184                                H_HT(*this) = HT_FULL;
185                                channel.lastOutAbsTs = H_TS(*this);
186                        } else {
187                                H_HT(*this) = HT_CONTINUATION;
188                        }
189                } else {
190                        if (channel.lastOutProcBytes == 0) {
191                                H_HT(*this) = HT_SAME_STREAM;
192                                if ((H_MT(*this) == H_MT(channel.lastOutHeader)) &&
193                                                (H_ML(*this) == H_ML(channel.lastOutHeader))) {
194                                        H_HT(*this) = HT_SAME_LENGTH_AND_STREAM;
195                                        if (H_TS(*this) == H_TS(channel.lastOutHeader)) {
196                                                H_HT(*this) = HT_CONTINUATION;
197                                        }
198                                }
199                                channel.lastOutAbsTs += H_TS(*this);
200                        } else {
201                                H_HT(*this) = HT_CONTINUATION;
202                        }
203                }
204        } else {
205                H_HT(*this) = HT_FULL;
206                H_IA(*this) = true;
207                channel.lastOutAbsTs = H_TS(*this);
208                channel.lastOutStreamId = H_SI(*this);
209        }
210
211        //2. Save the last sent header
212        channel.lastOutHeader = *this;
213
214        //3. do the write
215        return Write(buffer);
216}
217
218bool Header::Write(IOBuffer &buffer) {
219        if (ci < 64) {
220                buffer.ReadFromByte((ht << 6) | ci);
221        } else if (ci < 319) {
222                buffer.ReadFromByte(ht << 6);
223                buffer.ReadFromByte(ci - 64);
224        } else if (ci < 65599) {
225                uint16_t temp = EHTONS(ci - 64);
226                buffer.ReadFromByte((ht << 6) | 0x01);
227                buffer.ReadFromBuffer((uint8_t *) & temp, 2);
228        } else {
229                FATAL("Invalid channel index");
230                return false;
231        }
232
233        switch (ht) {
234                case HT_FULL:
235                {
236                        if (hf.s.ts < 0x00ffffff) {
237                                hf.s.ts = EHTONL(hf.s.ts); //----MARKED-LONG---
238                                hf.s.ml = EHTONL(hf.s.ml << 8); //----MARKED-LONG---
239                                buffer.ReadFromBuffer(&hf.datac[1], 11);
240                                hf.s.ts = ENTOHL(hf.s.ts); //----MARKED-LONG---
241                                hf.s.ml = ENTOHL(hf.s.ml) >> 8; //----MARKED-LONG---
242                                return true;
243                        } else {
244                                uint32_t temp = EHTONL(hf.s.ts); //----MARKED-LONG---
245                                hf.s.ts = EHTONL(0x00ffffff); //----MARKED-LONG---
246                                hf.s.ml = EHTONL(hf.s.ml << 8); //----MARKED-LONG---
247                                buffer.ReadFromBuffer(&hf.datac[1], 11);
248                                hf.s.ts = ENTOHL(temp); //----MARKED-LONG---
249                                hf.s.ml = ENTOHL(hf.s.ml) >> 8; //----MARKED-LONG---
250                                buffer.ReadFromBuffer((uint8_t *) & temp, 4);
251                                return true;
252                        }
253                }
254                case HT_SAME_STREAM:
255                {
256                        if (hf.s.ts < 0x00ffffff) {
257                                hf.s.ts = EHTONL(hf.s.ts); //----MARKED-LONG---
258                                hf.s.ml = EHTONL(hf.s.ml << 8); //----MARKED-LONG---
259                                buffer.ReadFromBuffer(&hf.datac[1], 7);
260                                hf.s.ts = ENTOHL(hf.s.ts); //----MARKED-LONG---
261                                hf.s.ml = ENTOHL(hf.s.ml) >> 8; //----MARKED-LONG---
262                                return true;
263                        } else {
264                                uint32_t temp = EHTONL(hf.s.ts); //----MARKED-LONG---
265                                hf.s.ts = EHTONL(0x00ffffff); //----MARKED-LONG---
266                                hf.s.ml = EHTONL(hf.s.ml << 8); //----MARKED-LONG---
267                                buffer.ReadFromBuffer(&hf.datac[1], 7);
268                                hf.s.ts = ENTOHL(temp); //----MARKED-LONG---
269                                hf.s.ml = ENTOHL(hf.s.ml) >> 8; //----MARKED-LONG---
270                                buffer.ReadFromBuffer((uint8_t *) & temp, 4);
271                                return true;
272                        }
273                }
274                case HT_SAME_LENGTH_AND_STREAM:
275                {
276                        if (hf.s.ts < 0x00ffffff) {
277                                hf.s.ts = EHTONL(hf.s.ts); //----MARKED-LONG---
278                                buffer.ReadFromBuffer(&hf.datac[1], 3);
279                                hf.s.ts = ENTOHL(hf.s.ts); //----MARKED-LONG---
280                                return true;
281                        } else {
282                                uint32_t temp = EHTONL(hf.s.ts); //----MARKED-LONG---
283                                hf.s.ts = EHTONL(0x00ffffff); //----MARKED-LONG---
284                                buffer.ReadFromBuffer(&hf.datac[1], 3);
285                                hf.s.ts = ENTOHL(temp); //----MARKED-LONG---
286                                buffer.ReadFromBuffer((uint8_t *) & temp, 4);
287                                return true;
288                        }
289                }
290                case HT_CONTINUATION:
291                {
292                        if (hf.s.ts >= 0x00ffffff) {
293                                uint32_t temp = EHTONL(hf.s.ts); //----MARKED-LONG---
294                                buffer.ReadFromBuffer((uint8_t *) & temp, 4);
295                                hf.s.ts = ENTOHL(temp); //----MARKED-LONG---
296                        }
297                        return true;
298                }
299                default:
300                {
301                        FATAL("Invalid header size: %hhu", ht);
302                        return false;
303                }
304        }
305}
306
307Header::operator string() {
308        //      return format("(RC: %hhu; HT: %hhu; CI: %02u; T: % 9u; L: % 6u; MT: % 2u; SI: % 2u; IA: %u)",
309        //                      readCompleted, ht, ci, hf.s.ts, hf.s.ml, hf.s.mt, hf.s.si, isAbsolute);
310        return "Not yet implemented";
311}
312
313
314#endif /* LITTLE_ENDIAN_SHORT_ALIGNED */
315#endif /* HAS_PROTOCOL_RTMP */
Note: See TracBrowser for help on using the repository browser.