girl 9.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,1409 @@
1
+ module Girl
2
+ class ProxydWorker
3
+ include Dns
4
+
5
+ def initialize(
6
+ proxyd_port,
7
+ memd_port,
8
+ nameservers,
9
+ reset_traff_day,
10
+ ims,
11
+ p2d_host,
12
+ p2d_port,
13
+ head_len,
14
+ h_a_new_source,
15
+ h_a_new_p2,
16
+ h_dst_close,
17
+ h_heartbeat,
18
+ h_p1_close,
19
+ h_p2_close,
20
+ h_p2_traffic,
21
+ h_p1_overflow,
22
+ h_p1_underhalf,
23
+ h_p2_overflow,
24
+ h_p2_underhalf,
25
+ h_query,
26
+ h_response,
27
+ h_src_close,
28
+ h_traffic,
29
+ h_src_overflow,
30
+ h_src_underhalf,
31
+ h_dst_overflow,
32
+ h_dst_underhalf,
33
+ expire_connecting,
34
+ expire_long_after,
35
+ expire_proxy_after,
36
+ expire_resolv_cache,
37
+ expire_short_after,
38
+ is_debug,
39
+ is_server_fastopen )
40
+
41
+ @nameserver_addrs = nameservers.map{ | n | Socket.sockaddr_in( 53, n ) }
42
+ @reset_traff_day = reset_traff_day
43
+ @update_roles = [ :dns, :dst, :mem, :p2, :proxy, :rsv ] # 参与淘汰的角色
44
+ @updates_limit = 1011 - ims.size # 淘汰池上限,1015(mac) - info, infod, memd, proxyd, p2ds(=ims)
45
+ @eliminate_count = 0 # 淘汰次数
46
+ @reads = [] # 读池
47
+ @writes = [] # 写池
48
+ @roles = {} # sock => :dns / :dst / :infod / :mem / :memd / :p2 / :p2d / :proxy / :proxyd / :rsv
49
+ @updates = {} # sock => updated_at
50
+ @proxy_infos = {} # proxy => { :addrinfo :im :paused_dsts :paused_p2s :rbuff :src_infos :wbuff }
51
+ @im_infos = {} # im => { :addrinfo :in :out :p2d :p2d_host :p2d_port :proxy }
52
+ @mem_infos = {} # mem => { :wbuff }
53
+ @dst_infos = {} # dst => { :closing :connected :domain :im :ip :overflowing :port :proxy :rbuffs :src_id :wbuff }
54
+ @dns_infos = {} # dns => { :domain :im :port :proxy :src_id }
55
+ @rsv_infos = {} # rsv => { :domain :im :near_id :proxy }
56
+ @resolv_caches = {} # domain => [ ip, created_at, im ]
57
+ @p2d_infos = {} # p2d => { :im }
58
+ @p2_infos = {} # p2 => { :addrinfo :closing :im :overflowing :p2_id :wbuff }
59
+
60
+ @head_len = head_len
61
+ @h_a_new_source = h_a_new_source
62
+ @h_a_new_p2 = h_a_new_p2
63
+ @h_dst_close = h_dst_close
64
+ @h_heartbeat = h_heartbeat
65
+ @h_p1_close = h_p1_close
66
+ @h_p2_close = h_p2_close
67
+ @h_p2_traffic = h_p2_traffic
68
+ @h_p1_overflow = h_p1_overflow
69
+ @h_p1_underhalf = h_p1_underhalf
70
+ @h_p2_overflow = h_p2_overflow
71
+ @h_p2_underhalf = h_p2_underhalf
72
+ @h_query = h_query
73
+ @h_response = h_response
74
+ @h_src_close = h_src_close
75
+ @h_traffic = h_traffic
76
+ @h_src_overflow = h_src_overflow
77
+ @h_src_underhalf = h_src_underhalf
78
+ @h_dst_overflow = h_dst_overflow
79
+ @h_dst_underhalf = h_dst_underhalf
80
+ @expire_connecting = expire_connecting
81
+ @expire_long_after = expire_long_after
82
+ @expire_proxy_after = expire_proxy_after
83
+ @expire_resolv_cache = expire_resolv_cache
84
+ @expire_short_after = expire_short_after
85
+ @is_debug = is_debug
86
+ @is_server_fastopen = is_server_fastopen
87
+
88
+ init_im_infos( ims, p2d_host, p2d_port )
89
+ new_a_proxyd( proxyd_port )
90
+ new_a_infod( proxyd_port )
91
+ new_a_memd( memd_port )
92
+ end
93
+
94
+ def looping
95
+ puts "looping"
96
+ loop_heartbeat
97
+ loop_check_traff
98
+
99
+ loop do
100
+ rs, ws = IO.select( @reads, @writes )
101
+
102
+ rs.each do | sock |
103
+ role = @roles[ sock ]
104
+
105
+ case role
106
+ when :dns then
107
+ read_dns( sock )
108
+ when :dst then
109
+ read_dst( sock )
110
+ when :infod then
111
+ read_infod( sock )
112
+ when :mem then
113
+ read_mem( sock )
114
+ when :memd then
115
+ read_memd( sock )
116
+ when :p2 then
117
+ read_p2( sock )
118
+ when :p2d then
119
+ read_p2d( sock )
120
+ when :rsv then
121
+ read_rsv( sock )
122
+ when :proxy then
123
+ read_proxy( sock )
124
+ when :proxyd then
125
+ read_proxyd( sock )
126
+ else
127
+ close_sock( sock )
128
+ end
129
+ end
130
+
131
+ ws.each do | sock |
132
+ role = @roles[ sock ]
133
+
134
+ case role
135
+ when :dst then
136
+ write_dst( sock )
137
+ when :mem then
138
+ write_mem( sock )
139
+ when :p2 then
140
+ write_p2( sock )
141
+ when :proxy then
142
+ write_proxy( sock )
143
+ else
144
+ close_sock( sock )
145
+ end
146
+ end
147
+ end
148
+ rescue Interrupt => e
149
+ puts e.class
150
+ quit!
151
+ end
152
+
153
+ def quit!
154
+ exit
155
+ end
156
+
157
+ private
158
+
159
+ def add_dst_wbuff( dst, data )
160
+ return if dst.nil? || dst.closed? || data.nil? || data.empty?
161
+ dst_info = @dst_infos[ dst ]
162
+ dst_info[ :wbuff ] << data
163
+ bytesize = dst_info[ :wbuff ].bytesize
164
+ im = dst_info[ :im ]
165
+ src_id = dst_info[ :src_id ]
166
+ domain = dst_info[ :domain ]
167
+
168
+ if bytesize >= CLOSE_ABOVE then
169
+ puts "close overflow dst #{ src_id } #{ domain }"
170
+ close_dst( dst )
171
+ return
172
+ end
173
+
174
+ if !dst_info[ :overflowing ] && ( bytesize >= WBUFF_LIMIT ) then
175
+ proxy = dst_info[ :proxy ]
176
+ puts "add h_dst_overflow #{ im } #{ src_id } #{ domain }"
177
+ msg = "#{ @h_dst_overflow }#{ [ src_id ].pack( 'Q>' ) }"
178
+ add_proxy_wbuff( proxy, pack_a_chunk( msg ) )
179
+ dst_info[ :overflowing ] = true
180
+ end
181
+
182
+ add_write( dst )
183
+ end
184
+
185
+ def add_mem_wbuff( mem, data )
186
+ return if mem.nil? || mem.closed? || data.nil? || data.empty?
187
+ mem_info = @mem_infos[ mem ]
188
+ mem_info[ :wbuff ] << data
189
+ add_write( mem )
190
+ end
191
+
192
+ def add_p2_wbuff( p2, data )
193
+ return if p2.nil? || p2.closed? || data.nil? || data.empty?
194
+ p2_info = @p2_infos[ p2 ]
195
+ im = p2_info[ :im ]
196
+ im_info = @im_infos[ im ]
197
+
198
+ unless im_info then
199
+ close_p2( p2 )
200
+ return
201
+ end
202
+
203
+ p2_info[ :wbuff ] << data
204
+ bytesize = p2_info[ :wbuff ].bytesize
205
+ p2_id = p2_info[ :p2_id ]
206
+
207
+ if bytesize >= CLOSE_ABOVE then
208
+ puts "close overflow p2 #{ p2_id }"
209
+ close_p2( p2 )
210
+ return
211
+ end
212
+
213
+ if !p2_info[ :overflowing ] && ( bytesize >= WBUFF_LIMIT ) then
214
+ proxy = im_info[ :proxy ]
215
+ puts "add h_p2_overflow #{ im } #{ p2_id }"
216
+ msg = "#{ @h_p2_overflow }#{ [ p2_id ].pack( 'Q>' ) }"
217
+ add_proxy_wbuff( proxy, pack_a_chunk( msg ) )
218
+ p2_info[ :overflowing ] = true
219
+ end
220
+
221
+ add_write( p2 )
222
+ end
223
+
224
+ def add_proxy_wbuff( proxy, data )
225
+ return if proxy.nil? || proxy.closed? || data.nil? || data.empty?
226
+ proxy_info = @proxy_infos[ proxy ]
227
+ proxy_info[ :wbuff ] << data
228
+ bytesize = proxy_info[ :wbuff ].bytesize
229
+
230
+ if bytesize >= CLOSE_ABOVE then
231
+ puts "close overflow proxy #{ proxy_info[ :im ] }"
232
+ close_proxy( proxy )
233
+ return
234
+ end
235
+
236
+ add_write( proxy )
237
+ end
238
+
239
+ def add_read( sock, role = nil )
240
+ return if sock.nil? || sock.closed? || @reads.include?( sock )
241
+ @reads << sock
242
+
243
+ if role then
244
+ @roles[ sock ] = role
245
+ else
246
+ role = @roles[ sock ]
247
+ end
248
+
249
+ if @update_roles.include?( role ) then
250
+ set_update( sock )
251
+ end
252
+ end
253
+
254
+ def add_write( sock )
255
+ return if sock.nil? || sock.closed? || @writes.include?( sock )
256
+ @writes << sock
257
+ role = @roles[ sock ]
258
+
259
+ if @update_roles.include?( role ) then
260
+ set_update( sock )
261
+ end
262
+ end
263
+
264
+ def check_expire_dnses
265
+ now = Time.new
266
+
267
+ @dns_infos.select{ | dns, _ | now.to_i - @updates[ dns ].to_i >= @expire_short_after }.each do | dns, info |
268
+ puts "expire dns #{ info[ :im ] } #{ info[ :domain ] }" if @is_debug
269
+ close_dns( dns )
270
+ end
271
+ end
272
+
273
+ def check_expire_dsts
274
+ now = Time.new
275
+
276
+ @dst_infos.select{ | dst, info | info[ :connected ] ? ( now.to_i - @updates[ dst ].to_i >= @expire_long_after ) : ( now.to_i - @updates[ dst ].to_i >= @expire_connecting ) }.each do | dst, info |
277
+ puts "expire dst #{ info[ :im ] } #{ info[ :domain ] }" if @is_debug
278
+ close_dst( dst )
279
+ end
280
+ end
281
+
282
+ def check_expire_mems
283
+ now = Time.new
284
+
285
+ @mem_infos.select{ | mem, _ | now.to_i - @updates[ mem ].to_i >= @expire_short_after }.each do | mem, _ |
286
+ puts "expire mem" if @is_debug
287
+ close_mem( mem )
288
+ end
289
+ end
290
+
291
+ def check_expire_p2s
292
+ now = Time.new
293
+
294
+ @p2_infos.select{ | p2, _ | now.to_i - @updates[ p2 ].to_i >= @expire_long_after }.each do | p2, info |
295
+ puts "expire p2 #{ info[ :im ] } #{ info[ :p2_id ] }" if @is_debug
296
+ close_p2( p2 )
297
+ end
298
+ end
299
+
300
+ def check_expire_proxies
301
+ now = Time.new
302
+
303
+ @proxy_infos.select{ | proxy, _ | now.to_i - @updates[ proxy ].to_i >= @expire_long_after }.each do | proxy, info |
304
+ puts "expire proxy #{ info[ :im ] }"
305
+ close_proxy( proxy )
306
+ end
307
+ end
308
+
309
+ def check_expire_rsvs
310
+ now = Time.new
311
+
312
+ @rsv_infos.select{ | rsv, _ | now.to_i - @updates[ rsv ].to_i >= @expire_short_after }.each do | rsv, info |
313
+ puts "expire rsv #{ info[ :im ] } #{ info[ :domain ] }" if @is_debug
314
+ close_rsv( rsv )
315
+ end
316
+ end
317
+
318
+ def check_expire_srcs( proxy )
319
+ return if proxy.nil? || proxy.closed?
320
+ proxy_info = @proxy_infos[ proxy ]
321
+ im = proxy_info[ :im ]
322
+ now = Time.new
323
+
324
+ proxy_info[ :src_infos ].select{ | _, info | info[ :dst ].nil? && ( now.to_i - info[ :created_at ].to_i >= @expire_short_after ) }.each do | src_id, _ |
325
+ puts "expire src info #{ im } #{ src_id }" if @is_debug
326
+ proxy_info[ :src_infos ].delete( src_id )
327
+ end
328
+ end
329
+
330
+ def close_dns( dns )
331
+ return nil if dns.nil? || dns.closed?
332
+ close_sock( dns )
333
+ dns_info = @dns_infos.delete( dns )
334
+ puts "close dns #{ dns_info[ :im ] } #{ dns_info[ :domain ] }" if @is_debug
335
+ dns_info
336
+ end
337
+
338
+ def close_dst( dst )
339
+ return nil if dst.nil? || dst.closed?
340
+ close_sock( dst )
341
+ dst_info = @dst_infos.delete( dst )
342
+ im = dst_info[ :im ]
343
+ src_id = dst_info[ :src_id ]
344
+ domain = dst_info[ :domain ]
345
+ puts "close dst #{ im } #{ src_id } #{ domain }" if @is_debug
346
+ proxy = dst_info[ :proxy ]
347
+
348
+ unless proxy.closed? then
349
+ proxy_info = @proxy_infos[ proxy ]
350
+ proxy_info[ :paused_dsts ].delete( dst )
351
+ proxy_info[ :src_infos ].delete( src_id )
352
+ puts "add h_dst_close #{ im } #{ src_id }" if @is_debug
353
+ msg = "#{ @h_dst_close }#{ [ src_id ].pack( 'Q>' ) }"
354
+ add_proxy_wbuff( proxy, pack_a_chunk( msg ) )
355
+ end
356
+
357
+ dst_info
358
+ end
359
+
360
+ def close_mem( mem )
361
+ return nil if mem.nil? || mem.closed?
362
+ close_sock( mem )
363
+ @mem_infos.delete( mem )
364
+ end
365
+
366
+ def close_p2( p2 )
367
+ return nil if p2.nil? || p2.closed?
368
+ close_sock( p2 )
369
+ p2_info = @p2_infos.delete( p2 )
370
+ im = p2_info[ :im ]
371
+ p2_id = p2_info[ :p2_id ]
372
+ puts "close p2 #{ im } #{ p2_id }"
373
+ im_info = @im_infos[ im ]
374
+
375
+ if im_info then
376
+ proxy = im_info[ :proxy ]
377
+
378
+ if proxy && !proxy.closed? then
379
+ proxy_info = @proxy_infos[ proxy ]
380
+ proxy_info[ :paused_p2s ].delete( p2 )
381
+ puts "add h_p2_close #{ im } #{ p2_id }"
382
+ msg = "#{ @h_p2_close }#{ [ p2_id ].pack( 'Q>' ) }"
383
+ add_proxy_wbuff( proxy, pack_a_chunk( msg ) )
384
+ end
385
+ end
386
+
387
+ p2_info
388
+ end
389
+
390
+ def close_proxy( proxy )
391
+ return nil if proxy.nil? || proxy.closed?
392
+ close_sock( proxy )
393
+ proxy_info = @proxy_infos.delete( proxy )
394
+ im = proxy_info[ :im ]
395
+ puts "close proxy #{ proxy_info[ :addrinfo ].ip_unpack.inspect } #{ im }" if @is_debug
396
+ @dst_infos.select{ | _, info | info[ :proxy ] == proxy }.each{ | dst, _ | close_dst( dst ) }
397
+ @p2_infos.select{ | _, info | info[ :im ] == im }.each{ | p2, _ | close_p2( p2 ) }
398
+ proxy_info
399
+ end
400
+
401
+ def close_rsv( rsv )
402
+ return nil if rsv.nil? || rsv.closed?
403
+ close_sock( rsv )
404
+ rsv_info = @rsv_infos.delete( rsv )
405
+ puts "close rsv #{ rsv_info[ :im ] } #{ rsv_info[ :domain ] }" if @is_debug
406
+ rsv_info
407
+ end
408
+
409
+ def close_sock( sock )
410
+ return if sock.nil? || sock.closed?
411
+ sock.close
412
+ @reads.delete( sock )
413
+ @writes.delete( sock )
414
+ @updates.delete( sock )
415
+ @roles.delete( sock )
416
+ end
417
+
418
+ def deal_msg( data, proxy )
419
+ return if data.nil? || data.empty? || proxy.nil? || proxy.closed?
420
+ proxy_info = @proxy_infos[ proxy ]
421
+ im = proxy_info[ :im ]
422
+ return unless im
423
+ h = data[ 0 ]
424
+
425
+ case h
426
+ when @h_a_new_source then
427
+ return if data.bytesize < 9
428
+ check_expire_srcs( proxy )
429
+ src_id = data[ 1, 8 ].unpack( 'Q>' ).first
430
+ domain_port = data[ 9..-1 ]
431
+ puts "got h_a_new_source #{ im } #{ src_id } #{ domain_port.inspect }" if @is_debug
432
+
433
+ src_info = {
434
+ created_at: Time.new,
435
+ dst: nil,
436
+ rbuff: ''
437
+ }
438
+
439
+ proxy_info[ :src_infos ][ src_id ] = src_info
440
+ resolve_domain_port( domain_port, src_id, proxy, im )
441
+ when @h_p1_close then
442
+ return if data.bytesize < 9
443
+ p2_id = data[ 1, 8 ].unpack( 'Q>' ).first
444
+ puts "got h_p1_close #{ im } #{ p2_id }"
445
+ p2, _ = @p2_infos.find{ | _, info | ( info[ :im ] == im ) && ( info[ :p2_id ] == p2_id ) }
446
+ set_p2_closing( p2 )
447
+ when @h_p2_traffic then
448
+ return if data.bytesize < 9
449
+ p2_id = data[ 1, 8 ].unpack( 'Q>' ).first
450
+ data = data[ 9..-1 ]
451
+ # puts "got h_p2_traffic #{ im } #{ p2_id } #{ data.bytesize }" if @is_debug
452
+ p2, _ = @p2_infos.find{ | _, info | ( info[ :im ] == im ) && ( info[ :p2_id ] == p2_id ) }
453
+ add_p2_wbuff( p2, data )
454
+ when @h_p1_overflow then
455
+ return if data.bytesize < 9
456
+ p2_id = data[ 1, 8 ].unpack( 'Q>' ).first
457
+ puts "got h_p1_overflow pause p2 #{ im } #{ p2_id }"
458
+ p2, _ = @p2_infos.find{ | _, info | ( info[ :im ] == im ) && ( info[ :p2_id ] == p2_id ) }
459
+ @reads.delete( p2 )
460
+ proxy_info[ :paused_p2s ].delete( p2 )
461
+ when @h_p1_underhalf then
462
+ return if data.bytesize < 9
463
+ p2_id = data[ 1, 8 ].unpack( 'Q>' ).first
464
+ puts "got h_p1_underhalf #{ im } #{ p2_id }"
465
+ p2, _ = @p2_infos.find{ | _, info | ( info[ :im ] == im ) && ( info[ :p2_id ] == p2_id ) }
466
+ add_read( p2 )
467
+ when @h_query then
468
+ return if data.bytesize < 10
469
+ near_id, type = data[ 1, 9 ].unpack( 'Q>C' )
470
+ return unless [ 1, 28 ].include?( type )
471
+ domain = data[ 10..-1 ]
472
+ return if domain.nil? || domain.empty?
473
+ puts "got h_query #{ im } #{ near_id } #{ type } #{ domain.inspect }" if @is_debug
474
+ new_a_rsv( domain, near_id, type, proxy, im )
475
+ when @h_src_close then
476
+ return if data.bytesize < 9
477
+ src_id = data[ 1, 8 ].unpack( 'Q>' ).first
478
+ puts "got h_src_close #{ im } #{ src_id }" if @is_debug
479
+ src_info = proxy_info[ :src_infos ].delete( src_id )
480
+ set_dst_closing( src_info[ :dst ] ) if src_info
481
+ when @h_traffic then
482
+ return if data.bytesize < 9
483
+ src_id = data[ 1, 8 ].unpack( 'Q>' ).first
484
+ data = data[ 9..-1 ]
485
+ # puts "got h_traffic #{ im } #{ src_id } #{ data.bytesize }" if @is_debug
486
+ src_info = proxy_info[ :src_infos ][ src_id ]
487
+
488
+ if src_info then
489
+ dst = src_info[ :dst ]
490
+
491
+ if dst then
492
+ add_dst_wbuff( dst, data )
493
+ else
494
+ puts "add src rbuff #{ im } #{ data.bytesize }" if @is_debug
495
+ src_info[ :rbuff ] << data
496
+
497
+ if src_info[ :rbuff ].bytesize >= WBUFF_LIMIT then
498
+ puts "src rbuff full"
499
+ close_proxy( proxy )
500
+ end
501
+ end
502
+ end
503
+ when @h_src_overflow then
504
+ return if data.bytesize < 9
505
+ src_id = data[ 1, 8 ].unpack( 'Q>' ).first
506
+ puts "got h_src_overflow pause dst #{ im } #{ src_id }"
507
+ src_info = proxy_info[ :src_infos ][ src_id ]
508
+
509
+ if src_info then
510
+ dst = src_info[ :dst ]
511
+ @reads.delete( dst )
512
+ # 远端收取目的地比传给近端快,近端收取远端又比传给客户端快(2g wifi),流量即在远端proxy堆积,又在近端src堆积
513
+ # 这种情况只等待近端src降半,等到降半消息才恢复读dst,忽略proxy降半
514
+ proxy_info[ :paused_dsts ].delete( dst )
515
+ end
516
+ when @h_src_underhalf then
517
+ return if data.bytesize < 9
518
+ src_id = data[ 1, 8 ].unpack( 'Q>' ).first
519
+ puts "got h_src_underhalf #{ im } #{ src_id }"
520
+ src_info = proxy_info[ :src_infos ][ src_id ]
521
+ add_read( src_info[ :dst ] ) if src_info
522
+ end
523
+ end
524
+
525
+ def decode_to_msgs( data )
526
+ msgs = []
527
+ part = ''
528
+
529
+ loop do
530
+ if data.bytesize <= 2 then
531
+ part = data
532
+ break
533
+ end
534
+
535
+ len = data[ 0, 2 ].unpack( 'n' ).first
536
+
537
+ if len == 0 then
538
+ puts "msg zero len?"
539
+ break
540
+ end
541
+
542
+ if data.bytesize < ( 2 + len ) then
543
+ part = data
544
+ break
545
+ end
546
+
547
+ msgs << data[ 2, len ]
548
+ data = data[ ( 2 + len )..-1 ]
549
+ break if data.empty?
550
+ end
551
+
552
+ [ msgs, part ]
553
+ end
554
+
555
+ def init_im_infos( ims, p2d_host, p2d_port )
556
+ ims.sort.each_with_index do | im, i |
557
+ @im_infos[ im ] = {
558
+ addrinfo: nil,
559
+ in: 0,
560
+ out: 0,
561
+ p2d: nil,
562
+ p2d_host: p2d_host,
563
+ p2d_port: p2d_port + i,
564
+ proxy: nil
565
+ }
566
+ end
567
+ end
568
+
569
+ def loop_check_traff
570
+ if @reset_traff_day > 0 then
571
+ Thread.new do
572
+ loop do
573
+ sleep CHECK_TRAFF_INTERVAL
574
+ now = Time.new
575
+
576
+ if ( now.day == @reset_traff_day ) && ( now.hour == 0 ) then
577
+ msg = { message_type: 'reset-traffic' }
578
+ send_data( @info, JSON.generate( msg ), @infod_addr )
579
+ end
580
+ end
581
+ end
582
+ end
583
+ end
584
+
585
+ def loop_heartbeat
586
+ Thread.new do
587
+ loop do
588
+ sleep HEARTBEAT_INTERVAL
589
+ msg = { message_type: 'heartbeat' }
590
+ send_data( @info, JSON.generate( msg ), @infod_addr )
591
+ end
592
+ end
593
+ end
594
+
595
+ def new_a_dst( domain, ip, port, src_id, proxy )
596
+ return if proxy.nil? || proxy.closed?
597
+ proxy_info = @proxy_infos[ proxy ]
598
+ im = proxy_info[ :im ]
599
+ src_info = proxy_info[ :src_infos ][ src_id ]
600
+ return unless src_info
601
+
602
+ check_expire_dsts
603
+
604
+ begin
605
+ dst = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
606
+ rescue Exception => e
607
+ puts "new a dst #{ e.class } #{ im } #{ domain }:#{ port }"
608
+ return
609
+ end
610
+
611
+ dst.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 )
612
+
613
+ begin
614
+ destination_addr = Socket.sockaddr_in( port, ip )
615
+ dst.connect_nonblock( destination_addr )
616
+ rescue IO::WaitWritable
617
+ rescue Exception => e
618
+ puts "connect destination #{ e.class } #{ im } #{ domain }:#{ port }"
619
+ dst.close
620
+ return
621
+ end
622
+
623
+ dst_info = {
624
+ closing: false,
625
+ connected: false,
626
+ domain: domain,
627
+ im: im,
628
+ ip: ip,
629
+ overflowing: false,
630
+ port: port,
631
+ proxy: proxy,
632
+ rbuffs: [],
633
+ src_id: src_id,
634
+ wbuff: src_info[ :rbuff ].dup
635
+ }
636
+
637
+ @dst_infos[ dst ] = dst_info
638
+ add_read( dst, :dst )
639
+ add_write( dst )
640
+ src_info[ :dst ] = dst
641
+ end
642
+
643
+ def new_a_infod( infod_port )
644
+ infod_ip = '127.0.0.1'
645
+ infod_addr = Socket.sockaddr_in( infod_port, infod_ip )
646
+ infod = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
647
+ infod.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 ) if RUBY_PLATFORM.include?( 'linux' )
648
+ infod.bind( infod_addr )
649
+ puts "infod bind on #{ infod_ip } #{ infod_port }"
650
+ add_read( infod, :infod )
651
+ info = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
652
+ @infod_addr = infod_addr
653
+ @infod = infod
654
+ @info = info
655
+ end
656
+
657
+ def new_a_memd( memd_port )
658
+ memd_ip = '127.0.0.1'
659
+ memd = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
660
+ memd.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 )
661
+ memd.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 ) if RUBY_PLATFORM.include?( 'linux' )
662
+ memd.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_FASTOPEN, 5 ) if @is_server_fastopen
663
+ memd.bind( Socket.sockaddr_in( memd_port, memd_ip ) )
664
+ memd.listen( 5 )
665
+ puts "memd listen on #{ memd_ip } #{ memd_port }"
666
+ add_read( memd, :memd )
667
+ end
668
+
669
+ def new_a_rsv( domain, near_id, type, proxy, im )
670
+ check_expire_rsvs
671
+ rsv = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
672
+
673
+ begin
674
+ data = pack_a_query( domain, type )
675
+ rescue Exception => e
676
+ puts "rsv pack a query #{ e.class } #{ e.message } #{ domain }" if @is_debug
677
+ return
678
+ end
679
+
680
+ begin
681
+ @nameserver_addrs.each{ | addr | rsv.sendmsg( data, 0, addr ) }
682
+ rescue Exception => e
683
+ puts "rsv send data #{ e.class }"
684
+ rsv.close
685
+ return
686
+ end
687
+
688
+ rsv_info = {
689
+ domain: domain,
690
+ im: im,
691
+ near_id: near_id,
692
+ proxy: proxy
693
+ }
694
+
695
+ @rsv_infos[ rsv ] = rsv_info
696
+ add_read( rsv, :rsv )
697
+ end
698
+
699
+ def new_a_p2d( p2d_host, p2d_port, im, proxy )
700
+ begin
701
+ p2d = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
702
+ p2d.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 )
703
+ p2d.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 ) if RUBY_PLATFORM.include?( 'linux' )
704
+ p2d.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_FASTOPEN, 5 ) if @is_server_fastopen
705
+ p2d.bind( Socket.sockaddr_in( p2d_port, p2d_host ) )
706
+ p2d.listen( 5 )
707
+ puts "p2d listen on #{ p2d_host } #{ p2d_port } #{ im }"
708
+ @p2d_infos[ p2d ] = { im: im }
709
+ add_read( p2d, :p2d )
710
+ rescue Exception => e
711
+ puts "new a p2d #{ e.class }"
712
+ end
713
+
714
+ p2d
715
+ end
716
+
717
+ def new_a_proxyd( proxyd_port )
718
+ proxyd_ip = '0.0.0.0'
719
+ proxyd = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
720
+ proxyd.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 )
721
+ proxyd.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 ) if RUBY_PLATFORM.include?( 'linux' )
722
+ proxyd.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_FASTOPEN, BACKLOG ) if @is_server_fastopen
723
+ proxyd.bind( Socket.sockaddr_in( proxyd_port, proxyd_ip ) )
724
+ proxyd.listen( BACKLOG )
725
+ puts "proxyd listen on #{ proxyd_ip } #{ proxyd_port }"
726
+ add_read( proxyd, :proxyd )
727
+ end
728
+
729
+ def pack_a_chunk( msg )
730
+ "#{ [ msg.bytesize ].pack( 'n' ) }#{ msg }"
731
+ end
732
+
733
+ def pack_p2_traffic( p2_id, data )
734
+ chunks = ''
735
+
736
+ loop do
737
+ part = data[ 0, 65526 ]
738
+ # puts "add h_p2_traffic #{ p2_id } #{ part.bytesize }" if @is_debug
739
+ msg = "#{ @h_p2_traffic }#{ [ p2_id ].pack( 'Q>' ) }#{ part }"
740
+ chunks << pack_a_chunk( msg )
741
+ data = data[ part.bytesize..-1 ]
742
+ break if data.empty?
743
+ end
744
+
745
+ chunks
746
+ end
747
+
748
+ def pack_traffic( src_id, data )
749
+ chunks = ''
750
+
751
+ loop do
752
+ part = data[ 0, 65526 ]
753
+ # puts "add h_traffic #{ src_id } #{ part.bytesize }" if @is_debug
754
+ msg = "#{ @h_traffic }#{ [ src_id ].pack( 'Q>' ) }#{ part }"
755
+ chunks << pack_a_chunk( msg )
756
+ data = data[ part.bytesize..-1 ]
757
+ break if data.empty?
758
+ end
759
+
760
+ chunks
761
+ end
762
+
763
+ def read_dns( dns )
764
+ begin
765
+ data, addrinfo, rflags, *controls = dns.recvmsg
766
+ rescue Exception => e
767
+ puts "dns recvmsg #{ e.class }"
768
+ close_dns( dns )
769
+ return
770
+ end
771
+
772
+ return if data.empty?
773
+
774
+ begin
775
+ ip = seek_ip( data )
776
+ rescue Exception => e
777
+ puts "seek ip #{ e.class } #{ e.message }"
778
+ close_dns( dns )
779
+ return
780
+ end
781
+
782
+ dns_info = @dns_infos[ dns ]
783
+ domain = dns_info[ :domain ]
784
+
785
+ if ip then
786
+ port = dns_info[ :port ]
787
+ src_id = dns_info[ :src_id ]
788
+ proxy = dns_info[ :proxy ]
789
+ im = dns_info[ :im ]
790
+ puts "got ip #{ im } #{ domain } #{ ip }" if @is_debug
791
+ new_a_dst( domain, ip, port, src_id, proxy )
792
+ @resolv_caches[ domain ] = [ ip, Time.new, im ]
793
+ else
794
+ puts "no ip in answer #{ domain }" if @is_debug
795
+ end
796
+
797
+ close_dns( dns )
798
+ end
799
+
800
+ def read_dst( dst )
801
+ begin
802
+ data = dst.read_nonblock( READ_SIZE )
803
+ rescue Errno::ENOTCONN => e
804
+ return
805
+ rescue Exception => e
806
+ close_dst( dst )
807
+ return
808
+ end
809
+
810
+ set_update( dst )
811
+ dst_info = @dst_infos[ dst ]
812
+ proxy = dst_info[ :proxy ]
813
+
814
+ if proxy.closed? then
815
+ close_dst( dst )
816
+ return
817
+ end
818
+
819
+ im = dst_info[ :im ]
820
+ im_info = @im_infos[ im ]
821
+ im_info[ :in ] += data.bytesize if im_info
822
+ src_id = dst_info[ :src_id ]
823
+ add_proxy_wbuff( proxy, pack_traffic( src_id, data ) )
824
+
825
+ unless proxy.closed? then
826
+ proxy_info = @proxy_infos[ proxy ]
827
+ bytesize = proxy_info[ :wbuff ].bytesize
828
+
829
+ if ( bytesize >= WBUFF_LIMIT ) && !proxy_info[ :paused_dsts ].include?( dst ) then
830
+ puts "proxy overflow pause dst #{ im } #{ src_id } #{ dst_info[ :domain ] }"
831
+ @reads.delete( dst )
832
+ proxy_info[ :paused_dsts ] << dst
833
+ end
834
+ end
835
+ end
836
+
837
+ def read_infod( infod )
838
+ begin
839
+ data, addrinfo, rflags, *controls = infod.recvmsg
840
+ rescue Exception => e
841
+ puts "infod recvmsg #{ e.class }"
842
+ return
843
+ end
844
+
845
+ return if data.empty?
846
+
847
+ begin
848
+ msg = JSON.parse( data, symbolize_names: true )
849
+ rescue JSON::ParserError, EncodingError => e
850
+ puts "read infod #{ e.class }"
851
+ return
852
+ end
853
+
854
+ message_type = msg[ :message_type ]
855
+
856
+ case message_type
857
+ when 'heartbeat' then
858
+ @proxy_infos.select{ | _, info | info[ :im ] }.each{ | proxy, _ | add_proxy_wbuff( proxy, pack_a_chunk( @h_heartbeat ) ) }
859
+ when 'reset-traffic' then
860
+ puts "reset traffic"
861
+ @im_infos.each{ | _, info | info[ :in ] = info[ :out ] = 0 }
862
+ end
863
+ end
864
+
865
+ def read_mem( mem )
866
+ begin
867
+ mem.read_nonblock( READ_SIZE )
868
+ rescue Errno::ENOTCONN => e
869
+ return
870
+ rescue Exception => e
871
+ close_mem( mem )
872
+ return
873
+ end
874
+
875
+ set_update( mem )
876
+ im_arr = []
877
+
878
+ @im_infos.select{ | _, info | info[ :addrinfo ] }.sort.each do | im, info |
879
+ im_arr << {
880
+ im: im,
881
+ addrinfo: info[ :addrinfo ].ip_unpack,
882
+ in: info[ :in ],
883
+ out: info[ :out ],
884
+ p2d_host: info[ :p2d_host ],
885
+ p2d_port: info[ :p2d_port ]
886
+ }
887
+ end
888
+
889
+ msg = {
890
+ resolv_caches: @resolv_caches.sort,
891
+ sizes: {
892
+ reads: @reads.size,
893
+ writes: @writes.size,
894
+ roles: @roles.size,
895
+ updates: @updates.size,
896
+ proxy_infos: @proxy_infos.size,
897
+ im_infos: @im_infos.size,
898
+ mem_infos: @mem_infos.size,
899
+ dst_infos: @dst_infos.size,
900
+ dns_infos: @dns_infos.size,
901
+ rsv_infos: @rsv_infos.size,
902
+ resolv_caches: @resolv_caches.size,
903
+ p2d_infos: @p2d_infos.size,
904
+ p2_infos: @p2_infos.size
905
+ },
906
+ updates_limit: @updates_limit,
907
+ eliminate_count: @eliminate_count,
908
+ im_arr: im_arr
909
+ }
910
+
911
+ add_mem_wbuff( mem, JSON.generate( msg ) )
912
+ end
913
+
914
+ def read_memd( memd )
915
+ check_expire_mems
916
+
917
+ begin
918
+ mem, addrinfo = memd.accept_nonblock
919
+ rescue Exception => e
920
+ puts "memd accept #{ e.class }"
921
+ return
922
+ end
923
+
924
+ mem_info = {
925
+ wbuff: ''
926
+ }
927
+
928
+ @mem_infos[ mem ] = mem_info
929
+ add_read( mem, :mem )
930
+ end
931
+
932
+ def read_p2( p2 )
933
+ begin
934
+ data = p2.read_nonblock( READ_SIZE )
935
+ rescue Errno::ENOTCONN => e
936
+ return
937
+ rescue Exception => e
938
+ close_p2( p2 )
939
+ return
940
+ end
941
+
942
+ set_update( p2 )
943
+ p2_info = @p2_infos[ p2 ]
944
+ im = p2_info[ :im ]
945
+ # puts "read p2 #{ im } #{ data.bytesize }" if @is_debug
946
+ im_info = @im_infos[ im ]
947
+
948
+ unless im_info then
949
+ close_p2( p2 )
950
+ return
951
+ end
952
+
953
+ proxy = im_info[ :proxy ]
954
+ p2_id = p2_info[ :p2_id ]
955
+ add_proxy_wbuff( proxy, pack_p2_traffic( p2_id, data ) )
956
+
957
+ unless proxy.closed? then
958
+ proxy_info = @proxy_infos[ proxy ]
959
+ bytesize = proxy_info[ :wbuff ].bytesize
960
+
961
+ if ( bytesize >= WBUFF_LIMIT ) && !proxy_info[ :paused_p2s ].include?( p2 ) then
962
+ puts "proxy overflow pause p2 #{ im } #{ p2_id }"
963
+ @reads.delete( p2 )
964
+ proxy_info[ :paused_p2s ] << p2
965
+ end
966
+ end
967
+ end
968
+
969
+ def read_p2d( p2d )
970
+ check_expire_p2s
971
+
972
+ begin
973
+ p2, addrinfo = p2d.accept_nonblock
974
+ rescue Exception => e
975
+ puts "p2d accept #{ e.class }"
976
+ return
977
+ end
978
+
979
+ p2d_info = @p2d_infos[ p2d ]
980
+ im = p2d_info[ :im ]
981
+ p2_id = rand( ( 2 ** 64 ) - 2 ) + 1
982
+
983
+ p2_info = {
984
+ addrinfo: addrinfo,
985
+ closing: false,
986
+ im: im,
987
+ overflowing: false,
988
+ p2_id: p2_id,
989
+ wbuff: ''
990
+ }
991
+
992
+ @p2_infos[ p2 ] = p2_info
993
+ add_read( p2, :p2 )
994
+ im_info = @im_infos[ im ]
995
+ return unless im_info
996
+ proxy = im_info[ :proxy ]
997
+ puts "add h_a_new_p2 #{ im } #{ p2_id }"
998
+ msg = "#{ @h_a_new_p2 }#{ [ p2_id ].pack( 'Q>' ) }"
999
+ add_proxy_wbuff( proxy, pack_a_chunk( msg ) )
1000
+ end
1001
+
1002
+ def read_rsv( rsv )
1003
+ begin
1004
+ data, addrinfo, rflags, *controls = rsv.recvmsg
1005
+ rescue Exception => e
1006
+ puts "rsv recvmsg #{ e.class }"
1007
+ close_rsv( rsv )
1008
+ return
1009
+ end
1010
+
1011
+ return if data.empty?
1012
+
1013
+ if data.bytesize <= 65526 then
1014
+ rsv_info = @rsv_infos[ rsv ]
1015
+ proxy = rsv_info[ :proxy ]
1016
+ near_id = rsv_info[ :near_id ]
1017
+ puts "add h_response #{ rsv_info[ :im ] } #{ near_id } #{ rsv_info[ :domain ] } #{ data.bytesize }" if @is_debug
1018
+ msg = "#{ @h_response }#{ [ near_id ].pack( 'Q>' ) }#{ data }"
1019
+ add_proxy_wbuff( proxy, pack_a_chunk( msg ) )
1020
+ else
1021
+ puts "response too big? #{ data.bytesize }"
1022
+ end
1023
+
1024
+ close_rsv( rsv )
1025
+ end
1026
+
1027
+ def read_proxy( proxy )
1028
+ begin
1029
+ data = proxy.read_nonblock( READ_SIZE )
1030
+ rescue Errno::ENOTCONN => e
1031
+ return
1032
+ rescue Exception => e
1033
+ close_proxy( proxy )
1034
+ return
1035
+ end
1036
+
1037
+ set_update( proxy )
1038
+ proxy_info = @proxy_infos[ proxy ]
1039
+ im = proxy_info[ :im ]
1040
+ data = "#{ proxy_info[ :rbuff ] }#{ data }"
1041
+
1042
+ unless im then
1043
+ if data.bytesize < @head_len + 1 then
1044
+ proxy_info[ :rbuff ] = data
1045
+ return
1046
+ end
1047
+
1048
+ len = data[ @head_len ].unpack( 'C' ).first
1049
+
1050
+ if len == 0 then
1051
+ puts "im zero len?"
1052
+ return
1053
+ end
1054
+
1055
+ if data.bytesize < @head_len + 1 + len then
1056
+ proxy_info[ :rbuff ] = data
1057
+ return
1058
+ end
1059
+
1060
+ im = data[ @head_len + 1, len ]
1061
+
1062
+ if @im_infos.any? && !@im_infos.include?( im ) then
1063
+ puts "unknown im #{ im.inspect }"
1064
+ return
1065
+ end
1066
+
1067
+ puts "got im #{ im }"
1068
+ proxy_info[ :im ] = im
1069
+ im_info = @im_infos[ im ]
1070
+
1071
+ if im_info then
1072
+ im_info[ :proxy ] = proxy
1073
+ im_info[ :addrinfo ] = proxy_info[ :addrinfo ]
1074
+ im_info[ :p2d ] = new_a_p2d( im_info[ :p2d_host ], im_info[ :p2d_port ], im, proxy ) unless im_info[ :p2d ]
1075
+ end
1076
+
1077
+ add_proxy_wbuff( proxy, pack_a_chunk( @h_heartbeat ) )
1078
+ data = data[ ( @head_len + 1 + len )..-1 ]
1079
+ return if data.empty?
1080
+ end
1081
+
1082
+ im_info = @im_infos[ im ]
1083
+ im_info[ :in ] += data.bytesize if im_info
1084
+ msgs, part = decode_to_msgs( data )
1085
+ msgs.each{ | msg | deal_msg( msg, proxy ) }
1086
+ proxy_info[ :rbuff ] = part
1087
+ end
1088
+
1089
+ def read_proxyd( proxyd )
1090
+ check_expire_proxies
1091
+
1092
+ begin
1093
+ proxy, addrinfo = proxyd.accept_nonblock
1094
+ rescue Exception => e
1095
+ puts "accept a proxy #{ e.class }"
1096
+ return
1097
+ end
1098
+
1099
+ puts "accept a proxy #{ addrinfo.ip_unpack.inspect }"
1100
+
1101
+ proxy_info = {
1102
+ addrinfo: addrinfo,
1103
+ im: nil,
1104
+ paused_dsts: [],
1105
+ paused_p2s: [],
1106
+ rbuff: '',
1107
+ src_infos: {}, # src_id => { :created_at :dst :rbuff }
1108
+ wbuff: ''
1109
+ }
1110
+
1111
+ @proxy_infos[ proxy ] = proxy_info
1112
+ add_read( proxy, :proxy )
1113
+ end
1114
+
1115
+ def resolve_domain_port( domain_port, src_id, proxy, im )
1116
+ return if domain_port.nil? || domain_port.empty?
1117
+ colon_idx = domain_port.rindex( ':' )
1118
+ return unless colon_idx
1119
+
1120
+ domain = domain_port[ 0...colon_idx ]
1121
+ port = domain_port[ ( colon_idx + 1 )..-1 ].to_i
1122
+
1123
+ if ( domain !~ /^[0-9a-zA-Z\-\.]{1,63}$/ ) || ( domain =~ /^((0\.\d{1,3}\.\d{1,3}\.\d{1,3})|(10\.\d{1,3}\.\d{1,3}\.\d{1,3})|(127\.\d{1,3}\.\d{1,3}\.\d{1,3})|(169\.254\.\d{1,3}\.\d{1,3})|(172\.((1[6-9])|(2\d)|(3[01]))\.\d{1,3}\.\d{1,3})|(192\.168\.\d{1,3}\.\d{1,3})|(255\.255\.255\.255)|(localhost))$/ ) then
1124
+ # 忽略非法域名,内网地址
1125
+ puts "ignore #{ domain }"
1126
+ return
1127
+ end
1128
+
1129
+ if domain =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}.\d{1,3}$/ then
1130
+ # ipv4
1131
+ new_a_dst( domain, domain, port, src_id, proxy )
1132
+ return
1133
+ end
1134
+
1135
+ resolv_cache = @resolv_caches[ domain ]
1136
+
1137
+ if resolv_cache then
1138
+ ip, created_at, im = resolv_cache
1139
+
1140
+ if Time.new - created_at < @expire_resolv_cache then
1141
+ new_a_dst( domain, ip, port, src_id, proxy )
1142
+ return
1143
+ end
1144
+
1145
+ @resolv_caches.delete( domain )
1146
+ end
1147
+
1148
+ begin
1149
+ data = pack_a_query( domain )
1150
+ rescue Exception => e
1151
+ puts "dns pack a query #{ e.class } #{ e.message } #{ domain }" if @is_debug
1152
+ return
1153
+ end
1154
+
1155
+ check_expire_dnses
1156
+ dns = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
1157
+
1158
+ begin
1159
+ @nameserver_addrs.each{ | addr | dns.sendmsg( data, 0, addr ) }
1160
+ rescue Exception => e
1161
+ puts "dns send data #{ e.class } #{ domain }"
1162
+ dns.close
1163
+ return
1164
+ end
1165
+
1166
+ dns_info = {
1167
+ domain: domain,
1168
+ im: im,
1169
+ port: port,
1170
+ proxy: proxy,
1171
+ src_id: src_id
1172
+ }
1173
+
1174
+ @dns_infos[ dns ] = dns_info
1175
+ add_read( dns, :dns )
1176
+ end
1177
+
1178
+ def send_data( sock, data, target_addr )
1179
+ begin
1180
+ sock.sendmsg( data, 0, target_addr )
1181
+ rescue Exception => e
1182
+ puts "sendmsg #{ e.class }"
1183
+ end
1184
+ end
1185
+
1186
+ def set_dst_closing( dst )
1187
+ return if dst.nil? || dst.closed?
1188
+ dst_info = @dst_infos[ dst ]
1189
+ return if dst_info.nil? || dst_info[ :closing ]
1190
+ dst_info[ :closing ] = true
1191
+ add_write( dst )
1192
+ end
1193
+
1194
+ def set_p2_closing( p2 )
1195
+ return if p2.nil? || p2.closed?
1196
+ p2_info = @p2_infos[ p2 ]
1197
+ return if p2_info.nil? || p2_info[ :closing ]
1198
+ p2_info[ :closing ] = true
1199
+ add_write( p2 )
1200
+ end
1201
+
1202
+ def set_update( sock )
1203
+ @updates[ sock ] = Time.new
1204
+
1205
+ if @updates_limit - @updates.size <= 20 then
1206
+ puts "updates #{ @updates.size }"
1207
+ end
1208
+
1209
+ if @updates.size >= @updates_limit then
1210
+ puts "eliminate updates"
1211
+
1212
+ @updates.keys.each do | _sock |
1213
+ case @roles[ _sock ]
1214
+ when :dns
1215
+ close_dns( _sock )
1216
+ when :dst
1217
+ close_dst( _sock )
1218
+ when :mem
1219
+ close_mem( _sock )
1220
+ when :p2
1221
+ close_p2( _sock )
1222
+ when :proxy
1223
+ close_proxy( _sock )
1224
+ when :rsv
1225
+ close_rsv( _sock )
1226
+ else
1227
+ close_sock( _sock )
1228
+ end
1229
+ end
1230
+
1231
+ @eliminate_count += 1
1232
+ end
1233
+ end
1234
+
1235
+ def write_dst( dst )
1236
+ if dst.closed? then
1237
+ puts "write closed dst?"
1238
+ return
1239
+ end
1240
+
1241
+ dst_info = @dst_infos[ dst ]
1242
+ dst_info[ :connected ] = true
1243
+ data = dst_info[ :wbuff ]
1244
+
1245
+ if data.empty? then
1246
+ if dst_info[ :closing ] then
1247
+ close_dst( dst )
1248
+ else
1249
+ @writes.delete( dst )
1250
+ end
1251
+
1252
+ return
1253
+ end
1254
+
1255
+ begin
1256
+ written = dst.write_nonblock( data )
1257
+ rescue Errno::EINPROGRESS
1258
+ return
1259
+ rescue Exception => e
1260
+ close_dst( dst )
1261
+ return
1262
+ end
1263
+
1264
+ set_update( dst )
1265
+ im = dst_info[ :im ]
1266
+ im_info = @im_infos[ im ]
1267
+ im_info[ :out ] += written if im_info
1268
+ data = data[ written..-1 ]
1269
+ dst_info[ :wbuff ] = data
1270
+ bytesize = dst_info[ :wbuff ].bytesize
1271
+
1272
+ if dst_info[ :overflowing ] && ( bytesize < RESUME_BELOW ) then
1273
+ proxy = dst_info[ :proxy ]
1274
+ src_id = dst_info[ :src_id ]
1275
+ puts "add h_dst_underhalf #{ im } #{ src_id } #{ dst_info[ :domain ] }"
1276
+ msg = "#{ @h_dst_underhalf }#{ [ src_id ].pack( 'Q>' ) }"
1277
+ add_proxy_wbuff( proxy, pack_a_chunk( msg ) )
1278
+ dst_info[ :overflowing ] = false
1279
+ end
1280
+ end
1281
+
1282
+ def write_mem( mem )
1283
+ if mem.closed? then
1284
+ puts "write closed mem?"
1285
+ return
1286
+ end
1287
+
1288
+ mem_info = @mem_infos[ mem ]
1289
+ data = mem_info[ :wbuff ]
1290
+
1291
+ if data.empty? then
1292
+ @writes.delete( mem )
1293
+ close_mem( mem )
1294
+ return
1295
+ end
1296
+
1297
+ begin
1298
+ written = mem.write_nonblock( data )
1299
+ rescue Errno::EINPROGRESS
1300
+ return
1301
+ rescue Exception => e
1302
+ close_mem( mem )
1303
+ return
1304
+ end
1305
+
1306
+ set_update( mem )
1307
+ data = data[ written..-1 ]
1308
+ mem_info[ :wbuff ] = data
1309
+ end
1310
+
1311
+ def write_p2( p2 )
1312
+ if p2.closed? then
1313
+ puts "write closed p2?"
1314
+ return
1315
+ end
1316
+
1317
+ p2_info = @p2_infos[ p2 ]
1318
+ im = p2_info[ :im ]
1319
+ im_info = @im_infos[ im ]
1320
+
1321
+ unless im_info then
1322
+ close_p2( p2 )
1323
+ return
1324
+ end
1325
+
1326
+ data = p2_info[ :wbuff ]
1327
+
1328
+ if data.empty? then
1329
+ if p2_info[ :closing ] then
1330
+ close_p2( p2 )
1331
+ else
1332
+ @writes.delete( p2 )
1333
+ end
1334
+
1335
+ return
1336
+ end
1337
+
1338
+ begin
1339
+ written = p2.write_nonblock( data )
1340
+ rescue Errno::EINPROGRESS
1341
+ return
1342
+ rescue Exception => e
1343
+ close_p2( p2 )
1344
+ return
1345
+ end
1346
+
1347
+ set_update( p2 )
1348
+ data = data[ written..-1 ]
1349
+ p2_info[ :wbuff ] = data
1350
+ bytesize = p2_info[ :wbuff ].bytesize
1351
+
1352
+ if p2_info[ :overflowing ] && ( bytesize < RESUME_BELOW ) then
1353
+ proxy = im_info[ :proxy ]
1354
+ p2_id = p2_info[ :p2_id ]
1355
+ puts "add h_p2_underhalf #{ im } #{ p2_id }"
1356
+ msg = "#{ @h_p2_underhalf }#{ [ p2_id ].pack( 'Q>' ) }"
1357
+ add_proxy_wbuff( proxy, pack_a_chunk( msg ) )
1358
+ p2_info[ :overflowing ] = false
1359
+ end
1360
+ end
1361
+
1362
+ def write_proxy( proxy )
1363
+ if proxy.closed? then
1364
+ puts "write closed proxy?"
1365
+ return
1366
+ end
1367
+
1368
+ proxy_info = @proxy_infos[ proxy ]
1369
+ data = proxy_info[ :wbuff ]
1370
+
1371
+ if data.empty? then
1372
+ @writes.delete( proxy )
1373
+ return
1374
+ end
1375
+
1376
+ begin
1377
+ written = proxy.write_nonblock( data )
1378
+ rescue Errno::EINPROGRESS
1379
+ return
1380
+ rescue Exception => e
1381
+ close_proxy( proxy )
1382
+ return
1383
+ end
1384
+
1385
+ set_update( proxy )
1386
+ im = proxy_info[ :im ]
1387
+ im_info = @im_infos[ im ]
1388
+ im_info[ :out ] += written if im_info
1389
+ data = data[ written..-1 ]
1390
+ proxy_info[ :wbuff ] = data
1391
+ bytesize = proxy_info[ :wbuff ].bytesize
1392
+
1393
+ if bytesize < RESUME_BELOW then
1394
+ if proxy_info[ :paused_dsts ].any? then
1395
+ puts "proxy underhalf resume dsts #{ im } #{ proxy_info[ :paused_dsts ].size }"
1396
+ proxy_info[ :paused_dsts ].each{ | dst | add_read( dst ) }
1397
+ proxy_info[ :paused_dsts ].clear
1398
+ end
1399
+
1400
+ if proxy_info[ :paused_p2s ].any? then
1401
+ puts "proxy underhalf resume p2s #{ im } #{ proxy_info[ :paused_p2s ].size }"
1402
+ proxy_info[ :paused_p2s ].each{ | p2 | add_read( p2 ) }
1403
+ proxy_info[ :paused_p2s ].clear
1404
+ end
1405
+ end
1406
+ end
1407
+
1408
+ end
1409
+ end