]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
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 | ||
23 | namespace Thrift\Transport; | |
24 | ||
25 | use Thrift\Factory\TStringFuncFactory; | |
26 | ||
27 | /** | |
28 | * Framed transport. Writes and reads data in chunks that are stamped with | |
29 | * their length. | |
30 | * | |
31 | * @package thrift.transport | |
32 | */ | |
33 | class TFramedTransport extends TTransport | |
34 | { | |
35 | /** | |
36 | * Underlying transport object. | |
37 | * | |
38 | * @var TTransport | |
39 | */ | |
40 | private $transport_; | |
41 | ||
42 | /** | |
43 | * Buffer for read data. | |
44 | * | |
45 | * @var string | |
46 | */ | |
47 | private $rBuf_; | |
48 | ||
49 | /** | |
50 | * Buffer for queued output data | |
51 | * | |
52 | * @var string | |
53 | */ | |
54 | private $wBuf_; | |
55 | ||
56 | /** | |
57 | * Whether to frame reads | |
58 | * | |
59 | * @var bool | |
60 | */ | |
61 | private $read_; | |
62 | ||
63 | /** | |
64 | * Whether to frame writes | |
65 | * | |
66 | * @var bool | |
67 | */ | |
68 | private $write_; | |
69 | ||
70 | /** | |
71 | * Constructor. | |
72 | * | |
73 | * @param TTransport $transport Underlying transport | |
74 | */ | |
75 | public function __construct($transport = null, $read = true, $write = true) | |
76 | { | |
77 | $this->transport_ = $transport; | |
78 | $this->read_ = $read; | |
79 | $this->write_ = $write; | |
80 | } | |
81 | ||
82 | public function isOpen() | |
83 | { | |
84 | return $this->transport_->isOpen(); | |
85 | } | |
86 | ||
87 | public function open() | |
88 | { | |
89 | $this->transport_->open(); | |
90 | } | |
91 | ||
92 | public function close() | |
93 | { | |
94 | $this->transport_->close(); | |
95 | } | |
96 | ||
97 | /** | |
98 | * Reads from the buffer. When more data is required reads another entire | |
99 | * chunk and serves future reads out of that. | |
100 | * | |
101 | * @param int $len How much data | |
102 | */ | |
103 | public function read($len) | |
104 | { | |
105 | if (!$this->read_) { | |
106 | return $this->transport_->read($len); | |
107 | } | |
108 | ||
109 | if (TStringFuncFactory::create()->strlen($this->rBuf_) === 0) { | |
110 | $this->readFrame(); | |
111 | } | |
112 | ||
113 | // Just return full buff | |
114 | if ($len >= TStringFuncFactory::create()->strlen($this->rBuf_)) { | |
115 | $out = $this->rBuf_; | |
116 | $this->rBuf_ = null; | |
117 | ||
118 | return $out; | |
119 | } | |
120 | ||
121 | // Return TStringFuncFactory::create()->substr | |
122 | $out = TStringFuncFactory::create()->substr($this->rBuf_, 0, $len); | |
123 | $this->rBuf_ = TStringFuncFactory::create()->substr($this->rBuf_, $len); | |
124 | ||
125 | return $out; | |
126 | } | |
127 | ||
128 | /** | |
129 | * Put previously read data back into the buffer | |
130 | * | |
131 | * @param string $data data to return | |
132 | */ | |
133 | public function putBack($data) | |
134 | { | |
135 | if (TStringFuncFactory::create()->strlen($this->rBuf_) === 0) { | |
136 | $this->rBuf_ = $data; | |
137 | } else { | |
138 | $this->rBuf_ = ($data . $this->rBuf_); | |
139 | } | |
140 | } | |
141 | ||
142 | /** | |
143 | * Reads a chunk of data into the internal read buffer. | |
144 | */ | |
145 | private function readFrame() | |
146 | { | |
147 | $buf = $this->transport_->readAll(4); | |
148 | $val = unpack('N', $buf); | |
149 | $sz = $val[1]; | |
150 | ||
151 | $this->rBuf_ = $this->transport_->readAll($sz); | |
152 | } | |
153 | ||
154 | /** | |
155 | * Writes some data to the pending output buffer. | |
156 | * | |
157 | * @param string $buf The data | |
158 | * @param int $len Limit of bytes to write | |
159 | */ | |
160 | public function write($buf, $len = null) | |
161 | { | |
162 | if (!$this->write_) { | |
163 | return $this->transport_->write($buf, $len); | |
164 | } | |
165 | ||
166 | if ($len !== null && $len < TStringFuncFactory::create()->strlen($buf)) { | |
167 | $buf = TStringFuncFactory::create()->substr($buf, 0, $len); | |
168 | } | |
169 | $this->wBuf_ .= $buf; | |
170 | } | |
171 | ||
172 | /** | |
173 | * Writes the output buffer to the stream in the format of a 4-byte length | |
174 | * followed by the actual data. | |
175 | */ | |
176 | public function flush() | |
177 | { | |
178 | if (!$this->write_ || TStringFuncFactory::create()->strlen($this->wBuf_) == 0) { | |
179 | return $this->transport_->flush(); | |
180 | } | |
181 | ||
182 | $out = pack('N', TStringFuncFactory::create()->strlen($this->wBuf_)); | |
183 | $out .= $this->wBuf_; | |
184 | ||
185 | // Note that we clear the internal wBuf_ prior to the underlying write | |
186 | // to ensure we're in a sane state (i.e. internal buffer cleaned) | |
187 | // if the underlying write throws up an exception | |
188 | $this->wBuf_ = ''; | |
189 | $this->transport_->write($out); | |
190 | $this->transport_->flush(); | |
191 | } | |
192 | } |