• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Austinb / GameQ / 12094481485

30 Nov 2024 07:08AM UTC coverage: 93.572% (-0.3%) from 93.905%
12094481485

push

travis-ci

web-flow
Solve warnings and remove deprecated code (#729)

* [Fix] PHPDoc annotations for improved static analysis
* [Change] Drop use of soon to be removed utf8_encode / utf8_decode functions
* [Change] Prevent sprintf template being null on getJoinLink()
* [Fix] Protocols::joinLink default value and type hints
* [Fix] Deprecated pass preg_replace subject as null
* [Fix] Implicit conversion losing precision from float to integer
* [Fix] Deprecated dynamic property in test Issue588
* [Change] Refactor Iterators in Filters with Arr::recursively
* [Change] Refactor Normalize Filter
* [Change] Refactor Stripcolors Filter
* [Change] Add comments to know what is to be deprecated
* [Change] Refactor the CI workflow matrix
* [Fix] Keep build logs directory
* [Change] Protocol packetResponse parameter default value to empty array instead of null (ported back from @Krymonota)
* [Fix] Updated PHPDoc throws for all Protocols
* [Fix] Source protocol skip non´challenge response (ported back from @Krymonota)
* [Change] Use Coveralis action and enable parallel support
* [Add] Docker in Docker to DevContainer to run act
* [Add] Tool act to the DevContainer for local GitHub Workflows

163 of 192 new or added lines in 27 files covered. (84.9%)

4 existing lines in 3 files now uncovered.

2402 of 2567 relevant lines covered (93.57%)

263.17 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

50.75
/src/GameQ/Query/Native.php
1
<?php
2
/**
3
 * This file is part of GameQ.
4
 *
5
 * GameQ is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU Lesser General Public License as published by
7
 * the Free Software Foundation; either version 3 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * GameQ is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU Lesser General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU Lesser General Public License
16
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
 */
18

19
namespace GameQ\Query;
20

21
use GameQ\Exception\Query as Exception;
22

23
/**
24
 * Native way of querying servers
25
 *
26
 * @author Austin Bischoff <austin@codebeard.com>
27
 */
28
class Native extends Core
29
{
30
    /**
31
     * Get the current socket or create one and return
32
     *
33
     * @return resource|null
34
     * @throws \GameQ\Exception\Query
35
     */
UNCOV
36
    public function get()
×
37
    {
38

39
        // No socket for this server, make one
40
        if (is_null($this->socket)) {
×
41
            $this->create();
×
42
        }
43

44
        return $this->socket;
×
45
    }
46

47
    /**
48
     * Write data to the socket
49
     *
50
     * @param string $data
51
     *
52
     * @return int The number of bytes written
53
     * @throws \GameQ\Exception\Query
54
     */
55
    public function write($data)
55✔
56
    {
57

58
        try {
59
            // No socket for this server, make one
60
            if (is_null($this->socket)) {
55✔
61
                $this->create();
55✔
62
            }
63

64
            // Send the packet
65
            return fwrite($this->socket, $data);
×
66
        } catch (\Exception $e) {
55✔
67
            throw new Exception($e->getMessage(), $e->getCode(), $e);
55✔
68
        }
69
    }
70

71
    /**
72
     * Close the current socket
73
     */
UNCOV
74
    public function close()
×
75
    {
76

77
        if ($this->socket) {
×
78
            fclose($this->socket);
×
79
            $this->socket = null;
×
80
        }
81
    }
82

83
    /**
84
     * Create a new socket for this query
85
     *
86
     * @throws \GameQ\Exception\Query
87
     */
88
    protected function create()
55✔
89
    {
90

91
        // Create the remote address
92
        $remote_addr = sprintf("%s://%s:%d", $this->transport, $this->ip, $this->port);
55✔
93

94
        // Create context
95
        $context = stream_context_create([
55✔
96
            'socket' => [
50✔
97
                'bindto' => '0:0', // Bind to any available IP and OS decided port
40✔
98
            ],
40✔
99
        ]);
40✔
100

101
        // Define these first
102
        $errno = null;
55✔
103
        $errstr = null;
55✔
104

105
        // Create the socket
106
        if (($this->socket =
55✔
107
                @stream_socket_client($remote_addr, $errno, $errstr, $this->timeout, STREAM_CLIENT_CONNECT, $context))
55✔
108
            !== false
15✔
109
        ) {
5✔
110
            // Set the read timeout on the streams
111
            stream_set_timeout($this->socket, $this->timeout);
×
112

113
            // Set blocking mode
114
            stream_set_blocking($this->socket, $this->blocking);
×
115

116
            // Set the read buffer
117
            stream_set_read_buffer($this->socket, 0);
×
118

119
            // Set the write buffer
120
            stream_set_write_buffer($this->socket, 0);
×
121
        } else {
122
            // Reset socket
123
            $this->socket = null;
55✔
124

125
            // Something bad happened, throw query exception
126
            throw new Exception(
55✔
127
                __METHOD__ . " - Error creating socket to server {$this->ip}:{$this->port}. Error: " . $errstr,
55✔
128
                $errno
50✔
129
            );
40✔
130
        }
131
    }
132

133
    /**
134
     * Pull the responses out of the stream
135
     *
136
     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
137
     * @SuppressWarnings(PHPMD.NPathComplexity)
138
     *
139
     * @param array $sockets
140
     * @param int   $timeout
141
     * @param int   $stream_timeout
142
     *
143
     * @return array Raw responses
144
     */
145
    public function getResponses(array $sockets, $timeout, $stream_timeout)
55✔
146
    {
147

148
        // Set the loop to active
149
        $loop_active = true;
55✔
150

151
        // Will hold the responses read from the sockets
152
        $responses = [];
55✔
153

154
        // To store the sockets
155
        $sockets_tmp = [];
55✔
156

157
        // Loop and pull out all the actual sockets we need to listen on
158
        foreach ($sockets as $socket_id => $socket_data) {
55✔
159
            // Get the socket
160
            /* @var $socket \GameQ\Query\Core */
161
            $socket = $socket_data['socket'];
×
162

163
            // Append the actual socket we are listening to
164
            $sockets_tmp[$socket_id] = $socket->get();
×
165

166
            unset($socket);
×
167
        }
5✔
168

169
        // Init some variables
170
        $read = $sockets_tmp;
55✔
171
        $write = null;
55✔
172
        $except = null;
55✔
173

174
        // Check to see if $read is empty, if so stream_select() will throw a warning
175
        if (empty($read)) {
55✔
176
            return $responses;
55✔
177
        }
178

179
        // This is when it should stop
180
        $time_stop = microtime(true) + $timeout;
×
181

182
        // Let's loop until we break something.
183
        while ($loop_active && microtime(true) < $time_stop) {
×
184
            // Check to make sure $read is not empty, if so we are done
185
            if (empty($read)) {
×
186
                break;
×
187
            }
188

189
            // Now lets listen for some streams, but do not cross the streams!
190
            $streams = stream_select($read, $write, $except, 0, $stream_timeout);
×
191

192
            // We had error or no streams left, kill the loop
193
            if ($streams === false || ($streams <= 0)) {
×
194
                break;
×
195
            }
196

197
            // Loop the sockets that received data back
198
            foreach ($read as $socket) {
×
199
                /* @var $socket resource */
200

201
                // See if we have a response
202
                if (($response = fread($socket, 32768)) === false) {
×
203
                    continue; // No response yet so lets continue.
×
204
                }
205

206
                // Check to see if the response is empty, if so we are done with this server
207
                if (strlen($response) == 0) {
×
208
                    // Remove this server from any future read loops
209
                    unset($sockets_tmp[(int)$socket]);
×
210
                    continue;
×
211
                }
212

213
                // Add the response we got back
214
                $responses[(int)$socket][] = $response;
×
215
            }
216

217
            // Because stream_select modifies read we need to reset it each time to the original array of sockets
218
            $read = $sockets_tmp;
×
219
        }
220

221
        // Free up some memory
222
        unset($streams, $read, $write, $except, $sockets_tmp, $time_stop, $response);
×
223

224
        // Return all of the responses, may be empty if something went wrong
225
        return $responses;
×
226
    }
227
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc