Passed
Pull Request — master (#20)
by Nikolay
04:51
created

PBX::stop()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 7
c 0
b 0
f 0
dl 0
loc 9
rs 10
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, 9 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\{AclConf,
14
    ExtensionsConf,
15
    FeaturesConf,
16
    HttpConf,
17
    IAXConf,
18
    ManagerConf,
19
    ModulesConf,
20
    MusicOnHoldConf,
21
    SIPConf,
22
    VoiceMailConf};
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
        self::rotatePbxLog('verbose');
83
    }
84
85
    public static function rotatePbxLog($f_name): void
86
    {
87
        $di           = Di::getDefault();
88
        $asteriskPath = Util::which('asterisk');
89
        if ($di === null) {
90
            return;
91
        }
92
        $max_size    = 2;
93
        $log_dir     = System::getLogDir() . '/asterisk/';
94
        $text_config = "{$log_dir}{$f_name} {
95
    nocreate
96
    nocopytruncate
97
    delaycompress
98
    nomissingok
99
    start 0
100
    rotate 9
101
    size {$max_size}M
102
    missingok
103
    noolddir
104
    postrotate
105
        {$asteriskPath} -rx 'logger reload' > /dev/null 2> /dev/null
106
    endscript
107
}";
108
        $varEtcDir  = $di->getShared('config')->path('core.varEtcDir');
109
        $path_conf   = $varEtcDir . '/asterisk_logrotate_' . $f_name . '.conf';
110
        file_put_contents($path_conf, $text_config);
111
        $mb10 = $max_size * 1024 * 1024;
112
113
        $options = '';
114
        if (Util::mFileSize("{$log_dir}{$f_name}") > $mb10) {
115
            $options = '-f';
116
        }
117
        $logrotatePath = Util::which('logrotate');
118
        Util::mwExecBg("{$logrotatePath} {$options} '{$path_conf}' > /dev/null 2> /dev/null");
119
    }
120
121
    /**
122
     * Refresh features configs and reload features module
123
     */
124
    public static function featuresReload(): void
125
    {
126
        $featuresConf = new FeaturesConf();
127
        $featuresConf->generateConfig();
128
        $arr_out      = [];
129
        $asteriskPath = Util::which('asterisk');
130
        Util::mwExec("{$asteriskPath} -rx 'module reload features'", $arr_out);
131
    }
132
133
    /**
134
     * Restarts asterisk core
135
     */
136
    public static function coreReload(): void
137
    {
138
        $featuresConf = new FeaturesConf();
139
        $featuresConf->generateConfig();
140
        $arr_out      = [];
141
        $asteriskPath = Util::which('asterisk');
142
        Util::mwExec("{$asteriskPath} -rx 'core reload'", $arr_out);
143
    }
144
145
    /**
146
     *  Reloads Asterisk manager interface module
147
     */
148
    public static function managerReload(): void
149
    {
150
        $managerCong = new ManagerConf();
151
        $managerCong->generateConfig();
152
153
        $httpConf = new HttpConf();
154
        $httpConf->generateConfig();
155
156
        $arr_out      = [];
157
        $asteriskPath = Util::which('asterisk');
158
        Util::mwExec("{$asteriskPath} -rx 'module reload manager'", $arr_out);
159
        Util::mwExec("{$asteriskPath} -rx 'module reload http'", $arr_out);
160
    }
161
162
    /**
163
     *  Reloads Asterisk music on hold module
164
     */
165
    public static function musicOnHoldReload(): void
166
    {
167
        $o = new MusicOnHoldConf();
168
        $o->generateConfig();
169
        $asteriskPath = Util::which('asterisk');
170
        Util::mwExec("{$asteriskPath} -rx 'moh reload'");
171
    }
172
173
    /**
174
     *  Reloads Asterisk voicemail module
175
     */
176
    public static function voicemailReload(): void
177
    {
178
        $o = new VoiceMailConf();
179
        $o->generateConfig();
180
        $arr_out      = [];
181
        $asteriskPath = Util::which('asterisk');
182
        Util::mwExec("{$asteriskPath} -rx 'voicemail reload'", $arr_out);
183
    }
184
185
    /**
186
     *  Reloads Asterisk modules
187
     */
188
    public static function modulesReload(): array
189
    {
190
        $pbx = new ModulesConf();
191
        $pbx->generateConfig();
192
        $arr_out      = [];
193
        $asteriskPath = Util::which('asterisk');
194
        Util::mwExec("{$asteriskPath} -rx 'core restart now'", $arr_out);
195
196
        return [
197
            'result' => 'Success',
198
            'data'   => '',
199
        ];
200
    }
201
202
203
    public static function checkCodec($name, $desc, $type): void
204
    {
205
        $codec = Codecs::findFirst('name="' . $name . '"');
206
        if ($codec === null) {
207
            /** @var \MikoPBX\Common\Models\Codecs $codec_g722 */
208
            $codec              = new Codecs();
209
            $codec->name        = $name;
210
            $codec->type        = $type;
211
            $codec->description = $desc;
212
            $codec->save();
213
        }
214
    }
215
216
    /**
217
     *  Refresh SIP configs and reload PJSIP module
218
     */
219
    public static function sipReload():void
220
    {
221
        $di     = Di::getDefault();
222
        if ($di === null) {
223
            return;
224
        }
225
        $sip = new SIPConf();
226
        $needRestart = $sip->needAsteriskRestart();
227
        $sip->generateConfig();
228
229
        $acl = new AclConf();
230
        $acl->generateConfig();
231
232
        $asteriskPath = Util::which('asterisk');
233
        if ($needRestart === false) {
234
            Util::mwExec("{$asteriskPath} -rx 'module reload acl'");
235
            Util::mwExec("{$asteriskPath} -rx 'core reload'");
236
        } else {
237
            Util::sysLogMsg('SIP RELOAD', 'Need reload asterisk',LOG_INFO, LOG_INFO);
238
            // Завершаем каналы.
239
            Util::mwExec("{$asteriskPath} -rx 'channel request hangup all'");
240
            usleep(500000);
241
            Util::mwExec("{$asteriskPath} -rx 'core restart now'");
242
        }
243
    }
244
245
    /**
246
     * Refresh IAX configs and reload iax2 module
247
     */
248
    public static function iaxReload(): void
249
    {
250
        $iax    = new IAXConf();
251
        $iax->generateConfig();
252
        $asteriskPath = Util::which('asterisk');
253
        Util::mwExec("{$asteriskPath} -rx 'iax2 reload'");
254
    }
255
256
    public static function mohReload(): void
257
    {
258
        $asteriskPath = Util::which('asterisk');
259
        Util::mwExec("{$asteriskPath} -rx 'moh reload'");
260
    }
261
    /**
262
     * Ожидаем полной загрузки asterisk.
263
     *
264
     * @return bool
265
     */
266
    public static function waitFullyBooted(): bool
267
    {
268
        $time_start = microtime(true);
269
        $result     = false;
270
        $out        = [];
271
        if (Util::isSystemctl()) {
272
            $options = '';
273
        } else {
274
            $options = '-t';
275
        }
276
        $timeoutPath  = Util::which('timeout');
277
        $asteriskPath = Util::which('asterisk');
278
        while (true) {
279
            $execResult = Util::mwExec(
280
                "{$timeoutPath} {$options} 1 {$asteriskPath} -rx'core waitfullybooted'",
281
                $out
282
            );
283
            if ($execResult === 0 && implode('', $out) === 'Asterisk has fully booted.') {
284
                $result = true;
285
                break;
286
            }
287
            sleep(1);
288
            $time = microtime(true) - $time_start;
289
            if ($time > 60) {
290
                Util::sysLogMsg(__CLASS__, 'Error: Asterisk has not booted');
291
                break;
292
            }
293
        }
294
295
        return $result;
296
    }
297
298
    /**
299
     * Generates all Asterisk configuration files and (re)starts the Asterisk process
300
     */
301
    public function configure(): array
302
    {
303
        $result = [
304
            'result' => 'ERROR',
305
        ];
306
307
        if ( ! $this->di->getShared('registry')->booting) {
308
            $this->stop();
309
        }
310
        /**
311
         * Создание конфигурационных файлов.
312
         */
313
        foreach ($this->di->getShared('pbxConfModules') as $appClass) {
314
            $appClass->generateConfig();
315
        }
316
        self::dialplanReload();
317
        if ($this->di->getShared('registry')->booting) {
318
            echo "   |- dialplan reload \033[32;1mdone\033[0m \n";
319
        }
320
        // Создание базы данных истории звонков.
321
        /** @var \Phalcon\Db\Adapter\Pdo\Sqlite $connection */
322
        $connection = $this->di->get('dbCDR');
323
        if ( ! $connection->tableExists('cdr')) {
324
            RegisterDIServices::recreateDBConnections();
325
        } else {
326
            CdrDb::checkDb();
327
        }
328
329
        $result['result'] = 'Success';
330
331
        return $result;
332
    }
333
334
    /**
335
     * Refresh extensions.conf file and reloads asterisk dialplan.
336
     *
337
     */
338
    public static function dialplanReload(): void
339
    {
340
        $di = Di::getDefault();
341
        if ($di === null) {
342
            return;
343
        }
344
        $extensions = new ExtensionsConf();
345
        $extensions->generateConfig();
346
        if ($di->getRegistry()->booting !== true) {
347
            $path_asterisk = Util::which('asterisk');
348
            Util::mwExec("{$path_asterisk} -rx 'dialplan reload'");
349
            Util::mwExec("{$path_asterisk} -rx 'module reload pbx_lua.so'");
350
        }
351
    }
352
353
}
354