From c61d27de0640cc09b2e48e499bec568c0cc63342 Mon Sep 17 00:00:00 2001
From: Nigel Kukard <nkukard@lbsd.net>
Date: Thu, 18 Apr 2013 18:42:48 +0000
Subject: [PATCH] Fixed timeouts and added noblocking write

* Fixed timeouts for non-blocking read
* Added non-blocking write (fixes short write errors)

- Special thanks to Srinivasu for reporting this

Change-Id: I5aa36c023640a4cef130383ba48635f39ce7a086
---
 .../registrars/cozaepp/Net/EPP/Protocol.php   | 47 +++++++++++++++++--
 1 file changed, 43 insertions(+), 4 deletions(-)

diff --git a/modules/registrars/cozaepp/Net/EPP/Protocol.php b/modules/registrars/cozaepp/Net/EPP/Protocol.php
index bd4f210..ae2d694 100644
--- a/modules/registrars/cozaepp/Net/EPP/Protocol.php
+++ b/modules/registrars/cozaepp/Net/EPP/Protocol.php
@@ -49,13 +49,13 @@ class Net_EPP_Protocol {
 				}
 			} else {
 				// Sleep 0.25s
-	       	 		usleep(2500);
+				usleep(250000);
 			}
 			// Update metadata
 			$info = stream_get_meta_data($socket);
 			$time_end = microtime(true);
-			if (($time_end - $time_start) > 5) {
-				throw new exception('Timeout while contacting EPP Server');
+			if (($time_end - $time_start) > 10000000) {
+				throw new exception('Timeout while reading from EPP Server');
 			}
 		}
 
@@ -67,6 +67,45 @@ class Net_EPP_Protocol {
 		return $result;
 	}
 
+
+	static function _fwrite_nb($socket,$buffer,$length) {
+		// Loop writing and checking info to see if we hit timeout
+		$info = stream_get_meta_data($socket);
+		$time_start = microtime(true);
+
+		$pos = 0;
+		while (!$info['timed_out'] && !feof($socket)) {
+			// Some servers don't like alot of data, so keep it small per chunk
+			$wlen = $length - $pos;
+			if ($wlen > 1024) { $wlen = 1024; }
+			// Try write remaining data from socket
+			$written = @fwrite($socket,substr($buffer,$pos),$wlen);
+			// If we read something, bump up the position
+			if ($written && $written !== false) {
+				$pos += $written;
+				// If we hit the length we looking for, break
+				if ($pos == $length) {
+					break;
+				}
+			} else {
+				// Sleep 0.25s
+				usleep(250000);
+			}
+			// Update metadata
+			$info = stream_get_meta_data($socket);
+			$time_end = microtime(true);
+			if (($time_end - $time_start) > 10000000) {
+				throw new exception('Timeout while writing to EPP Server');
+			}
+		}
+		// Check for timeout
+		if ($info['timed_out']) {
+			throw new Exception('Timeout while writing data to socket');
+		}
+
+		return $pos;
+	}
+
 	/**
 	* get an EPP frame from the remote peer
 	* @param resource $socket a socket connected to the remote peer
@@ -100,7 +139,7 @@ class Net_EPP_Protocol {
 	static function sendFrame($socket, $xml) {
 		// Grab XML length & add on 4 bytes for the counter
 		$length = strlen($xml) + 4;
-		$res = fwrite($socket, pack('N',$length) . $xml);
+		$res = Net_EPP_Protocol::_fwrite_nb($socket, pack('N',$length) . $xml,$length);
 		// Check our write matches
 		if ($length != $res) {
 			throw new Exception("Short write when sending XML");
-- 
GitLab