]> git.sesse.net Git - vlc/blob - modules/stream_filter/dash/http/HTTPConnectionManager.cpp
dash: Don't crash when a segment can't be accessed.
[vlc] / modules / stream_filter / dash / http / HTTPConnectionManager.cpp
1 /*
2  * HTTPConnectionManager.cpp
3  *****************************************************************************
4  * Copyright (C) 2010 - 2011 Klagenfurt University
5  *
6  * Created on: Aug 10, 2010
7  * Authors: Christopher Mueller <christopher.mueller@itec.uni-klu.ac.at>
8  *          Christian Timmerer  <christian.timmerer@itec.uni-klu.ac.at>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU Lesser General Public License as published
12  * by the Free Software Foundation; either version 2.1 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24 #ifdef HAVE_CONFIG_H
25 # include "config.h"
26 #endif
27
28 #include "HTTPConnectionManager.h"
29
30 using namespace dash::http;
31 using namespace dash::logic;
32
33 HTTPConnectionManager::HTTPConnectionManager    (stream_t *stream)
34 {
35     this->timeSecSession    = 0;
36     this->bytesReadSession  = 0;
37     this->timeSecChunk      = 0;
38     this->bytesReadChunk    = 0;
39     this->bpsAvg            = 0;
40     this->bpsLastChunk      = 0;
41     this->chunkCount        = 0;
42     this->stream            = stream;
43 }
44 HTTPConnectionManager::~HTTPConnectionManager   ()
45 {
46     this->closeAllConnections();
47 }
48
49 bool                HTTPConnectionManager::closeConnection          (IHTTPConnection *con)
50 {
51     for(std::vector<HTTPConnection *>::iterator it = this->connections.begin(); it != this->connections.end(); ++it)
52     {
53         if(*it == con)
54         {
55             (*it)->closeSocket();
56             delete(*it);
57             this->connections.erase(it);
58             return true;
59         }
60     }
61     return false;
62 }
63 bool                HTTPConnectionManager::closeConnection          (Chunk *chunk)
64 {
65     HTTPConnection *con = this->chunkMap[chunk];
66     bool ret = this->closeConnection(con);
67     this->chunkMap.erase(chunk);
68     delete(chunk);
69     return ret;
70 }
71 void                HTTPConnectionManager::closeAllConnections      ()
72 {
73     for(std::vector<HTTPConnection *>::iterator it = this->connections.begin(); it != this->connections.end(); ++it)
74     {
75         (*it)->closeSocket();
76         delete(*it);
77     }
78     this->connections.clear();
79     this->urlMap.clear();
80
81     std::map<Chunk *, HTTPConnection *>::iterator it;
82
83     for(it = this->chunkMap.begin(); it != this->chunkMap.end(); ++it)
84     {
85         delete(it->first);
86     }
87
88     this->chunkMap.clear();
89 }
90 int                 HTTPConnectionManager::read                     (Chunk *chunk, void *p_buffer, size_t len)
91 {
92     if(this->chunkMap.find(chunk) != this->chunkMap.end())
93     {
94         mtime_t start = mdate();
95         int ret = this->chunkMap[chunk]->read(p_buffer, len);
96         mtime_t end = mdate();
97
98         double time = ((double)(end - start)) / 1000000;
99
100         this->bytesReadSession += ret;
101         this->bytesReadChunk   += ret;
102         this->timeSecSession   += time;
103         this->timeSecChunk     += time;
104
105
106         if(this->timeSecSession > 0)
107             this->bpsAvg = (this->bytesReadSession / this->timeSecSession) * 8;
108
109         if(this->timeSecChunk > 0)
110             this->bpsLastChunk = (this->bytesReadChunk / this->timeSecChunk) * 8;
111
112         if(this->bpsAvg < 0 || this->chunkCount < 2)
113             this->bpsAvg = 0;
114
115         if(this->bpsLastChunk < 0 || this->chunkCount < 2)
116             this->bpsLastChunk = 0;
117
118         this->notify();
119
120         if(ret <= 0)
121             this->closeConnection(chunk);
122
123         return ret;
124     }
125     else
126     {
127         this->bytesReadChunk    = 0;
128         this->timeSecChunk      = 0;
129
130         if ( this->initConnection(chunk) == NULL )
131             return -1;
132         return this->read(chunk, p_buffer, len);
133     }
134 }
135 int                 HTTPConnectionManager::peek                     (Chunk *chunk, const uint8_t **pp_peek, size_t i_peek)
136 {
137     if(this->chunkMap.find(chunk) != this->chunkMap.end())
138         return this->chunkMap[chunk]->peek(pp_peek, i_peek);
139
140     if ( this->initConnection(chunk) == NULL )
141         return -1;
142     return this->peek(chunk, pp_peek, i_peek);
143 }
144
145 IHTTPConnection*     HTTPConnectionManager::initConnection(Chunk *chunk)
146 {
147     HTTPConnection *con = new HTTPConnection(chunk->getUrl(), this->stream);
148     if ( con->init() == false )
149         return NULL;
150     this->connections.push_back(con);
151     this->chunkMap[chunk] = con;
152     this->chunkCount++;
153     return con;
154 }
155 void                HTTPConnectionManager::attach                   (IDownloadRateObserver *observer)
156 {
157     this->rateObservers.push_back(observer);
158 }
159 void                HTTPConnectionManager::notify                   ()
160 {
161     if ( this->bpsAvg <= 0 )
162         return ;
163     for(size_t i = 0; i < this->rateObservers.size(); i++)
164         this->rateObservers.at(i)->downloadRateChanged(this->bpsAvg, this->bpsLastChunk);
165 }