source: trunk/sources/thelib/src/protocols/rtmp/inboundhttp4rtmp.cpp @ 759

Revision 759, 6.1 KB checked in by shiretu, 8 weeks ago (diff)

-- fixed various bugs related to the new way in which the new xcode compiler is reporting errors

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
21#ifdef HAS_PROTOCOL_HTTP
22#ifdef HAS_PROTOCOL_RTMP
23#include "protocols/rtmp/inboundhttp4rtmp.h"
24#include "protocols/http/inboundhttpprotocol.h"
25#include "netio/netio.h"
26#include "protocols/rtmp/inboundrtmpprotocol.h"
27#include "protocols/protocolmanager.h"
28
29map<string, string> InboundHTTP4RTMP::_generatedSids;
30map<string, uint32_t> InboundHTTP4RTMP::_protocolsBySid;
31
32InboundHTTP4RTMP::InboundHTTP4RTMP()
33: BaseProtocol(PT_INBOUND_HTTP_FOR_RTMP) {
34
35}
36
37InboundHTTP4RTMP::~InboundHTTP4RTMP() {
38}
39
40bool InboundHTTP4RTMP::Initialize(Variant &parameters) {
41        GetCustomParameters() = parameters;
42        return true;
43}
44
45bool InboundHTTP4RTMP::AllowFarProtocol(uint64_t type) {
46        return type == PT_INBOUND_HTTP;
47}
48
49bool InboundHTTP4RTMP::AllowNearProtocol(uint64_t type) {
50        return (type == PT_INBOUND_RTMP) || (type == PT_RTMPE);
51}
52
53IOBuffer * InboundHTTP4RTMP::GetOutputBuffer() {
54        if (GETAVAILABLEBYTESCOUNT(_outputBuffer) != 0) {
55                return &_outputBuffer;
56        }
57        return NULL;
58}
59
60bool InboundHTTP4RTMP::SignalInputData(int32_t recvAmount) {
61        ASSERT("OPERATION NOT SUPPORTED");
62        return false;
63}
64
65bool InboundHTTP4RTMP::SignalInputData(IOBuffer &buffer) {
66        //1. Get the HTTP far protool and test to see if it has ContentLength
67        InboundHTTPProtocol *pHTTP = (InboundHTTPProtocol *) _pFarProtocol;
68        if (pHTTP == NULL || pHTTP->GetContentLength() == 0) {
69                FATAL("Invalid HTTP request");
70                return false;
71        }
72
73        //2. Test it and see if all the data was transfered
74        if (!pHTTP->TransferCompleted()) {
75                return true;
76        }
77
78        //3. Get the HTTP request
79        Variant request = pHTTP->GetHeaders();
80
81        //4. Is this a keep-alive?
82        pHTTP->SetDisconnectAfterTransfer(
83                        request[HTTP_HEADERS][HTTP_HEADERS_CONNECTION]
84                        != HTTP_HEADERS_CONNECTION_KEEP_ALIVE);
85        DeleteNearProtocol(false);
86
87        //4. Get the URL
88        string url = request[HTTP_FIRST_LINE][HTTP_URL];
89
90        //5. split it in meaningful parts
91        vector<string> parts;
92        split(url, "/", parts);
93        if (parts.size() < 2) {
94                FATAL("Invalid request:\n%s", STR(request.ToString()));
95                return false;
96        }
97
98        //7. Do the dammage
99        bool result;
100        if (parts[1] == "fcs") {
101                result = ProcessFcs(parts);
102                buffer.Ignore(pHTTP->GetContentLength());
103        } else if (parts[1] == "open") {
104                result = ProcessOpen(parts);
105                buffer.Ignore(pHTTP->GetContentLength());
106        } else if (parts[1] == "idle") {
107                result = ProcessIdle(parts);
108                buffer.Ignore(pHTTP->GetContentLength());
109        } else if (parts[1] == "send") {
110                if (GETAVAILABLEBYTESCOUNT(buffer) < 1)
111                        return false;
112                _inputBuffer.ReadFromBuffer(GETIBPOINTER(buffer), pHTTP->GetContentLength());
113                buffer.Ignore(pHTTP->GetContentLength());
114                result = ProcessSend(parts);
115        } else {
116                FATAL("Invalid command: %s", STR(parts[1]));
117                result = false;
118        }
119
120        //8. Cleanup
121        if (!result) {
122                DeleteNearProtocol(true);
123                EnqueueForDelete();
124        }
125
126        //9. Done
127        return result;
128}
129
130bool InboundHTTP4RTMP::EnqueueForOutbound() {
131        return true;
132}
133
134void InboundHTTP4RTMP::ReadyForSend() {
135        if (_pNearProtocol != NULL) {
136                _pNearProtocol->ReadyForSend();
137        }
138}
139
140BaseProtocol *InboundHTTP4RTMP::Bind(string sid) {
141        BaseProtocol *pResult = NULL;
142        if (_pNearProtocol == NULL) {
143                //14. This might be a new connection. Do we have that sid generated?
144                if (!MAP_HAS1(_generatedSids, sid)) {
145                        FATAL("Invalid sid: %s", STR(sid));
146                        return NULL;
147                }
148
149                //15. See if we have to generate a new connection or we just pick up
150                //a disconnected one
151                if (MAP_HAS1(_protocolsBySid, sid)) {
152                        pResult = ProtocolManager::GetProtocol(_protocolsBySid[sid]);
153                } else {
154                        pResult = new InboundRTMPProtocol();
155                        pResult->Initialize(GetCustomParameters());
156                        pResult->SetApplication(GetApplication());
157                        _protocolsBySid[sid] = pResult->GetId();
158                        SetNearProtocol(pResult);
159                        pResult->SetFarProtocol(this);
160                }
161        } else {
162                pResult = _pNearProtocol;
163        }
164
165        return pResult;
166}
167
168bool InboundHTTP4RTMP::ProcessFcs(vector<string> &parts) {
169        _outputBuffer.ReadFromString(((TCPCarrier *) GetIOHandler())->GetNearEndpointAddressIp() + "\n");
170        return BaseProtocol::EnqueueForOutbound();
171}
172
173bool InboundHTTP4RTMP::ProcessOpen(vector<string> &parts) {
174        if (parts.size() != 3) {
175                return false;
176        }
177        if (parts[2] != "1") {
178                return false;
179        }
180
181        //2. create a SID, save it, and send it after that
182        string sid = md5(format("%u", GetId()), true).substr(0, 16);
183        _generatedSids[sid] = sid;
184        _outputBuffer.ReadFromString(sid + "\n");
185
186        //3. We are done
187        return BaseProtocol::EnqueueForOutbound();
188}
189
190bool InboundHTTP4RTMP::ProcessIdle(vector<string> &parts) {
191
192        BaseProtocol *pProtocol = Bind(parts[2]);
193        if (pProtocol == NULL) {
194                FATAL("Unable to bind protocol");
195                return false;
196        }
197
198        _outputBuffer.ReadFromByte(1);
199        IOBuffer *pBuffer = pProtocol->GetOutputBuffer();
200        if (pBuffer != NULL) {
201                _outputBuffer.ReadFromBuffer(GETIBPOINTER(*pBuffer), GETAVAILABLEBYTESCOUNT(*pBuffer));
202                pBuffer->IgnoreAll();
203        }
204
205        return BaseProtocol::EnqueueForOutbound();
206}
207
208bool InboundHTTP4RTMP::ProcessSend(vector<string> &parts) {
209        BaseProtocol *pProtocol = Bind(parts[2]);
210        if (pProtocol == NULL) {
211                FATAL("Unable to bind protocol");
212                return false;
213        }
214
215        if (!pProtocol->SignalInputData(_inputBuffer)) {
216                FATAL("Unable to call upper protocol");
217                return false;
218        }
219
220        _outputBuffer.ReadFromByte(1);
221        IOBuffer *pBuffer = pProtocol->GetOutputBuffer();
222        if (pBuffer != NULL) {
223                _outputBuffer.ReadFromBuffer(GETIBPOINTER(*pBuffer), GETAVAILABLEBYTESCOUNT(*pBuffer));
224                pBuffer->IgnoreAll();
225        }
226
227        return BaseProtocol::EnqueueForOutbound();
228}
229#endif /* HAS_PROTOCOL_RTMP */
230#endif /* HAS_PROTOCOL_HTTP */
231
232
Note: See TracBrowser for help on using the repository browser.