1# 2#-- 3#= $RCSfile$ -- Buffering mix-in module. 4# 5#= Info 6# 'OpenSSL for Ruby 2' project 7# Copyright (C) 2001 GOTOU YUUZOU <gotoyuzo@notwork.org> 8# All rights reserved. 9# 10#= Licence 11# This program is licenced under the same licence as Ruby. 12# (See the file 'LICENCE'.) 13# 14#= Version 15# $Id: buffering.rb 45053 2014-02-19 17:14:45Z nagachika $ 16#++ 17 18## 19# OpenSSL IO buffering mix-in module. 20# 21# This module allows an OpenSSL::SSL::SSLSocket to behave like an IO. 22 23module OpenSSL::Buffering 24 include Enumerable 25 26 ## 27 # The "sync mode" of the SSLSocket. 28 # 29 # See IO#sync for full details. 30 31 attr_accessor :sync 32 33 ## 34 # Default size to read from or write to the SSLSocket for buffer operations. 35 36 BLOCK_SIZE = 1024*16 37 38 def initialize(*args) 39 @eof = false 40 @rbuffer = "" 41 @sync = @io.sync 42 end 43 44 # 45 # for reading. 46 # 47 private 48 49 ## 50 # Fills the buffer from the underlying SSLSocket 51 52 def fill_rbuff 53 begin 54 @rbuffer << self.sysread(BLOCK_SIZE) 55 rescue Errno::EAGAIN 56 retry 57 rescue EOFError 58 @eof = true 59 end 60 end 61 62 ## 63 # Consumes +size+ bytes from the buffer 64 65 def consume_rbuff(size=nil) 66 if @rbuffer.empty? 67 nil 68 else 69 size = @rbuffer.size unless size 70 ret = @rbuffer[0, size] 71 @rbuffer[0, size] = "" 72 ret 73 end 74 end 75 76 public 77 78 ## 79 # Reads +size+ bytes from the stream. If +buf+ is provided it must 80 # reference a string which will receive the data. 81 # 82 # See IO#read for full details. 83 84 def read(size=nil, buf=nil) 85 if size == 0 86 if buf 87 buf.clear 88 return buf 89 else 90 return "" 91 end 92 end 93 until @eof 94 break if size && size <= @rbuffer.size 95 fill_rbuff 96 end 97 ret = consume_rbuff(size) || "" 98 if buf 99 buf.replace(ret) 100 ret = buf 101 end 102 (size && ret.empty?) ? nil : ret 103 end 104 105 ## 106 # Reads at most +maxlen+ bytes from the stream. If +buf+ is provided it 107 # must reference a string which will receive the data. 108 # 109 # See IO#readpartial for full details. 110 111 def readpartial(maxlen, buf=nil) 112 if maxlen == 0 113 if buf 114 buf.clear 115 return buf 116 else 117 return "" 118 end 119 end 120 if @rbuffer.empty? 121 begin 122 return sysread(maxlen, buf) 123 rescue Errno::EAGAIN 124 retry 125 end 126 end 127 ret = consume_rbuff(maxlen) 128 if buf 129 buf.replace(ret) 130 ret = buf 131 end 132 raise EOFError if ret.empty? 133 ret 134 end 135 136 ## 137 # Reads at most +maxlen+ bytes in the non-blocking manner. 138 # 139 # When no data can be read without blocking it raises 140 # OpenSSL::SSL::SSLError extended by IO::WaitReadable or IO::WaitWritable. 141 # 142 # IO::WaitReadable means SSL needs to read internally so read_nonblock 143 # should be called again when the underlying IO is readable. 144 # 145 # IO::WaitWritable means SSL needs to write internally so read_nonblock 146 # should be called again after the underlying IO is writable. 147 # 148 # OpenSSL::Buffering#read_nonblock needs two rescue clause as follows: 149 # 150 # # emulates blocking read (readpartial). 151 # begin 152 # result = ssl.read_nonblock(maxlen) 153 # rescue IO::WaitReadable 154 # IO.select([io]) 155 # retry 156 # rescue IO::WaitWritable 157 # IO.select(nil, [io]) 158 # retry 159 # end 160 # 161 # Note that one reason that read_nonblock writes to the underlying IO is 162 # when the peer requests a new TLS/SSL handshake. See openssl the FAQ for 163 # more details. http://www.openssl.org/support/faq.html 164 165 def read_nonblock(maxlen, buf=nil) 166 if maxlen == 0 167 if buf 168 buf.clear 169 return buf 170 else 171 return "" 172 end 173 end 174 if @rbuffer.empty? 175 return sysread_nonblock(maxlen, buf) 176 end 177 ret = consume_rbuff(maxlen) 178 if buf 179 buf.replace(ret) 180 ret = buf 181 end 182 raise EOFError if ret.empty? 183 ret 184 end 185 186 ## 187 # Reads the next "line+ from the stream. Lines are separated by +eol+. If 188 # +limit+ is provided the result will not be longer than the given number of 189 # bytes. 190 # 191 # +eol+ may be a String or Regexp. 192 # 193 # Unlike IO#gets the line read will not be assigned to +$_+. 194 # 195 # Unlike IO#gets the separator must be provided if a limit is provided. 196 197 def gets(eol=$/, limit=nil) 198 idx = @rbuffer.index(eol) 199 until @eof 200 break if idx 201 fill_rbuff 202 idx = @rbuffer.index(eol) 203 end 204 if eol.is_a?(Regexp) 205 size = idx ? idx+$&.size : nil 206 else 207 size = idx ? idx+eol.size : nil 208 end 209 if limit and limit >= 0 210 size = [size, limit].min 211 end 212 consume_rbuff(size) 213 end 214 215 ## 216 # Executes the block for every line in the stream where lines are separated 217 # by +eol+. 218 # 219 # See also #gets 220 221 def each(eol=$/) 222 while line = self.gets(eol) 223 yield line 224 end 225 end 226 alias each_line each 227 228 ## 229 # Reads lines from the stream which are separated by +eol+. 230 # 231 # See also #gets 232 233 def readlines(eol=$/) 234 ary = [] 235 while line = self.gets(eol) 236 ary << line 237 end 238 ary 239 end 240 241 ## 242 # Reads a line from the stream which is separated by +eol+. 243 # 244 # Raises EOFError if at end of file. 245 246 def readline(eol=$/) 247 raise EOFError if eof? 248 gets(eol) 249 end 250 251 ## 252 # Reads one character from the stream. Returns nil if called at end of 253 # file. 254 255 def getc 256 read(1) 257 end 258 259 ## 260 # Calls the given block once for each byte in the stream. 261 262 def each_byte # :yields: byte 263 while c = getc 264 yield(c.ord) 265 end 266 end 267 268 ## 269 # Reads a one-character string from the stream. Raises an EOFError at end 270 # of file. 271 272 def readchar 273 raise EOFError if eof? 274 getc 275 end 276 277 ## 278 # Pushes character +c+ back onto the stream such that a subsequent buffered 279 # character read will return it. 280 # 281 # Unlike IO#getc multiple bytes may be pushed back onto the stream. 282 # 283 # Has no effect on unbuffered reads (such as #sysread). 284 285 def ungetc(c) 286 @rbuffer[0,0] = c.chr 287 end 288 289 ## 290 # Returns true if the stream is at file which means there is no more data to 291 # be read. 292 293 def eof? 294 fill_rbuff if !@eof && @rbuffer.empty? 295 @eof && @rbuffer.empty? 296 end 297 alias eof eof? 298 299 # 300 # for writing. 301 # 302 private 303 304 ## 305 # Writes +s+ to the buffer. When the buffer is full or #sync is true the 306 # buffer is flushed to the underlying socket. 307 308 def do_write(s) 309 @wbuffer = "" unless defined? @wbuffer 310 @wbuffer << s 311 @wbuffer.force_encoding(Encoding::BINARY) 312 @sync ||= false 313 if @sync or @wbuffer.size > BLOCK_SIZE or idx = @wbuffer.rindex($/) 314 remain = idx ? idx + $/.size : @wbuffer.length 315 nwritten = 0 316 while remain > 0 317 str = @wbuffer[nwritten,remain] 318 begin 319 nwrote = syswrite(str) 320 rescue Errno::EAGAIN 321 retry 322 end 323 remain -= nwrote 324 nwritten += nwrote 325 end 326 @wbuffer[0,nwritten] = "" 327 end 328 end 329 330 public 331 332 ## 333 # Writes +s+ to the stream. If the argument is not a string it will be 334 # converted using String#to_s. Returns the number of bytes written. 335 336 def write(s) 337 do_write(s) 338 s.bytesize 339 end 340 341 ## 342 # Writes +str+ in the non-blocking manner. 343 # 344 # If there is buffered data, it is flushed first. This may block. 345 # 346 # write_nonblock returns number of bytes written to the SSL connection. 347 # 348 # When no data can be written without blocking it raises 349 # OpenSSL::SSL::SSLError extended by IO::WaitReadable or IO::WaitWritable. 350 # 351 # IO::WaitReadable means SSL needs to read internally so write_nonblock 352 # should be called again after the underlying IO is readable. 353 # 354 # IO::WaitWritable means SSL needs to write internally so write_nonblock 355 # should be called again after underlying IO is writable. 356 # 357 # So OpenSSL::Buffering#write_nonblock needs two rescue clause as follows. 358 # 359 # # emulates blocking write. 360 # begin 361 # result = ssl.write_nonblock(str) 362 # rescue IO::WaitReadable 363 # IO.select([io]) 364 # retry 365 # rescue IO::WaitWritable 366 # IO.select(nil, [io]) 367 # retry 368 # end 369 # 370 # Note that one reason that write_nonblock reads from the underlying IO 371 # is when the peer requests a new TLS/SSL handshake. See the openssl FAQ 372 # for more details. http://www.openssl.org/support/faq.html 373 374 def write_nonblock(s) 375 flush 376 syswrite_nonblock(s) 377 end 378 379 ## 380 # Writes +s+ to the stream. +s+ will be converted to a String using 381 # String#to_s. 382 383 def << (s) 384 do_write(s) 385 self 386 end 387 388 ## 389 # Writes +args+ to the stream along with a record separator. 390 # 391 # See IO#puts for full details. 392 393 def puts(*args) 394 s = "" 395 if args.empty? 396 s << "\n" 397 end 398 args.each{|arg| 399 s << arg.to_s 400 if $/ && /\n\z/ !~ s 401 s << "\n" 402 end 403 } 404 do_write(s) 405 nil 406 end 407 408 ## 409 # Writes +args+ to the stream. 410 # 411 # See IO#print for full details. 412 413 def print(*args) 414 s = "" 415 args.each{ |arg| s << arg.to_s } 416 do_write(s) 417 nil 418 end 419 420 ## 421 # Formats and writes to the stream converting parameters under control of 422 # the format string. 423 # 424 # See Kernel#sprintf for format string details. 425 426 def printf(s, *args) 427 do_write(s % args) 428 nil 429 end 430 431 ## 432 # Flushes buffered data to the SSLSocket. 433 434 def flush 435 osync = @sync 436 @sync = true 437 do_write "" 438 return self 439 ensure 440 @sync = osync 441 end 442 443 ## 444 # Closes the SSLSocket and flushes any unwritten data. 445 446 def close 447 flush rescue nil 448 sysclose 449 end 450end 451