5
5
6
6
extends Node
7
7
8
-
9
- class Future :
10
- signal completed (http : HTTPClient )
11
-
8
+ signal http_tick
12
9
13
10
var next_request : int = 0
14
11
var pending_requests : Dictionary = {} # int -> Future
15
12
16
13
var http_client_pool : Array [HTTPClient ]
17
14
var total_http_clients : int = 0
18
15
19
- signal http_tick
16
+
17
+ class Future :
18
+ signal completed (http : HTTPClient )
20
19
21
20
22
21
class HTTPState :
22
+ signal connection_finished (http_client : HTTPClient )
23
+ signal request_finished (success : bool )
24
+ signal download_progressed (bytes : int , total_bytes : int )
25
+
23
26
const YIELD_PERIOD_MS = 50
24
27
25
28
var out_path : String = ""
@@ -41,11 +44,6 @@ class HTTPState:
41
44
var bytes : int
42
45
var total_bytes : int
43
46
44
- signal _connection_finished (http_client : HTTPClient )
45
- signal _request_finished (success : bool )
46
-
47
- signal download_progressed (bytes : int , total_bytes : int )
48
-
49
47
func _init (p_http_pool : Node , p_http_client : HTTPClient ):
50
48
self .http = p_http_client
51
49
self .http_pool = p_http_pool
@@ -65,121 +63,127 @@ class HTTPState:
65
63
http .close ()
66
64
http = HTTPClient .new ()
67
65
68
- func http_tick () -> void :
69
- if not sent_request :
70
- if terminated :
71
- if file :
72
- file .close ()
73
- _connection_finished .emit (null )
74
- return
75
-
76
- if cancelled :
77
- if file :
78
- file .close ()
79
- cancelled = false
80
- busy = false
81
- http .close ()
82
- _connection_finished .emit (null )
83
- return
84
-
85
- var _poll_error : int = http .poll ()
86
- status = http .get_status ()
87
-
88
- if (
89
- status == HTTPClient .STATUS_CONNECTED
90
- or status == HTTPClient .STATUS_REQUESTING
91
- or status == HTTPClient .STATUS_BODY
92
- ):
93
- _connection_finished .emit (http )
94
- return
95
- if (
96
- status != HTTPClient .STATUS_CONNECTING
97
- and status != HTTPClient .STATUS_RESOLVING
98
- and status != HTTPClient .STATUS_CONNECTED
99
- ):
100
- busy = false
101
- push_error (
102
- (
103
- "GodotUroRequester: could not connect to host: status = %s "
104
- % [str (http .get_status ())]
105
- )
106
- )
107
- _connection_finished .emit (null )
108
- return
109
- return
110
-
111
- status = http .get_status ()
66
+ func handle_connection_tick () -> void :
112
67
if terminated :
113
68
if file :
114
69
file .close ()
115
- _request_finished .emit (false )
70
+ connection_finished .emit (null )
116
71
return
117
72
118
- if status != HTTPClient .STATUS_REQUESTING and status != HTTPClient .STATUS_BODY :
119
- _request_finished .emit (false )
73
+ var poll_error : int = http .poll ()
74
+ status = http .get_status ()
75
+
76
+ if (
77
+ status == HTTPClient .STATUS_CONNECTED
78
+ or status == HTTPClient .STATUS_REQUESTING
79
+ or status == HTTPClient .STATUS_BODY
80
+ ):
81
+ connection_finished .emit (http )
82
+ return
83
+
84
+ if (
85
+ status != HTTPClient .STATUS_CONNECTING
86
+ and status != HTTPClient .STATUS_RESOLVING
87
+ and status != HTTPClient .STATUS_CONNECTED
88
+ ):
89
+ busy = false
90
+ push_error (
91
+ (
92
+ "GodotUroRequester: could not connect to host: status = %s "
93
+ % [str (http .get_status ())]
94
+ )
95
+ )
96
+ connection_finished .emit (null )
120
97
return
121
98
122
- if cancelled :
99
+ func handle_request_tick () -> void :
100
+ var exit_result = null # Can be true, false, or null (not exiting)
101
+
102
+ status = http .get_status ()
103
+
104
+ if terminated :
105
+ if file :
106
+ file .close ()
107
+ exit_result = false
108
+ elif status != HTTPClient .STATUS_REQUESTING and status != HTTPClient .STATUS_BODY :
109
+ exit_result = false
110
+ elif cancelled :
123
111
if file :
124
112
file .close ()
125
113
cancelled = false
126
114
busy = false
127
115
http .close ()
128
- _request_finished .emit (false )
129
- return
130
-
131
- if status == HTTPClient .STATUS_REQUESTING :
132
- http .poll ()
133
- if status == HTTPClient .STATUS_BODY :
134
- response_code = http .get_response_code ()
135
- response_headers = http .get_response_headers_as_dictionary ()
136
-
137
- bytes = 0
138
- if response_headers .has ("Content-Length" ):
139
- total_bytes = int (response_headers ["Content-Length" ])
140
- else :
141
- total_bytes = - 1
142
- if not out_path .is_empty ():
143
- file = FileAccess .open (out_path , FileAccess .WRITE )
144
- if file .is_null ():
116
+ exit_result = false
117
+ else :
118
+ if status == HTTPClient .STATUS_REQUESTING :
119
+ http .poll ()
120
+ if status == HTTPClient .STATUS_BODY :
121
+ response_code = http .get_response_code ()
122
+ response_headers = http .get_response_headers_as_dictionary ()
123
+
124
+ bytes = 0
125
+ if response_headers .has ("Content-Length" ):
126
+ total_bytes = int (response_headers ["Content-Length" ])
127
+ else :
128
+ total_bytes = - 1
129
+ if not out_path .is_empty ():
130
+ file = FileAccess .open (out_path , FileAccess .WRITE )
131
+ if file .is_null ():
132
+ busy = false
133
+ status = HTTPClient .STATUS_CONNECTED
134
+ exit_result = false
135
+
136
+ # Only proceed if no exit yet
137
+ if exit_result == null :
138
+ var last_yield = Time .get_ticks_msec ()
139
+ var time : int = 0
140
+ var should_yield := false
141
+
142
+ while status == HTTPClient .STATUS_BODY and exit_result == null :
143
+ var poll_error : int = http .poll ()
144
+
145
+ var chunk = http .read_response_body_chunk ()
146
+ response_code = http .get_response_code ()
147
+
148
+ if file :
149
+ file .store_buffer (chunk )
150
+ else :
151
+ response_body .append_array (chunk )
152
+ bytes += chunk .size ()
153
+ self .download_progressed .emit (bytes , total_bytes )
154
+
155
+ time = Time .get_ticks_msec ()
156
+
157
+ status = http .get_status ()
158
+ if status == HTTPClient .STATUS_CONNECTION_ERROR and ! terminated and ! cancelled :
159
+ if file :
160
+ file .close ()
145
161
busy = false
146
- status = HTTPClient .STATUS_CONNECTED # failed to write to file
147
- _request_finished .emit (false )
148
- return
149
-
150
- var last_yield = Time .get_ticks_msec ()
151
- while status == HTTPClient .STATUS_BODY :
152
- var _poll_error : int = http .poll ()
153
-
154
- var chunk = http .read_response_body_chunk ()
155
- response_code = http .get_response_code ()
162
+ exit_result = false
163
+ else :
164
+ if status != HTTPClient .STATUS_BODY :
165
+ busy = false
166
+ exit_result = true
167
+ if file :
168
+ file .close ()
169
+ else :
170
+ if time - last_yield > YIELD_PERIOD_MS :
171
+ should_yield = true
172
+ break
173
+
174
+ if should_yield :
175
+ return # Yield without finishing
176
+
177
+ # Emit result and exit if needed
178
+ if exit_result != null :
179
+ request_finished .emit (exit_result )
180
+ return
156
181
157
- if file :
158
- file .store_buffer (chunk )
159
- else :
160
- response_body .append_array (chunk )
161
- bytes += chunk .size ()
162
- self .download_progressed .emit (bytes , total_bytes )
163
-
164
- var time = Time .get_ticks_msec ()
165
-
166
- status = http .get_status ()
167
- if status == HTTPClient .STATUS_CONNECTION_ERROR and ! terminated and ! cancelled :
168
- if file :
169
- file .close ()
170
- busy = false
171
- _request_finished .emit (false )
172
- return
173
-
174
- if status != HTTPClient .STATUS_BODY :
175
- busy = false
176
- _request_finished .emit (true )
177
- if file :
178
- file .close ()
179
- return
180
-
181
- if time - last_yield > YIELD_PERIOD_MS :
182
- return
182
+ func http_tick () -> void :
183
+ if not sent_request :
184
+ handle_connection_tick ()
185
+ else :
186
+ handle_request_tick ()
183
187
184
188
func connect_http (hostname : String , port : int , use_ssl : bool ) -> HTTPClient :
185
189
sent_request = false
@@ -228,25 +232,23 @@ class HTTPState:
228
232
return null
229
233
230
234
http_pool .http_tick .connect (self .http_tick )
231
- var ret = await self ._connection_finished
235
+ var ret = await self .connection_finished
232
236
http_pool .http_tick .disconnect (self .http_tick )
233
237
return ret
234
238
235
239
func wait_for_request ():
236
240
sent_request = true
237
241
http_pool .http_tick .connect (self .http_tick )
238
- var ret = await self ._request_finished
242
+ var ret = await self .request_finished
239
243
call_deferred ("release" )
240
244
return ret
241
245
242
246
func release ():
243
247
if not http_pool :
244
248
return
245
- # print("Do release")
246
249
if http_pool .http_tick .is_connected (self .http_tick ):
247
250
http_pool .http_tick .disconnect (self .http_tick )
248
251
if self .http_pool != null and self .http != null :
249
- # print("Release http")
250
252
self .http_pool ._release_client (self .http )
251
253
self .http_pool = null
252
254
self .http = null
@@ -270,6 +272,11 @@ func _init(p_http_client_limit: int = 5):
270
272
http_client_pool .push_back (HTTPClient .new ())
271
273
272
274
275
+ func new_http_state () -> HTTPState :
276
+ var http_client : HTTPClient = await _acquire_client ()
277
+ return HTTPState .new (self , http_client )
278
+
279
+
273
280
func _acquire_client () -> HTTPClient :
274
281
if not http_client_pool .is_empty ():
275
282
return http_client_pool .pop_back ()
@@ -289,8 +296,3 @@ func _release_client(http: HTTPClient):
289
296
f .completed .emit (http )
290
297
else :
291
298
http_client_pool .push_back (http )
292
-
293
-
294
- func new_http_state () -> HTTPState :
295
- var http_client : HTTPClient = await _acquire_client ()
296
- return HTTPState .new (self , http_client )
0 commit comments