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

sineflow / clamav / 22680423281

02 Mar 2026 08:04PM UTC coverage: 95.455% (+19.3%) from 76.106%
22680423281

push

github

pmishev
Dropped support for PHP <8.2 and Symfony <6.4.
Modernise codebase with minor API changes.
Added socket_timeout option.
Fixed potential issue with socket connections.
Switched to PSR12 code style standard.
Added tests and a docker env for test execution.

68 of 74 new or added lines in 11 files covered. (91.89%)

126 of 132 relevant lines covered (95.45%)

77.5 hits per line

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

83.78
/src/Socket/Socket.php
1
<?php
2

3
namespace Sineflow\ClamAV\Socket;
4

5
use Sineflow\ClamAV\Exception\SocketException;
6

7
class Socket
8
{
9
    public const UNIX = \AF_UNIX;
10
    public const NETWORK = \AF_INET;
11

12
    private const MAX_READ_BYTES = 8192;
13

14
    private ?\Socket $socket = null;
15

16
    public function __construct(
240✔
17
        private readonly int $socketType,
18
        private readonly array $connectionArguments,
19
        private readonly ?int $timeoutSeconds = null,
20
    ) {
21
    }
240✔
22

23
    public function sendCommand(string $dataIn, int $flagsSend = 0, int $flagsReceive = MSG_WAITALL): string
170✔
24
    {
25
        $this->connect();
170✔
26

27
        if (false === socket_send($this->socket, $dataIn, strlen($dataIn), $flagsSend)) {
170✔
NEW
28
            $this->closeAndThrow('Writing to socket failed');
×
29
        }
30
        $dataOut = '';
170✔
31

32
        do {
33
            $bytes = socket_recv($this->socket, $chunk, self::MAX_READ_BYTES, $flagsReceive);
170✔
34
            if (false === $bytes) {
170✔
35
                $this->closeAndThrow('Reading from socket failed');
10✔
36
            }
37
            $dataOut .= $chunk;
160✔
38
        } while ($bytes);
160✔
39
        socket_close($this->socket);
160✔
40
        $this->socket = null;
160✔
41

42
        return $dataOut;
160✔
43
    }
44

45
    /**
46
     * @throws SocketException
47
     */
48
    private function connect(): void
170✔
49
    {
50
        if ($this->socket instanceof \Socket) {
170✔
NEW
51
            return;
×
52
        }
53

54
        $socket = @ socket_create($this->socketType, SOCK_STREAM, 0);
170✔
55
        if ($socket === false) {
170✔
NEW
56
            $this->closeAndThrow('Creating socket failed');
×
57
        }
58
        $this->socket = $socket;
170✔
59

60
        $success = @ socket_connect($this->socket, ...$this->connectionArguments);
170✔
61
        if ($success === false) {
170✔
NEW
62
            $this->closeAndThrow('Connecting to socket failed');
×
63
        }
64

65
        if ($this->timeoutSeconds !== null) {
170✔
66
            $timeout = ['sec' => $this->timeoutSeconds, 'usec' => 0];
10✔
67
            if (false === socket_set_option($this->socket, SOL_SOCKET, SO_SNDTIMEO, $timeout)) {
10✔
NEW
68
                $this->closeAndThrow('Setting socket send timeout failed');
×
69
            }
70
            if (false === socket_set_option($this->socket, SOL_SOCKET, SO_RCVTIMEO, $timeout)) {
10✔
NEW
71
                $this->closeAndThrow('Setting socket receive timeout failed');
×
72
            }
73
        }
74
    }
75

76
    private function closeAndThrow(string $message): never
10✔
77
    {
78
        $errorCode = socket_last_error($this->socket);
10✔
79
        if (null !== $this->socket) {
10✔
80
            socket_close($this->socket);
10✔
81
            $this->socket = null;
10✔
82
        }
83
        throw new SocketException($message, $errorCode);
10✔
84
    }
85
}
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