girl 9.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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