girl 3.9.0 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of girl might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/girl.gemspec +1 -0
- data/lib/girl/concurrent_hash.rb +4 -0
- data/lib/girl/custom.rb +11 -0
- data/lib/girl/head.rb +11 -1
- data/lib/girl/proxy.rb +30 -31
- data/lib/girl/proxy_custom.rb +16 -13
- data/lib/girl/proxy_worker.rb +491 -595
- data/lib/girl/proxyd.rb +1 -15
- data/lib/girl/proxyd_custom.rb +12 -9
- data/lib/girl/proxyd_worker.rb +499 -481
- data/lib/girl/relay.rb +0 -1
- data/lib/girl/relay_worker.rb +460 -573
- data/lib/girl/resolvd_worker.rb +1 -1
- data/lib/girl/ssl.rb +1 -14
- data/lib/girl/ssl_worker.rb +124 -100
- data/lib/girl/version.rb +1 -1
- metadata +3 -2
data/lib/girl/resolvd_worker.rb
CHANGED
data/lib/girl/ssl.rb
CHANGED
@@ -44,26 +44,13 @@ module Girl
|
|
44
44
|
puts title
|
45
45
|
puts "redir port #{ redir_port } worker count #{ worker_count }"
|
46
46
|
|
47
|
-
now = Time.new
|
48
|
-
name = OpenSSL::X509::Name.new
|
49
|
-
key = OpenSSL::PKey::RSA.new 2048
|
50
|
-
cert = OpenSSL::X509::Certificate.new
|
51
|
-
cert.version = 2
|
52
|
-
cert.serial = 0
|
53
|
-
cert.not_before = now
|
54
|
-
cert.not_after = now + 365 * 24 * 60 * 60
|
55
|
-
cert.public_key = key.public_key
|
56
|
-
cert.subject = name
|
57
|
-
cert.issuer = name
|
58
|
-
cert.sign key, OpenSSL::Digest.new('SHA1')
|
59
|
-
|
60
47
|
$0 = title
|
61
48
|
workers = []
|
62
49
|
|
63
50
|
worker_count.times do | i |
|
64
51
|
workers << fork do
|
65
52
|
$0 = 'girl ssl worker'
|
66
|
-
worker = Girl::SslWorker.new( redir_port
|
53
|
+
worker = Girl::SslWorker.new( redir_port )
|
67
54
|
|
68
55
|
Signal.trap( :TERM ) do
|
69
56
|
puts "w#{ i } exit"
|
data/lib/girl/ssl_worker.rb
CHANGED
@@ -4,7 +4,8 @@ module Girl
|
|
4
4
|
##
|
5
5
|
# initialize
|
6
6
|
#
|
7
|
-
def initialize( redir_port
|
7
|
+
def initialize( redir_port )
|
8
|
+
@redir_port = redir_port
|
8
9
|
@reads = []
|
9
10
|
@writes = []
|
10
11
|
@closing_srcs = []
|
@@ -12,15 +13,15 @@ module Girl
|
|
12
13
|
@paused_dsts = []
|
13
14
|
@resume_srcs = []
|
14
15
|
@resume_dsts = []
|
15
|
-
@roles = ConcurrentHash.new
|
16
|
-
@src_infos = ConcurrentHash.new
|
17
|
-
@dst_infos = ConcurrentHash.new
|
18
|
-
@resolv_caches = ConcurrentHash.new
|
16
|
+
@roles = ConcurrentHash.new # sock => :dotr / :redir / :src / :dst
|
17
|
+
@src_infos = ConcurrentHash.new # src => {}
|
18
|
+
@dst_infos = ConcurrentHash.new # dst => {}
|
19
|
+
@resolv_caches = ConcurrentHash.new # domain => [ ip, created_at ]
|
19
20
|
|
20
21
|
dotr, dotw = IO.pipe
|
21
22
|
@dotw = dotw
|
22
23
|
add_read( dotr, :dotr )
|
23
|
-
new_a_redir
|
24
|
+
new_a_redir
|
24
25
|
end
|
25
26
|
|
26
27
|
##
|
@@ -65,7 +66,7 @@ module Girl
|
|
65
66
|
# quit!
|
66
67
|
#
|
67
68
|
def quit!
|
68
|
-
# puts "
|
69
|
+
# puts "debug exit"
|
69
70
|
exit
|
70
71
|
end
|
71
72
|
|
@@ -84,6 +85,7 @@ module Girl
|
|
84
85
|
# add dst wbuff
|
85
86
|
#
|
86
87
|
def add_dst_wbuff( dst, data )
|
88
|
+
return if dst.closed?
|
87
89
|
dst_info = @dst_infos[ dst ]
|
88
90
|
dst_info[ :wbuff ] << data
|
89
91
|
add_write( dst )
|
@@ -155,7 +157,7 @@ module Girl
|
|
155
157
|
# +----+-----+-------+------+----------+----------+
|
156
158
|
redir_ip, redir_port = @redir_local_address.ip_unpack
|
157
159
|
data = [ [ 5, 0, 0, 1 ].pack( 'C4' ), IPAddr.new( redir_ip ).hton, [ redir_port ].pack( 'n' ) ].join
|
158
|
-
# puts "
|
160
|
+
# puts "debug add src.wbuff socks5 conn reply #{ data.inspect }"
|
159
161
|
add_src_wbuff( src, data )
|
160
162
|
end
|
161
163
|
|
@@ -167,7 +169,7 @@ module Girl
|
|
167
169
|
src_info[ :rbuff ] << data
|
168
170
|
|
169
171
|
if src_info[ :rbuff ].bytesize >= WBUFF_LIMIT then
|
170
|
-
# puts "
|
172
|
+
# puts "debug src.rbuff full"
|
171
173
|
add_closing_src( src )
|
172
174
|
end
|
173
175
|
end
|
@@ -206,20 +208,15 @@ module Girl
|
|
206
208
|
#
|
207
209
|
def close_read_dst( dst )
|
208
210
|
return if dst.closed?
|
209
|
-
# puts "
|
211
|
+
# puts "debug close read dst"
|
210
212
|
dst.close_read
|
211
213
|
@reads.delete( dst )
|
212
214
|
|
213
215
|
if dst.closed? then
|
214
|
-
# puts "debug1 delete dst info"
|
215
216
|
@writes.delete( dst )
|
216
217
|
@roles.delete( dst )
|
217
|
-
|
218
|
-
else
|
219
|
-
dst_info = @dst_infos[ dst ]
|
218
|
+
del_dst_info( dst )
|
220
219
|
end
|
221
|
-
|
222
|
-
dst_info
|
223
220
|
end
|
224
221
|
|
225
222
|
##
|
@@ -227,19 +224,16 @@ module Girl
|
|
227
224
|
#
|
228
225
|
def close_read_src( src )
|
229
226
|
return if src.closed?
|
230
|
-
# puts "
|
227
|
+
# puts "debug close read src"
|
231
228
|
src_info = @src_infos[ src ]
|
232
229
|
src_info[ :close_read ] = true
|
233
230
|
|
234
231
|
if src_info[ :close_write ] then
|
235
|
-
# puts "debug1 delete src info"
|
236
232
|
close_sock( src )
|
237
|
-
|
233
|
+
del_src_info( src )
|
238
234
|
else
|
239
235
|
@reads.delete( src )
|
240
236
|
end
|
241
|
-
|
242
|
-
src_info
|
243
237
|
end
|
244
238
|
|
245
239
|
##
|
@@ -257,14 +251,14 @@ module Girl
|
|
257
251
|
#
|
258
252
|
def close_src( src )
|
259
253
|
return if src.closed?
|
260
|
-
# puts "
|
254
|
+
# puts "debug close src"
|
261
255
|
close_sock( src )
|
262
|
-
src_info =
|
256
|
+
src_info = del_src_info( src )
|
263
257
|
dst = src_info[ :dst ]
|
264
258
|
|
265
259
|
if dst then
|
266
260
|
close_sock( dst )
|
267
|
-
|
261
|
+
del_dst_info( dst )
|
268
262
|
end
|
269
263
|
end
|
270
264
|
|
@@ -273,20 +267,15 @@ module Girl
|
|
273
267
|
#
|
274
268
|
def close_write_dst( dst )
|
275
269
|
return if dst.closed?
|
276
|
-
# puts "
|
270
|
+
# puts "debug close write dst"
|
277
271
|
dst.close_write
|
278
272
|
@writes.delete( dst )
|
279
273
|
|
280
274
|
if dst.closed? then
|
281
|
-
# puts "debug1 delete dst info"
|
282
275
|
@reads.delete( dst )
|
283
276
|
@roles.delete( dst )
|
284
|
-
|
285
|
-
else
|
286
|
-
dst_info = @dst_infos[ dst ]
|
277
|
+
del_dst_info( dst )
|
287
278
|
end
|
288
|
-
|
289
|
-
dst_info
|
290
279
|
end
|
291
280
|
|
292
281
|
##
|
@@ -294,18 +283,37 @@ module Girl
|
|
294
283
|
#
|
295
284
|
def close_write_src( src )
|
296
285
|
return if src.closed?
|
297
|
-
# puts "
|
286
|
+
# puts "debug close write src"
|
298
287
|
src_info = @src_infos[ src ]
|
299
288
|
src_info[ :close_write ] = true
|
300
289
|
|
301
290
|
if src_info[ :close_read ] then
|
302
|
-
# puts "debug1 delete src info"
|
303
291
|
close_sock( src )
|
304
|
-
|
292
|
+
del_src_info( src )
|
305
293
|
else
|
306
294
|
@writes.delete( src )
|
307
295
|
end
|
296
|
+
end
|
308
297
|
|
298
|
+
##
|
299
|
+
# del dst info
|
300
|
+
#
|
301
|
+
def del_dst_info( dst )
|
302
|
+
# puts "debug delete dst info"
|
303
|
+
dst_info = @dst_infos.delete( dst )
|
304
|
+
@paused_dsts.delete( dst )
|
305
|
+
@resume_dsts.delete( dst )
|
306
|
+
dst_info
|
307
|
+
end
|
308
|
+
|
309
|
+
##
|
310
|
+
# del src info
|
311
|
+
#
|
312
|
+
def del_src_info( src )
|
313
|
+
# puts "debug delete src info"
|
314
|
+
src_info = @src_infos.delete( src )
|
315
|
+
@paused_srcs.delete( src )
|
316
|
+
@resume_srcs.delete( src )
|
309
317
|
src_info
|
310
318
|
end
|
311
319
|
|
@@ -324,7 +332,7 @@ module Girl
|
|
324
332
|
expire_after = src_info[ :dst ] ? EXPIRE_AFTER : EXPIRE_NEW
|
325
333
|
|
326
334
|
if ( now - last_recv_at >= expire_after ) && ( now - last_sent_at >= expire_after ) then
|
327
|
-
puts "p#{ Process.pid } #{ Time.new } expire src #{ expire_after } #{ src_info[ :destination_domain ] }"
|
335
|
+
puts "p#{ Process.pid } #{ Time.new } expire src #{ expire_after } #{ src_info[ :id ] } #{ src_info[ :destination_domain ] }"
|
328
336
|
add_closing_src( src )
|
329
337
|
|
330
338
|
unless src_info[ :rbuff ].empty? then
|
@@ -345,35 +353,27 @@ module Girl
|
|
345
353
|
sleep CHECK_RESUME_INTERVAL
|
346
354
|
|
347
355
|
@paused_srcs.each do | src |
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
if
|
355
|
-
|
356
|
-
|
357
|
-
if dst_info[ :wbuff ].size < RESUME_BELOW then
|
358
|
-
puts "p#{ Process.pid } #{ Time.new } resume direct src #{ src_info[ :destination_domain ] }"
|
359
|
-
add_resume_src( src )
|
360
|
-
end
|
356
|
+
src_info = @src_infos[ src ]
|
357
|
+
dst = src_info[ :dst ]
|
358
|
+
|
359
|
+
if dst then
|
360
|
+
dst_info = @dst_infos[ dst ]
|
361
|
+
|
362
|
+
if dst_info[ :wbuff ].size < RESUME_BELOW then
|
363
|
+
puts "p#{ Process.pid } #{ Time.new } resume direct src #{ src_info[ :destination_domain ] }"
|
364
|
+
add_resume_src( src )
|
361
365
|
end
|
362
366
|
end
|
363
367
|
end
|
364
368
|
|
365
369
|
@paused_dsts.each do | dst |
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
dst_info = @dst_infos[ dst ]
|
370
|
-
src = dst_info[ :src ]
|
371
|
-
src_info = @src_infos[ src ]
|
370
|
+
dst_info = @dst_infos[ dst ]
|
371
|
+
src = dst_info[ :src ]
|
372
|
+
src_info = @src_infos[ src ]
|
372
373
|
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
end
|
374
|
+
if src_info[ :wbuff ].size < RESUME_BELOW then
|
375
|
+
puts "p#{ Process.pid } #{ Time.new } resume dst #{ dst_info[ :domain ] }"
|
376
|
+
add_resume_dst( dst )
|
377
377
|
end
|
378
378
|
end
|
379
379
|
end
|
@@ -389,7 +389,6 @@ module Girl
|
|
389
389
|
domain = src_info[ :destination_domain ]
|
390
390
|
destination_addr = Socket.sockaddr_in( src_info[ :destination_port ], ip_info.ip_address )
|
391
391
|
dst = Socket.new( ip_info.ipv4? ? Socket::AF_INET : Socket::AF_INET6, Socket::SOCK_STREAM, 0 )
|
392
|
-
dst.setsockopt( Socket::SOL_TCP, Socket::TCP_NODELAY, 1 )
|
393
392
|
|
394
393
|
begin
|
395
394
|
dst.connect_nonblock( destination_addr )
|
@@ -402,7 +401,7 @@ module Girl
|
|
402
401
|
return
|
403
402
|
end
|
404
403
|
|
405
|
-
# puts "
|
404
|
+
# puts "debug a new dst #{ dst.local_address.inspect }"
|
406
405
|
dst_info = {
|
407
406
|
src: src, # 对应src
|
408
407
|
domain: domain, # 目的地
|
@@ -420,19 +419,32 @@ module Girl
|
|
420
419
|
##
|
421
420
|
# new a redir
|
422
421
|
#
|
423
|
-
def new_a_redir
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
422
|
+
def new_a_redir
|
423
|
+
pre = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
|
424
|
+
pre.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1 )
|
425
|
+
pre.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
|
426
|
+
pre.bind( Socket.sockaddr_in( @redir_port, '0.0.0.0' ) )
|
427
|
+
@redir_local_address = pre.local_address
|
428
|
+
puts "p#{ Process.pid } #{ Time.new } pre bind on #{ @redir_port } local address #{ pre.local_address.inspect }"
|
429
|
+
|
430
|
+
now = Time.new
|
431
|
+
name = OpenSSL::X509::Name.new
|
432
|
+
key = OpenSSL::PKey::RSA.new 1024
|
433
|
+
cert = OpenSSL::X509::Certificate.new
|
434
|
+
cert.version = 2
|
435
|
+
cert.serial = 0
|
436
|
+
cert.not_before = now
|
437
|
+
cert.not_after = now + 365 * 24 * 60 * 60
|
438
|
+
cert.public_key = key.public_key
|
439
|
+
cert.subject = name
|
440
|
+
cert.issuer = name
|
441
|
+
cert.sign key, OpenSSL::Digest.new('SHA1')
|
431
442
|
context = OpenSSL::SSL::SSLContext.new
|
443
|
+
context.security_level = 1
|
432
444
|
context.add_certificate( cert, key )
|
433
|
-
redir = OpenSSL::SSL::SSLServer.new
|
445
|
+
redir = OpenSSL::SSL::SSLServer.new pre, context
|
434
446
|
redir.listen( 127 )
|
435
|
-
puts "p#{ Process.pid } #{ Time.new } redir
|
447
|
+
puts "p#{ Process.pid } #{ Time.new } redir listening"
|
436
448
|
add_read( redir, :redir )
|
437
449
|
end
|
438
450
|
|
@@ -453,12 +465,12 @@ module Girl
|
|
453
465
|
ip_info, created_at = resolv_cache
|
454
466
|
|
455
467
|
if Time.new - created_at < RESOLV_CACHE_EXPIRE then
|
456
|
-
# puts "
|
468
|
+
# puts "debug #{ domain } hit resolv cache #{ ip_info.inspect }"
|
457
469
|
new_a_dst( src, ip_info )
|
458
470
|
return
|
459
471
|
end
|
460
472
|
|
461
|
-
# puts "
|
473
|
+
# puts "debug expire #{ domain } resolv cache"
|
462
474
|
@resolv_caches.delete( domain )
|
463
475
|
end
|
464
476
|
|
@@ -508,7 +520,7 @@ module Girl
|
|
508
520
|
# read dotr
|
509
521
|
#
|
510
522
|
def read_dotr( dotr )
|
511
|
-
dotr.read_nonblock(
|
523
|
+
dotr.read_nonblock( 65535 )
|
512
524
|
|
513
525
|
if @closing_srcs.any? then
|
514
526
|
@closing_srcs.each { | src | close_src( src ) }
|
@@ -538,17 +550,30 @@ module Girl
|
|
538
550
|
# read redir
|
539
551
|
#
|
540
552
|
def read_redir( redir )
|
553
|
+
accepted = false
|
554
|
+
|
555
|
+
Thread.new do
|
556
|
+
sleep 1
|
557
|
+
|
558
|
+
unless accepted then
|
559
|
+
puts "p#{ Process.pid } #{ Time.new } accept timeout"
|
560
|
+
redir.close
|
561
|
+
@roles.delete( redir )
|
562
|
+
@reads.delete( redir )
|
563
|
+
new_a_redir
|
564
|
+
end
|
565
|
+
end
|
566
|
+
|
541
567
|
begin
|
542
568
|
src = redir.accept
|
543
|
-
rescue IO::WaitReadable, Errno::EINTR
|
544
|
-
print 'r'
|
545
|
-
return
|
546
569
|
rescue Exception => e
|
547
570
|
puts "p#{ Process.pid } #{ Time.new } redir accept #{ e.class }"
|
571
|
+
puts e.full_message
|
548
572
|
return
|
549
573
|
end
|
550
574
|
|
551
|
-
|
575
|
+
accepted = true
|
576
|
+
# puts "debug accept a src"
|
552
577
|
|
553
578
|
@src_infos[ src ] = {
|
554
579
|
proxy_proto: :uncheck, # :uncheck / :socks5
|
@@ -579,17 +604,19 @@ module Girl
|
|
579
604
|
return
|
580
605
|
end
|
581
606
|
|
607
|
+
src_info = @src_infos[ src ]
|
608
|
+
|
582
609
|
begin
|
583
|
-
data = src.read_nonblock(
|
610
|
+
data = src.read_nonblock( 65535 )
|
584
611
|
rescue IO::WaitReadable
|
585
612
|
return
|
586
613
|
rescue Errno::EINTR => e
|
587
614
|
puts e.class
|
588
615
|
return
|
589
616
|
rescue Exception => e
|
590
|
-
# puts "
|
591
|
-
src_info = close_read_src( src )
|
617
|
+
# puts "debug read src #{ e.class }"
|
592
618
|
dst = src_info[ :dst ]
|
619
|
+
close_read_src( src )
|
593
620
|
|
594
621
|
if dst then
|
595
622
|
set_dst_closing_write( dst )
|
@@ -607,7 +634,7 @@ module Girl
|
|
607
634
|
"p#{ Process.pid } #{ Time.new } unknown data #{ data.inspect }"
|
608
635
|
end
|
609
636
|
|
610
|
-
# puts "
|
637
|
+
# puts "debug socks5 #{ data.inspect }"
|
611
638
|
|
612
639
|
# https://tools.ietf.org/html/rfc1928
|
613
640
|
#
|
@@ -635,7 +662,7 @@ module Girl
|
|
635
662
|
src_info[ :proxy_proto ] = :socks5
|
636
663
|
src_info[ :proxy_type ] = :negotiation
|
637
664
|
when :checking then
|
638
|
-
# puts "
|
665
|
+
# puts "debug add src rbuff before resolved #{ data.inspect }"
|
639
666
|
src_info[ :rbuff ] << data
|
640
667
|
when :negotiation then
|
641
668
|
# +----+-----+-------+------+----------+----------+
|
@@ -643,11 +670,11 @@ module Girl
|
|
643
670
|
# +----+-----+-------+------+----------+----------+
|
644
671
|
# | 1 | 1 | X'00' | 1 | Variable | 2 |
|
645
672
|
# +----+-----+-------+------+----------+----------+
|
646
|
-
# puts "
|
673
|
+
# puts "debug negotiation #{ data.inspect }"
|
647
674
|
ver, cmd, rsv, atyp = data[ 0, 4 ].unpack( 'C4' )
|
648
675
|
|
649
676
|
if cmd == 1 then
|
650
|
-
# puts "
|
677
|
+
# puts "debug socks5 CONNECT"
|
651
678
|
|
652
679
|
if atyp == 1 then
|
653
680
|
destination_host, destination_port = data[ 4, 6 ].unpack( 'Nn' )
|
@@ -656,7 +683,7 @@ module Girl
|
|
656
683
|
destination_ip = destination_addrinfo.ip_address
|
657
684
|
src_info[ :destination_domain ] = destination_ip
|
658
685
|
src_info[ :destination_port ] = destination_port
|
659
|
-
# puts "
|
686
|
+
# puts "debug IP V4 address #{ destination_addrinfo.ip_unpack.inspect }"
|
660
687
|
new_a_dst( src, destination_addrinfo )
|
661
688
|
elsif atyp == 3 then
|
662
689
|
domain_len = data[ 4 ].unpack( 'C' ).first
|
@@ -666,7 +693,7 @@ module Girl
|
|
666
693
|
port = data[ ( 5 + domain_len ), 2 ].unpack( 'n' ).first
|
667
694
|
src_info[ :destination_domain ] = domain
|
668
695
|
src_info[ :destination_port ] = port
|
669
|
-
# puts "
|
696
|
+
# puts "debug DOMAINNAME #{ domain } #{ port }"
|
670
697
|
resolve_domain( src, domain )
|
671
698
|
end
|
672
699
|
end
|
@@ -677,12 +704,9 @@ module Girl
|
|
677
704
|
dst = src_info[ :dst ]
|
678
705
|
|
679
706
|
if dst then
|
680
|
-
|
681
|
-
# puts "debug2 add dst.wbuff #{ data.bytesize }"
|
682
|
-
add_dst_wbuff( dst, data )
|
683
|
-
end
|
707
|
+
add_dst_wbuff( dst, data )
|
684
708
|
else
|
685
|
-
# puts "
|
709
|
+
# puts "debug add src.rbuff #{ data.bytesize }"
|
686
710
|
add_src_rbuff( src, data )
|
687
711
|
end
|
688
712
|
end
|
@@ -697,21 +721,22 @@ module Girl
|
|
697
721
|
return
|
698
722
|
end
|
699
723
|
|
724
|
+
dst_info = @dst_infos[ dst ]
|
725
|
+
src = dst_info[ :src ]
|
726
|
+
|
700
727
|
begin
|
701
|
-
data = dst.read_nonblock(
|
728
|
+
data = dst.read_nonblock( 65535 )
|
702
729
|
rescue IO::WaitReadable, Errno::EINTR
|
703
730
|
print 'r'
|
704
731
|
return
|
705
732
|
rescue Exception => e
|
706
|
-
# puts "
|
707
|
-
|
708
|
-
src = dst_info[ :src ]
|
733
|
+
# puts "debug read dst #{ e.class }"
|
734
|
+
close_read_dst( dst )
|
709
735
|
set_src_closing_write( src )
|
710
736
|
return
|
711
737
|
end
|
712
738
|
|
713
|
-
|
714
|
-
src = dst_info[ :src ]
|
739
|
+
# puts "debug read dst #{ data.bytesize }"
|
715
740
|
add_src_wbuff( src, data )
|
716
741
|
end
|
717
742
|
|
@@ -746,7 +771,7 @@ module Girl
|
|
746
771
|
print 'w'
|
747
772
|
return
|
748
773
|
rescue Exception => e
|
749
|
-
# puts "
|
774
|
+
# puts "debug write src #{ e.class }"
|
750
775
|
close_write_src( src )
|
751
776
|
|
752
777
|
if dst then
|
@@ -756,7 +781,6 @@ module Girl
|
|
756
781
|
return
|
757
782
|
end
|
758
783
|
|
759
|
-
# puts "debug2 written src #{ written }"
|
760
784
|
data = data[ written..-1 ]
|
761
785
|
src_info[ :wbuff ] = data
|
762
786
|
end
|
@@ -792,7 +816,7 @@ module Girl
|
|
792
816
|
print 'w'
|
793
817
|
return
|
794
818
|
rescue Exception => e
|
795
|
-
# puts "
|
819
|
+
# puts "debug write dst #{ e.class }"
|
796
820
|
close_write_dst( dst )
|
797
821
|
close_read_src( src )
|
798
822
|
return
|