root/framework/trunk/src/main/php/net/stubbles/peer/stubSocket.php @ 2253

Revision 2253, 5.8 kB (checked in by mikey, 15 months ago)

fixed defect #204: chunked encoding reading problems

  • Property svn:keywords set to Id
Line 
1<?php
2/**
3 * Class for operations on sockets.
4 *
5 * @author      Frank Kleine <mikey@stubbles.net>
6 * @package     stubbles
7 * @subpackage  peer
8 */
9stubClassLoader::load('net::stubbles::lang::exceptions::stubIllegalStateException',
10                      'net::stubbles::peer::stubConnectionException'
11);
12/**
13 * Class for operations on sockets.
14 *
15 * @package     stubbles
16 * @subpackage  peer
17 */
18class stubSocket extends stubBaseObject
19{
20    /**
21     * host to open socket to
22     *
23     * @var  string
24     */
25    protected $host    = null;
26    /**
27     * port to use for opening the socket
28     *
29     * @var  int
30     */
31    protected $port    = 80;
32    /**
33     * timeout
34     *
35     * @var  int
36     */
37    protected $timeout = 30;
38    /**
39     * internal resource pointer
40     *
41     * @var  resource
42     */
43    protected $fp      = null;
44
45    /**
46     * constructor
47     *
48     * @param  string  $host  host to open socket to
49     * @param  int     $port  port to use for opening the socket
50     */
51    public function __construct($host, $port = 80)
52    {
53        $this->host = $host;
54        $this->port = $port;
55    }
56
57    /**
58     * destructor
59     */
60    public function __destruct()
61    {
62        $this->disconnect();
63    }
64
65    /**
66     * opens a http connection to host
67     *
68     * @return  bool    TRUE if connect was successful
69     * @throws  stubConnectionException
70     */
71    public function connect()
72    {
73        if ($this->isConnected() === true) {
74            return true;
75        }
76
77        if (null == $this->host) {
78            return false;
79        }
80
81        $errno    = 0;
82        $errstr   = '';
83        $this->fp = @fsockopen($this->host, $this->port, $errno, $errstr, $this->timeout);
84        if (false === $this->fp) {
85            $this->fp = null;
86            throw new stubConnectionException('Connecting to ' . $this->host . ':' . $this->port . ' within ' . $this->timeout . ' seconds failed: ' . $errstr . ' (' . $errno . ').');
87        }
88
89        socket_set_timeout($this->fp, $this->timeout);
90        return true;
91    }
92
93    /**
94     * closes a connection
95     */
96    public function disconnect()
97    {
98        if ($this->isConnected() === true) {
99            fclose($this->fp);
100            $this->fp = null;
101        }
102    }
103
104    /**
105     * set timeout for connections
106     *
107     * @param  int  $timeout  timeout for connection in seconds
108     */
109    public function setTimeout($timeout)
110    {
111        $this->timeout = $timeout;
112        if ($this->isConnected() === true) {
113            socket_set_timeout($this->fp, $this->timeout);
114        }
115    }
116
117    /**
118     * read from socket
119     *
120     * @param   int     $length  optional  length of data to read
121     * @return  string  data read from socket
122     * @throws  stubConnectionException
123     * @throws  stubIllegalStateException
124     */
125    public function read($length = 4096)
126    {
127        if ($this->isConnected() === false) {
128            throw new stubIllegalStateException('Can not read on unconnected socket.');
129        }
130
131        $data = fgets($this->fp, $length);
132        if (false === $data) {
133            // fgets returns false on eof while feof() returned false before
134            // but will now return true
135            if ($this->eof() === true) {
136                return null;
137            }
138           
139            throw new stubConnectionException('Reading of ' . $length . ' bytes failed.');
140        }
141
142        return $data;
143    }
144
145    /**
146     * read a whole line from socket
147     *
148     * @param   int     $length  optional  length of data to read
149     * @return  string  data read from socket
150     */
151    public function readLine($length = 4096)
152    {
153        return rtrim($this->read($length));
154    }
155
156    /**
157     * read binary data from socket
158     *
159     * @param   int     $length  optional  length of data to read
160     * @return  string  data read from socket
161     * @throws  stubConnectionException
162     * @throws  stubIllegalStateException
163     */
164    public function readBinary($length = 1024)
165    {
166        if ($this->isConnected() === false) {
167            throw new stubIllegalStateException('Can not read on unconnected socket.');
168        }
169
170        $data = fread($this->fp, $length);
171        if (false === $data) {
172            throw new stubConnectionException('Reading of ' . $length . ' bytes failed.');
173        }
174
175        return $data;
176    }
177
178    /**
179     * write data to socket
180     *
181     * @param   string  $data  data to write
182     * @return  int     amount of bytes written to socket
183     * @throws  stubConnectionException
184     * @throws  stubIllegalStateException
185     */
186    public function write($data)
187    {
188        if ($this->isConnected() === false) {
189            throw new stubIllegalStateException('Can not write on unconnected socket.');
190        }
191
192        $length = fputs($this->fp, $data, strlen($data));
193        if (false === $length) {
194            throw new stubConnectionException('"Writing of ' . strlen($data) . ' bytes failed.');
195        }
196
197        return $length;
198    }
199
200    /**
201     * get host of current connection
202     *
203     * @return  string
204     */
205    public function getHost()
206    {
207        return $this->host;
208    }
209
210    /**
211     * get port of current connection
212     *
213     * @return  int
214     */
215    public function getPort()
216    {
217        return $this->port;
218    }
219
220    /**
221     * get timeout for connections
222     *
223     * @return  int
224     */
225    public function getTimeout()
226    {
227        return $this->timeout;
228    }
229
230    /**
231     * checks if we already have a connection
232     *
233     * @return  bool
234     */
235    public function isConnected()
236    {
237        return is_resource($this->fp);
238    }
239
240    /**
241     * check if we reached end of data
242     *
243     * @return  bool
244     */
245    public function eof()
246    {
247        if ($this->isConnected() === true) {
248            return feof($this->fp);
249        }
250
251        return true;
252    }
253}
254?>
Note: See TracBrowser for help on using the browser.