1: <?php
2: /**
3: * This code is licensed under AGPLv3 license or Afterlogic Software License
4: * if commercial version of the product was purchased.
5: * For full statements of the licenses see LICENSE-AFTERLOGIC and LICENSE-AGPL3 files.
6: */
7:
8: namespace Aurora\System\Net;
9:
10: /**
11: * @license https://www.gnu.org/licenses/agpl-3.0.html AGPL-3.0
12: * @license https://afterlogic.com/products/common-licensing Afterlogic Software License
13: * @copyright Copyright (c) 2019, Afterlogic Corp.
14: *
15: * @package Api
16: * @subpackage Net
17: */
18: abstract class AbstractProtocol
19: {
20: /**
21: * @var resource
22: */
23: protected $rConnect;
24:
25: /**
26: * @var string
27: */
28: protected $sHost;
29:
30: /**
31: * @var int
32: */
33: protected $iPort;
34:
35: /**
36: * @var bool
37: */
38: protected $bUseSsl;
39:
40: /**
41: * @var int
42: */
43: protected $iConnectTimeOut;
44:
45: /**
46: * @var int
47: */
48: protected $iSocketTimeOut;
49:
50: /**
51: * @param string $sHost
52: * @param int $iPort
53: * @param bool $bUseSsl = false
54: * @param int $iConnectTimeOut = null
55: * @param int $iSocketTimeOut = null
56: */
57: public function __construct($sHost, $iPort, $bUseSsl = false, $iConnectTimeOut = null, $iSocketTimeOut = null)
58: {
59: $oSettings =& \Aurora\System\Api::GetSettings();
60: $iConnectTimeOut = (null === $iConnectTimeOut) ? $oSettings->GetValue('SocketConnectTimeoutSeconds', 5) : $iConnectTimeOut;
61: $iSocketTimeOut = (null === $iSocketTimeOut) ? $oSettings->GetValue('SocketGetTimeoutSeconds', 5) : $iSocketTimeOut;
62:
63: $this->sHost = $sHost;
64: $this->iPort = $iPort;
65: $this->bUseSsl = $bUseSsl;
66: $this->iConnectTimeOut = $iConnectTimeOut;
67: $this->iSocketTimeOut = $iSocketTimeOut;
68: }
69:
70: /**
71: * @return bool
72: */
73: public function Connect()
74: {
75: $sHost = ($this->bUseSsl) ? 'ssl://'.$this->sHost : $this->sHost;
76:
77: if ($this->IsConnected()) {
78: \Aurora\System\Api::Log('already connected['.$sHost.':'.$this->iPort.']: result = false', \Aurora\System\Enums\LogLevel::Error);
79:
80: $this->Disconnect();
81: return false;
82: }
83:
84: $sErrorStr = '';
85: $iErrorNo = 0;
86:
87: \Aurora\System\Api::Log('start connect to '.$sHost.':'.$this->iPort);
88: $this->rConnect = @fsockopen($sHost, $this->iPort, $iErrorNo, $sErrorStr, $this->iConnectTimeOut);
89:
90: if (!$this->IsConnected()) {
91: \Aurora\System\Api::Log('connection error['.$sHost.':'.$this->iPort.']: fsockopen = false ('.$iErrorNo.': '.$sErrorStr.')', \Aurora\System\Enums\LogLevel::Error);
92: return false;
93: } else {
94: \Aurora\System\Api::Log('connected');
95: }
96:
97: if (\MailSo\Base\Utils::FunctionExistsAndEnabled('stream_set_timeout')) {
98: @stream_set_timeout($this->rConnect, $this->iSocketTimeOut);
99: }
100:
101: if (\MailSo\Base\Utils::FunctionExistsAndEnabled('@stream_set_blocking')) {
102: @stream_set_blocking($this->rConnect, true);
103: }
104:
105: return true;
106: }
107:
108: /**
109: * @return bool
110: */
111: public function Disconnect()
112: {
113: if ($this->IsConnected()) {
114: \Aurora\System\Api::Log('disconnect from '.$this->sHost.':'.$this->iPort);
115: @fclose($this->rConnect);
116: }
117: $this->rConnect = null;
118: return true;
119: }
120:
121: /**
122: * @return resource
123: */
124: public function GetConnectResource()
125: {
126: return $this->rConnect;
127: }
128:
129: /**
130: * @return bool
131: */
132: public function IsConnected()
133: {
134: return is_resource($this->rConnect);
135: }
136:
137: /**
138: * @return string | bool
139: */
140: public function ReadLine()
141: {
142: $sLine = @fgets($this->rConnect, 4096);
143: \Aurora\System\Api::Log('NET < '.\Aurora\System\Utils::ShowCRLF($sLine));
144:
145: if (false === $sLine) {
146: $aSocketStatus = @socket_get_status($this->rConnect);
147: if (isset($aSocketStatus['timed_out']) && $aSocketStatus['timed_out']) {
148: \Aurora\System\Api::Log('NET[Error] < Socket timeout reached during connection.', \Aurora\System\Enums\LogLevel::Error);
149: } else {
150: \Aurora\System\Api::Log('NET[Error] < fgets = false', \Aurora\System\Enums\LogLevel::Error);
151: }
152: }
153:
154: return $sLine;
155: }
156:
157: /**
158: * @param string $sLine
159: * @return bool
160: */
161: public function WriteLine($sLine, $aHideValues = array())
162: {
163: $sLine = $sLine."\r\n";
164: $sLogLine = (0 < count($aHideValues))
165: ? str_replace($aHideValues, '*******', $sLine) : $sLine;
166:
167: \Aurora\System\Api::Log('NET > '.\Aurora\System\Utils::ShowCRLF($sLogLine));
168:
169: if (!@fputs($this->rConnect, $sLine)) {
170: \Aurora\System\Api::Log('NET[Error] < Could not send user request', \Aurora\System\Enums\LogLevel::Error);
171: return false;
172: }
173:
174: return true;
175: }
176: }
177: