Asterisk и миграция на PJSIP

Не буду писать о том, что такое PJSIP и почему он теперь есть. И без меня писателей хватает, поэтому быстренько пробежимся по настройкам, и основным моментам для тех, кто использовал chan_sip.
Главная проблема при переходе заключается в том, что в PJSIP добавили гибкости, причем в таких количествах, что ей подавиться не сложно. Для каждого пира (теперь он называется endpoint) нужно сделать несколько секций (входящая и исходящая авторизация, регистрация, сам endpoint и еще несколько). Но, через какое-то время передумали и добавили модуль pjsip wizard, который, при загрузке сам сделает что нужно. На него-то и будем рассчитывать. В ubuntu-server 18.04 LTS Asterisk версии 13, древненько но пусть будет.
Читать далее

Прозрачный gVim в windows

Мне нравятся терминалы с прозрачным фоном, а вот gVim под Windows как-то из этой темы выпадает, а бывает что им иногда пользуюсь. Никогда не заморачивался, а вот решение оказывается есть:

if has("win32")
Plug 'mattn/transparency-windows-vim'
Plug 'mattn/vimtweak'
endif

STM32: Шифруем прошивку.

Не сильно хорошая, но все же защита от бездумного копирования устройства. А может быть и еще что-то. В общем, идея такая: зашифровать некоторые критические функции, без которых устройство работать не будет, хитрожопые алгоритмы или математика какая-нибудь. Причем, желательно не потерять удобную сборку и отладку, и использовать желательно без всяких указателей. Я использую arm-none-eabi-gcc в качестве тулчейна и CMake как систему сборки. Поэтому все нижесказанное относится именно к этой связки и для других компиляторов-сборщиков придется немного перепилить.
Читать далее

STM32 и malloc во внешней памяти FMC / SDRAM

После того, как FMC/FSMC запустился и работает, внешняя память отражается по соответствующим адресам. Эту память можно использовать по захардкоденным адресам

char * ptr = (char*)0xC0000000;

но каждый раз вычислять адреса не комильфо. Тем более, для этого как раз есть специальная штука — heap и malloc/free.
Нужно только рассказать malloc где у нас эта память и сколько её. Самый простой способ — исправить правила линковки: Суть такова. _sbrk использует память начиная c адреса переданного линковщиком как end, стоит положить его адрес SDRAM, как malloc начинает раздавать адреса из неё.
Читать далее

AVR упрощаем TWI (I2C)

Давно уже написал, а выложить все как-то влом было. Но если вдруг, кому потребуется, простенькая библиотечка для работы с Two-Wire Interface (TWI, он же I2C) на AVR вообще и ATMega328p (та самая, которая в arduino nano v3 стоит) в частности.

Пользоваться проще некуда, подглядеть в libtwi.h всегда можно.

Скачать на гитхабе github.com/bevice/libtwi

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include "main.h"
#include "libtwi.h"
#include <util/delay.h>
void setup() {
    twi_init();
    DDRB |= _BV(PB5); // включим PB5 на выход, на Arduino Nano там светодиодик
 
}
 
#define DATA_SIZE 10
static uint8_t data[DATA_SIZE] ={0};
 
void twi_cb(uint8_t status){
    if(status!= TWI_STATUS_ERROR) // если все прочиталось - перевернем светодиод
        DDRB ^= _BV(PB5);
}
 
int main() {
    setup();
 
    while (1) {
        // для 24CXX при записи передается адрес и следом данные.
        uint8_t buff[] = {0x10,1,2,3,4,5}; 
        // передаем buff в железку с адресом  0xA0, 
        // как закончим передавать - дергаем twi_cb
        twi_transmit_data(0xA0, sizeof(buff), buff, &twi_cb);
 
        _delay_ms(1000);
 
        // читаем  DATA_SIZE байт из железки 
        // с адресом 0xA0 начиная с регистра 0x10
        // как в буффер data, как дочитаем
        //  - попадем в коллбек twi_cb с соответствующим статусом
    twi_receive_data_adr8(0xA0, 0x10, DATA_SIZE, data, &twi_cb);
 
    _delay_ms(1000);
    }
}

Такие дела..


Сижу отлаживаю железку на китайской arduino-nano-v3, тыкаю анализатором на RX ногу, а там пусто, иголки одни. Хотя AVR-ка точно с уарта читает и отвечает как надо.
А на самом деле-то не должна, полтора вольта за логический 0 это вообще как?

Asterisk, Lua и MySQL. Добавляем номер в черный список

Табличка немного отличается от предыдущего поста, поле number уникальное.

Пишем макрос:

extensions['macro-ban'] = {
        s = function()
                cid = channel.CALLERID("num"):get()
                query = "INSERT INTO blacklist (number, expires) VALUES ('" .. cid .. "', date_add(NOW(), INTERVAL 1 DAY)) on duplicate key update expires = date_add(NOW() INTERVAL 1 DAY);"
                local con = assert (env:connect(DB_NAME,DB_USER,DB_PASSWORD))
                assert (con:execute(query))
                con:close()
        end
};

Добалвяем макрос в features.conf:

[applicationmap]
ban => *5,peer/callee,macro(ban)

и не забываем включить в __DYNAMIC_FEATURES в диалплане:

extensions = {
    ["incoming"] = {
        ["DID"] = function()
            channel.__DYNAMIC_FEATURES = "ban"
            app.dial("SIP/100")
        end;
    }
}

Теперь ответивший нажатием *5 может добавить номер звонящего в черный список.

Asterisk, LUA и MySQL. Черный Список.

С помощью LUA делается элементарно:

В MySQL делаем табличку blacklist:

CREATE TABLE blacklist (
  NUMBER VARCHAR(20) NOT NULL,
  expires datetime DEFAULT NULL
)

Подключаем к LUA библиотеку luaSQL и luasql.mysql для работы с базой данных

 
-- расскажем, где искать
package.cpath = package.cpath .. ";/usr/lib/i386-linux-gnu/lua/5.1/?.so" 
-- и подключем
local luasql = require "luasql.mysql"
local mysql = assert (luasql.mysql())
 
-- данные для подключения к базе MySQL
local DB_HOST = "localhost"
local DB_NAME = "db_name"
local DB_USER = "db_user"
local DB_PASSWORD = "db_passwod"
 
-- и пишем функцию проверки: 
function is_banned(cid_number)
        local con = assert (env:connect(DB_NAME,DB_USER,DB_PASSWORD))
        local cur = assert (con:execute("SELECT * FROM blacklist where '".. cid_number.."' like number and (expires>now() or expires is NULL);"))
        c = cur:numrows()
        cur:close()
        con:close()
        return c>0
end
 
 
-- а дальше и начинаем использовать:
 
extensions = {
    ["incoming"] = {
        ["DID"] = function() 
            if is_banned(channel.CALLERID["number"]:get()) then
                -- Номер в черном списке, что-то с ним делаем
                app.answer()
                app.wait(1)
                app.hangup()
            end;
        end;
    }
}

Конечно, для полноценного использования нужно добавить индексы в базу и по-хорошему еще разрулить ситуацию, когда база данных недоступна.
А чуть позже мы добавим бан номера по кнопке оператора.