Passed
Push — develop ( b91c6d...602856 )
by Nikolay
05:44 queued 10s
created

PBX::logRotate()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 5
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
/**
3
 * Copyright © MIKO LLC - All Rights Reserved
4
 * Unauthorized copying of this file, via any medium is strictly prohibited
5
 * Proprietary and confidential
6
 * Written by Alexey Portnov, 7 2020
7
 */
8
9
namespace MikoPBX\Core\System;
10
11
use MikoPBX\Common\Models\Codecs;
12
use MikoPBX\Core\Asterisk\CdrDb;
13
use MikoPBX\Core\Asterisk\Configs\{ExtensionsConf,
14
    FeaturesConf,
15
    HttpConf,
16
    IAXConf,
17
    ManagerConf,
18
    ModulesConf,
19
    MusicOnHoldConf,
20
    SIPConf,
21
    VoiceMailConf
22
};
23
use MikoPBX\Core\Config\RegisterDIServices;
24
use MikoPBX\Core\Workers\WorkerAmiListener;
25
use MikoPBX\Core\Workers\WorkerCallEvents;
26
use Phalcon\Di;
27
use Phalcon\Di\Injectable;
28
29
/**
30
 * Class PBX
31
 *
32
 * @package MikoPBX\Core\System
33
 */
34
class PBX extends Injectable
35
{
36
    /**
37
     * Перезапуск процесса Asterisk.
38
     */
39
    public static function restart(): void
40
    {
41
        $pbx = new PBX();
42
        $pbx->stop();
43
        $pbx->start();
44
    }
45
46
    /**
47
     * Остановка процесса Asterisk.
48
     */
49
    public function stop(): void
50
    {
51
        Util::killByName('safe_asterisk');
52
        sleep(1);
53
        $asteriskPath = Util::which('asterisk');
54
        Util::mwExec("{$asteriskPath} -rx 'core stop now'");
55
        Util::processWorker('', '', WorkerCallEvents::class, 'stop');
56
        Util::processWorker('', '', WorkerAmiListener::class, 'stop');
57
        Util::killByName('asterisk');
58
    }
59
60
    /**
61
     * Запуск процесса Asterisk.
62
     *
63
     */
64
    public function start(): void
65
    {
66
        Network::startSipDump();
67
        if (Util::isSystemctl()) {
68
            $systemctlPath = Util::which('systemctl');
69
            Util::mwExecBg("{$systemctlPath} restart asterisk");
70
        } else {
71
            $safe_asteriskPath = Util::which('safe_asterisk');
72
            // Ключ "-n" отключает подсветку цветом в CLI asterisk.
73
            Util::mwExecBg("{$safe_asteriskPath} -f");
74
        }
75
    }
76
77
    public static function logRotate(): void
78
    {
79
        self::rotatePbxLog('messages');
80
        self::rotatePbxLog('security_log');
81
        self::rotatePbxLog('error');
82
    }
83
84
    public static function rotatePbxLog($f_name): void
85
    {
86
        $di           = Di::getDefault();
87
        $asteriskPath = Util::which('asterisk');
88
        if ($di === null) {
89
            return;
90
        }
91
        $max_size    = 2;
92
        $log_dir     = System::getLogDir() . '/asterisk/';
93
        $text_config = "{$log_dir}{$f_name} {
94
    nocreate
95
    nocopytruncate
96
    delaycompress
97
    nomissingok
98
    start 0
99
    rotate 9
100
    size {$max_size}M
101
    missingok
102
    noolddir
103
    postrotate
104
        {$asteriskPath} -rx 'logger reload' > /dev/null 2> /dev/null
105
    endscript
106
}";
107
        $varEtcPath  = $di->getShared('config')->path('core.varEtcPath');
108
        $path_conf   = $varEtcPath . '/asterisk_logrotate_' . $f_name . '.conf';
109
        file_put_contents($path_conf, $text_config);
110
        $mb10 = $max_size * 1024 * 1024;
111
112
        $options = '';
113
        if (Util::mFileSize("{$log_dir}{$f_name}") > $mb10) {
114
            $options = '-f';
115
        }
116
        $logrotatePath = Util::which('logrotate');
117
        Util::mwExecBg("{$logrotatePath} {$options} '{$path_conf}' > /dev/null 2> /dev/null");
118
    }
119
120
    /**
121
     * Refresh features configs and reload features module
122
     */
123
    public static function featuresReload(): void
124
    {
125
        $featuresConf = new FeaturesConf();
126
        $featuresConf->generateConfig();
127
        $arr_out      = [];
128
        $asteriskPath = Util::which('asterisk');
129
        Util::mwExec("{$asteriskPath} -rx 'module reload features'", $arr_out);
130
    }
131
132
    /**
133
     * Restarts asterisk core
134
     */
135
    public static function coreReload(): void
136
    {
137
        $featuresConf = new FeaturesConf();
138
        $featuresConf->generateConfig();
139
        $arr_out      = [];
140
        $asteriskPath = Util::which('asterisk');
141
        Util::mwExec("{$asteriskPath} -rx 'core reload'", $arr_out);
142
    }
143
144
    /**
145
     *  Reloads Asterisk manager interface module
146
     */
147
    public static function managerReload(): void
148
    {
149
        $managerCong = new ManagerConf();
150
        $managerCong->generateConfig();
151
152
        $httpConf = new HttpConf();
153
        $httpConf->generateConfig();
154
155
        $arr_out      = [];
156
        $asteriskPath = Util::which('asterisk');
157
        Util::mwExec("{$asteriskPath} -rx 'module reload manager'", $arr_out);
158
        Util::mwExec("{$asteriskPath} -rx 'module reload http'", $arr_out);
159
    }
160
161
    /**
162
     *  Reloads Asterisk music on hold module
163
     */
164
    public static function musicOnHoldReload(): void
165
    {
166
        $o = new MusicOnHoldConf();
167
        $o->generateConfig();
168
        $asteriskPath = Util::which('asterisk');
169
        Util::mwExec("{$asteriskPath} -rx 'moh reload'");
170
    }
171
172
    /**
173
     *  Reloads Asterisk voicemail module
174
     */
175
    public static function voicemailReload(): void
176
    {
177
        $o = new VoiceMailConf();
178
        $o->generateConfig();
179
        $arr_out      = [];
180
        $asteriskPath = Util::which('asterisk');
181
        Util::mwExec("{$asteriskPath} -rx 'voicemail reload'", $arr_out);
182
    }
183
184
    /**
185
     *  Reloads Asterisk modules
186
     */
187
    public static function modulesReload(): array
188
    {
189
        $pbx = new ModulesConf();
190
        $pbx->generateConfig();
191
        $arr_out      = [];
192
        $asteriskPath = Util::which('asterisk');
193
        Util::mwExec("{$asteriskPath} -rx 'core restart now'", $arr_out);
194
195
        return [
196
            'result' => 'Success',
197
            'data'   => '',
198
        ];
199
    }
200
201
202
    public static function checkCodec($name, $desc, $type): void
203
    {
204
        $codec = Codecs::findFirst('name="' . $name . '"');
205
        if ($codec === null) {
206
            /** @var \MikoPBX\Common\Models\Codecs $codec_g722 */
207
            $codec              = new Codecs();
208
            $codec->name        = $name;
209
            $codec->type        = $type;
210
            $codec->description = $desc;
211
            $codec->save();
212
        }
213
    }
214
215
    /**
216
     *  Refresh SIP configs and reload PJSIP module
217
     */
218
    public static function sipReload():void
219
    {
220
        $di     = Di::getDefault();
221
        if ($di === null) {
222
            return;
223
        }
224
        $network = new Network();
225
226
        $topology    = 'public';
227
        $extipaddr   = '';
228
        $exthostname = '';
229
        $networks    = $network->getEnabledLanInterfaces();
230
        foreach ($networks as $if_data) {
231
            $lan_config = $network->getInterface($if_data['interface']);
232
            if (null === $lan_config['ipaddr'] || null === $lan_config['subnet']) {
233
                continue;
234
            }
235
            if (trim($if_data['internet']) === '1') {
236
                $topology    = trim($if_data['topology']);
237
                $extipaddr   = trim($if_data['extipaddr']);
238
                $exthostname = trim($if_data['exthostname']);
239
            }
240
        }
241
        $old_hash   = '';
242
        $varEtcPath = $di->getShared('config')->path('core.varEtcPath');
243
        if (file_exists($varEtcPath . '/topology_hash')) {
244
            $old_hash = file_get_contents($varEtcPath . '/topology_hash');
245
        }
246
        $now_hadh = md5($topology . $exthostname . $extipaddr);
247
248
        $sip = new SIPConf();
249
        $sip->generateConfig();
250
251
        $out = [];
252
        if ($old_hash === $now_hadh) {
253
            $asteriskPath = Util::which('asterisk');
254
            Util::mwExec("{$asteriskPath} -rx 'module reload acl'", $out);
255
            Util::mwExec("{$asteriskPath} -rx 'core reload'", $out);
256
        } else {
257
            // Завершаем каналы.
258
            $asteriskPath = Util::which('asterisk');
259
            Util::mwExec("{$asteriskPath} -rx 'channel request hangup all'", $out);
260
            usleep(500000);
261
            Util::mwExec("{$asteriskPath} -rx 'core restart now'", $out);
262
        }
263
    }
264
265
    /**
266
     * Refresh IAX configs and reload iax2 module
267
     */
268
    public static function iaxReload(): void
269
    {
270
        $iax    = new IAXConf();
271
        $iax->generateConfig();
272
        $asteriskPath = Util::which('asterisk');
273
        Util::mwExec("{$asteriskPath} -rx 'iax2 reload'");
274
    }
275
276
    /**
277
     * Ожидаем полной загрузки asterisk.
278
     *
279
     * @return bool
280
     */
281
    public static function waitFullyBooted(): bool
282
    {
283
        $time_start = microtime(true);
284
        $result     = false;
285
        $out        = [];
286
        if (Util::isSystemctl()) {
287
            $options = '';
288
        } else {
289
            $options = '-t';
290
        }
291
        $timeoutPath  = Util::which('timeout');
292
        $asteriskPath = Util::which('asterisk');
293
        while (true) {
294
            $execResult = Util::mwExec(
295
                "{$timeoutPath} {$options} 1 {$asteriskPath} -rx'core waitfullybooted'",
296
                $out
297
            );
298
            if ($execResult === 0 && implode('', $out) === 'Asterisk has fully booted.') {
299
                $result = true;
300
                break;
301
            }
302
            $time = microtime(true) - $time_start;
303
            if ($time > 60) {
304
                Util::sysLogMsg(__CLASS__, 'Error: Asterisk has not booted');
305
                break;
306
            }
307
        }
308
309
        return $result;
310
    }
311
312
    /**
313
     * Generates all Asterisk configuration files and (re)starts the Asterisk process
314
     */
315
    public function configure(): array
316
    {
317
        $result = [
318
            'result' => 'ERROR',
319
        ];
320
321
        if ( ! $this->registry->booting) {
0 ignored issues
show
Bug Best Practice introduced by
The property registry does not exist on MikoPBX\Core\System\PBX. Since you implemented __get, consider adding a @property annotation.
Loading history...
322
            $this->stop();
323
        }
324
        /**
325
         * Создание конфигурационных файлов.
326
         */
327
        foreach ($this->pbxConfModules as $appClass) {
0 ignored issues
show
Bug Best Practice introduced by
The property pbxConfModules does not exist on MikoPBX\Core\System\PBX. Since you implemented __get, consider adding a @property annotation.
Loading history...
328
            $appClass->generateConfig();
329
        }
330
        self::dialplanReload();
331
        if ($this->registry->booting) {
332
            echo "   |- dialplan reload \033[32;1mdone\033[0m \n";
333
        }
334
        // Создание базы данных истории звонков.
335
        /** @var \Phalcon\Db\Adapter\Pdo\Sqlite $connection */
336
        $connection = $this->di->get('dbCDR');
337
        if ( ! $connection->tableExists('cdr')) {
338
            RegisterDIServices::recreateDBConnections();
339
        } else {
340
            CdrDb::checkDb();
341
        }
342
343
        $result['result'] = 'Success';
344
345
        return $result;
346
    }
347
348
    /**
349
     * Запуск генератора dialplan.
350
     *
351
     * @return array
352
     */
353
    public static function dialplanReload(): void
354
    {
355
        $di = Di::getDefault();
356
        if ($di === null) {
357
            return;
358
        }
359
        $extensions = new ExtensionsConf();
360
        $extensions->generateConfig();
361
        if ($di->getRegistry()->booting !== true) {
362
            $path_asterisk = Util::which('asterisk');
363
            Util::mwExec("{$path_asterisk} -rx 'dialplan reload'");
364
            Util::mwExec("{$path_asterisk} -rx 'module reload pbx_lua.so'");
365
        }
366
    }
367
368
}
369