Реализовать данную возможность можно использую класс из штатной поставки дин.кода ru.bitel.bgbilling.modules.inet.dyn.device.misc.RadiusFanoutServiceActivator.
Данный класс необходимо установить обработчиком активации сервисов на Типе устройства для устройства
В шапке класса приведены примеры макросов для формирования пакетов по структуре необходимой для СОРМ.
Свои макросы для старт и стоп пакетов нужно прописать в конфигурации типа устройства. Пример:
sa.radius.fanout.accountingStart.attributes.macros=User-Name=$contractTitle();Acct-Session-Id=$connectionId()-$acctSessionId();Acct-Status-Type=1;Framed-IP-Address=$ip();Calling-Station-Id=$callingStationId()
sa.radius.fanout.accountingStop.attributes.macros=User-Name=$contractTitle();Acct-Session-Id=$acctSessionId();Acct-Status-Type=2;Framed-IP-Address=$ip();Calling-Station-Id=$callingStationId();
А так же хост и порт для отправки сформированных пакетов
sa.radius.fanout.host=XXX.XXX.X.XX
sa.radius.fanout.port=1813
Затем, в Типе сервиса для тех договоров по которым нужно будет формировать пакеты прописать настройку: sa.connection.auto.accountingEvent=1
Из документации к модулю Инет: "sa.connection.auto.accountingEvent - нужно ли генерировать start-stop accounting-пакеты для сессий по трафику. Это может понадобится для генерации фейковых radius- пакетов для СОРМа при помощи сервис-активатора RadiusFanoutServiceActivator. Возможные значения 0 (false) - отключено, 1 (true) - включено. По умолчанию 0."
Обработчик RadiusFanoutServiceActivator отправляет стоп пакеты при разрыве соединения и т.к. сессии по трафику логически приостанавливаются по таймауту или на границе суток, то возможно, что пакеты формироваться не будут, в таком случае нужно добавить в планировщик скрипт на приостановку активных соединений. Простейший пример такого скрипта представлен ниже.
package ru.sorm3;
import org.apache.log4j.Logger;
import ru.bitel.bgbilling.common.BGException;
import ru.bitel.bgbilling.kernel.container.managed.ServerContext;
import ru.bitel.bgbilling.kernel.script.server.dev.GlobalScriptBase;
import ru.bitel.bgbilling.modules.inet.api.common.bean.InetSessionLog;
import ru.bitel.bgbilling.modules.inet.api.common.service.InetSessionService;
import ru.bitel.bgbilling.server.util.Setup;
import ru.bitel.common.sql.ConnectionSet;
import java.util.Collections;
import java.util.List;
public class InetSessionStopScript
extends GlobalScriptBase
{
private final static Logger logger = Logger.getLogger( InetSessionStopScript.class );
private final int TEST_CID = -1;
private final int inetModuleId = 12;
@Override
public void execute( Setup setup, ConnectionSet connectionSet )
throws Exception
{
ServerContext serverContext = ServerContext.get();
InetSessionService sessionService = serverContext.getService( InetSessionService.class, inetModuleId );
List<InetSessionLog> aliveSessions = getAliveSessions( sessionService );
if( aliveSessions != null && aliveSessions.size() > 0 )
{
logger.info( "Всего сессий для приостановки= " + aliveSessions.size() );
}
else
{
logger.info( "Сессий для приостановки не найдено" );
}
for( InetSessionLog session : aliveSessions )
{
try
{
sessionService.connectionFinish( session.getContractId(), session.getConnectionId() );
}
catch( BGException e )
{
logger.error( "Ошибка при закрытии сессии=" + session.getConnectionId() +
" Для договора id=" + session.getContractId() +
" Ошибка: " + e.getMessage() );
}
}
}
private List<InetSessionLog> getAliveSessions( InetSessionService sessionService )
{
try
{
return sessionService.inetSessionAliveList( null, TEST_CID > 0 ?
Collections.singleton(TEST_CID) : null ,null,null,null,null,null,null,null ).getList();
}
catch( BGException e )
{
logger.error( e.getMessage() );
}
return Collections.emptyList();
}
}