3
3
4
4
5
5
require "socket"
6
- require "timeout"
7
6
require "stringio"
8
7
require "openssl"
9
8
require_relative 'authenticator.rb'
@@ -511,20 +510,18 @@ def read
511
510
data = ''
512
511
len = nil
513
512
begin
514
- Timeout . timeout @opts [ :read_timeout ] do
515
- header = @socket . read ( 4 )
516
- raise EOFError unless header && header . length == 4
517
- len1 , len2 , seq = header . unpack ( "CvC" )
518
- len = ( len2 << 8 ) + len1
519
- raise ProtocolError , "invalid packet: sequence number mismatch(#{ seq } != #{ @seq } (expected))" if @seq != seq
520
- @seq = ( @seq + 1 ) % 256
521
- ret = @socket . read ( len )
522
- raise EOFError unless ret && ret . length == len
523
- data . concat ret
524
- end
513
+ header = read_timeout ( 4 , @opts [ :read_timeout ] )
514
+ raise EOFError unless header && header . length == 4
515
+ len1 , len2 , seq = header . unpack ( "CvC" )
516
+ len = ( len2 << 8 ) + len1
517
+ raise ProtocolError , "invalid packet: sequence number mismatch(#{ seq } != #{ @seq } (expected))" if @seq != seq
518
+ @seq = ( @seq + 1 ) % 256
519
+ ret = read_timeout ( len , @opts [ :read_timeout ] )
520
+ raise EOFError unless ret && ret . length == len
521
+ data . concat ret
525
522
rescue EOFError
526
523
raise ClientError ::ServerGoneError , 'MySQL server has gone away'
527
- rescue Timeout :: Error
524
+ rescue Errno :: ETIMEDOUT
528
525
raise ClientError , "read timeout"
529
526
end while len == MAX_PACKET_LENGTH
530
527
@@ -546,34 +543,73 @@ def read
546
543
Packet . new ( data )
547
544
end
548
545
546
+ def read_timeout ( len , timeout )
547
+ return @socket . read ( len ) if timeout . nil? || timeout == 0
548
+ result = ''
549
+ e = ::Time . now + timeout
550
+ while result . size < len
551
+ now = ::Time . now
552
+ raise Errno ::ETIMEDOUT if now > e
553
+ r = @socket . read_nonblock ( len - result . size , exception : false )
554
+ case r
555
+ when :wait_readable
556
+ IO . select ( [ @socket ] , nil , nil , e - now )
557
+ next
558
+ when :wait_writable
559
+ IO . select ( nil , [ @socket ] , nil , e - now )
560
+ next
561
+ else
562
+ result << r
563
+ end
564
+ end
565
+ return result
566
+ end
567
+
549
568
# Write one packet data
550
569
# === Argument
551
570
# data :: [String / IO] packet data. If data is nil, write empty packet.
552
571
def write ( data )
553
572
begin
554
- Timeout . timeout @opts [ :write_timeout ] do
555
- @socket . sync = false
556
- if data . nil?
557
- @socket . write [ 0 , 0 , @seq ] . pack ( "CvC" )
573
+ @socket . sync = false
574
+ if data . nil?
575
+ write_timeout ( [ 0 , 0 , @seq ] . pack ( "CvC" ) , @opts [ :write_timeout ] )
576
+ @seq = ( @seq + 1 ) % 256
577
+ else
578
+ data = StringIO . new data if data . is_a? String
579
+ while d = data . read ( MAX_PACKET_LENGTH )
580
+ write_timeout ( [ d . length %256 , d . length /256 , @seq ] . pack ( "CvC" ) +d , @opts [ :write_timeout ] )
558
581
@seq = ( @seq + 1 ) % 256
559
- else
560
- data = StringIO . new data if data . is_a? String
561
- while d = data . read ( MAX_PACKET_LENGTH )
562
- @socket . write [ d . length %256 , d . length /256 , @seq ] . pack ( "CvC" )
563
- @socket . write d
564
- @seq = ( @seq + 1 ) % 256
565
- end
566
582
end
567
- @socket . sync = true
568
- @socket . flush
569
583
end
584
+ @socket . sync = true
585
+ @socket . flush
570
586
rescue Errno ::EPIPE
571
587
raise ClientError ::ServerGoneError , 'MySQL server has gone away'
572
- rescue Timeout :: Error
588
+ rescue Errno :: ETIMEDOUT
573
589
raise ClientError , "write timeout"
574
590
end
575
591
end
576
592
593
+ def write_timeout ( data , timeout )
594
+ return @socket . write ( data ) if timeout . nil? || timeout == 0
595
+ len = 0
596
+ e = ::Time . now + timeout
597
+ while len < data . size
598
+ now = ::Time . now
599
+ raise Errno ::ETIMEDOUT if now > e
600
+ l = @socket . write_nonblock ( data [ len ..-1 ] , exception : false )
601
+ case l
602
+ when :wait_readable
603
+ IO . select ( [ @socket ] , nil , nil , e - now )
604
+ when :wait_writable
605
+ IO . select ( nil , [ @socket ] , nil , e - now )
606
+ else
607
+ len += l
608
+ end
609
+ end
610
+ return len
611
+ end
612
+
577
613
# Read EOF packet
578
614
# === Exception
579
615
# [ProtocolError] packet is not EOF
0 commit comments