Skip to content

Releases: matasarei/php-tcp

1.3.1

Choose a tag to compare

@matasarei matasarei released this 07 Sep 00:39
c08ace6

Fixed

  • A read timeout was reported as a broken connection on PHP 8.1 and newer. fread() returns
    false there where earlier versions returned an empty string, and the client took that for a
    dead stream — so the default framing mode, which ends a response on a quiet interval, threw
    ConnectionException: Request failed, broken connection. on every request against a real
    socket. A timeout is now told apart from a broken stream by
    stream_get_meta_data()['timed_out'].

    Present since 1.0 and dormant until PHP 8.1 changed the return value. The suite missed it
    because it drives the client through a php:// stream wrapper, whose read cannot return
    false; a socket-pair test now covers the real thing.

1.3.0

Choose a tag to compare

@matasarei matasarei released this 06 Sep 23:52

Added

  • Client::setMaxResponseSize() and Client::DEFAULT_MAX_RESPONSE_SIZE — a response is now
    capped at 8 MiB by default and throws a RequestException beyond it. Pass null for the
    previous unlimited behaviour.
  • StreamSocket and FSocket take a second constructor argument, $blocking. The first
    argument now only sets the read timeout; previously it decided both, so a positive timeout
    forced a blocking stream. Defaults keep the old behaviour.

Fixed

  • Security: neither transport pinned a scheme, so a host such as udp://127.0.0.1 opened a
    UDP socket. StreamSocket and FSocket now build a tcp:// address and reject a host
    containing :// with a SocketException.
  • Security: the read timeout was only checked when a read came back empty, so a peer that
    kept sending was never timed out and the response grew until the process ran out of memory.
    The elapsed time is now checked on every iteration.
  • The debug log carried the whole Request object, putting the request body — credentials
    included — into the consumer's log. It now carries the body length.
  • Client::connect() accepts a float timeout. It had no parameter type and passed the value
    to an int parameter, so connect(0.5) became 0 and raised an implicit-conversion
    deprecation on PHP 8.1+.
  • A read no longer takes twice the timeout: the clock started after the initial wait had already
    returned, so the wait and the read loop each got a full one. The remaining overshoot is the
    socket's own read timeout, since the elapsed check sits before a blocking fread().
  • phpunit.xml no longer sets stopOnFailure, so a failing run reports every failure.

Changed

  • Package renamed from matasarei/phptcp to matasarei/php-tcp, and the repository renamed to
    match — install with composer require matasarei/php-tcp. The PHP namespace Matasar\PhpTcp
    is unchanged, so no code changes are required. Packagist serves the whole tag history under the
    new name, so 1.0, 1.1 and 1.2.0 resolve there too, even though their own composer.json still
    carries the old one.
  • The no-response exception message is now Request timeout, no response. — it previously
    carried a stray backslash. Code matching on that string needs updating.
  • StreamSocket and FSocket type their first constructor argument as int; a value that is
    not an integer now raises a TypeError instead of being coerced. Same for
    Client::connect(), which is now float and no longer accepts null.

1.2.0

Choose a tag to compare

@matasarei matasarei released this 23 Jul 21:25
197a083

Robustness fixes for the stream handling, opt-in delimiter-based response framing, and modernized tooling.

Added

  • Client::setDelimiter() — optional end-of-response marker (e.g. "\n" for line-based protocols such as JSON-RPC over TCP). With a delimiter set, a response is complete as soon as it ends with the delimiter instead of after a silent interval on the stream: reads return sooner and truncated responses are detected (RequestException on timeout, ConnectionException when the connection closes before the response is completed) rather than silently accepted.
  • Client::setPollInterval() and Client::DEFAULT_POLL_INTERVAL — renamed from "connection lag": the value is the pause between data availability checks.
  • CI: GitHub Actions matrix testing PHP 7.4, 8.0, 8.1, 8.2, 8.3, 8.4 and 8.5.

Fixed

  • Infinite loop on a broken stream: read() looped on fread() !== '', but fread() returns false on error, so a broken stream spun forever. It now throws a ConnectionException.
  • A connection closed by the peer looked like a timeout: neither read loop checked feof(), so a closed connection kept polling for the full request timeout (30 s by default) and then reported a timeout. It now fails fast with ConnectionException.
  • Unchecked and partial writes: request() ignored the fwrite() result, so large request bodies could be partially written with no error surfaced. Writes now continue until the whole body is sent; a zero-byte write (full send buffer in non-blocking mode) is retried until the request timeout.

Changed

  • Default chunk size raised from 1024 to 8192 bytes to match the size of PHP's internal stream read buffer.
  • psr/log v1, v2 and v3 are now accepted (Client::setLogger() returns void per the v3 interface).
  • Minimum PHP version raised from 7.1 to 7.4.
  • Test suite migrated from PHPUnit 7 to PHPUnit 9.6; README rewritten.

Deprecated

  • Client::setConnectionLag() — use setPollInterval() instead.
  • Client::DEFAULT_CONNECTION_LAG — use DEFAULT_POLL_INTERVAL instead.

Removed

  • Unused ext-json requirement from composer.json.

Backward-compatibility notes

  • Wire behaviour without a delimiter is unchanged.
  • A peer-closed connection now throws ConnectionException promptly instead of RequestException after the full timeout — code that caught only RequestException for that case should also catch ConnectionException.

Full Changelog: 1.1...1.2.0