TFramedTransport.php 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. <?php
  2. /*
  3. * Licensed to the Apache Software Foundation (ASF) under one
  4. * or more contributor license agreements. See the NOTICE file
  5. * distributed with this work for additional information
  6. * regarding copyright ownership. The ASF licenses this file
  7. * to you under the Apache License, Version 2.0 (the
  8. * "License"); you may not use this file except in compliance
  9. * with the License. You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing,
  14. * software distributed under the License is distributed on an
  15. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  16. * KIND, either express or implied. See the License for the
  17. * specific language governing permissions and limitations
  18. * under the License.
  19. *
  20. * @package thrift.transport
  21. */
  22. namespace Thrift\Transport;
  23. use Thrift\Factory\TStringFuncFactory;
  24. /**
  25. * Framed transport. Writes and reads data in chunks that are stamped with
  26. * their length.
  27. *
  28. * @package thrift.transport
  29. */
  30. class TFramedTransport extends TTransport
  31. {
  32. /**
  33. * Underlying transport object.
  34. *
  35. * @var TTransport
  36. */
  37. private $transport_;
  38. /**
  39. * Buffer for read data.
  40. *
  41. * @var string
  42. */
  43. private $rBuf_;
  44. /**
  45. * Buffer for queued output data
  46. *
  47. * @var string
  48. */
  49. private $wBuf_;
  50. /**
  51. * Whether to frame reads
  52. *
  53. * @var bool
  54. */
  55. private $read_;
  56. /**
  57. * Whether to frame writes
  58. *
  59. * @var bool
  60. */
  61. private $write_;
  62. /**
  63. * Constructor.
  64. *
  65. * @param TTransport $transport Underlying transport
  66. */
  67. public function __construct($transport=null, $read=true, $write=true)
  68. {
  69. $this->transport_ = $transport;
  70. $this->read_ = $read;
  71. $this->write_ = $write;
  72. }
  73. public function isOpen()
  74. {
  75. return $this->transport_->isOpen();
  76. }
  77. public function open()
  78. {
  79. $this->transport_->open();
  80. }
  81. public function close()
  82. {
  83. $this->transport_->close();
  84. }
  85. /**
  86. * Reads from the buffer. When more data is required reads another entire
  87. * chunk and serves future reads out of that.
  88. *
  89. * @param int $len How much data
  90. */
  91. public function read($len)
  92. {
  93. if (!$this->read_) {
  94. return $this->transport_->read($len);
  95. }
  96. if (TStringFuncFactory::create()->strlen($this->rBuf_) === 0) {
  97. $this->readFrame();
  98. }
  99. // Just return full buff
  100. if ($len >= TStringFuncFactory::create()->strlen($this->rBuf_)) {
  101. $out = $this->rBuf_;
  102. $this->rBuf_ = null;
  103. return $out;
  104. }
  105. // Return TStringFuncFactory::create()->substr
  106. $out = TStringFuncFactory::create()->substr($this->rBuf_, 0, $len);
  107. $this->rBuf_ = TStringFuncFactory::create()->substr($this->rBuf_, $len);
  108. return $out;
  109. }
  110. /**
  111. * Put previously read data back into the buffer
  112. *
  113. * @param string $data data to return
  114. */
  115. public function putBack($data)
  116. {
  117. if (TStringFuncFactory::create()->strlen($this->rBuf_) === 0) {
  118. $this->rBuf_ = $data;
  119. } else {
  120. $this->rBuf_ = ($data . $this->rBuf_);
  121. }
  122. }
  123. /**
  124. * Reads a chunk of data into the internal read buffer.
  125. */
  126. private function readFrame()
  127. {
  128. $buf = $this->transport_->readAll(4);
  129. $val = unpack('N', $buf);
  130. $sz = $val[1];
  131. $this->rBuf_ = $this->transport_->readAll($sz);
  132. }
  133. /**
  134. * Writes some data to the pending output buffer.
  135. *
  136. * @param string $buf The data
  137. * @param int $len Limit of bytes to write
  138. */
  139. public function write($buf, $len=null)
  140. {
  141. if (!$this->write_) {
  142. return $this->transport_->write($buf, $len);
  143. }
  144. if ($len !== null && $len < TStringFuncFactory::create()->strlen($buf)) {
  145. $buf = TStringFuncFactory::create()->substr($buf, 0, $len);
  146. }
  147. $this->wBuf_ .= $buf;
  148. }
  149. /**
  150. * Writes the output buffer to the stream in the format of a 4-byte length
  151. * followed by the actual data.
  152. */
  153. public function flush()
  154. {
  155. if (!$this->write_ || TStringFuncFactory::create()->strlen($this->wBuf_) == 0) {
  156. return $this->transport_->flush();
  157. }
  158. $out = pack('N', TStringFuncFactory::create()->strlen($this->wBuf_));
  159. $out .= $this->wBuf_;
  160. // Note that we clear the internal wBuf_ prior to the underlying write
  161. // to ensure we're in a sane state (i.e. internal buffer cleaned)
  162. // if the underlying write throws up an exception
  163. $this->wBuf_ = '';
  164. $this->transport_->write($out);
  165. $this->transport_->flush();
  166. }
  167. }