@@ -92,6 +92,13 @@ final class UdpTransportExecutor implements ExecutorInterface
9292 private $ parser ;
9393 private $ dumper ;
9494
95+ /**
96+ * maximum UDP packet size to send and receive
97+ *
98+ * @var int
99+ */
100+ private $ maxPacketSize = 512 ;
101+
95102 /**
96103 * @param string $nameserver
97104 * @param LoopInterface $loop
@@ -119,7 +126,7 @@ public function query(Query $query)
119126 $ request = Message::createRequestForQuery ($ query );
120127
121128 $ queryData = $ this ->dumper ->toBinary ($ request );
122- if (isset ($ queryData [512 ])) {
129+ if (isset ($ queryData [$ this -> maxPacketSize ])) {
123130 return \React \Promise \reject (new \RuntimeException (
124131 'DNS query for ' . $ query ->name . ' failed: Query too large for UDP transport ' ,
125132 \defined ('SOCKET_EMSGSIZE ' ) ? \SOCKET_EMSGSIZE : 90
@@ -142,14 +149,14 @@ public function query(Query $query)
142149 if ($ written !== \strlen ($ queryData )) {
143150 // Write may potentially fail, but most common errors are already caught by connection check above.
144151 // Among others, macOS is known to report here when trying to send to broadcast address.
145- // @codeCoverageIgnoreStart
152+ // This can also be reproduced by writing data exceeding `stream_set_chunk_size()` to a server refusing UDP data.
153+ // fwrite(): send of 8192 bytes failed with errno=111 Connection refused
146154 $ error = \error_get_last ();
147155 \preg_match ('/errno=(\d+) (.+)/ ' , $ error ['message ' ], $ m );
148156 return \React \Promise \reject (new \RuntimeException (
149157 'DNS query for ' . $ query ->name . ' failed: Unable to send query to DNS server ( ' . (isset ($ m [2 ]) ? $ m [2 ] : $ error ['message ' ]) . ') ' ,
150158 isset ($ m [1 ]) ? (int ) $ m [1 ] : 0
151159 ));
152- // @codeCoverageIgnoreEnd
153160 }
154161
155162 $ loop = $ this ->loop ;
@@ -161,11 +168,12 @@ public function query(Query $query)
161168 throw new CancellationException ('DNS query for ' . $ query ->name . ' has been cancelled ' );
162169 });
163170
171+ $ max = $ this ->maxPacketSize ;
164172 $ parser = $ this ->parser ;
165- $ loop ->addReadStream ($ socket , function ($ socket ) use ($ loop , $ deferred , $ query , $ parser , $ request ) {
173+ $ loop ->addReadStream ($ socket , function ($ socket ) use ($ loop , $ deferred , $ query , $ parser , $ request, $ max ) {
166174 // try to read a single data packet from the DNS server
167175 // ignoring any errors, this is uses UDP packets and not a stream of data
168- $ data = @\fread ($ socket , 512 );
176+ $ data = @\fread ($ socket , $ max );
169177
170178 try {
171179 $ response = $ parser ->parseMessage ($ data );
0 commit comments