1
1
using System ;
2
2
using System . IO ;
3
3
using System . Net ;
4
+ using System . Collections . Generic ;
4
5
using JetBrains . Annotations ;
5
6
using PatchKit . Logging ;
6
7
using PatchKit . Network ;
@@ -14,26 +15,25 @@ public sealed class BaseHttpDownloader : IBaseHttpDownloader
14
15
{
15
16
private readonly ILogger _logger ;
16
17
17
- private static readonly int BufferSize = 5 * ( int ) Units . MB ;
18
+ private static readonly ulong DefaultBufferSize = 5 * ( ulong ) Units . MB ;
18
19
19
20
private readonly string _url ;
20
21
private readonly int _timeout ;
21
22
private readonly IHttpClient _httpClient ;
22
23
24
+ private readonly ulong _bufferSize ;
23
25
private readonly byte [ ] _buffer ;
24
26
25
27
private bool _downloadHasBeenCalled ;
26
28
private BytesRange ? _bytesRange ;
27
29
28
- public event DataAvailableHandler DataAvailable ;
29
-
30
30
public BaseHttpDownloader ( string url , int timeout ) :
31
- this ( url , timeout , new DefaultHttpClient ( ) , PatcherLogManager . DefaultLogger )
31
+ this ( url , timeout , new DefaultHttpClient ( ) , PatcherLogManager . DefaultLogger , DefaultBufferSize )
32
32
{
33
33
}
34
34
35
35
public BaseHttpDownloader ( [ NotNull ] string url , int timeout , [ NotNull ] IHttpClient httpClient ,
36
- [ NotNull ] ILogger logger )
36
+ [ NotNull ] ILogger logger , ulong bufferSize )
37
37
{
38
38
if ( string . IsNullOrEmpty ( url ) ) throw new ArgumentException ( "Value cannot be null or empty." , "url" ) ;
39
39
if ( timeout <= 0 ) throw new ArgumentOutOfRangeException ( "timeout" ) ;
@@ -45,7 +45,8 @@ public BaseHttpDownloader([NotNull] string url, int timeout, [NotNull] IHttpClie
45
45
_httpClient = httpClient ;
46
46
_logger = logger ;
47
47
48
- _buffer = new byte [ BufferSize ] ;
48
+ _bufferSize = bufferSize ;
49
+ _buffer = new byte [ _bufferSize ] ;
49
50
50
51
ServicePointManager . ServerCertificateValidationCallback =
51
52
( sender , certificate , chain , errors ) => true ;
@@ -62,13 +63,26 @@ public void SetBytesRange(BytesRange? range)
62
63
}
63
64
}
64
65
65
- public void Download ( CancellationToken cancellationToken )
66
+ public void Download ( CancellationToken cancellationToken , [ NotNull ] DataAvailableHandler onDataAvailable )
67
+ {
68
+ if ( onDataAvailable == null )
69
+ {
70
+ throw new ArgumentNullException ( "onDataAvailable" ) ;
71
+ }
72
+
73
+ foreach ( DataPacket packet in ReadPackets ( cancellationToken ) )
74
+ {
75
+ onDataAvailable ( packet . Data , packet . Length ) ;
76
+ }
77
+ }
78
+
79
+ public IEnumerable < DataPacket > ReadPackets ( CancellationToken cancellationToken )
66
80
{
67
81
try
68
82
{
69
83
_logger . LogDebug ( "Downloading..." ) ;
70
84
_logger . LogTrace ( "url = " + _url ) ;
71
- _logger . LogTrace ( "bufferSize = " + BufferSize ) ;
85
+ _logger . LogTrace ( "bufferSize = " + _bufferSize ) ;
72
86
_logger . LogTrace ( "bytesRange = " + ( _bytesRange . HasValue
73
87
? _bytesRange . Value . Start + "-" + _bytesRange . Value . End
74
88
: "(none)" ) ) ;
@@ -84,37 +98,7 @@ public void Download(CancellationToken cancellationToken)
84
98
ReadWriteTimeout = _timeout ,
85
99
} ;
86
100
87
- using ( var response = _httpClient . Get ( request ) )
88
- {
89
- cancellationToken . ThrowIfCancellationRequested ( ) ;
90
-
91
- _logger . LogDebug ( "Received response from server." ) ;
92
- _logger . LogTrace ( "statusCode = " + response . StatusCode ) ;
93
-
94
- if ( Is2XXStatus ( response . StatusCode ) )
95
- {
96
- _logger . LogDebug ( "Successful response. Reading response stream..." ) ;
97
-
98
- //TODO: Could response.ContentStream be null? Need to check it.
99
-
100
- ReadResponseStream ( response . ContentStream , cancellationToken ) ;
101
-
102
- _logger . LogDebug ( "Stream has been read." ) ;
103
- }
104
- else if ( Is4XXStatus ( response . StatusCode ) )
105
- {
106
- throw new DataNotAvailableException ( string . Format (
107
- "Request data for {0} is not available (status: {1})" , _url , response . StatusCode ) ) ;
108
- }
109
- else
110
- {
111
- throw new ServerErrorException ( string . Format (
112
- "Server has experienced some issues with request for {0} which resulted in {1} status code." ,
113
- _url , response . StatusCode ) ) ;
114
- }
115
- }
116
-
117
- _logger . LogDebug ( "Downloading finished." ) ;
101
+ return ReadResponseStream ( request , cancellationToken ) ;
118
102
}
119
103
catch ( WebException webException )
120
104
{
@@ -129,14 +113,45 @@ public void Download(CancellationToken cancellationToken)
129
113
}
130
114
}
131
115
132
- private void ReadResponseStream ( Stream responseStream , CancellationToken cancellationToken )
116
+ private IEnumerable < DataPacket > ReadResponseStream ( HttpGetRequest request , CancellationToken cancellationToken )
133
117
{
134
- int bufferRead ;
135
- while ( ( bufferRead = responseStream . Read ( _buffer , 0 , BufferSize ) ) > 0 )
118
+ using ( var response = _httpClient . Get ( request ) )
136
119
{
137
120
cancellationToken . ThrowIfCancellationRequested ( ) ;
138
121
139
- OnDataAvailable ( _buffer , bufferRead ) ;
122
+ _logger . LogDebug ( "Received response from server." ) ;
123
+ _logger . LogTrace ( "statusCode = " + response . StatusCode ) ;
124
+
125
+ if ( Is2XXStatus ( response . StatusCode ) )
126
+ {
127
+ _logger . LogDebug ( "Successful response. Reading response stream..." ) ;
128
+
129
+ //TODO: Could response.ContentStream be null? Need to check it.
130
+
131
+ var responseStream = response . ContentStream ;
132
+ int bufferRead ;
133
+ while ( ( bufferRead = responseStream . Read ( _buffer , 0 , ( int ) _bufferSize ) ) > 0 )
134
+ {
135
+ cancellationToken . ThrowIfCancellationRequested ( ) ;
136
+
137
+ var dataPacket = new DataPacket { Data = _buffer , Length = bufferRead , } ;
138
+
139
+ yield return dataPacket ;
140
+ }
141
+
142
+ _logger . LogDebug ( "Downloading finished." ) ;
143
+ }
144
+ else if ( Is4XXStatus ( response . StatusCode ) )
145
+ {
146
+ throw new DataNotAvailableException ( string . Format (
147
+ "Request data for {0} is not available (status: {1})" , _url , response . StatusCode ) ) ;
148
+ }
149
+ else
150
+ {
151
+ throw new ServerErrorException ( string . Format (
152
+ "Server has experienced some issues with request for {0} which resulted in {1} status code." ,
153
+ _url , response . StatusCode ) ) ;
154
+ }
140
155
}
141
156
}
142
157
@@ -151,11 +166,5 @@ private static bool Is4XXStatus(HttpStatusCode statusCode)
151
166
{
152
167
return ( int ) statusCode >= 400 && ( int ) statusCode <= 499 ;
153
168
}
154
-
155
- private void OnDataAvailable ( byte [ ] data , int length )
156
- {
157
- var handler = DataAvailable ;
158
- if ( handler != null ) handler ( data , length ) ;
159
- }
160
169
}
161
170
}
0 commit comments